diff --git a/DEPS b/DEPS index 1e46bf2..40e14f4 100644 --- a/DEPS +++ b/DEPS
@@ -105,7 +105,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '767fddfcce612c1618c1b6f6dbac4d88565f0b13', + 'skia_revision': 'cd8689f0042727666e468dc18bdb4d65b02b6fd9', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -117,7 +117,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': '3fd614d06e50fb98d1434fabf31e8583516ad5c1', + 'angle_revision': '6e5bf36ff50f7976463c3c32151ece044e802284', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling build tools # and whatever else without interference from each other. @@ -129,7 +129,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': '3e360453cded5f2f435195923ede0935f6847194', + 'pdfium_revision': '5f4cd74d2693e23b27237b935f28a87611e25e6b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other. @@ -165,7 +165,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '5314945fa47aafd1edb930ace2590bdc7c874632', + 'catapult_revision': 'ed63b1319414a36b099cad8443d497bda8f085a2', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -552,7 +552,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '937745b816068ad929ea185686c1627fe1b8b220', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'a82d0a22067f72fda9d72c3679f108a9c1550407', 'condition': 'checkout_linux', }, @@ -567,7 +567,7 @@ # For Linux and Chromium OS. 'src/third_party/cros_system_api': { - 'url': Var('chromium_git') + '/chromiumos/platform/system_api.git' + '@' + 'c0be499563b84ec733af9fea34b6ae74d9667003', + 'url': Var('chromium_git') + '/chromiumos/platform/system_api.git' + '@' + '71adbf6a56865ae5500686eaa221b0f988c3bada', 'condition': 'checkout_linux', }, @@ -577,7 +577,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '3d429cf5131a10f0e6ced89e8809820398ece78b', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'efb38bb3d729f9d5b27f5202c766d43186c0103a', 'src/third_party/devtools-node-modules': Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'), @@ -832,7 +832,7 @@ Var('chromium_git') + '/webm/libwebm.git' + '@' + '01c1d1d76f139345c442bfc8e61b4e1cba809059', 'src/third_party/libyuv': - Var('chromium_git') + '/libyuv/libyuv.git' + '@' + '55f5d91f11f929c4c59c32621c3d5457cca3ab0b', # from r1714 + Var('chromium_git') + '/libyuv/libyuv.git' + '@' + 'd694f0a82b4da9d8ea37e6c453b7a34947eb5790', # from r1714 'src/third_party/lighttpd': { 'url': Var('chromium_git') + '/chromium/deps/lighttpd.git' + '@' + Var('lighttpd_revision'), @@ -1049,7 +1049,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '7ca87fb1d3da3b3d2060886e8c58e726d74c8219', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'e9721f2f08307e67c602a3c614ec144c5fb7e5c2', + Var('webrtc_git') + '/src.git' + '@' + '74ed734d717a3d3f47f393ab0f8593c7f6a696d6', 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 1274976..6d3147b 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -333,6 +333,7 @@ "sticky_keys/sticky_keys_state.h", "system/accessibility/dictation_button_tray.h", "system/accessibility/select_to_speak_tray.h", + "system/accessibility/select_to_speak_tray_utils.h", "system/audio/audio_detailed_view.h", "system/audio/display_speaker_controller.h", "system/audio/tray_audio.h", @@ -970,6 +971,7 @@ "sticky_keys/sticky_keys_overlay.cc", "system/accessibility/dictation_button_tray.cc", "system/accessibility/select_to_speak_tray.cc", + "system/accessibility/select_to_speak_tray_utils.cc", "system/audio/audio_detailed_view.cc", "system/audio/display_speaker_controller.cc", "system/audio/tray_audio.cc",
diff --git a/ash/accessibility/accessibility_controller.cc b/ash/accessibility/accessibility_controller.cc index ae467fe..1e9825b 100644 --- a/ash/accessibility/accessibility_controller.cc +++ b/ash/accessibility/accessibility_controller.cc
@@ -222,6 +222,18 @@ message_center->AddNotification(std::move(notification)); } +AccessibilityPanelLayoutManager* GetLayoutManager() { + // The accessibility panel is only shown on the primary display. + aura::Window* root = Shell::GetPrimaryRootWindow(); + aura::Window* container = + Shell::GetContainer(root, kShellWindowId_AccessibilityPanelContainer); + // TODO(jamescook): Avoid this cast by moving ash::AccessibilityObserver + // ownership to this class and notifying it on accessibility panel fullscreen + // updates. + return static_cast<AccessibilityPanelLayoutManager*>( + container->layout_manager()); +} + } // namespace AccessibilityController::AccessibilityController( @@ -700,17 +712,15 @@ accessibility_highlight_controller_->SetCaretBounds(bounds_in_screen); } -void AccessibilityController::SetAccessibilityPanelFullscreen(bool fullscreen) { - // The accessibility panel is only shown on the primary display. - aura::Window* root = Shell::GetPrimaryRootWindow(); - aura::Window* container = - Shell::GetContainer(root, kShellWindowId_AccessibilityPanelContainer); - // TODO(jamescook): Avoid this cast by moving ash::AccessibilityObserver - // ownership to this class and notifying it on ChromeVox fullscreen updates. - AccessibilityPanelLayoutManager* layout = - static_cast<AccessibilityPanelLayoutManager*>( - container->layout_manager()); - layout->SetPanelFullscreen(fullscreen); +void AccessibilityController::SetAccessibilityPanelAlwaysVisible( + bool always_visible) { + GetLayoutManager()->SetAlwaysVisible(always_visible); +} + +void AccessibilityController::SetAccessibilityPanelBounds( + const gfx::Rect& bounds, + mojom::AccessibilityPanelState state) { + GetLayoutManager()->SetPanelBounds(bounds, state); } void AccessibilityController::OnSigninScreenPrefServiceInitialized(
diff --git a/ash/accessibility/accessibility_controller.h b/ash/accessibility/accessibility_controller.h index e1ad856..219d55d 100644 --- a/ash/accessibility/accessibility_controller.h +++ b/ash/accessibility/accessibility_controller.h
@@ -163,7 +163,10 @@ void BrailleDisplayStateChanged(bool connected) override; void SetFocusHighlightRect(const gfx::Rect& bounds_in_screen) override; void SetCaretBounds(const gfx::Rect& bounds_in_screen) override; - void SetAccessibilityPanelFullscreen(bool fullscreen) override; + void SetAccessibilityPanelAlwaysVisible(bool always_visible) override; + void SetAccessibilityPanelBounds( + const gfx::Rect& bounds, + mojom::AccessibilityPanelState state) override; void SetSelectToSpeakState(mojom::SelectToSpeakState state) override; // SessionObserver:
diff --git a/ash/accessibility/accessibility_panel_layout_manager.cc b/ash/accessibility/accessibility_panel_layout_manager.cc index 91704ce..949b0b1 100644 --- a/ash/accessibility/accessibility_panel_layout_manager.cc +++ b/ash/accessibility/accessibility_panel_layout_manager.cc
@@ -26,11 +26,20 @@ display::Screen::GetScreen()->RemoveObserver(this); } -void AccessibilityPanelLayoutManager::SetPanelFullscreen(bool fullscreen) { - panel_fullscreen_ = fullscreen; +void AccessibilityPanelLayoutManager::SetAlwaysVisible(bool always_visible) { + always_visible_ = always_visible; UpdateWindowBounds(); } +void AccessibilityPanelLayoutManager::SetPanelBounds( + const gfx::Rect& bounds, + mojom::AccessibilityPanelState state) { + panel_bounds_ = bounds; + panel_state_ = state; + UpdateWindowBounds(); + UpdateWorkArea(); +} + void AccessibilityPanelLayoutManager::OnWindowAddedToLayout( aura::Window* child) { panel_window_ = child; @@ -90,29 +99,44 @@ RootWindowController* root_controller = RootWindowController::ForWindow(root_window); - // By default the panel sits at the top of the screen. - DCHECK(panel_window_->bounds().origin().IsOrigin()); - gfx::Rect bounds(0, 0, root_window->bounds().width(), kPanelHeight); + gfx::Rect bounds = panel_bounds_; // The panel can make itself fill the screen (including covering the shelf). - if (panel_fullscreen_) - bounds.set_height(root_window->bounds().height()); + if (panel_state_ == mojom::AccessibilityPanelState::FULLSCREEN) { + bounds = root_window->bounds(); + } else if (panel_state_ == mojom::AccessibilityPanelState::FULL_WIDTH) { + bounds.set_x(0); + bounds.set_width(root_window->bounds().width()); + } // If a fullscreen browser window is open, give the panel a height of 0 - // unless it's active. - if (root_controller->GetWindowForFullscreenMode() && + // unless it's active or always_visible_ is true. + if (!always_visible_ && root_controller->GetWindowForFullscreenMode() && !::wm::IsActiveWindow(panel_window_)) { bounds.set_height(0); } - // Make sure the ChromeVox panel is always below the Docked Magnifier viewport - // so it shows up and gets magnified. - bounds.Offset(0, root_controller->shelf()->GetDockedMagnifierHeight()); + // Make sure the accessibility panel is always below the Docked Magnifier + // viewport so it shows up and gets magnified. + int magnifier_height = root_controller->shelf()->GetDockedMagnifierHeight(); + if (bounds.y() < magnifier_height) + bounds.Offset(0, magnifier_height); + + // Make sure the accessibility panel doesn't go offscreen when the Docked + // Magnifier is on. + int screen_height = root_window->bounds().height(); + int available_height = screen_height - magnifier_height; + if (bounds.height() > available_height) + bounds.set_height(available_height); panel_window_->SetBounds(bounds); } void AccessibilityPanelLayoutManager::UpdateWorkArea() { + if (panel_window_ && panel_window_->bounds().y() != 0) + return; + if (panel_state_ == mojom::AccessibilityPanelState::FULLSCREEN) + return; Shell::GetPrimaryRootWindowController()->shelf()->SetAccessibilityPanelHeight( panel_window_ ? panel_window_->bounds().height() : 0); }
diff --git a/ash/accessibility/accessibility_panel_layout_manager.h b/ash/accessibility/accessibility_panel_layout_manager.h index f16e818..2c3a849d 100644 --- a/ash/accessibility/accessibility_panel_layout_manager.h +++ b/ash/accessibility/accessibility_panel_layout_manager.h
@@ -6,10 +6,12 @@ #define ASH_ACCESSIBILITY_ACCESSIBILITY_PANEL_LAYOUT_MANAGER_H_ #include "ash/ash_export.h" +#include "ash/public/interfaces/accessibility_controller.mojom.h" #include "ash/shell_observer.h" #include "base/macros.h" #include "ui/aura/layout_manager.h" #include "ui/display/display_observer.h" +#include "ui/gfx/geometry/rect.h" #include "ui/wm/public/activation_change_observer.h" namespace aura { @@ -30,13 +32,15 @@ public ash::ShellObserver { public: // Height of the panel in DIPs. Public for test. - static constexpr int kPanelHeight = 35; + static constexpr int kDefaultPanelHeight = 35; AccessibilityPanelLayoutManager(); ~AccessibilityPanelLayoutManager() override; - // Sets whether the panel covers the entire display. - void SetPanelFullscreen(bool fullscreen); + // Controls the panel's visibility and location. + void SetAlwaysVisible(bool always_visible); + void SetPanelBounds(const gfx::Rect& bounds, + mojom::AccessibilityPanelState state); // aura::LayoutManager: void OnWindowResized() override {} @@ -75,8 +79,15 @@ // The panel being managed (e.g. the ChromeVoxPanel's native aura window). aura::Window* panel_window_ = nullptr; - // Whether the panel itself is filling the display. - bool panel_fullscreen_ = false; + // Window bounds when not in fullscreen + gfx::Rect panel_bounds_ = gfx::Rect(0, 0, 0, 0); + + // Determines whether panel is hidden when browser is in fullscreen. + bool always_visible_ = false; + + // Determines how the panel_bounds_ are used when displaying the panel. + mojom::AccessibilityPanelState panel_state_ = + mojom::AccessibilityPanelState::BOUNDED; DISALLOW_COPY_AND_ASSIGN(AccessibilityPanelLayoutManager); };
diff --git a/ash/accessibility/accessibility_panel_layout_manager_unittest.cc b/ash/accessibility/accessibility_panel_layout_manager_unittest.cc index 5bd3165..b231a6c 100644 --- a/ash/accessibility/accessibility_panel_layout_manager_unittest.cc +++ b/ash/accessibility/accessibility_panel_layout_manager_unittest.cc
@@ -17,7 +17,8 @@ namespace { // Shorten the name for better line wrapping. -constexpr int kPanelHeight = AccessibilityPanelLayoutManager::kPanelHeight; +constexpr int kDefaultPanelHeight = + AccessibilityPanelLayoutManager::kDefaultPanelHeight; AccessibilityPanelLayoutManager* GetLayoutManager() { aura::Window* container = @@ -74,27 +75,6 @@ // Ash should not crash if the window is still open at shutdown. } -TEST_F(AccessibilityPanelLayoutManagerTest, InitialBounds) { - display::Screen* screen = display::Screen::GetScreen(); - gfx::Rect initial_work_area = screen->GetPrimaryDisplay().work_area(); - - // Simulate Chrome creating the ChromeVox window, but don't show it yet. - std::unique_ptr<views::Widget> widget = CreateChromeVoxPanel(); - - // The layout manager has not adjusted the work area yet. - EXPECT_EQ(screen->GetPrimaryDisplay().work_area(), initial_work_area); - - // Showing the panel causes the layout manager to adjust the panel bounds and - // the display work area. - widget->Show(); - gfx::Rect expected_bounds(0, 0, screen->GetPrimaryDisplay().bounds().width(), - kPanelHeight); - EXPECT_EQ(widget->GetNativeWindow()->bounds(), expected_bounds); - gfx::Rect expected_work_area = initial_work_area; - expected_work_area.Inset(0, kPanelHeight, 0, 0); - EXPECT_EQ(screen->GetPrimaryDisplay().work_area(), expected_work_area); -} - TEST_F(AccessibilityPanelLayoutManagerTest, PanelFullscreen) { AccessibilityPanelLayoutManager* layout_manager = GetLayoutManager(); display::Screen* screen = display::Screen::GetScreen(); @@ -102,38 +82,56 @@ std::unique_ptr<views::Widget> widget = CreateChromeVoxPanel(); widget->Show(); + layout_manager->SetPanelBounds(gfx::Rect(0, 0, 0, kDefaultPanelHeight), + mojom::AccessibilityPanelState::FULL_WIDTH); + gfx::Rect expected_work_area = screen->GetPrimaryDisplay().work_area(); // When the panel is fullscreen it fills the display and does not change the // work area. - layout_manager->SetPanelFullscreen(true); + layout_manager->SetPanelBounds(gfx::Rect(), + mojom::AccessibilityPanelState::FULLSCREEN); EXPECT_EQ(widget->GetNativeWindow()->bounds(), screen->GetPrimaryDisplay().bounds()); EXPECT_EQ(screen->GetPrimaryDisplay().work_area(), expected_work_area); // Restoring the panel to default size restores the bounds and does not change // the work area. - layout_manager->SetPanelFullscreen(false); + layout_manager->SetPanelBounds(gfx::Rect(0, 0, 0, kDefaultPanelHeight), + mojom::AccessibilityPanelState::FULL_WIDTH); gfx::Rect expected_bounds(0, 0, screen->GetPrimaryDisplay().bounds().width(), - kPanelHeight); + kDefaultPanelHeight); EXPECT_EQ(widget->GetNativeWindow()->bounds(), expected_bounds); EXPECT_EQ(screen->GetPrimaryDisplay().work_area(), expected_work_area); } +TEST_F(AccessibilityPanelLayoutManagerTest, SetBounds) { + std::unique_ptr<views::Widget> widget = CreateChromeVoxPanel(); + widget->Show(); + + gfx::Rect bounds(0, 0, 100, 100); + GetLayoutManager()->SetPanelBounds(bounds, + mojom::AccessibilityPanelState::BOUNDED); + EXPECT_EQ(widget->GetNativeWindow()->bounds(), bounds); +} + TEST_F(AccessibilityPanelLayoutManagerTest, DisplayBoundsChange) { std::unique_ptr<views::Widget> widget = CreateChromeVoxPanel(); widget->Show(); + GetLayoutManager()->SetPanelBounds( + gfx::Rect(0, 0, 0, kDefaultPanelHeight), + mojom::AccessibilityPanelState::FULL_WIDTH); // When the display resolution changes the panel still sits at the top of the // screen. UpdateDisplay("1234,567"); display::Screen* screen = display::Screen::GetScreen(); gfx::Rect expected_bounds(0, 0, screen->GetPrimaryDisplay().bounds().width(), - kPanelHeight); + kDefaultPanelHeight); EXPECT_EQ(widget->GetNativeWindow()->bounds(), expected_bounds); gfx::Rect expected_work_area = screen->GetPrimaryDisplay().bounds(); - expected_work_area.Inset(0, kPanelHeight, 0, kShelfSize); + expected_work_area.Inset(0, kDefaultPanelHeight, 0, kShelfSize); EXPECT_EQ(screen->GetPrimaryDisplay().work_area(), expected_work_area); }
diff --git a/ash/app_list/app_list_controller_impl.cc b/ash/app_list/app_list_controller_impl.cc index 55980af0..b23f5272 100644 --- a/ash/app_list/app_list_controller_impl.cc +++ b/ash/app_list/app_list_controller_impl.cc
@@ -547,6 +547,10 @@ ->IsTabletModeWindowManagerEnabled(); } +void AppListControllerImpl::Back() { + presenter_.GetView()->Back(); +} + //////////////////////////////////////////////////////////////////////////////// // Methods of |client_|: @@ -595,7 +599,7 @@ client_->OpenSearchResult(result_id, event_flags); if (IsHomeLauncherEnabledInTabletMode() && presenter_.IsVisible()) - presenter_.GetView()->ResetToInitialState(); + presenter_.GetView()->CloseOpenedPage(); } void AppListControllerImpl::InvokeSearchResultAction( @@ -644,7 +648,7 @@ client_->ActivateItem(id, event_flags); if (IsHomeLauncherEnabledInTabletMode() && presenter_.IsVisible()) - presenter_.GetView()->ResetToInitialState(); + presenter_.GetView()->CloseOpenedPage(); } void AppListControllerImpl::GetContextMenuModel(
diff --git a/ash/app_list/app_list_controller_impl.h b/ash/app_list/app_list_controller_impl.h index 31fbf7d..11847b4 100644 --- a/ash/app_list/app_list_controller_impl.h +++ b/ash/app_list/app_list_controller_impl.h
@@ -203,6 +203,9 @@ // Returns true if the home launcher is enabled in tablet mode. bool IsHomeLauncherEnabledInTabletMode() const; + // Performs the 'back' action for the active page. + void Back(); + private: syncer::StringOrdinal GetOemFolderPos(); std::unique_ptr<app_list::AppListItem> CreateAppListItem(
diff --git a/ash/app_list/app_list_presenter_delegate_impl.cc b/ash/app_list/app_list_presenter_delegate_impl.cc index 9013af6..e6ee690 100644 --- a/ash/app_list/app_list_presenter_delegate_impl.cc +++ b/ash/app_list/app_list_presenter_delegate_impl.cc
@@ -218,7 +218,7 @@ } aura::Window* window = view_->GetWidget()->GetNativeView()->parent(); - if (!window->Contains(target) && !presenter_->Back() && + if (!window->Contains(target) && !presenter_->CloseOpenedPage() && !app_list::switches::ShouldNotDismissOnBlur() && !IsHomeLauncherEnabledInTabletMode()) { presenter_->Dismiss(event->time_stamp());
diff --git a/ash/app_list/app_list_presenter_delegate_unittest.cc b/ash/app_list/app_list_presenter_delegate_unittest.cc index ea136cf..f35f2dfe 100644 --- a/ash/app_list/app_list_presenter_delegate_unittest.cc +++ b/ash/app_list/app_list_presenter_delegate_unittest.cc
@@ -485,6 +485,23 @@ shelf_layout_manager->GetShelfBackgroundType()); } +// Tests the shelf background type is as expected when in tablet mode. +TEST_F(AppListPresenterDelegateTest, ShelfBackgroundWithHomeLauncher) { + // Enter tablet mode to display the home launcher. + GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId()); + EnableTabletMode(true); + ShelfLayoutManager* shelf_layout_manager = + Shelf::ForWindow(Shell::GetRootWindowForDisplayId(GetPrimaryDisplayId())) + ->shelf_layout_manager(); + EXPECT_EQ(ShelfBackgroundType::SHELF_BACKGROUND_DEFAULT, + shelf_layout_manager->GetShelfBackgroundType()); + + // Add a window. It should be maximized because it is in tablet mode. + auto window = CreateTestWindow(); + EXPECT_EQ(ShelfBackgroundType::SHELF_BACKGROUND_MAXIMIZED, + shelf_layout_manager->GetShelfBackgroundType()); +} + // Tests that the peeking app list closes if the user taps or clicks outside // its bounds. TEST_P(AppListPresenterDelegateTest, TapAndClickOutsideClosesPeekingAppList) {
diff --git a/ash/app_list/presenter/app_list_presenter_impl.cc b/ash/app_list/presenter/app_list_presenter_impl.cc index 9d33cb47..749d9582 100644 --- a/ash/app_list/presenter/app_list_presenter_impl.cc +++ b/ash/app_list/presenter/app_list_presenter_impl.cc
@@ -147,14 +147,14 @@ base::RecordAction(base::UserMetricsAction("Launcher_Dismiss")); } -bool AppListPresenterImpl::Back() { +bool AppListPresenterImpl::CloseOpenedPage() { if (!is_visible_) return false; // If the app list is currently visible, there should be an existing view. DCHECK(view_); - return view_->app_list_main_view()->contents_view()->Back(); + return view_->CloseOpenedPage(); } void AppListPresenterImpl::ToggleAppList(int64_t display_id,
diff --git a/ash/app_list/presenter/app_list_presenter_impl.h b/ash/app_list/presenter/app_list_presenter_impl.h index 0ce3a83..3fe4931c 100644 --- a/ash/app_list/presenter/app_list_presenter_impl.h +++ b/ash/app_list/presenter/app_list_presenter_impl.h
@@ -58,9 +58,9 @@ // one AppListShowSource or focusing out side of the launcher. void Dismiss(base::TimeTicks event_time_stamp); - // Performs the 'back' action for the active page. Returns whether the action - // was handled. - bool Back(); + // Closes opened folder or search result page if they are opened. Returns + // whether the action was handled. + bool CloseOpenedPage(); // Show the app list if it is visible, hide it if it is hidden. If // |event_time_stamp| is not 0, it means |ToggleAppList()| was triggered by
diff --git a/ash/app_list/views/app_list_view.cc b/ash/app_list/views/app_list_view.cc index 2bc626b7..821b6143 100644 --- a/ash/app_list/views/app_list_view.cc +++ b/ash/app_list/views/app_list_view.cc
@@ -395,7 +395,18 @@ GetWidget()->Deactivate(); } -void AppListView::ResetToInitialState() { +bool AppListView::CloseOpenedPage() { + if (!app_list_main_view_) + return false; + + if (app_list_main_view_->contents_view()->IsShowingSearchResults() || + GetAppsContainerView()->IsInFolderView()) { + return app_list_main_view_->contents_view()->Back(); + } + return false; +} + +void AppListView::Back() { app_list_main_view_->contents_view()->Back(); }
diff --git a/ash/app_list/views/app_list_view.h b/ash/app_list/views/app_list_view.h index 1d47f2b6..fef964f3 100644 --- a/ash/app_list/views/app_list_view.h +++ b/ash/app_list/views/app_list_view.h
@@ -126,8 +126,12 @@ // Dismisses the UI, cleans up and sets the state to CLOSED. void Dismiss(); - // Resets the UI to initial state. - void ResetToInitialState(); + // Closes opened folder or search result page if they are opened. Returns + // whether the action was handled. + bool CloseOpenedPage(); + + // Performs the 'back' action for the active page. + void Back(); // Enables/disables a semi-transparent overlay over the app list (good for // hiding the app list when a modal dialog is being shown).
diff --git a/ash/app_list/views/app_list_view_unittest.cc b/ash/app_list/views/app_list_view_unittest.cc index 2a04aea..18c9f4c0 100644 --- a/ash/app_list/views/app_list_view_unittest.cc +++ b/ash/app_list/views/app_list_view_unittest.cc
@@ -150,6 +150,7 @@ params.is_tablet_mode = is_tablet_mode; params.is_side_shelf = is_side_shelf; view_->Initialize(params); + test_api_.reset(new AppsGridViewTestApi(apps_grid_view())); EXPECT_FALSE(view_->GetWidget()->IsVisible()); } @@ -200,8 +201,17 @@ return view_->app_list_main_view()->search_box_view(); } + ContentsView* contents_view() { + return view_->app_list_main_view()->contents_view(); + } + + AppsGridView* apps_grid_view() { + return contents_view()->GetAppsContainerView()->apps_grid_view(); + } + AppListView* view_ = nullptr; // Owned by native widget. std::unique_ptr<AppListTestViewDelegate> delegate_; + std::unique_ptr<AppsGridViewTestApi> test_api_; // Used by AppListFolderView::UpdatePreferredBounds. keyboard::KeyboardController keyboard_controller_; @@ -246,11 +256,11 @@ is_new_style_launcher_enabled_ = GetParam().is_new_style_launcher_enabled; } if (is_new_style_launcher_enabled_) { - scoped_feature_list_.InitWithFeatures({features::kEnableNewStyleLauncher}, - {}); + scoped_feature_list_.InitAndEnableFeature( + features::kEnableNewStyleLauncher); } else { - scoped_feature_list_.InitWithFeatures( - {}, {features::kEnableNewStyleLauncher}); + scoped_feature_list_.InitAndDisableFeature( + features::kEnableNewStyleLauncher); } views::ViewsTestBase::SetUp(); @@ -582,6 +592,24 @@ AppListViewFocusTest, testing::ValuesIn(kAppListViewFocusTestParams)); +// Test behaviors in tablet mode when homcher launcher feature is enabled. +class AppListViewHomeLauncherTest : public AppListViewTest { + public: + AppListViewHomeLauncherTest() = default; + ~AppListViewHomeLauncherTest() override = default; + + void SetUp() override { + scoped_feature_list_.InitAndEnableFeature( + app_list::features::kEnableHomeLauncher); + AppListViewTest::SetUp(); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; + + DISALLOW_COPY_AND_ASSIGN(AppListViewHomeLauncherTest); +}; + // Test behaviors in tablet mode when homcher launcher feature is not enabled. class AppListViewNonHomeLauncherTest : public AppListViewTest { public: @@ -589,8 +617,8 @@ ~AppListViewNonHomeLauncherTest() override = default; void SetUp() override { - scoped_feature_list_.InitWithFeatures( - {}, {app_list::features::kEnableHomeLauncher}); + scoped_feature_list_.InitAndDisableFeature( + app_list::features::kEnableHomeLauncher); AppListViewTest::SetUp(); } @@ -2021,5 +2049,56 @@ ASSERT_EQ(AppListViewState::FULLSCREEN_SEARCH, view_->app_list_state()); } +// Tests the back action in home launcher. +TEST_F(AppListViewHomeLauncherTest, BackAction) { + // Put into fullscreen using tablet mode. + Initialize(0, true, false); + + // Populate apps to fill up the first page and add a folder in the second + // page. + AppListTestModel* model = delegate_->GetTestModel(); + const int kAppListItemNum = test_api_->TilesPerPage(0); + const int kItemNumInFolder = 5; + model->PopulateApps(kAppListItemNum); + model->CreateAndPopulateFolderWithApps(kItemNumInFolder); + + // Show the app list + Show(); + EXPECT_EQ(AppListViewState::FULLSCREEN_ALL_APPS, view_->app_list_state()); + EXPECT_EQ(2, apps_grid_view()->pagination_model()->total_pages()); + + // Select the second page and open the folder. + apps_grid_view()->pagination_model()->SelectPage(1, false); + test_api_->PressItemAt(kAppListItemNum); + EXPECT_TRUE(contents_view()->GetAppsContainerView()->IsInFolderView()); + EXPECT_EQ(1, apps_grid_view()->pagination_model()->selected_page()); + + // Back action will first close the folder. + contents_view()->Back(); + EXPECT_FALSE(contents_view()->GetAppsContainerView()->IsInFolderView()); + EXPECT_EQ(1, apps_grid_view()->pagination_model()->selected_page()); + + // Back action will then select the first page. + contents_view()->Back(); + EXPECT_FALSE(contents_view()->GetAppsContainerView()->IsInFolderView()); + EXPECT_EQ(0, apps_grid_view()->pagination_model()->selected_page()); + + // Select the second page and open search results page. + apps_grid_view()->pagination_model()->SelectPage(1, false); + search_box_view()->search_box()->InsertText(base::UTF8ToUTF16("A")); + EXPECT_EQ(AppListViewState::FULLSCREEN_SEARCH, view_->app_list_state()); + EXPECT_EQ(1, apps_grid_view()->pagination_model()->selected_page()); + + // Back action will first close the search results page. + contents_view()->Back(); + EXPECT_EQ(AppListViewState::FULLSCREEN_ALL_APPS, view_->app_list_state()); + EXPECT_EQ(1, apps_grid_view()->pagination_model()->selected_page()); + + // Back action will then select the first page. + contents_view()->Back(); + EXPECT_EQ(AppListViewState::FULLSCREEN_ALL_APPS, view_->app_list_state()); + EXPECT_EQ(0, apps_grid_view()->pagination_model()->selected_page()); +} + } // namespace test } // namespace app_list
diff --git a/ash/app_list/views/contents_view.cc b/ash/app_list/views/contents_view.cc index 37fc55d..8ee89a1 100644 --- a/ash/app_list/views/contents_view.cc +++ b/ash/app_list/views/contents_view.cc
@@ -418,14 +418,22 @@ case ash::AppListState::kStateStart: // Close the app list when Back() is called from the start page. return false; - case ash::AppListState::kStateApps: + case ash::AppListState::kStateApps: { + PaginationModel* pagination_model = + GetAppsContainerView()->apps_grid_view()->pagination_model(); if (GetAppsContainerView()->IsInFolderView()) { GetAppsContainerView()->app_list_folder_view()->CloseFolderPage(); + } else if (app_list_view_->IsHomeLauncherEnabledInTabletMode() && + pagination_model->total_pages() > 0 && + pagination_model->selected_page() > 0) { + pagination_model->SelectPage( + 0, !app_list_view_->ShortAnimationsForTesting()); } else { // Close the app list when Back() is called from the apps page. return false; } break; + } case ash::AppListState::kStateSearchResults: GetSearchBoxView()->ClearSearch(); GetSearchBoxView()->SetSearchBoxActive(false, ui::ET_UNKNOWN);
diff --git a/ash/public/cpp/app_list/app_list_constants.cc b/ash/public/cpp/app_list/app_list_constants.cc index 5ba246f..dacb74e 100644 --- a/ash/public/cpp/app_list/app_list_constants.cc +++ b/ash/public/cpp/app_list/app_list_constants.cc
@@ -114,7 +114,7 @@ const size_t kMaxFolderItemsPerPage = 16; // Maximum length of the folder name in chars. -const size_t kMaxFolderNameChars = 80; +const size_t kMaxFolderNameChars = 28; // Font style for app item labels. const ui::ResourceBundle::FontStyle kItemTextFontStyle =
diff --git a/ash/public/interfaces/accessibility_controller.mojom b/ash/public/interfaces/accessibility_controller.mojom index 3951d78..d9cea94 100644 --- a/ash/public/interfaces/accessibility_controller.mojom +++ b/ash/public/interfaces/accessibility_controller.mojom
@@ -36,6 +36,17 @@ WINDOW_OVERVIEW_MODE_ENTERED }; +enum AccessibilityPanelState { + // Window bounds are set explicitly. + BOUNDED, + + // Width of panel matches screen width, y_coord and height are set by bounds. + FULL_WIDTH, + + // Panel occupies the full screen. Bounds are ignored. + FULLSCREEN +}; + enum SelectToSpeakState { // Select to Speak is not actively selecting text or speaking. kSelectToSpeakStateInactive, @@ -70,9 +81,14 @@ // Setting off-screen or empty bounds suppresses the highlight. SetCaretBounds(gfx.mojom.Rect bounds_in_screen); - // Sets whether the accessibility panel is filling the entire screen (e.g. to - // show the expanded UI for the ChromeVox spoken feedback extension). - SetAccessibilityPanelFullscreen(bool fullscreen); + // Sets whether the accessibility panel should always be visible, regardless + // of whether the window is fullscreen. + SetAccessibilityPanelAlwaysVisible(bool always_visible); + + // Sets the bounds for the accessibility panel. Overrides current + // configuration (i.e. fullscreen, full-width). + SetAccessibilityPanelBounds(gfx.mojom.Rect bounds, + AccessibilityPanelState state); // Sets the current Select-to-Speak state. This should be used by the Select- // to-Speak extension to inform ash of its updated state.
diff --git a/ash/shelf/app_list_shelf_item_delegate.cc b/ash/shelf/app_list_shelf_item_delegate.cc index 06f52ad..3ecd8caa 100644 --- a/ash/shelf/app_list_shelf_item_delegate.cc +++ b/ash/shelf/app_list_shelf_item_delegate.cc
@@ -38,13 +38,21 @@ return; } + // Whether to perform the "back" action for the app list. It will only be + // performed if other actions are not performed. + bool back_action = true; + // End overview mode. - if (Shell::Get()->window_selector_controller()->IsSelecting()) + if (Shell::Get()->window_selector_controller()->IsSelecting()) { Shell::Get()->window_selector_controller()->ToggleOverview(); + back_action = false; + } // End split view mode. - if (Shell::Get()->split_view_controller()->IsSplitViewModeActive()) + if (Shell::Get()->split_view_controller()->IsSplitViewModeActive()) { Shell::Get()->split_view_controller()->EndSplitView(); + back_action = false; + } // Minimize all windows that aren't the app list. aura::Window* app_list_container = @@ -56,8 +64,12 @@ if (!app_list_container->Contains(window) && !wm::GetWindowState(window)->IsMinimized()) { wm::GetWindowState(window)->Minimize(); + back_action = false; } } + + if (back_action) + Shell::Get()->app_list_controller()->Back(); } void AppListShelfItemDelegate::ExecuteCommand(bool from_context_menu,
diff --git a/ash/shelf/shelf_layout_manager.cc b/ash/shelf/shelf_layout_manager.cc index 8fd2a81..ccebe52 100644 --- a/ash/shelf/shelf_layout_manager.cc +++ b/ash/shelf/shelf_layout_manager.cc
@@ -527,9 +527,13 @@ return SHELF_BACKGROUND_LOGIN; } - // If the app list is active, hide the shelf background to prevent overlap. - if (is_app_list_visible_) + // If the app list is active and the home launcher is not shown, hide the + // shelf background to prevent overlap. + if (is_app_list_visible_ && !Shell::Get() + ->app_list_controller() + ->IsHomeLauncherEnabledInTabletMode()) { return SHELF_BACKGROUND_APP_LIST; + } if (state_.visibility_state != SHELF_AUTO_HIDE && state_.window_state == wm::WORKSPACE_WINDOW_STATE_MAXIMIZED) {
diff --git a/ash/shelf/shelf_view_unittest.cc b/ash/shelf/shelf_view_unittest.cc index ea1eff12..c3728af7 100644 --- a/ash/shelf/shelf_view_unittest.cc +++ b/ash/shelf/shelf_view_unittest.cc
@@ -56,7 +56,6 @@ #include "base/test/scoped_feature_list.h" #include "base/test/scoped_mock_time_message_loop_task_runner.h" #include "base/time/time.h" -#include "build/build_config.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/aura/test/aura_test_base.h" @@ -2935,14 +2934,9 @@ ASSERT_TRUE(test_api_->IsShowingOverflowBubble()); } -#if defined(OS_LINUX) -#define MAYBE_MouseContextMenu DISABLED_MouseContextMenu -#else -#define MAYBE_MouseContextMenu MouseContextMenu -#endif // Tests ink drop state transitions for the overflow button when the user // right clicks on the button to show the context menu. -TEST_F(OverflowButtonInkDropTest, MAYBE_MouseContextMenu) { +TEST_F(OverflowButtonInkDropTest, MouseContextMenu) { ui::test::EventGenerator* generator = GetEventGenerator(); generator->MoveMouseTo(GetScreenPointInsideOverflowButton()); @@ -3251,14 +3245,9 @@ EXPECT_FALSE(test_api_->IsShowingOverflowBubble()); } -#if defined(OS_LINUX) -#define MAYBE_MouseContextMenu DISABLED_MouseContextMenu -#else -#define MAYBE_MouseContextMenu MouseContextMenu -#endif // Tests ink drop state transitions for the overflow button when it is active // and the user right clicks on the button to show the context menu. -TEST_F(OverflowButtonActiveInkDropTest, MAYBE_MouseContextMenu) { +TEST_F(OverflowButtonActiveInkDropTest, MouseContextMenu) { ui::test::EventGenerator* generator = GetEventGenerator(); generator->MoveMouseTo(GetScreenPointInsideOverflowButton());
diff --git a/ash/shell.cc b/ash/shell.cc index d48cd2fd..6fd9c12b 100644 --- a/ash/shell.cc +++ b/ash/shell.cc
@@ -1164,7 +1164,7 @@ power_button_controller_->OnDisplayModeChanged( display_configurator_->cached_displays()); - if (!::features::IsAshInBrowserProcess() || ::features::IsSingleProcessMash()) + if (::features::IsUsingWindowService()) client_image_registry_ = std::make_unique<ClientImageRegistry>(); drag_drop_controller_ = std::make_unique<DragDropController>();
diff --git a/ash/system/accessibility/select_to_speak_tray.cc b/ash/system/accessibility/select_to_speak_tray.cc index 8a69bb9d..79028e58 100644 --- a/ash/system/accessibility/select_to_speak_tray.cc +++ b/ash/system/accessibility/select_to_speak_tray.cc
@@ -73,6 +73,10 @@ CheckStatusAndUpdateIcon(); } +bool SelectToSpeakTray::ContainsPointInScreen(const gfx::Point& point) { + return GetBoundsInScreen().Contains(point); +} + void SelectToSpeakTray::CheckStatusAndUpdateIcon() { if (!Shell::Get()->accessibility_controller()->IsSelectToSpeakEnabled()) { SetVisible(false);
diff --git a/ash/system/accessibility/select_to_speak_tray.h b/ash/system/accessibility/select_to_speak_tray.h index 05b7f32..96419c52 100644 --- a/ash/system/accessibility/select_to_speak_tray.h +++ b/ash/system/accessibility/select_to_speak_tray.h
@@ -34,6 +34,10 @@ // AccessibilityObserver: void OnAccessibilityStatusChanged() override; + // Returns true if the screen point passed in is contained within this tray's + // bounds. + bool ContainsPointInScreen(const gfx::Point& point); + private: friend class SelectToSpeakTrayTest;
diff --git a/ash/system/accessibility/select_to_speak_tray_utils.cc b/ash/system/accessibility/select_to_speak_tray_utils.cc new file mode 100644 index 0000000..f459b629 --- /dev/null +++ b/ash/system/accessibility/select_to_speak_tray_utils.cc
@@ -0,0 +1,30 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/system/accessibility/select_to_speak_tray_utils.h" + +#include "ash/session/session_controller.h" +#include "ash/shelf/shelf.h" +#include "ash/shell.h" +#include "ash/system/accessibility/select_to_speak_tray.h" +#include "ash/system/status_area_widget.h" +#include "ui/display/display.h" +#include "ui/gfx/geometry/point.h" + +namespace ash { +namespace select_to_speak_tray_utils { + +bool SelectToSpeakTrayContainsPointInScreen(const gfx::Point& point) { + for (aura::Window* window : Shell::GetAllRootWindows()) { + SelectToSpeakTray* tray = + Shelf::ForWindow(window)->GetStatusAreaWidget()->select_to_speak_tray(); + if (tray && tray->ContainsPointInScreen(point)) + return true; + } + + return false; +} + +} // namespace select_to_speak_tray_utils +} // namespace ash \ No newline at end of file
diff --git a/ash/system/accessibility/select_to_speak_tray_utils.h b/ash/system/accessibility/select_to_speak_tray_utils.h new file mode 100644 index 0000000..efa545f --- /dev/null +++ b/ash/system/accessibility/select_to_speak_tray_utils.h
@@ -0,0 +1,24 @@ +// 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 ASH_SYSTEM_ACCESSIBILITY_SELECT_TO_SPEAK_TRAY_UTILS_H_ +#define ASH_SYSTEM_ACCESSIBILITY_SELECT_TO_SPEAK_TRAY_UTILS_H_ + +#include "ash/ash_export.h" + +namespace gfx { +class Point; +} + +namespace ash { +namespace select_to_speak_tray_utils { + +// Returns true if either the select-to-speak tray icon contains the +// given point (in screen space). +ASH_EXPORT bool SelectToSpeakTrayContainsPointInScreen(const gfx::Point& point); + +} // namespace select_to_speak_tray_utils +} // namespace ash + +#endif // ASH_SYSTEM_ACCESSIBILITY_SELECT_TO_SPEAK_TRAY_UTILS_H_
diff --git a/ash/wm/overview/overview_utils.h b/ash/wm/overview/overview_utils.h index 02dd79c..0ff5006 100644 --- a/ash/wm/overview/overview_utils.h +++ b/ash/wm/overview/overview_utils.h
@@ -5,13 +5,13 @@ #ifndef ASH_WM_OVERVIEW_OVERVIEW_UTILS_H_ #define ASH_WM_OVERVIEW_OVERVIEW_UTILS_H_ +#include <memory> + #include "ash/ash_export.h" #include "ash/wm/overview/overview_animation_type.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/compositor/layer_type.h" -#include <memory> - namespace aura { class Window; } // namespace aura
diff --git a/ash/wm/overview/window_grid.cc b/ash/wm/overview/window_grid.cc index 719c1aa..0779473 100644 --- a/ash/wm/overview/window_grid.cc +++ b/ash/wm/overview/window_grid.cc
@@ -212,6 +212,28 @@ return widget; } +// Gets the expected grid bounds according the current |indicator_state| during +// window dragging. +gfx::Rect GetGridBoundsInScreenDuringDragging(aura::Window* dragged_window, + IndicatorState indicator_state) { + switch (indicator_state) { + case IndicatorState::kPreviewAreaLeft: + return Shell::Get() + ->split_view_controller() + ->GetSnappedWindowBoundsInScreen(dragged_window, + SplitViewController::RIGHT); + case IndicatorState::kPreviewAreaRight: + return Shell::Get() + ->split_view_controller() + ->GetSnappedWindowBoundsInScreen(dragged_window, + SplitViewController::LEFT); + default: + return Shell::Get() + ->split_view_controller() + ->GetDisplayWorkAreaBoundsInScreen(dragged_window); + } +} + } // namespace // ShieldView contains the background for overview mode. It also contains text @@ -585,6 +607,31 @@ const gfx::Point& location_in_screen, IndicatorState indicator_state) { DCHECK_EQ(dragged_window->GetRootWindow(), root_window_); + + // Adjust the window grid's bounds and the new selector item's visibility + // according to |indicator_state| if split view is not active at the moment. + if (!Shell::Get()->split_view_controller()->IsSplitViewModeActive()) { + WindowSelectorItem* new_selector_item = GetNewSelectorItem(); + const bool should_visible = + (indicator_state != IndicatorState::kPreviewAreaLeft && + indicator_state != IndicatorState::kPreviewAreaRight); + if (new_selector_item) { + const bool visible = new_selector_item_widget_->IsVisible(); + if (should_visible != visible) { + new_selector_item_widget_->GetLayer()->SetVisible(should_visible); + new_selector_item->SetOpacity(should_visible ? 1.f : 0.f); + } + } + + // Update the grid's bounds. + const gfx::Rect expected_bounds = + GetGridBoundsInScreenDuringDragging(dragged_window, indicator_state); + if (bounds_ != expected_bounds) { + SetBoundsAndUpdatePositionsIgnoringWindow( + expected_bounds, should_visible ? nullptr : new_selector_item); + } + } + // Find the window selector item that contains |location_in_screen|. auto iter = std::find_if( window_list_.begin(), window_list_.end(), @@ -678,6 +725,15 @@ new_selector_item_widget_->GetNativeWindow() == window; } +WindowSelectorItem* WindowGrid::GetNewSelectorItem() { + if (!new_selector_item_widget_ || window_list_.empty()) + return nullptr; + + WindowSelectorItem* first_item = window_list_.front().get(); + return IsNewSelectorItemWindow(first_item->GetWindow()) ? first_item + : nullptr; +} + void WindowGrid::OnWindowDestroying(aura::Window* window) { window_observer_.Remove(window); window_state_observer_.Remove(wm::GetWindowState(window));
diff --git a/ash/wm/overview/window_grid.h b/ash/wm/overview/window_grid.h index b5de4bb..4eac75d 100644 --- a/ash/wm/overview/window_grid.h +++ b/ash/wm/overview/window_grid.h
@@ -137,6 +137,10 @@ // item. bool IsNewSelectorItemWindow(aura::Window* window) const; + // Returns the selector item that accociates with |new_selector_item_widget_|. + // Returns nullptr if overview does not have the new selector item. + WindowSelectorItem* GetNewSelectorItem(); + // aura::WindowObserver: void OnWindowDestroying(aura::Window* window) override; // TODO(flackr): Handle window bounds changed in WindowSelectorItem.
diff --git a/ash/wm/splitview/split_view_controller_unittest.cc b/ash/wm/splitview/split_view_controller_unittest.cc index 9ad77458..a997b66 100644 --- a/ash/wm/splitview/split_view_controller_unittest.cc +++ b/ash/wm/splitview/split_view_controller_unittest.cc
@@ -2342,6 +2342,107 @@ EXPECT_TRUE(wm::GetWindowState(window.get())->IsMaximized()); } +// Tests that if dragging a window into the preview split area, overivew bounds +// should be adjusted accordingly. +TEST_F(SplitViewTabDraggingTest, AdjustOverviewBoundsDuringDragging) { + const gfx::Rect bounds(0, 0, 400, 400); + std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); + std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); + std::unique_ptr<aura::Window> window3(CreateWindow(bounds)); + + WindowSelectorController* selector_controller = + Shell::Get()->window_selector_controller(); + EXPECT_FALSE(selector_controller->IsSelecting()); + + // Start dragging |window1|. + std::unique_ptr<WindowResizer> resizer = + StartDrag(window1.get(), window1.get()); + // Overview should have been opened. + EXPECT_TRUE(selector_controller->IsSelecting()); + + // Test that the new selector item shows up as the first item in overview. + WindowGrid* current_grid = + selector_controller->window_selector()->GetGridWithRootWindow( + window1->GetRootWindow()); + EXPECT_TRUE(current_grid->GetNewSelectorItem()); + const gfx::Rect work_area_bounds = + split_view_controller()->GetDisplayWorkAreaBoundsInScreen(window1.get()); + EXPECT_EQ(current_grid->bounds(), work_area_bounds); + // The new selector item should be visible. + views::Widget* new_selector_widget = + current_grid->new_selector_item_widget_for_testing(); + EXPECT_TRUE(new_selector_widget); + EXPECT_TRUE(new_selector_widget->IsVisible()); + + // Now drag |window1| to the left preview split area. + DragWindowTo(resizer.get(), + gfx::Point(0, work_area_bounds.CenterPoint().y())); + EXPECT_EQ(current_grid->bounds(), + split_view_controller()->GetSnappedWindowBoundsInScreen( + window1.get(), SplitViewController::RIGHT)); + EXPECT_FALSE(new_selector_widget->IsVisible()); + + // Drag it to middle. + DragWindowTo(resizer.get(), work_area_bounds.CenterPoint()); + EXPECT_EQ(current_grid->bounds(), work_area_bounds); + EXPECT_TRUE(new_selector_widget->IsVisible()); + + // Drag |window1| to the right preview split area. + DragWindowTo(resizer.get(), gfx::Point(work_area_bounds.right(), + work_area_bounds.CenterPoint().y())); + EXPECT_EQ(current_grid->bounds(), + split_view_controller()->GetSnappedWindowBoundsInScreen( + window1.get(), SplitViewController::LEFT)); + EXPECT_FALSE(new_selector_widget->IsVisible()); + + CompleteDrag(std::move(resizer)); + EXPECT_EQ(split_view_controller()->state(), + SplitViewController::RIGHT_SNAPPED); + EXPECT_TRUE(selector_controller->IsSelecting()); + + // Snap another window should end overview. + split_view_controller()->SnapWindow(window2.get(), SplitViewController::LEFT); + EXPECT_EQ(split_view_controller()->state(), + SplitViewController::BOTH_SNAPPED); + EXPECT_FALSE(selector_controller->IsSelecting()); + + // Now drag |window1| again. Overview and splitview should be both active at + // the same time during dragging. + resizer = StartDrag(window1.get(), window1.get()); + EXPECT_TRUE(selector_controller->IsSelecting()); + EXPECT_EQ(split_view_controller()->state(), + SplitViewController::LEFT_SNAPPED); + + current_grid = selector_controller->window_selector()->GetGridWithRootWindow( + window1->GetRootWindow()); + // The new selector item should be visible. + new_selector_widget = current_grid->new_selector_item_widget_for_testing(); + EXPECT_TRUE(new_selector_widget); + EXPECT_TRUE(new_selector_widget->IsVisible()); + EXPECT_EQ(current_grid->bounds(), + split_view_controller()->GetSnappedWindowBoundsInScreen( + window1.get(), SplitViewController::RIGHT)); + + // Drag |window1| to the right preview split area. + DragWindowTo(resizer.get(), gfx::Point(work_area_bounds.right(), + work_area_bounds.CenterPoint().y())); + // Overview bounds stays the same. + EXPECT_EQ(current_grid->bounds(), + split_view_controller()->GetSnappedWindowBoundsInScreen( + window1.get(), SplitViewController::RIGHT)); + EXPECT_TRUE(new_selector_widget->IsVisible()); + + // Drag |window1| to the left preview split area. + DragWindowTo(resizer.get(), + gfx::Point(0, work_area_bounds.CenterPoint().y())); + EXPECT_EQ(current_grid->bounds(), + split_view_controller()->GetSnappedWindowBoundsInScreen( + window1.get(), SplitViewController::RIGHT)); + EXPECT_TRUE(new_selector_widget->IsVisible()); + + CompleteDrag(std::move(resizer)); +} + class TestWindowDelegateWithWidget : public views::WidgetDelegate { public: TestWindowDelegateWithWidget(bool can_activate)
diff --git a/ash/wm/tablet_mode/tablet_mode_window_drag_delegate.cc b/ash/wm/tablet_mode/tablet_mode_window_drag_delegate.cc index ee4a3d8..60008307 100644 --- a/ash/wm/tablet_mode/tablet_mode_window_drag_delegate.cc +++ b/ash/wm/tablet_mode/tablet_mode_window_drag_delegate.cc
@@ -50,9 +50,8 @@ if (!window_grid || window_grid->empty()) return gfx::Rect(); - WindowSelectorItem* new_selector_item = - window_grid->window_list().front().get(); - if (!window_grid->IsNewSelectorItemWindow(new_selector_item->GetWindow())) + WindowSelectorItem* new_selector_item = window_grid->GetNewSelectorItem(); + if (!new_selector_item) return gfx::Rect(); return new_selector_item->target_bounds();
diff --git a/ash/ws/window_service_owner.cc b/ash/ws/window_service_owner.cc index 98a1995..0bd5d746 100644 --- a/ash/ws/window_service_owner.cc +++ b/ash/ws/window_service_owner.cc
@@ -29,7 +29,7 @@ service_manager::mojom::ServiceRequest request) { // This should only be called once. If called more than once it means the // WindowService lost its connection to the service_manager, which triggered - // a new connection WindowService to be created. That should never happen. + // a new WindowService to be created. That should never happen. DCHECK(!service_context_); window_service_delegate_ = std::make_unique<WindowServiceDelegateImpl>();
diff --git a/build/android/gyp/write_build_config.py b/build/android/gyp/write_build_config.py index 761dc18..a2387da7 100755 --- a/build/android/gyp/write_build_config.py +++ b/build/android/gyp/write_build_config.py
@@ -829,20 +829,22 @@ parser.add_option('--shared-libraries-runtime-deps', help='Path to file containing runtime deps for shared ' 'libraries.') + parser.add_option('--native-libs', + action='append', + help='GN-list of native libraries for primary ' + 'android-abi. Can be specified multiple times.', + default=[]) parser.add_option('--secondary-abi-shared-libraries-runtime-deps', help='Path to file containing runtime deps for secondary ' 'abi shared libraries.') parser.add_option('--secondary-native-libs', action='append', - help='GYP-list of native libraries for secondary ' + help='GN-list of native libraries for secondary ' 'android-abi. Can be specified multiple times.', default=[]) parser.add_option('--uncompress-shared-libraries', default=False, action='store_true', help='Whether to store native libraries uncompressed') - parser.add_option('--extra-shared-libraries', - help='GN-list of paths to extra native libraries stored ' - 'in the APK.') # apk options parser.add_option('--apk-path', help='Path to the target\'s apk output.') parser.add_option('--incremental-apk-path', @@ -1220,7 +1222,7 @@ if options.type in ('android_apk', 'dist_aar', 'dist_jar', 'android_app_bundle_module', 'android_app_bundle'): all_configs = deps_info.get('proguard_configs', []) - extra_jars = list(system_jars) + extra_jars = list() for c in all_library_deps: all_configs.extend( p for p in c.get('proguard_configs', []) if p not in all_configs) @@ -1381,12 +1383,12 @@ secondary_abi_runtime_deps_files) secondary_abi_java_libraries_list = _CreateJavaLibrariesList( secondary_abi_library_paths) + for gn_list in options.secondary_native_libs: + secondary_abi_library_paths.extend(build_utils.ParseGnList(gn_list)) - for gyp_list in options.secondary_native_libs: - secondary_abi_library_paths.extend(build_utils.ParseGnList(gyp_list)) - - extra_shared_libraries = build_utils.ParseGnList( - options.extra_shared_libraries) + extra_shared_libraries = [] + for gn_list in options.native_libs: + extra_shared_libraries.extend(build_utils.ParseGnList(gn_list)) all_inputs.extend(runtime_deps_files) config['native'] = {
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni index 15aa173..dd1a248 100644 --- a/build/config/android/internal_rules.gni +++ b/build/config/android/internal_rules.gni
@@ -284,10 +284,15 @@ ] } + if (defined(invoker.loadable_modules) && invoker.loadable_modules != []) { + _rebased_modules = rebase_path(invoker.loadable_modules, root_build_dir) + args += [ "--native-libs=$_rebased_modules" ] + } + if (defined(invoker.extra_shared_libraries)) { _rebased_extra_shared_libraries = rebase_path(invoker.extra_shared_libraries, root_build_dir) - args += [ "--extra-shared-libraries=$_rebased_extra_shared_libraries" ] + args += [ "--native-libs=$_rebased_extra_shared_libraries" ] } if (defined(invoker.secondary_abi_shared_libraries_runtime_deps_file)) { @@ -303,9 +308,9 @@ if (defined(invoker.secondary_abi_loadable_modules) && invoker.secondary_abi_loadable_modules != []) { - _rebased_modules = + _rebased_secondary_abi_modules = rebase_path(invoker.secondary_abi_loadable_modules, root_build_dir) - args += [ "--secondary-native-libs=$_rebased_modules" ] + args += [ "--secondary-native-libs=$_rebased_secondary_abi_modules" ] } if (defined(invoker.uncompress_shared_libraries) && @@ -921,6 +926,8 @@ rebase_path(_output_jar_path, root_build_dir), "--classpath", "@FileArg($_rebased_build_config:deps_info:proguard_classpath_jars)", + "--classpath", + "@FileArg($_rebased_build_config:android:sdk_jars)", ] if (experimental_r8_path != "") { args += [ @@ -2884,6 +2891,7 @@ "classpath_deps", "gradle_treat_as_prebuilt", "input_jars_paths", + "loadable_modules", "main_class", "proguard_configs", "proguard_enabled",
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index f0da799..63b346e 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni
@@ -2296,6 +2296,7 @@ "emma_never_instrument", "java_files", "javac_args", + "loadable_modules", "no_build_hooks", "secondary_abi_loadable_modules", "uncompress_shared_libraries", @@ -2633,8 +2634,6 @@ args += [ "--native-libs=$_native_libs_file_arg" ] } if (_extra_native_libs != []) { - # Don't pass in _extra_native_libs_even_when_incremental, since these are - # end up in the apk and are not side-loaded. _rebased_extra_native_libs = rebase_path(_extra_native_libs, root_build_dir) args += [ "--native-libs=$_rebased_extra_native_libs" ] @@ -3640,7 +3639,10 @@ # proguarding. # # enable_multidex: Optional. Enable multidexing of optimized modules jars - # when using synchronized proguarding. + # when using synchronized proguarding. Only applies to base module. + # + # proguard_android_sdk_dep: Optional. android_system_java_prebuilt() target + # used as a library jar for synchronized proguarding. # # Example: # android_app_bundle("chrome_public_bundle") { @@ -3692,9 +3694,14 @@ _build_config = "$target_gen_dir/${target_name}.build_config" _rebased_build_config = rebase_path(_build_config, root_build_dir) _build_config_target = "${target_name}__build_config" + if (defined(invoker.proguard_android_sdk_dep)) { + proguard_android_sdk_dep_ = invoker.proguard_android_sdk_dep + } else { + proguard_android_sdk_dep_ = "//third_party/android_tools:android_sdk_java" + } write_build_config(_build_config_target) { type = "android_app_bundle" - possible_config_deps = _module_targets + possible_config_deps = _module_targets + [ proguard_android_sdk_dep_ ] build_config = _build_config } @@ -3770,7 +3777,7 @@ # http://crbug.com/725224. Fix for bots running out of memory. use_pool = true - if (_enable_multidex) { + if (_enable_multidex && _module.name == "base") { enable_multidex = _enable_multidex extra_main_dex_proguard_config = "$_module_target_gen_dir/$_module_target_name/" +
diff --git a/build/config/fuchsia/sandbox_policy b/build/config/fuchsia/sandbox_policy index 9419bdd2..44f8c1b 100644 --- a/build/config/fuchsia/sandbox_policy +++ b/build/config/fuchsia/sandbox_policy
@@ -1,4 +1,4 @@ { - "features": [ "persistent-storage", "root-ssl-certificates", "system-temp" ] + "features": [ "persistent-storage", "root-ssl-certificates", "system-temp", + "deprecated-all-services" ] } -
diff --git a/build/config/fuchsia/testing_sandbox_policy b/build/config/fuchsia/testing_sandbox_policy index 9d4db8f..f100a30 100644 --- a/build/config/fuchsia/testing_sandbox_policy +++ b/build/config/fuchsia/testing_sandbox_policy
@@ -1,5 +1,5 @@ { - "features": [ "persistent-storage", "root-ssl-certificates", "system-temp"], + "features": [ "persistent-storage", "root-ssl-certificates", "system-temp", + "deprecated-all-services" ], "dev": ["null", "zero"] } -
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc index ad02739..da40e52d 100644 --- a/cc/trees/layer_tree_host.cc +++ b/cc/trees/layer_tree_host.cc
@@ -795,6 +795,22 @@ std::getline(ss, line); VLOG(3) << line; } + + VLOG(3) << "CC Layer List:"; + for (auto* layer : *this) { + VLOG(3) << "layer id " << layer->id(); + VLOG(3) << " element_id: " << layer->element_id(); + VLOG(3) << " bounds: " << layer->bounds().ToString(); + VLOG(3) << " opacity: " << layer->opacity(); + VLOG(3) << " position: " << layer->position().ToString(); + VLOG(3) << " draws_content: " << layer->DrawsContent(); + VLOG(3) << " scrollable: " << layer->scrollable(); + VLOG(3) << " contents_opaque: " << layer->contents_opaque(); + VLOG(3) << " transform_tree_index: " << layer->transform_tree_index(); + VLOG(3) << " clip_tree_index: " << layer->clip_tree_index(); + VLOG(3) << " effect_tree_index: " << layer->effect_tree_index(); + VLOG(3) << " scroll_tree_index: " << layer->scroll_tree_index(); + } } bool painted_content_has_slow_paths = false;
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 39b59af..1584569 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -22,6 +22,9 @@ import("channel.gni") import("java_sources.gni") import("static_initializers.gni") +if (enable_arcore) { + import("//chrome/android/modules/ar/ar_module_tmpl.gni") +} manifest_package = "org.chromium.chrome" @@ -1705,7 +1708,14 @@ } } -# Generate application bundles if possible. +# Feature modules that go into Chrome Android application bundles. +if (enable_arcore) { + ar_module_tmpl("ar_public_module") { + manifest_package = manifest_package + } +} + +# Chrome Android application bundles. android_app_bundle("chrome_public_bundle") { bundle_name = "ChromePublicBundle" base_module_target = ":chrome_public_base_module" @@ -1729,5 +1739,14 @@ if (!is_java_debug) { proguard_enabled = true enable_multidex = true + proguard_android_sdk_dep = webview_framework_dep + } + if (enable_arcore) { + extra_modules = [ + { + name = "ar" + module_target = ":ar_public_module" + }, + ] } }
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni index 4d20dc4..a5ce20b 100644 --- a/chrome/android/chrome_public_apk_tmpl.gni +++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -263,23 +263,19 @@ png_to_webp = true } - if (enable_arcore) { - deps += [ "//third_party/arcore-android-sdk:libdynamite_client_java" ] - } - if (package_arcore) { - # We store this as a separate .so in the APK and only load as needed. - if (android_64bit_target_cpu && build_apk_secondary_abi) { - deps += [ - "//third_party/arcore-android-sdk:libarcore_library_secondary_abi", - ] - toolchain_out_dir = get_label_info( - "//third_party/arcore-android-sdk:libarcore_library($android_secondary_abi_toolchain)", - "root_out_dir") - secondary_abi_loadable_modules = - [ "${toolchain_out_dir}/libarcore_sdk_c_minimal.so" ] - } else { - deps += [ "//third_party/arcore-android-sdk:libarcore_library" ] - loadable_modules = [ "${root_out_dir}/libarcore_sdk_c_minimal.so" ] + if (invoker.target_type == "android_apk") { + if (enable_arcore) { + deps += [ "//third_party/arcore-android-sdk:libdynamite_client_java" ] + } + if (package_arcore) { + # We store this as a separate .so in the APK and only load as needed. + if (android_64bit_target_cpu && build_apk_secondary_abi) { + secondary_abi_loadable_modules = [ "//third_party/arcore-android-sdk/libraries/android_arm/libarcore_sdk_c_minimal.so" ] + } else if (android_64bit_target_cpu && !build_apk_secondary_abi) { + loadable_modules = [ "//third_party/arcore-android-sdk/libraries/android_arm64/libarcore_sdk_c_minimal.so" ] + } else { + loadable_modules = [ "//third_party/arcore-android-sdk/libraries/android_arm/libarcore_sdk_c_minimal.so" ] + } } } }
diff --git a/chrome/android/java/res/drawable-nodpi/widget_preview.png b/chrome/android/java/res/drawable-nodpi/widget_preview.png index 58627ca..4c17ce8a 100644 --- a/chrome/android/java/res/drawable-nodpi/widget_preview.png +++ b/chrome/android/java/res/drawable-nodpi/widget_preview.png Binary files differ
diff --git a/chrome/android/java/res/layout/contacts_picker_toolbar.xml b/chrome/android/java/res/layout/contacts_picker_toolbar.xml index 6cd3b1e..0cef73a0 100644 --- a/chrome/android/java/res/layout/contacts_picker_toolbar.xml +++ b/chrome/android/java/res/layout/contacts_picker_toolbar.xml
@@ -18,6 +18,15 @@ android:layout_height="wrap_content" android:layout_gravity="end"> + <!-- The ContentDescription for this View gets set in Java --> + <ImageView + android:id="@+id/search" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:background="@drawable/ic_search" + tools:ignore="ContentDescription" /> + <Button android:id="@+id/done" android:layout_width="wrap_content"
diff --git a/chrome/android/java/res/layout/download_manager_video_item.xml b/chrome/android/java/res/layout/download_manager_video_item.xml new file mode 100644 index 0000000..c3a8259 --- /dev/null +++ b/chrome/android/java/res/layout/download_manager_video_item.xml
@@ -0,0 +1,69 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> + + <android.support.v7.widget.GridLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:clickable="true" + android:background="@drawable/hairline_border_card_background" + app:columnCount="2" + app:rowCount="3"> + + <org.chromium.ui.widget.RoundedCornerImageView + android:id="@+id/thumbnail" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:scaleType="centerCrop" + android:adjustViewBounds="true" + android:background="@color/google_grey_300" + android:src="@drawable/audio_playing_square" + app:layout_column="0" + app:layout_row="0" + app:layout_columnSpan="2" + app:layout_gravity="center" + app:cornerRadiusTopStart="@dimen/download_manager_prefetch_thumbnail_corner_radius" + app:cornerRadiusTopEnd="@dimen/download_manager_prefetch_thumbnail_corner_radius"/> + + <org.chromium.chrome.browser.download.home.view.SelectionView + android:id="@+id/selection" + style="@style/DownloadItemSelectionView" + app:layout_column="0" + app:layout_row="0" /> + + <TextView + android:id="@+id/title" + style="@style/DownloadItemText" + android:layout_width="wrap_content" + android:layout_marginTop="11dp" + android:textAppearance="@style/BlackTitle1" + app:layout_column="0" + app:layout_row="1" + android:layout_marginStart="16dp" + app:layout_gravity="fill_horizontal" /> + + <TextView + android:id="@+id/caption" + style="@style/DownloadItemText" + android:layout_width="wrap_content" + android:layout_marginBottom="11dp" + android:textAppearance="@style/BlackHint2" + app:layout_column="0" + app:layout_row="2" + android:layout_marginStart="16dp" + app:layout_gravity="fill_horizontal" /> + + <include layout="@layout/list_menu_button" + android:layout_width="48dp" + android:layout_height="48dp" + app:layout_column="1" + app:layout_row="1" + app:layout_rowSpan="2" + app:layout_gravity="center_vertical|end" /> + +</android.support.v7.widget.GridLayout>
diff --git a/chrome/android/java/res/layout/new_tab_page_layout.xml b/chrome/android/java/res/layout/new_tab_page_layout.xml index fe391b0d..4105edc 100644 --- a/chrome/android/java/res/layout/new_tab_page_layout.xml +++ b/chrome/android/java/res/layout/new_tab_page_layout.xml
@@ -43,6 +43,7 @@ android:paddingTop="3dp" android:paddingBottom="3dp" > <EditText + style="@style/TextAppearance.NewTabPageSearchBoxText" android:id="@+id/search_box_text" android:layout_width="0dp" android:layout_height="match_parent" @@ -57,8 +58,7 @@ android:focusable="false" android:gravity="center_vertical" android:inputType="text" - android:singleLine="true" - android:textAppearance="@style/TextAppearance.NewTabPageSearchBoxText" /> + android:singleLine="true" /> <org.chromium.chrome.browser.widget.TintedImageView android:id="@+id/voice_search_button" android:layout_width="wrap_content"
diff --git a/chrome/android/java/res/layout/search_activity.xml b/chrome/android/java/res/layout/search_activity.xml index b75ebec4..df9c8bcb 100644 --- a/chrome/android/java/res/layout/search_activity.xml +++ b/chrome/android/java/res/layout/search_activity.xml
@@ -17,15 +17,6 @@ android:background="@android:color/white" android:layout="@layout/omnibox_results_container" /> - <ImageView - android:id="@+id/toolbar_shadow" - android:src="@drawable/toolbar_shadow" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginTop="@dimen/toolbar_height_no_shadow" - android:scaleType="fitXY" - tools:ignore="ContentDescription" /> - <FrameLayout android:id="@+id/toolbar" android:layout_width="match_parent" @@ -38,8 +29,10 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical" - android:layout_marginStart="@dimen/search_activity_location_bar_margin_start" - android:layout_marginEnd="@dimen/search_activity_location_bar_margin_end" /> + android:layout_marginTop="@dimen/location_bar_vertical_margin" + android:layout_marginBottom="@dimen/location_bar_vertical_margin" + android:layout_marginStart="@dimen/modern_toolbar_background_focused_left_margin" + android:layout_marginEnd="@dimen/modern_toolbar_background_focused_left_margin" /> </FrameLayout>
diff --git a/chrome/android/java/res/layout/search_widget_template.xml b/chrome/android/java/res/layout/search_widget_template.xml index 4571adf..02d17a75 100644 --- a/chrome/android/java/res/layout/search_widget_template.xml +++ b/chrome/android/java/res/layout/search_widget_template.xml
@@ -15,7 +15,7 @@ android:layout_height="wrap_content" android:layout_gravity="center" android:alpha="0.9" - android:background="@drawable/card_single" + android:background="@drawable/modern_toolbar_background_white" android:gravity="center_vertical" android:orientation="horizontal" > @@ -23,6 +23,7 @@ and sits in a 48dp x 48dp box. This means there's an implied 12dp of padding around the entire microphone. --> <TextView + style="@style/TextAppearance.NewTabPageSearchBoxText" android:id="@+id/title" android:layout_width="0dp" android:layout_height="48dp" @@ -31,9 +32,7 @@ android:gravity="center_vertical" android:singleLine="true" android:textAlignment="viewStart" - android:text="@string/search_widget_default" - android:textColor="@color/google_grey_600" - android:textSize="17sp" /> + android:hint="@string/search_widget_default" /> <ImageView android:id="@+id/microphone_icon"
diff --git a/chrome/android/java/res/values-sw600dp/dimens.xml b/chrome/android/java/res/values-sw600dp/dimens.xml index 8408e13d..797143a 100644 --- a/chrome/android/java/res/values-sw600dp/dimens.xml +++ b/chrome/android/java/res/values-sw600dp/dimens.xml
@@ -43,10 +43,6 @@ <!-- Payments UI --> <dimen name="payments_ui_max_dialog_width">600dp</dimen> - <!-- Search widget dimensions --> - <dimen name="search_activity_location_bar_margin_start">0dp</dimen> - <dimen name="search_activity_location_bar_margin_end">4dp</dimen> - <!-- Clear browsing data preferences dimensions --> <dimen name="clear_browsing_data_button_margin">16dp</dimen>
diff --git a/chrome/android/java/res/values-v17/styles.xml b/chrome/android/java/res/values-v17/styles.xml index 9dd564f..fccda2d1 100644 --- a/chrome/android/java/res/values-v17/styles.xml +++ b/chrome/android/java/res/values-v17/styles.xml
@@ -50,7 +50,7 @@ <!-- Extend MainThemeBase rather than MainTheme to avoid values-v27 navigation bar colors from being applied --> <style name="SearchActivityTheme" parent="MainThemeBase"> - <item name="android:windowBackground">@color/google_grey_500</item> + <item name="android:windowBackground">@android:color/white</item> </style> <style name="TabbedModeThemeBase" parent="MainTheme"> @@ -615,6 +615,11 @@ <style name="NewTabPageRecyclerView"> <item name="android:colorEdgeEffect" tools:targetApi="21">@color/google_grey_300</item> </style> + + <!-- Use style="..." for the following search box style as textColorHint + can not use android:textAppearance="...". textColorHint is defined + in a parent theme therefore can not be overridden by appearance. + --> <style name="TextAppearance.NewTabPageSearchBoxText"> <item name="android:textSize">@dimen/location_bar_url_text_size</item> <item name="android:textColorHint">@color/search_box_hint</item>
diff --git a/chrome/android/java/res/values/colors.xml b/chrome/android/java/res/values/colors.xml index 4e642cb..7ef18ef 100644 --- a/chrome/android/java/res/values/colors.xml +++ b/chrome/android/java/res/values/colors.xml
@@ -44,6 +44,7 @@ <color name="modern_light_grey">#F1F3F4</color> <color name="modern_grey_800">#3C4043</color> + <color name="modern_grey_700">#5F6368</color> <color name="modern_grey_500">#9AA0A6</color> <!-- Old color palette --> @@ -56,7 +57,6 @@ <color name="google_grey_200">#EEEEEE</color> <color name="google_grey_300">#E0E0E0</color> <color name="google_grey_400">#BDBDBD</color> - <color name="google_grey_500">#9E9E9E</color> <color name="google_grey_600">#757575</color> <color name="light_grey">#CCCCCC</color> @@ -221,7 +221,7 @@ <color name="toolbar_shadow_color">@color/black_alpha_11</color> <color name="bottom_system_nav_color">@android:color/white</color> <color name="bottom_system_nav_divider_color">@color/black_alpha_12</color> - <color name="search_box_hint">@color/black_alpha_54</color> + <color name="search_box_hint">@color/modern_grey_700</color> <color name="placeholder_thumbnail_bg_color">#DADCE0</color> <color name="clear_browsing_data_selected_tab_color">@color/modern_blue_600</color>
diff --git a/chrome/android/java/res/values/dimens.xml b/chrome/android/java/res/values/dimens.xml index 15860c8a..836c9b3 100644 --- a/chrome/android/java/res/values/dimens.xml +++ b/chrome/android/java/res/values/dimens.xml
@@ -550,10 +550,6 @@ <!-- Divider Dimensions --> <dimen name="divider_height">1dp</dimen> - <!-- Search widget dimensions --> - <dimen name="search_activity_location_bar_margin_start">16dp</dimen> - <dimen name="search_activity_location_bar_margin_end">8dp</dimen> - <!-- Reader Mode dimensions --> <!-- Padding surrounding the message. --> <dimen name="reader_mode_infobar_text_padding">8dp</dimen>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityUi.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityUi.java index afc0e6c..9752b67 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityUi.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityUi.java
@@ -22,6 +22,9 @@ * Thread safety: All methods on this class should be called on the UI thread. */ public class TrustedWebActivityUi { + /** The Digital Asset Link relationship used for Trusted Web Activities. */ + private final static int RELATIONSHIP = CustomTabsService.RELATION_HANDLE_ALL_URLS; + private final TrustedWebActivityUiDelegate mDelegate; private final TrustedWebActivityDisclosure mDisclosure; @@ -82,8 +85,8 @@ // This doesn't perform a network request or attempt new verification - it checks to // see if a verification already exists for the given inputs. - setTrustedWebActivityMode(OriginVerifier.isValidOrigin(packageName, new Origin(url), - CustomTabsService.RELATION_HANDLE_ALL_URLS), tab); + setTrustedWebActivityMode( + OriginVerifier.isValidOrigin(packageName, new Origin(url), RELATIONSHIP), tab); } }; @@ -123,6 +126,22 @@ } /** + * Perform verification for the URL that the CustomTabActivity starts on. + */ + public void attemptVerificationForInitialUrl(String url, Tab tab) { + assert mDelegate.getClientPackageName() != null; + + String packageName = mDelegate.getClientPackageName(); + Origin origin = new Origin(url); + + new OriginVerifier((packageName2, origin2, verified, online) -> { + if (!origin.equals(new Origin(tab.getUrl()))) return; + + setTrustedWebActivityMode(verified, tab); + }, packageName, RELATIONSHIP).start(origin); + } + + /** * Updates the UI appropriately for whether or not Trusted Web Activity mode is enabled. */ private void setTrustedWebActivityMode(boolean enabled, Tab tab) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/PickerAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/PickerAdapter.java index c2e16a2..88a2db0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/PickerAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/PickerAdapter.java
@@ -57,6 +57,22 @@ } /** + * Sets the search query (filter) for the contact list. Filtering is by display name. + * @param query The search term to use. + */ + public void setSearchString(String query) { + String searchString = "%" + query + "%"; + String[] selectionArgs = {searchString}; + mContactsCursor.close(); + + mContactsCursor = mCategoryView.getActivity().getContentResolver().query( + ContactsContract.Contacts.CONTENT_URI, PROJECTION, + ContactsContract.Contacts.DISPLAY_NAME_PRIMARY + " LIKE ?", selectionArgs, + ContactsContract.Contacts.DISPLAY_NAME_PRIMARY + " ASC"); + notifyDataSetChanged(); + } + + /** * Fetches all known contacts and their emails. * @return The contact list as a set. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/PickerCategoryView.java b/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/PickerCategoryView.java index 5cb963b..990c044 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/PickerCategoryView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/PickerCategoryView.java
@@ -13,25 +13,30 @@ import android.view.LayoutInflater; import android.view.View; import android.widget.Button; +import android.widget.ImageView; import android.widget.RelativeLayout; import org.chromium.base.ApiCompatibilityUtils; import org.chromium.chrome.R; import org.chromium.chrome.browser.widget.RoundedIconGenerator; import org.chromium.chrome.browser.widget.selection.SelectableListLayout; +import org.chromium.chrome.browser.widget.selection.SelectableListToolbar; import org.chromium.chrome.browser.widget.selection.SelectionDelegate; import org.chromium.ui.ContactsPickerListener; import org.chromium.ui.UiUtils; import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; import java.util.List; /** * A class for keeping track of common data associated with showing contact details in * the contacts picker, for example the RecyclerView. */ -public class PickerCategoryView extends RelativeLayout implements View.OnClickListener { +public class PickerCategoryView extends RelativeLayout + implements View.OnClickListener, SelectionDelegate.SelectionObserver<ContactDetails>, + SelectableListToolbar.SearchDelegate { // Constants for the RoundedIconGenerator. private static final int ICON_SIZE_DP = 32; private static final int ICON_CORNER_RADIUS_DP = 20; @@ -67,6 +72,12 @@ // The {@link SelectionDelegate} keeping track of which contacts are selected. private SelectionDelegate<ContactDetails> mSelectionDelegate; + // The search icon. + private ImageView mSearchButton; + + // Keeps track of list of last selected contacts. + List<ContactDetails> mPreviousSelection; + // The Done text button that confirms the selection choice. private Button mDoneButton; @@ -79,6 +90,7 @@ mActivity = (Activity) context; mSelectionDelegate = new SelectionDelegate<ContactDetails>(); + mSelectionDelegate.addObserver(this); Resources resources = getActivity().getResources(); int iconColor = @@ -97,7 +109,10 @@ R.string.contacts_picker_select_contacts, null, 0, 0, R.color.modern_primary_color, null, false, false); mToolbar.setNavigationOnClickListener(this); + mToolbar.initializeSearchView(this, R.string.contacts_picker_search, 0); + mSearchButton = (ImageView) mToolbar.findViewById(R.id.search); + mSearchButton.setOnClickListener(this); mDoneButton = (Button) mToolbar.findViewById(R.id.done); mDoneButton.setOnClickListener(this); @@ -128,6 +143,58 @@ mPickerAdapter.notifyDataSetChanged(); } + private void onStartSearch() { + mDoneButton.setVisibility(GONE); + + // Showing the search clears current selection. Save it, so we can restore it after the + // search has completed. + mPreviousSelection = mSelectionDelegate.getSelectedItems(); + mSearchButton.setVisibility(GONE); + mToolbar.showSearchView(); + } + + // SelectableListToolbar.SearchDelegate: + + @Override + public void onEndSearch() { + mPickerAdapter.setSearchString(""); + mToolbar.showCloseButton(); + mToolbar.setNavigationOnClickListener(this); + mDoneButton.setVisibility(VISIBLE); + mSearchButton.setVisibility(VISIBLE); + + // Hiding the search view clears the selection. Save it first and restore to the old + // selection, with the new item added during search. + // TODO(finnur): This needs to be revisited after UX is finalized. + HashSet<ContactDetails> selection = new HashSet<>(); + for (ContactDetails item : mSelectionDelegate.getSelectedItems()) { + selection.add(item); + } + mToolbar.hideSearchView(); + for (ContactDetails item : mPreviousSelection) { + selection.add(item); + } + + // TODO(finnur): Do this asynchronously to make the number roll view show the right number. + mSelectionDelegate.setSelectedItems(selection); + } + + @Override + public void onSearchTextChanged(String query) { + mPickerAdapter.setSearchString(query); + } + + // SelectionDelegate.SelectionObserver: + + @Override + public void onSelectionStateChange(List<ContactDetails> selectedItems) { + // Once a selection is made, drop out of search mode. Note: This function is also called + // when entering search mode (with selectedItems then being 0 in size). + if (mToolbar.isSearching() && selectedItems.size() > 0) { + mToolbar.hideSearchView(); + } + } + // OnClickListener: @Override @@ -135,6 +202,8 @@ int id = view.getId(); if (id == R.id.done) { notifyContactsSelected(); + } else if (id == R.id.search) { + onStartSearch(); } else { executeAction(ContactsPickerListener.ContactsPickerAction.CANCEL, null); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java index 01b1382..db3e819 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
@@ -660,6 +660,7 @@ } if (mTrustedWebActivityUi != null) { + mTrustedWebActivityUi.attemptVerificationForInitialUrl(url, getActivityTab()); mTrustedWebActivityUi.initialShowSnackbarIfNeeded(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/glue/ThumbnailRequestGlue.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/glue/ThumbnailRequestGlue.java index a5ff269c..9ec41e03 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/glue/ThumbnailRequestGlue.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/glue/ThumbnailRequestGlue.java
@@ -5,10 +5,14 @@ package org.chromium.chrome.browser.download.home.glue; import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import org.chromium.base.Callback; +import org.chromium.base.ContextUtils; +import org.chromium.chrome.R; import org.chromium.chrome.browser.widget.ThumbnailProvider.ThumbnailRequest; import org.chromium.components.offline_items_collection.OfflineItem; +import org.chromium.components.offline_items_collection.OfflineItemFilter; import org.chromium.components.offline_items_collection.OfflineItemVisuals; import org.chromium.components.offline_items_collection.VisualsCallback; @@ -62,6 +66,14 @@ @Override public boolean getThumbnail(Callback<Bitmap> callback) { + // TODO(shaktisahu, xingliu): Remove this after video thumbnail generation pipeline is done. + if (mItem.filter == OfflineItemFilter.FILTER_VIDEO) { + callback.onResult(BitmapFactory.decodeResource( + ContextUtils.getApplicationContext().getResources(), + R.drawable.audio_playing_square)); + return true; + } + return mProvider.getVisualsForItem(mItem.id, (id, visuals) -> { if (visuals == null) { callback.onResult(null);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListView.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListView.java index 93ef2a3..fb2eb0b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListView.java
@@ -143,6 +143,11 @@ outRect.top = mImagePaddingPx; outRect.bottom = mImagePaddingPx; break; + case ListUtils.ViewType.VIDEO: + outRect.left = mPrefetchHorizontalPaddingPx; + outRect.right = mPrefetchHorizontalPaddingPx; + outRect.bottom = mPrefetchHorizontalPaddingPx; + break; case ListUtils.ViewType.PREFETCH: outRect.left = mPrefetchHorizontalPaddingPx; outRect.right = mPrefetchHorizontalPaddingPx;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/ListItemViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/ListItemViewHolder.java index 9152116..cf54202e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/ListItemViewHolder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/ListItemViewHolder.java
@@ -36,7 +36,7 @@ case ListUtils.ViewType.GENERIC: return GenericViewHolder.create(parent); case ListUtils.ViewType.VIDEO: - return new VideoViewHolder(parent); + return VideoViewHolder.create(parent); case ListUtils.ViewType.IMAGE: return ImageViewHolder.create(parent); case ListUtils.ViewType.CUSTOM_VIEW:
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/VideoViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/VideoViewHolder.java index 71432b67..03d1fd5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/VideoViewHolder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/VideoViewHolder.java
@@ -4,25 +4,73 @@ package org.chromium.chrome.browser.download.home.list.holder; -import android.support.v7.widget.AppCompatTextView; +import android.support.annotation.Nullable; +import android.view.LayoutInflater; +import android.view.View; import android.view.ViewGroup; +import android.widget.ImageView; import android.widget.TextView; +import org.chromium.chrome.R; import org.chromium.chrome.browser.download.home.list.ListItem; +import org.chromium.chrome.browser.download.home.list.UiUtils; +import org.chromium.chrome.browser.download.home.view.LoadingBackground; import org.chromium.chrome.browser.modelutil.PropertyModel; +import org.chromium.components.offline_items_collection.OfflineItemVisuals; /** * A {@link RecyclerView.ViewHolder} specifically meant to display a video {@code OfflineItem}. */ -public class VideoViewHolder extends ListItemViewHolder { - public VideoViewHolder(ViewGroup parent) { - super(new AppCompatTextView(parent.getContext())); +public class VideoViewHolder extends ThumbnailAwareViewHolder { + private final TextView mTitle; + private final TextView mCaption; + private final ImageView mThumbnailView; + private LoadingBackground mLoadingBackground; + + /** + * Creates a new {@link VideoViewHolder} instance. + */ + public static VideoViewHolder create(ViewGroup parent) { + View view = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.download_manager_video_item, null); + int thumbnailWidth = parent.getContext().getResources().getDimensionPixelSize( + R.dimen.download_manager_image_width); + int thumbnailHeight = parent.getContext().getResources().getDimensionPixelSize( + R.dimen.download_manager_image_width); + return new VideoViewHolder(view, thumbnailWidth, thumbnailHeight); } - // ListItemViewHolder implementation. + public VideoViewHolder(View view, int thumbnailWidthPx, int thumbnailHeightPx) { + super(view, thumbnailWidthPx, thumbnailHeightPx); + + mTitle = (TextView) itemView.findViewById(R.id.title); + mCaption = (TextView) itemView.findViewById(R.id.caption); + mThumbnailView = (ImageView) itemView.findViewById(R.id.thumbnail); + mLoadingBackground = new LoadingBackground(view.getContext()); + } + @Override public void bind(PropertyModel properties, ListItem item) { + super.bind(properties, item); ListItem.OfflineItemListItem offlineItem = (ListItem.OfflineItemListItem) item; - ((TextView) itemView).setText(offlineItem.item.title); + + mTitle.setText(offlineItem.item.title); + mCaption.setText(UiUtils.generateGenericCaption(offlineItem.item)); + mThumbnailView.setContentDescription(offlineItem.item.title); + } + + @Override + void onVisualsChanged(ImageView view, @Nullable OfflineItemVisuals visuals) { + view.setImageBitmap(visuals == null ? null : visuals.icon); + } + + @Override + protected void showLoadingView(ImageView view) { + mLoadingBackground.show(view); + } + + @Override + protected void hideLoadingView() { + mLoadingBackground.hide(); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/SuggestionView.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/SuggestionView.java index e289e30e..2cc28e06 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/SuggestionView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/SuggestionView.java
@@ -316,7 +316,10 @@ .getDimension(R.dimen.omnibox_suggestion_second_line_text_size)); mRefineViewOffsetPx = useModernDesign ? mRefineViewModernEndPadding : 0; - mSuggestionViewStartOffset = useModernDesign ? mSuggestionListModernOffset : 0; + mSuggestionViewStartOffset = + useModernDesign && !mLocationBar.mustQueryUrlBarLocationForSuggestions() + ? mSuggestionListModernOffset + : 0; // Suggestions with attached answers are rendered with rich results regardless of which // suggestion type they are.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivityLocationBarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivityLocationBarLayout.java index 8f604b10..ad3ac5a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivityLocationBarLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivityLocationBarLayout.java
@@ -7,6 +7,7 @@ import android.content.Context; import android.os.Handler; import android.support.annotation.Nullable; +import android.support.v4.view.ViewCompat; import android.text.TextUtils; import android.util.AttributeSet; import android.view.View; @@ -20,6 +21,7 @@ import org.chromium.chrome.browser.omnibox.UrlBarCoordinator.SelectionState; import org.chromium.chrome.browser.omnibox.UrlBarData; import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.toolbar.ToolbarPhone; import org.chromium.ui.UiUtils; import java.util.List; @@ -42,6 +44,25 @@ public SearchActivityLocationBarLayout(Context context, AttributeSet attrs) { super(context, attrs, R.layout.location_bar_base); setUrlBarFocusable(true); + setBackground(ToolbarPhone.createModernLocationBarBackground(getResources())); + + // Now you might ask yourself what these paddings are doing? Great question, really glad + // you asked...OH MY...LOOK BEHIND YOU!!! + // + // <Sounds of original author running away> + // + // These numbers were chosen at a single snapshot in time where they roughly equated to + // the padding used in the modern tabbed mode focused omnibox. There is minimal rhyme or + // reason to this, but using something that approximated the toolbar logic looked even + // worse. + // + // Shrug. Once that layout logic is cleaned up, this should be universally replaced with + // something sane. + int toolbarSidePadding = getResources().getDimensionPixelSize(R.dimen.toolbar_edge_padding); + int backgroundSidePadding = getResources().getDimensionPixelSize( + R.dimen.modern_toolbar_background_focused_left_margin); + ViewCompat.setPaddingRelative(this, backgroundSidePadding + toolbarSidePadding, + getPaddingTop(), backgroundSidePadding, getPaddingBottom()); mPendingSearchPromoDecision = LocaleManager.getInstance().needToCheckForSearchEnginePromo(); } @@ -163,6 +184,6 @@ @Override public boolean useModernDesign() { - return false; + return true; } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchWidgetProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchWidgetProvider.java index c56ce718..778b978 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchWidgetProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchWidgetProvider.java
@@ -284,7 +284,7 @@ String text = TextUtils.isEmpty(engineName) || !shouldShowFullString() ? context.getString(R.string.search_widget_default) : context.getString(R.string.search_with_product, engineName); - views.setTextViewText(R.id.title, text); + views.setCharSequence(R.id.title, "setHint", text); return views; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarCoordinator.java index 23ac32f..6c61519 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarCoordinator.java
@@ -4,6 +4,8 @@ package org.chromium.chrome.browser.toolbar; +import android.content.res.ColorStateList; +import android.support.v7.content.res.AppCompatResources; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnTouchListener; @@ -21,6 +23,7 @@ import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.toolbar.BottomToolbarViewBinder.ViewHolder; import org.chromium.chrome.browser.toolbar.ToolbarButtonSlotData.ToolbarButtonData; +import org.chromium.chrome.browser.util.ColorUtils; import org.chromium.ui.base.WindowAndroid; import org.chromium.ui.resources.ResourceManager; @@ -40,11 +43,17 @@ /** The menu button that lives in the bottom toolbar. */ private final MenuButton mMenuButton; + /** The light mode tint to be used in bottom toolbar buttons. */ + private final ColorStateList mLightModeTint; + + /** The dark mode tint to be used in bottom toolbar buttons. */ + private final ColorStateList mDarkModeTint; + /** * Build the coordinator that manages the bottom toolbar. * @param fullscreenManager A {@link ChromeFullscreenManager} to update the bottom controls * height for the renderer. - * @param root The root {@link ViewGroup} for locating the vies to inflate. + * @param root The root {@link ViewGroup} for locating the views to inflate. * @param firstSlotData The data required to fill in the leftmost bottom toolbar button slot. * @param secondSlotData The data required to fill in the second bottom toolbar button slot. */ @@ -71,6 +80,11 @@ mTabSwitcherButtonCoordinator = new TabSwitcherButtonCoordinator(toolbarRoot); mMenuButton = toolbarRoot.findViewById(R.id.menu_button_wrapper); + + mLightModeTint = + AppCompatResources.getColorStateList(root.getContext(), R.color.light_mode_tint); + mDarkModeTint = + AppCompatResources.getColorStateList(root.getContext(), R.color.dark_mode_tint); } /** @@ -149,6 +163,15 @@ return mMenuButton.getMenuButton(); } + public void setPrimaryColor(int color) { + mMediator.setPrimaryColor(color); + + final boolean useLight = ColorUtils.shouldUseLightForegroundOnBackground(color); + final ColorStateList tint = useLight ? mLightModeTint : mDarkModeTint; + mTabSwitcherButtonCoordinator.setTint(tint); + mMenuButton.setTint(tint); + } + /** * Clean up any state when the bottom toolbar is destroyed. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarMediator.java index 5bab11d..a3b1392 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarMediator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarMediator.java
@@ -247,4 +247,8 @@ mSecondSlotData.tabSwitcherModeButtonData); } } + + void setPrimaryColor(int color) { + mModel.setValue(BottomToolbarModel.PRIMARY_COLOR, color); + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarModel.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarModel.java index bd868dd..7df5c40 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarModel.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarModel.java
@@ -47,10 +47,13 @@ public static final ObjectPropertyKey<ToolbarButtonData> SECOND_BUTTON_DATA = new ObjectPropertyKey<>(); + /** Primary color of bottom toolbar. */ + public static final IntPropertyKey PRIMARY_COLOR = new IntPropertyKey(); + /** Default constructor. */ public BottomToolbarModel() { super(Y_OFFSET, ANDROID_VIEW_VISIBLE, COMPOSITED_VIEW_VISIBLE, LAYOUT_MANAGER, TOOLBAR_SWIPE_LAYOUT, RESOURCE_MANAGER, TOOLBAR_SWIPE_HANDLER, FIRST_BUTTON_DATA, - SECOND_BUTTON_DATA); + SECOND_BUTTON_DATA, PRIMARY_COLOR); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarViewBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarViewBinder.java index c8d70aa..fa962b12 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarViewBinder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarViewBinder.java
@@ -12,6 +12,7 @@ import org.chromium.chrome.browser.modelutil.PropertyKey; import org.chromium.chrome.browser.modelutil.PropertyModelChangeProcessor; import org.chromium.chrome.browser.toolbar.ToolbarButtonSlotData.ToolbarButtonData; +import org.chromium.chrome.browser.util.ColorUtils; import org.chromium.chrome.browser.widget.TintedImageButton; /** @@ -89,21 +90,40 @@ model.getValue(BottomToolbarModel.TOOLBAR_SWIPE_HANDLER)); } else if (BottomToolbarModel.FIRST_BUTTON_DATA == propertyKey) { updateButton(view.firstTintedImageButton, - model.getValue(BottomToolbarModel.FIRST_BUTTON_DATA)); + model.getValue(BottomToolbarModel.FIRST_BUTTON_DATA), useLightIcons(model)); } else if (BottomToolbarModel.SECOND_BUTTON_DATA == propertyKey) { updateButton(view.secondTintedImageButton, - model.getValue(BottomToolbarModel.SECOND_BUTTON_DATA)); + model.getValue(BottomToolbarModel.SECOND_BUTTON_DATA), useLightIcons(model)); + } else if (BottomToolbarModel.PRIMARY_COLOR == propertyKey) { + final boolean useLightIcons = useLightIcons(model); + view.toolbarRoot.findViewById(R.id.bottom_sheet_toolbar) + .setBackgroundColor(model.getValue(BottomToolbarModel.PRIMARY_COLOR)); + updateButtonDrawable(view.firstTintedImageButton, + model.getValue(BottomToolbarModel.FIRST_BUTTON_DATA), useLightIcons); + updateButtonDrawable(view.secondTintedImageButton, + model.getValue(BottomToolbarModel.SECOND_BUTTON_DATA), useLightIcons); } else { assert false : "Unhandled property detected in BottomToolbarViewBinder!"; } } - private static void updateButton(TintedImageButton button, ToolbarButtonData buttonData) { + private static boolean useLightIcons(BottomToolbarModel model) { + return ColorUtils.shouldUseLightForegroundOnBackground( + model.getValue(BottomToolbarModel.PRIMARY_COLOR)); + } + + private static void updateButton( + TintedImageButton button, ToolbarButtonData buttonData, boolean useLightIcons) { if (buttonData == null) { button.setVisibility(View.INVISIBLE); } else { - buttonData.updateButton(button); + buttonData.updateButton(button, useLightIcons); button.setVisibility(View.VISIBLE); } } + + private static void updateButtonDrawable( + TintedImageButton button, ToolbarButtonData buttonData, boolean useLightIcons) { + if (buttonData != null) buttonData.updateButtonDrawable(button, useLightIcons); + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/MenuButton.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/MenuButton.java index 71b036d..1c1159d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/MenuButton.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/MenuButton.java
@@ -5,19 +5,21 @@ package org.chromium.chrome.browser.toolbar; import android.content.Context; +import android.content.res.ColorStateList; import android.util.AttributeSet; import android.view.View; import android.view.View.OnTouchListener; import android.widget.FrameLayout; import org.chromium.chrome.R; +import org.chromium.chrome.browser.widget.TintedImageButton; /** * The overflow menu button. */ class MenuButton extends FrameLayout { - /** The view for the menu button. */ - private View mMenuButtonView; + /** The {@link TintedImageButton} for the menu button. */ + private TintedImageButton mMenuTintedImageButton; /** The view for the update badge. */ private View mUpdateBadgeView; @@ -29,7 +31,7 @@ @Override protected void onFinishInflate() { super.onFinishInflate(); - mMenuButtonView = findViewById(R.id.menu_button); + mMenuTintedImageButton = findViewById(R.id.menu_button); mUpdateBadgeView = findViewById(R.id.menu_badge); } @@ -38,7 +40,7 @@ * clicked. */ void setTouchListener(OnTouchListener onTouchListener) { - mMenuButtonView.setOnTouchListener(onTouchListener); + mMenuTintedImageButton.setOnTouchListener(onTouchListener); } /** @@ -56,6 +58,14 @@ } View getMenuButton() { - return mMenuButtonView; + return mMenuTintedImageButton; + } + + /** + * @param tintList The {@link ColorStateList} that will tint the menu button (the badge is not + * tinted). + */ + void setTint(ColorStateList tintList) { + mMenuTintedImageButton.setTint(tintList); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonCoordinator.java index 18170a6..d0206a5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonCoordinator.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser.toolbar; +import android.content.res.ColorStateList; import android.view.View.OnClickListener; import android.view.ViewGroup; @@ -121,6 +122,13 @@ updateTabCount(); } + /** + * @param tint The {@ColorStateList} used to tint the button. + */ + public void setTint(ColorStateList tint) { + mTabSwitcherButtonModel.setValue(TabSwitcherButtonProperties.TINT, tint); + } + public void destroy() { if (mTabModelSelector != null) mTabModelSelector.removeObserver(mTabModelSelectorObserver); if (mTabModelSelectorTabModelObserver != null) mTabModelSelectorTabModelObserver.destroy();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonProperties.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonProperties.java index fb50d0f0..57070b9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonProperties.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonProperties.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser.toolbar; +import android.content.res.ColorStateList; import android.view.View.OnClickListener; import android.view.View.OnLongClickListener; @@ -26,6 +27,9 @@ public static final ObjectPropertyKey<OnLongClickListener> ON_LONG_CLICK_LISTENER = new ObjectPropertyKey<>(); + /** The button tint. */ + public static final ObjectPropertyKey<ColorStateList> TINT = new ObjectPropertyKey<>(); + public static final PropertyKey[] ALL_KEYS = - new PropertyKey[] {NUMBER_OF_TABS, ON_CLICK_LISTENER, ON_LONG_CLICK_LISTENER}; + new PropertyKey[] {NUMBER_OF_TABS, ON_CLICK_LISTENER, ON_LONG_CLICK_LISTENER, TINT}; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonView.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonView.java index 7de441d8..3971e59 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonView.java
@@ -5,6 +5,7 @@ package org.chromium.chrome.browser.toolbar; import android.content.Context; +import android.content.res.ColorStateList; import android.util.AttributeSet; import android.widget.ImageView; @@ -18,7 +19,7 @@ /** * A drawable for the tab switcher icon. */ - private TabSwitcherDrawable mTabSwitcherButtonButtonDrawable; + private TabSwitcherDrawable mTabSwitcherButtonDrawable; public TabSwitcherButtonView(Context context, AttributeSet attrs) { super(context, attrs); @@ -28,9 +29,9 @@ protected void onFinishInflate() { super.onFinishInflate(); - mTabSwitcherButtonButtonDrawable = + mTabSwitcherButtonDrawable = TabSwitcherDrawable.createTabSwitcherDrawable(getContext(), false); - setImageDrawable(mTabSwitcherButtonButtonDrawable); + setImageDrawable(mTabSwitcherButtonDrawable); } /** @@ -41,6 +42,13 @@ setContentDescription(getResources().getQuantityString( R.plurals.accessibility_toolbar_btn_tabswitcher_toggle, numberOfTabs, numberOfTabs)); - mTabSwitcherButtonButtonDrawable.updateForTabCount(numberOfTabs, false); + mTabSwitcherButtonDrawable.updateForTabCount(numberOfTabs, false); + } + + /** + * @param tint The {@ColorStateList} used to tint the button. + */ + public void setTint(ColorStateList tint) { + mTabSwitcherButtonDrawable.setTint(tint); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonViewBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonViewBinder.java index 16920b03..3fef53d5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonViewBinder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonViewBinder.java
@@ -32,6 +32,8 @@ } else if (TabSwitcherButtonProperties.ON_LONG_CLICK_LISTENER == propertyKey) { view.setOnLongClickListener( model.getValue(TabSwitcherButtonProperties.ON_LONG_CLICK_LISTENER)); + } else if (TabSwitcherButtonProperties.TINT == propertyKey) { + view.setTint(model.getValue(TabSwitcherButtonProperties.TINT)); } else { assert false : "Unhandled property detected in TabSwitcherViewBinder!"; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarButtonSlotData.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarButtonSlotData.java index 8849cba5..c01f058 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarButtonSlotData.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarButtonSlotData.java
@@ -5,7 +5,10 @@ package org.chromium.chrome.browser.toolbar; import android.content.Context; -import android.support.v4.content.ContextCompat; +import android.content.res.ColorStateList; +import android.graphics.drawable.Drawable; +import android.support.v4.graphics.drawable.DrawableCompat; +import android.support.v7.content.res.AppCompatResources; import android.view.View.OnClickListener; import org.chromium.chrome.R; @@ -34,42 +37,52 @@ * buttons when entering or leaving tab switching mode. */ static class ToolbarButtonData { - private final int mDrawableResId; - // TODO(amaralp): Add incognito accessibility string. - private final CharSequence mAccessibilityStringResId; + private final Drawable mDrawable; + private final CharSequence mLightAccessibilityString; + private final CharSequence mDarkAccessibilityString; private final OnClickListener mOnClickListener; - private final boolean mShouldTint; + + private final ColorStateList mLightTint; + private final ColorStateList mDarkTint; /** - * @param drawableResId The drawable's resource id. - * @param accessibilityStringResId The accessibility's resource id. - * @param onClickListener An {@link OnClickListener} that is triggered when this button is - * clicked. - * @param shouldTint Whether the button should be tinted. - * @param context The {@link Context} used to get the drawable and accessibility string - * resources. + * @param drawable The {@link Drawable} that will be shown in the button slot. + * @param lightAccessibilityString The accessibility string to be used in light mode. + * @param darkAccessibilityString The accessibility string to be used in dark mode. + * @param onClickListener The listener that will be fired when this button is clicked. + * @param context The {@link Context} that is used to obtain tinting information. */ - ToolbarButtonData(int drawableResId, int accessibilityStringResId, - OnClickListener onClickListener, boolean shouldTint, Context context) { - mAccessibilityStringResId = context.getString(accessibilityStringResId); + ToolbarButtonData(Drawable drawable, CharSequence lightAccessibilityString, + CharSequence darkAccessibilityString, OnClickListener onClickListener, + Context context) { + mLightTint = AppCompatResources.getColorStateList(context, R.color.light_mode_tint); + mDarkTint = AppCompatResources.getColorStateList(context, R.color.dark_mode_tint); + + mDrawable = drawable; + mLightAccessibilityString = lightAccessibilityString; + mDarkAccessibilityString = darkAccessibilityString; mOnClickListener = onClickListener; - mDrawableResId = drawableResId; - mShouldTint = shouldTint; } /** * @param imageButton The {@link TintedImageButton} this button data will fill. + * @param isLight Whether or not to use light mode. */ - void updateButton(TintedImageButton imageButton) { + void updateButton(TintedImageButton imageButton, boolean isLight) { imageButton.setOnClickListener(mOnClickListener); - imageButton.setImageResource(mDrawableResId); - imageButton.setContentDescription(mAccessibilityStringResId); - if (mShouldTint) { - imageButton.setImageTintList(ContextCompat.getColorStateList( - imageButton.getContext(), R.color.dark_mode_tint)); - } else { - imageButton.setImageTintList(null); - } + updateButtonDrawable(imageButton, isLight); + } + + /** + * @param imageButton The {@link TintedImageButton} this button data will fill. + * @param isLight Whether or not to use light mode. + */ + void updateButtonDrawable(TintedImageButton imageButton, boolean isLight) { + DrawableCompat.setTintList(mDrawable, isLight ? mLightTint : mDarkTint); + imageButton.setImageDrawable(mDrawable); + imageButton.setContentDescription( + isLight ? mLightAccessibilityString : mDarkAccessibilityString); + imageButton.invalidate(); } } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java index 9dece39..6eb78ec 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -4,7 +4,6 @@ package org.chromium.chrome.browser.toolbar; -import android.content.Context; import android.content.res.Configuration; import android.graphics.drawable.Drawable; import android.os.Handler; @@ -14,6 +13,8 @@ import android.support.annotation.DrawableRes; import android.support.annotation.IntDef; import android.support.annotation.StringRes; +import android.support.graphics.drawable.VectorDrawableCompat; +import android.support.v4.content.ContextCompat; import android.support.v7.app.ActionBar; import android.text.TextUtils; import android.view.View; @@ -642,9 +643,9 @@ public void enableBottomToolbar() { if (FeatureUtilities.isBottomToolbarEnabled()) { final ToolbarButtonSlotData firstButtonSlot = - new ToolbarButtonSlotData(createHomeButton(mActivity)); + new ToolbarButtonSlotData(createHomeButton()); final ToolbarButtonSlotData secondButtonSlot = - new ToolbarButtonSlotData(createSearchAccelerator(mActivity)); + new ToolbarButtonSlotData(createSearchAccelerator()); mBottomToolbarCoordinator = new BottomToolbarCoordinator( mActivity.getFullscreenManager(), mActivity.findViewById(R.id.coordinator), firstButtonSlot, secondButtonSlot); @@ -672,38 +673,54 @@ }; } - private ToolbarButtonData createHomeButton(Context context) { + private ToolbarButtonData createHomeButton() { final OnClickListener homeButtonListener = v -> { recordBottomToolbarUseForIPH(); openHomepage(); }; - return new ToolbarButtonData(R.drawable.btn_toolbar_home, - R.string.accessibility_toolbar_btn_home, homeButtonListener, true, context); + final Drawable drawable = ContextCompat.getDrawable(mActivity, R.drawable.btn_toolbar_home); + final CharSequence accessibilityString = + mActivity.getString(R.string.accessibility_toolbar_btn_home); + return new ToolbarButtonData( + drawable, accessibilityString, accessibilityString, homeButtonListener, mActivity); } - private ToolbarButtonData createNewTabButton( - OnClickListener newTabClickListener, Context context) { - return new ToolbarButtonData(R.drawable.btn_new_tab_white_normal, - R.string.accessibility_toolbar_btn_new_tab, newTabClickListener, false, context); + private ToolbarButtonData createNewTabButton(OnClickListener newTabClickListener) { + final CharSequence normalAccessibilityString = + mActivity.getString(R.string.accessibility_toolbar_btn_new_tab); + final CharSequence incognitoAccessibilityString = + mActivity.getString(R.string.accessibility_toolbar_btn_new_incognito_tab); + + final Drawable drawable = VectorDrawableCompat.create( + mActivity.getResources(), R.drawable.new_tab_icon, mActivity.getTheme()); + return new ToolbarButtonData(drawable, normalAccessibilityString, + incognitoAccessibilityString, newTabClickListener, mActivity); } - private ToolbarButtonData createSearchAccelerator(Context context) { + private ToolbarButtonData createSearchAccelerator() { final OnClickListener searchAcceleratorListener = v -> { recordBottomToolbarUseForIPH(); recordOmniboxFocusReason(OmniboxFocusReason.ACCELERATOR_TAP); ACCELERATOR_BUTTON_TAP_ACTION.record(); setUrlBarFocus(true); }; - return new ToolbarButtonData(R.drawable.ic_search, - R.string.accessibility_toolbar_btn_search_accelerator, searchAcceleratorListener, - true, context); + final Drawable drawable = ContextCompat.getDrawable(mActivity, R.drawable.ic_search); + final CharSequence accessibilityString = + mActivity.getString(R.string.accessibility_toolbar_btn_search_accelerator); + return new ToolbarButtonData(drawable, accessibilityString, accessibilityString, + searchAcceleratorListener, mActivity); } private ToolbarButtonData createIncognitoToggleButton( - OnClickListener incognitoToggleClickHandler, Context context) { - return new ToolbarButtonData(R.drawable.btn_tabstrip_switch_normal, - R.string.accessibility_tabstrip_btn_incognito_toggle_standard, - incognitoToggleClickHandler, false, context); + OnClickListener incognitoToggleClickHandler) { + final CharSequence normalAccessibilityString = + mActivity.getString(R.string.accessibility_tabstrip_btn_incognito_toggle_standard); + final CharSequence incognitoAccessibilityString = + mActivity.getString(R.string.accessibility_tabstrip_btn_incognito_toggle_incognito); + final Drawable drawable = + ContextCompat.getDrawable(mActivity, R.drawable.incognito_statusbar); + return new ToolbarButtonData(drawable, normalAccessibilityString, + incognitoAccessibilityString, incognitoToggleClickHandler, mActivity); } /** @@ -831,8 +848,7 @@ && PrefServiceBridge.getInstance().isIncognitoModeEnabled(); final ToolbarButtonData firstSlotTabSwitcherButtonData = showIncognitoToggleButton ? createIncognitoToggleButton( - wrapBottomToolbarClickListenerForIPH(incognitoClickHandler), - mActivity) + wrapBottomToolbarClickListenerForIPH(incognitoClickHandler)) : null; mAppMenuButtonHelper.setOnClickRunnable(() -> recordBottomToolbarUseForIPH()); mBottomToolbarCoordinator.initializeWithNative( @@ -842,8 +858,7 @@ mAppMenuButtonHelper, mTabModelSelector, mOverviewModeBehavior, mActivity.getContextualSearchManager(), mActivity.getWindowAndroid(), firstSlotTabSwitcherButtonData, - createNewTabButton( - wrapBottomToolbarClickListenerForIPH(newTabClickHandler), mActivity)); + createNewTabButton(wrapBottomToolbarClickListenerForIPH(newTabClickHandler))); Tab currentTab = tabModelSelector.getCurrentTab(); maybeShowDuetHelpBubble(currentTab); @@ -1288,6 +1303,10 @@ mCurrentThemeColor = color; mToolbarModel.setPrimaryColor(color); mToolbar.onPrimaryColorChanged(shouldAnimate); + + if (mBottomToolbarCoordinator != null) { + mBottomToolbarCoordinator.setPrimaryColor(color); + } } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java index 6ead434..3d98256 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java
@@ -419,7 +419,7 @@ Resources res = getResources(); mModernLocationBarBackgroundHeight = res.getDimensionPixelSize(R.dimen.modern_toolbar_background_size); - mLocationBarBackground = createModernLocationBarBackground(); + mLocationBarBackground = createModernLocationBarBackground(getResources()); mLocationBarBackground.getPadding(mLocationBarBackgroundPadding); mLocationBarBackground.mutate(); mLocationBar.setPadding(mLocationBarBackgroundPadding.left, @@ -448,12 +448,12 @@ /** * @return The drawable for the modern location bar background. */ - public Drawable createModernLocationBarBackground() { + public static Drawable createModernLocationBarBackground(Resources resources) { Drawable drawable = ApiCompatibilityUtils.getDrawable( - getResources(), R.drawable.modern_toolbar_background_white); + resources, R.drawable.modern_toolbar_background_white); drawable.mutate(); drawable.setColorFilter( - ApiCompatibilityUtils.getColor(getResources(), R.color.modern_light_grey), + ApiCompatibilityUtils.getColor(resources, R.color.modern_light_grey), PorterDuff.Mode.SRC_IN); return drawable; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectionDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectionDelegate.java index 03f0b03..3c58623 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectionDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectionDelegate.java
@@ -21,6 +21,7 @@ /** * Observer interface to be notified of selection changes. + * @param <E> The type of the selectable items this delegate interacts with. */ public interface SelectionObserver<E> { /** @@ -60,6 +61,15 @@ } /** + * Initializes the selected item list with a new set (clears previous selection). + * @param items The items to set as selected. + */ + public void setSelectedItems(Set<E> items) { + mSelectedItems = items; + notifyObservers(); + } + + /** * True if the item is selected. False otherwise. * @param item The item. * @return Whether the item is selected.
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd index 59b760e..05fa4293 100644 --- a/chrome/android/java/strings/android_chrome_strings.grd +++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -3072,7 +3072,7 @@ Update available. More options </message> <message name="IDS_ACCESSIBILITY_TOOLBAR_BTN_SEARCH_ACCELERATOR" desc="Content description for the search accelerator button"> - Search Accelerator + Search button </message> <message name="IDS_ACCESSIBILITY_TOOLBAR_BTN_SITE_INFO" desc="Content description for the page icon that gives more site information when clicked. The icon can be a magnifier for search result pages, or other icons representing the page state."> Site information @@ -3401,6 +3401,9 @@ </message> <!-- Contacts Picker strings --> + <message name="IDS_CONTACTS_PICKER_SEARCH" desc="The hint text for the search box for contacts."> + Search your contacts + </message> <message name="IDS_CONTACTS_PICKER_SELECT_CONTACTS" desc="The label at the top of the dialog that allows users to select contacts from their device and share the details with a web page."> Select contacts </message>
diff --git a/chrome/android/java/strings/android_chrome_strings_grd/IDS_CONTACTS_PICKER_SEARCH.png.sha1 b/chrome/android/java/strings/android_chrome_strings_grd/IDS_CONTACTS_PICKER_SEARCH.png.sha1 new file mode 100644 index 0000000..ced839a --- /dev/null +++ b/chrome/android/java/strings/android_chrome_strings_grd/IDS_CONTACTS_PICKER_SEARCH.png.sha1
@@ -0,0 +1 @@ +26c0c8e6612f7798a1c2648c17f1cba0cb088aa9 \ No newline at end of file
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/searchwidget/SearchWidgetProviderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/searchwidget/SearchWidgetProviderTest.java index fcb36f5..ce2bd15 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/searchwidget/SearchWidgetProviderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/searchwidget/SearchWidgetProviderTest.java
@@ -249,7 +249,7 @@ // Confirm that the string is correct. TextView titleView = (TextView) view.findViewById(R.id.title); Assert.assertEquals(View.VISIBLE, titleView.getVisibility()); - Assert.assertEquals(expectedString, titleView.getText()); + Assert.assertEquals(expectedString, titleView.getHint()); // Confirm the visibility of the microphone. View microphoneView = view.findViewById(R.id.microphone_icon);
diff --git a/chrome/android/modules/ar/AndroidManifest.xml b/chrome/android/modules/ar/AndroidManifest.xml new file mode 100644 index 0000000..f457fc7 --- /dev/null +++ b/chrome/android/modules/ar/AndroidManifest.xml
@@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. --> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:dist="http://schemas.android.com/apk/distribution" + package="{{manifest_package}}"> + + <!-- Chrome AR is only supported on Android N+. --> + <uses-sdk + android:minSdkVersion="24" + android:targetSdkVersion="{{target_sdk_version}}" /> + + <!-- TODO(crbug.com/863068): Set dist:onDemand="true" once we can on-demand + install modules. --> + <!-- TODO(crbug.com/871912: Use @string reference for dist:title. --> + <dist:module + dist:onDemand="false" + dist:title="AR"> + <dist:fusing dist:include="false" /> + </dist:module> + + <application> + </application> +</manifest>
diff --git a/chrome/android/modules/ar/OWNERS b/chrome/android/modules/ar/OWNERS new file mode 100644 index 0000000..4227433e --- /dev/null +++ b/chrome/android/modules/ar/OWNERS
@@ -0,0 +1,6 @@ +tiborg@chromium.org +vollick@chromium.org + +# TEAM: xr-dev@chromium.org +# COMPONENT: Internals>XR>AR +# OS: Android \ No newline at end of file
diff --git a/chrome/android/modules/ar/README b/chrome/android/modules/ar/README new file mode 100644 index 0000000..e621db2 --- /dev/null +++ b/chrome/android/modules/ar/README
@@ -0,0 +1,3 @@ +The AR dynamic feature module on-demand delivers code necessary to support AR in +Chrome. This folder contains the template for creating an AR DFM target as well +as the required Android manifest. \ No newline at end of file
diff --git a/chrome/android/modules/ar/ar_module_tmpl.gni b/chrome/android/modules/ar/ar_module_tmpl.gni new file mode 100644 index 0000000..5400cbe --- /dev/null +++ b/chrome/android/modules/ar/ar_module_tmpl.gni
@@ -0,0 +1,53 @@ +# Copyright 2018 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/android/rules.gni") +import("//device/vr/buildflags/buildflags.gni") + +assert(enable_arcore) + +template("ar_module_tmpl") { + _manifest = "$target_gen_dir/AndroidManifest.xml" + assert(defined(invoker.manifest_package)) + + _manifest_target = "${target_name}__manifest" + jinja_template(_manifest_target) { + input = "//chrome/android/modules/ar/AndroidManifest.xml" + output = _manifest + variables = [ + "target_sdk_version=$android_sdk_version", + "manifest_package=${invoker.manifest_package}", + ] + } + + android_app_bundle_module(target_name) { + module_name = "ArModule" + android_manifest = _manifest + android_manifest_dep = ":$_manifest_target" + deps = [ + "//third_party/arcore-android-sdk:libdynamite_client_java", + ] + + # We only want to add the 32 bit arcore shim even for 64 bit monochrome + # builds. AR is never used in 64 bit mode. We store the arcore shim as a + # separate .so in the bundle module and only load as needed. + if (android_64bit_target_cpu && build_apk_secondary_abi) { + secondary_abi_loadable_modules = [ "//third_party/arcore-android-sdk/libraries/android_arm/libarcore_sdk_c_minimal.so" ] + + # Bundletool requires all modules of a bundle to support the same set of + # architectures. Monochrome base module supports arm64. Add a zero-byte, + # "64 bit" dummy library to trick bundletool into thinking that the AR + # module does support arm64, too. + loadable_modules = + [ "//third_party/arcore-android-sdk/libarcore_dummy.so" ] + } else if (android_64bit_target_cpu && !build_apk_secondary_abi) { + loadable_modules = [ "//third_party/arcore-android-sdk/libraries/android_arm64/libarcore_sdk_c_minimal.so" ] + } else { + loadable_modules = [ "//third_party/arcore-android-sdk/libraries/android_arm/libarcore_sdk_c_minimal.so" ] + } + uncompress_shared_libraries = true + + proguard_enabled = !is_java_debug + } +}
diff --git a/chrome/app/nibs/BUILD.gn b/chrome/app/nibs/BUILD.gn index 9763cb9..bfd6727f 100644 --- a/chrome/app/nibs/BUILD.gn +++ b/chrome/app/nibs/BUILD.gn
@@ -20,13 +20,7 @@ ] if (!mac_views_browser) { - translated_xibs += [ - "ExtensionInstallPrompt.xib", - "ExtensionInstallPromptNoWarnings.xib", - "ExtensionInstallPromptWebstoreData.xib", - "ExtensionInstalledBubble.xib", - "HttpAuthLoginSheet.xib", - ] + translated_xibs += [ "HttpAuthLoginSheet.xib" ] } untranslated_xibs = [
diff --git a/chrome/app/nibs/ExtensionInstallPrompt.xib b/chrome/app/nibs/ExtensionInstallPrompt.xib deleted file mode 100644 index 506e2cb..0000000 --- a/chrome/app/nibs/ExtensionInstallPrompt.xib +++ /dev/null
@@ -1,138 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="5056" systemVersion="13F1077" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none"> - <dependencies> - <deployment version="1090" identifier="macosx"/> - <development version="5100" identifier="xcode"/> - <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="5056"/> - </dependencies> - <objects> - <customObject id="-2" userLabel="File's Owner" customClass="ExtensionInstallViewController"> - <connections> - <outlet property="cancelButton_" destination="169" id="189"/> - <outlet property="iconView_" destination="170" id="188"/> - <outlet property="okButton_" destination="168" id="190"/> - <outlet property="outlineView_" destination="172" id="194"/> - <outlet property="titleField_" destination="167" id="187"/> - <outlet property="view" destination="166" id="186"/> - </connections> - </customObject> - <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/> - <customObject id="-3" userLabel="Application"/> - <customObject id="140" customClass="ChromeUILocalizer"/> - <customObject id="141" customClass="GTMUILocalizerAndLayoutTweaker"> - <connections> - <outlet property="localizer_" destination="140" id="142"/> - <outlet property="uiObject_" destination="166" id="185"/> - </connections> - </customObject> - <customView id="166"> - <rect key="frame" x="0.0" y="0.0" width="468" height="149"/> - <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> - <subviews> - <textField verticalHuggingPriority="750" id="167"> - <rect key="frame" x="19" y="118" width="357" height="17"/> - <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> - <textFieldCell key="cell" sendsActionOnEndEditing="YES" title="Title" id="180"> - <font key="font" metaFont="system" size="15"/> - <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/> - <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/> - </textFieldCell> - </textField> - <button id="168" customClass="ConstrainedWindowButton"> - <rect key="frame" x="352" y="19" width="96" height="28"/> - <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/> - <buttonCell key="cell" type="square" title="^IDS_EXTENSION_PROMPT_INSTALL_BUTTON" bezelStyle="shadowlessSquare" image="D4520959-E685-4758-9BD2-329FFA7259A0" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="179" customClass="ConstrainedWindowButtonCell"> - <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> - <font key="font" metaFont="system"/> - </buttonCell> - <connections> - <action selector="ok:" target="-2" id="184"/> - </connections> - </button> - <button id="169" customClass="ConstrainedWindowButton"> - <rect key="frame" x="246" y="19" width="96" height="28"/> - <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/> - <buttonCell key="cell" type="square" title="^IDS_CANCEL" bezelStyle="shadowlessSquare" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="178" customClass="ConstrainedWindowButtonCell"> - <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> - <font key="font" metaFont="system"/> - <string key="keyEquivalent" base64-UTF8="YES"> -DQ -</string> - </buttonCell> - <connections> - <action selector="cancel:" target="-2" id="183"/> - </connections> - </button> - <imageView id="170"> - <rect key="frame" x="380" y="64" width="64" height="64"/> - <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/> - <imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" id="177"/> - </imageView> - <scrollView focusRingType="none" borderType="none" autohidesScrollers="YES" horizontalLineScroll="19" horizontalPageScroll="10" verticalLineScroll="19" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" id="171"> - <rect key="frame" x="0.0" y="62" width="376" height="48"/> - <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> - <clipView key="contentView" drawsBackground="NO" copiesOnScroll="NO" id="IXK-Nb-gJ2"> - <rect key="frame" x="0.0" y="0.0" width="376" height="48"/> - <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> - <subviews> - <outlineView focusRingType="none" verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="none" columnReordering="NO" columnResizing="NO" multipleSelection="NO" autosaveColumns="NO" typeSelect="NO" indentationPerLevel="16" outlineTableColumn="175" id="172"> - <rect key="frame" x="0.0" y="0.0" width="378" height="48"/> - <autoresizingMask key="autoresizingMask"/> - <size key="intercellSpacing" width="3" height="2"/> - <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/> - <color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/> - <tableColumns> - <tableColumn editable="NO" width="375" minWidth="16" maxWidth="1000" id="175"> - <tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left"> - <font key="font" size="12" name="LucidaGrande"/> - <color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/> - <color key="backgroundColor" white="0.33333298560000002" alpha="1" colorSpace="calibratedWhite"/> - </tableHeaderCell> - <textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" alignment="left" title="Text Cell" id="176"> - <font key="font" metaFont="cellTitle"/> - <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/> - <color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/> - </textFieldCell> - </tableColumn> - </tableColumns> - <connections> - <outlet property="dataSource" destination="-2" id="192"/> - <outlet property="delegate" destination="-2" id="193"/> - </connections> - </outlineView> - </subviews> - <color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/> - </clipView> - <scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="173"> - <rect key="frame" x="-100" y="-100" width="283" height="15"/> - <autoresizingMask key="autoresizingMask"/> - </scroller> - <scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="NO" id="174"> - <rect key="frame" x="-100" y="-100" width="15" height="17"/> - <autoresizingMask key="autoresizingMask"/> - </scroller> - </scrollView> - </subviews> - </customView> - </objects> - <resources> - <image name="D4520959-E685-4758-9BD2-329FFA7259A0" width="1" height="1"> - <mutableData key="keyedArchiveRepresentation"> -YnBsaXN0MDDUAQIDBAUGPj9YJHZlcnNpb25YJG9iamVjdHNZJGFyY2hpdmVyVCR0b3ASAAGGoK4HCBMU -GR4fIyQsLzI4O1UkbnVsbNUJCgsMDQ4PEBESVk5TU2l6ZVYkY2xhc3NcTlNJbWFnZUZsYWdzVk5TUmVw -c1dOU0NvbG9ygAKADRIgwwAAgAOAC1Z7MSwgMX3SFQoWGFpOUy5vYmplY3RzoReABIAK0hUKGh2iGxyA -BYAGgAkQANIgCiEiXxAUTlNUSUZGUmVwcmVzZW50YXRpb26AB4AITxCsTU0AKgAAAAoAAAANAQAAAwAA -AAEAAQAAAQEAAwAAAAEAAQAAAQIAAwAAAAIACAAIAQMAAwAAAAEAAQAAAQYAAwAAAAEAAQAAAREABAAA -AAEAAAAIARIAAwAAAAEAAQAAARUAAwAAAAEAAgAAARYAAwAAAAEAAQAAARcABAAAAAEAAAACARwAAwAA -AAEAAQAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAANIlJicoWiRjbGFzc25hbWVYJGNsYXNzZXNf -EBBOU0JpdG1hcEltYWdlUmVwoykqK18QEE5TQml0bWFwSW1hZ2VSZXBaTlNJbWFnZVJlcFhOU09iamVj -dNIlJi0uV05TQXJyYXmiLSvSJSYwMV5OU011dGFibGVBcnJheaMwLSvTMzQKNTY3V05TV2hpdGVcTlND -b2xvclNwYWNlRDAgMAAQA4AM0iUmOTpXTlNDb2xvcqI5K9IlJjw9V05TSW1hZ2WiPCtfEA9OU0tleWVk -QXJjaGl2ZXLRQEFUcm9vdIABAAgAEQAaACMALQAyADcARgBMAFcAXgBlAHIAeQCBAIMAhQCKAIwAjgCV -AJoApQCnAKkAqwCwALMAtQC3ALkAuwDAANcA2QDbAYoBjwGaAaMBtgG6Ac0B2AHhAeYB7gHxAfYCBQIJ -AhACGAIlAioCLAIuAjMCOwI+AkMCSwJOAmACYwJoAAAAAAAAAgEAAAAAAAAAQgAAAAAAAAAAAAAAAAAA -Amo -</mutableData> - </image> - </resources> -</document>
diff --git a/chrome/app/nibs/ExtensionInstallPromptNoWarnings.xib b/chrome/app/nibs/ExtensionInstallPromptNoWarnings.xib deleted file mode 100644 index 60c62d51..0000000 --- a/chrome/app/nibs/ExtensionInstallPromptNoWarnings.xib +++ /dev/null
@@ -1,93 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="5056" systemVersion="13F1077" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none"> - <dependencies> - <deployment version="1090" identifier="macosx"/> - <development version="5100" identifier="xcode"/> - <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="5056"/> - </dependencies> - <objects> - <customObject id="-2" userLabel="File's Owner" customClass="ExtensionInstallViewController"> - <connections> - <outlet property="cancelButton_" destination="8" id="11"/> - <outlet property="iconView_" destination="3" id="19"/> - <outlet property="okButton_" destination="7" id="12"/> - <outlet property="titleField_" destination="5" id="25"/> - <outlet property="view" destination="23" id="24"/> - </connections> - </customObject> - <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/> - <customObject id="-3" userLabel="Application"/> - <customObject id="15" customClass="ChromeUILocalizer"/> - <customObject id="16" customClass="GTMUILocalizerAndLayoutTweaker"> - <connections> - <outlet property="localizer_" destination="15" id="18"/> - <outlet property="uiObject_" destination="23" id="26"/> - </connections> - </customObject> - <customView id="23"> - <rect key="frame" x="0.0" y="0.0" width="468" height="151"/> - <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> - <subviews> - <imageView id="3"> - <rect key="frame" x="380" y="66" width="64" height="64"/> - <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/> - <imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" id="4"/> - </imageView> - <textField verticalHuggingPriority="750" id="5"> - <rect key="frame" x="19" y="120" width="347" height="17"/> - <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> - <textFieldCell key="cell" sendsActionOnEndEditing="YES" title="Title" id="6"> - <font key="font" metaFont="system" size="15"/> - <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/> - <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/> - </textFieldCell> - </textField> - <button id="7" customClass="ConstrainedWindowButton"> - <rect key="frame" x="352" y="19" width="96" height="28"/> - <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/> - <buttonCell key="cell" type="square" title="^IDS_EXTENSION_PROMPT_INSTALL_BUTTON" bezelStyle="shadowlessSquare" image="C25F3098-40C0-44B1-BEBC-90A59D6FCD55" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="10" customClass="ConstrainedWindowButtonCell"> - <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> - <font key="font" metaFont="system"/> - </buttonCell> - <connections> - <action selector="ok:" target="-2" id="22"/> - </connections> - </button> - <button id="8" customClass="ConstrainedWindowButton"> - <rect key="frame" x="246" y="19" width="96" height="28"/> - <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/> - <buttonCell key="cell" type="square" title="^IDS_CANCEL" bezelStyle="shadowlessSquare" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="9" customClass="ConstrainedWindowButtonCell"> - <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> - <font key="font" metaFont="system"/> - <string key="keyEquivalent" base64-UTF8="YES"> -DQ -</string> - </buttonCell> - <connections> - <action selector="cancel:" target="-2" id="21"/> - </connections> - </button> - </subviews> - </customView> - </objects> - <resources> - <image name="C25F3098-40C0-44B1-BEBC-90A59D6FCD55" width="1" height="1"> - <mutableData key="keyedArchiveRepresentation"> -YnBsaXN0MDDUAQIDBAUGPj9YJHZlcnNpb25YJG9iamVjdHNZJGFyY2hpdmVyVCR0b3ASAAGGoK4HCBMU -GR4fIyQsLzI4O1UkbnVsbNUJCgsMDQ4PEBESVk5TU2l6ZVYkY2xhc3NcTlNJbWFnZUZsYWdzVk5TUmVw -c1dOU0NvbG9ygAKADRIgwwAAgAOAC1Z7MSwgMX3SFQoWGFpOUy5vYmplY3RzoReABIAK0hUKGh2iGxyA -BYAGgAkQANIgCiEiXxAUTlNUSUZGUmVwcmVzZW50YXRpb26AB4AITxCsTU0AKgAAAAoAAAANAQAAAwAA -AAEAAQAAAQEAAwAAAAEAAQAAAQIAAwAAAAIACAAIAQMAAwAAAAEAAQAAAQYAAwAAAAEAAQAAAREABAAA -AAEAAAAIARIAAwAAAAEAAQAAARUAAwAAAAEAAgAAARYAAwAAAAEAAQAAARcABAAAAAEAAAACARwAAwAA -AAEAAQAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAANIlJicoWiRjbGFzc25hbWVYJGNsYXNzZXNf -EBBOU0JpdG1hcEltYWdlUmVwoykqK18QEE5TQml0bWFwSW1hZ2VSZXBaTlNJbWFnZVJlcFhOU09iamVj -dNIlJi0uV05TQXJyYXmiLSvSJSYwMV5OU011dGFibGVBcnJheaMwLSvTMzQKNTY3V05TV2hpdGVcTlND -b2xvclNwYWNlRDAgMAAQA4AM0iUmOTpXTlNDb2xvcqI5K9IlJjw9V05TSW1hZ2WiPCtfEA9OU0tleWVk -QXJjaGl2ZXLRQEFUcm9vdIABAAgAEQAaACMALQAyADcARgBMAFcAXgBlAHIAeQCBAIMAhQCKAIwAjgCV -AJoApQCnAKkAqwCwALMAtQC3ALkAuwDAANcA2QDbAYoBjwGaAaMBtgG6Ac0B2AHhAeYB7gHxAfYCBQIJ -AhACGAIlAioCLAIuAjMCOwI+AkMCSwJOAmACYwJoAAAAAAAAAgEAAAAAAAAAQgAAAAAAAAAAAAAAAAAA -Amo -</mutableData> - </image> - </resources> -</document>
diff --git a/chrome/app/nibs/ExtensionInstallPromptWebstoreData.xib b/chrome/app/nibs/ExtensionInstallPromptWebstoreData.xib deleted file mode 100644 index ebc531b..0000000 --- a/chrome/app/nibs/ExtensionInstallPromptWebstoreData.xib +++ /dev/null
@@ -1,183 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="5056" systemVersion="13F1077" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none"> - <dependencies> - <deployment version="1090" identifier="macosx"/> - <development version="5100" identifier="xcode"/> - <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="5056"/> - </dependencies> - <objects> - <customObject id="-2" userLabel="File's Owner" customClass="ExtensionInstallViewController"> - <connections> - <outlet property="cancelButton_" destination="126" id="150"/> - <outlet property="iconView_" destination="130" id="137"/> - <outlet property="okButton_" destination="124" id="149"/> - <outlet property="outlineView_" destination="183" id="188"/> - <outlet property="ratingCountField_" destination="169" id="171"/> - <outlet property="ratingStars_" destination="172" id="173"/> - <outlet property="storeLinkButton_" destination="155" id="194"/> - <outlet property="titleField_" destination="118" id="144"/> - <outlet property="userCountField_" destination="153" id="158"/> - <outlet property="view" destination="191" id="193"/> - <outlet property="warningsSeparator_" destination="152" id="180"/> - </connections> - </customObject> - <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/> - <customObject id="-3" userLabel="Application"/> - <customObject id="140" customClass="ChromeUILocalizer"/> - <customObject id="141" customClass="GTMUILocalizerAndLayoutTweaker"> - <connections> - <outlet property="localizer_" destination="140" id="142"/> - <outlet property="uiObject_" destination="191" id="192"/> - </connections> - </customObject> - <customView id="191"> - <rect key="frame" x="0.0" y="0.0" width="468" height="214"/> - <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> - <subviews> - <textField verticalHuggingPriority="750" id="118"> - <rect key="frame" x="19" y="183" width="357" height="17"/> - <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> - <textFieldCell key="cell" sendsActionOnEndEditing="YES" title="Title" id="119"> - <font key="font" metaFont="system" size="15"/> - <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/> - <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/> - </textFieldCell> - </textField> - <button id="124" customClass="ConstrainedWindowButton"> - <rect key="frame" x="352" y="14" width="96" height="28"/> - <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/> - <buttonCell key="cell" type="square" title="^IDS_EXTENSION_PROMPT_INSTALL_BUTTON" bezelStyle="shadowlessSquare" image="454BDBF6-F64D-4B84-9B01-98D6D896672C" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="125" customClass="ConstrainedWindowButtonCell"> - <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> - <font key="font" metaFont="system"/> - </buttonCell> - <connections> - <action selector="ok:" target="-2" id="134"/> - </connections> - </button> - <button id="126" customClass="ConstrainedWindowButton"> - <rect key="frame" x="246" y="14" width="96" height="28"/> - <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/> - <buttonCell key="cell" type="square" title="^IDS_CANCEL" bezelStyle="shadowlessSquare" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="127" customClass="ConstrainedWindowButtonCell"> - <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> - <font key="font" metaFont="system"/> - <string key="keyEquivalent" base64-UTF8="YES"> -DQ -</string> - </buttonCell> - <connections> - <action selector="cancel:" target="-2" id="133"/> - </connections> - </button> - <imageView id="130"> - <rect key="frame" x="380" y="129" width="64" height="64"/> - <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/> - <imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" id="131"/> - </imageView> - <box autoresizesSubviews="NO" verticalHuggingPriority="750" title="Box" boxType="separator" titlePosition="noTitle" id="152"> - <rect key="frame" x="22" y="110" width="428" height="5"/> - <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> - <color key="borderColor" white="0.0" alpha="0.41999999999999998" colorSpace="calibratedWhite"/> - <color key="fillColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/> - <font key="titleFont" metaFont="system"/> - </box> - <textField verticalHuggingPriority="750" id="153"> - <rect key="frame" x="18" y="148" width="357" height="14"/> - <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> - <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="123 users" id="154"> - <font key="font" metaFont="cellTitle"/> - <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/> - <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/> - </textFieldCell> - </textField> - <textField verticalHuggingPriority="750" id="169"> - <rect key="frame" x="79" y="164" width="295" height="14"/> - <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> - <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="(345)" id="170"> - <font key="font" metaFont="cellTitle"/> - <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/> - <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/> - </textFieldCell> - </textField> - <button id="155"> - <rect key="frame" x="19" y="127" width="351" height="17"/> - <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> - <buttonCell key="cell" type="square" title="^IDS_EXTENSION_PROMPT_STORE_LINK" bezelStyle="shadowlessSquare" alignment="left" controlSize="small" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="156" customClass="HyperlinkButtonCell"> - <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> - <font key="font" metaFont="cellTitle"/> - </buttonCell> - <connections> - <action selector="storeLinkClicked:" target="-2" id="157"/> - </connections> - </button> - <customView focusRingType="none" id="172"> - <rect key="frame" x="21" y="166" width="55" height="11"/> - <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> - </customView> - <scrollView focusRingType="none" borderType="none" autohidesScrollers="YES" horizontalLineScroll="19" horizontalPageScroll="10" verticalLineScroll="19" verticalPageScroll="10" hasHorizontalScroller="NO" hasVerticalScroller="NO" usesPredominantAxisScrolling="NO" id="182"> - <rect key="frame" x="1" y="57" width="445" height="45"/> - <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> - <clipView key="contentView" drawsBackground="NO" copiesOnScroll="NO" id="SpA-7M-MHM"> - <rect key="frame" x="0.0" y="0.0" width="445" height="45"/> - <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> - <subviews> - <outlineView focusRingType="none" verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="none" columnReordering="NO" columnResizing="NO" multipleSelection="NO" autosaveColumns="NO" typeSelect="NO" indentationPerLevel="16" outlineTableColumn="186" id="183"> - <rect key="frame" x="0.0" y="0.0" width="447" height="45"/> - <autoresizingMask key="autoresizingMask"/> - <size key="intercellSpacing" width="3" height="2"/> - <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/> - <color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/> - <tableColumns> - <tableColumn editable="NO" width="444" minWidth="16" maxWidth="1000" id="186"> - <tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left"> - <font key="font" metaFont="smallSystem"/> - <color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/> - <color key="backgroundColor" white="0.33333298560000002" alpha="1" colorSpace="calibratedWhite"/> - </tableHeaderCell> - <textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" alignment="left" title="Text Cell" id="187"> - <font key="font" metaFont="cellTitle"/> - <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/> - <color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/> - </textFieldCell> - </tableColumn> - </tableColumns> - <connections> - <outlet property="dataSource" destination="-2" id="189"/> - <outlet property="delegate" destination="-2" id="190"/> - </connections> - </outlineView> - </subviews> - <color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/> - </clipView> - <scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="184"> - <rect key="frame" x="-100" y="-100" width="283" height="15"/> - <autoresizingMask key="autoresizingMask"/> - </scroller> - <scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="NO" id="185"> - <rect key="frame" x="-100" y="-100" width="15" height="17"/> - <autoresizingMask key="autoresizingMask"/> - </scroller> - </scrollView> - </subviews> - </customView> - </objects> - <resources> - <image name="454BDBF6-F64D-4B84-9B01-98D6D896672C" width="1" height="1"> - <mutableData key="keyedArchiveRepresentation"> -YnBsaXN0MDDUAQIDBAUGPj9YJHZlcnNpb25YJG9iamVjdHNZJGFyY2hpdmVyVCR0b3ASAAGGoK4HCBMU -GR4fIyQsLzI4O1UkbnVsbNUJCgsMDQ4PEBESVk5TU2l6ZVYkY2xhc3NcTlNJbWFnZUZsYWdzVk5TUmVw -c1dOU0NvbG9ygAKADRIgwwAAgAOAC1Z7MSwgMX3SFQoWGFpOUy5vYmplY3RzoReABIAK0hUKGh2iGxyA -BYAGgAkQANIgCiEiXxAUTlNUSUZGUmVwcmVzZW50YXRpb26AB4AITxCsTU0AKgAAAAoAAAANAQAAAwAA -AAEAAQAAAQEAAwAAAAEAAQAAAQIAAwAAAAIACAAIAQMAAwAAAAEAAQAAAQYAAwAAAAEAAQAAAREABAAA -AAEAAAAIARIAAwAAAAEAAQAAARUAAwAAAAEAAgAAARYAAwAAAAEAAQAAARcABAAAAAEAAAACARwAAwAA -AAEAAQAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAANIlJicoWiRjbGFzc25hbWVYJGNsYXNzZXNf -EBBOU0JpdG1hcEltYWdlUmVwoykqK18QEE5TQml0bWFwSW1hZ2VSZXBaTlNJbWFnZVJlcFhOU09iamVj -dNIlJi0uV05TQXJyYXmiLSvSJSYwMV5OU011dGFibGVBcnJheaMwLSvTMzQKNTY3V05TV2hpdGVcTlND -b2xvclNwYWNlRDAgMAAQA4AM0iUmOTpXTlNDb2xvcqI5K9IlJjw9V05TSW1hZ2WiPCtfEA9OU0tleWVk -QXJjaGl2ZXLRQEFUcm9vdIABAAgAEQAaACMALQAyADcARgBMAFcAXgBlAHIAeQCBAIMAhQCKAIwAjgCV -AJoApQCnAKkAqwCwALMAtQC3ALkAuwDAANcA2QDbAYoBjwGaAaMBtgG6Ac0B2AHhAeYB7gHxAfYCBQIJ -AhACGAIlAioCLAIuAjMCOwI+AkMCSwJOAmACYwJoAAAAAAAAAgEAAAAAAAAAQgAAAAAAAAAAAAAAAAAA -Amo -</mutableData> - </image> - </resources> -</document>
diff --git a/chrome/app/nibs/ExtensionInstalledBubble.xib b/chrome/app/nibs/ExtensionInstalledBubble.xib deleted file mode 100644 index 969d892..0000000 --- a/chrome/app/nibs/ExtensionInstalledBubble.xib +++ /dev/null
@@ -1,125 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="5056" systemVersion="13F1077" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none"> - <dependencies> - <deployment version="1090" identifier="macosx"/> - <development version="5100" identifier="xcode"/> - <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="5056"/> - </dependencies> - <objects> - <customObject id="-2" userLabel="File's Owner" customClass="ExtensionInstalledBubbleController"> - <connections> - <outlet property="appShortcutLink_" destination="74" id="77"/> - <outlet property="bubble_" destination="44" id="48"/> - <outlet property="closeButton_" destination="15" id="30"/> - <outlet property="heading_" destination="33" id="70"/> - <outlet property="howToManage_" destination="37" id="71"/> - <outlet property="howToUse_" destination="35" id="72"/> - <outlet property="iconImage_" destination="18" id="20"/> - <outlet property="manageShortcutLink_" destination="49" id="51"/> - <outlet property="promoContainer_" destination="67" id="73"/> - <outlet property="window" destination="1" id="8"/> - </connections> - </customObject> - <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/> - <customObject id="-3" userLabel="Application"/> - <customObject id="3" customClass="ChromeUILocalizer"/> - <customObject id="4" customClass="GTMUILocalizerAndLayoutTweaker"> - <connections> - <outlet property="localizer_" destination="3" id="9"/> - <outlet property="uiObject_" destination="44" id="46"/> - </connections> - </customObject> - <window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" oneShot="NO" showsToolbarButton="NO" visibleAtLaunch="NO" animationBehavior="default" id="1" customClass="InfoBubbleWindow"> - <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/> - <windowPositionMask key="initialPositionMask" leftStrut="YES" bottomStrut="YES"/> - <rect key="contentRect" x="196" y="339" width="373" height="171"/> - <rect key="screenRect" x="0.0" y="0.0" width="2560" height="1578"/> - <view key="contentView" id="2"> - <rect key="frame" x="0.0" y="0.0" width="373" height="171"/> - <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> - <subviews> - <customView id="44" customClass="InfoBubbleView"> - <rect key="frame" x="0.0" y="0.0" width="373" height="171"/> - <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/> - <userGuides> - <userLayoutGuide location="8" affinity="maxY"/> - </userGuides> - <subviews> - <imageView id="18"> - <rect key="frame" x="15" y="110" width="43" height="43"/> - <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> - <imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" id="19"/> - </imageView> - <button focusRingType="none" id="15" customClass="HoverCloseButton"> - <rect key="frame" x="347" y="138" width="16" height="16"/> - <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/> - <buttonCell key="cell" type="square" bezelStyle="shadowlessSquare" imagePosition="overlaps" alignment="center" focusRingType="none" inset="2" id="16"> - <behavior key="behavior" lightByContents="YES"/> - <font key="font" metaFont="system"/> - </buttonCell> - <connections> - <action selector="closeWindow:" target="-2" id="43"/> - </connections> - </button> - <textField focusRingType="none" verticalHuggingPriority="750" id="33"> - <rect key="frame" x="71" y="134" width="275" height="17"/> - <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> - <textFieldCell key="cell" sendsActionOnEndEditing="YES" focusRingType="none" title="^IDS_EXTENSION_INSTALLED_HEADING" id="34"> - <font key="font" metaFont="system"/> - <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/> - <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/> - </textFieldCell> - </textField> - <textField hidden="YES" focusRingType="none" verticalHuggingPriority="750" id="35"> - <rect key="frame" x="71" y="67" width="285" height="17"/> - <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> - <textFieldCell key="cell" sendsActionOnEndEditing="YES" focusRingType="none" title="^IDS_EXTENSION_INSTALLED_PAGE_ACTION_INFO" id="36"> - <font key="font" metaFont="system"/> - <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/> - <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/> - </textFieldCell> - </textField> - <textField focusRingType="none" verticalHuggingPriority="750" id="37"> - <rect key="frame" x="71" y="33" width="285" height="17"/> - <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> - <textFieldCell key="cell" sendsActionOnEndEditing="YES" focusRingType="none" title="^IDS_EXTENSION_INSTALLED_MANAGE_INFO" id="38"> - <font key="font" metaFont="system"/> - <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/> - <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/> - </textFieldCell> - </textField> - <button hidden="YES" id="49"> - <rect key="frame" x="71" y="10" width="161" height="19"/> - <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> - <buttonCell key="cell" type="square" title="^IDS_EXTENSION_INSTALLED_MANAGE_SHORTCUTS" bezelStyle="shadowlessSquare" alignment="center" controlSize="small" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="50" customClass="HyperlinkButtonCell"> - <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> - <font key="font" metaFont="smallSystem"/> - </buttonCell> - <connections> - <action selector="onManageShortcutClicked:" target="-2" id="53"/> - </connections> - </button> - <button hidden="YES" id="74"> - <rect key="frame" x="192" y="50" width="161" height="19"/> - <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> - <buttonCell key="cell" type="square" title="^IDS_EXTENSION_INSTALLED_APP_INFO" bezelStyle="shadowlessSquare" alignment="right" controlSize="small" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="75" customClass="HyperlinkButtonCell"> - <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> - <font key="font" metaFont="smallSystem"/> - </buttonCell> - <connections> - <action selector="onAppShortcutClicked:" target="-2" id="78"/> - </connections> - </button> - <customView id="67" userLabel="Sync Promo Container"> - <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/> - </customView> - </subviews> - </customView> - </subviews> - </view> - <connections> - <outlet property="delegate" destination="-2" id="7"/> - </connections> - </window> - </objects> -</document>
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index 10fdfba..e380670 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -3382,7 +3382,7 @@ Add another </message> <message name="IDS_SETTINGS_PEOPLE_PASSWORD_PROMPT_ENTER_PASSWORD_LOCK" desc="Text above a password input field that tells the user they need to submit their password to configure these settings."> - To set up Smart Lock, enter your password + To set up screen lock, enter your password </message> <message name="IDS_SETTINGS_PEOPLE_PASSWORD_PROMPT_ENTER_PASSWORD_LOGIN_LOCK" desc="Text above a password input field that tells the user they need to submit their password to configure these settings."> To set up Smart Lock for sign-in, enter your password
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 75d6bb7..bc08939a 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -3403,11 +3403,6 @@ {"use-google-local-ntp", flag_descriptions::kUseGoogleLocalNtpName, flag_descriptions::kUseGoogleLocalNtpDescription, kOsDesktop, FEATURE_VALUE_TYPE(features::kUseGoogleLocalNtp)}, - - {"one-google-bar-on-local-ntp", - flag_descriptions::kOneGoogleBarOnLocalNtpName, - flag_descriptions::kOneGoogleBarOnLocalNtpDescription, kOsDesktop, - FEATURE_VALUE_TYPE(features::kOneGoogleBarOnLocalNtp)}, #endif // !defined(OS_ANDROID) #if defined(OS_MACOSX) @@ -3884,11 +3879,9 @@ FEATURE_VALUE_TYPE(features::kOobeRecommendAppsScreen)}, #endif // OS_CHROMEOS -#if defined(OS_ANDROID) {"enable-query-in-omnibox", flag_descriptions::kQueryInOmniboxName, - flag_descriptions::kQueryInOmniboxDescription, kOsAndroid, - FEATURE_VALUE_TYPE(chrome::android::kQueryInOmnibox)}, -#endif // OS_ANDROID + flag_descriptions::kQueryInOmniboxDescription, kOsAll, + FEATURE_VALUE_TYPE(omnibox::kQueryInOmnibox)}, {"enable-viz-hit-test-draw-quad", flag_descriptions::kVizHitTestDrawQuadName, @@ -4336,6 +4329,11 @@ kResamplingInputEventsFeatureVariations, "ResamplingScrollEvents")}, + {"enable-autoplay-unified-sound-settings", + flag_descriptions::kEnableAutoplayUnifiedSoundSettingsName, + flag_descriptions::kEnableAutoplayUnifiedSoundSettingsDescription, + kOsDesktop, FEATURE_VALUE_TYPE(media::kAutoplaySoundSettings)}, + // NOTE: Adding a new flag requires adding a corresponding entry to enum // "LoginCustomFlags" in tools/metrics/histograms/enums.xml. See "Flag // Histograms" in tools/metrics/histograms/README.md (run the
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc index f68c12a..fe21dcb1 100644 --- a/chrome/browser/android/chrome_feature_list.cc +++ b/chrome/browser/android/chrome_feature_list.cc
@@ -129,7 +129,6 @@ &kProgressBarThrottleFeature, &kPwaImprovedSplashScreen, &kPwaPersistentNotification, - &kQueryInOmnibox, &kReaderModeInCCT, &kSearchEnginePromoExistingDevice, &kSearchEnginePromoNewDevice, @@ -162,6 +161,7 @@ &offline_pages::kOfflinePagesSharingFeature, &offline_pages::kOfflinePagesLivePageSharingFeature, &offline_pages::kPrefetchingOfflinePagesFeature, + &omnibox::kQueryInOmnibox, &omnibox::kUIExperimentHideSteadyStateUrlSchemeAndSubdomains, &password_manager::features::kPasswordExport, &password_manager::features::kPasswordSearchMobile, @@ -375,9 +375,6 @@ const base::Feature kPwaPersistentNotification{ "PwaPersistentNotification", base::FEATURE_ENABLED_BY_DEFAULT}; -const base::Feature kQueryInOmnibox{"QueryInOmnibox", - base::FEATURE_DISABLED_BY_DEFAULT}; - const base::Feature kReaderModeInCCT{"ReaderModeInCCT", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/chrome/browser/android/chrome_feature_list.h b/chrome/browser/android/chrome_feature_list.h index 8e17326..4a9f2a7 100644 --- a/chrome/browser/android/chrome_feature_list.h +++ b/chrome/browser/android/chrome_feature_list.h
@@ -75,7 +75,6 @@ extern const base::Feature kProgressBarThrottleFeature; extern const base::Feature kPwaImprovedSplashScreen; extern const base::Feature kPwaPersistentNotification; -extern const base::Feature kQueryInOmnibox; extern const base::Feature kReaderModeInCCT; extern const base::Feature kSimplifiedNTP; extern const base::Feature kSoleIntegration;
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index 0ed7b5f..5516f94 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -83,6 +83,7 @@ "//chromeos/components/tether", "//chromeos/services/device_sync/public/cpp", "//chromeos/services/multidevice_setup/public/cpp", + "//chromeos/services/multidevice_setup/public/cpp:auth_token_validator", "//chromeos/services/multidevice_setup/public/cpp:prefs", "//chromeos/services/secure_channel/public/cpp/client", "//components/arc", @@ -189,6 +190,7 @@ # TODO: care about enable_basic_printing and enable_print_preview. "//components/sync", "//printing", + "//remoting/host/it2me:chrome_os_host", "//services/ui/public/cpp", "//services/ui/public/cpp/input_devices", "//skia", @@ -1287,6 +1289,10 @@ "mobile/mobile_activator.h", "mobile_config.cc", "mobile_config.h", + "multidevice_setup/auth_token_validator_factory.cc", + "multidevice_setup/auth_token_validator_factory.h", + "multidevice_setup/auth_token_validator_impl.cc", + "multidevice_setup/auth_token_validator_impl.h", "multidevice_setup/multidevice_setup_client_factory.cc", "multidevice_setup/multidevice_setup_client_factory.h", "net/cert_verify_proc_chromeos.cc",
diff --git a/chrome/browser/chromeos/DEPS b/chrome/browser/chromeos/DEPS index 8641d15..f59b114 100644 --- a/chrome/browser/chromeos/DEPS +++ b/chrome/browser/chromeos/DEPS
@@ -19,6 +19,7 @@ "+media/audio/sounds", # For system sounds "+media/base/media_switches.h", # For media command line switches. "+media/mojo/interfaces", # For platform verification mojom interface. + "+remoting/host/it2me", # For CRD host in remote command "+services/device/public", "+services/metrics/public", "+services/tracing/public",
diff --git a/chrome/browser/chromeos/accessibility/DEPS b/chrome/browser/chromeos/accessibility/DEPS index 1269720..b0f20e2 100644 --- a/chrome/browser/chromeos/accessibility/DEPS +++ b/chrome/browser/chromeos/accessibility/DEPS
@@ -12,6 +12,10 @@ "+ash/magnifier/magnification_controller.h", "+ash/shell.h", ], + "select_to_speak_event_handler\.cc": [ + # TODO(mash): Port the EventHandler to ash. http://crbug.com/874295 + "+ash/system/accessibility/select_to_speak_tray_utils.h", + ], "switch_access_event_handler\.cc": [ # TODO(mash): Fix. https://crbug.com/854025 "+ash/shell.h",
diff --git a/chrome/browser/chromeos/accessibility/chromevox_panel.cc b/chrome/browser/chromeos/accessibility/chromevox_panel.cc index 6bf946b..7fba88fb 100644 --- a/chrome/browser/chromeos/accessibility/chromevox_panel.cc +++ b/chrome/browser/chromeos/accessibility/chromevox_panel.cc
@@ -18,6 +18,16 @@ const char kFocusURLFragment[] = "focus"; const char kFullscreenURLFragment[] = "fullscreen"; const char kWidgetName[] = "ChromeVoxPanel"; +const int kPanelHeight = 35; + +ash::mojom::AccessibilityControllerPtr GetAccessibilityController() { + // Connect to the accessibility mojo interface in ash. + ash::mojom::AccessibilityControllerPtr accessibility_controller; + content::ServiceManagerConnection::GetForProcess() + ->GetConnector() + ->BindInterface(ash::mojom::kServiceName, &accessibility_controller); + return accessibility_controller; +} } // namespace @@ -54,6 +64,8 @@ : AccessibilityPanel(browser_context, GetUrlForContent(), kWidgetName) { web_contents_observer_.reset( new ChromeVoxPanelWebContentsObserver(GetWebContents(), this)); + + SetAccessibilityPanelFullscreen(false); } ChromeVoxPanel::~ChromeVoxPanel() {} @@ -76,12 +88,10 @@ } void ChromeVoxPanel::SetAccessibilityPanelFullscreen(bool fullscreen) { - // Connect to the accessibility mojo interface in ash. - ash::mojom::AccessibilityControllerPtr accessibility_controller; - content::ServiceManagerConnection::GetForProcess() - ->GetConnector() - ->BindInterface(ash::mojom::kServiceName, &accessibility_controller); - accessibility_controller->SetAccessibilityPanelFullscreen(fullscreen); + gfx::Rect bounds(0, 0, 0, kPanelHeight); + auto state = fullscreen ? ash::mojom::AccessibilityPanelState::FULLSCREEN + : ash::mojom::AccessibilityPanelState::FULL_WIDTH; + GetAccessibilityController()->SetAccessibilityPanelBounds(bounds, state); } std::string ChromeVoxPanel::GetUrlForContent() {
diff --git a/chrome/browser/chromeos/accessibility/select_to_speak_event_handler.cc b/chrome/browser/chromeos/accessibility/select_to_speak_event_handler.cc index dc1cddc..91777ec2 100644 --- a/chrome/browser/chromeos/accessibility/select_to_speak_event_handler.cc +++ b/chrome/browser/chromeos/accessibility/select_to_speak_event_handler.cc
@@ -8,6 +8,7 @@ #include <string> #include <utility> +#include "ash/system/accessibility/select_to_speak_tray_utils.h" #include "chrome/browser/chromeos/accessibility/accessibility_manager.h" #include "chrome/browser/chromeos/accessibility/event_handler_common.h" #include "chrome/common/extensions/extension_constants.h" @@ -166,8 +167,13 @@ return; DCHECK(event); - if (state_ == INACTIVE) + if (state_ == INACTIVE) { + if (event->type() == ui::ET_MOUSE_PRESSED) { + // Check if the mouse event occurred on the tray button. + CancelEventIfOverSelectToSpeakTray(event); + } return; + } if (event->type() == ui::ET_MOUSE_PRESSED) { if (state_ == SEARCH_DOWN || state_ == MOUSE_RELEASED) @@ -207,6 +213,12 @@ return; DCHECK(event); + + if (state_ == INACTIVE && event->type() == ui::ET_TOUCH_PRESSED) { + // Check if the touch event occurred on the tray button. + CancelEventIfOverSelectToSpeakTray(event); + } + // Only capture touch events if selection was requested or we are capturing // touch events already. if (state_ != SELECTION_REQUESTED && state_ != CAPTURING_TOUCH_ONLY) @@ -296,4 +308,16 @@ } } +// TODO(katie): Refactor this for mash, http://crbug.com/874295. +void SelectToSpeakEventHandler::CancelEventIfOverSelectToSpeakTray( + ui::LocatedEvent* event) { + if (ash::select_to_speak_tray_utils::SelectToSpeakTrayContainsPointInScreen( + event->root_location())) { + // Cancel the event so it does not cause any UI changes after a button tap. + CancelEvent(event); + // Enter the selecting mode as if we've clicked or tapped the button. + chromeos::AccessibilityManager::Get()->RequestSelectToSpeakStateChange(); + } +} + } // namespace chromeos
diff --git a/chrome/browser/chromeos/accessibility/select_to_speak_event_handler.h b/chrome/browser/chromeos/accessibility/select_to_speak_event_handler.h index 89922e4..0bac6d8 100644 --- a/chrome/browser/chromeos/accessibility/select_to_speak_event_handler.h +++ b/chrome/browser/chromeos/accessibility/select_to_speak_event_handler.h
@@ -52,6 +52,11 @@ // Forwards a mouse event to the Select-to-Speak extension. void ForwardMouseEventToExtension(ui::MouseEvent* event); + // For touch and mouse events events, the Select-to-Speak tray needs to + // cancel all further event propagation so that dialogs and menus do not + // close and therefore can be read by the user. + void CancelEventIfOverSelectToSpeakTray(ui::LocatedEvent* event); + enum State { // The search key is not down, no selection has been requested. // No other keys or mouse events are captured.
diff --git a/chrome/browser/chromeos/dbus/finch_features_service_provider_delegate.cc b/chrome/browser/chromeos/dbus/finch_features_service_provider_delegate.cc index fba84cfa..0e2a9af9 100644 --- a/chrome/browser/chromeos/dbus/finch_features_service_provider_delegate.cc +++ b/chrome/browser/chromeos/dbus/finch_features_service_provider_delegate.cc
@@ -34,4 +34,8 @@ return base::FeatureList::IsEnabled(features::kUsbguard); } +bool FinchFeaturesServiceProviderDelegate::IsShillSandboxingEnabled() { + return base::FeatureList::IsEnabled(features::kShillSandboxing); +} + } // namespace chromeos
diff --git a/chrome/browser/chromeos/dbus/finch_features_service_provider_delegate.h b/chrome/browser/chromeos/dbus/finch_features_service_provider_delegate.h index eb1e241..99315ae29 100644 --- a/chrome/browser/chromeos/dbus/finch_features_service_provider_delegate.h +++ b/chrome/browser/chromeos/dbus/finch_features_service_provider_delegate.h
@@ -20,6 +20,7 @@ // ChromeServiceProvider::Delegate: bool IsCrostiniEnabled(const std::string& user_id_hash) override; bool IsUsbguardEnabled() override; + bool IsShillSandboxingEnabled() override; private: DISALLOW_COPY_AND_ASSIGN(FinchFeaturesServiceProviderDelegate);
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc index 300dcbb..5866c27 100644 --- a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc +++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
@@ -264,7 +264,8 @@ TestCase("renameFileDownloads"), TestCase("renameFileDrive"), TestCase("renameFileDrive").EnableDriveFs(), - TestCase("renameNewFolderDownloads").InGuestMode(), + // https://crbug.com/874954, failed on MSan bots. + // TestCase("renameNewFolderDownloads").InGuestMode(), TestCase("renameNewFolderDownloads"), TestCase("renameNewFolderDrive"), TestCase("renameNewFolderDrive").EnableDriveFs()));
diff --git a/chrome/browser/chromeos/login/signin/token_handle_fetcher.cc b/chrome/browser/chromeos/login/signin/token_handle_fetcher.cc index 773abd431..c824f8c3 100644 --- a/chrome/browser/chromeos/login/signin/token_handle_fetcher.cc +++ b/chrome/browser/chromeos/login/signin/token_handle_fetcher.cc
@@ -15,6 +15,7 @@ #include "components/signin/core/browser/profile_oauth2_token_service.h" #include "components/signin/core/browser/signin_manager.h" #include "google_apis/gaia/gaia_constants.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" namespace { const int kMaxRetries = 3; @@ -120,7 +121,7 @@ void TokenHandleFetcher::FillForAccessToken(const std::string& access_token) { if (!gaia_client_.get()) gaia_client_.reset( - new gaia::GaiaOAuthClient(profile_->GetRequestContext())); + new gaia::GaiaOAuthClient(profile_->GetURLLoaderFactory())); tokeninfo_response_start_time_ = base::TimeTicks::Now(); gaia_client_->GetTokenInfo(access_token, kMaxRetries, this); }
diff --git a/chrome/browser/chromeos/login/signin/token_handle_util.cc b/chrome/browser/chromeos/login/signin/token_handle_util.cc index 7892d6b..9c2fdae 100644 --- a/chrome/browser/chromeos/login/signin/token_handle_util.cc +++ b/chrome/browser/chromeos/login/signin/token_handle_util.cc
@@ -11,6 +11,7 @@ #include "chrome/browser/profiles/profile.h" #include "components/user_manager/known_user.h" #include "google_apis/gaia/gaia_oauth_client.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" namespace { @@ -86,9 +87,11 @@ } if (!gaia_client_.get()) { - auto* request_context = - chromeos::ProfileHelper::Get()->GetSigninProfile()->GetRequestContext(); - gaia_client_.reset(new gaia::GaiaOAuthClient(request_context)); + auto url_loader_factory = chromeos::ProfileHelper::Get() + ->GetSigninProfile() + ->GetURLLoaderFactory(); + gaia_client_.reset( + new gaia::GaiaOAuthClient(std::move(url_loader_factory))); } validation_delegates_[token] =
diff --git a/chrome/browser/chromeos/login/ui/oobe_ui_dialog_delegate.cc b/chrome/browser/chromeos/login/ui/oobe_ui_dialog_delegate.cc index 1fd2223..9d23d6f 100644 --- a/chrome/browser/chromeos/login/ui/oobe_ui_dialog_delegate.cc +++ b/chrome/browser/chromeos/login/ui/oobe_ui_dialog_delegate.cc
@@ -9,6 +9,7 @@ #include "chrome/browser/chromeos/login/ui/login_display_host_mojo.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/extensions/chrome_extension_web_contents_observer.h" +#include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h" #include "chrome/browser/ui/ash/ash_util.h" #include "chrome/browser/ui/ash/login_screen_client.h" #include "chrome/browser/ui/ash/tablet_mode_client.h" @@ -36,6 +37,31 @@ } // namespace +class OobeWebDialogView : public views::WebDialogView { + public: + OobeWebDialogView(content::BrowserContext* context, + ui::WebDialogDelegate* delegate, + WebContentsHandler* handler) + : views::WebDialogView(context, delegate, handler) {} + + // views::WebDialogView: + void RequestMediaAccessPermission( + content::WebContents* web_contents, + const content::MediaStreamRequest& request, + content::MediaResponseCallback callback) override { + // This is required for accessing the camera for SAML logins. + MediaCaptureDevicesDispatcher::GetInstance()->ProcessMediaAccessRequest( + web_contents, request, std::move(callback), nullptr /* extension */); + } + + bool CheckMediaAccessPermission(content::RenderFrameHost* render_frame_host, + const GURL& security_origin, + content::MediaStreamType type) override { + return MediaCaptureDevicesDispatcher::GetInstance() + ->CheckMediaAccessPermission(render_frame_host, security_origin, type); + } +}; + OobeUIDialogDelegate::OobeUIDialogDelegate( base::WeakPtr<LoginDisplayHostMojo> controller) : controller_(controller), @@ -62,8 +88,8 @@ // Widget owns a root view which has |dialog_view_| as its child view. // Before the widget is destroyed, it will clean up the view hierarchy // starting from root view. - dialog_view_ = new views::WebDialogView(ProfileHelper::GetSigninProfile(), - this, new ChromeWebContentsHandler); + dialog_view_ = new OobeWebDialogView(ProfileHelper::GetSigninProfile(), this, + new ChromeWebContentsHandler); views::Widget::InitParams params( views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); params.delegate = dialog_view_;
diff --git a/chrome/browser/chromeos/multidevice_setup/auth_token_validator_factory.cc b/chrome/browser/chromeos/multidevice_setup/auth_token_validator_factory.cc new file mode 100644 index 0000000..b00cda5 --- /dev/null +++ b/chrome/browser/chromeos/multidevice_setup/auth_token_validator_factory.cc
@@ -0,0 +1,46 @@ +// 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. + +#include "chrome/browser/chromeos/multidevice_setup/auth_token_validator_factory.h" + +#include "base/macros.h" +#include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_factory.h" +#include "chrome/browser/chromeos/multidevice_setup/auth_token_validator_impl.h" +#include "chrome/browser/profiles/profile.h" +#include "components/keyed_service/content/browser_context_dependency_manager.h" +#include "components/keyed_service/core/keyed_service.h" +#include "content/public/browser/browser_context.h" + +namespace chromeos { + +namespace multidevice_setup { + +// static +AuthTokenValidator* AuthTokenValidatorFactory::GetForProfile(Profile* profile) { + return static_cast<AuthTokenValidatorImpl*>( + GetInstance()->GetServiceForBrowserContext(profile, true)); +} + +// static +AuthTokenValidatorFactory* AuthTokenValidatorFactory::GetInstance() { + return base::Singleton<AuthTokenValidatorFactory>::get(); +} + +AuthTokenValidatorFactory::AuthTokenValidatorFactory() + : BrowserContextKeyedServiceFactory( + "AuthTokenValidatorFactory", + BrowserContextDependencyManager::GetInstance()) {} + +AuthTokenValidatorFactory::~AuthTokenValidatorFactory() {} + +KeyedService* AuthTokenValidatorFactory::BuildServiceInstanceFor( + content::BrowserContext* context) const { + return new AuthTokenValidatorImpl( + chromeos::quick_unlock::QuickUnlockFactory::GetForProfile( + Profile::FromBrowserContext(context))); +} + +} // namespace multidevice_setup + +} // namespace chromeos
diff --git a/chrome/browser/chromeos/multidevice_setup/auth_token_validator_factory.h b/chrome/browser/chromeos/multidevice_setup/auth_token_validator_factory.h new file mode 100644 index 0000000..66e1e8e --- /dev/null +++ b/chrome/browser/chromeos/multidevice_setup/auth_token_validator_factory.h
@@ -0,0 +1,44 @@ +// 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_MULTIDEVICE_SETUP_AUTH_TOKEN_VALIDATOR_FACTORY_H_ +#define CHROME_BROWSER_CHROMEOS_MULTIDEVICE_SETUP_AUTH_TOKEN_VALIDATOR_FACTORY_H_ + +#include "base/memory/singleton.h" +#include "components/keyed_service/content/browser_context_keyed_service_factory.h" + +class KeyedService; +class Profile; + +namespace chromeos { + +namespace multidevice_setup { + +class AuthTokenValidator; + +// Owns AuthTokenValidator instances and associates them with Profiles. +class AuthTokenValidatorFactory : public BrowserContextKeyedServiceFactory { + public: + static AuthTokenValidator* GetForProfile(Profile* profile); + + static AuthTokenValidatorFactory* GetInstance(); + + private: + friend struct base::DefaultSingletonTraits<AuthTokenValidatorFactory>; + + AuthTokenValidatorFactory(); + ~AuthTokenValidatorFactory() override; + + // BrowserContextKeyedServiceFactory: + KeyedService* BuildServiceInstanceFor( + content::BrowserContext* context) const override; + + DISALLOW_COPY_AND_ASSIGN(AuthTokenValidatorFactory); +}; + +} // namespace multidevice_setup + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_MULTIDEVICE_SETUP_AUTH_TOKEN_VALIDATOR_FACTORY_H_
diff --git a/chrome/browser/chromeos/multidevice_setup/auth_token_validator_impl.cc b/chrome/browser/chromeos/multidevice_setup/auth_token_validator_impl.cc new file mode 100644 index 0000000..ecaf8422 --- /dev/null +++ b/chrome/browser/chromeos/multidevice_setup/auth_token_validator_impl.cc
@@ -0,0 +1,32 @@ +// 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. + +#include "chrome/browser/chromeos/multidevice_setup/auth_token_validator_impl.h" + +#include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_factory.h" +#include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_storage.h" + +namespace chromeos { + +namespace multidevice_setup { + +AuthTokenValidatorImpl::AuthTokenValidatorImpl( + quick_unlock::QuickUnlockStorage* quick_unlock_storage) + : quick_unlock_storage_(quick_unlock_storage) {} + +AuthTokenValidatorImpl::~AuthTokenValidatorImpl() = default; + +bool AuthTokenValidatorImpl::IsAuthTokenValid(const std::string& auth_token) { + return quick_unlock_storage_ && + !quick_unlock_storage_->GetAuthTokenExpired() && + auth_token == quick_unlock_storage_->GetAuthToken(); +} + +void AuthTokenValidatorImpl::Shutdown() { + quick_unlock_storage_ = nullptr; +} + +} // namespace multidevice_setup + +} // namespace chromeos
diff --git a/chrome/browser/chromeos/multidevice_setup/auth_token_validator_impl.h b/chrome/browser/chromeos/multidevice_setup/auth_token_validator_impl.h new file mode 100644 index 0000000..f3777d8 --- /dev/null +++ b/chrome/browser/chromeos/multidevice_setup/auth_token_validator_impl.h
@@ -0,0 +1,45 @@ +// 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_MULTIDEVICE_SETUP_AUTH_TOKEN_VALIDATOR_IMPL_H_ +#define CHROME_BROWSER_CHROMEOS_MULTIDEVICE_SETUP_AUTH_TOKEN_VALIDATOR_IMPL_H_ + +#include "chromeos/services/multidevice_setup/public/cpp/auth_token_validator.h" +#include "components/keyed_service/core/keyed_service.h" + +namespace chromeos { + +namespace quick_unlock { +class QuickUnlockStorage; +} // namespace quick_unlock + +namespace multidevice_setup { + +// Concrete AuthTokenValidator implementation. +// +// The functionality of this class is very simple, to the point that it does not +// merit a test. If this class becomes any more complex, simple unit tests +// should be added. +class AuthTokenValidatorImpl : public AuthTokenValidator, public KeyedService { + public: + AuthTokenValidatorImpl( + quick_unlock::QuickUnlockStorage* quick_unlock_storage); + ~AuthTokenValidatorImpl() override; + + bool IsAuthTokenValid(const std::string& auth_token) override; + + private: + // KeyedService: + void Shutdown() override; + + quick_unlock::QuickUnlockStorage* quick_unlock_storage_; + + DISALLOW_COPY_AND_ASSIGN(AuthTokenValidatorImpl); +}; + +} // namespace multidevice_setup + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_MULTIDEVICE_SETUP_AUTH_TOKEN_VALIDATOR_IMPL_H_
diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos_unittest.cc b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos_unittest.cc index 1c07ebe..9a2bdf3 100644 --- a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos_unittest.cc +++ b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos_unittest.cc
@@ -58,10 +58,11 @@ #include "components/prefs/pref_registry_simple.h" #include "components/prefs/testing_pref_service.h" #include "google_apis/gaia/gaia_oauth_client.h" -#include "net/url_request/test_url_fetcher_factory.h" +#include "google_apis/gaia/gaia_urls.h" #include "net/url_request/url_request_test_util.h" #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" #include "services/network/test/test_url_loader_factory.h" +#include "services/network/test/test_utils.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -161,20 +162,18 @@ RegisterLocalState(local_state_.registry()); manager_->Init(&schema_registry_); - // DeviceOAuth2TokenService uses the system request context to fetch + // DeviceOAuth2TokenService uses the system url loader factory fetch // OAuth tokens, then writes the token to local state, encrypting it // first with methods in CryptohomeTokenEncryptor. - request_context_getter_ = new net::TestURLRequestContextGetter( - base::ThreadTaskRunnerHandle::Get()); - TestingBrowserProcess::GetGlobal()->SetSystemRequestContext( - request_context_getter_.get()); + TestingBrowserProcess::GetGlobal()->SetSharedURLLoaderFactory( + test_shared_loader_factory_); TestingBrowserProcess::GetGlobal()->SetLocalState(&local_state_); // SystemSaltGetter is used in DeviceOAuth2TokenService. chromeos::SystemSaltGetter::Initialize(); chromeos::DeviceOAuth2TokenServiceFactory::Initialize( test_shared_loader_factory_); - url_fetcher_response_code_ = 200; + url_fetcher_response_code_ = net::HTTP_OK; url_fetcher_response_string_ = "{\"access_token\":\"accessToken4Test\"," "\"expires_in\":1234," "\"refresh_token\":\"refreshToken4Test\"}"; @@ -266,9 +265,7 @@ std::unique_ptr<chromeos::InstallAttributes> install_attributes_; - scoped_refptr<net::URLRequestContextGetter> request_context_getter_; - net::TestURLFetcherFactory url_fetcher_factory_; - int url_fetcher_response_code_; + net::HttpStatusCode url_fetcher_response_code_; std::string url_fetcher_response_string_; TestingPrefServiceSimple local_state_; MockDeviceManagementService device_management_service_; @@ -282,9 +279,9 @@ SchemaRegistry schema_registry_; std::unique_ptr<TestingDeviceCloudPolicyManagerChromeOS> manager_; std::unique_ptr<DeviceCloudPolicyInitializer> initializer_; + network::TestURLLoaderFactory test_url_loader_factory_; private: - network::TestURLLoaderFactory test_url_loader_factory_; scoped_refptr<network::WeakWrapperSharedURLLoaderFactory> test_shared_loader_factory_; @@ -586,17 +583,14 @@ // Process robot refresh token fetch if the auth code fetch succeeded. // DeviceCloudPolicyInitializer holds an EnrollmentHandlerChromeOS which // holds a GaiaOAuthClient that fetches the refresh token during enrollment. - // We return a successful OAuth response via a TestURLFetcher to trigger the - // happy path for these classes so that enrollment can continue. + // We return a successful OAuth response via a TestURLLoaderFactory to + // trigger the happy path for these classes so that enrollment can continue. if (robot_auth_fetch_status_ == DM_STATUS_SUCCESS) { - net::TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID( - gaia::GaiaOAuthClient::kUrlFetcherId); - ASSERT_TRUE(url_fetcher); - url_fetcher->SetMaxRetriesOn5xx(0); - url_fetcher->set_status(net::URLRequestStatus()); - url_fetcher->set_response_code(url_fetcher_response_code_); - url_fetcher->SetResponseString(url_fetcher_response_string_); - url_fetcher->delegate()->OnURLFetchComplete(url_fetcher); + test_url_loader_factory_.SimulateResponseForPendingRequest( + GaiaUrls::GetInstance()->oauth2_token_url(), + network::URLLoaderCompletionStatus(net::OK), + network::CreateResourceResponseHead(url_fetcher_response_code_), + url_fetcher_response_string_); } // Process robot refresh token store and policy store. @@ -714,10 +708,10 @@ TEST_P(DeviceCloudPolicyManagerChromeOSEnrollmentTest, RobotRefreshTokenFetchResponseCodeFailed) { - url_fetcher_response_code_ = 400; + url_fetcher_response_code_ = net::HTTP_BAD_REQUEST; RunTest(); ExpectFailedEnrollment(EnrollmentStatus::ROBOT_REFRESH_FETCH_FAILED); - EXPECT_EQ(400, status_.http_status()); + EXPECT_EQ(net::HTTP_BAD_REQUEST, status_.http_status()); } TEST_P(DeviceCloudPolicyManagerChromeOSEnrollmentTest,
diff --git a/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc b/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc index de36090..d8a12fd4 100644 --- a/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc +++ b/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc
@@ -38,6 +38,7 @@ #include "google_apis/gaia/gaia_auth_util.h" #include "google_apis/gaia/gaia_urls.h" #include "net/http/http_status_code.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" namespace em = enterprise_management; @@ -566,8 +567,8 @@ client_info.redirect_uri = "oob"; // Use the system request context to avoid sending user cookies. - gaia_oauth_client_.reset( - new gaia::GaiaOAuthClient(g_browser_process->system_request_context())); + gaia_oauth_client_.reset(new gaia::GaiaOAuthClient( + g_browser_process->shared_url_loader_factory())); gaia_oauth_client_->GetTokensFromAuthCode( client_info, client->robot_api_auth_code(), 0 /* max_retries */, this); }
diff --git a/chrome/browser/chromeos/policy/remote_commands/crd_host_delegate.cc b/chrome/browser/chromeos/policy/remote_commands/crd_host_delegate.cc index 790e2201..4573b86 100644 --- a/chrome/browser/chromeos/policy/remote_commands/crd_host_delegate.cc +++ b/chrome/browser/chromeos/policy/remote_commands/crd_host_delegate.cc
@@ -5,15 +5,21 @@ #include "chrome/browser/chromeos/policy/remote_commands/crd_host_delegate.h" #include "base/json/json_reader.h" +#include "base/json/json_writer.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/chromeos/settings/device_oauth2_token_service.h" #include "chrome/browser/chromeos/settings/device_oauth2_token_service_factory.h" #include "components/user_manager/user_manager.h" +#include "content/public/browser/browser_thread.h" #include "content/public/browser/storage_partition.h" +#include "extensions/browser/api/messaging/native_message_host.h" #include "google_apis/gaia/gaia_constants.h" #include "google_apis/gaia/oauth2_token_service.h" #include "net/base/load_flags.h" #include "net/http/http_request_headers.h" +#include "remoting/host/it2me/it2me_native_messaging_host_chromeos.h" #include "services/network/public/cpp/simple_url_loader.h" #include "ui/base/user_activity/user_activity_detector.h" @@ -21,7 +27,52 @@ namespace { -const char kICEConfigURL[] = +// TODO(https://crbug.com/864455): move these constants to some place +// that they can be reused by both this code and It2MeNativeMessagingHost. + +// Communication with CRD Host, messages sent to host: +constexpr char kCRDMessageTypeKey[] = "type"; + +constexpr char kCRDMessageHello[] = "hello"; +constexpr char kCRDMessageConnect[] = "connect"; +constexpr char kCRDMessageDisconnect[] = "disconnect"; + +// Communication with CRD Host, messages received from host: +constexpr char kCRDResponseHello[] = "helloResponse"; +constexpr char kCRDResponseConnect[] = "connectResponse"; +constexpr char kCRDStateChanged[] = "hostStateChanged"; +constexpr char kCRDResponseDisconnect[] = "disconnectResponse"; + +// Connect message parameters: +constexpr char kCRDConnectUserName[] = "userName"; +constexpr char kCRDConnectAuth[] = "authServiceWithToken"; +constexpr char kCRDConnectXMPPServer[] = "xmppServerAddress"; +constexpr char kCRDConnectXMPPTLS[] = "xmppServerUseTls"; +constexpr char kCRDConnectDirectoryBot[] = "directoryBotJid"; +constexpr char kCRDConnectICEConfig[] = "iceConfig"; +constexpr char kCRDConnectNoDialogs[] = "noDialogs"; + +// Connect message parameter values: +constexpr char kCRDConnectXMPPServerValue[] = "talk.google.com:443"; +constexpr char kCRDConnectDirectoryBotValue[] = "remoting@bot.talk.google.com"; + +// CRD host states we care about: +constexpr char kCRDStateKey[] = "state"; +constexpr char kCRDStateError[] = "ERROR"; +constexpr char kCRDStateStarting[] = "STARTING"; +constexpr char kCRDStateAccessCodeRequested[] = "REQUESTED_ACCESS_CODE"; +constexpr char kCRDStateDomainError[] = "INVALID_DOMAIN_ERROR"; +constexpr char kCRDStateAccessCode[] = "RECEIVED_ACCESS_CODE"; +constexpr char kCRDStateRemoteDisconnected[] = "DISCONNECTED"; +constexpr char kCRDStateRemoteConnected[] = "CONNECTED"; + +constexpr char kCRDErrorCodeKey[] = "error_code"; +constexpr char kCRDAccessCodeKey[] = "accessCode"; +constexpr char kCRDAccessCodeLifetimeKey[] = "accessCodeLifetime"; + +constexpr char kCRDConnectClientKey[] = "client"; + +constexpr char kICEConfigURL[] = "https://www.googleapis.com/chromoting/v1/@me/iceconfig"; // OAuth2 Token scopes @@ -76,14 +127,14 @@ : OAuth2TokenService::Consumer("crd_host_delegate"), weak_factory_(this) {} CRDHostDelegate::~CRDHostDelegate() { - // TODO(antrim): shutdown host somewhat correctly. } bool CRDHostDelegate::HasActiveSession() const { - return false; + return host_ != nullptr; } void CRDHostDelegate::TerminateSession(base::OnceClosure callback) { + DoShutdownHost(); std::move(callback).Run(); } @@ -97,8 +148,16 @@ bool CRDHostDelegate::IsRunningKiosk() const { auto* user_manager = user_manager::UserManager::Get(); // TODO(antrim): find out if Arc Kiosk is also eligible. - // TODO(antrim): find out if only auto-started Kiosks are elidgible. - return user_manager->IsLoggedInAsKioskApp() && GetKioskProfile() != nullptr; + if (!user_manager->IsLoggedInAsKioskApp()) + return false; + if (!GetKioskProfile()) + return false; + chromeos::KioskAppManager* manager = chromeos::KioskAppManager::Get(); + if (manager->GetAutoLaunchApp().empty()) + return false; + chromeos::KioskAppManager::App app; + CHECK(manager->GetApp(manager->GetAutoLaunchApp(), &app)); + return app.was_auto_launched_with_zero_delay; } base::TimeDelta CRDHostDelegate::GetIdlenessPeriod() const { @@ -188,24 +247,255 @@ "Could not parse config"); return; } - error_callback_.Reset(); - std::move(ice_success_callback_).Run(std::move(*value)); - } else { - ice_success_callback_.Reset(); - std::move(error_callback_) - .Run(DeviceCommandStartCRDSessionJob::FAILURE_NO_ICE_CONFIG, - std::string()); + auto* config = value->FindKeyOfType("data", base::Value::Type::DICTIONARY); + if (config) { + error_callback_.Reset(); + std::move(ice_success_callback_).Run(std::move(*config)); + return; + } } + + ice_success_callback_.Reset(); + std::move(error_callback_) + .Run(DeviceCommandStartCRDSessionJob::FAILURE_NO_ICE_CONFIG, + std::string()); } void CRDHostDelegate::StartCRDHostAndGetCode( - const std::string& directory_bot_jid, const std::string& oauth_token, base::Value ice_config, - DeviceCommandStartCRDSessionJob::AuthCodeCallback success_callback, + DeviceCommandStartCRDSessionJob::AccessCodeCallback success_callback, DeviceCommandStartCRDSessionJob::ErrorCallback error_callback) { - // TODO(antrim): actual implementation - std::move(success_callback).Run(std::string("TODO: Auth Code")); + DCHECK(!host_); + DCHECK(!code_success_callback_); + DCHECK(!error_callback_); + + // Store all parameters for future connect call. + base::Value connect_params(base::Value::Type::DICTIONARY); + std::string username = + chromeos::DeviceOAuth2TokenServiceFactory::Get()->GetRobotAccountId(); + + connect_params.SetKey(kCRDConnectUserName, base::Value(username)); + connect_params.SetKey(kCRDConnectAuth, base::Value("oauth2:" + oauth_token)); + connect_params.SetKey(kCRDConnectXMPPServer, + base::Value(kCRDConnectXMPPServerValue)); + connect_params.SetKey(kCRDConnectXMPPTLS, base::Value(true)); + connect_params.SetKey(kCRDConnectDirectoryBot, + base::Value(kCRDConnectDirectoryBotValue)); + connect_params.SetKey(kCRDConnectICEConfig, std::move(ice_config)); + connect_params.SetKey(kCRDConnectNoDialogs, base::Value(true)); + connect_params_ = std::move(connect_params); + + remote_connected_ = false; + command_awaiting_crd_access_code_ = true; + + code_success_callback_ = std::move(success_callback); + error_callback_ = std::move(error_callback); + + // TODO(antrim): set up watchdog timer (reasonable cutoff). + host_ = remoting::CreateIt2MeNativeMessagingHostForChromeOS( + g_browser_process->system_request_context(), + content::BrowserThread::GetTaskRunnerForThread( + content::BrowserThread::IO), + content::BrowserThread::GetTaskRunnerForThread( + content::BrowserThread::UI), + g_browser_process->policy_service()); + host_->Start(this); + + base::Value params(base::Value::Type::DICTIONARY); + SendMessageToHost(kCRDMessageHello, params); +} + +void CRDHostDelegate::PostMessageFromNativeHost(const std::string& message) { + std::unique_ptr<base::Value> message_value = base::JSONReader::Read(message); + if (!message_value->is_dict()) { + OnProtocolBroken("Message is not a dictionary"); + return; + } + + auto* type_value = message_value->FindKeyOfType(kCRDMessageTypeKey, + base::Value::Type::STRING); + if (!type_value) { + OnProtocolBroken("Message without type"); + return; + } + std::string type = type_value->GetString(); + + if (type == kCRDResponseHello) { + OnHelloResponse(); + return; + } else if (type == kCRDResponseConnect) { + // Ok, just ignore. + return; + } else if (type == kCRDResponseDisconnect) { + OnDisconnectResponse(); + return; + } else if (type == kCRDStateChanged) { + // Handle CRD host state changes + auto* state_value = + message_value->FindKeyOfType(kCRDStateKey, base::Value::Type::STRING); + if (!state_value) { + OnProtocolBroken("No state in message"); + return; + } + std::string state = state_value->GetString(); + + if (state == kCRDStateAccessCode) { + OnStateReceivedAccessCode(*message_value); + } else if (state == kCRDStateRemoteConnected) { + OnStateRemoteConnected(*message_value); + } else if (state == kCRDStateRemoteDisconnected) { + OnStateRemoteDisconnected(); + } else if (state == kCRDStateError || state == kCRDStateDomainError) { + OnStateError(state, *message_value); + } else if (state == kCRDStateStarting || + state == kCRDStateAccessCodeRequested) { + // Just ignore these states. + } else { + LOG(WARNING) << "Unhandled state :" << type; + } + return; + } + LOG(WARNING) << "Unknown message type :" << type; +} + +void CRDHostDelegate::OnHelloResponse() { + // Host is initialized, start connection. + SendMessageToHost(kCRDMessageConnect, connect_params_); +} + +void CRDHostDelegate::OnDisconnectResponse() { + // Should happen only when remoting session finished and we + // have requested host to shut down, or when we have got second auth code + // without receiving connection. + DCHECK(!command_awaiting_crd_access_code_); + DCHECK(!remote_connected_); + ShutdownHost(); +} + +void CRDHostDelegate::OnStateError(std::string error_state, + base::Value& message) { + std::string error_message; + if (error_state == kCRDStateDomainError) { + error_message = "CRD Error : Invalid domain"; + } else { + auto* error_code_value = + message.FindKeyOfType(kCRDErrorCodeKey, base::Value::Type::STRING); + if (error_code_value) + error_message = error_code_value->GetString(); + else + error_message = "Unknown CRD Error"; + } + // Notify callback if command is still running. + if (command_awaiting_crd_access_code_) { + command_awaiting_crd_access_code_ = false; + std::move(error_callback_) + .Run(DeviceCommandStartCRDSessionJob::FAILURE_CRD_HOST_ERROR, + "CRD Error state " + error_state); + code_success_callback_.Reset(); + } + // Shut down host, if any + ShutdownHost(); +} + +void CRDHostDelegate::OnStateRemoteConnected(base::Value& message) { + remote_connected_ = true; + // TODO(antrim): set up watchdog timer (session duration). + auto* client_value = + message.FindKeyOfType(kCRDConnectClientKey, base::Value::Type::STRING); + if (client_value) { + VLOG(1) << "Remote connection by " << client_value->GetString(); + } +} + +void CRDHostDelegate::OnStateRemoteDisconnected() { + // There could be a connection attempt that was not successful, we will + // receive "disconnected" message without actually receiving "connected". + if (!remote_connected_) + return; + remote_connected_ = false; + // Remote has disconnected, time to send "disconnect" that would result + // in shutting down the host. + base::Value params(base::Value::Type::DICTIONARY); + SendMessageToHost(kCRDMessageDisconnect, params); +} + +void CRDHostDelegate::OnStateReceivedAccessCode(base::Value& message) { + if (!command_awaiting_crd_access_code_) { + if (!remote_connected_) { + // We have already sent the access code back to the server which initiated + // this CRD session through a remote command, and we can not send a new + // access code. Assuming that the old access code is no longer valid, we + // can only terminate the current CRD session. + base::Value params(base::Value::Type::DICTIONARY); + SendMessageToHost(kCRDMessageDisconnect, params); + } + return; + } + + auto* code_value = + message.FindKeyOfType(kCRDAccessCodeKey, base::Value::Type::STRING); + auto* code_lifetime_value = message.FindKeyOfType(kCRDAccessCodeLifetimeKey, + base::Value::Type::INTEGER); + if (!code_value || !code_lifetime_value) { + OnProtocolBroken("Can not obtain access code"); + return; + } + // TODO(antrim): set up watchdog timer (access code lifetime). + command_awaiting_crd_access_code_ = false; + std::move(code_success_callback_).Run(std::string(code_value->GetString())); + error_callback_.Reset(); +} + +void CRDHostDelegate::CloseChannel(const std::string& error_message) { + LOG(ERROR) << "CRD Host closed channel" << error_message; + command_awaiting_crd_access_code_ = false; + + if (error_callback_) { + std::move(error_callback_) + .Run(DeviceCommandStartCRDSessionJob::FAILURE_CRD_HOST_ERROR, + error_message); + } + code_success_callback_.Reset(); + ShutdownHost(); +} + +void CRDHostDelegate::SendMessageToHost(const std::string& type, + base::Value& params) { + std::string message_json; + params.SetKey(kCRDMessageTypeKey, base::Value(type)); + base::JSONWriter::Write(params, &message_json); + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(&CRDHostDelegate::DoSendMessage, + weak_factory_.GetWeakPtr(), message_json)); +} + +void CRDHostDelegate::DoSendMessage(const std::string& json) { + if (!host_) + return; + host_->OnMessage(json); +} + +void CRDHostDelegate::OnProtocolBroken(const std::string& message) { + LOG(ERROR) << "Error communicating with CRD Host : " << message; + command_awaiting_crd_access_code_ = false; + + std::move(error_callback_) + .Run(DeviceCommandStartCRDSessionJob::FAILURE_CRD_HOST_ERROR, message); + code_success_callback_.Reset(); + ShutdownHost(); +} + +void CRDHostDelegate::ShutdownHost() { + if (!host_) + return; + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(&CRDHostDelegate::DoShutdownHost, + weak_factory_.GetWeakPtr())); +} + +void CRDHostDelegate::DoShutdownHost() { + host_.reset(); } Profile* CRDHostDelegate::GetKioskProfile() const {
diff --git a/chrome/browser/chromeos/policy/remote_commands/crd_host_delegate.h b/chrome/browser/chromeos/policy/remote_commands/crd_host_delegate.h index ccc27a10..0e370259 100644 --- a/chrome/browser/chromeos/policy/remote_commands/crd_host_delegate.h +++ b/chrome/browser/chromeos/policy/remote_commands/crd_host_delegate.h
@@ -13,6 +13,7 @@ #include "base/time/time.h" #include "base/values.h" #include "chrome/browser/chromeos/policy/remote_commands/device_command_start_crd_session_job.h" +#include "extensions/browser/api/messaging/native_message_host.h" #include "google_apis/gaia/oauth2_token_service.h" namespace network { @@ -25,7 +26,8 @@ // An implementation of the |DeviceCommandStartCRDSessionJob::Delegate|. class CRDHostDelegate : public DeviceCommandStartCRDSessionJob::Delegate, - public OAuth2TokenService::Consumer { + public OAuth2TokenService::Consumer, + public extensions::NativeMessageHost::Client { public: CRDHostDelegate(); ~CRDHostDelegate() override; @@ -45,10 +47,9 @@ DeviceCommandStartCRDSessionJob::ICEConfigCallback success_callback, DeviceCommandStartCRDSessionJob::ErrorCallback error_callback) override; void StartCRDHostAndGetCode( - const std::string& directory_bot_jid, const std::string& oauth_token, base::Value ice_config, - DeviceCommandStartCRDSessionJob::AuthCodeCallback success_callback, + DeviceCommandStartCRDSessionJob::AccessCodeCallback success_callback, DeviceCommandStartCRDSessionJob::ErrorCallback error_callback) override; // OAuth2TokenService::Consumer: @@ -58,16 +59,51 @@ void OnGetTokenFailure(const OAuth2TokenService::Request* request, const GoogleServiceAuthError& error) override; + // extensions::NativeMessageHost::Client: + // Invoked when native host sends a message + void PostMessageFromNativeHost(const std::string& message) override; + void CloseChannel(const std::string& error_message) override; + void OnICEConfigurationLoaded(std::unique_ptr<std::string> response_body); + // Sends message to host in separate task. + void SendMessageToHost(const std::string& type, base::Value& params); + // Actually sends message to host. + void DoSendMessage(const std::string& json); + void OnProtocolBroken(const std::string& message); + // Shuts down host in a separate task. + void ShutdownHost(); + // Actually shuts down a host. + void DoShutdownHost(); + + // Handlers for messages from host + void OnHelloResponse(); + void OnDisconnectResponse(); + + void OnStateError(std::string error_state, base::Value& message); + void OnStateRemoteConnected(base::Value& message); + void OnStateRemoteDisconnected(); + void OnStateReceivedAccessCode(base::Value& message); Profile* GetKioskProfile() const; DeviceCommandStartCRDSessionJob::OAuthTokenCallback oauth_success_callback_; DeviceCommandStartCRDSessionJob::ICEConfigCallback ice_success_callback_; + DeviceCommandStartCRDSessionJob::AccessCodeCallback code_success_callback_; DeviceCommandStartCRDSessionJob::ErrorCallback error_callback_; std::unique_ptr<OAuth2TokenService::Request> oauth_request_; std::unique_ptr<network::SimpleURLLoader> ice_config_loader_; + std::unique_ptr<extensions::NativeMessageHost> host_; + + // Filled structure with parameters for "connect" message. + base::Value connect_params_; + + // Determines actions when receiving messages from CRD host, + // if command is still running (no error / access code), then + // callbacks have to be called. + bool command_awaiting_crd_access_code_; + // True if remote session was established. + bool remote_connected_; base::WeakPtrFactory<CRDHostDelegate> weak_factory_;
diff --git a/chrome/browser/chromeos/policy/remote_commands/device_command_start_crd_session_job.cc b/chrome/browser/chromeos/policy/remote_commands/device_command_start_crd_session_job.cc index 3089162..f51c543 100644 --- a/chrome/browser/chromeos/policy/remote_commands/device_command_start_crd_session_job.cc +++ b/chrome/browser/chromeos/policy/remote_commands/device_command_start_crd_session_job.cc
@@ -26,16 +26,13 @@ // activity. const char kIdlenessCutoffFieldName[] = "idlenessCutoffSec"; -// Parameters that are directly passed to CRD Host. -const char kDirectoryBotJIDFieldName[] = "directoryBotJID"; - // Result payload fields: // Integer value containing DeviceCommandStartCRDSessionJob::ResultCode const char kResultCodeFieldName[] = "resultCode"; -// CRD Auth Code if job was completed successfully -const char kResultAuthCodeFieldName[] = "authCode"; +// CRD Access Code if job was completed successfully +const char kResultAccessCodeFieldName[] = "accessCode"; // Optional detailed error message for error result codes. const char kResultMessageFieldName[] = "message"; @@ -50,13 +47,13 @@ : public RemoteCommandJob::ResultPayload { public: ResultPayload(ResultCode result_code, - const base::Optional<std::string>& auth_code, + const base::Optional<std::string>& access_code, const base::Optional<base::TimeDelta>& time_delta, const base::Optional<std::string>& error_message); ~ResultPayload() override {} static std::unique_ptr<ResultPayload> CreateSuccessPayload( - const std::string& auth_code); + const std::string& access_code); static std::unique_ptr<ResultPayload> CreateNonIdlePayload( const base::TimeDelta& time_delta); static std::unique_ptr<ResultPayload> CreateErrorPayload( @@ -72,15 +69,15 @@ DeviceCommandStartCRDSessionJob::ResultPayload::ResultPayload( ResultCode result_code, - const base::Optional<std::string>& auth_code, + const base::Optional<std::string>& access_code, const base::Optional<base::TimeDelta>& time_delta, const base::Optional<std::string>& error_message) { base::Value value(base::Value::Type::DICTIONARY); value.SetKey(kResultCodeFieldName, base::Value(result_code)); if (error_message && !error_message.value().empty()) value.SetKey(kResultMessageFieldName, base::Value(error_message.value())); - if (auth_code) - value.SetKey(kResultAuthCodeFieldName, base::Value(auth_code.value())); + if (access_code) + value.SetKey(kResultAccessCodeFieldName, base::Value(access_code.value())); if (time_delta) { value.SetKey(kResultLastActivityFieldName, base::Value(static_cast<int>(time_delta.value().InSeconds()))); @@ -90,8 +87,8 @@ std::unique_ptr<DeviceCommandStartCRDSessionJob::ResultPayload> DeviceCommandStartCRDSessionJob::ResultPayload::CreateSuccessPayload( - const std::string& auth_code) { - return std::make_unique<ResultPayload>(ResultCode::SUCCESS, auth_code, + const std::string& access_code) { + return std::make_unique<ResultPayload>(ResultCode::SUCCESS, access_code, base::nullopt /*time_delta*/, base::nullopt /* error_message */); } @@ -100,7 +97,7 @@ DeviceCommandStartCRDSessionJob::ResultPayload::CreateNonIdlePayload( const base::TimeDelta& time_delta) { return std::make_unique<ResultPayload>( - ResultCode::FAILURE_NOT_IDLE, base::nullopt /* auth_code */, time_delta, + ResultCode::FAILURE_NOT_IDLE, base::nullopt /* access_code */, time_delta, base::nullopt /* error_message */); } @@ -111,8 +108,8 @@ DCHECK(result_code != ResultCode::SUCCESS); DCHECK(result_code != ResultCode::FAILURE_NOT_IDLE); return std::make_unique<ResultPayload>( - result_code, base::nullopt /* auth_code */, base::nullopt /*time_delta*/, - error_message); + result_code, base::nullopt /* access_code */, + base::nullopt /*time_delta*/, error_message); } std::unique_ptr<std::string> @@ -151,12 +148,6 @@ idleness_cutoff_ = base::TimeDelta::FromSeconds(0); } - base::Value* directory_jid_value = - root->FindKeyOfType(kDirectoryBotJIDFieldName, base::Value::Type::STRING); - if (!directory_jid_value) - return false; - directory_bot_jid_ = directory_jid_value->GetString(); - return true; } @@ -230,21 +221,21 @@ base::Value ice_config) { ice_config_ = std::move(ice_config); delegate_->StartCRDHostAndGetCode( - directory_bot_jid_, oauth_token_, std::move(ice_config_), - base::BindOnce(&DeviceCommandStartCRDSessionJob::OnAuthCodeReceived, + oauth_token_, std::move(ice_config_), + base::BindOnce(&DeviceCommandStartCRDSessionJob::OnAccessCodeReceived, weak_factory_.GetWeakPtr()), base::BindOnce(&DeviceCommandStartCRDSessionJob::FinishWithError, weak_factory_.GetWeakPtr())); } -void DeviceCommandStartCRDSessionJob::OnAuthCodeReceived( - const std::string& auth_code) { +void DeviceCommandStartCRDSessionJob::OnAccessCodeReceived( + const std::string& access_code) { if (!succeeded_callback_) return; // Task was terminated. base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(std::move(succeeded_callback_), - ResultPayload::CreateSuccessPayload(auth_code))); + ResultPayload::CreateSuccessPayload(access_code))); } void DeviceCommandStartCRDSessionJob::TerminateImpl() {
diff --git a/chrome/browser/chromeos/policy/remote_commands/device_command_start_crd_session_job.h b/chrome/browser/chromeos/policy/remote_commands/device_command_start_crd_session_job.h index 29bb0b89..96857ed 100644 --- a/chrome/browser/chromeos/policy/remote_commands/device_command_start_crd_session_job.h +++ b/chrome/browser/chromeos/policy/remote_commands/device_command_start_crd_session_job.h
@@ -44,7 +44,7 @@ }; using OAuthTokenCallback = base::OnceCallback<void(const std::string&)>; - using AuthCodeCallback = base::OnceCallback<void(const std::string&)>; + using AccessCodeCallback = base::OnceCallback<void(const std::string&)>; using ICEConfigCallback = base::OnceCallback<void(base::Value)>; using ErrorCallback = base::OnceCallback<void(ResultCode, const std::string&)>; @@ -80,10 +80,9 @@ ErrorCallback error_callback) = 0; // Attempts to start CRD host and get Auth Code. - virtual void StartCRDHostAndGetCode(const std::string& directory_bot_jid, - const std::string& oauth_token, + virtual void StartCRDHostAndGetCode(const std::string& oauth_token, base::Value ice_config, - AuthCodeCallback success_callback, + AccessCodeCallback success_callback, ErrorCallback error_callback) = 0; }; @@ -108,7 +107,7 @@ void OnOAuthTokenReceived(const std::string& token); void OnICEConfigReceived(base::Value ice_config); - void OnAuthCodeReceived(const std::string& token); + void OnAccessCodeReceived(const std::string& access_code); // The callback that will be called when the access code was successfully // obtained. @@ -123,7 +122,6 @@ base::TimeDelta idleness_cutoff_; std::string oauth_token_; - std::string directory_bot_jid_; base::Value ice_config_; // The Delegate is used to interact with chrome services and CRD host.
diff --git a/chrome/browser/chromeos/policy/remote_commands/device_command_start_crd_session_unittest.cc b/chrome/browser/chromeos/policy/remote_commands/device_command_start_crd_session_unittest.cc index 742018b7..63a9992 100644 --- a/chrome/browser/chromeos/policy/remote_commands/device_command_start_crd_session_unittest.cc +++ b/chrome/browser/chromeos/policy/remote_commands/device_command_start_crd_session_unittest.cc
@@ -29,25 +29,21 @@ constexpr char kResultCodeFieldName[] = "resultCode"; constexpr char kResultMessageFieldName[] = "message"; -constexpr char kResultAuthCodeFieldName[] = "authCode"; +constexpr char kResultAccessCodeFieldName[] = "accessCode"; constexpr char kResultLastActivityFieldName[] = "lastActivitySec"; constexpr RemoteCommandJob::UniqueIDType kUniqueID = 123456789; -constexpr char kTestDirectoryBotJID[] = "remote@bot.jabber.nowhere.org"; - constexpr char kTestOAuthToken[] = "test-oauth-token"; -constexpr char kTestAuthCode[] = "1111-2222-3333"; +constexpr char kTestAccessCode[] = "111122223333"; constexpr char kTestNoOAuthTokenReason[] = "oops-no-oauth-token"; constexpr char kTestNoICEConfigReason[] = "oops-no-ice-config"; constexpr char kIdlenessCutoffFieldName[] = "idlenessCutoffSec"; -constexpr char kDirectoryBotJIDFieldName[] = "directoryBotJID"; em::RemoteCommand GenerateCommandProto(RemoteCommandJob::UniqueIDType unique_id, base::TimeDelta age_of_command, - base::TimeDelta idleness_cutoff, - const std::string& directory_bot_jid) { + base::TimeDelta idleness_cutoff) { em::RemoteCommand command_proto; command_proto.set_type( enterprise_management::RemoteCommand_Type_DEVICE_START_CRD_SESSION); @@ -58,7 +54,6 @@ base::Value root_dict(base::Value::Type::DICTIONARY); root_dict.SetKey(kIdlenessCutoffFieldName, base::Value((int)idleness_cutoff.InSeconds())); - root_dict.SetKey(kDirectoryBotJIDFieldName, base::Value(directory_bot_jid)); base::JSONWriter::Write(root_dict, &payload); command_proto.set_payload(payload); return command_proto; @@ -72,7 +67,7 @@ base::TimeDelta idleness_period, bool oauth_token_success, bool ice_config_success, - bool auth_code_success); + bool access_code_success); ~StubCRDHostDelegate() override; bool HasActiveSession() const override; @@ -92,10 +87,9 @@ DeviceCommandStartCRDSessionJob::ErrorCallback error_callback) override; void StartCRDHostAndGetCode( - const std::string& directory_bot_jid, const std::string& oauth_token, base::Value ice_config, - DeviceCommandStartCRDSessionJob::AuthCodeCallback success_callback, + DeviceCommandStartCRDSessionJob::AccessCodeCallback success_callback, DeviceCommandStartCRDSessionJob::ErrorCallback error_callback) override; private: @@ -105,7 +99,7 @@ base::TimeDelta idleness_period_; bool oauth_token_success_; bool ice_config_success_; - bool auth_code_success_; + bool access_code_success_; DISALLOW_COPY_AND_ASSIGN(StubCRDHostDelegate); }; @@ -116,14 +110,14 @@ base::TimeDelta idleness_period, bool oauth_token_success, bool ice_config_success, - bool auth_code_success) + bool access_code_success) : has_active_session_(has_active_session), are_services_ready_(are_services_ready), is_running_kiosk_(is_running_kiosk), idleness_period_(idleness_period), oauth_token_success_(oauth_token_success), ice_config_success_(ice_config_success), - auth_code_success_(auth_code_success) {} + access_code_success_(access_code_success) {} StubCRDHostDelegate::~StubCRDHostDelegate() {} @@ -175,13 +169,12 @@ } void StubCRDHostDelegate::StartCRDHostAndGetCode( - const std::string& directory_bot_jid, const std::string& oauth_token, base::Value ice_config, - DeviceCommandStartCRDSessionJob::AuthCodeCallback success_callback, + DeviceCommandStartCRDSessionJob::AccessCodeCallback success_callback, DeviceCommandStartCRDSessionJob::ErrorCallback error_callback) { - if (auth_code_success_) { - std::move(success_callback).Run(kTestAuthCode); + if (access_code_success_) { + std::move(success_callback).Run(kTestAccessCode); } else { std::move(error_callback) .Run(DeviceCommandStartCRDSessionJob::FAILURE_CRD_HOST_ERROR, @@ -206,10 +199,9 @@ void InitializeJob(RemoteCommandJob* job, RemoteCommandJob::UniqueIDType unique_id, base::TimeTicks issued_time, - base::TimeDelta idleness_cutoff, - const std::string& directory_bot_jid); + base::TimeDelta idleness_cutoff); - std::string CreateSuccessPayload(const std::string& auth_code); + std::string CreateSuccessPayload(const std::string& access_code); std::string CreateErrorPayload( DeviceCommandStartCRDSessionJob::ResultCode result_code, const std::string& error_message); @@ -234,24 +226,23 @@ RemoteCommandJob* job, RemoteCommandJob::UniqueIDType unique_id, base::TimeTicks issued_time, - base::TimeDelta idleness_cutoff, - const std::string& directory_bot_jid) { + base::TimeDelta idleness_cutoff) { EXPECT_TRUE(job->Init( base::TimeTicks::Now(), GenerateCommandProto(unique_id, base::TimeTicks::Now() - issued_time, - idleness_cutoff, directory_bot_jid))); + idleness_cutoff))); EXPECT_EQ(unique_id, job->unique_id()); EXPECT_EQ(RemoteCommandJob::NOT_STARTED, job->status()); } std::string DeviceCommandStartCRDSessionJobTest::CreateSuccessPayload( - const std::string& auth_code) { + const std::string& access_code) { std::string payload; base::Value root(base::Value::Type::DICTIONARY); root.SetKey(kResultCodeFieldName, base::Value(DeviceCommandStartCRDSessionJob::SUCCESS)); - root.SetKey(kResultAuthCodeFieldName, base::Value(auth_code)); + root.SetKey(kResultAccessCodeFieldName, base::Value(access_code)); base::JSONWriter::Write(root, &payload); return payload; } @@ -297,18 +288,18 @@ true /* is_running_kiosk */, base::TimeDelta::FromHours(1) /* idleness_period */, true /* oauth_token_success */, true /* ice_config_success */, - true /* auth_code_success */); + true /* access_code_success */); std::unique_ptr<RemoteCommandJob> job = std::make_unique<DeviceCommandStartCRDSessionJob>(&delegate); InitializeJob(job.get(), kUniqueID, test_start_time_, - base::TimeDelta::FromSeconds(30), kTestDirectoryBotJID); + base::TimeDelta::FromSeconds(30)); bool success = job->Run( base::TimeTicks::Now(), base::BindOnce(&DeviceCommandStartCRDSessionJobTest::VerifyResults, base::Unretained(this), base::Unretained(job.get()), RemoteCommandJob::SUCCEEDED, - CreateSuccessPayload(kTestAuthCode))); + CreateSuccessPayload(kTestAccessCode))); EXPECT_TRUE(success); run_loop_.Run(); } @@ -319,18 +310,18 @@ true /* is_running_kiosk */, base::TimeDelta::FromHours(1) /* idleness_period */, true /* oauth_token_success */, true /* ice_config_success */, - true /* auth_code_success */); + true /* access_code_success */); std::unique_ptr<RemoteCommandJob> job = std::make_unique<DeviceCommandStartCRDSessionJob>(&delegate); InitializeJob(job.get(), kUniqueID, test_start_time_, - base::TimeDelta::FromSeconds(30), kTestDirectoryBotJID); + base::TimeDelta::FromSeconds(30)); bool success = job->Run( base::TimeTicks::Now(), base::BindOnce(&DeviceCommandStartCRDSessionJobTest::VerifyResults, base::Unretained(this), base::Unretained(job.get()), RemoteCommandJob::SUCCEEDED, - CreateSuccessPayload(kTestAuthCode))); + CreateSuccessPayload(kTestAccessCode))); EXPECT_TRUE(success); run_loop_.Run(); } @@ -341,12 +332,12 @@ true /* is_running_kiosk */, base::TimeDelta::FromHours(1) /* idleness_period */, true /* oauth_token_success */, true /* ice_config_success */, - true /* auth_code_success */); + true /* access_code_success */); std::unique_ptr<RemoteCommandJob> job = std::make_unique<DeviceCommandStartCRDSessionJob>(&delegate); InitializeJob(job.get(), kUniqueID, test_start_time_, - base::TimeDelta::FromSeconds(30), kTestDirectoryBotJID); + base::TimeDelta::FromSeconds(30)); bool success = job->Run( base::TimeTicks::Now(), base::BindOnce( @@ -366,12 +357,12 @@ false /* is_running_kiosk */, base::TimeDelta::FromHours(1) /* idleness_period */, true /* oauth_token_success */, true /* ice_config_success */, - true /* auth_code_success */); + true /* access_code_success */); std::unique_ptr<RemoteCommandJob> job = std::make_unique<DeviceCommandStartCRDSessionJob>(&delegate); InitializeJob(job.get(), kUniqueID, test_start_time_, - base::TimeDelta::FromSeconds(30), kTestDirectoryBotJID); + base::TimeDelta::FromSeconds(30)); bool success = job->Run( base::TimeTicks::Now(), base::BindOnce(&DeviceCommandStartCRDSessionJobTest::VerifyResults, @@ -390,12 +381,12 @@ true /* is_running_kiosk */, base::TimeDelta::FromSeconds(1) /* idleness_period */, true /* oauth_token_success */, true /* ice_config_success */, - true /* auth_code_success */); + true /* access_code_success */); std::unique_ptr<RemoteCommandJob> job = std::make_unique<DeviceCommandStartCRDSessionJob>(&delegate); InitializeJob(job.get(), kUniqueID, test_start_time_, - base::TimeDelta::FromSeconds(30), kTestDirectoryBotJID); + base::TimeDelta::FromSeconds(30)); bool success = job->Run( base::TimeTicks::Now(), base::BindOnce(&DeviceCommandStartCRDSessionJobTest::VerifyResults, @@ -412,12 +403,12 @@ true /* is_running_kiosk */, base::TimeDelta::FromHours(1) /* idleness_period */, false /* oauth_token_success */, true /* ice_config_success */, - true /* auth_code_success */); + true /* access_code_success */); std::unique_ptr<RemoteCommandJob> job = std::make_unique<DeviceCommandStartCRDSessionJob>(&delegate); InitializeJob(job.get(), kUniqueID, test_start_time_, - base::TimeDelta::FromSeconds(30), kTestDirectoryBotJID); + base::TimeDelta::FromSeconds(30)); bool success = job->Run(base::TimeTicks::Now(), base::BindOnce( @@ -437,12 +428,12 @@ true /* is_running_kiosk */, base::TimeDelta::FromHours(1) /* idleness_period */, true /* oauth_token_success */, false /* ice_config_success */, - true /* auth_code_success */); + true /* access_code_success */); std::unique_ptr<RemoteCommandJob> job = std::make_unique<DeviceCommandStartCRDSessionJob>(&delegate); InitializeJob(job.get(), kUniqueID, test_start_time_, - base::TimeDelta::FromSeconds(30), kTestDirectoryBotJID); + base::TimeDelta::FromSeconds(30)); bool success = job->Run( base::TimeTicks::Now(), base::BindOnce(&DeviceCommandStartCRDSessionJobTest::VerifyResults, @@ -461,12 +452,12 @@ true /* is_running_kiosk */, base::TimeDelta::FromHours(1) /* idleness_period */, true /* oauth_token_success */, true /* ice_config_success */, - false /* auth_code_success */); + false /* access_code_success */); std::unique_ptr<RemoteCommandJob> job = std::make_unique<DeviceCommandStartCRDSessionJob>(&delegate); InitializeJob(job.get(), kUniqueID, test_start_time_, - base::TimeDelta::FromSeconds(30), kTestDirectoryBotJID); + base::TimeDelta::FromSeconds(30)); bool success = job->Run(base::TimeTicks::Now(), base::BindOnce(
diff --git a/chrome/browser/chromeos/settings/device_oauth2_token_service_delegate.cc b/chrome/browser/chromeos/settings/device_oauth2_token_service_delegate.cc index fcbbeb7..eb9d85d 100644 --- a/chrome/browser/chromeos/settings/device_oauth2_token_service_delegate.cc +++ b/chrome/browser/chromeos/settings/device_oauth2_token_service_delegate.cc
@@ -281,8 +281,8 @@ state_ = STATE_VALIDATION_STARTED; - gaia_oauth_client_.reset( - new gaia::GaiaOAuthClient(g_browser_process->system_request_context())); + gaia_oauth_client_.reset(new gaia::GaiaOAuthClient( + g_browser_process->shared_url_loader_factory())); GaiaUrls* gaia_urls = GaiaUrls::GetInstance(); gaia::OAuthClientInfo client_info;
diff --git a/chrome/browser/chromeos/settings/device_oauth2_token_service_unittest.cc b/chrome/browser/chromeos/settings/device_oauth2_token_service_unittest.cc index 01e58efa..c6fcfd4 100644 --- a/chrome/browser/chromeos/settings/device_oauth2_token_service_unittest.cc +++ b/chrome/browser/chromeos/settings/device_oauth2_token_service_unittest.cc
@@ -35,11 +35,9 @@ #include "google_apis/gaia/gaia_urls.h" #include "google_apis/gaia/oauth2_token_service_test_util.h" #include "net/http/http_status_code.h" -#include "net/url_request/test_url_fetcher_factory.h" -#include "net/url_request/url_fetcher_delegate.h" -#include "net/url_request/url_request_test_util.h" #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" #include "services/network/test/test_url_loader_factory.h" +#include "services/network/test/test_utils.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -63,16 +61,16 @@ } // namespace -static const int kValidatorUrlFetcherId = gaia::GaiaOAuthClient::kUrlFetcherId; - class DeviceOAuth2TokenServiceTest : public testing::Test { public: DeviceOAuth2TokenServiceTest() : scoped_testing_local_state_(TestingBrowserProcess::GetGlobal()), test_shared_loader_factory_( base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( - &test_url_loader_factory_)) {} - ~DeviceOAuth2TokenServiceTest() override {} + &test_url_loader_factory_)) { + TestingBrowserProcess::GetGlobal()->SetSharedURLLoaderFactory( + test_shared_loader_factory_); + } // Most tests just want a noop crypto impl with a dummy refresh token value in // Local State (if the value is an empty string, it will be ignored). @@ -127,6 +125,7 @@ } void TearDown() override { + TestingBrowserProcess::GetGlobal()->SetSharedURLLoaderFactory(nullptr); oauth2_service_.reset(); test_shared_loader_factory_->Detach(); CrosSettings::Shutdown(); @@ -176,16 +175,15 @@ // A utility method to return fake URL results, for testing the refresh token // validation logic. For a successful validation attempt, this method will be - // called three times for the steps listed below (steps 1 and 2 happen in - // parallel). + // called three times for the steps listed below. // // Step 1a: fetch the access token for the tokeninfo API. // Step 1b: call the tokeninfo API. // Step 2: Fetch the access token for the requested scope // (in this case, cloudprint). - void ReturnOAuthUrlFetchResults(int fetcher_id, + void ReturnOAuthUrlFetchResults(const std::string& url, net::HttpStatusCode response_code, - const std::string& response_string); + const std::string& response_string); // Generates URL fetch replies with the specified results for requests // generated by the token service. @@ -218,7 +216,6 @@ network::TestURLLoaderFactory test_url_loader_factory_; scoped_refptr<network::WeakWrapperSharedURLLoaderFactory> test_shared_loader_factory_; - net::TestURLFetcherFactory factory_; FakeCryptohomeClient* fake_cryptohome_client_; FakeSessionManagerClient session_manager_client_; policy::DevicePolicyBuilder device_policy_; @@ -228,16 +225,13 @@ }; void DeviceOAuth2TokenServiceTest::ReturnOAuthUrlFetchResults( - int fetcher_id, + const std::string& url, net::HttpStatusCode response_code, const std::string& response_string) { - net::TestURLFetcher* fetcher = factory_.GetFetcherByID(fetcher_id); - if (fetcher) { - factory_.RemoveFetcherFromMap(fetcher_id); - fetcher->set_response_code(response_code); - fetcher->SetResponseString(response_string); - fetcher->delegate()->OnURLFetchComplete(fetcher); - base::RunLoop().RunUntilIdle(); + if (test_url_loader_factory_.IsPending(url)) { + test_url_loader_factory_.SimulateResponseForPendingRequest( + GURL(url), network::URLLoaderCompletionStatus(net::OK), + network::CreateResourceResponseHead(response_code), response_string); } } @@ -248,21 +242,17 @@ const std::string& tokeninfo_fetch_response, net::HttpStatusCode service_access_token_status, const std::string& service_access_token_response) { - test_url_loader_factory_.AddResponse( - GaiaUrls::GetInstance()->oauth2_token_url().spec(), - service_access_token_response, service_access_token_status); - - // This sends a response to the OAuth token request made by - // GaiaOAuthClient::Core, that should eventually be ported to SimpleURLLoader. - ReturnOAuthUrlFetchResults( - kValidatorUrlFetcherId, - tokeninfo_access_token_status, - tokeninfo_access_token_response); + ReturnOAuthUrlFetchResults(GaiaUrls::GetInstance()->oauth2_token_url().spec(), + tokeninfo_access_token_status, + tokeninfo_access_token_response); ReturnOAuthUrlFetchResults( - kValidatorUrlFetcherId, - tokeninfo_fetch_status, - tokeninfo_fetch_response); + GaiaUrls::GetInstance()->oauth2_token_info_url().spec(), + tokeninfo_fetch_status, tokeninfo_fetch_response); + + ReturnOAuthUrlFetchResults(GaiaUrls::GetInstance()->oauth2_token_url().spec(), + service_access_token_status, + service_access_token_response); } void DeviceOAuth2TokenServiceTest::PerformURLFetches() {
diff --git a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc index a6529fc..e0fbac6 100644 --- a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc +++ b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
@@ -1496,12 +1496,21 @@ ASSERT_EQ(items[2]->GetTargetFilePath().value(), item_name); } +// https://crbug.com/874946, flaky on Win. +#if defined(OS_WIN) +#define MAYBE_DownloadExtensionTest_SearchPauseResumeCancelGetFileIconIncognito \ + DISABLED_DownloadExtensionTest_SearchPauseResumeCancelGetFileIconIncognito +#else +#define MAYBE_DownloadExtensionTest_SearchPauseResumeCancelGetFileIconIncognito \ + DownloadExtensionTest_SearchPauseResumeCancelGetFileIconIncognito +#endif // Test that incognito downloads are only visible in incognito contexts, and // test that on-record downloads are visible in both incognito and on-record // contexts, for DownloadsSearchFunction, DownloadsPauseFunction, // DownloadsResumeFunction, and DownloadsCancelFunction. -IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, - DownloadExtensionTest_SearchPauseResumeCancelGetFileIconIncognito) { +IN_PROC_BROWSER_TEST_F( + DownloadExtensionTest, + MAYBE_DownloadExtensionTest_SearchPauseResumeCancelGetFileIconIncognito) { std::unique_ptr<base::Value> result_value; base::ListValue* result_list = NULL; base::DictionaryValue* result_dict = NULL;
diff --git a/chrome/browser/extensions/api/web_request/web_request_apitest.cc b/chrome/browser/extensions/api/web_request/web_request_apitest.cc index 46d68e7..6d1da85 100644 --- a/chrome/browser/extensions/api/web_request/web_request_apitest.cc +++ b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
@@ -1611,9 +1611,7 @@ base::Unretained(this))); ASSERT_TRUE(https_test_server_.InitializeAndListen()); ExtensionApiTest::SetUp(); - feature_list_.InitWithFeatures( - {::features::kUseGoogleLocalNtp, ::features::kOneGoogleBarOnLocalNtp}, - {}); + feature_list_.InitWithFeatures({::features::kUseGoogleLocalNtp}, {}); } void SetUpCommandLine(base::CommandLine* command_line) override { ExtensionApiTest::SetUpCommandLine(command_line);
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 25ccc34b..7ed258a 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -440,6 +440,11 @@ const char kEnableAutoplayIgnoreWebAudioDescription[] = "If enabled, autoplay restrictions will be ignored for WebAudio."; +const char kEnableAutoplayUnifiedSoundSettingsName[] = + "Autoplay unified sound settings UI"; +const char kEnableAutoplayUnifiedSoundSettingsDescription[] = + "If enabled, shows the new unified autoplay sound settings UI."; + const char kEnableBreakingNewsPushName[] = "Breaking News Push"; const char kEnableBreakingNewsPushDescription[] = "Listen for breaking news content suggestions (e.g. for New Tab Page) " @@ -2812,12 +2817,6 @@ "Enable receiving tail suggestions, a type of search suggestion based on " "the last few words in the query, for the Omnibox."; -const char kOneGoogleBarOnLocalNtpName[] = - "Enable the OneGoogleBar on the local NTP"; -const char kOneGoogleBarOnLocalNtpDescription[] = - "Show a OneGoogleBar on the local New Tab page if Google is the default " - "search engine."; - const char kPageAlmostIdleName[] = "Page Almost Idle"; const char kPageAlmostIdleDescription[] = "Make session restore use a definition of loading that waits for CPU and "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 07311c4..1fd39d1 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -296,6 +296,9 @@ extern const char kEnableAutoplayIgnoreWebAudioName[]; extern const char kEnableAutoplayIgnoreWebAudioDescription[]; +extern const char kEnableAutoplayUnifiedSoundSettingsName[]; +extern const char kEnableAutoplayUnifiedSoundSettingsDescription[]; + extern const char kEnableBreakingNewsPushName[]; extern const char kEnableBreakingNewsPushDescription[]; @@ -1697,9 +1700,6 @@ extern const char kOmniboxTailSuggestionsName[]; extern const char kOmniboxTailSuggestionsDescription[]; -extern const char kOneGoogleBarOnLocalNtpName[]; -extern const char kOneGoogleBarOnLocalNtpDescription[]; - extern const char kPageAlmostIdleName[]; extern const char kPageAlmostIdleDescription[];
diff --git a/chrome/browser/infobars/infobars_browsertest.cc b/chrome/browser/infobars/infobars_browsertest.cc index 1a29372..f893686 100644 --- a/chrome/browser/infobars/infobars_browsertest.cc +++ b/chrome/browser/infobars/infobars_browsertest.cc
@@ -415,8 +415,7 @@ case IBD::DATA_REDUCTION_PROXY_PREVIEW_INFOBAR_DELEGATE: PreviewsInfoBarDelegate::Create( GetWebContents(), previews::PreviewsType::LOFI, base::Time::Now(), - true, true, - PreviewsInfoBarDelegate::OnDismissPreviewsInfobarCallback(), nullptr); + true, true, OnDismissPreviewsUICallback(), nullptr); break; case IBD::AUTOMATION_INFOBAR_DELEGATE:
diff --git a/chrome/browser/metrics/desktop_session_duration/audible_contents_tracker.cc b/chrome/browser/metrics/desktop_session_duration/audible_contents_tracker.cc index a2f95488..ec94801 100644 --- a/chrome/browser/metrics/desktop_session_duration/audible_contents_tracker.cc +++ b/chrome/browser/metrics/desktop_session_duration/audible_contents_tracker.cc
@@ -32,10 +32,34 @@ browser->tab_strip_model()->RemoveObserver(this); } -void AudibleContentsTracker::TabClosingAt(TabStripModel* model, - content::WebContents* web_contents, - int index) { - RemoveAudibleWebContents(web_contents); +void AudibleContentsTracker::OnTabStripModelChanged( + TabStripModel* tab_strip_model, + const TabStripModelChange& change, + const TabStripSelectionChange& selection) { + if (change.type() != TabStripModelChange::kRemoved && + change.type() != TabStripModelChange::kReplaced) + return; + + for (const auto& delta : change.deltas()) { + content::WebContents* removed_contents = nullptr; + content::WebContents* added_contents = nullptr; + if (change.type() == TabStripModelChange::kReplaced) { + removed_contents = delta.replace.old_contents; + added_contents = delta.replace.new_contents; + } else if (delta.remove.will_be_deleted) { + removed_contents = delta.remove.contents; + } + + if (removed_contents) + RemoveAudibleWebContents(removed_contents); + + if (added_contents) { + auto* audible_helper = + RecentlyAudibleHelper::FromWebContents(added_contents); + if (audible_helper->WasRecentlyAudible()) + AddAudibleWebContents(added_contents); + } + } } void AudibleContentsTracker::TabChangedAt(content::WebContents* web_contents, @@ -52,18 +76,6 @@ RemoveAudibleWebContents(web_contents); } -void AudibleContentsTracker::TabReplacedAt( - TabStripModel* model, - content::WebContents* old_web_contents, - content::WebContents* new_web_contents, - int index) { - RemoveAudibleWebContents(old_web_contents); - auto* audible_helper = - RecentlyAudibleHelper::FromWebContents(new_web_contents); - if (audible_helper->WasRecentlyAudible()) - AddAudibleWebContents(new_web_contents); -} - void AudibleContentsTracker::AddAudibleWebContents( content::WebContents* web_contents) { // The first web contents to become audible indicates that audio has started.
diff --git a/chrome/browser/metrics/desktop_session_duration/audible_contents_tracker.h b/chrome/browser/metrics/desktop_session_duration/audible_contents_tracker.h index eb51e3e8..0f295f4bf 100644 --- a/chrome/browser/metrics/desktop_session_duration/audible_contents_tracker.h +++ b/chrome/browser/metrics/desktop_session_duration/audible_contents_tracker.h
@@ -50,16 +50,13 @@ void OnBrowserRemoved(Browser* browser) override; // TabStripModelObserver: - void TabClosingAt(TabStripModel* model, - content::WebContents* web_contents, - int index) override; + void OnTabStripModelChanged( + TabStripModel* tab_strip_model, + const TabStripModelChange& change, + const TabStripSelectionChange& selection) override; void TabChangedAt(content::WebContents* web_contents, int index, TabChangeType change_type) override; - void TabReplacedAt(TabStripModel* model, - content::WebContents* old_web_contents, - content::WebContents* new_web_contents, - int index) override; // Used for managing audible_contents_, and invoking OnAudioStart and // OnAudioEnd callbacks.
diff --git a/chrome/browser/metrics/tab_reactivation_tracker.cc b/chrome/browser/metrics/tab_reactivation_tracker.cc index 7a2a1e2..20c11dc 100644 --- a/chrome/browser/metrics/tab_reactivation_tracker.cc +++ b/chrome/browser/metrics/tab_reactivation_tracker.cc
@@ -75,25 +75,23 @@ TabReactivationTracker::~TabReactivationTracker() = default; -void TabReactivationTracker::TabInsertedAt(TabStripModel* tab_strip_model, - content::WebContents* contents, - int index, - bool foreground) {} +void TabReactivationTracker::OnTabStripModelChanged( + TabStripModel* tab_strip_model, + const TabStripModelChange& change, + const TabStripSelectionChange& selection) { + if (change.type() == TabStripModelChange::kRemoved) { + for (const auto& delta : change.deltas()) { + if (delta.remove.will_be_deleted) + GetHelper(delta.remove.contents)->OnTabClosing(); + } + } -void TabReactivationTracker::TabClosingAt(TabStripModel* tab_strip_model, - content::WebContents* contents, - int index) { - GetHelper(contents)->OnTabClosing(); -} - -void TabReactivationTracker::ActiveTabChanged( - content::WebContents* old_contents, - content::WebContents* new_contents, - int index, - int reason) { - if (old_contents) - GetHelper(old_contents)->OnTabDeactivating(); - GetHelper(new_contents)->OnTabActivating(); + if (selection.active_tab_changed()) { + if (selection.old_contents) + GetHelper(selection.old_contents)->OnTabDeactivating(); + if (selection.new_contents) + GetHelper(selection.new_contents)->OnTabActivating(); + } } void TabReactivationTracker::NotifyTabDeactivating(
diff --git a/chrome/browser/metrics/tab_reactivation_tracker.h b/chrome/browser/metrics/tab_reactivation_tracker.h index 177e18f7..39278c9 100644 --- a/chrome/browser/metrics/tab_reactivation_tracker.h +++ b/chrome/browser/metrics/tab_reactivation_tracker.h
@@ -31,17 +31,10 @@ ~TabReactivationTracker() override; // TabStripModelObserver: - void TabInsertedAt(TabStripModel* tab_strip_model, - content::WebContents* contents, - int index, - bool foreground) override; - void TabClosingAt(TabStripModel* tab_strip_model, - content::WebContents* contents, - int index) override; - void ActiveTabChanged(content::WebContents* old_contents, - content::WebContents* new_contents, - int index, - int reason) override; + void OnTabStripModelChanged( + TabStripModel* tab_strip_model, + const TabStripModelChange& change, + const TabStripSelectionChange& selection) override; void NotifyTabDeactivating(content::WebContents* contents); void NotifyTabReactivating(content::WebContents* contents);
diff --git a/chrome/browser/metrics/tab_stats_tracker.cc b/chrome/browser/metrics/tab_stats_tracker.cc index 2180049..364e16ca 100644 --- a/chrome/browser/metrics/tab_stats_tracker.cc +++ b/chrome/browser/metrics/tab_stats_tracker.cc
@@ -240,15 +240,32 @@ browser->tab_strip_model()->RemoveObserver(this); } -void TabStatsTracker::TabInsertedAt(TabStripModel* model, - content::WebContents* web_contents, - int index, - bool foreground) { +void TabStatsTracker::OnTabStripModelChanged( + TabStripModel* tab_strip_model, + const TabStripModelChange& change, + const TabStripSelectionChange& selection) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - OnInitialOrInsertedTab(web_contents); + if (change.type() == TabStripModelChange::kInserted) { + for (const auto& delta : change.deltas()) + OnInitialOrInsertedTab(delta.insert.contents); - tab_stats_data_store_->UpdateMaxTabsPerWindowIfNeeded( - static_cast<size_t>(model->count())); + tab_stats_data_store_->UpdateMaxTabsPerWindowIfNeeded( + static_cast<size_t>(tab_strip_model->count())); + + return; + } + + if (change.type() == TabStripModelChange::kReplaced) { + for (const auto& delta : change.deltas()) { + content::WebContents* old_contents = delta.replace.old_contents; + content::WebContents* new_contents = delta.replace.new_contents; + tab_stats_data_store_->OnTabReplaced(old_contents, new_contents); + web_contents_usage_observers_.insert(std::make_pair( + new_contents, + std::make_unique<WebContentsUsageObserver>(new_contents, this))); + web_contents_usage_observers_.erase(old_contents); + } + } } void TabStatsTracker::TabChangedAt(content::WebContents* web_contents, @@ -262,18 +279,6 @@ tab_stats_data_store_->OnTabAudible(web_contents); } -void TabStatsTracker::TabReplacedAt(TabStripModel* tab_strip_model, - content::WebContents* old_contents, - content::WebContents* new_contents, - int index) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - tab_stats_data_store_->OnTabReplaced(old_contents, new_contents); - web_contents_usage_observers_.insert(std::make_pair( - new_contents, - std::make_unique<WebContentsUsageObserver>(new_contents, this))); - web_contents_usage_observers_.erase(old_contents); -} - void TabStatsTracker::OnResume() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); reporting_delegate_->ReportTabCountOnResume(
diff --git a/chrome/browser/metrics/tab_stats_tracker.h b/chrome/browser/metrics/tab_stats_tracker.h index a6ecbcf..25703a2 100644 --- a/chrome/browser/metrics/tab_stats_tracker.h +++ b/chrome/browser/metrics/tab_stats_tracker.h
@@ -131,18 +131,13 @@ void OnBrowserRemoved(Browser* browser) override; // TabStripModelObserver: - void TabInsertedAt(TabStripModel* tab_strip_model, - content::WebContents* contents, - int index, - bool foreground) override; + void OnTabStripModelChanged( + TabStripModel* tab_strip_model, + const TabStripModelChange& change, + const TabStripSelectionChange& selection) override; void TabChangedAt(content::WebContents* web_contents, int index, TabChangeType change_type) override; - void TabReplacedAt(TabStripModel* tab_strip_model, - content::WebContents* old_contents, - content::WebContents* new_contents, - int index) override; - // base::PowerObserver: void OnResume() override;
diff --git a/chrome/browser/metrics/tab_usage_recorder.cc b/chrome/browser/metrics/tab_usage_recorder.cc index b121f73..6c9d042f 100644 --- a/chrome/browser/metrics/tab_usage_recorder.cc +++ b/chrome/browser/metrics/tab_usage_recorder.cc
@@ -101,12 +101,18 @@ GetWebContentsData(contents)->RecordTabReactivation(); } -void TabUsageRecorder::TabInsertedAt(TabStripModel* tab_strip_model, - content::WebContents* contents, - int index, - bool foreground) { - // Set the initial pin state. - TabPinnedStateChanged(tab_strip_model, contents, index); +void TabUsageRecorder::OnTabStripModelChanged( + TabStripModel* tab_strip_model, + const TabStripModelChange& change, + const TabStripSelectionChange& selection) { + if (change.type() != TabStripModelChange::kInserted) + return; + + for (const auto& delta : change.deltas()) { + // Set the initial pin state. + TabPinnedStateChanged(tab_strip_model, delta.insert.contents, + delta.insert.index); + } } void TabUsageRecorder::TabPinnedStateChanged(TabStripModel* tab_strip_model,
diff --git a/chrome/browser/metrics/tab_usage_recorder.h b/chrome/browser/metrics/tab_usage_recorder.h index 55d5b6e..8dd1f93 100644 --- a/chrome/browser/metrics/tab_usage_recorder.h +++ b/chrome/browser/metrics/tab_usage_recorder.h
@@ -28,10 +28,10 @@ void OnTabReactivated(content::WebContents* contents) override; // TabStripModelObserver: - void TabInsertedAt(TabStripModel* tab_strip_model, - content::WebContents* contents, - int index, - bool foreground) override; + void OnTabStripModelChanged( + TabStripModel* tab_strip_model, + const TabStripModelChange& change, + const TabStripSelectionChange& selection) override; void TabPinnedStateChanged(TabStripModel* tab_strip_model, content::WebContents* contents, int index) override;
diff --git a/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_io_data.cc b/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_io_data.cc index 5ce825b..d215b80 100644 --- a/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_io_data.cc +++ b/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_io_data.cc
@@ -61,12 +61,6 @@ void OnLoFiResponseReceivedOnUI(content::WebContents* web_contents) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - // Retrieve PreviewsUIService* from |web_contents| if available. - PreviewsService* previews_service = PreviewsServiceFactory::GetForProfile( - Profile::FromBrowserContext(web_contents->GetBrowserContext())); - previews::PreviewsUIService* previews_ui_service = - previews_service ? previews_service->previews_ui_service() : nullptr; - PreviewsUITabHelper* ui_tab_helper = PreviewsUITabHelper::FromWebContents(web_contents); @@ -75,17 +69,15 @@ page_id = ui_tab_helper->previews_user_data()->page_id(); } - PreviewsInfoBarDelegate::Create( - web_contents, previews::PreviewsType::LOFI, - base::Time() /* previews_freshness */, true /* is_data_saver_user */, - false /* is_reload */, + ui_tab_helper->ShowUIElement( + previews::PreviewsType::LOFI, base::Time() /* previews_freshness */, + true /* is_data_saver_user */, false /* is_reload */, base::BindOnce(&AddPreviewNavigationToBlackListCallback, web_contents->GetBrowserContext(), web_contents->GetController() .GetLastCommittedEntry() ->GetRedirectChain()[0], - previews::PreviewsType::LOFI, page_id), - previews_ui_service); + previews::PreviewsType::LOFI, page_id)); } } // namespace
diff --git a/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc b/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc index efec4022..1dcdd5f6 100644 --- a/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc +++ b/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc
@@ -640,7 +640,8 @@ const mojom::PageLoadTiming& timing, const mojom::PageLoadMetadata& metadata, const mojom::PageLoadFeatures& new_features, - const mojom::PageLoadDataUse& new_data_use) { + const mojom::PageLoadDataUse& new_data_use, + const std::vector<mojom::ResourceDataUpdatePtr>& resources) { // We may receive notifications from frames that have been navigated away // from. We simply ignore them. if (GetMainFrame(render_frame_host) != web_contents()->GetMainFrame()) { @@ -673,7 +674,8 @@ if (committed_load_) { committed_load_->metrics_update_dispatcher()->UpdateMetrics( - render_frame_host, timing, metadata, new_features, new_data_use); + render_frame_host, timing, metadata, new_features, new_data_use, + resources); } } @@ -681,11 +683,12 @@ const mojom::PageLoadTimingPtr timing, const mojom::PageLoadMetadataPtr metadata, const mojom::PageLoadFeaturesPtr new_features, - const mojom::PageLoadDataUsePtr new_data_use) { + const mojom::PageLoadDataUsePtr new_data_use, + const std::vector<mojom::ResourceDataUpdatePtr> resources) { content::RenderFrameHost* render_frame_host = page_load_metrics_binding_.GetCurrentTargetFrame(); OnTimingUpdated(render_frame_host, *timing, *metadata, *new_features, - *new_data_use); + *new_data_use, resources); } bool MetricsWebContentsObserver::ShouldTrackNavigation(
diff --git a/chrome/browser/page_load_metrics/metrics_web_contents_observer.h b/chrome/browser/page_load_metrics/metrics_web_contents_observer.h index e6430afa..55ba9146 100644 --- a/chrome/browser/page_load_metrics/metrics_web_contents_observer.h +++ b/chrome/browser/page_load_metrics/metrics_web_contents_observer.h
@@ -146,11 +146,13 @@ void RemoveTestingObserver(TestingObserver* observer); // public only for testing - void OnTimingUpdated(content::RenderFrameHost* render_frame_host, - const mojom::PageLoadTiming& timing, - const mojom::PageLoadMetadata& metadata, - const mojom::PageLoadFeatures& new_features, - const mojom::PageLoadDataUse& new_data_use); + void OnTimingUpdated( + content::RenderFrameHost* render_frame_host, + const mojom::PageLoadTiming& timing, + const mojom::PageLoadMetadata& metadata, + const mojom::PageLoadFeatures& new_features, + const mojom::PageLoadDataUse& new_data_use, + const std::vector<mojom::ResourceDataUpdatePtr>& resources); // Informs the observers of the currently committed load that the event // corresponding to |event_key| has occurred. This should not be called within @@ -162,10 +164,12 @@ friend class content::WebContentsUserData<MetricsWebContentsObserver>; // page_load_metrics::mojom::PageLoadMetrics implementation. - void UpdateTiming(const mojom::PageLoadTimingPtr timing, - const mojom::PageLoadMetadataPtr metadata, - const mojom::PageLoadFeaturesPtr new_features, - const mojom::PageLoadDataUsePtr new_data_use) override; + void UpdateTiming( + const mojom::PageLoadTimingPtr timing, + const mojom::PageLoadMetadataPtr metadata, + const mojom::PageLoadFeaturesPtr new_features, + const mojom::PageLoadDataUsePtr new_data_use, + const std::vector<mojom::ResourceDataUpdatePtr> resources) override; void HandleFailedNavigationForTrackedLoad( content::NavigationHandle* navigation_handle,
diff --git a/chrome/browser/page_load_metrics/metrics_web_contents_observer_unittest.cc b/chrome/browser/page_load_metrics/metrics_web_contents_observer_unittest.cc index 6ca129e6..8307a50 100644 --- a/chrome/browser/page_load_metrics/metrics_web_contents_observer_unittest.cc +++ b/chrome/browser/page_load_metrics/metrics_web_contents_observer_unittest.cc
@@ -258,7 +258,8 @@ content::RenderFrameHost* render_frame_host) { observer()->OnTimingUpdated( render_frame_host, timing, mojom::PageLoadMetadata(), - mojom::PageLoadFeatures(), mojom::PageLoadDataUse()); + mojom::PageLoadFeatures(), mojom::PageLoadDataUse(), + std::vector<mojom::ResourceDataUpdatePtr>()); } void AttachObserver() {
diff --git a/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_tester.cc b/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_tester.cc index 641e4d27..9d99233 100644 --- a/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_tester.cc +++ b/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_tester.cc
@@ -88,7 +88,8 @@ const mojom::PageLoadMetadata& metadata, const mojom::PageLoadFeatures& new_features) { observer_->OnTimingUpdated(web_contents()->GetMainFrame(), timing, metadata, - new_features, mojom::PageLoadDataUse()); + new_features, mojom::PageLoadDataUse(), + std::vector<mojom::ResourceDataUpdatePtr>()); // If sending the timing update caused the PageLoadMetricsUpdateDispatcher to // schedule a buffering timer, then fire it now so metrics are dispatched to // observers. @@ -101,7 +102,8 @@ const mojom::PageLoadDataUse& data_use) { observer_->OnTimingUpdated(web_contents()->GetMainFrame(), mojom::PageLoadTiming(), mojom::PageLoadMetadata(), - mojom::PageLoadFeatures(), data_use); + mojom::PageLoadFeatures(), data_use, + std::vector<mojom::ResourceDataUpdatePtr>()); } void PageLoadMetricsObserverTester::SimulateLoadedResource(
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc index 8a390ddf..e8fdfc7 100644 --- a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc +++ b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
@@ -1852,3 +1852,89 @@ waiter->AddMinimumPageLoadDataUseExpectation(7 * (one_frame_page_size - 100)); waiter->Wait(); } + +IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, + ReceivedAggregateResourceDataLength) { + embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data"); + content::SetupCrossSiteRedirector(embedded_test_server()); + ASSERT_TRUE(embedded_test_server()->Start()); + + auto waiter = CreatePageLoadMetricsTestWaiter(); + waiter->AddPageExpectation(TimingField::kLoadEvent); + ui_test_utils::NavigateToURL( + browser(), embedded_test_server()->GetURL( + "foo.com", "/cross_site_iframe_factory.html?foo")); + waiter->Wait(); + int64_t one_frame_page_size = waiter->current_resource_bytes(); + + waiter = CreatePageLoadMetricsTestWaiter(); + waiter->AddPageExpectation(TimingField::kLoadEvent); + ui_test_utils::NavigateToURL( + browser(), + embedded_test_server()->GetURL( + "a.com", "/cross_site_iframe_factory.html?a(b,c,d(e,f,g))")); + // Verify that 7 iframes are fetched, with some amount of tolerance since + // favicon is fetched only once. + waiter->AddMinimumResourceBytesExpectation(7 * (one_frame_page_size - 100)); + waiter->Wait(); +} + +IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, ReceivedCompleteResources) { + const char kHttpResponseHeader[] = + "HTTP/1.1 200 OK\r\n" + "Content-Type: text/html; charset=utf-8\r\n" + "\r\n"; + auto main_html_response = + std::make_unique<net::test_server::ControllableHttpResponse>( + embedded_test_server(), "/mock_page.html", + true /*relative_url_is_prefix*/); + auto script_response = + std::make_unique<net::test_server::ControllableHttpResponse>( + embedded_test_server(), "/script.js", + true /*relative_url_is_prefix*/); + auto iframe_response = + std::make_unique<net::test_server::ControllableHttpResponse>( + embedded_test_server(), "/iframe.html", + true /*relative_url_is_prefix*/); + ASSERT_TRUE(embedded_test_server()->Start()); + + auto waiter = CreatePageLoadMetricsTestWaiter(); + + browser()->OpenURL(content::OpenURLParams( + embedded_test_server()->GetURL("/mock_page.html"), content::Referrer(), + WindowOpenDisposition::CURRENT_TAB, ui::PAGE_TRANSITION_TYPED, false)); + + main_html_response->WaitForRequest(); + main_html_response->Send(kHttpResponseHeader); + main_html_response->Send( + "<html><body></body><script src=\"script.js\"></script></html>"); + main_html_response->Send(std::string(1000, ' ')); + main_html_response->Done(); + waiter->AddCompleteResourcesExpectation(1); + waiter->AddMinimumResourceBytesExpectation(1000); + waiter->Wait(); + + script_response->WaitForRequest(); + script_response->Send(kHttpResponseHeader); + script_response->Send( + "var iframe = document.createElement(\"iframe\");" + "iframe.src =\"iframe.html\";" + "document.body.appendChild(iframe);"); + script_response->Send(std::string(1000, ' ')); + // Data received but resource not complete + waiter->AddCompleteResourcesExpectation(1); + waiter->AddMinimumResourceBytesExpectation(2000); + waiter->Wait(); + script_response->Done(); + waiter->AddCompleteResourcesExpectation(2); + waiter->Wait(); + + // Make sure main resources are loaded correctly + iframe_response->WaitForRequest(); + iframe_response->Send(kHttpResponseHeader); + iframe_response->Send(std::string(2000, ' ')); + iframe_response->Done(); + waiter->AddCompleteResourcesExpectation(3); + waiter->AddMinimumResourceBytesExpectation(4000); + waiter->Wait(); +}
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_observer.h b/chrome/browser/page_load_metrics/page_load_metrics_observer.h index ce97795a..9fb569c 100644 --- a/chrome/browser/page_load_metrics/page_load_metrics_observer.h +++ b/chrome/browser/page_load_metrics/page_load_metrics_observer.h
@@ -428,6 +428,12 @@ virtual void OnDataUseObserved(int64_t received_data_length, int64_t data_reduction_proxy_bytes_saved) {} + // Invoked when there is data use for loading a resource on the page + // acrosss all frames. This only contains resources that have had new + // data use since the last callback. + virtual void OnResourceDataUseObserved( + const std::vector<mojom::ResourceDataUpdatePtr>& resources) {} + // Invoked when a media element starts playing. virtual void MediaStartedPlaying( const content::WebContentsObserver::MediaPlayerInfo& video_type,
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_test_waiter.cc b/chrome/browser/page_load_metrics/page_load_metrics_test_waiter.cc index 23f1652..6a69dc5 100644 --- a/chrome/browser/page_load_metrics/page_load_metrics_test_waiter.cc +++ b/chrome/browser/page_load_metrics/page_load_metrics_test_waiter.cc
@@ -38,6 +38,16 @@ page_expected_fields_.Set(field); } +void PageLoadMetricsTestWaiter::AddCompleteResourcesExpectation( + int expected_num_complete_resources) { + expected_num_complete_resources_ = expected_num_complete_resources; +} + +void PageLoadMetricsTestWaiter::AddMinimumResourceBytesExpectation( + int expected_minimum_resource_bytes) { + expected_minimum_resource_bytes_ = expected_minimum_resource_bytes; +} + void PageLoadMetricsTestWaiter::AddMinimumPageLoadDataUseExpectation( int expected_minimum_page_load_data_use) { expected_minimum_page_load_data_use_ = expected_minimum_page_load_data_use; @@ -48,21 +58,21 @@ } void PageLoadMetricsTestWaiter::Wait() { - if (expectations_satisfied()) + if (ExpectationsSatisfied()) return; run_loop_ = std::make_unique<base::RunLoop>(); run_loop_->Run(); run_loop_ = nullptr; - EXPECT_TRUE(expectations_satisfied()); + EXPECT_TRUE(ExpectationsSatisfied()); } void PageLoadMetricsTestWaiter::OnTimingUpdated( content::RenderFrameHost* subframe_rfh, const page_load_metrics::mojom::PageLoadTiming& timing, const page_load_metrics::PageLoadExtraInfo& extra_info) { - if (expectations_satisfied()) + if (ExpectationsSatisfied()) return; const page_load_metrics::mojom::PageLoadMetadata& metadata = subframe_rfh ? extra_info.subframe_metadata @@ -74,14 +84,14 @@ page_expected_fields_.ClearMatching(matched_bits); observed_page_fields_.Merge(matched_bits); } - if (expectations_satisfied() && run_loop_) + if (ExpectationsSatisfied() && run_loop_) run_loop_->Quit(); } void PageLoadMetricsTestWaiter::OnLoadedResource( const page_load_metrics::ExtraRequestCompleteInfo& extra_request_complete_info) { - if (expectations_satisfied()) + if (ExpectationsSatisfied()) return; if (extra_request_complete_info.resource_type != @@ -97,7 +107,7 @@ observed_page_fields_.Set(TimingField::kLoadTimingInfo); } - if (expectations_satisfied() && run_loop_) + if (ExpectationsSatisfied() && run_loop_) run_loop_->Quit(); } @@ -105,7 +115,27 @@ int64_t received_data_length, int64_t data_reduction_proxy_bytes_saved) { current_page_load_data_use_ += received_data_length; - if (expectations_satisfied() && run_loop_) + if (ExpectationsSatisfied() && run_loop_) + run_loop_->Quit(); +} + +void PageLoadMetricsTestWaiter::OnResourceDataUseObserved( + const std::vector<page_load_metrics::mojom::ResourceDataUpdatePtr>& + resources) { + for (auto const& resource : resources) { + auto it = page_resources_.find(resource->request_id); + if (it != page_resources_.end()) { + it->second = resource.get(); + } else { + page_resources_.emplace(std::piecewise_construct, + std::forward_as_tuple(resource->request_id), + std::forward_as_tuple(resource.get())); + } + if (resource->is_complete) + current_complete_resources_++; + current_resource_bytes_ += resource->delta_bytes; + } + if (ExpectationsSatisfied() && run_loop_) run_loop_->Quit(); } @@ -166,12 +196,23 @@ did_add_observer_ = true; } -bool PageLoadMetricsTestWaiter::expectations_satisfied() const { - return subframe_expected_fields_.Empty() && page_expected_fields_.Empty() && - (expected_minimum_page_load_data_use_ == 0 || +bool PageLoadMetricsTestWaiter::ResourceUseExpectationsSatisfied() const { + return (expected_num_complete_resources_ == 0 || + current_complete_resources_ == expected_num_complete_resources_) && + (expected_minimum_resource_bytes_ == 0 || + current_resource_bytes_ >= expected_minimum_resource_bytes_); +} + +bool PageLoadMetricsTestWaiter::DataUseExpectationsSatisfied() const { + return (expected_minimum_page_load_data_use_ == 0 || current_page_load_data_use_ >= expected_minimum_page_load_data_use_); } +bool PageLoadMetricsTestWaiter::ExpectationsSatisfied() const { + return subframe_expected_fields_.Empty() && page_expected_fields_.Empty() && + DataUseExpectationsSatisfied() && ResourceUseExpectationsSatisfied(); +} + PageLoadMetricsTestWaiter::WaiterMetricsObserver::~WaiterMetricsObserver() {} PageLoadMetricsTestWaiter::WaiterMetricsObserver::WaiterMetricsObserver( @@ -202,4 +243,12 @@ } } +void PageLoadMetricsTestWaiter::WaiterMetricsObserver:: + OnResourceDataUseObserved( + const std::vector<page_load_metrics::mojom::ResourceDataUpdatePtr>& + resources) { + if (waiter_) + waiter_->OnResourceDataUseObserved(resources); +} + } // namespace page_load_metrics
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_test_waiter.h b/chrome/browser/page_load_metrics/page_load_metrics_test_waiter.h index c206f419..17ece08 100644 --- a/chrome/browser/page_load_metrics/page_load_metrics_test_waiter.h +++ b/chrome/browser/page_load_metrics/page_load_metrics_test_waiter.h
@@ -40,6 +40,12 @@ // Add a subframe-level expectation. void AddSubFrameExpectation(TimingField field); + // Add completed resource expectation + void AddCompleteResourcesExpectation(int expected_minimum_complete_resources); + + // Add aggregate received resource bytes expectation + void AddMinimumResourceBytesExpectation(int expected_minimum_resource_bytes); + // Add a data use expectation void AddMinimumPageLoadDataUseExpectation( int expected_minimum_page_load_data_use); @@ -56,6 +62,8 @@ return current_page_load_data_use_; } + int64_t current_resource_bytes() const { return current_resource_bytes_; } + private: // PageLoadMetricsObserver used by the PageLoadMetricsTestWaiter to observe // metrics updates. @@ -79,6 +87,10 @@ void OnDataUseObserved(int64_t received_data_length, int64_t data_reduction_proxy_bytes_saved) override; + void OnResourceDataUseObserved( + const std::vector<page_load_metrics::mojom::ResourceDataUpdatePtr>& + resources) override; + private: const base::WeakPtr<PageLoadMetricsTestWaiter> waiter_; }; @@ -139,11 +151,22 @@ void OnDataUseObserved(int64_t received_data_length, int64_t data_reduction_proxy_bytes_saved); + // Updates resource map and associated data counters as updates are received + // from a resource load. Stops waiting if expectations are satisfied after + // update. + void OnResourceDataUseObserved( + const std::vector<page_load_metrics::mojom::ResourceDataUpdatePtr>& + resources); + void OnTrackerCreated(page_load_metrics::PageLoadTracker* tracker) override; void OnCommit(page_load_metrics::PageLoadTracker* tracker) override; - bool expectations_satisfied() const; + bool ResourceUseExpectationsSatisfied() const; + + bool DataUseExpectationsSatisfied() const; + + virtual bool ExpectationsSatisfied() const; std::unique_ptr<base::RunLoop> run_loop_; @@ -154,10 +177,19 @@ int64_t expected_minimum_page_load_data_use_ = 0; int64_t current_page_load_data_use_ = 0; + int current_complete_resources_ = 0; + int64_t current_resource_bytes_ = 0; + int expected_num_complete_resources_ = 0; + int expected_minimum_resource_bytes_ = 0; bool attach_on_tracker_creation_ = false; bool did_add_observer_ = false; + // Map of all resources loaded by the page, keyed by resource request id. + // Contains ongoing and completed resources. Contains only the most recent + // update (version) of the resource. + std::map<int, page_load_metrics::mojom::ResourceDataUpdate*> page_resources_; + base::WeakPtrFactory<PageLoadMetricsTestWaiter> weak_factory_; };
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.cc b/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.cc index 91be0e2..32ac745 100644 --- a/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.cc +++ b/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.cc
@@ -431,7 +431,8 @@ const mojom::PageLoadTiming& new_timing, const mojom::PageLoadMetadata& new_metadata, const mojom::PageLoadFeatures& new_features, - const mojom::PageLoadDataUse& new_data_use) { + const mojom::PageLoadDataUse& new_data_use, + const std::vector<mojom::ResourceDataUpdatePtr>& resources) { if (render_frame_host->GetLastCommittedURL().SchemeIs( extensions::kExtensionScheme)) { // Extensions can inject child frames into a page. We don't want to track @@ -442,6 +443,7 @@ // Report data usage before new timing and metadata for messages that have // both updates. client_->UpdateDataUse(new_data_use); + client_->UpdateResourceDataUse(resources); if (render_frame_host->GetParent() == nullptr) { UpdateMainFrameMetadata(new_metadata); UpdateMainFrameTiming(new_timing);
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.h b/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.h index 70728700..ee61a70e 100644 --- a/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.h +++ b/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.h
@@ -110,6 +110,8 @@ virtual void UpdateFeaturesUsage( const mojom::PageLoadFeatures& new_features) = 0; virtual void UpdateDataUse(const mojom::PageLoadDataUse& new_data_use) = 0; + virtual void UpdateResourceDataUse( + const std::vector<mojom::ResourceDataUpdatePtr>& resources) = 0; }; // The |client| instance must outlive this object. @@ -119,11 +121,13 @@ PageLoadMetricsEmbedderInterface* embedder_interface); ~PageLoadMetricsUpdateDispatcher(); - void UpdateMetrics(content::RenderFrameHost* render_frame_host, - const mojom::PageLoadTiming& new_timing, - const mojom::PageLoadMetadata& new_metadata, - const mojom::PageLoadFeatures& new_features, - const mojom::PageLoadDataUse& new_data_use); + void UpdateMetrics( + content::RenderFrameHost* render_frame_host, + const mojom::PageLoadTiming& new_timing, + const mojom::PageLoadMetadata& new_metadata, + const mojom::PageLoadFeatures& new_features, + const mojom::PageLoadDataUse& new_data_use, + const std::vector<mojom::ResourceDataUpdatePtr>& resources); // This method is only intended to be called for PageLoadFeatures being // recorded directly from the browser process. Features coming from the
diff --git a/chrome/browser/page_load_metrics/page_load_tracker.cc b/chrome/browser/page_load_metrics/page_load_tracker.cc index eedce78..2d020269 100644 --- a/chrome/browser/page_load_metrics/page_load_tracker.cc +++ b/chrome/browser/page_load_metrics/page_load_tracker.cc
@@ -651,4 +651,11 @@ } } +void PageLoadTracker::UpdateResourceDataUse( + const std::vector<mojom::ResourceDataUpdatePtr>& resources) { + for (const auto& observer : observers_) { + observer->OnResourceDataUseObserved(resources); + } +} + } // namespace page_load_metrics
diff --git a/chrome/browser/page_load_metrics/page_load_tracker.h b/chrome/browser/page_load_metrics/page_load_tracker.h index 4c52200..00f956bb 100644 --- a/chrome/browser/page_load_metrics/page_load_tracker.h +++ b/chrome/browser/page_load_metrics/page_load_tracker.h
@@ -181,6 +181,8 @@ void UpdateFeaturesUsage( const mojom::PageLoadFeatures& new_features) override; void UpdateDataUse(const mojom::PageLoadDataUse& new_datause) override; + void UpdateResourceDataUse( + const std::vector<mojom::ResourceDataUpdatePtr>& resources) override; void Redirect(content::NavigationHandle* navigation_handle); void WillProcessNavigationResponse(
diff --git a/chrome/browser/prefs/pref_service_incognito_whitelist.cc b/chrome/browser/prefs/pref_service_incognito_whitelist.cc index df1b7a9..cd6bbcb 100644 --- a/chrome/browser/prefs/pref_service_incognito_whitelist.cc +++ b/chrome/browser/prefs/pref_service_incognito_whitelist.cc
@@ -684,11 +684,6 @@ #endif // defined(GOOGLE_CHROME_BUILD) #endif // defined(OS_WIN) - prefs::kSettingsResetPromptPromptWave, - prefs::kSettingsResetPromptLastTriggeredForDefaultSearch, - prefs::kSettingsResetPromptLastTriggeredForStartupUrls, - prefs::kSettingsResetPromptLastTriggeredForHomepage, - #if defined(OS_ANDROID) prefs::kClipboardLastModifiedTime, #endif
diff --git a/chrome/browser/previews/previews_infobar_delegate.cc b/chrome/browser/previews/previews_infobar_delegate.cc index 1cfcd42..e305c38 100644 --- a/chrome/browser/previews/previews_infobar_delegate.cc +++ b/chrome/browser/previews/previews_infobar_delegate.cc
@@ -115,7 +115,7 @@ base::Time previews_freshness, bool is_data_saver_user, bool is_reload, - OnDismissPreviewsInfobarCallback on_dismiss_callback, + OnDismissPreviewsUICallback on_dismiss_callback, previews::PreviewsUIService* previews_ui_service) { PreviewsUITabHelper* ui_tab_helper = PreviewsUITabHelper::FromWebContents(web_contents); @@ -167,7 +167,7 @@ base::Time previews_freshness, bool is_data_saver_user, bool is_reload, - OnDismissPreviewsInfobarCallback on_dismiss_callback) + OnDismissPreviewsUICallback on_dismiss_callback) : ConfirmInfoBarDelegate(), ui_tab_helper_(ui_tab_helper), previews_type_(previews_type),
diff --git a/chrome/browser/previews/previews_infobar_delegate.h b/chrome/browser/previews/previews_infobar_delegate.h index 99f7bdb0..23f40fb 100644 --- a/chrome/browser/previews/previews_infobar_delegate.h +++ b/chrome/browser/previews/previews_infobar_delegate.h
@@ -5,9 +5,9 @@ #ifndef CHROME_BROWSER_PREVIEWS_PREVIEWS_INFOBAR_DELEGATE_H_ #define CHROME_BROWSER_PREVIEWS_PREVIEWS_INFOBAR_DELEGATE_H_ -#include "base/callback.h" #include "base/strings/string16.h" #include "base/time/time.h" +#include "chrome/browser/previews/previews_ui_tab_helper.h" #include "components/infobars/core/confirm_infobar_delegate.h" #include "components/previews/core/previews_experiments.h" @@ -27,9 +27,6 @@ // infobar. class PreviewsInfoBarDelegate : public ConfirmInfoBarDelegate { public: - typedef base::OnceCallback<void(bool opt_out)> - OnDismissPreviewsInfobarCallback; - // Actions on the previews infobar. This enum must remain synchronized with // the enum of the same name in metrics/histograms/histograms.xml. enum PreviewsInfoBarAction { @@ -59,16 +56,13 @@ // Creates a preview infobar and corresponding delegate and adds the infobar // to InfoBarService. |on_dismiss_callback| is called when the InfoBar is // dismissed. - static void Create( - content::WebContents* web_contents, - previews::PreviewsType previews_type, - base::Time previews_freshness, - bool is_data_saver_user, - bool is_reload, - // TODO(ryansturm): Replace |on_dismiss_callback| with direct call to - // |previews_ui_service|. - OnDismissPreviewsInfobarCallback on_dismiss_callback, - previews::PreviewsUIService* previews_ui_service); + static void Create(content::WebContents* web_contents, + previews::PreviewsType previews_type, + base::Time previews_freshness, + bool is_data_saver_user, + bool is_reload, + OnDismissPreviewsUICallback on_dismiss_callback, + previews::PreviewsUIService* previews_ui_service); // ConfirmInfoBarDelegate overrides: int GetIconId() const override; @@ -86,7 +80,7 @@ base::Time previews_freshness, bool is_data_saver_user, bool is_reload, - OnDismissPreviewsInfobarCallback on_dismiss_callback); + OnDismissPreviewsUICallback on_dismiss_callback); // ConfirmInfoBarDelegate overrides: infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override; @@ -105,7 +99,7 @@ const base::string16 message_text_; - OnDismissPreviewsInfobarCallback on_dismiss_callback_; + OnDismissPreviewsUICallback on_dismiss_callback_; DISALLOW_COPY_AND_ASSIGN(PreviewsInfoBarDelegate); };
diff --git a/chrome/browser/previews/previews_infobar_delegate_unittest.cc b/chrome/browser/previews/previews_infobar_delegate_unittest.cc index 1e844ec14..b79f6667 100644 --- a/chrome/browser/previews/previews_infobar_delegate_unittest.cc +++ b/chrome/browser/previews/previews_infobar_delegate_unittest.cc
@@ -320,8 +320,7 @@ PreviewsInfoBarDelegate::Create( web_contents(), previews::PreviewsType::LOFI, base::Time() /* previews_freshness */, true /* is_data_saver_user */, - false /* is_reload */, - PreviewsInfoBarDelegate::OnDismissPreviewsInfobarCallback(), + false /* is_reload */, OnDismissPreviewsUICallback(), previews_ui_service_.get()); EXPECT_EQ(1U, infobar_service()->infobar_count()); @@ -348,8 +347,7 @@ PreviewsInfoBarDelegate::Create( web_contents(), previews::PreviewsType::LOFI, base::Time() /* previews_freshness */, true /* is_data_saver_user */, - false /* is_reload */, - PreviewsInfoBarDelegate::OnDismissPreviewsInfobarCallback(), + false /* is_reload */, OnDismissPreviewsUICallback(), previews_ui_service_.get()); EXPECT_EQ(1U, infobar_service()->infobar_count()); @@ -478,8 +476,7 @@ PreviewsInfoBarDelegate::Create( web_contents(), previews::PreviewsType::LOFI, base::Time() /* previews_freshness */, true /* is_data_saver_user */, - false /* is_reload */, - PreviewsInfoBarDelegate::OnDismissPreviewsInfobarCallback(), + false /* is_reload */, OnDismissPreviewsUICallback(), previews_ui_service_.get()); // Infobar should not be shown again since a navigation hasn't happened.
diff --git a/chrome/browser/previews/previews_ui_tab_helper.cc b/chrome/browser/previews/previews_ui_tab_helper.cc index 1c63309..62c6405 100644 --- a/chrome/browser/previews/previews_ui_tab_helper.cc +++ b/chrome/browser/previews/previews_ui_tab_helper.cc
@@ -53,6 +53,23 @@ PreviewsUITabHelper::~PreviewsUITabHelper() {} +void PreviewsUITabHelper::ShowUIElement( + previews::PreviewsType previews_type, + base::Time previews_freshness, + bool is_data_saver_user, + bool is_reload, + OnDismissPreviewsUICallback on_dismiss_callback) { + // Retrieve PreviewsUIService* from |web_contents| if available. + PreviewsService* previews_service = PreviewsServiceFactory::GetForProfile( + Profile::FromBrowserContext(web_contents()->GetBrowserContext())); + previews::PreviewsUIService* previews_ui_service = + previews_service ? previews_service->previews_ui_service() : nullptr; + + PreviewsInfoBarDelegate::Create( + web_contents(), previews_type, previews_freshness, is_data_saver_user, + is_reload, std::move(on_dismiss_callback), previews_ui_service); +} + PreviewsUITabHelper::PreviewsUITabHelper(content::WebContents* web_contents) : content::WebContentsObserver(web_contents), displayed_preview_ui_(false), @@ -86,12 +103,6 @@ displayed_preview_ui_ = false; displayed_preview_timestamp_ = false; - // Retrieve PreviewsUIService* from |web_contents| if available. - PreviewsService* previews_service = PreviewsServiceFactory::GetForProfile( - Profile::FromBrowserContext(web_contents()->GetBrowserContext())); - previews::PreviewsUIService* previews_ui_service = - previews_service ? previews_service->previews_ui_service() : nullptr; - #if BUILDFLAG(ENABLE_OFFLINE_PAGES) offline_pages::OfflinePageTabHelper* tab_helper = offline_pages::OfflinePageTabHelper::FromWebContents(web_contents()); @@ -128,16 +139,15 @@ true, data_use_measurement::DataUseUserData::OTHER, 0); - PreviewsInfoBarDelegate::Create( - web_contents(), previews::PreviewsType::OFFLINE, - base::Time() /* previews_freshness */, + PreviewsUITabHelper::ShowUIElement( + previews::PreviewsType::OFFLINE, base::Time() /* previews_freshness */, data_reduction_proxy_settings && data_saver_enabled, false /* is_reload */, base::BindOnce(&AddPreviewNavigationCallback, web_contents()->GetBrowserContext(), navigation_handle->GetRedirectChain()[0], - previews::PreviewsType::OFFLINE, page_id), - previews_ui_service); + previews::PreviewsType::OFFLINE, page_id)); + // Don't try to show other UIs if this is an offline preview. return; } @@ -157,14 +167,13 @@ headers->GetDateValue(&previews_freshness); } - PreviewsInfoBarDelegate::Create( - web_contents(), main_frame_preview, previews_freshness, - true /* is_data_saver_user */, is_reload, + PreviewsUITabHelper::ShowUIElement( + main_frame_preview, previews_freshness, true /* is_data_saver_user */, + is_reload, base::BindOnce(&AddPreviewNavigationCallback, web_contents()->GetBrowserContext(), navigation_handle->GetRedirectChain()[0], - main_frame_preview, page_id), - previews_ui_service); + main_frame_preview, page_id)); } } }
diff --git a/chrome/browser/previews/previews_ui_tab_helper.h b/chrome/browser/previews/previews_ui_tab_helper.h index 2143bf9..bbec8027d 100644 --- a/chrome/browser/previews/previews_ui_tab_helper.h +++ b/chrome/browser/previews/previews_ui_tab_helper.h
@@ -5,12 +5,17 @@ #ifndef CHROME_BROWSER_PREVIEWS_PREVIEWS_UI_TAB_HELPER_H_ #define CHROME_BROWSER_PREVIEWS_PREVIEWS_UI_TAB_HELPER_H_ +#include "base/callback.h" #include "base/macros.h" #include "base/optional.h" +#include "base/time/time.h" +#include "components/previews/core/previews_experiments.h" #include "components/previews/core/previews_user_data.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" +typedef base::OnceCallback<void(bool opt_out)> OnDismissPreviewsUICallback; + // Tracks whether a previews UI has been shown for a page. Handles showing // the UI when the main frame response indicates a Lite Page. class PreviewsUITabHelper @@ -19,6 +24,13 @@ public: ~PreviewsUITabHelper() override; + // Trigger the Previews UI to be shown to the user. + void ShowUIElement(previews::PreviewsType previews_type, + base::Time previews_freshness, + bool is_data_saver_user, + bool is_reload, + OnDismissPreviewsUICallback on_dismiss_callback); + // Indicates whether the UI for a preview has been shown for the page. bool displayed_preview_ui() const { return displayed_preview_ui_; }
diff --git a/chrome/browser/printing/cloud_print/privet_notifications.cc b/chrome/browser/printing/cloud_print/privet_notifications.cc index 0a63a3d..3ff101b 100644 --- a/chrome/browser/printing/cloud_print/privet_notifications.cc +++ b/chrome/browser/printing/cloud_print/privet_notifications.cc
@@ -338,9 +338,8 @@ } else if (*enable_privet_notification_member_) { ReportPrivetUmaEvent(PRIVET_SERVICE_STARTED); traffic_detector_ = base::MakeRefCounted<PrivetTrafficDetector>( - net::ADDRESS_FAMILY_IPV4, profile_, - base::BindRepeating(&PrivetNotificationService::StartLister, - AsWeakPtr())); + profile_, base::BindRepeating(&PrivetNotificationService::StartLister, + AsWeakPtr())); traffic_detector_->Start(); } else { device_lister_.reset();
diff --git a/chrome/browser/printing/cloud_print/privet_traffic_detector.cc b/chrome/browser/printing/cloud_print/privet_traffic_detector.cc index 5176dad..18959f8 100644 --- a/chrome/browser/printing/cloud_print/privet_traffic_detector.cc +++ b/chrome/browser/printing/cloud_print/privet_traffic_detector.cc
@@ -4,10 +4,8 @@ #include "chrome/browser/printing/cloud_print/privet_traffic_detector.h" -#include <stddef.h> +#include <utility> -#include "base/location.h" -#include "base/macros.h" #include "base/metrics/histogram_macros.h" #include "base/single_thread_task_runner.h" #include "base/sys_byteorder.h" @@ -17,8 +15,8 @@ #include "content/public/browser/browser_context.h" #include "content/public/browser/network_service_instance.h" #include "content/public/browser/storage_partition.h" +#include "net/base/address_family.h" #include "net/base/ip_address.h" -#include "net/base/net_errors.h" #include "net/base/network_interfaces.h" #include "net/dns/dns_protocol.h" #include "net/dns/mdns_client.h" @@ -26,22 +24,20 @@ namespace { const int kMaxRestartAttempts = 10; -const char kPrivetDeviceTypeDnsString[] = "\x07_privet"; void GetNetworkListInBackground( - const base::Callback<void(const net::NetworkInterfaceList&)> callback) { + base::OnceCallback<void(net::NetworkInterfaceList)> callback) { base::AssertBlockingAllowed(); net::NetworkInterfaceList networks; if (!GetNetworkList(&networks, net::INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES)) return; net::NetworkInterfaceList ip4_networks; - for (size_t i = 0; i < networks.size(); ++i) { - net::AddressFamily address_family = - net::GetAddressFamily(networks[i].address); + for (const auto& network : networks) { + net::AddressFamily address_family = net::GetAddressFamily(network.address); if (address_family == net::ADDRESS_FAMILY_IPV4 && - networks[i].prefix_length >= 24) { - ip4_networks.push_back(networks[i]); + network.prefix_length >= 24) { + ip4_networks.push_back(network); } } @@ -54,8 +50,20 @@ localhost_prefix, 8, net::IP_ADDRESS_ATTRIBUTE_NONE)); - content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, - base::BindOnce(callback, ip4_networks)); + content::BrowserThread::PostTask( + content::BrowserThread::IO, FROM_HERE, + base::BindOnce(std::move(callback), std::move(ip4_networks))); +} + +void CreateUDPSocketOnUIThread( + content::BrowserContext* profile, + network::mojom::UDPSocketRequest request, + network::mojom::UDPSocketReceiverPtr receiver_ptr) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + network::mojom::NetworkContext* network_context = + content::BrowserContext::GetDefaultStoragePartition(profile) + ->GetNetworkContext(); + network_context->CreateUDPSocket(std::move(request), std::move(receiver_ptr)); } } // namespace @@ -63,16 +71,15 @@ namespace cloud_print { PrivetTrafficDetector::PrivetTrafficDetector( - net::AddressFamily address_family, content::BrowserContext* profile, - const base::Closure& on_traffic_detected) + const base::RepeatingClosure& on_traffic_detected) : on_traffic_detected_(on_traffic_detected), - callback_runner_(base::ThreadTaskRunnerHandle::Get()), - address_family_(address_family), restart_attempts_(kMaxRestartAttempts), receiver_binding_(this), profile_(profile), - weak_ptr_factory_(this) {} + weak_ptr_factory_(this) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); +} PrivetTrafficDetector::~PrivetTrafficDetector() { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); @@ -108,14 +115,14 @@ base::PostDelayedTaskWithTraits( FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()}, base::BindOnce(&GetNetworkListInBackground, - base::Bind(&PrivetTrafficDetector::Restart, - weak_ptr_factory_.GetWeakPtr())), + base::BindOnce(&PrivetTrafficDetector::Restart, + weak_ptr_factory_.GetWeakPtr())), base::TimeDelta::FromSeconds(3)); } -void PrivetTrafficDetector::Restart(const net::NetworkInterfaceList& networks) { +void PrivetTrafficDetector::Restart(net::NetworkInterfaceList networks) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - networks_ = networks; + networks_ = std::move(networks); Bind(); } @@ -133,10 +140,11 @@ receiver_binding_.Bind(std::move(receiver_request)); content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, - base::BindOnce(&PrivetTrafficDetector::CreateUDPSocketOnUIThread, this, + base::BindOnce(&CreateUDPSocketOnUIThread, profile_, mojo::MakeRequest(&socket_), std::move(receiver_ptr))); - net::IPEndPoint multicast_addr = net::GetMDnsIPEndPoint(address_family_); + net::IPEndPoint multicast_addr = + net::GetMDnsIPEndPoint(net::ADDRESS_FAMILY_IPV4); net::IPEndPoint bind_endpoint( net::IPAddress::AllZeros(multicast_addr.address().size()), multicast_addr.port()); @@ -151,35 +159,27 @@ multicast_addr)); } -void PrivetTrafficDetector::CreateUDPSocketOnUIThread( - network::mojom::UDPSocketRequest request, - network::mojom::UDPSocketReceiverPtr receiver_ptr) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - network::mojom::NetworkContext* network_context = - content::BrowserContext::GetDefaultStoragePartition(profile_) - ->GetNetworkContext(); - network_context->CreateUDPSocket(std::move(request), std::move(receiver_ptr)); -} - void PrivetTrafficDetector::OnBindComplete( net::IPEndPoint multicast_addr, int rv, const base::Optional<net::IPEndPoint>& ip_endpoint) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - if (rv != net::OK) { - if ((restart_attempts_--) > 0) - ScheduleRestart(); - } else { + if (rv == net::OK) { socket_->JoinGroup( multicast_addr.address(), base::BindOnce(&PrivetTrafficDetector::OnJoinGroupComplete, this)); + return; } + + if (restart_attempts_-- > 0) + ScheduleRestart(); } bool PrivetTrafficDetector::IsSourceAcceptable() const { - for (size_t i = 0; i < networks_.size(); ++i) { - if (net::IPAddressMatchesPrefix(recv_addr_.address(), networks_[i].address, - networks_[i].prefix_length)) { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + for (const auto& network : networks_) { + if (net::IPAddressMatchesPrefix(recv_addr_.address(), network.address, + network.prefix_length)) { return true; } } @@ -188,6 +188,7 @@ bool PrivetTrafficDetector::IsPrivetPacket( base::span<const uint8_t> data) const { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); if (data.size() <= sizeof(net::dns_protocol::Header) || !IsSourceAcceptable()) { return false; @@ -200,6 +201,8 @@ // Check if response packet. if (!(header->flags & base::HostToNet16(net::dns_protocol::kFlagResponse))) return false; + + static const char kPrivetDeviceTypeDnsString[] = "\x07_privet"; const char* substring_begin = kPrivetDeviceTypeDnsString; const char* substring_end = substring_begin + arraysize(kPrivetDeviceTypeDnsString) - 1; @@ -210,14 +213,15 @@ void PrivetTrafficDetector::OnJoinGroupComplete(int rv) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - if (rv != net::OK) { - if ((restart_attempts_--) > 0) - ScheduleRestart(); - } else { + if (rv == net::OK) { // Reset on success. restart_attempts_ = kMaxRestartAttempts; socket_->ReceiveMoreWithBufferSize(1, net::dns_protocol::kMaxMulticastSize); + return; } + + if (restart_attempts_-- > 0) + ScheduleRestart(); } void PrivetTrafficDetector::ResetConnection() { @@ -248,7 +252,8 @@ recv_addr_ = src_addr.value(); if (IsPrivetPacket(data.value())) { ResetConnection(); - callback_runner_->PostTask(FROM_HERE, on_traffic_detected_); + content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, + on_traffic_detected_); base::TimeDelta time_delta = base::Time::Now() - start_time_; UMA_HISTOGRAM_LONG_TIMES("LocalDiscovery.DetectorTriggerTime", time_delta); } else {
diff --git a/chrome/browser/printing/cloud_print/privet_traffic_detector.h b/chrome/browser/printing/cloud_print/privet_traffic_detector.h index f8153442..e749a0de 100644 --- a/chrome/browser/printing/cloud_print/privet_traffic_detector.h +++ b/chrome/browser/printing/cloud_print/privet_traffic_detector.h
@@ -8,11 +8,9 @@ #include <memory> #include "base/callback.h" -#include "base/cancelable_callback.h" #include "base/macros.h" #include "content/public/browser/browser_thread.h" #include "mojo/public/cpp/bindings/binding.h" -#include "net/base/address_family.h" #include "net/base/ip_endpoint.h" #include "services/network/public/cpp/network_connection_tracker.h" #include "services/network/public/mojom/udp_socket.mojom.h" @@ -23,10 +21,13 @@ namespace cloud_print { -// Detects mDns traffic that looks like "Privet" protocol. -// Can produce false positives results, but main task of the class is to avoid -// running full mDns listener if user doesn't have devices. -// When traffic is detected, class fires callback and shutdowns itself. +// Detects mDns traffic that looks like the "Privet" protocol. This can produce +// false positives results, but the main task of the class is to avoid running a +// full mDns listener if user doesn't have devices. +// When potential "Privet" traffic has been detected, fire a callback and stop +// listening for traffic. +// When the network changes, restarts itself to start listening for traffic +// again on the new network(s). class PrivetTrafficDetector : public base::RefCountedThreadSafe< PrivetTrafficDetector, @@ -34,10 +35,11 @@ private network::NetworkConnectionTracker::NetworkConnectionObserver, public network::mojom::UDPSocketReceiver { public: - PrivetTrafficDetector(net::AddressFamily address_family, - content::BrowserContext* profile, - const base::Closure& on_traffic_detected); + // Called on the UI thread. + PrivetTrafficDetector(content::BrowserContext* profile, + const base::RepeatingClosure& on_traffic_detected); + // Called on the UI thread. void Start(); void Stop(); @@ -45,17 +47,14 @@ friend struct content::BrowserThread::DeleteOnThread< content::BrowserThread::IO>; friend class base::DeleteHelper<PrivetTrafficDetector>; + ~PrivetTrafficDetector() override; + // Unless otherwise noted, all methods are called on the IO thread. void HandleConnectionChanged(network::mojom::ConnectionType type); - - void StartOnIOThread(); void ScheduleRestart(); - void Restart(const net::NetworkInterfaceList& networks); + void Restart(net::NetworkInterfaceList networks); void Bind(); - void CreateUDPSocketOnUIThread( - network::mojom::UDPSocketRequest request, - network::mojom::UDPSocketReceiverPtr receiver_ptr); void OnBindComplete(net::IPEndPoint multicast_addr, int rv, const base::Optional<net::IPEndPoint>& ip_address); @@ -65,6 +64,7 @@ void ResetConnection(); // network::NetworkConnectionTracker::NetworkConnectionObserver: + // Called on the UI thread. void OnConnectionChanged(network::mojom::ConnectionType type) override; // network::mojom::UDPSocketReceiver implementation @@ -72,22 +72,22 @@ const base::Optional<net::IPEndPoint>& src_addr, base::Optional<base::span<const uint8_t>> data) override; - base::Closure on_traffic_detected_; - scoped_refptr<base::TaskRunner> callback_runner_; - net::NetworkInterfaceList networks_; - net::AddressFamily address_family_; - net::IPEndPoint recv_addr_; - base::Time start_time_; + // Initialized on the UI thread, but only accessed on the IO thread. + base::RepeatingClosure on_traffic_detected_; int restart_attempts_; - // Only accessed on the IO thread - + // Only accessed on the IO thread. + net::NetworkInterfaceList networks_; + net::IPEndPoint recv_addr_; + base::Time start_time_; network::mojom::UDPSocketPtr socket_; - // Implementation of socket receiver callback + + // Implementation of socket receiver callback. + // Initialized on the UI thread, but only accessed on the IO thread. mojo::Binding<network::mojom::UDPSocketReceiver> receiver_binding_; - // Only accessed on the UI thread - + // Initialized on the UI thread, but only accessed on the IO thread for the + // purpose of passing it back to the UI thread. Safe because it is const. content::BrowserContext* const profile_; base::WeakPtrFactory<PrivetTrafficDetector> weak_ptr_factory_;
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc index 9af4767..94eb633 100644 --- a/chrome/browser/profiles/profile_impl.cc +++ b/chrome/browser/profiles/profile_impl.cc
@@ -149,6 +149,8 @@ #include "chrome/browser/chromeos/device_sync/device_sync_client_factory.h" #include "chrome/browser/chromeos/locale_change_guard.h" #include "chrome/browser/chromeos/login/session/user_session_manager.h" +#include "chrome/browser/chromeos/multidevice_setup/auth_token_validator_factory.h" +#include "chrome/browser/chromeos/multidevice_setup/auth_token_validator_impl.h" #include "chrome/browser/chromeos/net/delay_network_call.h" #include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h" #include "chrome/browser/chromeos/policy/user_policy_manager_factory_chromeos.h" @@ -1524,7 +1526,9 @@ GetPrefs(), chromeos::device_sync::DeviceSyncClientFactory::GetForProfile(this), chromeos::secure_channel::SecureChannelClientProvider::GetInstance() - ->GetClient()); + ->GetClient(), + chromeos::multidevice_setup::AuthTokenValidatorFactory::GetForProfile( + this)); } #endif // defined(OS_CHROMEOS)
diff --git a/chrome/browser/resources/chromeos/switch_access/automation_manager.js b/chrome/browser/resources/chromeos/switch_access/automation_manager.js index 3d76554e..b7fe09a 100644 --- a/chrome/browser/resources/chromeos/switch_access/automation_manager.js +++ b/chrome/browser/resources/chromeos/switch_access/automation_manager.js
@@ -64,15 +64,9 @@ AutomationManager.prototype = { /** - * Set this.node_, this.root_, and this.desktop_ to the desktop node, and - * creates an initial tree walker. - * * @private */ init_: function() { - console.log('AutomationNode for desktop is loaded'); - this.printNode_(this.node_); - this.desktop_.addEventListener( chrome.automation.EventType.FOCUS, this.handleFocusChange_.bind(this), false); @@ -95,7 +89,6 @@ handleFocusChange_: function(event) { if (this.node_ === event.target) return; - console.log('Focus changed'); // Rebuild scope stack and set scope for focused node. this.buildScopeStack_(event.target); @@ -104,10 +97,9 @@ this.node_ = event.target; // In case the node that gained focus is not a subtreeLeaf. - if (SwitchAccessPredicate.isSubtreeLeaf(this.node_, this.scope_)) { - this.printNode_(this.node_); + if (SwitchAccessPredicate.isSubtreeLeaf(this.node_, this.scope_)) this.updateFocusRing_(); - } else + else this.moveForward(); }, @@ -163,7 +155,6 @@ if (!removedByRWA && treeChange.target !== this.node_) return; - console.log('Node removed'); chrome.accessibilityPrivate.setFocusRing([]); // Current node not invalid until after treeChange callback, so move to @@ -247,7 +238,6 @@ */ setCurrentNode_: function(node) { this.node_ = node; - this.printNode_(this.node_); this.updateFocusRing_(); }, @@ -258,7 +248,6 @@ this.node_ = this.scope_; this.visitingScopeAsActionable_ = true; - this.printNode_(this.node_); this.updateFocusRing_(AutomationManager.Color.LEAF); }, @@ -292,22 +281,17 @@ } while (!this.scope_.role && this.scopeStack_.length > 0); this.updateFocusRing_(); - console.log('Moved to previous scope'); - this.printNode_(this.node_); return; } if (SwitchAccessPredicate.isGroup(this.node_, this.scope_)) { this.scopeStack_.push(this.scope_); this.scope_ = this.node_; - console.log('Entered scope'); this.moveForward(); return; } this.node_.doDefault(); - console.log('Performed default action'); - console.log('\n'); }, /** @@ -341,7 +325,6 @@ startAtValidNode_: function() { if (this.node_.role) return; - console.log('Finding new valid node'); // Current node is invalid, but current scope is still valid, so set node // to the current scope.
diff --git a/chrome/browser/resources/chromeos/switch_access/keyboard_handler.js b/chrome/browser/resources/chromeos/switch_access/keyboard_handler.js index 23bf3f6e4c..d043e3b 100644 --- a/chrome/browser/resources/chromeos/switch_access/keyboard_handler.js +++ b/chrome/browser/resources/chromeos/switch_access/keyboard_handler.js
@@ -65,7 +65,6 @@ for (let command of this.switchAccess_.getCommands()) { if (this.keyCodeFor_(command) === event.keyCode) { let key = event.key.toUpperCase(); - console.log('\'' + key + '\' pressed for command: ' + command); this.switchAccess_.runCommand(command); this.switchAccess_.performedUserAction(); return;
diff --git a/chrome/browser/resources/chromeos/switch_access/switch_access_predicate.js b/chrome/browser/resources/chromeos/switch_access/switch_access_predicate.js index 319a2a8..0eacd4d 100644 --- a/chrome/browser/resources/chromeos/switch_access/switch_access_predicate.js +++ b/chrome/browser/resources/chromeos/switch_access/switch_access_predicate.js
@@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +let StateType = chrome.automation.StateType; +let RoleType = chrome.automation.RoleType; + /** * Class containing predicates for the chrome automation API. Each predicate * can be run on one or more AutomationNodes and returns a boolean value. @@ -61,7 +64,7 @@ */ SwitchAccessPredicate.visit = function(scope) { return function(node) { - return node.role !== chrome.automation.RoleType.DESKTOP && + return node.role !== RoleType.DESKTOP && SwitchAccessPredicate.isSubtreeLeaf(node, scope); }.bind(scope); }; @@ -98,8 +101,8 @@ // Work around for client nested in client. No need to have user select both // clients for a window. Once locations for outer client updates correctly, // this won't be needed. - if (node.role === chrome.automation.RoleType.CLIENT && - node.role === scope.role && node !== scope) + if (node.role === RoleType.CLIENT && node.role === scope.role && + node !== scope) return false; let interestingBranches = 0; @@ -154,28 +157,22 @@ let role = node.role; let state = node.state; - // TODO(elichtenberg): Define shorthand for chrome.automation.RoleType and - // StateType. - // Skip things that are offscreen - if (state[chrome.automation.StateType.OFFSCREEN] || loc.top < 0 || - loc.left < 0) + if (state[StateType.OFFSCREEN] || loc.top < 0 || loc.left < 0) return false; // Should just leave these as groups - if (role === chrome.automation.RoleType.WEB_VIEW || - role === chrome.automation.RoleType.ROOT_WEB_AREA) + if (role === RoleType.WEB_VIEW || role === RoleType.ROOT_WEB_AREA) return false; if (parent) { // crbug.com/710559 // Work around for browser tabs - if (role === chrome.automation.RoleType.TAB && - parent.role === chrome.automation.RoleType.TAB_LIST && - root.role === chrome.automation.RoleType.DESKTOP) + if (role === RoleType.TAB && parent.role === RoleType.TAB_LIST && + root.role === RoleType.DESKTOP) return true; } // The general rule that applies to everything. - return state[chrome.automation.StateType.FOCUSABLE] === true; + return state[StateType.FOCUSABLE]; };
diff --git a/chrome/browser/resources/local_ntp/local_ntp.html b/chrome/browser/resources/local_ntp/local_ntp.html index 489280c..8d8286b3 100644 --- a/chrome/browser/resources/local_ntp/local_ntp.html +++ b/chrome/browser/resources/local_ntp/local_ntp.html
@@ -79,7 +79,7 @@ <div id="attribution"><div id="attribution-text"></div></div> <div id="edit-bg" tabindex="0" hidden> - <button id="edit-bg-gear" tabindex="-1"></button> + <div id="edit-bg-gear" tabindex="-1" role="button"></div> </div> <div id="message-box-container" class="message-box-hide">
diff --git a/chrome/browser/resources/print_preview/new/preview_area.js b/chrome/browser/resources/print_preview/new/preview_area.js index 98fb39c0..161ba287 100644 --- a/chrome/browser/resources/print_preview/new/preview_area.js +++ b/chrome/browser/resources/print_preview/new/preview_area.js
@@ -503,18 +503,15 @@ // We only care about: PageUp, PageDown, Left, Up, Right, Down. // If the user is holding a modifier key, ignore. if (!this.pluginProxy_.pluginReady() || - !arrayContains( - [ - 'PageUp', 'PageDown', 'ArrowLeft', 'ArrowRight', 'ArrowUp', - 'ArrowDown' - ], - e.code) || + !['PageUp', 'PageDown', 'ArrowLeft', 'ArrowRight', 'ArrowUp', + 'ArrowDown'] + .includes(e.code) || hasKeyModifiers(e)) { return; } // Don't handle the key event for these elements. - const tagName = e.path[0].tagName; + const tagName = e.composedPath()[0].tagName; if (['INPUT', 'SELECT', 'EMBED'].includes(tagName)) return; @@ -523,13 +520,13 @@ // element, and work up the DOM tree to see if any element has a // scrollbar. If there exists a scrollbar, do not handle the key event // here. - let element = e.target; - while (element) { - if (element.scrollHeight > element.clientHeight || - element.scrollWidth > element.clientWidth) { + const isEventHorizontal = ['ArrowLeft', 'ArrowRight'].includes(e.code); + for (let i = 0; i < e.composedPath().length; i++) { + const element = e.composedPath()[i]; + if (element.scrollHeight > element.clientHeight && !isEventHorizontal || + element.scrollWidth > element.clientWidth && isEventHorizontal) { return; } - element = element.parentElement; } // No scroll bar anywhere, or the active element is something else, like a
diff --git a/chrome/browser/resources/settings/multidevice_page/multidevice_constants.js b/chrome/browser/resources/settings/multidevice_page/multidevice_constants.js index a4928d7..b2f5470 100644 --- a/chrome/browser/resources/settings/multidevice_page/multidevice_constants.js +++ b/chrome/browser/resources/settings/multidevice_page/multidevice_constants.js
@@ -19,70 +19,47 @@ }; /** - * MultiDevice software features. Note that this is copied from (and must - * include an analog of all values in) the enum of the same name in - * //components/cryptauth/proto/cryptauth_api.proto. + * Possible states of MultiDevice features. Note that this is copied from (and + * must include an analog of all values in) the FeatureState enum in + * //chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom. * @enum {number} */ - MultiDeviceSoftwareFeature = { - UNKNOWN_FEATURE: 0, - BETTER_TOGETHER_HOST: 1, - BETTER_TOGETHER_CLIENT: 2, - EASY_UNLOCK_HOST: 3, - EASY_UNLOCK_CLIENT: 4, - MAGIC_TETHER_HOST: 5, - MAGIC_TETHER_CLIENT: 6, - SMS_CONNECT_HOST: 7, - SMS_CONNECT_CLIENT: 8, - }; - - /** - * Possible states of MultiDevice software features. Note that this is based - * on (and must include an analog of all values in) the enum of the same name - * in //components/cryptauth/software_feature_state.h. - * @enum {number} - */ - MultiDeviceSoftwareFeatureState = { - NOT_SUPPORTED: 0, - SUPPORTED: 1, - ENABLED: 2, + MultiDeviceFeatureState = { + DISABLED_BY_POLICY: 0, + DISABLED_BY_USER: 1, + ENABLED_BY_USER: 2, + NOT_SUPPORTED_BY_CHROMEBOOK: 3, + NOT_SUPPORTED_BY_PHONE: 4, + UNAVAILABLE_NO_VERIFIED_HOST: 5, + UNAVAILABLE_INSUFFICIENT_SECURITY: 6, }; return { MultiDeviceSettingsMode: MultiDeviceSettingsMode, - MultiDeviceSoftwareFeature: MultiDeviceSoftwareFeature, - MultiDeviceSoftwareFeatureState: MultiDeviceSoftwareFeatureState, + MultiDeviceFeatureState: MultiDeviceFeatureState, }; }); /** - * Represents a multidevice host, i.e. a phone set by the user to connect to - * their Chromebook(s). The type is a subset of the RemoteDevice structure - * defined by CryptAuth (components/cryptauth/remote_device.h). It contains the - * host device's name (e.g. Pixel, Nexus 5) and the map softwareFeatures - * sending each MultiDevice feature to the host device's state with regards to - * that feature. - * - * @typedef {{ - * name: string, - * softwareFeatures: - * !Object<settings.MultiDeviceSoftwareFeature, - * settings.MultiDeviceSoftwareFeatureState> - * }} - */ -let RemoteDevice; - -/** * Container for the initial data that the page requires in order to display * the correct content. It is also used for receiving status updates during - * use. Note that the host may be verified (enabled or disabled), awaiting - * verification, or it may have failed setup because it was not able to connect - * to the server. If the property is null or undefined, then no host has been - * set up, although there may be potential hosts on the account. + * use. Note that the host device may be verified (enabled or disabled), + * awaiting verification, or it may have failed setup because it was not able + * to connect to the server. + * + * For each MultiDevice feature (including the "suite" feature, which acts as a + * gatekeeper for the others), the corresponding *State property is an enum + * containing the data necessary to display it. Note that hostDeviceName should + * be undefined if and only if no host has been set up, regardless of whether + * there are potential hosts on the account. * * @typedef {{ * mode: !settings.MultiDeviceSettingsMode, - * hostDevice: (RemoteDevice|undefined) + * hostDeviceName: (string|undefined), + * betterTogetherState: !settings.MultiDeviceFeatureState, + * instantTetheringState: !settings.MultiDeviceFeatureState, + * messagesState: !settings.MultiDeviceFeatureState, + * smartLockState: !settings.MultiDeviceFeatureState, * }} */ let MultiDevicePageContentData;
diff --git a/chrome/browser/resources/settings/multidevice_page/multidevice_page.html b/chrome/browser/resources/settings/multidevice_page/multidevice_page.html index cb2e46d..12d24756 100644 --- a/chrome/browser/resources/settings/multidevice_page/multidevice_page.html +++ b/chrome/browser/resources/settings/multidevice_page/multidevice_page.html
@@ -58,7 +58,7 @@ </neon-animatable> <template is="dom-if" route-path="/multidevice/features"> <settings-subpage associated-control="[[$$('#multidevice-item')]]" - page-title="[[pageContentData.hostDevice.name]]"> + page-title="[[pageContentData.hostDeviceName]]"> <settings-multidevice-subpage prefs="{{prefs}}" page-content-data="[[pageContentData]]"> </settings-multidevice-subpage>
diff --git a/chrome/browser/resources/settings/multidevice_page/multidevice_page.js b/chrome/browser/resources/settings/multidevice_page/multidevice_page.js index 97054e51..2f7f8be 100644 --- a/chrome/browser/resources/settings/multidevice_page/multidevice_page.js +++ b/chrome/browser/resources/settings/multidevice_page/multidevice_page.js
@@ -49,8 +49,7 @@ * @private */ getLabelText_: function() { - return !!this.pageContentData.hostDevice ? - this.pageContentData.hostDevice.name : + return this.pageContentData.hostDeviceName || this.i18n('multideviceSetupItemHeading'); },
diff --git a/chrome/browser/resources/settings/multidevice_page/multidevice_page_container.js b/chrome/browser/resources/settings/multidevice_page/multidevice_page_container.js index 87143142..87cb6087 100644 --- a/chrome/browser/resources/settings/multidevice_page/multidevice_page_container.js +++ b/chrome/browser/resources/settings/multidevice_page/multidevice_page_container.js
@@ -71,8 +71,8 @@ /** * If the new mode corresponds to no eligible host or unset potential hosts - * (i.e. NO_ELIGIBLE_HOSTS or NO_HOST_SET), then newHostDevice should be null - * or undefined. Otherwise it should be defined and non-null. + * (i.e. NO_ELIGIBLE_HOSTS or NO_HOST_SET), then newHostDeviceName should be + * falsy. Otherwise it should be truthy. * @param {!MultiDevicePageContentData} newData * @private */ @@ -81,7 +81,7 @@ settings.MultiDeviceSettingsMode.NO_ELIGIBLE_HOSTS, settings.MultiDeviceSettingsMode.NO_HOST_SET, ]; - return !newData.hostDevice == noHostModes.includes(newData.mode); + return !newData.hostDeviceName === noHostModes.includes(newData.mode); }, /**
diff --git a/chrome/browser/resources/settings/printing_page/BUILD.gn b/chrome/browser/resources/settings/printing_page/BUILD.gn index aeb05cf..5452ef3 100644 --- a/chrome/browser/resources/settings/printing_page/BUILD.gn +++ b/chrome/browser/resources/settings/printing_page/BUILD.gn
@@ -9,6 +9,7 @@ ":cloud_printers", ":cups_add_printer_dialog", ":cups_add_printer_dialog_elements", + ":cups_add_printer_dialog_util", ":cups_edit_printer_dialog", ":cups_printers", ":cups_printers_browser_proxy", @@ -40,6 +41,12 @@ ] } +js_library("cups_add_printer_dialog_util") { + deps = [ + "//ui/webui/resources/js:cr", + ] +} + js_library("cups_edit_printer_dialog") { deps = [ ":cups_set_manufacturer_model_behavior",
diff --git a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html index d8557cc9..b0c6432 100644 --- a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html +++ b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html
@@ -8,6 +8,7 @@ <link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner-lite.html"> <link rel="import" href="../i18n_setup.html"> <link rel="import" href="cups_add_printer_dialog_elements.html"> +<link rel="import" href="cups_add_printer_dialog_util.html"> <link rel="import" href="cups_printer_shared_css.html"> <link rel="import" href="cups_printers_browser_proxy.html"> <link rel="import" href="cups_set_manufacturer_model_behavior.html">
diff --git a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js index fc6d7f1..c882c08 100644 --- a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js +++ b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js
@@ -193,49 +193,13 @@ }, /** - * This function uses regular expressions to determine whether the provided - * printer address is valid. Address can be either an ipv4/6 address or a - * hostname followed by an optional port. - * NOTE: The regular expression for hostnames will allow hostnames that are - * over 255 characters. - * @param {String} name - * @param {String} address + * @param {string} name + * @param {string} address * @return {boolean} Whether the add printer button is enabled. * @private */ canAddPrinter_: function(name, address) { - if (!name || !address) - return false; - - const hostnamePrefix = '([a-z\\d]|[a-z\\d][a-z\\d\\-]{0,61}[a-z\\d])'; - - // Matches an arbitrary number of 'prefix patterns' which are separated by a - // dot. - const hostnameSuffix = `(\\.${hostnamePrefix})*`; - - // Matches an optional port at the end of the address. - const portNumber = '(:\\d+)?'; - - const ipv6Full = '(([a-f\\d]){1,4}(:(:)?([a-f\\d]){1,4}){1,7})'; - - // Special cases for addresses using a shorthand notation. - const ipv6Prefix = '(::([a-f\\d]){1,4})'; - const ipv6Suffix = '(([a-f\\d]){1,4}::)'; - const ipv6Combined = `(${ipv6Full}|${ipv6Prefix}|${ipv6Suffix})`; - const ipv6WithPort = `(\\[${ipv6Combined}\\]${portNumber})`; - - // Matches valid hostnames and ipv4 addresses. - const hostnameRegex = - new RegExp(`^${hostnamePrefix}${hostnameSuffix}${portNumber}$`, 'i'); - - // Matches valid ipv6 addresses. - const ipv6AddressRegex = - new RegExp(`^(${ipv6Combined}|${ipv6WithPort})$`, 'i'); - - const invalidIpv6Regex = new RegExp('.*::.*::.*'); - - return hostnameRegex.test(address) || - (ipv6AddressRegex.test(address) && !invalidIpv6Regex.test(address)); + return settings.printing.isNameAndAddressValid(name, address); }, }); @@ -271,7 +235,8 @@ * @private */ canAddPrinter_: function(ppdManufacturer, ppdModel, printerPPDPath) { - return !!((ppdManufacturer && ppdModel) || printerPPDPath); + return settings.printing.isPPDInfoValid( + ppdManufacturer, ppdModel, printerPPDPath); }, });
diff --git a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_util.html b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_util.html new file mode 100644 index 0000000..c7d68b6b --- /dev/null +++ b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_util.html
@@ -0,0 +1,2 @@ +<link rel="import" href="chrome://resources/html/cr.html"> +<script src="cups_add_printer_dialog_util.js"></script>
diff --git a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_util.js b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_util.js new file mode 100644 index 0000000..6cff6ec --- /dev/null +++ b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_util.js
@@ -0,0 +1,71 @@ +// 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. + +/** + * @fileoverview Utility functions that are used in Cups printer setup dialogs. + */ + +cr.define('settings.printing', function() { + /** + * Returns true if the printer's name and address is valid. This function + * uses regular expressions to determine whether the provided printer name + * and address are valid. Address can be either an ipv4/6 address or a + * hostname followed by an optional port. + * NOTE: The regular expression for hostnames will allow hostnames that are + * over 255 characters. + * @param {string} name + * @param {string} address + * @return {boolean} + */ + function isNameAndAddressValid(name, address) { + if (!name || !address) + return false; + + const hostnamePrefix = '([a-z\\d]|[a-z\\d][a-z\\d\\-]{0,61}[a-z\\d])'; + + // Matches an arbitrary number of 'prefix patterns' which are separated by a + // dot. + const hostnameSuffix = `(\\.${hostnamePrefix})*`; + + // Matches an optional port at the end of the address. + const portNumber = '(:\\d+)?'; + + const ipv6Full = '(([a-f\\d]){1,4}(:(:)?([a-f\\d]){1,4}){1,7})'; + + // Special cases for addresses using a shorthand notation. + const ipv6Prefix = '(::([a-f\\d]){1,4})'; + const ipv6Suffix = '(([a-f\\d]){1,4}::)'; + const ipv6Combined = `(${ipv6Full}|${ipv6Prefix}|${ipv6Suffix})`; + const ipv6WithPort = `(\\[${ipv6Combined}\\]${portNumber})`; + + // Matches valid hostnames and ipv4 addresses. + const hostnameRegex = + new RegExp(`^${hostnamePrefix}${hostnameSuffix}${portNumber}$`, 'i'); + + // Matches valid ipv6 addresses. + const ipv6AddressRegex = + new RegExp(`^(${ipv6Combined}|${ipv6WithPort})$`, 'i'); + + const invalidIpv6Regex = new RegExp('.*::.*::.*'); + + return hostnameRegex.test(address) || + (ipv6AddressRegex.test(address) && !invalidIpv6Regex.test(address)); + } + + /** + * Returns true if the printer's manufacturer and model or ppd path is valid. + * @param {string} manufacturer + * @param {string} model + * @param {string} ppdPath + * @return {boolean} + */ + function isPPDInfoValid(manufacturer, model, ppdPath) { + return !!((manufacturer && model) || ppdPath); + } + + return { + isNameAndAddressValid: isNameAndAddressValid, + isPPDInfoValid: isPPDInfoValid, + }; +});
diff --git a/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.html b/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.html index 31456eb6..c544bcf 100644 --- a/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.html +++ b/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.html
@@ -5,6 +5,7 @@ <link rel="import" href="chrome://resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> <link rel="import" href="cups_add_printer_dialog_elements.html"> +<link rel="import" href="cups_add_printer_dialog_util.html"> <link rel="import" href="cups_printer_shared_css.html"> <link rel="import" href="cups_printers_browser_proxy.html"> <link rel="import" href="cups_set_manufacturer_model_behavior.html"> @@ -116,7 +117,8 @@ on-click="onCancelTap_"> $i18n{cancel} </paper-button> - <paper-button class="action-button" on-click="onSaveTap_"> + <paper-button class="action-button" on-click="onSaveTap_" + disabled="[[!canSavePrinter_(activePrinter.*)]]"> $i18n{editPrinterButtonText} </paper-button> </div>
diff --git a/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.js b/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.js index 32ca08a..488afe0 100644 --- a/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.js +++ b/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.js
@@ -136,4 +136,17 @@ isNetworkProtocol_: function(protocol) { return ['ipp', 'ipps', 'http', 'https', 'socket', 'lpd'].includes(protocol); }, + + /** + * @return {boolean} Whether the Save button is enabled. + * @private + */ + canSavePrinter_: function() { + return settings.printing.isNameAndAddressValid( + this.activePrinter.printerName, + this.activePrinter.printerAddress) && + settings.printing.isPPDInfoValid( + this.activePrinter.ppdManufacturer, this.activePrinter.ppdModel, + this.activePrinter.printerPPDPath); + }, });
diff --git a/chrome/browser/resources/settings/settings_resources.grd b/chrome/browser/resources/settings/settings_resources.grd index aefffa5..e569323 100644 --- a/chrome/browser/resources/settings/settings_resources.grd +++ b/chrome/browser/resources/settings/settings_resources.grd
@@ -906,6 +906,12 @@ <structure name="IDR_SETTINGS_CUPS_ADD_PRINTER_DIALOG_ELEMENTS_JS" file="printing_page/cups_add_printer_dialog_elements.js" type="chrome_html" /> + <structure name="IDR_SETTINGS_CUPS_ADD_PRINTER_DIALOG_UTIL_HTML" + file="printing_page/cups_add_printer_dialog_util.html" + type="chrome_html" /> + <structure name="IDR_SETTINGS_CUPS_ADD_PRINTER_DIALOG_UTIL_JS" + file="printing_page/cups_add_printer_dialog_util.js" + type="chrome_html" /> </if> <if expr="not chromeos"> <structure name="IDR_SETTINGS_PRINTING_BROWSER_PROXY_HTML"
diff --git a/chrome/browser/search/one_google_bar/one_google_bar_loader_impl.cc b/chrome/browser/search/one_google_bar/one_google_bar_loader_impl.cc index df6f5cd..b04f0f7 100644 --- a/chrome/browser/search/one_google_bar/one_google_bar_loader_impl.cc +++ b/chrome/browser/search/one_google_bar/one_google_bar_loader_impl.cc
@@ -258,12 +258,10 @@ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, GoogleURLTracker* google_url_tracker, const std::string& application_locale, - const base::Optional<std::string>& api_url_override, bool account_consistency_mirror_required) : url_loader_factory_(url_loader_factory), google_url_tracker_(google_url_tracker), application_locale_(application_locale), - api_url_override_(api_url_override), account_consistency_mirror_required_(account_consistency_mirror_required), weak_ptr_factory_(this) {} @@ -292,8 +290,7 @@ google_base_url = google_url_tracker_->google_url(); } - GURL api_url = - google_base_url.Resolve(api_url_override_.value_or(kNewTabOgbApiPath)); + GURL api_url = google_base_url.Resolve(kNewTabOgbApiPath); // Add the "hl=" parameter. api_url = net::AppendQueryParameter(api_url, "hl", application_locale_);
diff --git a/chrome/browser/search/one_google_bar/one_google_bar_loader_impl.h b/chrome/browser/search/one_google_bar/one_google_bar_loader_impl.h index 70428084..f359cba 100644 --- a/chrome/browser/search/one_google_bar/one_google_bar_loader_impl.h +++ b/chrome/browser/search/one_google_bar/one_google_bar_loader_impl.h
@@ -32,13 +32,10 @@ // See https://crbug.com/751534. class OneGoogleBarLoaderImpl : public OneGoogleBarLoader { public: - // |api_url_override| can be either absolute, or relative to the Google base - // URL. OneGoogleBarLoaderImpl( scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, GoogleURLTracker* google_url_tracker, const std::string& application_locale, - const base::Optional<std::string>& api_url_override, bool account_consistency_mirror_required); ~OneGoogleBarLoaderImpl() override; @@ -62,7 +59,6 @@ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; GoogleURLTracker* google_url_tracker_; const std::string application_locale_; - const base::Optional<std::string> api_url_override_; const bool account_consistency_mirror_required_; std::vector<OneGoogleCallback> callbacks_;
diff --git a/chrome/browser/search/one_google_bar/one_google_bar_loader_impl_unittest.cc b/chrome/browser/search/one_google_bar/one_google_bar_loader_impl_unittest.cc index 0fe8719c..21b8982e 100644 --- a/chrome/browser/search/one_google_bar/one_google_bar_loader_impl_unittest.cc +++ b/chrome/browser/search/one_google_bar/one_google_bar_loader_impl_unittest.cc
@@ -68,21 +68,9 @@ public: OneGoogleBarLoaderImplTest() : OneGoogleBarLoaderImplTest( - /*api_url_override=*/base::nullopt, /*account_consistency_mirror_required=*/false) {} explicit OneGoogleBarLoaderImplTest( - const base::Optional<std::string>& api_url_override) - : OneGoogleBarLoaderImplTest( - api_url_override, - /*account_consistency_mirror_required=*/false) {} - - explicit OneGoogleBarLoaderImplTest(bool account_consistency_mirror_required) - : OneGoogleBarLoaderImplTest(/*api_url_override=*/base::nullopt, - account_consistency_mirror_required) {} - - OneGoogleBarLoaderImplTest( - const base::Optional<std::string>& api_url_override, bool account_consistency_mirror_required) : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP), google_url_tracker_(std::make_unique<GoogleURLTrackerClientStub>(), @@ -90,7 +78,6 @@ test_shared_loader_factory_( base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( &test_url_loader_factory_)), - api_url_override_(api_url_override), account_consistency_mirror_required_( account_consistency_mirror_required) {} @@ -103,7 +90,7 @@ one_google_bar_loader_ = std::make_unique<OneGoogleBarLoaderImpl>( test_shared_loader_factory_, &google_url_tracker_, kApplicationLocale, - api_url_override_, account_consistency_mirror_required_); + account_consistency_mirror_required_); } void SetUpResponseWithData(const std::string& response) { @@ -143,7 +130,6 @@ GoogleURLTracker google_url_tracker_; network::TestURLLoaderFactory test_url_loader_factory_; scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_; - base::Optional<std::string> api_url_override_; bool account_consistency_mirror_required_; GURL last_request_url_; @@ -376,56 +362,3 @@ last_request_headers().HasHeader(signin::kChromeConnectedHeader)); #endif } - -class OneGoogleBarLoaderImplWithRelativeApiUrlOverrideTest - : public OneGoogleBarLoaderImplTest { - public: - OneGoogleBarLoaderImplWithRelativeApiUrlOverrideTest() - : OneGoogleBarLoaderImplTest(std::string("/testapi?q=a")) {} -}; - -TEST_F(OneGoogleBarLoaderImplWithRelativeApiUrlOverrideTest, - RequestUrlRespectsOverride) { - SetUpResponseWithData(kMinimalValidResponse); - - // Trigger a request. - base::MockCallback<OneGoogleBarLoader::OneGoogleCallback> callback; - one_google_bar_loader()->Load(callback.Get()); - - base::RunLoop loop; - EXPECT_CALL(callback, Run(_, _)).WillOnce(Quit(&loop)); - loop.Run(); - - // Make sure the request URL corresponds to the override, but also contains - // the "hl=" query param. - EXPECT_EQ("/testapi", last_request_url().path()); - std::string expected_query = - base::StringPrintf("q=a&hl=%s&async=fixed:0", kApplicationLocale); - EXPECT_EQ(expected_query, last_request_url().query()); -} - -class OneGoogleBarLoaderImplWithAbsoluteApiUrlOverrideTest - : public OneGoogleBarLoaderImplTest { - public: - OneGoogleBarLoaderImplWithAbsoluteApiUrlOverrideTest() - : OneGoogleBarLoaderImplTest(std::string("http://test.com/path?q=a")) {} -}; - -TEST_F(OneGoogleBarLoaderImplWithAbsoluteApiUrlOverrideTest, - RequestUrlRespectsOverride) { - SetUpResponseWithData(kMinimalValidResponse); - - // Trigger a request. - base::MockCallback<OneGoogleBarLoader::OneGoogleCallback> callback; - one_google_bar_loader()->Load(callback.Get()); - - base::RunLoop loop; - EXPECT_CALL(callback, Run(_, _)).WillOnce(Quit(&loop)); - loop.Run(); - - // Make sure the request URL corresponds to the override, but also contains - // the "hl=" query param. - GURL expected_url = GURL(base::StringPrintf( - "http://test.com/path?q=a&hl=%s&async=fixed:0", kApplicationLocale)); - EXPECT_EQ(expected_url, last_request_url()); -}
diff --git a/chrome/browser/search/one_google_bar/one_google_bar_service_factory.cc b/chrome/browser/search/one_google_bar/one_google_bar_service_factory.cc index 4721b46..904da48 100644 --- a/chrome/browser/search/one_google_bar/one_google_bar_service_factory.cc +++ b/chrome/browser/search/one_google_bar/one_google_bar_service_factory.cc
@@ -49,21 +49,12 @@ KeyedService* OneGoogleBarServiceFactory::BuildServiceInstanceFor( content::BrowserContext* context) const { - if (!base::FeatureList::IsEnabled(features::kOneGoogleBarOnLocalNtp)) { - return nullptr; - } Profile* profile = Profile::FromBrowserContext(context); GaiaCookieManagerService* cookie_service = GaiaCookieManagerServiceFactory::GetForProfile(profile); GoogleURLTracker* google_url_tracker = GoogleURLTrackerFactory::GetForProfile(profile); - std::string override_api_url_str = base::GetFieldTrialParamValueByFeature( - features::kOneGoogleBarOnLocalNtp, "one-google-api-url"); - base::Optional<std::string> override_api_url; - if (!override_api_url_str.empty()) { - override_api_url = override_api_url_str; - } content_settings::CookieSettings* cookie_settings = CookieSettingsFactory::GetForProfile(profile).get(); auto url_loader_factory = @@ -73,7 +64,7 @@ cookie_service, std::make_unique<OneGoogleBarLoaderImpl>( url_loader_factory, google_url_tracker, - g_browser_process->GetApplicationLocale(), override_api_url, + g_browser_process->GetApplicationLocale(), AccountConsistencyModeManager::IsMirrorEnabledForProfile(profile) && signin::SettingsAllowSigninCookies(cookie_settings))); }
diff --git a/chrome/browser/signin/chrome_signin_client.cc b/chrome/browser/signin/chrome_signin_client.cc index 0bc9e35..8d1d26f 100644 --- a/chrome/browser/signin/chrome_signin_client.cc +++ b/chrome/browser/signin/chrome_signin_client.cc
@@ -367,8 +367,7 @@ // verification that the token is still valid (i.e. the password has not // been changed). if (!oauth_client_) { - oauth_client_.reset(new gaia::GaiaOAuthClient( - profile_->GetRequestContext())); + oauth_client_.reset(new gaia::GaiaOAuthClient(GetURLLoaderFactory())); } oauth_client_->GetTokenInfo(access_token, 3 /* retries */, this); }
diff --git a/chrome/browser/ssl/ssl_browsertest.cc b/chrome/browser/ssl/ssl_browsertest.cc index d884e614..ad8ba3be 100644 --- a/chrome/browser/ssl/ssl_browsertest.cc +++ b/chrome/browser/ssl/ssl_browsertest.cc
@@ -4012,13 +4012,12 @@ content::SetBrowserClientForTesting(old_browser_client); } -// Flaky on Windows 7 (dbg) trybot, see https://crbug.com/443374. -#if defined(OS_WIN) && !defined(NDEBUG) +// Flaky on Windows 7 bot, see https://crbug.com/874959. +#if defined(OS_WIN) #define MAYBE_MixedContentSubFrame DISABLED_MixedContentSubFrame #else #define MAYBE_MixedContentSubFrame MixedContentSubFrame #endif - // This test checks that all mixed content requests from a dedicated worker // which is started from a subframe are blocked if // allow_running_insecure_content setting is false or
diff --git a/chrome/browser/sync/test/integration/two_client_passwords_sync_test.cc b/chrome/browser/sync/test/integration/two_client_passwords_sync_test.cc index 4a3892f..0c89b21 100644 --- a/chrome/browser/sync/test/integration/two_client_passwords_sync_test.cc +++ b/chrome/browser/sync/test/integration/two_client_passwords_sync_test.cc
@@ -143,7 +143,7 @@ // https://crbug.com/874929, flaky on all platform. IN_PROC_BROWSER_TEST_F(TwoClientPasswordsSyncTest, - MAYBE_SetPassphraseAndThenSetupSync) { + DISABLED_SetPassphraseAndThenSetupSync) { ASSERT_TRUE(SetupClients()); ASSERT_TRUE(GetClient(0)->SetupSync());
diff --git a/chrome/browser/themes/theme_properties.cc b/chrome/browser/themes/theme_properties.cc index b44a0375..42919e3 100644 --- a/chrome/browser/themes/theme_properties.cc +++ b/chrome/browser/themes/theme_properties.cc
@@ -51,7 +51,7 @@ const SkColor kDefaultDetachedBookmarkBarBackground = SK_ColorWHITE; const SkColor kDefaultDetachedBookmarkBarBackgroundIncognito = - SkColorSetRGB(0x32, 0x32, 0x32); + SkColorSetRGB(0x32, 0x36, 0x39); // "Toolbar" text is used for active tabs and the bookmarks bar. constexpr SkColor kDefaultColorToolbarText = SK_ColorBLACK;
diff --git a/chrome/browser/translate/translate_manager_render_view_host_unittest.cc b/chrome/browser/translate/translate_manager_render_view_host_unittest.cc index 1bd7bd31..d56e4c1 100644 --- a/chrome/browser/translate/translate_manager_render_view_host_unittest.cc +++ b/chrome/browser/translate/translate_manager_render_view_host_unittest.cc
@@ -69,6 +69,7 @@ #include "services/network/test/test_url_loader_factory.h" #include "testing/gmock/include/gmock/gmock.h" #include "third_party/blink/public/web/web_context_menu_data.h" +#include "ui/base/page_transition_types.h" #include "url/gurl.h" namespace { @@ -423,8 +424,9 @@ // Ensures it is really handled a reload. const content::LoadCommittedDetails& nav_details = nav_observer.load_committed_details(); - EXPECT_TRUE(nav_details.entry != NULL); // There was a navigation. - EXPECT_EQ(content::NAVIGATION_TYPE_EXISTING_PAGE, nav_details.type); + EXPECT_TRUE(nav_details.entry); // There was a navigation. + EXPECT_TRUE(ui::PageTransitionCoreTypeIs( + ui::PAGE_TRANSITION_RELOAD, nav_details.entry->GetTransitionType())); // The TranslateManager class processes the navigation entry committed // notification in a posted task; process that task.
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 4d608b4..f676ec9 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -144,8 +144,6 @@ "cocoa/bubble_anchor_util_views_mac.mm", "cocoa/bubble_combobox.h", "cocoa/bubble_combobox.mm", - "cocoa/bubble_sync_promo_controller.h", - "cocoa/bubble_sync_promo_controller.mm", "cocoa/bubble_view.h", "cocoa/bubble_view.mm", "cocoa/certificate_viewer_mac_cocoa.h", @@ -231,12 +229,6 @@ "cocoa/extensions/chooser_dialog_cocoa_controller.mm", "cocoa/extensions/extension_action_platform_delegate_cocoa.h", "cocoa/extensions/extension_action_platform_delegate_cocoa.mm", - "cocoa/extensions/extension_install_dialog_controller.h", - "cocoa/extensions/extension_install_dialog_controller.mm", - "cocoa/extensions/extension_install_view_controller.h", - "cocoa/extensions/extension_install_view_controller.mm", - "cocoa/extensions/extension_installed_bubble_controller.h", - "cocoa/extensions/extension_installed_bubble_controller.mm", "cocoa/extensions/extension_keybinding_registry_cocoa.h", "cocoa/extensions/extension_keybinding_registry_cocoa.mm", "cocoa/extensions/extension_popup_controller.h", @@ -254,8 +246,6 @@ "cocoa/extensions/toolbar_actions_bar_bubble_mac.mm", "cocoa/extensions/toolbar_actions_bar_bubble_views_presenter.h", "cocoa/extensions/toolbar_actions_bar_bubble_views_presenter.mm", - "cocoa/extensions/windowed_install_dialog_controller.h", - "cocoa/extensions/windowed_install_dialog_controller.mm", "cocoa/external_protocol_dialog.h", "cocoa/external_protocol_dialog_cocoa.mm", "cocoa/external_protocol_dialog_views_mac.mm", @@ -2545,15 +2535,7 @@ "cocoa/extensions/chooser_dialog_cocoa.mm", "cocoa/extensions/chooser_dialog_cocoa_controller.h", "cocoa/extensions/chooser_dialog_cocoa_controller.mm", - "cocoa/extensions/extension_install_dialog_controller.h", - "cocoa/extensions/extension_install_dialog_controller.mm", - "cocoa/extensions/extension_install_view_controller.h", - "cocoa/extensions/extension_install_view_controller.mm", - "cocoa/extensions/extension_installed_bubble_controller.h", - "cocoa/extensions/extension_installed_bubble_controller.mm", "cocoa/extensions/extension_uninstall_dialog_cocoa.mm", - "cocoa/extensions/windowed_install_dialog_controller.h", - "cocoa/extensions/windowed_install_dialog_controller.mm", "cocoa/external_protocol_dialog_views_mac.mm", "cocoa/global_error_bubble_controller.h", "cocoa/global_error_bubble_controller.mm",
diff --git a/chrome/browser/ui/ash/accessibility/accessibility_controller_client_unittest.cc b/chrome/browser/ui/ash/accessibility/accessibility_controller_client_unittest.cc index d031b97..26a760a 100644 --- a/chrome/browser/ui/ash/accessibility/accessibility_controller_client_unittest.cc +++ b/chrome/browser/ui/ash/accessibility/accessibility_controller_client_unittest.cc
@@ -38,7 +38,10 @@ void BrailleDisplayStateChanged(bool connected) override {} void SetFocusHighlightRect(const gfx::Rect& bounds_in_screen) override {} void SetCaretBounds(const gfx::Rect& bounds_in_screen) override {} - void SetAccessibilityPanelFullscreen(bool fullscreen) override {} + void SetAccessibilityPanelAlwaysVisible(bool always_visible) override {} + void SetAccessibilityPanelBounds( + const gfx::Rect& bounds, + ash::mojom::AccessibilityPanelState state) override {} void SetSelectToSpeakState(ash::mojom::SelectToSpeakState state) override {} bool was_client_set() const { return was_client_set_; }
diff --git a/chrome/browser/ui/cocoa/bubble_sync_promo_controller.h b/chrome/browser/ui/cocoa/bubble_sync_promo_controller.h deleted file mode 100644 index b9edbe1..0000000 --- a/chrome/browser/ui/cocoa/bubble_sync_promo_controller.h +++ /dev/null
@@ -1,48 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_COCOA_BUBBLE_SYNC_PROMO_CONTROLLER_H_ -#define CHROME_BROWSER_UI_COCOA_BUBBLE_SYNC_PROMO_CONTROLLER_H_ - -#import <Cocoa/Cocoa.h> - -#include "base/mac/scoped_nsobject.h" -#include "components/signin/core/browser/signin_metrics.h" - -class Browser; -@class HyperlinkTextView; - -// Controller of the bookmark sync promo displayed at the bottom of the -// bookmark bubble. -@interface BubbleSyncPromoController : NSViewController<NSTextViewDelegate> { - @private - // The browser in which the sign in page will be loaded. - Browser* browser_; // weak - - // The text view that displays the promo message. Ownership is shared between - // the controller and its view. - base::scoped_nsobject<HyperlinkTextView> textView_; - - // The resource ids of the promo string and link string. - int promoStringId_; - int linkStringId_; - - // The access point for signing in. - signin_metrics::AccessPoint accessPoint_; -} - -@property(nonatomic, readonly) CGFloat borderWidth; - -- (id)initWithBrowser:(Browser*)browser - promoStringId:(int)promoStringId - linkStringId:(int)linkStringId - accessPoint:(signin_metrics::AccessPoint)accessPoint; - -// Preferred height of the sync promo view for a given width. The border is -// is included in the provided width and in the returned height. -- (CGFloat)preferredHeightForWidth:(CGFloat)width; - -@end - -#endif // CHROME_BROWSER_UI_COCOA_BUBBLE_SYNC_PROMO_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/bubble_sync_promo_controller.mm b/chrome/browser/ui/cocoa/bubble_sync_promo_controller.mm deleted file mode 100644 index c93fe73a..0000000 --- a/chrome/browser/ui/cocoa/bubble_sync_promo_controller.mm +++ /dev/null
@@ -1,112 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "chrome/browser/ui/cocoa/bubble_sync_promo_controller.h" - -#include <stddef.h> - -#include "base/strings/sys_string_conversions.h" -#include "chrome/browser/signin/signin_promo.h" -#include "chrome/browser/ui/chrome_pages.h" -#include "chrome/browser/ui/cocoa/chrome_style.h" -#include "chrome/browser/ui/cocoa/cocoa_util.h" -#include "skia/ext/skia_utils_mac.h" -#include "third_party/skia/include/core/SkColor.h" -#import "ui/base/cocoa/controls/hyperlink_text_view.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/l10n/l10n_util_mac.h" - -namespace { - -const SkColor kPromoTextColor = SkColorSetRGB(0x66, 0x66, 0x66); -const SkColor kPromoViewBackgroundColor = SkColorSetRGB(0xf5, 0xf5, 0xf5); -const SkColor kPromoBorderColor = SkColorSetRGB(0xe5, 0xe5, 0xe5); - -// Vertical padding of the promo (dp). -const CGFloat kPromoVerticalPadding = 15; - -// Width of the border (dp). -const CGFloat kPromoBorderWidth = 1.0; - -// Font size of the promo text (pt). -const int kPromoFontSize = 11; - -} // namespace - -@implementation BubbleSyncPromoController - -- (id)initWithBrowser:(Browser*)browser - promoStringId:(int)promoStringId - linkStringId:(int)linkStringId - accessPoint:(signin_metrics::AccessPoint)accessPoint { - if ((self = [super init])) { - browser_ = browser; - promoStringId_ = promoStringId; - linkStringId_ = linkStringId; - accessPoint_ = accessPoint; - } - return self; -} - -- (CGFloat)borderWidth { - return kPromoBorderWidth; -} - -- (CGFloat)preferredHeightForWidth:(CGFloat)width { - CGFloat availableWidth = - width - (2 * chrome_style::kHorizontalPadding) - (2 * kPromoBorderWidth); - NSRect frame = [[textView_ textStorage] - boundingRectWithSize:NSMakeSize(availableWidth, 0.0) - options:NSStringDrawingUsesLineFragmentOrigin]; - return frame.size.height + (2 * kPromoVerticalPadding) + - (2 * kPromoBorderWidth); -} - -- (void)loadView { - NSBox* promoView = [[[NSBox alloc] init] autorelease]; - [promoView setBoxType:NSBoxCustom]; - [promoView - setFillColor:skia::SkColorToDeviceNSColor(kPromoViewBackgroundColor)]; - [promoView setContentViewMargins:NSMakeSize(chrome_style::kHorizontalPadding, - kPromoVerticalPadding)]; - [promoView setBorderType:NSLineBorder]; - [promoView setBorderWidth:kPromoBorderWidth]; - [promoView setBorderColor:skia::SkColorToDeviceNSColor(kPromoBorderColor)]; - - // Add the sync promo text. - size_t offset; - const base::string16 linkText = l10n_util::GetStringUTF16(linkStringId_); - const base::string16 promoText = - l10n_util::GetStringFUTF16(promoStringId_, linkText, &offset); - NSString* nsPromoText = base::SysUTF16ToNSString(promoText); - NSString* nsLinkText = base::SysUTF16ToNSString(linkText); - NSFont* font = [NSFont labelFontOfSize:kPromoFontSize]; - NSColor* linkColor = skia::SkColorToCalibratedNSColor( - chrome_style::GetLinkColor()); - - textView_.reset([[HyperlinkTextView alloc] init]); - [textView_ setMessage:nsPromoText - withFont:font - messageColor:skia::SkColorToDeviceNSColor(kPromoTextColor)]; - [textView_ addLinkRange:NSMakeRange(offset, [nsLinkText length]) - withURL:nil - linkColor:linkColor]; - [textView_ setRefusesFirstResponder:YES]; - [[textView_ textContainer] setLineFragmentPadding:0.0]; - cocoa_util::RemoveUnderlining(textView_, offset, linkText.size()); - [textView_ setDelegate:self]; - - [promoView setContentView:textView_]; - - [self setView:promoView]; -} - -- (BOOL)textView:(NSTextView *)textView - clickedOnLink:(id)link - atIndex:(NSUInteger)charIndex { - chrome::ShowBrowserSignin(browser_, accessPoint_); - return YES; -} - -@end
diff --git a/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.h b/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.h deleted file mode 100644 index dd2d076..0000000 --- a/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.h +++ /dev/null
@@ -1,55 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_COCOA_EXTENSIONS_EXTENSION_INSTALL_DIALOG_CONTROLLER_H_ -#define CHROME_BROWSER_UI_COCOA_EXTENSIONS_EXTENSION_INSTALL_DIALOG_CONTROLLER_H_ - -#import <Cocoa/Cocoa.h> - -#include "base/mac/scoped_nsobject.h" -#include "base/macros.h" -#include "chrome/browser/extensions/extension_install_prompt.h" -#import "chrome/browser/ui/cocoa/constrained_window/constrained_window_mac.h" -#import "chrome/browser/ui/cocoa/extensions/extension_install_view_controller.h" - -class ExtensionInstallPromptShowParams; -@class ExtensionInstallViewController; - -// Displays an extension install prompt as a tab modal dialog. -class ExtensionInstallDialogController : - public ExtensionInstallViewDelegate, - public ConstrainedWindowMacDelegate { - public: - ExtensionInstallDialogController( - ExtensionInstallPromptShowParams* show_params, - const ExtensionInstallPrompt::DoneCallback& done_callback, - std::unique_ptr<ExtensionInstallPrompt::Prompt> prompt); - ~ExtensionInstallDialogController() override; - - // ExtensionInstallViewDelegate implementation. - void OnOkButtonClicked() override; - void OnCancelButtonClicked() override; - void OnStoreLinkClicked() override; - - // ConstrainedWindowMacDelegate implementation. - void OnConstrainedWindowClosed(ConstrainedWindowMac* window) override; - - ConstrainedWindowMac* constrained_window() const { - return constrained_window_.get(); - } - ExtensionInstallViewController* view_controller() const { - return view_controller_; - } - - private: - void OnPromptButtonClicked(ExtensionInstallPrompt::Result result); - - ExtensionInstallPrompt::DoneCallback done_callback_; - base::scoped_nsobject<ExtensionInstallViewController> view_controller_; - std::unique_ptr<ConstrainedWindowMac> constrained_window_; - - DISALLOW_COPY_AND_ASSIGN(ExtensionInstallDialogController); -}; - -#endif // CHROME_BROWSER_UI_COCOA_EXTENSIONS_EXTENSION_INSTALL_DIALOG_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.mm b/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.mm deleted file mode 100644 index a44a5f9..0000000 --- a/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.mm +++ /dev/null
@@ -1,104 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.h" - -#include <utility> - -#include "base/bind.h" -#include "base/callback_helpers.h" -#include "base/logging.h" -#include "base/memory/ref_counted.h" -#include "base/threading/thread_task_runner_handle.h" -#include "chrome/browser/extensions/extension_install_prompt_show_params.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/browser_finder.h" -#include "chrome/browser/ui/cocoa/browser_dialogs_views_mac.h" -#import "chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_sheet.h" -#include "chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_window.h" -#import "chrome/browser/ui/cocoa/extensions/windowed_install_dialog_controller.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "content/public/browser/web_contents.h" -#include "ui/base/ui_features.h" - -namespace { - -void ShowExtensionInstallDialogImpl( - ExtensionInstallPromptShowParams* show_params, - const ExtensionInstallPrompt::DoneCallback& done_callback, - std::unique_ptr<ExtensionInstallPrompt::Prompt> prompt) { - // These objects will delete themselves when the dialog closes. - if (!show_params->GetParentWebContents()) { - new WindowedInstallDialogController(show_params, done_callback, - std::move(prompt)); - return; - } - - new ExtensionInstallDialogController(show_params, done_callback, - std::move(prompt)); -} - -} // namespace - -ExtensionInstallDialogController::ExtensionInstallDialogController( - ExtensionInstallPromptShowParams* show_params, - const ExtensionInstallPrompt::DoneCallback& done_callback, - std::unique_ptr<ExtensionInstallPrompt::Prompt> prompt) - : done_callback_(done_callback) { - view_controller_.reset([[ExtensionInstallViewController alloc] - initWithProfile:show_params->profile() - navigator:show_params->GetParentWebContents() - delegate:this - prompt:std::move(prompt)]); - - base::scoped_nsobject<NSWindow> window([[ConstrainedWindowCustomWindow alloc] - initWithContentRect:[[view_controller_ view] bounds]]); - [[window contentView] addSubview:[view_controller_ view]]; - [window setBackgroundColor:[NSColor whiteColor]]; - - base::scoped_nsobject<CustomConstrainedWindowSheet> sheet( - [[CustomConstrainedWindowSheet alloc] initWithCustomWindow:window]); - // The extension install dialog can cause window server crashes when using the - // complex animations provided by private APIs, so use simple animations. See - // https://crbug.com/548824. - [sheet setUseSimpleAnimations:YES]; - constrained_window_ = CreateAndShowWebModalDialogMac( - this, show_params->GetParentWebContents(), sheet); -} - -ExtensionInstallDialogController::~ExtensionInstallDialogController() { -} - -void ExtensionInstallDialogController::OnOkButtonClicked() { - OnPromptButtonClicked(ExtensionInstallPrompt::Result::ACCEPTED); -} - -void ExtensionInstallDialogController::OnCancelButtonClicked() { - OnPromptButtonClicked(ExtensionInstallPrompt::Result::USER_CANCELED); -} - -void ExtensionInstallDialogController::OnStoreLinkClicked() { - OnPromptButtonClicked(ExtensionInstallPrompt::Result::USER_CANCELED); -} - -void ExtensionInstallDialogController::OnConstrainedWindowClosed( - ConstrainedWindowMac* window) { - if (!done_callback_.is_null()) { - base::ResetAndReturn(&done_callback_).Run( - ExtensionInstallPrompt::Result::ABORTED); - } - base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this); -} - -void ExtensionInstallDialogController::OnPromptButtonClicked( - ExtensionInstallPrompt::Result result) { - base::ResetAndReturn(&done_callback_).Run(result); - constrained_window_->CloseWebContentsModalDialog(); -} - -// static -ExtensionInstallPrompt::ShowDialogCallback -ExtensionInstallPrompt::GetDefaultShowDialogCallback() { - return base::BindRepeating(&ShowExtensionInstallDialogImpl); -}
diff --git a/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller_browsertest.mm b/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller_browsertest.mm deleted file mode 100644 index 9668fd2..0000000 --- a/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller_browsertest.mm +++ /dev/null
@@ -1,84 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.h" - -#include <utility> - -#include "chrome/browser/extensions/extension_install_prompt_show_params.h" -#include "chrome/browser/extensions/extension_install_prompt_test_helper.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/cocoa/constrained_window/constrained_window_sheet_controller.h" -#import "chrome/browser/ui/cocoa/extensions/extension_install_prompt_test_utils.h" -#import "chrome/browser/ui/cocoa/extensions/extension_install_view_controller.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/test/base/in_process_browser_test.h" -#include "extensions/common/extension.h" - -using extensions::Extension; - -class ExtensionInstallDialogControllerTest : public InProcessBrowserTest { -public: - ExtensionInstallDialogControllerTest() {} - - void SetUpOnMainThread() override { - extension_ = chrome::LoadInstallPromptExtension(); - } - - protected: - scoped_refptr<Extension> extension_; -}; - -IN_PROC_BROWSER_TEST_F(ExtensionInstallDialogControllerTest, BasicTest) { - content::WebContents* tab = browser()->tab_strip_model()->GetWebContentsAt(0); - ExtensionInstallPromptShowParams show_params(tab); - - ExtensionInstallPromptTestHelper test_helper; - std::unique_ptr<ExtensionInstallPrompt::Prompt> prompt = - chrome::BuildExtensionInstallPrompt(extension_.get()); - - ExtensionInstallDialogController* controller = - new ExtensionInstallDialogController( - &show_params, test_helper.GetCallback(), std::move(prompt)); - - base::scoped_nsobject<NSWindow> window( - [[[controller->view_controller() view] window] retain]); - EXPECT_TRUE([window isVisible]); - - // Press cancel to close the window. - [[controller->view_controller() cancelButton] performClick:nil]; - - // Wait for the window to finish closing. - EXPECT_FALSE([window isVisible]); - - EXPECT_EQ(ExtensionInstallPrompt::Result::USER_CANCELED, - test_helper.result()); -} - -IN_PROC_BROWSER_TEST_F(ExtensionInstallDialogControllerTest, - DISABLED_Permissions) { - content::WebContents* tab = browser()->tab_strip_model()->GetWebContentsAt(0); - ExtensionInstallPromptShowParams show_params(tab); - - ExtensionInstallPromptTestHelper test_helper; - std::unique_ptr<ExtensionInstallPrompt::Prompt> prompt = - chrome::BuildExtensionPostInstallPermissionsPrompt(extension_.get()); - - ExtensionInstallDialogController* controller = - new ExtensionInstallDialogController( - &show_params, test_helper.GetCallback(), std::move(prompt)); - - base::scoped_nsobject<NSWindow> window( - [[[controller->view_controller() view] window] retain]); - EXPECT_TRUE([window isVisible]); - - // Press cancel to close the window. - [[controller->view_controller() cancelButton] performClick:nil]; - - // Wait for the window to finish closing. - EXPECT_FALSE([window isVisible]); - - EXPECT_EQ(ExtensionInstallPrompt::Result::USER_CANCELED, - test_helper.result()); -}
diff --git a/chrome/browser/ui/cocoa/extensions/extension_install_prompt_test_utils.h b/chrome/browser/ui/cocoa/extensions/extension_install_prompt_test_utils.h deleted file mode 100644 index 7f9f663..0000000 --- a/chrome/browser/ui/cocoa/extensions/extension_install_prompt_test_utils.h +++ /dev/null
@@ -1,33 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_COCOA_EXTENSIONS_EXTENSION_INSTALL_PROMPT_TEST_UTILS_H_ -#define CHROME_BROWSER_UI_COCOA_EXTENSIONS_EXTENSION_INSTALL_PROMPT_TEST_UTILS_H_ - -#include "base/memory/ref_counted.h" -#include "chrome/browser/extensions/extension_install_prompt.h" - -namespace chrome { - -// Loads the test extension from the given test directory and manifest file. -scoped_refptr<extensions::Extension> LoadInstallPromptExtension( - const char* extension_dir_name, - const char* manifest_file); - -// Loads the default install_prompt test extension. -scoped_refptr<extensions::Extension> LoadInstallPromptExtension(); - -// Loads the icon for the install prompt extension. -gfx::Image LoadInstallPromptIcon(); - -// Builds a prompt using the given extension. -std::unique_ptr<ExtensionInstallPrompt::Prompt> BuildExtensionInstallPrompt( - extensions::Extension* extension); - -std::unique_ptr<ExtensionInstallPrompt::Prompt> -BuildExtensionPostInstallPermissionsPrompt(extensions::Extension* extension); - -} // namespace chrome - -#endif // CHROME_BROWSER_UI_COCOA_EXTENSIONS_EXTENSION_INSTALL_PROMPT_TEST_UTILS_H_
diff --git a/chrome/browser/ui/cocoa/extensions/extension_install_prompt_test_utils.mm b/chrome/browser/ui/cocoa/extensions/extension_install_prompt_test_utils.mm deleted file mode 100644 index 3cb657b..0000000 --- a/chrome/browser/ui/cocoa/extensions/extension_install_prompt_test_utils.mm +++ /dev/null
@@ -1,89 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "chrome/browser/ui/cocoa/extensions/extension_install_prompt_test_utils.h" - -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/json/json_file_value_serializer.h" -#include "base/path_service.h" -#include "base/threading/thread_restrictions.h" -#include "chrome/common/chrome_paths.h" -#include "extensions/common/extension.h" - -using extensions::Extension; - -namespace chrome { - -scoped_refptr<extensions::Extension> LoadInstallPromptExtension( - const char* extension_dir_name, - const char* manifest_file) { - base::ScopedAllowBlockingForTesting allow_blocking; - scoped_refptr<Extension> extension; - - base::FilePath path; - base::PathService::Get(chrome::DIR_TEST_DATA, &path); - path = path.AppendASCII("extensions") - .AppendASCII(extension_dir_name) - .AppendASCII(manifest_file); - - std::string error; - JSONFileValueDeserializer deserializer(path); - std::unique_ptr<base::DictionaryValue> value = - base::DictionaryValue::From(deserializer.Deserialize(NULL, &error)); - if (!value.get()) { - LOG(ERROR) << error; - return extension; - } - - extension = Extension::Create( - path.DirName(), extensions::Manifest::INVALID_LOCATION, *value, - Extension::NO_FLAGS, &error); - if (!extension.get()) - LOG(ERROR) << error; - - return extension; -} - -scoped_refptr<Extension> LoadInstallPromptExtension() { - return LoadInstallPromptExtension("install_prompt", "extension.json"); -} - -gfx::Image LoadInstallPromptIcon() { - base::ScopedAllowBlockingForTesting allow_blocking; - base::FilePath path; - base::PathService::Get(chrome::DIR_TEST_DATA, &path); - path = path.AppendASCII("extensions") - .AppendASCII("install_prompt") - .AppendASCII("icon.png"); - - std::string file_contents; - base::ReadFileToString(path, &file_contents); - - return gfx::Image::CreateFrom1xPNGBytes( - reinterpret_cast<const unsigned char*>(file_contents.c_str()), - file_contents.length()); -} - -std::unique_ptr<ExtensionInstallPrompt::Prompt> BuildExtensionInstallPrompt( - Extension* extension) { - std::unique_ptr<ExtensionInstallPrompt::Prompt> prompt( - new ExtensionInstallPrompt::Prompt( - ExtensionInstallPrompt::INSTALL_PROMPT)); - prompt->set_extension(extension); - prompt->set_icon(LoadInstallPromptIcon()); - return prompt; -} - -std::unique_ptr<ExtensionInstallPrompt::Prompt> -BuildExtensionPostInstallPermissionsPrompt(Extension* extension) { - std::unique_ptr<ExtensionInstallPrompt::Prompt> prompt( - new ExtensionInstallPrompt::Prompt( - ExtensionInstallPrompt::POST_INSTALL_PERMISSIONS_PROMPT)); - prompt->set_extension(extension); - prompt->set_icon(LoadInstallPromptIcon()); - return prompt; -} - -} // namespace chrome
diff --git a/chrome/browser/ui/cocoa/extensions/extension_install_view_controller.h b/chrome/browser/ui/cocoa/extensions/extension_install_view_controller.h deleted file mode 100644 index ff284af..0000000 --- a/chrome/browser/ui/cocoa/extensions/extension_install_view_controller.h +++ /dev/null
@@ -1,88 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_COCOA_EXTENSIONS_EXTENSION_INSTALL_VIEW_CONTROLLER_H_ -#define CHROME_BROWSER_UI_COCOA_EXTENSIONS_EXTENSION_INSTALL_VIEW_CONTROLLER_H_ - -#include <vector> - -#import <Cocoa/Cocoa.h> - -#include "base/mac/scoped_nsobject.h" -#include "base/memory/ref_counted.h" -#include "base/strings/string16.h" -#include "chrome/browser/extensions/extension_install_prompt.h" -#include "ui/gfx/image/image_skia.h" - -class Profile; - -namespace content { -class PageNavigator; -} - -class ExtensionInstallViewDelegate { - public: - virtual void OnOkButtonClicked() = 0; - virtual void OnCancelButtonClicked() = 0; - virtual void OnStoreLinkClicked() = 0; - - protected: - virtual ~ExtensionInstallViewDelegate() {} -}; - -// Displays the extension install prompt, and notifies the Delegate of success -// or failure. -@interface ExtensionInstallViewController : NSViewController - <NSOutlineViewDataSource, - NSOutlineViewDelegate> { - IBOutlet NSImageView* iconView_; - IBOutlet NSTextField* titleField_; - IBOutlet NSTextField* itemsField_; - IBOutlet NSButton* cancelButton_; - IBOutlet NSButton* okButton_; - - // Present only when the dialog has permission warnings issues to display. - IBOutlet NSOutlineView* outlineView_; - - // Present only in the install dialogs with webstore data (inline and - // external). - IBOutlet NSBox* warningsSeparator_; // Only when there are permissions. - IBOutlet NSView* ratingStars_; - IBOutlet NSTextField* ratingCountField_; - IBOutlet NSTextField* userCountField_; - IBOutlet NSButton* storeLinkButton_; - - Profile* profile_; // weak - content::PageNavigator* navigator_; // weak - ExtensionInstallViewDelegate* delegate_; // weak - std::unique_ptr<ExtensionInstallPrompt::Prompt> prompt_; - - base::scoped_nsobject<NSArray> warnings_; - BOOL isComputingRowHeight_; -} - -// For unit test use only. -@property(nonatomic, readonly) NSImageView* iconView; -@property(nonatomic, readonly) NSTextField* titleField; -@property(nonatomic, readonly) NSTextField* itemsField; -@property(nonatomic, readonly) NSButton* cancelButton; -@property(nonatomic, readonly) NSButton* okButton; -@property(nonatomic, readonly) NSOutlineView* outlineView; -@property(nonatomic, readonly) NSBox* warningsSeparator; -@property(nonatomic, readonly) NSView* ratingStars; -@property(nonatomic, readonly) NSTextField* ratingCountField; -@property(nonatomic, readonly) NSTextField* userCountField; -@property(nonatomic, readonly) NSButton* storeLinkButton; - -- (id)initWithProfile:(Profile*)profile - navigator:(content::PageNavigator*)navigator - delegate:(ExtensionInstallViewDelegate*)delegate - prompt:(std::unique_ptr<ExtensionInstallPrompt::Prompt>)prompt; -- (IBAction)storeLinkClicked:(id)sender; // Callback for "View details" link. -- (IBAction)cancel:(id)sender; -- (IBAction)ok:(id)sender; - -@end - -#endif // CHROME_BROWSER_UI_COCOA_EXTENSIONS_EXTENSION_INSTALL_VIEW_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/extensions/extension_install_view_controller.mm b/chrome/browser/ui/cocoa/extensions/extension_install_view_controller.mm deleted file mode 100644 index 47463649..0000000 --- a/chrome/browser/ui/cocoa/extensions/extension_install_view_controller.mm +++ /dev/null
@@ -1,833 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "chrome/browser/ui/cocoa/extensions/extension_install_view_controller.h" - -#include <stddef.h> - -#include <utility> - -#include "base/auto_reset.h" -#include "base/i18n/rtl.h" -#include "base/mac/bundle_locations.h" -#include "base/mac/mac_util.h" -#include "base/strings/string_util.h" -#include "base/strings/sys_string_conversions.h" -#include "base/strings/utf_string_conversions.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/browser.h" -#import "chrome/browser/ui/cocoa/chrome_style.h" -#include "chrome/browser/ui/scoped_tabbed_browser_displayer.h" -#include "chrome/common/extensions/extension_constants.h" -#include "chrome/grit/generated_resources.h" -#include "content/public/browser/page_navigator.h" -#include "extensions/common/extension.h" -#include "extensions/common/extension_urls.h" -#include "skia/ext/skia_utils_mac.h" -#import "third_party/google_toolbox_for_mac/src/AppKit/GTMUILocalizerAndLayoutTweaker.h" -#import "ui/base/cocoa/a11y_util.h" -#import "ui/base/cocoa/controls/hyperlink_button_cell.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/l10n/l10n_util_mac.h" -#include "ui/gfx/image/image_skia_util_mac.h" - -using base::SysUTF16ToNSString; -using content::OpenURLParams; -using content::Referrer; - -namespace { - -// A collection of attributes (bitmask) for how to draw a cell, the expand -// marker and the text in the cell. -enum CellAttributesMask { - kBoldText = 1 << 0, - kNoExpandMarker = 1 << 1, - kUseBullet = 1 << 2, - kAutoExpandCell = 1 << 3, - kUseCustomLinkCell = 1 << 4, - kCanExpand = 1 << 5, -}; - -typedef NSUInteger CellAttributes; - -} // namespace. - -@interface ExtensionInstallViewController () -- (BOOL)hasWebstoreData; -- (void)appendRatingStar:(const gfx::ImageSkia*)skiaImage; -- (void)onOutlineViewRowCountDidChange; -- (NSDictionary*)buildItemWithTitle:(NSString*)title - cellAttributes:(CellAttributes)cellAttributes - children:(NSArray*)children; -- (NSDictionary*)buildDetailToggleItem:(size_t)type - permissionsDetailIndex:(size_t)index; -- (NSArray*)buildWarnings:(const ExtensionInstallPrompt::Prompt&)prompt; -// Adds permissions of |type| from |prompt| to |children| and returns the -// the appropriate permissions header. If no permissions are found, NULL is -// returned. -- (NSString*) -appendPermissionsForPrompt:(const ExtensionInstallPrompt::Prompt&)prompt - children:(NSMutableArray*)children; -- (void)updateViewFrame:(NSRect)frame; -@end - -@interface DetailToggleHyperlinkButtonCell : HyperlinkButtonCell { - NSUInteger permissionsDetailIndex_; - ExtensionInstallPrompt::DetailsType permissionsDetailType_; - SEL linkClickedAction_; -} - -@property(assign, nonatomic) NSUInteger permissionsDetailIndex; -@property(assign, nonatomic) - ExtensionInstallPrompt::DetailsType permissionsDetailType; -@property(assign, nonatomic) SEL linkClickedAction; - -@end - -namespace { - -// Padding above the warnings separator, we must also subtract this when hiding -// it. -const CGFloat kWarningsSeparatorPadding = 14; - -// The left padding for the link cell. -const CGFloat kLinkCellPaddingLeft = 3; - -// Maximum height we will adjust controls to when trying to accomodate their -// contents. -const CGFloat kMaxControlHeight = 250; - -NSString* const kTitleKey = @"title"; -NSString* const kChildrenKey = @"children"; -NSString* const kCellAttributesKey = @"cellAttributes"; -NSString* const kPermissionsDetailIndex = @"permissionsDetailIndex"; -NSString* const kPermissionsDetailType = @"permissionsDetailType"; - -// Computes the |control|'s desired height to fit its contents, constrained to -// be kMaxControlHeight at most. -CGFloat ComputeDesiredControlHeight(NSControl* control) { - NSRect rect = [control frame]; - rect.size.height = kMaxControlHeight; - return [[control cell] cellSizeForBounds:rect].height; -} - -// Adjust the |control|'s height so that its content is not clipped. -// This also adds the change in height to the |total_offset| and shifts the -// control down by that amount. -void OffsetControlVerticallyToFitContent(NSControl* control, - CGFloat* total_offset) { - // Adjust the control's height so that its content is not clipped. - NSRect current_rect = [control frame]; - CGFloat desired_height = ComputeDesiredControlHeight(control); - CGFloat offset = desired_height - NSHeight(current_rect); - - [control setFrameSize:NSMakeSize(NSWidth(current_rect), - NSHeight(current_rect) + offset)]; - - *total_offset += offset; - - // Move the control vertically by the new total offset. - NSPoint origin = [control frame].origin; - origin.y -= *total_offset; - [control setFrameOrigin:origin]; -} - -// Adjust the |view|'s height so that its subviews are not clipped. -// This also adds the change in height to the |total_offset| and shifts the -// control down by that amount. -void OffsetViewVerticallyToFitContent(NSView* view, CGFloat* total_offset) { - // Adjust the view's height so that its subviews are not clipped. - CGFloat desired_height = 0; - for (NSView* subview in [view subviews]) { - int required_height = NSMaxY([subview frame]); - if (required_height > desired_height) - desired_height = required_height; - } - NSRect current_rect = [view frame]; - CGFloat offset = desired_height - NSHeight(current_rect); - - [view setFrameSize:NSMakeSize(NSWidth(current_rect), - NSHeight(current_rect) + offset)]; - - *total_offset += offset; - - // Move the view vertically by the new total offset. - NSPoint origin = [view frame].origin; - origin.y -= *total_offset; - [view setFrameOrigin:origin]; -} - -// Gets the desired height of |outline_view|. Simply using the view's frame -// doesn't work if an animation is pending. -CGFloat GetDesiredOutlineViewHeight(NSOutlineView* outline_view) { - CGFloat height = 0; - for (NSInteger i = 0; i < [outline_view numberOfRows]; ++i) - height += NSHeight([outline_view rectOfRow:i]); - return height; -} - -void OffsetOutlineViewVerticallyToFitContent(NSOutlineView* outline_view, - CGFloat* total_offset) { - NSScrollView* scroll_view = [outline_view enclosingScrollView]; - NSRect frame = [scroll_view frame]; - CGFloat desired_height = GetDesiredOutlineViewHeight(outline_view); - if (desired_height > kMaxControlHeight) - desired_height = kMaxControlHeight; - CGFloat offset = desired_height - NSHeight(frame); - frame.size.height += offset; - - *total_offset += offset; - - // Move the control vertically by the new total offset. - frame.origin.y -= *total_offset; - [scroll_view setFrame:frame]; -} - -void AppendRatingStarsShim(const gfx::ImageSkia* skia_image, void* data) { - ExtensionInstallViewController* controller = - static_cast<ExtensionInstallViewController*>(data); - [controller appendRatingStar:skia_image]; -} - -void DrawBulletInFrame(NSRect frame) { - NSRect rect; - rect.size.width = std::min(NSWidth(frame), NSHeight(frame)) * 0.25; - rect.size.height = NSWidth(rect); - rect.origin.x = frame.origin.x + (NSWidth(frame) - NSWidth(rect)) / 2.0; - rect.origin.y = frame.origin.y + (NSHeight(frame) - NSHeight(rect)) / 2.0; - rect = NSIntegralRect(rect); - - [[NSColor colorWithCalibratedWhite:0.0 alpha:0.42] set]; - [[NSBezierPath bezierPathWithOvalInRect:rect] fill]; -} - -bool HasAttribute(id item, CellAttributesMask attributeMask) { - return [[item objectForKey:kCellAttributesKey] intValue] & attributeMask; -} - -} // namespace - -@implementation ExtensionInstallViewController - -@synthesize iconView = iconView_; -@synthesize titleField = titleField_; -@synthesize itemsField = itemsField_; -@synthesize cancelButton = cancelButton_; -@synthesize okButton = okButton_; -@synthesize outlineView = outlineView_; -@synthesize warningsSeparator = warningsSeparator_; -@synthesize ratingStars = ratingStars_; -@synthesize ratingCountField = ratingCountField_; -@synthesize userCountField = userCountField_; -@synthesize storeLinkButton = storeLinkButton_; - -- (id)initWithProfile:(Profile*)profile - navigator:(content::PageNavigator*)navigator - delegate:(ExtensionInstallViewDelegate*)delegate - prompt:(std::unique_ptr<ExtensionInstallPrompt::Prompt>)prompt { - // We use a different XIB in the case of installs with webstore data, or no - // permission warnings. These are laid out nicely for the data they display. - NSString* nibName = nil; - if (prompt->has_webstore_data()) { - nibName = @"ExtensionInstallPromptWebstoreData"; - } else if (!prompt->ShouldShowPermissions() && - prompt->GetRetainedFileCount() == 0 && - prompt->GetRetainedDeviceCount() == 0) { - nibName = @"ExtensionInstallPromptNoWarnings"; - } else { - nibName = @"ExtensionInstallPrompt"; - } - - if ((self = [super initWithNibName:nibName - bundle:base::mac::FrameworkBundle()])) { - profile_ = profile; - navigator_ = navigator; - delegate_ = delegate; - prompt_ = std::move(prompt); - warnings_.reset([[self buildWarnings:*prompt_] retain]); - } - return self; -} - -- (IBAction)storeLinkClicked:(id)sender { - GURL store_url(extension_urls::GetWebstoreItemDetailURLPrefix() + - prompt_->extension()->id()); - OpenURLParams params(store_url, Referrer(), - WindowOpenDisposition::NEW_FOREGROUND_TAB, - ui::PAGE_TRANSITION_LINK, false); - if (navigator_) { - navigator_->OpenURL(params); - } else { - chrome::ScopedTabbedBrowserDisplayer displayer(profile_); - displayer.browser()->OpenURL(params); - } - - delegate_->OnStoreLinkClicked(); -} - -- (IBAction)cancel:(id)sender { - delegate_->OnCancelButtonClicked(); -} - -- (IBAction)ok:(id)sender { - delegate_->OnOkButtonClicked(); -} - -- (void)awakeFromNib { - // Since linking to 10.10, |outlineView_| needs an explicit background to - // ensure subpixel antialiasing is enabled for the permissions text. At the - // same time, the animation that shows the prompt breaks whenever the scroll - // view is present. Giving the scroll view a layer restores the animation, and - // since its contents has an opaque background, subpixel AA isn't affected. - [[outlineView_ enclosingScrollView] setWantsLayer:YES]; - [outlineView_ setBackgroundColor:[NSColor whiteColor]]; - - // Set control labels. - [titleField_ setStringValue:base::SysUTF16ToNSString( - prompt_->GetDialogTitle())]; - NSRect okButtonRect; - base::string16 acceptButtonLabel = prompt_->GetAcceptButtonLabel(); - if (!acceptButtonLabel.empty()) { - [okButton_ setTitle:base::SysUTF16ToNSString(acceptButtonLabel)]; - } else { - [okButton_ removeFromSuperview]; - okButtonRect = [okButton_ frame]; - okButton_ = nil; - } - [cancelButton_ setTitle:base::SysUTF16ToNSString( - prompt_->GetAbortButtonLabel())]; - if ([self hasWebstoreData]) { - prompt_->AppendRatingStars(AppendRatingStarsShim, self); - [ratingCountField_ setStringValue:base::SysUTF16ToNSString( - prompt_->GetRatingCount())]; - [userCountField_ setStringValue:base::SysUTF16ToNSString( - prompt_->GetUserCount())]; - [[storeLinkButton_ cell] setUnderlineBehavior: - hyperlink_button_cell::UnderlineBehavior::ON_HOVER]; - [[storeLinkButton_ cell] setTextColor: - skia::SkColorToCalibratedNSColor(chrome_style::GetLinkColor())]; - } - - [iconView_ setImage:prompt_->icon().ToNSImage()]; - // The icon does not add any additional information for VoiceOver beyond what - // the title already gives. Ignore the icon in VoiceOver. - ui::a11y_util::HideImageFromAccessibilityOrder(iconView_); - - // The dialog is laid out in the NIB exactly how we want it assuming that - // each label fits on one line. However, for each label, we want to allow - // wrapping onto multiple lines. So we accumulate an offset by measuring how - // big each label wants to be, and comparing it to how big it actually is. - // Then we shift each label down and resize by the appropriate amount, then - // finally resize the window. - CGFloat totalOffset = 0.0; - - OffsetControlVerticallyToFitContent(titleField_, &totalOffset); - - if ([self hasWebstoreData]) { - OffsetControlVerticallyToFitContent(ratingCountField_, &totalOffset); - OffsetViewVerticallyToFitContent(ratingStars_, &totalOffset); - OffsetControlVerticallyToFitContent(userCountField_, &totalOffset); - OffsetControlVerticallyToFitContent(storeLinkButton_, &totalOffset); - NSPoint separatorOrigin = [warningsSeparator_ frame].origin; - separatorOrigin.y -= totalOffset; - [warningsSeparator_ setFrameOrigin:separatorOrigin]; - } - - // Resize |okButton_| and |cancelButton_| to fit the button labels, but keep - // them right-aligned. - NSSize buttonDelta; - if (okButton_) { - buttonDelta = [GTMUILocalizerAndLayoutTweaker sizeToFitView:okButton_]; - if (buttonDelta.width) { - [okButton_ setFrame:NSOffsetRect([okButton_ frame], - -buttonDelta.width, 0)]; - [cancelButton_ setFrame:NSOffsetRect([cancelButton_ frame], - -buttonDelta.width, 0)]; - } - } else { - // Make |cancelButton_| right-aligned in the absence of |okButton_|. - NSRect cancelButtonRect = [cancelButton_ frame]; - cancelButtonRect.origin.x = - NSMaxX(okButtonRect) - NSWidth(cancelButtonRect); - [cancelButton_ setFrame:cancelButtonRect]; - } - buttonDelta = [GTMUILocalizerAndLayoutTweaker sizeToFitView:cancelButton_]; - if (buttonDelta.width) { - [cancelButton_ setFrame:NSOffsetRect([cancelButton_ frame], - -buttonDelta.width, 0)]; - } - - // If there are any warnings, retained devices or retained files, then we - // have to do some special layout. - if (prompt_->ShouldShowPermissions() || prompt_->GetRetainedFileCount() > 0) { - NSSize spacing = [outlineView_ intercellSpacing]; - spacing.width += 2; - spacing.height += 2; - [outlineView_ setIntercellSpacing:spacing]; - [[[[outlineView_ tableColumns] objectAtIndex:0] dataCell] setWraps:YES]; - for (id item in warnings_.get()) - [self expandItemAndChildren:item]; - - // Adjust the outline view to fit the warnings. - OffsetOutlineViewVerticallyToFitContent(outlineView_, &totalOffset); - } else if ([self hasWebstoreData]) { - // Installs with webstore data that don't have a permissions section need to - // hide controls related to that and shrink the window by the space they - // take up. - NSRect hiddenRect = NSUnionRect([warningsSeparator_ frame], - [[outlineView_ enclosingScrollView] frame]); - [warningsSeparator_ setHidden:YES]; - [[outlineView_ enclosingScrollView] setHidden:YES]; - totalOffset -= NSHeight(hiddenRect) + kWarningsSeparatorPadding; - } - - // If necessary, adjust the window size. - if (totalOffset) { - NSRect currentRect = [[self view] bounds]; - currentRect.size.height += totalOffset; - [self updateViewFrame:currentRect]; - } -} - -- (BOOL)hasWebstoreData { - return prompt_->has_webstore_data(); -} - -- (void)appendRatingStar:(const gfx::ImageSkia*)skiaImage { - NSImage* image = gfx::NSImageFromImageSkiaWithColorSpace( - *skiaImage, base::mac::GetSystemColorSpace()); - NSRect frame = NSMakeRect(0, 0, skiaImage->width(), skiaImage->height()); - base::scoped_nsobject<NSImageView> view( - [[NSImageView alloc] initWithFrame:frame]); - [view setImage:image]; - - // Add this star after all the other ones - CGFloat maxStarRight = 0; - if ([[ratingStars_ subviews] count]) { - maxStarRight = NSMaxX([[[ratingStars_ subviews] lastObject] frame]); - } - NSRect starBounds = NSMakeRect(maxStarRight, 0, - skiaImage->width(), skiaImage->height()); - [view setFrame:starBounds]; - [ratingStars_ addSubview:view]; -} - -- (void)onOutlineViewRowCountDidChange { - // Force the outline view to update. - [outlineView_ reloadData]; - - CGFloat totalOffset = 0.0; - OffsetOutlineViewVerticallyToFitContent(outlineView_, &totalOffset); - if (totalOffset) { - NSRect currentRect = [[self view] bounds]; - currentRect.size.height += totalOffset; - [self updateViewFrame:currentRect]; - } -} - -- (id)outlineView:(NSOutlineView*)outlineView - child:(NSInteger)index - ofItem:(id)item { - if (!item) - return [warnings_ objectAtIndex:index]; - if ([item isKindOfClass:[NSDictionary class]]) - return [[item objectForKey:kChildrenKey] objectAtIndex:index]; - NOTREACHED(); - return nil; -} - -- (BOOL)outlineView:(NSOutlineView*)outlineView - isItemExpandable:(id)item { - return [self outlineView:outlineView numberOfChildrenOfItem:item] > 0; -} - -- (NSInteger)outlineView:(NSOutlineView*)outlineView - numberOfChildrenOfItem:(id)item { - if (!item) - return [warnings_ count]; - - if ([item isKindOfClass:[NSDictionary class]]) - return [[item objectForKey:kChildrenKey] count]; - - NOTREACHED(); - return 0; -} - -- (id)outlineView:(NSOutlineView*)outlineView - objectValueForTableColumn:(NSTableColumn *)tableColumn - byItem:(id)item { - return [item objectForKey:kTitleKey]; -} - -- (BOOL)outlineView:(NSOutlineView *)outlineView - shouldExpandItem:(id)item { - return HasAttribute(item, kCanExpand); -} - -- (void)outlineViewItemDidExpand:sender { - // Call via run loop to avoid animation glitches. - [self performSelector:@selector(onOutlineViewRowCountDidChange) - withObject:nil - afterDelay:0]; -} - -- (void)outlineViewItemDidCollapse:sender { - // Call via run loop to avoid animation glitches. - [self performSelector:@selector(onOutlineViewRowCountDidChange) - withObject:nil - afterDelay:0]; -} - -- (CGFloat)outlineView:(NSOutlineView *)outlineView - heightOfRowByItem:(id)item { - // Prevent reentrancy due to the frameOfCellAtColumn:row: call below. - if (isComputingRowHeight_) - return 1; - base::AutoReset<BOOL> reset(&isComputingRowHeight_, YES); - - NSCell* cell = [[[outlineView_ tableColumns] objectAtIndex:0] dataCell]; - [cell setStringValue:[item objectForKey:kTitleKey]]; - NSRect bounds = NSZeroRect; - NSInteger row = [outlineView_ rowForItem:item]; - bounds.size.width = NSWidth([outlineView_ frameOfCellAtColumn:0 row:row]); - bounds.size.height = kMaxControlHeight; - - return [cell cellSizeForBounds:bounds].height; -} - -- (BOOL)outlineView:(NSOutlineView*)outlineView - shouldShowOutlineCellForItem:(id)item { - return !HasAttribute(item, kNoExpandMarker); -} - -- (BOOL)outlineView:(NSOutlineView*)outlineView - shouldTrackCell:(NSCell*)cell - forTableColumn:(NSTableColumn*)tableColumn - item:(id)item { - return HasAttribute(item, kUseCustomLinkCell); -} - -- (void)outlineView:(NSOutlineView*)outlineView - willDisplayCell:(id)cell - forTableColumn:(NSTableColumn *)tableColumn - item:(id)item { - if (HasAttribute(item, kBoldText)) - [cell setFont:[NSFont boldSystemFontOfSize:12.0]]; - else - [cell setFont:[NSFont systemFontOfSize:12.0]]; -} - -- (void)outlineView:(NSOutlineView *)outlineView - willDisplayOutlineCell:(id)cell - forTableColumn:(NSTableColumn *)tableColumn - item:(id)item { - if (HasAttribute(item, kNoExpandMarker)) { - [cell setImagePosition:NSNoImage]; - return; - } - - if (HasAttribute(item, kUseBullet)) { - // Replace disclosure triangles with bullet lists for leaf nodes. - [cell setImagePosition:NSNoImage]; - DrawBulletInFrame([outlineView_ frameOfOutlineCellAtRow: - [outlineView_ rowForItem:item]]); - return; - } - - // Reset image to default value. - [cell setImagePosition:NSImageOverlaps]; -} - -- (BOOL)outlineView:(NSOutlineView *)outlineView - shouldSelectItem:(id)item { - return false; -} - -- (NSCell*)outlineView:(NSOutlineView*)outlineView - dataCellForTableColumn:(NSTableColumn*)tableColumn - item:(id)item { - if (HasAttribute(item, kUseCustomLinkCell)) { - base::scoped_nsobject<DetailToggleHyperlinkButtonCell> cell( - [[DetailToggleHyperlinkButtonCell alloc] initTextCell:@""]); - [cell setTarget:self]; - [cell setLinkClickedAction:@selector(onToggleDetailsLinkClicked:)]; - [cell setAlignment:NSLeftTextAlignment]; - [cell setUnderlineBehavior: - hyperlink_button_cell::UnderlineBehavior::ON_HOVER]; - [cell setTextColor: - skia::SkColorToCalibratedNSColor(chrome_style::GetLinkColor())]; - - size_t detailsIndex = - [[item objectForKey:kPermissionsDetailIndex] unsignedIntegerValue]; - [cell setPermissionsDetailIndex:detailsIndex]; - - ExtensionInstallPrompt::DetailsType detailsType = - static_cast<ExtensionInstallPrompt::DetailsType>( - [[item objectForKey:kPermissionsDetailType] unsignedIntegerValue]); - [cell setPermissionsDetailType:detailsType]; - - if (prompt_->GetIsShowingDetails(detailsType, detailsIndex)) { - [cell setTitle: - l10n_util::GetNSStringWithFixup(IDS_EXTENSIONS_HIDE_DETAILS)]; - } else { - [cell setTitle: - l10n_util::GetNSStringWithFixup(IDS_EXTENSIONS_SHOW_DETAILS)]; - } - - return cell.autorelease(); - } else { - return [tableColumn dataCell]; - } -} - -- (void)expandItemAndChildren:(id)item { - if (HasAttribute(item, kAutoExpandCell)) - [outlineView_ expandItem:item expandChildren:NO]; - - for (id child in [item objectForKey:kChildrenKey]) - [self expandItemAndChildren:child]; -} - -- (void)onToggleDetailsLinkClicked:(id)sender { - size_t index = [sender permissionsDetailIndex]; - ExtensionInstallPrompt::DetailsType type = [sender permissionsDetailType]; - prompt_->SetIsShowingDetails( - type, index, !prompt_->GetIsShowingDetails(type, index)); - - warnings_.reset([[self buildWarnings:*prompt_] retain]); - [outlineView_ reloadData]; - - for (id item in warnings_.get()) - [self expandItemAndChildren:item]; -} - -- (NSDictionary*)buildItemWithTitle:(NSString*)title - cellAttributes:(CellAttributes)cellAttributes - children:(NSArray*)children { - if (!children || ([children count] == 0 && cellAttributes & kUseBullet)) { - // Add a dummy child even though this is a leaf node. This will cause - // the outline view to show a disclosure triangle for this item. - // This is later overriden in willDisplayOutlineCell: to draw a bullet - // instead. (The bullet could be placed in the title instead but then - // the bullet wouldn't line up with disclosure triangles of sibling nodes.) - children = [NSArray arrayWithObject:[NSDictionary dictionary]]; - } else { - cellAttributes = cellAttributes | kCanExpand; - } - - return @{ - kTitleKey : title, - kChildrenKey : children, - kCellAttributesKey : [NSNumber numberWithInt:cellAttributes], - kPermissionsDetailIndex : @0ul, - kPermissionsDetailType : @0ul, - }; -} - -- (NSDictionary*)buildDetailToggleItem:(size_t)type - permissionsDetailIndex:(size_t)index { - return @{ - kTitleKey : @"", - kChildrenKey : @[ @{} ], - kCellAttributesKey : [NSNumber numberWithInt:kUseCustomLinkCell | - kNoExpandMarker], - kPermissionsDetailIndex : [NSNumber numberWithUnsignedInteger:index], - kPermissionsDetailType : [NSNumber numberWithUnsignedInteger:type], - }; -} - -- (NSArray*)buildWarnings:(const ExtensionInstallPrompt::Prompt&)prompt { - NSMutableArray* warnings = [NSMutableArray array]; - NSString* heading = nil; - - bool hasPermissions = prompt.GetPermissionCount( - ExtensionInstallPrompt::PermissionsType::ALL_PERMISSIONS); - CellAttributes warningCellAttributes = - kBoldText | kAutoExpandCell | kNoExpandMarker; - if (prompt.ShouldShowPermissions()) { - NSMutableArray* children = [NSMutableArray array]; - - heading = - [self appendPermissionsForPrompt:prompt - children:children]; - - if (!hasPermissions) { - [children addObject: - [self buildItemWithTitle: - l10n_util::GetNSString(IDS_EXTENSION_NO_SPECIAL_PERMISSIONS) - cellAttributes:kUseBullet - children:nil]]; - heading = @""; - } - - if (heading) { - [warnings addObject:[self buildItemWithTitle:heading - cellAttributes:warningCellAttributes - children:children]]; - } - } - - if (prompt.GetRetainedFileCount() > 0) { - const ExtensionInstallPrompt::DetailsType type = - ExtensionInstallPrompt::RETAINED_FILES_DETAILS; - - NSMutableArray* children = [NSMutableArray array]; - - if (prompt.GetIsShowingDetails(type, 0)) { - for (size_t i = 0; i < prompt.GetRetainedFileCount(); ++i) { - NSString* title = SysUTF16ToNSString(prompt.GetRetainedFile(i)); - [children addObject:[self buildItemWithTitle:title - cellAttributes:kUseBullet - children:nil]]; - } - } - - NSString* title = SysUTF16ToNSString(prompt.GetRetainedFilesHeading()); - [warnings addObject:[self buildItemWithTitle:title - cellAttributes:warningCellAttributes - children:children]]; - - // Add a row for the link. - [warnings addObject: - [self buildDetailToggleItem:type permissionsDetailIndex:0]]; - } - - if (prompt.GetRetainedDeviceCount() > 0) { - const ExtensionInstallPrompt::DetailsType type = - ExtensionInstallPrompt::RETAINED_DEVICES_DETAILS; - - NSMutableArray* children = [NSMutableArray array]; - - if (prompt.GetIsShowingDetails(type, 0)) { - for (size_t i = 0; i < prompt.GetRetainedDeviceCount(); ++i) { - NSString* title = - SysUTF16ToNSString(prompt.GetRetainedDeviceMessageString(i)); - [children addObject:[self buildItemWithTitle:title - cellAttributes:kUseBullet - children:nil]]; - } - } - - NSString* title = SysUTF16ToNSString(prompt.GetRetainedDevicesHeading()); - [warnings addObject:[self buildItemWithTitle:title - cellAttributes:warningCellAttributes - children:children]]; - - // Add a row for the link. - [warnings - addObject:[self buildDetailToggleItem:type permissionsDetailIndex:0]]; - } - - return warnings; -} - -- (NSString*) -appendPermissionsForPrompt:(const ExtensionInstallPrompt::Prompt&)prompt - children:(NSMutableArray*)children { - size_t permissionsCount = prompt.GetPermissionCount(); - if (permissionsCount == 0) - return NULL; - - for (size_t i = 0; i < permissionsCount; ++i) { - NSDictionary* item = - [self buildItemWithTitle:SysUTF16ToNSString(prompt.GetPermission(i)) - cellAttributes:kUseBullet - children:nil]; - [children addObject:item]; - - // If there are additional details, add them below this item. - if (!prompt.GetPermissionsDetails(i).empty()) { - if (prompt.GetIsShowingDetails( - ExtensionInstallPrompt::PERMISSIONS_DETAILS, i)) { - item = [self buildItemWithTitle:SysUTF16ToNSString( - prompt.GetPermissionsDetails(i)) - cellAttributes:kNoExpandMarker - children:nil]; - [children addObject:item]; - } - - // Add a row for the link. - [children addObject: - [self buildDetailToggleItem:type permissionsDetailIndex:i]]; - } - } - - return SysUTF16ToNSString(prompt.GetPermissionsHeading()); -} - -- (void)updateViewFrame:(NSRect)frame { - NSWindow* window = [[self view] window]; - [window setFrame:[window frameRectForContentRect:frame] display:YES]; - [[self view] setFrame:frame]; -} - -@end - - -@implementation DetailToggleHyperlinkButtonCell - -@synthesize permissionsDetailIndex = permissionsDetailIndex_; -@synthesize permissionsDetailType = permissionsDetailType_; -@synthesize linkClickedAction = linkClickedAction_; - -+ (BOOL)prefersTrackingUntilMouseUp { - return YES; -} - -- (NSRect)drawingRectForBounds:(NSRect)rect { - NSRect rectInset = NSMakeRect(rect.origin.x + kLinkCellPaddingLeft, - rect.origin.y, - rect.size.width - kLinkCellPaddingLeft, - rect.size.height); - return [super drawingRectForBounds:rectInset]; -} - -- (NSUInteger)hitTestForEvent:(NSEvent*)event - inRect:(NSRect)cellFrame - ofView:(NSView*)controlView { - NSUInteger hitTestResult = - [super hitTestForEvent:event inRect:cellFrame ofView:controlView]; - if ((hitTestResult & NSCellHitContentArea) != 0) - hitTestResult |= NSCellHitTrackableArea; - return hitTestResult; -} - -- (void)handleLinkClicked { - [NSApp sendAction:linkClickedAction_ to:[self target] from:self]; -} - -- (BOOL)trackMouse:(NSEvent*)event - inRect:(NSRect)cellFrame - ofView:(NSView*)controlView - untilMouseUp:(BOOL)flag { - BOOL result = YES; - NSUInteger hitTestResult = - [self hitTestForEvent:event inRect:cellFrame ofView:controlView]; - if ((hitTestResult & NSCellHitContentArea) != 0) { - result = [super trackMouse:event - inRect:cellFrame - ofView:controlView - untilMouseUp:flag]; - event = [NSApp currentEvent]; - hitTestResult = - [self hitTestForEvent:event inRect:cellFrame ofView:controlView]; - if ((hitTestResult & NSCellHitContentArea) != 0) - [self handleLinkClicked]; - } - return result; -} - -- (NSArray*)accessibilityActionNames { - return [[super accessibilityActionNames] - arrayByAddingObject:NSAccessibilityPressAction]; -} - -- (void)accessibilityPerformAction:(NSString*)action { - if ([action isEqualToString:NSAccessibilityPressAction]) - [self handleLinkClicked]; - else - [super accessibilityPerformAction:action]; -} - -@end
diff --git a/chrome/browser/ui/cocoa/extensions/extension_install_view_controller_unittest.mm b/chrome/browser/ui/cocoa/extensions/extension_install_view_controller_unittest.mm deleted file mode 100644 index fc11f65b..0000000 --- a/chrome/browser/ui/cocoa/extensions/extension_install_view_controller_unittest.mm +++ /dev/null
@@ -1,379 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "chrome/browser/ui/cocoa/extensions/extension_install_view_controller.h" - -#import <Cocoa/Cocoa.h> - -#include <utility> - -#import "base/mac/scoped_nsobject.h" -#include "base/strings/sys_string_conversions.h" -#include "base/strings/utf_string_conversions.h" -#import "chrome/browser/extensions/extension_install_prompt.h" -#include "chrome/browser/ui/browser.h" -#import "chrome/browser/ui/cocoa/extensions/extension_install_prompt_test_utils.h" -#include "chrome/browser/ui/cocoa/test/cocoa_profile_test.h" -#include "extensions/common/extension.h" -#include "extensions/common/permissions/permission_message_provider.h" -#include "testing/gtest/include/gtest/gtest.h" -#import "testing/gtest_mac.h" - -using extensions::Extension; -using extensions::PermissionIDSet; -using extensions::PermissionMessage; -using extensions::PermissionMessages; - -namespace { - -class MockExtensionInstallViewDelegate : public ExtensionInstallViewDelegate { - public: - enum class Action { - UNDEFINED, - OKAY, - CANCEL, - LINK, - }; - - MockExtensionInstallViewDelegate() : action_(Action::UNDEFINED) {} - ~MockExtensionInstallViewDelegate() override {} - - void OnOkButtonClicked() override { SetAction(Action::OKAY); } - void OnCancelButtonClicked() override { SetAction(Action::CANCEL); } - void OnStoreLinkClicked() override { SetAction(Action::LINK); } - - Action action() const { return action_; } - - private: - void SetAction(Action action) { - if (action_ != Action::UNDEFINED) - ADD_FAILURE() << "SetAction() called twice!"; - action_ = action; - } - - Action action_; - - DISALLOW_COPY_AND_ASSIGN(MockExtensionInstallViewDelegate); -}; - -// Base class for our tests. -class ExtensionInstallViewControllerTest : public CocoaProfileTest { - public: - ExtensionInstallViewControllerTest() { - extension_ = chrome::LoadInstallPromptExtension(); - } - - protected: - scoped_refptr<extensions::Extension> extension_; -}; - -} // namespace - -// Test that we can load the two kinds of prompts correctly, that the outlets -// are hooked up, and that the dialog calls cancel when cancel is pressed. -TEST_F(ExtensionInstallViewControllerTest, BasicsNormalCancel) { - MockExtensionInstallViewDelegate delegate; - - std::unique_ptr<ExtensionInstallPrompt::Prompt> prompt( - chrome::BuildExtensionInstallPrompt(extension_.get())); - ExtensionInstallPrompt::PermissionsType type = - ExtensionInstallPrompt::PermissionsType::REGULAR_PERMISSIONS; - - PermissionMessages permissions; - permissions.push_back(PermissionMessage(base::UTF8ToUTF16("warning 1"), - PermissionIDSet())); - prompt->AddPermissions(permissions, type); - base::string16 permissionString = prompt->GetPermission(0, type); - - base::scoped_nsobject<ExtensionInstallViewController> controller( - [[ExtensionInstallViewController alloc] - initWithProfile:profile() - navigator:browser() - delegate:&delegate - prompt:std::move(prompt)]); - - [controller view]; // Force nib load. - - // Test the right nib loaded. - EXPECT_NSEQ(@"ExtensionInstallPrompt", [controller nibName]); - - // Check all the controls. - // Make sure everything is non-nil, and that the fields that are - // auto-translated don't start with a caret (that would indicate that they - // were not translated). - EXPECT_TRUE([controller iconView]); - EXPECT_TRUE([[controller iconView] image]); - - EXPECT_TRUE([controller titleField]); - EXPECT_NE(0u, [[[controller titleField] stringValue] length]); - - NSOutlineView* outlineView = [controller outlineView]; - EXPECT_TRUE(outlineView); - EXPECT_EQ(2, [outlineView numberOfRows]); - EXPECT_NSEQ(base::SysUTF16ToNSString(permissionString), - [[outlineView dataSource] outlineView:outlineView - objectValueForTableColumn:nil - byItem:[outlineView itemAtRow:1]]); - - EXPECT_TRUE([controller cancelButton]); - EXPECT_NE(0u, [[[controller cancelButton] stringValue] length]); - EXPECT_NE('^', [[[controller cancelButton] stringValue] characterAtIndex:0]); - - EXPECT_TRUE([controller okButton]); - EXPECT_NE(0u, [[[controller okButton] stringValue] length]); - EXPECT_NE('^', [[[controller okButton] stringValue] characterAtIndex:0]); - - // Test that cancel calls our callback. - [controller cancel:nil]; - EXPECT_EQ(MockExtensionInstallViewDelegate::Action::CANCEL, - delegate.action()); -} - -TEST_F(ExtensionInstallViewControllerTest, BasicsNormalOK) { - MockExtensionInstallViewDelegate delegate; - - std::unique_ptr<ExtensionInstallPrompt::Prompt> prompt( - chrome::BuildExtensionInstallPrompt(extension_.get())); - ExtensionInstallPrompt::PermissionsType type = - ExtensionInstallPrompt::PermissionsType::REGULAR_PERMISSIONS; - - PermissionMessages permissions; - permissions.push_back(PermissionMessage(base::UTF8ToUTF16("warning 1"), - PermissionIDSet())); - prompt->AddPermissions(permissions, type); - - base::scoped_nsobject<ExtensionInstallViewController> controller( - [[ExtensionInstallViewController alloc] - initWithProfile:profile() - navigator:browser() - delegate:&delegate - prompt:std::move(prompt)]); - - [controller view]; // Force nib load. - [controller ok:nil]; - - EXPECT_EQ(MockExtensionInstallViewDelegate::Action::OKAY, - delegate.action()); -} - -// Test that controls get repositioned when there are two warnings vs one -// warning. -TEST_F(ExtensionInstallViewControllerTest, MultipleWarnings) { - MockExtensionInstallViewDelegate delegate1; - MockExtensionInstallViewDelegate delegate2; - - std::unique_ptr<ExtensionInstallPrompt::Prompt> one_warning_prompt( - chrome::BuildExtensionInstallPrompt(extension_.get())); - ExtensionInstallPrompt::PermissionsType type = - ExtensionInstallPrompt::PermissionsType::REGULAR_PERMISSIONS; - - PermissionMessages permissions; - permissions.push_back(PermissionMessage(base::UTF8ToUTF16("warning 1"), - PermissionIDSet())); - one_warning_prompt->AddPermissions(permissions, type); - - std::unique_ptr<ExtensionInstallPrompt::Prompt> two_warnings_prompt( - chrome::BuildExtensionInstallPrompt(extension_.get())); - permissions.push_back(PermissionMessage(base::UTF8ToUTF16("warning 2"), - PermissionIDSet())); - two_warnings_prompt->AddPermissions(permissions, type); - - base::scoped_nsobject<ExtensionInstallViewController> controller1( - [[ExtensionInstallViewController alloc] - initWithProfile:profile() - navigator:browser() - delegate:&delegate1 - prompt:std::move(one_warning_prompt)]); - - [controller1 view]; // Force nib load. - - base::scoped_nsobject<ExtensionInstallViewController> controller2( - [[ExtensionInstallViewController alloc] - initWithProfile:profile() - navigator:browser() - delegate:&delegate2 - prompt:std::move(two_warnings_prompt)]); - - [controller2 view]; // Force nib load. - - // Test control positioning. We don't test exact positioning because we don't - // want this to depend on string details and localization. But we do know the - // relative effect that adding a second warning should have on the layout. - ASSERT_LT([[controller1 view] frame].size.height, - [[controller2 view] frame].size.height); - - ASSERT_LT([[controller1 view] frame].size.height, - [[controller2 view] frame].size.height); -} - -// Test that we can load the skinny prompt correctly, and that the outlets are -// are hooked up. -TEST_F(ExtensionInstallViewControllerTest, BasicsSkinny) { - MockExtensionInstallViewDelegate delegate; - - // No warnings should trigger skinny prompt. - std::unique_ptr<ExtensionInstallPrompt::Prompt> no_warnings_prompt( - chrome::BuildExtensionInstallPrompt(extension_.get())); - - base::scoped_nsobject<ExtensionInstallViewController> controller( - [[ExtensionInstallViewController alloc] - initWithProfile:profile() - navigator:browser() - delegate:&delegate - prompt:std::move(no_warnings_prompt)]); - - [controller view]; // Force nib load. - - // Test the right nib loaded. - EXPECT_NSEQ(@"ExtensionInstallPromptNoWarnings", [controller nibName]); - - // Check all the controls. - // In the skinny prompt, only the icon, title and buttons are non-nill. - // Everything else is nil. - EXPECT_TRUE([controller iconView]); - EXPECT_TRUE([[controller iconView] image]); - - EXPECT_TRUE([controller titleField]); - EXPECT_NE(0u, [[[controller titleField] stringValue] length]); - - EXPECT_TRUE([controller cancelButton]); - EXPECT_NE(0u, [[[controller cancelButton] stringValue] length]); - EXPECT_NE('^', [[[controller cancelButton] stringValue] characterAtIndex:0]); - - EXPECT_TRUE([controller okButton]); - EXPECT_NE(0u, [[[controller okButton] stringValue] length]); - EXPECT_NE('^', [[[controller okButton] stringValue] characterAtIndex:0]); - - EXPECT_FALSE([controller outlineView]); -} - - -// Test that we can load the inline prompt correctly, and that the outlets are -// are hooked up. -TEST_F(ExtensionInstallViewControllerTest, BasicsInline) { - MockExtensionInstallViewDelegate delegate; - - // No warnings should trigger skinny prompt. - std::unique_ptr<ExtensionInstallPrompt::Prompt> inline_prompt( - new ExtensionInstallPrompt::Prompt( - ExtensionInstallPrompt::INLINE_INSTALL_PROMPT)); - inline_prompt->SetWebstoreData("1,000", true, 3.5, 200); - inline_prompt->set_extension(extension_.get()); - inline_prompt->set_icon(chrome::LoadInstallPromptIcon()); - - base::scoped_nsobject<ExtensionInstallViewController> controller( - [[ExtensionInstallViewController alloc] - initWithProfile:profile() - navigator:browser() - delegate:&delegate - prompt:std::move(inline_prompt)]); - - [controller view]; // Force nib load. - - // Test the right nib loaded. - EXPECT_NSEQ(@"ExtensionInstallPromptWebstoreData", [controller nibName]); - - // Check all the controls. - EXPECT_TRUE([controller iconView]); - EXPECT_TRUE([[controller iconView] image]); - - EXPECT_TRUE([controller titleField]); - EXPECT_NE(0u, [[[controller titleField] stringValue] length]); - - EXPECT_TRUE([controller cancelButton]); - EXPECT_NE(0u, [[[controller cancelButton] stringValue] length]); - EXPECT_NE('^', [[[controller cancelButton] stringValue] characterAtIndex:0]); - - EXPECT_TRUE([controller okButton]); - EXPECT_NE(0u, [[[controller okButton] stringValue] length]); - EXPECT_NE('^', [[[controller okButton] stringValue] characterAtIndex:0]); - - EXPECT_TRUE([controller ratingStars]); - EXPECT_EQ(5u, [[[controller ratingStars] subviews] count]); - - EXPECT_TRUE([controller ratingCountField]); - EXPECT_NE(0u, [[[controller ratingCountField] stringValue] length]); - - EXPECT_TRUE([controller userCountField]); - EXPECT_NE(0u, [[[controller userCountField] stringValue] length]); - - EXPECT_TRUE([controller storeLinkButton]); - EXPECT_NE(0u, [[[controller storeLinkButton] stringValue] length]); - EXPECT_NE('^', - [[[controller storeLinkButton] stringValue] characterAtIndex:0]); - - // Though we have no permissions warnings, these should still be hooked up, - // just invisible. - EXPECT_TRUE([controller outlineView]); - EXPECT_TRUE([[[controller outlineView] enclosingScrollView] isHidden]); - EXPECT_TRUE([controller warningsSeparator]); - EXPECT_TRUE([[controller warningsSeparator] isHidden]); -} - -TEST_F(ExtensionInstallViewControllerTest, PostInstallPermissionsPrompt) { - MockExtensionInstallViewDelegate delegate; - - std::unique_ptr<ExtensionInstallPrompt::Prompt> prompt( - chrome::BuildExtensionPostInstallPermissionsPrompt(extension_.get())); - ExtensionInstallPrompt::PermissionsType type = - ExtensionInstallPrompt::PermissionsType::REGULAR_PERMISSIONS; - - PermissionMessages permissions; - permissions.push_back(PermissionMessage(base::UTF8ToUTF16("warning 1"), - PermissionIDSet())); - prompt->AddPermissions(permissions, type); - - base::scoped_nsobject<ExtensionInstallViewController> controller( - [[ExtensionInstallViewController alloc] - initWithProfile:profile() - navigator:browser() - delegate:&delegate - prompt:std::move(prompt)]); - - [controller view]; // Force nib load. - - EXPECT_TRUE([controller cancelButton]); - EXPECT_FALSE([controller okButton]); - - [controller cancel:nil]; - EXPECT_EQ(MockExtensionInstallViewDelegate::Action::CANCEL, - delegate.action()); -} - -// Test that permission details show up. -TEST_F(ExtensionInstallViewControllerTest, PermissionsDetails) { - MockExtensionInstallViewDelegate delegate; - - std::unique_ptr<ExtensionInstallPrompt::Prompt> prompt( - chrome::BuildExtensionInstallPrompt(extension_.get())); - ExtensionInstallPrompt::PermissionsType type = - ExtensionInstallPrompt::PermissionsType::REGULAR_PERMISSIONS; - - PermissionMessages permissions; - permissions.push_back(PermissionMessage( - base::UTF8ToUTF16("warning 1"), - PermissionIDSet(), - std::vector<base::string16>(1, base::UTF8ToUTF16("Detail 1")))); - prompt->AddPermissions(permissions, type); - prompt->SetIsShowingDetails( - ExtensionInstallPrompt::PERMISSIONS_DETAILS, 0, true); - base::string16 permissionString = prompt->GetPermissionsDetails(0, type); - - base::scoped_nsobject<ExtensionInstallViewController> controller( - [[ExtensionInstallViewController alloc] - initWithProfile:profile() - navigator:browser() - delegate:&delegate - prompt:std::move(prompt)]); - - [controller view]; // Force nib load. - - NSOutlineView* outlineView = [controller outlineView]; - EXPECT_TRUE(outlineView); - EXPECT_EQ(4, [outlineView numberOfRows]); - EXPECT_NSEQ(base::SysUTF16ToNSString(permissionString), - [[outlineView dataSource] outlineView:outlineView - objectValueForTableColumn:nil - byItem:[outlineView itemAtRow:2]]); -}
diff --git a/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.h b/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.h deleted file mode 100644 index 80817c62..0000000 --- a/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.h +++ /dev/null
@@ -1,111 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_COCOA_EXTENSIONS_EXTENSION_INSTALLED_BUBBLE_CONTROLLER_H_ -#define CHROME_BROWSER_UI_COCOA_EXTENSIONS_EXTENSION_INSTALLED_BUBBLE_CONTROLLER_H_ - -#import <Cocoa/Cocoa.h> - -#include "base/mac/scoped_nsobject.h" -#import "chrome/browser/ui/cocoa/base_bubble_controller.h" - -class Browser; -class ExtensionInstalledBubble; -@class HyperlinkTextView; -@class HoverCloseButton; -@class BubbleSyncPromoController; - -namespace extensions { -class Extension; -} - -namespace extension_installed_bubble { - -// Maximum height or width of extension's icon (corresponds to Windows & GTK). -const int kIconSize = 43; - -// Outer vertical margin for text, icon, and closing x. -const int kOuterVerticalMargin = 15; - -// Inner vertical margin for text messages. -const int kInnerVerticalMargin = 10; - -// An offset we apply to position the point of the bubble's arrow pointing at -// the NewTabButtonCocoa. -const int kAppsBubbleArrowOffset = 4; - -// We use a different kind of notification for each of these extension types. -enum ExtensionType { - kApp, - kExtension, -}; - -} // namespace extension_installed_bubble - -// Controller for the extension installed bubble. This bubble pops up after -// an extension has been installed to inform the user that the install happened -// properly, and to let the user know how to manage this extension in the -// future. -@interface ExtensionInstalledBubbleController : BaseBubbleController { - @private - const extensions::Extension* extension_; // weak - Browser* browser_; // weak - base::scoped_nsobject<NSImage> icon_; - - extension_installed_bubble::ExtensionType type_; - - // A weak reference to the bubble. It's owned by the BubbleManager. - ExtensionInstalledBubble* installedBubble_; - - // The controller for the sync promo. - base::scoped_nsobject<BubbleSyncPromoController> syncPromoController_; - - // References below are weak, being obtained from the nib. - IBOutlet HoverCloseButton* closeButton_; - IBOutlet NSImageView* iconImage_; - IBOutlet NSTextField* heading_; - // Only shown for browser actions, page actions and omnibox keywords. - IBOutlet NSTextField* howToUse_; - IBOutlet NSTextField* howToManage_; - // Only shown for app installs. - IBOutlet NSButton* appShortcutLink_; - // Only shown for extensions with commands. - IBOutlet NSButton* manageShortcutLink_; - // Only shown if the sign-in promo is active. - IBOutlet NSView* promoContainer_; -} - -@property(nonatomic, readonly) ExtensionInstalledBubble* installedBubble; -@property(nonatomic, readonly) NSView* heading; -@property(nonatomic, readonly) NSView* closeButton; -@property(nonatomic, readonly) NSView* howToUse; -@property(nonatomic, readonly) NSView* howToManage; -@property(nonatomic, readonly) NSView* appInstalledShortcutLink; -@property(nonatomic, readonly) NSView* manageShortcutLink; -@property(nonatomic, readonly) NSView* promoContainer; -@property(nonatomic, readonly) NSView* iconImage; - -// Initialize the window. It will be shown by the BubbleManager. -- (id)initWithParentWindow:(NSWindow*)parentWindow - extensionBubble:(ExtensionInstalledBubble*)extensionBubble; - -// Action for close button. -- (IBAction)closeWindow:(id)sender; - -// Displays the extension installed bubble. This callback is triggered by -// the extensionObserver when the extension has completed loading. -- (void)showWindow:(id)sender; - -// Opens the shortcut configuration UI. -- (IBAction)onManageShortcutClicked:(id)sender; - -// Shows the new app installed animation. -- (IBAction)onAppShortcutClicked:(id)sender; - -// Should be called by the extension bridge to close this window. -- (void)doClose; - -@end - -#endif // CHROME_BROWSER_UI_COCOA_EXTENSIONS_EXTENSION_INSTALLED_BUBBLE_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.mm b/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.mm deleted file mode 100644 index 5043545..0000000 --- a/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.mm +++ /dev/null
@@ -1,458 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.h" - -#include <stddef.h> - -#include <memory> - -#include "base/i18n/rtl.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/strings/sys_string_conversions.h" -#include "base/strings/utf_string_conversions.h" -#include "chrome/browser/extensions/extension_action.h" -#include "chrome/browser/extensions/extension_action_manager.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/browser_navigator.h" -#include "chrome/browser/ui/browser_navigator_params.h" -#include "chrome/browser/ui/browser_window.h" -#include "chrome/browser/ui/bubble_anchor_util.h" -#include "chrome/browser/ui/chrome_pages.h" -#include "chrome/browser/ui/cocoa/browser_dialogs_views_mac.h" -#include "chrome/browser/ui/cocoa/browser_window_cocoa.h" -#include "chrome/browser/ui/cocoa/browser_window_controller.h" -#include "chrome/browser/ui/cocoa/bubble_anchor_helper_views.h" -#import "chrome/browser/ui/cocoa/bubble_sync_promo_controller.h" -#include "chrome/browser/ui/cocoa/chrome_style.h" -#include "chrome/browser/ui/cocoa/extensions/browser_actions_controller.h" -#include "chrome/browser/ui/cocoa/hover_close_button.h" -#include "chrome/browser/ui/cocoa/info_bubble_view.h" -#include "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h" -#include "chrome/browser/ui/cocoa/new_tab_button.h" -#include "chrome/browser/ui/cocoa/tabs/tab_strip_view.h" -#include "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h" -#include "chrome/browser/ui/extensions/extension_install_ui_factory.h" -#include "chrome/browser/ui/extensions/extension_installed_bubble.h" -#include "chrome/browser/ui/singleton_tabs.h" -#include "chrome/browser/ui/sync/sync_promo_ui.h" -#include "chrome/common/extensions/api/omnibox/omnibox_handler.h" -#include "chrome/common/extensions/sync_helper.h" -#include "chrome/common/url_constants.h" -#include "chrome/grit/chromium_strings.h" -#include "chrome/grit/generated_resources.h" -#include "components/bubble/bubble_controller.h" -#include "components/bubble/bubble_ui.h" -#include "components/signin/core/browser/signin_metrics.h" -#include "content/public/browser/browser_thread.h" -#include "extensions/browser/install/extension_install_ui.h" -#include "extensions/common/extension.h" -#import "skia/ext/skia_utils_mac.h" -#import "third_party/google_toolbox_for_mac/src/AppKit/GTMUILocalizerAndLayoutTweaker.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "ui/base/cocoa/cocoa_base_utils.h" -#import "ui/base/cocoa/controls/hyperlink_text_view.h" -#include "ui/base/l10n/l10n_util.h" -#import "ui/gfx/mac/coordinate_conversion.h" - -using content::BrowserThread; -using extensions::Extension; - -@interface ExtensionInstalledBubbleController () - -- (const Extension*)extension; -- (void)windowWillClose:(NSNotification*)notification; -- (void)windowDidResignKey:(NSNotification*)notification; -- (NSPoint)calculateArrowPoint; -- (NSWindow*)initializeWindow; -- (int)calculateWindowHeight; -- (void)setMessageFrames:(int)newWindowHeight; -- (void)updateAnchorPosition; - -@end // ExtensionInstalledBubbleController () - -namespace { - -class ExtensionInstalledBubbleBridge : public BubbleUi { - public: - explicit ExtensionInstalledBubbleBridge( - ExtensionInstalledBubbleController* controller); - ~ExtensionInstalledBubbleBridge() override; - - private: - // BubbleUi: - void Show(BubbleReference bubble_reference) override; - void Close() override; - void UpdateAnchorPosition() override; - - // Weak reference to the controller. |controller_| will outlive the bridge. - ExtensionInstalledBubbleController* controller_; - - DISALLOW_COPY_AND_ASSIGN(ExtensionInstalledBubbleBridge); -}; - -ExtensionInstalledBubbleBridge::ExtensionInstalledBubbleBridge( - ExtensionInstalledBubbleController* controller) - : controller_(controller) { -} - -ExtensionInstalledBubbleBridge::~ExtensionInstalledBubbleBridge() { -} - -void ExtensionInstalledBubbleBridge::Show(BubbleReference bubble_reference) { - [controller_ setBubbleReference:bubble_reference]; - [controller_ showWindow:controller_]; -} - -void ExtensionInstalledBubbleBridge::Close() { - [controller_ doClose]; -} - -void ExtensionInstalledBubbleBridge::UpdateAnchorPosition() { - [controller_ updateAnchorPosition]; -} - -} // namespace - -// Cocoa specific implementation. -bool ExtensionInstalledBubble::ShouldShow() { - return true; -} - -gfx::Point ExtensionInstalledBubble::GetAnchorPoint( - gfx::NativeWindow window) const { - return bubble_anchor_util::GetExtensionInstalledAnchorPointCocoa(window, - this); -} - -// Implemented here to create the platform specific instance of the BubbleUi. -std::unique_ptr<BubbleUi> ExtensionInstalledBubble::BuildBubbleUi() { - if (chrome::ShowAllDialogsWithViewsToolkit()) - return chrome::BuildViewsExtensionInstalledBubbleUi(this); - - // |controller| is owned by the parent window. - ExtensionInstalledBubbleController* controller = - [[ExtensionInstalledBubbleController alloc] - initWithParentWindow:browser()->window()->GetNativeWindow() - extensionBubble:this]; - - // The bridge to the C++ object that performs shared logic across platforms. - // This tells the controller when to show the bubble. - return base::WrapUnique(new ExtensionInstalledBubbleBridge(controller)); -} - -@implementation ExtensionInstalledBubbleController - -@synthesize installedBubble = installedBubble_; -// Exposed for unit tests. -@synthesize heading = heading_; -@synthesize closeButton = closeButton_; -@synthesize howToUse = howToUse_; -@synthesize howToManage = howToManage_; -@synthesize appInstalledShortcutLink = appInstalledShortcutLink_; -@synthesize manageShortcutLink = manageShortcutLink_; -@synthesize promoContainer = promoContainer_; -@synthesize iconImage = iconImage_; - -- (id)initWithParentWindow:(NSWindow*)parentWindow - extensionBubble:(ExtensionInstalledBubble*)extensionBubble { - if ((self = [super initWithWindowNibPath:@"ExtensionInstalledBubble" - parentWindow:parentWindow - anchoredAt:NSZeroPoint])) { - DCHECK(extensionBubble); - const extensions::Extension* extension = extensionBubble->extension(); - browser_ = extensionBubble->browser(); - DCHECK(browser_); - icon_.reset([skia::SkBitmapToNSImage(extensionBubble->icon()) retain]); - - type_ = extension->is_app() ? extension_installed_bubble::kApp : - extension_installed_bubble::kExtension; - - installedBubble_ = extensionBubble; - } - return self; -} - -- (const Extension*)extension { - if (!installedBubble_) - return nullptr; - return installedBubble_->extension(); -} - -- (void)windowWillClose:(NSNotification*)notification { - // Turn off page action icon preview when the window closes, unless we - // already removed it when the window resigned key status. - browser_ = nullptr; - [closeButton_ setTrackingEnabled:NO]; - [super windowWillClose:notification]; -} - -// The controller is the delegate of the window, so it receives "did resign -// key" notifications. When key is resigned, close the window. -- (void)windowDidResignKey:(NSNotification*)notification { - // If the browser window is closing, we need to remove the page action - // immediately, otherwise the closing animation may overlap with - // browser destruction. - [super windowDidResignKey:notification]; -} - -- (IBAction)closeWindow:(id)sender { - DCHECK([[self window] isVisible]); - DCHECK([self bubbleReference]); - bool didClose = - [self bubbleReference]->CloseBubble(BUBBLE_CLOSE_USER_DISMISSED); - DCHECK(didClose); -} - -// The extension installed bubble points at the browser action icon or the -// page action icon (shown as a preview), depending on the extension type. -// We need to calculate the location of these icons and the size of the -// message itself (which varies with the title of the extension) in order -// to figure out the origin point for the extension installed bubble. -- (NSPoint)calculateArrowPoint { - BrowserWindowCocoa* window = - static_cast<BrowserWindowCocoa*>(browser_->window()); - if (type_ == extension_installed_bubble::kApp) { - TabStripView* view = [window->cocoa_controller() tabStripView]; - NewTabButtonCocoa* button = [view getNewTabButton]; - NSRect bounds = [button bounds]; - NSPoint anchor = NSMakePoint( - NSMidX(bounds), - NSMaxY(bounds) - extension_installed_bubble::kAppsBubbleArrowOffset); - return ui::ConvertPointFromWindowToScreen( - window->GetNativeWindow(), [button convertPoint:anchor toView:nil]); - } - - DCHECK(installedBubble_); - return gfx::ScreenPointToNSPoint( - installedBubble_->GetAnchorPoint(window->GetNativeWindow())); -} - -// Override -[BaseBubbleController showWindow:] to tweak bubble location and -// set up UI elements. -- (void)showWindow:(id)sender { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - - // Load nib and calculate height based on messages to be shown. - NSWindow* window = [self initializeWindow]; - int newWindowHeight = [self calculateWindowHeight]; - [self.bubble setFrameSize:NSMakeSize( - NSWidth([[window contentView] bounds]), newWindowHeight)]; - NSSize windowDelta = NSMakeSize( - 0, newWindowHeight - NSHeight([[window contentView] bounds])); - windowDelta = [[window contentView] convertSize:windowDelta toView:nil]; - NSRect newFrame = [window frame]; - newFrame.size.height += windowDelta.height; - [window setFrame:newFrame display:NO]; - - // Now that we have resized the window, adjust y pos of the messages. - [self setMessageFrames:newWindowHeight]; - - // Find window origin, taking into account bubble size and arrow location. - [self updateAnchorPosition]; - - if (syncPromoController_) { - signin_metrics::RecordSigninImpressionUserActionForAccessPoint( - signin_metrics::AccessPoint::ACCESS_POINT_EXTENSION_INSTALL_BUBBLE); - } - [super showWindow:sender]; -} - -// Finish nib loading, set arrow location and load icon into window. This -// function is exposed for unit testing. -- (NSWindow*)initializeWindow { - NSWindow* window = [self window]; // completes nib load - - if (installedBubble_ && - installedBubble_->anchor_position() == - ExtensionInstalledBubble::ANCHOR_OMNIBOX) { - [self.bubble setArrowLocation:info_bubble::kTopLeading]; - } else { - [self.bubble setArrowLocation:info_bubble::kTopTrailing]; - } - - // Set appropriate icon, resizing if necessary. - if ([icon_ size].width > extension_installed_bubble::kIconSize) { - [icon_ setSize:NSMakeSize(extension_installed_bubble::kIconSize, - extension_installed_bubble::kIconSize)]; - } - [iconImage_ setImage:icon_]; - [iconImage_ setNeedsDisplay:YES]; - return window; -} - -// Calculate the height of each install message, resizing messages in their -// frames to fit window width. Return the new window height, based on the -// total of all message heights. -- (int)calculateWindowHeight { - // Adjust the window height to reflect the sum height of all messages - // and vertical padding. - // If there's few enough messages, the icon area may be larger than the - // messages. - int contentColumnHeight = - 2 * extension_installed_bubble::kOuterVerticalMargin; - int iconColumnHeight = 2 * extension_installed_bubble::kOuterVerticalMargin + - NSHeight([iconImage_ frame]); - - CGFloat syncPromoHeight = 0; - if (installedBubble_->options() & ExtensionInstalledBubble::SIGN_IN_PROMO) { - signin_metrics::AccessPoint accessPoint = - signin_metrics::AccessPoint::ACCESS_POINT_EXTENSION_INSTALL_BUBBLE; - syncPromoController_.reset( - [[BubbleSyncPromoController alloc] - initWithBrowser:browser_ - promoStringId:IDS_EXTENSION_INSTALLED_SYNC_PROMO_NEW - linkStringId:IDS_EXTENSION_INSTALLED_SYNC_PROMO_LINK_NEW - accessPoint:accessPoint]); - [promoContainer_ addSubview:[syncPromoController_ view]]; - - // Resize the sync promo and its placeholder. - NSRect syncPromoPlaceholderFrame = [promoContainer_ frame]; - CGFloat windowWidth = NSWidth([[self bubble] frame]); - syncPromoPlaceholderFrame.size.width = windowWidth; - syncPromoHeight = - [syncPromoController_ preferredHeightForWidth:windowWidth]; - syncPromoPlaceholderFrame.size.height = syncPromoHeight; - - [promoContainer_ setFrame:syncPromoPlaceholderFrame]; - [[syncPromoController_ view] setFrame:syncPromoPlaceholderFrame]; - } else { - [promoContainer_ setHidden:YES]; - } - - // First part of extension installed message, the heading. - base::string16 extension_name = - base::UTF8ToUTF16([self extension]->name().c_str()); - base::i18n::AdjustStringForLocaleDirection(&extension_name); - [heading_ setStringValue:l10n_util::GetNSStringF( - IDS_EXTENSION_INSTALLED_HEADING, extension_name)]; - [GTMUILocalizerAndLayoutTweaker - sizeToFitFixedWidthTextField:heading_]; - contentColumnHeight += NSHeight([heading_ frame]); - - if (installedBubble_->options() & ExtensionInstalledBubble::HOW_TO_USE) { - [howToUse_ setStringValue:base::SysUTF16ToNSString( - installedBubble_->GetHowToUseDescription())]; - [howToUse_ setHidden:NO]; - [[howToUse_ cell] - setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]]; - [GTMUILocalizerAndLayoutTweaker - sizeToFitFixedWidthTextField:howToUse_]; - contentColumnHeight += NSHeight([howToUse_ frame]) + - extension_installed_bubble::kInnerVerticalMargin; - } - - // If type is app, hide howToManage_, and include a "show me" link in the - // bubble. - if (type_ == extension_installed_bubble::kApp) { - [howToManage_ setHidden:YES]; - [appShortcutLink_ setHidden:NO]; - contentColumnHeight += 2 * extension_installed_bubble::kInnerVerticalMargin; - contentColumnHeight += NSHeight([appShortcutLink_ frame]); - } else if (installedBubble_->options() & - ExtensionInstalledBubble::HOW_TO_MANAGE) { - // Second part of extension installed message. - [[howToManage_ cell] - setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]]; - [GTMUILocalizerAndLayoutTweaker - sizeToFitFixedWidthTextField:howToManage_]; - contentColumnHeight += NSHeight([howToManage_ frame]) + - extension_installed_bubble::kInnerVerticalMargin; - } else { - [howToManage_ setHidden:YES]; - } - - // Sync sign-in promo, if any. - if (syncPromoHeight > 0) { - // The sync promo goes at the bottom of the window and includes its own - // bottom margin. Thus, we subtract off the one of the outer margins, and - // apply it to both the icon area and content area. - int syncPromoDelta = extension_installed_bubble::kInnerVerticalMargin + - syncPromoHeight - - extension_installed_bubble::kOuterVerticalMargin; - contentColumnHeight += syncPromoDelta; - iconColumnHeight += syncPromoDelta; - } - - if (installedBubble_->options() & ExtensionInstalledBubble::SHOW_KEYBINDING) { - [manageShortcutLink_ setHidden:NO]; - [[manageShortcutLink_ cell] - setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]]; - [[manageShortcutLink_ cell] - setTextColor:skia::SkColorToCalibratedNSColor( - chrome_style::GetLinkColor())]; - [GTMUILocalizerAndLayoutTweaker sizeToFitView:manageShortcutLink_]; - contentColumnHeight += extension_installed_bubble::kInnerVerticalMargin; - contentColumnHeight += NSHeight([manageShortcutLink_ frame]); - } - - return std::max(contentColumnHeight, iconColumnHeight); -} - -// Adjust y-position of messages to sit properly in new window height. -- (void)setMessageFrames:(int)newWindowHeight { - NSRect headingFrame = [heading_ frame]; - headingFrame.origin.y = newWindowHeight - ( - NSHeight(headingFrame) + - extension_installed_bubble::kOuterVerticalMargin); - [heading_ setFrame:headingFrame]; - int nextY = NSMinY(headingFrame); - - auto adjustView = [](NSView* view, int* nextY) { - DCHECK(nextY); - NSRect frame = [view frame]; - frame.origin.y = *nextY - - (NSHeight(frame) + extension_installed_bubble::kInnerVerticalMargin); - [view setFrame:frame]; - *nextY = NSMinY(frame); - }; - - if (installedBubble_->options() & ExtensionInstalledBubble::HOW_TO_USE) - adjustView(howToUse_, &nextY); - - if (installedBubble_->options() & ExtensionInstalledBubble::HOW_TO_MANAGE) - adjustView(howToManage_, &nextY); - - if (installedBubble_->options() & ExtensionInstalledBubble::SHOW_KEYBINDING) - adjustView(manageShortcutLink_, &nextY); - - if (installedBubble_->options() & ExtensionInstalledBubble::SIGN_IN_PROMO) { - // The sync promo goes at the bottom of the bubble, but that might be - // different than directly below the previous content if the icon is larger - // than the messages. Workaround by just always setting nextY to be at the - // bottom. - nextY = NSHeight([promoContainer_ frame]) + - extension_installed_bubble::kInnerVerticalMargin; - adjustView(promoContainer_, &nextY); - } -} - -- (void)updateAnchorPosition { - self.anchorPoint = [self calculateArrowPoint]; -} - -- (IBAction)onManageShortcutClicked:(id)sender { - DCHECK([self bubbleReference]); - bool didClose = [self bubbleReference]->CloseBubble(BUBBLE_CLOSE_ACCEPTED); - DCHECK(didClose); - std::string configure_url = chrome::kChromeUIExtensionsURL; - configure_url += chrome::kExtensionConfigureCommandsSubPage; - NavigateParams params( - GetSingletonTabNavigateParams(browser_, GURL(configure_url))); - Navigate(¶ms); -} - -- (IBAction)onAppShortcutClicked:(id)sender { - std::unique_ptr<extensions::ExtensionInstallUI> install_ui( - extensions::CreateExtensionInstallUI(browser_->profile())); - install_ui->OpenAppInstalledUI([self extension]->id()); -} - -- (void)doClose { - installedBubble_ = nullptr; - [self close]; -} - -@end
diff --git a/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller_unittest.mm b/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller_unittest.mm deleted file mode 100644 index b6e35bf..0000000 --- a/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller_unittest.mm +++ /dev/null
@@ -1,367 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.h" - -#import <Cocoa/Cocoa.h> -#include <stddef.h> - -#include <memory> - -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/macros.h" -#include "base/path_service.h" -#include "base/values.h" -#include "chrome/browser/extensions/api/commands/command_service.h" -#include "chrome/browser/extensions/extension_service.h" -#include "chrome/browser/extensions/test_extension_system.h" -#include "chrome/browser/ui/browser_window.h" -#import "chrome/browser/ui/cocoa/info_bubble_window.h" -#import "chrome/browser/ui/cocoa/test/cocoa_profile_test.h" -#include "chrome/browser/ui/extensions/extension_installed_bubble.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/common/chrome_paths.h" -#include "chrome/test/base/testing_profile.h" -#include "components/crx_file/id_util.h" -#include "content/public/browser/site_instance.h" -#include "content/public/browser/web_contents.h" -#include "extensions/common/extension.h" -#include "extensions/common/extension_builder.h" -#include "extensions/common/feature_switch.h" -#include "extensions/common/manifest_constants.h" -#include "extensions/common/value_builder.h" -#import "third_party/ocmock/OCMock/OCMock.h" -#include "third_party/ocmock/gtest_support.h" -#include "ui/gfx/codec/png_codec.h" - -using extensions::Extension; -using extensions::DictionaryBuilder; - -class ExtensionInstalledBubbleControllerTest : public CocoaProfileTest { - protected: - ExtensionInstalledBubbleControllerTest() {} - ~ExtensionInstalledBubbleControllerTest() override {} - - enum ExtensionType { - BROWSER_ACTION, - PAGE_ACTION, - APP, - }; - - void SetUp() override { - CocoaProfileTest::SetUp(); - ASSERT_TRUE(browser()); - window_ = browser()->window()->GetNativeWindow(); - icon_ = LoadTestIcon(); - base::CommandLine command_line(base::CommandLine::NO_PROGRAM); - extensionService_ = static_cast<extensions::TestExtensionSystem*>( - extensions::ExtensionSystem::Get(profile()))->CreateExtensionService( - &command_line, base::FilePath(), false); - } - - // Adds a WebContents to the tab strip. - void AddWebContents() { - std::unique_ptr<content::WebContents> web_contents = base::WrapUnique( - content::WebContents::Create(content::WebContents::CreateParams( - profile(), content::SiteInstance::Create(profile())))); - browser()->tab_strip_model()->AppendWebContents(std::move(web_contents), - true); - } - - // Create a simple extension of the given |type| and manifest |location|, and - // optionally with an associated keybinding. - void CreateExtension(ExtensionType type, - bool has_keybinding, - extensions::Manifest::Location location) { - DictionaryBuilder manifest; - manifest.Set("version", "1.0"); - manifest.Set("name", "extension"); - manifest.Set("manifest_version", 2); - switch (type) { - case PAGE_ACTION: - manifest.Set("page_action", DictionaryBuilder().Build()); - break; - case BROWSER_ACTION: - manifest.Set("browser_action", DictionaryBuilder().Build()); - break; - case APP: - manifest.Set( - "app", - DictionaryBuilder() - .Set("launch", DictionaryBuilder() - .Set("web_url", "http://www.example.com") - .Build()) - .Build()); - break; - } - - if (has_keybinding) { - DictionaryBuilder command; - command.Set(type == PAGE_ACTION ? "_execute_page_action" - : "_execute_browser_action", - DictionaryBuilder() - .Set("suggested_key", DictionaryBuilder() - .Set("mac", "MacCtrl+Shift+E") - .Set("default", "Ctrl+Shift+E") - .Build()) - .Build()); - manifest.Set("commands", command.Build()); - } - - extension_ = extensions::ExtensionBuilder() - .SetManifest(manifest.Build()) - .SetID(crx_file::id_util::GenerateId("foo")) - .SetLocation(location) - .Build(); - extensionService_->AddExtension(extension_.get()); - if (has_keybinding) { - // Slight hack: manually notify the command service of the extension since - // it doesn't go through the normal installation flow. - extensions::CommandService::Get(profile())->UpdateKeybindingsForTest( - extension_.get()); - } - } - void CreateExtension(ExtensionType type, bool has_keybinding) { - CreateExtension(type, has_keybinding, extensions::Manifest::INTERNAL); - } - - // Create and return an ExtensionInstalledBubbleController and instruct it to - // show itself. - ExtensionInstalledBubbleController* CreateController() { - extensionBubble_.reset( - new ExtensionInstalledBubble(extension_.get(), browser(), icon_)); - extensionBubble_->Initialize(); - ExtensionInstalledBubbleController* controller = - [[ExtensionInstalledBubbleController alloc] - initWithParentWindow:window_ - extensionBubble:extensionBubble_.get()]; - - // Bring up the window and disable close animation. - [controller showWindow:nil]; - NSWindow* bubbleWindow = [controller window]; - CHECK([bubbleWindow isKindOfClass:[InfoBubbleWindow class]]); - [static_cast<InfoBubbleWindow*>(bubbleWindow) - setAllowedAnimations:info_bubble::kAnimateNone]; - - return controller; - } - - NSWindow* window() { return window_; } - - private: - // Load test icon from extension test directory. - SkBitmap LoadTestIcon() { - base::FilePath path; - base::PathService::Get(chrome::DIR_TEST_DATA, &path); - path = path.AppendASCII("extensions").AppendASCII("icon1.png"); - - std::string file_contents; - base::ReadFileToString(path, &file_contents); - const unsigned char* data = - reinterpret_cast<const unsigned char*>(file_contents.data()); - - SkBitmap bitmap; - gfx::PNGCodec::Decode(data, file_contents.length(), &bitmap); - return bitmap; - } - - // Required to initialize the extension installed bubble. - NSWindow* window_; // weak, owned by CocoaProfileTest. - - // The associated ExtensionService, owned by the ExtensionSystem. - ExtensionService* extensionService_; - - // Skeleton extension to be tested; reinitialized for each test. - scoped_refptr<Extension> extension_; - - // The bubble that tests are run on. - std::unique_ptr<ExtensionInstalledBubble> extensionBubble_; - - // The icon_ to be loaded into the bubble window. - SkBitmap icon_; - - DISALLOW_COPY_AND_ASSIGN(ExtensionInstalledBubbleControllerTest); -}; - -// We don't want to just test the bounds of these frames, because that results -// in a change detector test (and just duplicates the logic in the class). -// Instead, we do a few sanity checks. -void SanityCheckFrames(NSRect frames[], size_t size) { - for (size_t i = 0; i < size; ++i) { - // Check 1: Non-hidden views should have a non-empty frame. - EXPECT_FALSE(NSIsEmptyRect(frames[i])) << - "Frame at index " << i << " is empty"; - // Check 2: No frames should overlap. - for (size_t j = 0; j < i; ++j) { - EXPECT_FALSE(NSIntersectsRect(frames[i], frames[j])) << - "Frame at index " << i << " intersects frame at index " << j; - } - } -} - -// Test the basic layout of the bubble for an extension that is from the store. -TEST_F(ExtensionInstalledBubbleControllerTest, - BubbleLayoutFromStoreNoKeybinding) { - CreateExtension(BROWSER_ACTION, false); - ExtensionInstalledBubbleController* controller = CreateController(); - ASSERT_TRUE(controller); - - // The extension bubble should have the "how to use", "how to manage", and - // "sign in promo" areas. Since it doesn't have an associated keybinding, it - // shouldn't have the "manage shortcut" view. - EXPECT_FALSE([[controller howToUse] isHidden]); - EXPECT_FALSE([[controller howToManage] isHidden]); - EXPECT_FALSE([[controller promoContainer] isHidden]); - EXPECT_TRUE([[controller manageShortcutLink] isHidden]); - - NSRect headingFrame = [[controller heading] frame]; - NSRect closeFrame = [[controller closeButton] frame]; - NSRect howToUseFrame = [[controller howToUse] frame]; - NSRect howToManageFrame = [[controller howToManage] frame]; - NSRect syncPromoFrame = [[controller promoContainer] frame]; - NSRect iconFrame = [[controller iconImage] frame]; - - NSRect frames[] = {headingFrame, closeFrame, howToUseFrame, howToManageFrame, - syncPromoFrame, iconFrame}; - SanityCheckFrames(frames, arraysize(frames)); - - // Check the overall layout of the bubble; it should be: - // |------| | Heading | - // | icon | | How to Use | - // |------| | How to Manage | - // |-------------------------| - // | Sync Promo | - // |-------------------------| - EXPECT_GT(NSMinY(headingFrame), NSMinY(howToUseFrame)); - EXPECT_GT(NSMinY(howToUseFrame), NSMinY(howToManageFrame)); - EXPECT_GT(NSMinY(howToManageFrame), NSMinY(syncPromoFrame)); - EXPECT_GT(NSMinY(iconFrame), NSMinY(syncPromoFrame)); - EXPECT_GT(NSMinY(iconFrame), 0); - EXPECT_EQ(NSMinY(syncPromoFrame), 0); - - [controller close]; -} - -// Test the layout of a bubble for an extension that is from the store with an -// associated keybinding. -TEST_F(ExtensionInstalledBubbleControllerTest, - BubbleLayoutFromStoreWithKeybinding) { - CreateExtension(BROWSER_ACTION, true); - ExtensionInstalledBubbleController* controller = CreateController(); - ASSERT_TRUE(controller); - - // Since the extension has a keybinding, the "how to manage" section is - // hidden. The other fields are present. - EXPECT_FALSE([[controller howToUse] isHidden]); - EXPECT_TRUE([[controller howToManage] isHidden]); - EXPECT_FALSE([[controller manageShortcutLink] isHidden]); - EXPECT_FALSE([[controller promoContainer] isHidden]); - - NSRect headingFrame = [[controller heading] frame]; - NSRect closeFrame = [[controller closeButton] frame]; - NSRect howToUseFrame = [[controller howToUse] frame]; - NSRect manageShortcutFrame = [[controller manageShortcutLink] frame]; - NSRect syncPromoFrame = [[controller promoContainer] frame]; - NSRect iconFrame = [[controller iconImage] frame]; - - NSRect frames[] = {headingFrame, closeFrame, howToUseFrame, - manageShortcutFrame, syncPromoFrame, iconFrame}; - SanityCheckFrames(frames, arraysize(frames)); - - // Layout should be: - // |------| | Heading | - // | icon | | How to Use | - // |------| | Manage shortcut | - // |--------------------------| - // | Sync Promo | - // |--------------------------| - EXPECT_GT(NSMinY(headingFrame), NSMinY(howToUseFrame)); - EXPECT_GT(NSMinY(howToUseFrame), NSMinY(manageShortcutFrame)); - EXPECT_GT(NSMinY(manageShortcutFrame), NSMinY(syncPromoFrame)); - EXPECT_GT(NSMinY(iconFrame), NSMinY(syncPromoFrame)); - EXPECT_GT(NSMinY(iconFrame), 0); - EXPECT_EQ(NSMinY(syncPromoFrame), 0); - - [controller close]; -} - -// Test the layout of a bubble for an unpacked extension (which is not -// syncable). -TEST_F(ExtensionInstalledBubbleControllerTest, - BubbleLayoutBrowserActionUnpacked) { - CreateExtension(BROWSER_ACTION, true, extensions::Manifest::UNPACKED); - ExtensionInstalledBubbleController* controller = CreateController(); - ASSERT_TRUE(controller); - - // The extension has a keybinding (so the "how to manage" view is hidden) and - // is an unpacked extension (so the "sign in promo" view is also hidden). - EXPECT_FALSE([[controller howToUse] isHidden]); - EXPECT_TRUE([[controller howToManage] isHidden]); - EXPECT_TRUE([[controller promoContainer] isHidden]); - EXPECT_FALSE([[controller manageShortcutLink] isHidden]); - - NSRect headingFrame = [[controller heading] frame]; - NSRect closeFrame = [[controller closeButton] frame]; - NSRect howToUseFrame = [[controller howToUse] frame]; - NSRect howToManageFrame = [[controller howToManage] frame]; - NSRect iconFrame = [[controller iconImage] frame]; - - NSRect frames[] = {headingFrame, closeFrame, howToUseFrame, howToManageFrame, - iconFrame}; - SanityCheckFrames(frames, arraysize(frames)); - - // Layout should be: - // |------| | Heading | - // | icon | | How to Use | - // |------| | Manage shortcut | - EXPECT_FALSE(NSIntersectsRect(howToUseFrame, howToManageFrame)); - EXPECT_GT(NSMinY(headingFrame), NSMinY(howToManageFrame)); - EXPECT_GT(NSMinY(howToUseFrame), NSMinY(howToManageFrame)); - EXPECT_GT(NSMinY(iconFrame), 0); -} - -TEST_F(ExtensionInstalledBubbleControllerTest, ParentClose) { - CreateExtension(BROWSER_ACTION, false); - ExtensionInstalledBubbleController* controller = CreateController(); - EXPECT_TRUE(controller); - - NSWindow* bubbleWindow = [controller window]; - - // Observe whether the bubble window closes. - NSString* notification = NSWindowWillCloseNotification; - id observer = [OCMockObject observerMock]; - [[observer expect] notificationWithName:notification object:bubbleWindow]; - [[NSNotificationCenter defaultCenter] - addMockObserver:observer name:notification object:bubbleWindow]; - - // The bubble window goes from visible to not-visible. - EXPECT_TRUE([bubbleWindow isVisible]); - [window() close]; - EXPECT_FALSE([bubbleWindow isVisible]); - - [[NSNotificationCenter defaultCenter] removeObserver:observer]; - - // Check that the appropriate notification was received. - EXPECT_OCMOCK_VERIFY(observer); -} - -TEST_F(ExtensionInstalledBubbleControllerTest, AppTest) { - CreateExtension(APP, false); - ExtensionInstalledBubbleController* controller = CreateController(); - EXPECT_TRUE(controller); - - int height = NSHeight([[controller window] frame]); - - // Make sure there is always enough room for the icon and margin. - int minHeight = extension_installed_bubble::kIconSize + - (2 * extension_installed_bubble::kOuterVerticalMargin); - EXPECT_GT(height, minHeight); - - // Make sure the "show me" link is visible. - EXPECT_FALSE([[controller appInstalledShortcutLink] isHidden]); - - [controller close]; -}
diff --git a/chrome/browser/ui/cocoa/extensions/windowed_install_dialog_controller.h b/chrome/browser/ui/cocoa/extensions/windowed_install_dialog_controller.h deleted file mode 100644 index 9cbae5e..0000000 --- a/chrome/browser/ui/cocoa/extensions/windowed_install_dialog_controller.h +++ /dev/null
@@ -1,52 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_COCOA_EXTENSIONS_WINDOWED_INSTALL_DIALOG_CONTROLLER_H_ -#define CHROME_BROWSER_UI_COCOA_EXTENSIONS_WINDOWED_INSTALL_DIALOG_CONTROLLER_H_ - -#import <Cocoa/Cocoa.h> - -#include "base/gtest_prod_util.h" -#include "base/mac/scoped_nsobject.h" -#include "base/macros.h" -#include "chrome/browser/extensions/extension_install_prompt.h" -#import "chrome/browser/ui/cocoa/extensions/extension_install_view_controller.h" - -class ExtensionInstallPromptShowParams; -@class ExtensionInstallViewController; -@class WindowedInstallController; - -// Displays an app or extension install or permissions prompt as a standalone -// NSPanel. -class WindowedInstallDialogController : public ExtensionInstallViewDelegate { - public: - // Initializes the ExtensionInstallViewController and shows the window. This - // object will delete itself when the window is closed. - WindowedInstallDialogController( - ExtensionInstallPromptShowParams* show_params, - const ExtensionInstallPrompt::DoneCallback& callback, - std::unique_ptr<ExtensionInstallPrompt::Prompt> prompt); - ~WindowedInstallDialogController() override; - - // Invoked by the -[NSWindow windowWillClose:] notification after a dialog - // choice is invoked. Releases owned resources, then deletes |this|. - void OnWindowClosing(); - - // ExtensionInstallViewDelegate: - void OnOkButtonClicked() override; - void OnCancelButtonClicked() override; - void OnStoreLinkClicked() override; - - private: - FRIEND_TEST_ALL_PREFIXES(WindowedInstallDialogControllerBrowserTest, - ShowInstallDialog); - ExtensionInstallViewController* GetViewController(); - - ExtensionInstallPrompt::DoneCallback done_callback_; - base::scoped_nsobject<WindowedInstallController> install_controller_; - - DISALLOW_COPY_AND_ASSIGN(WindowedInstallDialogController); -}; - -#endif // CHROME_BROWSER_UI_COCOA_EXTENSIONS_WINDOWED_INSTALL_DIALOG_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/extensions/windowed_install_dialog_controller.mm b/chrome/browser/ui/cocoa/extensions/windowed_install_dialog_controller.mm deleted file mode 100644 index 62f7a5a..0000000 --- a/chrome/browser/ui/cocoa/extensions/windowed_install_dialog_controller.mm +++ /dev/null
@@ -1,134 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "chrome/browser/ui/cocoa/extensions/windowed_install_dialog_controller.h" - -#include <utility> - -#import "base/callback_helpers.h" -#import "base/mac/sdk_forward_declarations.h" -#include "base/strings/sys_string_conversions.h" -#include "base/threading/thread_task_runner_handle.h" -#include "chrome/browser/extensions/extension_install_prompt_show_params.h" -#include "chrome/browser/profiles/profile.h" -#import "chrome/browser/ui/cocoa/extensions/extension_install_view_controller.h" -#include "content/public/browser/web_contents.h" -#include "ui/base/cocoa/window_size_constants.h" - -@interface WindowedInstallController - : NSWindowController<NSWindowDelegate> { - @private - base::scoped_nsobject<ExtensionInstallViewController> installViewController_; - WindowedInstallDialogController* dialogController_; // Weak. Owns us. -} - -@property(readonly, nonatomic) ExtensionInstallViewController* viewController; - -- (id)initWithProfile:(Profile*)profile - navigator:(content::PageNavigator*)navigator - delegate:(WindowedInstallDialogController*)delegate - prompt:(std::unique_ptr<ExtensionInstallPrompt::Prompt>)prompt; - -@end - -WindowedInstallDialogController::WindowedInstallDialogController( - ExtensionInstallPromptShowParams* show_params, - const ExtensionInstallPrompt::DoneCallback& done_callback, - std::unique_ptr<ExtensionInstallPrompt::Prompt> prompt) - : done_callback_(done_callback) { - install_controller_.reset([[WindowedInstallController alloc] - initWithProfile:show_params->profile() - navigator:show_params->GetParentWebContents() - delegate:this - prompt:std::move(prompt)]); - [[install_controller_ window] makeKeyAndOrderFront:nil]; -} - -WindowedInstallDialogController::~WindowedInstallDialogController() { - DCHECK(!install_controller_); - DCHECK(done_callback_.is_null()); -} - -void WindowedInstallDialogController::OnWindowClosing() { - install_controller_.reset(); - if (!done_callback_.is_null()) { - base::ResetAndReturn(&done_callback_).Run( - ExtensionInstallPrompt::Result::ABORTED); - } - base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this); -} - -ExtensionInstallViewController* -WindowedInstallDialogController::GetViewController() { - return [install_controller_ viewController]; -} - -void WindowedInstallDialogController::OnOkButtonClicked() { - base::ResetAndReturn(&done_callback_).Run( - ExtensionInstallPrompt::Result::ACCEPTED); - [[install_controller_ window] close]; -} - -void WindowedInstallDialogController::OnCancelButtonClicked() { - base::ResetAndReturn(&done_callback_).Run( - ExtensionInstallPrompt::Result::USER_CANCELED); - [[install_controller_ window] close]; -} - -void WindowedInstallDialogController::OnStoreLinkClicked() { - base::ResetAndReturn(&done_callback_).Run( - ExtensionInstallPrompt::Result::USER_CANCELED); - [[install_controller_ window] close]; -} - -@implementation WindowedInstallController - -- (id)initWithProfile:(Profile*)profile - navigator:(content::PageNavigator*)navigator - delegate:(WindowedInstallDialogController*)delegate - prompt:(std::unique_ptr<ExtensionInstallPrompt::Prompt>)prompt { - base::scoped_nsobject<NSWindow> controlledPanel( - [[NSPanel alloc] initWithContentRect:ui::kWindowSizeDeterminedLater - styleMask:NSTitledWindowMask - backing:NSBackingStoreBuffered - defer:NO]); - if ((self = [super initWithWindow:controlledPanel])) { - dialogController_ = delegate; - ExtensionInstallPrompt::Prompt* weakPrompt = prompt.get(); - installViewController_.reset([[ExtensionInstallViewController alloc] - initWithProfile:profile - navigator:navigator - delegate:delegate - prompt:std::move(prompt)]); - NSWindow* window = [self window]; - - // Ensure the window does not display behind the app launcher window, and is - // otherwise hard to lose behind other windows (since it is not modal). - [window setLevel:NSDockWindowLevel]; - - // Animate the window when ordered in, the same way as an NSAlert. - if ([window respondsToSelector:@selector(setAnimationBehavior:)]) - [window setAnimationBehavior:NSWindowAnimationBehaviorAlertPanel]; - - [window setTitle:base::SysUTF16ToNSString(weakPrompt->GetDialogTitle())]; - NSRect viewFrame = [[installViewController_ view] frame]; - [window setFrame:[window frameRectForContentRect:viewFrame] - display:NO]; - [window setContentView:[installViewController_ view]]; - [window setDelegate:self]; - [window center]; - } - return self; -} - -- (ExtensionInstallViewController*)viewController { - return installViewController_; -} - -- (void)windowWillClose:(NSNotification*)notification { - [[self window] setDelegate:nil]; - dialogController_->OnWindowClosing(); -} - -@end
diff --git a/chrome/browser/ui/cocoa/extensions/windowed_install_dialog_controller_browsertest.mm b/chrome/browser/ui/cocoa/extensions/windowed_install_dialog_controller_browsertest.mm deleted file mode 100644 index bda2d0b..0000000 --- a/chrome/browser/ui/cocoa/extensions/windowed_install_dialog_controller_browsertest.mm +++ /dev/null
@@ -1,71 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "chrome/browser/ui/cocoa/extensions/windowed_install_dialog_controller.h" - -#include <utility> - -#include "base/run_loop.h" -#include "chrome/browser/extensions/extension_install_prompt_test_helper.h" -#include "chrome/browser/ui/browser.h" -#import "chrome/browser/ui/cocoa/extensions/extension_install_prompt_test_utils.h" -#import "chrome/browser/ui/cocoa/extensions/extension_install_view_controller.h" -#include "chrome/test/base/in_process_browser_test.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/test/test_utils.h" -#include "extensions/common/extension.h" - -namespace { - -// Similar to ShowExtensionInstallDialogImpl except this allows the created -// dialog controller to be captured and manipulated for tests. -void TestingShowAppListInstallDialogController( - WindowedInstallDialogController** controller, - ExtensionInstallPromptShowParams* show_params, - const ExtensionInstallPrompt::DoneCallback& done_callback, - std::unique_ptr<ExtensionInstallPrompt::Prompt> prompt) { - *controller = - new WindowedInstallDialogController(show_params, done_callback, - std::move(prompt)); -} - -typedef InProcessBrowserTest WindowedInstallDialogControllerBrowserTest; - -} // namespace - -// Test for showing an extension install prompt with no parent WebContents. -IN_PROC_BROWSER_TEST_F(WindowedInstallDialogControllerBrowserTest, - ShowInstallDialog) { - // Construct a prompt with a NULL parent window, the way ExtensionEnableFlow - // will for the Mac app list. For testing, sets a NULL PageNavigator as well. - std::unique_ptr<ExtensionInstallPrompt> prompt( - new ExtensionInstallPrompt(browser()->profile(), NULL)); - - WindowedInstallDialogController* controller = NULL; - ExtensionInstallPromptTestHelper test_helper; - scoped_refptr<extensions::Extension> extension = - chrome::LoadInstallPromptExtension("permissions", "many-apis.json"); - prompt->ShowDialog( - test_helper.GetCallback(), extension.get(), nullptr, - base::Bind(&TestingShowAppListInstallDialogController, &controller)); - - // The prompt needs to load the image, which happens on the blocking pool. - content::RunAllTasksUntilIdle(); - ASSERT_TRUE(controller); - - base::scoped_nsobject<NSWindow> window( - [[[controller->GetViewController() view] window] retain]); - EXPECT_TRUE([window isVisible]); - EXPECT_TRUE([window delegate]); - EXPECT_FALSE(test_helper.has_result()); - - // Press cancel to close the window. - [[controller->GetViewController() cancelButton] performClick:nil]; - EXPECT_FALSE([window delegate]); - EXPECT_EQ(ExtensionInstallPrompt::Result::USER_CANCELED, - test_helper.result()); - - // Ensure the window is closed. - EXPECT_FALSE([window isVisible]); -}
diff --git a/chrome/browser/ui/search/local_ntp_one_google_bar_browsertest.cc b/chrome/browser/ui/search/local_ntp_one_google_bar_browsertest.cc index 8cb32cc..d16cea69 100644 --- a/chrome/browser/ui/search/local_ntp_one_google_bar_browsertest.cc +++ b/chrome/browser/ui/search/local_ntp_one_google_bar_browsertest.cc
@@ -59,8 +59,7 @@ private: void SetUp() override { - feature_list_.InitWithFeatures( - {features::kUseGoogleLocalNtp, features::kOneGoogleBarOnLocalNtp}, {}); + feature_list_.InitWithFeatures({features::kUseGoogleLocalNtp}, {}); InProcessBrowserTest::SetUp(); }
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc index f99066b..9f6fe14 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
@@ -647,10 +647,8 @@ void BrowserNonClientFrameViewAsh::ChildPreferredSizeChanged( views::View* child) { - // TODO(estade): Do we need this in a world where Ash provides the header? - if (IsMash()) - return; - + // This is required even when Ash provides the header (as in Mash) for the + // |hosted_app_button_container_|. if (browser_view()->initialized()) { InvalidateLayout(); frame()->GetRootView()->Layout();
diff --git a/chrome/browser/ui/views/hover_button.cc b/chrome/browser/ui/views/hover_button.cc index 66d3d6f..4612b43 100644 --- a/chrome/browser/ui/views/hover_button.cc +++ b/chrome/browser/ui/views/hover_button.cc
@@ -72,6 +72,7 @@ icon_view_(nullptr), secondary_icon_view_(nullptr), listener_(button_listener) { + SetInstallFocusRingOnFocus(false); SetFocusBehavior(FocusBehavior::ALWAYS); SetFocusPainter(nullptr);
diff --git a/chrome/browser/ui/webui/media/webrtc_logs_ui.cc b/chrome/browser/ui/webui/media/webrtc_logs_ui.cc index e1f8d88..748f45c 100644 --- a/chrome/browser/ui/webui/media/webrtc_logs_ui.cc +++ b/chrome/browser/ui/webui/media/webrtc_logs_ui.cc
@@ -191,8 +191,8 @@ base::Value version(version_info::GetVersionNumber()); - web_ui()->CallJavascriptFunctionUnsafe("updateWebRtcLogsList", upload_list, - version); + AllowJavascript(); + CallJavascriptFunction("updateWebRtcLogsList", upload_list, version); } } // namespace
diff --git a/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.cc b/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.cc index a9a50cf..7a93363 100644 --- a/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.cc +++ b/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.cc
@@ -18,33 +18,11 @@ namespace { const char kPageContentDataModeKey[] = "mode"; -const char kPageContentDataHostDeviceKey[] = "hostDevice"; - -const char kRemoteDeviceNameKey[] = "name"; -const char kRemoteDeviceSoftwareFeaturesKey[] = "softwareFeatures"; - -std::unique_ptr<base::DictionaryValue> GeneratePageContentDataDictionary( - multidevice_setup::mojom::HostStatus host_status, - const base::Optional<cryptauth::RemoteDeviceRef>& host_device) { - auto page_content_dictionary = std::make_unique<base::DictionaryValue>(); - page_content_dictionary->SetInteger(kPageContentDataModeKey, - static_cast<int32_t>(host_status)); - - if (host_device) { - auto device_dictionary = std::make_unique<base::DictionaryValue>(); - device_dictionary->SetString(kRemoteDeviceNameKey, host_device->name()); - - // TODO(khorimoto): Send actual feature dictionary. Currently, an empty - // dictionary is passed. - device_dictionary->SetDictionary(kRemoteDeviceSoftwareFeaturesKey, - std::make_unique<base::DictionaryValue>()); - - page_content_dictionary->SetDictionary(kPageContentDataHostDeviceKey, - std::move(device_dictionary)); - } - - return page_content_dictionary; -} +const char kPageContentDataHostDeviceNameKey[] = "hostDeviceName"; +const char kPageContentDataBetterTogetherStateKey[] = "betterTogetherState"; +const char kPageContentDataInstantTetheringStateKey[] = "instantTetheringState"; +const char kPageContentDataMessagesStateKey[] = "messagesState"; +const char kPageContentDataSmartLockStateKey[] = "smartLockState"; void OnRetrySetHostNowResult(bool success) { if (success) @@ -93,9 +71,36 @@ void MultideviceHandler::OnHostStatusChanged( multidevice_setup::mojom::HostStatus host_status, const base::Optional<cryptauth::RemoteDeviceRef>& host_device) { - FireWebUIListener( - "settings.updateMultidevicePageContentData", - *GeneratePageContentDataDictionary(host_status, host_device)); + last_host_status_update_ = std::make_pair(host_status, host_device); + AttemptUpdatePageContent(); +} + +void MultideviceHandler::OnFeatureStatesChanged( + const multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap& + feature_states_map) { + last_feature_states_update_ = feature_states_map; + AttemptUpdatePageContent(); +} + +void MultideviceHandler::AttemptGetPageContentResponse( + const std::string& js_callback_id) { + std::unique_ptr<base::DictionaryValue> page_content_dictionary = + GeneratePageContentDataDictionary(); + if (!page_content_dictionary) + return; + + ResolveJavascriptCallback(base::Value(js_callback_id), + *page_content_dictionary); +} + +void MultideviceHandler::AttemptUpdatePageContent() { + std::unique_ptr<base::DictionaryValue> page_content_dictionary = + GeneratePageContentDataDictionary(); + if (!page_content_dictionary) + return; + + FireWebUIListener("settings.updateMultidevicePageContentData", + *page_content_dictionary); } void MultideviceHandler::HandleShowMultiDeviceSetupDialog( @@ -113,9 +118,17 @@ bool result = args->GetString(0, &callback_id); DCHECK(result); + if (last_host_status_update_ && last_feature_states_update_) { + AttemptGetPageContentResponse(callback_id); + return; + } + multidevice_setup_client_->GetHostStatus( base::BindOnce(&MultideviceHandler::OnHostStatusFetched, callback_weak_ptr_factory_.GetWeakPtr(), callback_id)); + multidevice_setup_client_->GetFeatureStates( + base::BindOnce(&MultideviceHandler::OnFeatureStatesFetched, + callback_weak_ptr_factory_.GetWeakPtr(), callback_id)); } void MultideviceHandler::HandleRetryPendingHostSetup( @@ -129,9 +142,56 @@ const std::string& js_callback_id, multidevice_setup::mojom::HostStatus host_status, const base::Optional<cryptauth::RemoteDeviceRef>& host_device) { - ResolveJavascriptCallback( - base::Value(js_callback_id), - *GeneratePageContentDataDictionary(host_status, host_device)); + last_host_status_update_ = std::make_pair(host_status, host_device); + AttemptGetPageContentResponse(js_callback_id); +} + +void MultideviceHandler::OnFeatureStatesFetched( + const std::string& js_callback_id, + const multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap& + feature_states_map) { + last_feature_states_update_ = feature_states_map; + AttemptGetPageContentResponse(js_callback_id); +} + +std::unique_ptr<base::DictionaryValue> +MultideviceHandler::GeneratePageContentDataDictionary() { + // Cannot generate page contents without all required data. + if (!last_host_status_update_ || !last_feature_states_update_) + return nullptr; + + auto page_content_dictionary = std::make_unique<base::DictionaryValue>(); + + page_content_dictionary->SetInteger( + kPageContentDataModeKey, + static_cast<int32_t>(last_host_status_update_->first)); + page_content_dictionary->SetInteger( + kPageContentDataBetterTogetherStateKey, + static_cast<int32_t>( + (*last_feature_states_update_) + [multidevice_setup::mojom::Feature::kBetterTogetherSuite])); + page_content_dictionary->SetInteger( + kPageContentDataInstantTetheringStateKey, + static_cast<int32_t>( + (*last_feature_states_update_) + [multidevice_setup::mojom::Feature::kInstantTethering])); + page_content_dictionary->SetInteger( + kPageContentDataMessagesStateKey, + static_cast<int32_t>((*last_feature_states_update_) + [multidevice_setup::mojom::Feature::kMessages])); + page_content_dictionary->SetInteger( + kPageContentDataSmartLockStateKey, + static_cast<int32_t>( + (*last_feature_states_update_) + [multidevice_setup::mojom::Feature::kSmartLock])); + + if (last_host_status_update_->second) { + page_content_dictionary->SetString( + kPageContentDataHostDeviceNameKey, + last_host_status_update_->second->name()); + } + + return page_content_dictionary; } } // namespace settings
diff --git a/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.h b/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.h index 571820a5..4f93a0eb 100644 --- a/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.h +++ b/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.h
@@ -39,6 +39,17 @@ void OnHostStatusChanged( multidevice_setup::mojom::HostStatus host_status, const base::Optional<cryptauth::RemoteDeviceRef>& host_device) override; + void OnFeatureStatesChanged( + const multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap& + feature_states_map) override; + + // Attempts to send the most recent PageContentData dictionary to the WebUI + // page as a response to a getPageContent() request. + void AttemptGetPageContentResponse(const std::string& js_callback_id); + + // Attempts to send the most recent PageContentData dictionary to the WebUI + // page as an update (e.g., not due to a getPageCOntent() request. + void AttemptUpdatePageContent(); void HandleShowMultiDeviceSetupDialog(const base::ListValue* args); void HandleGetPageContent(const base::ListValue* args); @@ -48,6 +59,15 @@ const std::string& js_callback_id, multidevice_setup::mojom::HostStatus host_status, const base::Optional<cryptauth::RemoteDeviceRef>& host_device); + void OnFeatureStatesFetched( + const std::string& js_callback_id, + const multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap& + feature_states_map); + + // Returns null if requisite data has not yet been fetched (i.e., if one or + // both of |last_host_status_update_| and |last_feature_states_update_| is + // null). + std::unique_ptr<base::DictionaryValue> GeneratePageContentDataDictionary(); multidevice_setup::MultiDeviceSetupClient* multidevice_setup_client_; @@ -55,6 +75,12 @@ multidevice_setup::MultiDeviceSetupClient::Observer> multidevice_setup_observer_; + base::Optional<std::pair<multidevice_setup::mojom::HostStatus, + base::Optional<cryptauth::RemoteDeviceRef>>> + last_host_status_update_; + base::Optional<multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap> + last_feature_states_update_; + // Used to cancel callbacks when JavaScript becomes disallowed. base::WeakPtrFactory<MultideviceHandler> callback_weak_ptr_factory_;
diff --git a/chrome/browser/ui/webui/settings/chromeos/multidevice_handler_unittest.cc b/chrome/browser/ui/webui/settings/chromeos/multidevice_handler_unittest.cc index 9dd5dbf..363c22f 100644 --- a/chrome/browser/ui/webui/settings/chromeos/multidevice_handler_unittest.cc +++ b/chrome/browser/ui/webui/settings/chromeos/multidevice_handler_unittest.cc
@@ -34,7 +34,9 @@ void VerifyPageContentDict( const base::Value* value, multidevice_setup::mojom::HostStatus expected_host_status, - const base::Optional<cryptauth::RemoteDeviceRef>& expected_host_device) { + const base::Optional<cryptauth::RemoteDeviceRef>& expected_host_device, + const multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap& + feature_states_map) { const base::DictionaryValue* page_content_dict; EXPECT_TRUE(value->GetAsDictionary(&page_content_dict)); @@ -42,16 +44,39 @@ EXPECT_TRUE(page_content_dict->GetInteger("mode", &mode)); EXPECT_EQ(static_cast<int>(expected_host_status), mode); - if (expected_host_device) { - const base::DictionaryValue* remote_device_dict; - EXPECT_TRUE( - page_content_dict->GetDictionary("hostDevice", &remote_device_dict)); + int better_together_state; + EXPECT_TRUE(page_content_dict->GetInteger("betterTogetherState", + &better_together_state)); + auto it = feature_states_map.find( + multidevice_setup::mojom::Feature::kBetterTogetherSuite); + EXPECT_EQ(static_cast<int>(it->second), better_together_state); - std::string name; - EXPECT_TRUE(remote_device_dict->GetString("name", &name)); - EXPECT_EQ(expected_host_device->name(), name); + int instant_tethering_state; + EXPECT_TRUE(page_content_dict->GetInteger("instantTetheringState", + &instant_tethering_state)); + it = feature_states_map.find( + multidevice_setup::mojom::Feature::kInstantTethering); + EXPECT_EQ(static_cast<int>(it->second), instant_tethering_state); + + int messages_state; + EXPECT_TRUE(page_content_dict->GetInteger("messagesState", &messages_state)); + it = feature_states_map.find(multidevice_setup::mojom::Feature::kMessages); + EXPECT_EQ(static_cast<int>(it->second), messages_state); + + int smart_lock_state; + EXPECT_TRUE( + page_content_dict->GetInteger("smartLockState", &smart_lock_state)); + it = feature_states_map.find(multidevice_setup::mojom::Feature::kSmartLock); + EXPECT_EQ(static_cast<int>(it->second), smart_lock_state); + + std::string host_device_name; + if (expected_host_device) { + EXPECT_TRUE( + page_content_dict->GetString("hostDeviceName", &host_device_name)); + EXPECT_EQ(expected_host_device->name(), host_device_name); } else { - EXPECT_FALSE(page_content_dict->GetDictionary("hostDevice", nullptr)); + EXPECT_FALSE( + page_content_dict->GetString("hostDeviceName", &host_device_name)); } } @@ -77,21 +102,40 @@ handler_->AllowJavascript(); } - void CallGetPageContentData( - multidevice_setup::mojom::HostStatus expected_host_status, - const base::Optional<cryptauth::RemoteDeviceRef>& expected_host_device) { + void SetPageContent( + multidevice_setup::mojom::HostStatus host_status, + const base::Optional<cryptauth::RemoteDeviceRef>& host_device, + const multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap& + feature_states_map) { + current_host_status_with_device_ = std::make_pair(host_status, host_device); + current_feature_states_map_ = feature_states_map; + } + + void CallGetPageContentData(bool expected_to_request_data_from_device_sync) { + EXPECT_TRUE(current_host_status_with_device_); + EXPECT_TRUE(current_host_status_with_device_); + size_t call_data_count_before_call = test_web_ui()->call_data().size(); base::ListValue args; args.AppendString("handlerFunctionName"); test_web_ui()->HandleReceivedMessage("getPageContentData", &args); - // The callback did not complete yet, so no call should have been made. - EXPECT_EQ(call_data_count_before_call, test_web_ui()->call_data().size()); + if (expected_to_request_data_from_device_sync) { + // The callback did not complete yet, so no call should have been made. + EXPECT_EQ(call_data_count_before_call, test_web_ui()->call_data().size()); - // Invoke the callback; this should trigger the event to be sent to JS. - fake_multidevice_setup_client()->InvokePendingGetHostStatusCallback( - expected_host_status, expected_host_device); + // Invoke the host status callback. + fake_multidevice_setup_client()->InvokePendingGetHostStatusCallback( + current_host_status_with_device_->first /* host_status */, + current_host_status_with_device_->second /* host_device */); + + // Invoke the feature states callback; this should trigger the event to be + // sent to JS. + fake_multidevice_setup_client()->InvokePendingGetFeatureStatesCallback( + *current_feature_states_map_); + } + EXPECT_EQ(call_data_count_before_call + 1u, test_web_ui()->call_data().size()); @@ -100,13 +144,13 @@ EXPECT_EQ("cr.webUIResponse", call_data.function_name()); EXPECT_EQ("handlerFunctionName", call_data.arg1()->GetString()); EXPECT_TRUE(call_data.arg2()->GetBool()); - VerifyPageContentDict(call_data.arg3(), expected_host_status, - expected_host_device); + VerifyPageContent(call_data.arg3()); } void SimulateHostStatusUpdate( multidevice_setup::mojom::HostStatus host_status, const base::Optional<cryptauth::RemoteDeviceRef>& host_device) { + current_host_status_with_device_ = std::make_pair(host_status, host_device); size_t call_data_count_before_call = test_web_ui()->call_data().size(); fake_multidevice_setup_client_->NotifyHostStatusChanged(host_status, @@ -119,7 +163,26 @@ EXPECT_EQ("cr.webUIListenerCallback", call_data.function_name()); EXPECT_EQ("settings.updateMultidevicePageContentData", call_data.arg1()->GetString()); - VerifyPageContentDict(call_data.arg2(), host_status, host_device); + VerifyPageContent(call_data.arg2()); + } + + void SimulateFeatureStatesUpdate( + const multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap& + feature_states_map) { + current_feature_states_map_ = feature_states_map; + size_t call_data_count_before_call = test_web_ui()->call_data().size(); + + fake_multidevice_setup_client_->NotifyFeatureStateChanged( + feature_states_map); + EXPECT_EQ(call_data_count_before_call + 1u, + test_web_ui()->call_data().size()); + + const content::TestWebUI::CallData& call_data = + CallDataAtIndex(call_data_count_before_call); + EXPECT_EQ("cr.webUIListenerCallback", call_data.function_name()); + EXPECT_EQ("settings.updateMultidevicePageContentData", + call_data.arg1()->GetString()); + VerifyPageContent(call_data.arg2()); } void CallRetryPendingHostSetup(bool success) { @@ -143,34 +206,45 @@ const cryptauth::RemoteDeviceRef test_device_; private: + void VerifyPageContent(const base::Value* value) { + VerifyPageContentDict(value, current_host_status_with_device_->first, + current_host_status_with_device_->second, + *current_feature_states_map_); + } + std::unique_ptr<content::TestWebUI> test_web_ui_; std::unique_ptr<multidevice_setup::FakeMultiDeviceSetupClient> fake_multidevice_setup_client_; std::unique_ptr<TestMultideviceHandler> handler_; + base::Optional<std::pair<multidevice_setup::mojom::HostStatus, + base::Optional<cryptauth::RemoteDeviceRef>>> + current_host_status_with_device_; + base::Optional<multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap> + current_feature_states_map_; + DISALLOW_COPY_AND_ASSIGN(MultideviceHandlerTest); }; TEST_F(MultideviceHandlerTest, PageContentData) { - CallGetPageContentData(multidevice_setup::mojom::HostStatus::kNoEligibleHosts, - base::nullopt /* host_device */); - CallGetPageContentData( - multidevice_setup::mojom::HostStatus::kEligibleHostExistsButNoHostSet, - base::nullopt /* host_device */); - CallGetPageContentData(multidevice_setup::mojom::HostStatus:: - kHostSetLocallyButWaitingForBackendConfirmation, - test_device_); - CallGetPageContentData( - multidevice_setup::mojom::HostStatus::kHostSetButNotYetVerified, - test_device_); - CallGetPageContentData(multidevice_setup::mojom::HostStatus::kHostVerified, - test_device_); -} + static multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap + feature_states_map{ + {multidevice_setup::mojom::Feature::kBetterTogetherSuite, + multidevice_setup::mojom::FeatureState::kUnavailableNoVerifiedHost}, + {multidevice_setup::mojom::Feature::kInstantTethering, + multidevice_setup::mojom::FeatureState::kUnavailableNoVerifiedHost}, + {multidevice_setup::mojom::Feature::kMessages, + multidevice_setup::mojom::FeatureState::kUnavailableNoVerifiedHost}, + {multidevice_setup::mojom::Feature::kSmartLock, + multidevice_setup::mojom::FeatureState::kUnavailableNoVerifiedHost}}; + // multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap + // feature_states_map = GenerateUnverifiedFeatureStatesMap(); -TEST_F(MultideviceHandlerTest, HostStatusUpdates) { - SimulateHostStatusUpdate( - multidevice_setup::mojom::HostStatus::kNoEligibleHosts, - base::nullopt /* host_device */); + SetPageContent(multidevice_setup::mojom::HostStatus::kNoEligibleHosts, + base::nullopt /* host_device */, feature_states_map); + CallGetPageContentData(true /* expected_to_request_data_from_device_sync */); + CallGetPageContentData(false /* expected_to_request_data_from_device_sync */); + SimulateHostStatusUpdate( multidevice_setup::mojom::HostStatus::kEligibleHostExistsButNoHostSet, base::nullopt /* host_device */); @@ -182,6 +256,14 @@ test_device_); SimulateHostStatusUpdate(multidevice_setup::mojom::HostStatus::kHostVerified, test_device_); + + feature_states_map[multidevice_setup::mojom::Feature::kBetterTogetherSuite] = + multidevice_setup::mojom::FeatureState::kEnabledByUser; + SimulateFeatureStatesUpdate(feature_states_map); + + feature_states_map[multidevice_setup::mojom::Feature::kBetterTogetherSuite] = + multidevice_setup::mojom::FeatureState::kDisabledByUser; + SimulateFeatureStatesUpdate(feature_states_map); } TEST_F(MultideviceHandlerTest, RetryPendingHostSetup) {
diff --git a/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc b/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc index 1d48096..d6285df2e 100644 --- a/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc +++ b/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc
@@ -351,8 +351,8 @@ if (!oauth_client_) { oauth_client_.reset(new gaia::GaiaOAuthClient( content::BrowserContext::GetDefaultStoragePartition( - web_ui()->GetWebContents()->GetBrowserContext())-> - GetURLRequestContext())); + web_ui()->GetWebContents()->GetBrowserContext()) + ->GetURLLoaderFactoryForBrowserProcess())); } const std::string token = entry->GetPasswordChangeDetectionToken();
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index b3f3f3d..677b96ce 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -424,12 +424,6 @@ base::FEATURE_DISABLED_BY_DEFAULT}; #endif -#if !defined(OS_ANDROID) -// Enables or disabled the OneGoogleBar on the local NTP. -const base::Feature kOneGoogleBarOnLocalNtp{"OneGoogleBarOnLocalNtp", - base::FEATURE_ENABLED_BY_DEFAULT}; -#endif - #if defined(OS_CHROMEOS) // Enables the Recommend Apps screen in OOBE. // TODO(https://crbug.com/862774): Remove this after the feature is fully @@ -662,6 +656,10 @@ // Enable USBGuard at the lockscreen on Chrome OS. // TODO(crbug.com/874630): Remove this kill-switch const base::Feature kUsbguard{"USBGuard", base::FEATURE_ENABLED_BY_DEFAULT}; + +// Enable running shill in a minijail sandbox on Chrome OS. +const base::Feature kShillSandboxing{"ShillSandboxing", + base::FEATURE_DISABLED_BY_DEFAULT}; #endif // defined(OS_CHROMEOS) #if !defined(OS_ANDROID)
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h index 1b56c28..bf26b67 100644 --- a/chrome/common/chrome_features.h +++ b/chrome/common/chrome_features.h
@@ -226,10 +226,6 @@ extern const base::Feature kOomIntervention; #endif -#if !defined(OS_ANDROID) -extern const base::Feature kOneGoogleBarOnLocalNtp; -#endif - #if defined(OS_CHROMEOS) extern const base::Feature kOobeRecommendAppsScreen; #endif @@ -357,6 +353,8 @@ extern const base::Feature kMachineLearningService; extern const base::Feature kUsbguard; + +extern const base::Feature kShillSandboxing; #endif // defined(OS_CHROMEOS) #if !defined(OS_ANDROID)
diff --git a/chrome/common/page_load_metrics/page_load_metrics.mojom b/chrome/common/page_load_metrics/page_load_metrics.mojom index 4842669..9fcd500 100644 --- a/chrome/common/page_load_metrics/page_load_metrics.mojom +++ b/chrome/common/page_load_metrics/page_load_metrics.mojom
@@ -152,6 +152,8 @@ }; // Data used for the page load. +// TODO(johnidel): Remove/deprecate this struct once per resource updates are +// being sent to the browser struct PageLoadDataUse { // Network bytes received for the page load. int64 received_data_length = 0; @@ -162,11 +164,28 @@ int64 data_reduction_proxy_bytes_saved = 0; }; +struct ResourceDataUpdate { + // The id for the resource request. + int32 request_id = 0; + + // Network bytes received for the resource since the last timing update + // from renderer to browser. + int64 delta_bytes = 0; + + // Total network bytes received for the resource across timing updates. This + // is the aggregate of the |delta_bytes| from each timing update. + int64 received_data_length = 0; + + // Whether this resource load has completed. + bool is_complete; +}; + // Sent from renderer to browser process when the PageLoadTiming for the // associated frame changed. interface PageLoadMetrics { UpdateTiming(PageLoadTiming page_load_timing, PageLoadMetadata page_load_metadata, PageLoadFeatures new_features, - PageLoadDataUse data_use); + PageLoadDataUse data_use, + array<ResourceDataUpdate> resources); };
diff --git a/chrome/renderer/page_load_metrics/fake_page_timing_sender.cc b/chrome/renderer/page_load_metrics/fake_page_timing_sender.cc index 1026984cb..80c3472 100644 --- a/chrome/renderer/page_load_metrics/fake_page_timing_sender.cc +++ b/chrome/renderer/page_load_metrics/fake_page_timing_sender.cc
@@ -18,8 +18,10 @@ const mojom::PageLoadTimingPtr& timing, const mojom::PageLoadMetadataPtr& metadata, mojom::PageLoadFeaturesPtr new_features, - mojom::PageLoadDataUsePtr new_data_use) { - validator_->UpdateTiming(timing, metadata, new_features, new_data_use); + mojom::PageLoadDataUsePtr new_data_use, + std::vector<mojom::ResourceDataUpdatePtr> resources) { + validator_->UpdateTiming(timing, metadata, new_features, new_data_use, + resources); } FakePageTimingSender::PageTimingValidator::PageTimingValidator() {} @@ -95,7 +97,8 @@ const mojom::PageLoadTimingPtr& timing, const mojom::PageLoadMetadataPtr& metadata, const mojom::PageLoadFeaturesPtr& new_features, - const mojom::PageLoadDataUsePtr& new_data_use) { + const mojom::PageLoadDataUsePtr& new_data_use, + const std::vector<mojom::ResourceDataUpdatePtr>& resources) { actual_timings_.push_back(timing.Clone()); for (const auto feature : new_features->features) { EXPECT_EQ(actual_features_.find(feature), actual_features_.end())
diff --git a/chrome/renderer/page_load_metrics/fake_page_timing_sender.h b/chrome/renderer/page_load_metrics/fake_page_timing_sender.h index 910e700..1d873a74 100644 --- a/chrome/renderer/page_load_metrics/fake_page_timing_sender.h +++ b/chrome/renderer/page_load_metrics/fake_page_timing_sender.h
@@ -68,10 +68,12 @@ return actual_timings_; } - void UpdateTiming(const mojom::PageLoadTimingPtr& timing, - const mojom::PageLoadMetadataPtr& metadata, - const mojom::PageLoadFeaturesPtr& new_features, - const mojom::PageLoadDataUsePtr& new_data_use); + void UpdateTiming( + const mojom::PageLoadTimingPtr& timing, + const mojom::PageLoadMetadataPtr& metadata, + const mojom::PageLoadFeaturesPtr& new_features, + const mojom::PageLoadDataUsePtr& new_data_use, + const std::vector<mojom::ResourceDataUpdatePtr>& resources); private: std::vector<mojom::PageLoadTimingPtr> expected_timings_; @@ -88,7 +90,8 @@ void SendTiming(const mojom::PageLoadTimingPtr& timing, const mojom::PageLoadMetadataPtr& metadata, mojom::PageLoadFeaturesPtr new_features, - mojom::PageLoadDataUsePtr new_data_use) override; + mojom::PageLoadDataUsePtr new_data_use, + std::vector<mojom::ResourceDataUpdatePtr> resources) override; private: PageTimingValidator* const validator_;
diff --git a/chrome/renderer/page_load_metrics/metrics_render_frame_observer.cc b/chrome/renderer/page_load_metrics/metrics_render_frame_observer.cc index 40131f3..0e861b3 100644 --- a/chrome/renderer/page_load_metrics/metrics_render_frame_observer.cc +++ b/chrome/renderer/page_load_metrics/metrics_render_frame_observer.cc
@@ -38,14 +38,16 @@ &page_load_metrics_); } ~MojoPageTimingSender() override {} - void SendTiming(const mojom::PageLoadTimingPtr& timing, - const mojom::PageLoadMetadataPtr& metadata, - mojom::PageLoadFeaturesPtr new_features, - mojom::PageLoadDataUsePtr new_data_use) override { + void SendTiming( + const mojom::PageLoadTimingPtr& timing, + const mojom::PageLoadMetadataPtr& metadata, + mojom::PageLoadFeaturesPtr new_features, + mojom::PageLoadDataUsePtr new_data_use, + std::vector<mojom::ResourceDataUpdatePtr> resources) override { DCHECK(page_load_metrics_); - page_load_metrics_->UpdateTiming(timing->Clone(), metadata->Clone(), - std::move(new_features), - std::move(new_data_use)); + page_load_metrics_->UpdateTiming( + timing->Clone(), metadata->Clone(), std::move(new_features), + std::move(new_data_use), std::move(resources)); } private:
diff --git a/chrome/renderer/page_load_metrics/page_resource_data_use.cc b/chrome/renderer/page_load_metrics/page_resource_data_use.cc index 02ba8714..3d1903c2 100644 --- a/chrome/renderer/page_load_metrics/page_resource_data_use.cc +++ b/chrome/renderer/page_load_metrics/page_resource_data_use.cc
@@ -14,7 +14,10 @@ PageResourceDataUse::PageResourceDataUse() : resource_id_(-1), data_reduction_proxy_compression_ratio_estimate_(1.0), - total_received_bytes_(0) {} + total_received_bytes_(0), + last_update_bytes_(0), + is_complete_(false), + is_canceled_(false) {} PageResourceDataUse::~PageResourceDataUse() = default; @@ -25,6 +28,7 @@ data_reduction_proxy_compression_ratio_estimate_ = data_reduction_proxy::EstimateCompressionRatioFromHeaders(&response_head); total_received_bytes_ = 0; + last_update_bytes_ = 0; } void PageResourceDataUse::DidReceiveTransferSizeUpdate( @@ -41,8 +45,10 @@ const network::URLLoaderCompletionStatus& status, mojom::PageLoadDataUse* delta_data_use) { // Report the difference in received bytes. + is_complete_ = true; int64_t delta_bytes = status.encoded_data_length - total_received_bytes_; if (delta_bytes > 0) { + total_received_bytes_ += delta_bytes; delta_data_use->received_data_length += delta_bytes; delta_data_use->data_reduction_proxy_bytes_saved += delta_bytes * (data_reduction_proxy_compression_ratio_estimate_ - 1.0); @@ -51,4 +57,28 @@ return false; } +void PageResourceDataUse::DidCancelResponse() { + is_canceled_ = true; +} + +bool PageResourceDataUse::IsFinishedLoading() { + return is_complete_ || is_canceled_; +} + +int PageResourceDataUse::CalculateNewlyReceivedBytes() { + int newly_received_bytes = total_received_bytes_ - last_update_bytes_; + last_update_bytes_ = total_received_bytes_; + DCHECK(newly_received_bytes >= 0); + return newly_received_bytes; +} + +mojom::ResourceDataUpdatePtr PageResourceDataUse::GetResourceDataUpdate() { + mojom::ResourceDataUpdatePtr resource_data_update = + mojom::ResourceDataUpdate::New(); + resource_data_update->request_id = resource_id(); + resource_data_update->received_data_length = total_received_bytes_; + resource_data_update->delta_bytes = CalculateNewlyReceivedBytes(); + resource_data_update->is_complete = is_complete_; + return resource_data_update; +} } // namespace page_load_metrics
diff --git a/chrome/renderer/page_load_metrics/page_resource_data_use.h b/chrome/renderer/page_load_metrics/page_resource_data_use.h index c115fb6..7391762 100644 --- a/chrome/renderer/page_load_metrics/page_resource_data_use.h +++ b/chrome/renderer/page_load_metrics/page_resource_data_use.h
@@ -34,9 +34,25 @@ bool DidCompleteResponse(const network::URLLoaderCompletionStatus& status, mojom::PageLoadDataUse* delta_data_use); + // Flags the resource as canceled. + void DidCancelResponse(); + + // Checks if the resource has completed loading or if the response was + // cancelled. + bool IsFinishedLoading(); + int resource_id() const { return resource_id_; } + // Creates a ResourceDataUpdate mojo for this resource. This page resource + // contains information since the last time update. Should be called at most + // once once per timing update. + mojom::ResourceDataUpdatePtr GetResourceDataUpdate(); + private: + // Calculates the difference between |total_received_bytes_| and + // |last_update_bytes_|, returns it, and updates |last_update_bytes_|. + int CalculateNewlyReceivedBytes(); + int resource_id_; // Compression ratio estimated from the response headers if data saver was @@ -44,6 +60,10 @@ double data_reduction_proxy_compression_ratio_estimate_; uint64_t total_received_bytes_; + uint64_t last_update_bytes_; + + bool is_complete_; + bool is_canceled_; DISALLOW_ASSIGN(PageResourceDataUse); };
diff --git a/chrome/renderer/page_load_metrics/page_timing_metrics_sender.cc b/chrome/renderer/page_load_metrics/page_timing_metrics_sender.cc index f2dd9ec..974ad11 100644 --- a/chrome/renderer/page_load_metrics/page_timing_metrics_sender.cc +++ b/chrome/renderer/page_load_metrics/page_timing_metrics_sender.cc
@@ -61,8 +61,9 @@ void PageTimingMetricsSender::DidObserveLoadingBehavior( blink::WebLoadingBehaviorFlag behavior) { - if (behavior & metadata_->behavior_flags) + if (behavior & metadata_->behavior_flags) { return; + } metadata_->behavior_flags |= behavior; EnsureSendTimer(); } @@ -70,8 +71,9 @@ void PageTimingMetricsSender::DidObserveNewFeatureUsage( blink::mojom::WebFeature feature) { int32_t feature_id = static_cast<int32_t>(feature); - if (features_sent_.test(feature_id)) + if (features_sent_.test(feature_id)) { return; + } features_sent_.set(feature_id); new_features_->features.push_back(feature); EnsureSendTimer(); @@ -109,11 +111,13 @@ // It is possible that resources are not in the map, if response headers were // not received or for failed/cancelled resources. - if (resource_it == page_resource_data_use_.end()) + if (resource_it == page_resource_data_use_.end()) { return; + } resource_it->second.DidReceiveTransferSizeUpdate(received_data_length, new_data_use_.get()); + modified_resources_.insert(&resource_it->second); EnsureSendTimer(); } @@ -132,17 +136,24 @@ resource_it = new_resource_it.first; } - if (resource_it->second.DidCompleteResponse(status, new_data_use_.get())) + if (resource_it->second.DidCompleteResponse(status, new_data_use_.get())) { EnsureSendTimer(); + } + modified_resources_.insert(&resource_it->second); } void PageTimingMetricsSender::DidCancelResponse(int resource_id) { - page_resource_data_use_.erase(resource_id); + auto resource_it = page_resource_data_use_.find(resource_id); + if (resource_it == page_resource_data_use_.end()) { + return; + } + resource_it->second.DidCancelResponse(); } void PageTimingMetricsSender::Send(mojom::PageLoadTimingPtr timing) { - if (last_timing_->Equals(*timing)) + if (last_timing_->Equals(*timing)) { return; + } // We want to make sure that each PageTimingMetricsSender is associated // with a distinct page navigation. Because we reset the object on commit, @@ -170,10 +181,18 @@ void PageTimingMetricsSender::SendNow() { have_sent_ipc_ = true; + std::vector<mojom::ResourceDataUpdatePtr> resources; + for (auto* resource : modified_resources_) { + resources.push_back(resource->GetResourceDataUpdate()); + if (resource->IsFinishedLoading()) { + page_resource_data_use_.erase(resource->resource_id()); + } + } sender_->SendTiming(last_timing_, metadata_, std::move(new_features_), - std::move(new_data_use_)); + std::move(new_data_use_), std::move(resources)); new_features_ = mojom::PageLoadFeatures::New(); new_data_use_ = mojom::PageLoadDataUse::New(); + modified_resources_.clear(); } } // namespace page_load_metrics
diff --git a/chrome/renderer/page_load_metrics/page_timing_metrics_sender.h b/chrome/renderer/page_load_metrics/page_timing_metrics_sender.h index 15529ed1..4f0b611 100644 --- a/chrome/renderer/page_load_metrics/page_timing_metrics_sender.h +++ b/chrome/renderer/page_load_metrics/page_timing_metrics_sender.h
@@ -8,6 +8,7 @@ #include <bitset> #include <memory> +#include "base/containers/flat_set.h" #include "base/containers/small_map.h" #include "base/macros.h" #include "chrome/common/page_load_metrics/page_load_timing.h" @@ -83,9 +84,15 @@ bool have_sent_ipc_ = false; + // The page's resources that are currently loading, or were completed after + // the last timing update. base::small_map<std::map<int, PageResourceDataUse>, 16> page_resource_data_use_; + // Set of all resources that have completed or received a transfer + // size update since the last timimg update. + base::flat_set<PageResourceDataUse*> modified_resources_; + // Field trial for alternating page timing metrics sender buffer timer delay. // https://crbug.com/847269. int buffer_timer_delay_ms_;
diff --git a/chrome/renderer/page_load_metrics/page_timing_sender.h b/chrome/renderer/page_load_metrics/page_timing_sender.h index b0e59214..3ab07ea9 100644 --- a/chrome/renderer/page_load_metrics/page_timing_sender.h +++ b/chrome/renderer/page_load_metrics/page_timing_sender.h
@@ -14,10 +14,12 @@ class PageTimingSender { public: virtual ~PageTimingSender() {} - virtual void SendTiming(const mojom::PageLoadTimingPtr& timing, - const mojom::PageLoadMetadataPtr& metadata, - mojom::PageLoadFeaturesPtr new_features, - mojom::PageLoadDataUsePtr new_data_use) = 0; + virtual void SendTiming( + const mojom::PageLoadTimingPtr& timing, + const mojom::PageLoadMetadataPtr& metadata, + mojom::PageLoadFeaturesPtr new_features, + mojom::PageLoadDataUsePtr new_data_use, + std::vector<mojom::ResourceDataUpdatePtr> resources) = 0; }; } // namespace page_load_metrics
diff --git a/chrome/service/cloud_print/DEPS b/chrome/service/cloud_print/DEPS index 9e66b99..01a9fac1 100644 --- a/chrome/service/cloud_print/DEPS +++ b/chrome/service/cloud_print/DEPS
@@ -5,4 +5,5 @@ "+google_apis", # sync notifier depends on the common jingle notifier classes. "+jingle/notifier", + "+services/network", ]
diff --git a/chrome/service/cloud_print/cloud_print_auth.cc b/chrome/service/cloud_print/cloud_print_auth.cc index 3a2ba1b9..8acf7d6 100644 --- a/chrome/service/cloud_print/cloud_print_auth.cc +++ b/chrome/service/cloud_print/cloud_print_auth.cc
@@ -14,8 +14,8 @@ #include "chrome/common/cloud_print/cloud_print_helpers.h" #include "chrome/service/cloud_print/cloud_print_token_store.h" #include "chrome/service/net/service_url_request_context_getter.h" -#include "chrome/service/service_process.h" #include "google_apis/gaia/gaia_urls.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" namespace cloud_print { @@ -95,8 +95,8 @@ robot_email_ = robot_email; // Now that we have an auth code we need to get the refresh and access tokens. - oauth_client_.reset(new gaia::GaiaOAuthClient( - g_service_process->GetServiceURLRequestContextGetter())); + oauth_client_.reset( + new gaia::GaiaOAuthClient(client_->GetURLLoaderFactory())); oauth_client_->GetTokensFromAuthCode(oauth_client_info_, robot_oauth_auth_code, kCloudPrintAuthMaxRetryCount, @@ -106,8 +106,8 @@ void CloudPrintAuth::RefreshAccessToken() { UMA_HISTOGRAM_ENUMERATION("CloudPrint.AuthEvent", AUTH_EVENT_REFRESH_REQUEST, AUTH_EVENT_MAX); - oauth_client_.reset(new gaia::GaiaOAuthClient( - g_service_process->GetServiceURLRequestContextGetter())); + oauth_client_.reset( + new gaia::GaiaOAuthClient(client_->GetURLLoaderFactory())); std::vector<std::string> empty_scope_list; // (Use scope from refresh token.) oauth_client_->RefreshToken(oauth_client_info_, refresh_token_, @@ -191,8 +191,8 @@ json_data->GetString(kXMPPJidValue, &robot_email_); // Now that we have an auth code we need to get the refresh and access tokens. - oauth_client_.reset(new gaia::GaiaOAuthClient( - g_service_process->GetServiceURLRequestContextGetter())); + oauth_client_.reset( + new gaia::GaiaOAuthClient(client_->GetURLLoaderFactory())); oauth_client_->GetTokensFromAuthCode(oauth_client_info_, auth_code, kCloudPrintAPIMaxRetryCount,
diff --git a/chrome/service/cloud_print/cloud_print_auth.h b/chrome/service/cloud_print/cloud_print_auth.h index d19dafb..a295398 100644 --- a/chrome/service/cloud_print/cloud_print_auth.h +++ b/chrome/service/cloud_print/cloud_print_auth.h
@@ -15,6 +15,10 @@ #include "net/traffic_annotation/network_traffic_annotation.h" #include "url/gurl.h" +namespace network { +class SharedURLLoaderFactory; +} + namespace cloud_print { // CloudPrintAuth is a class to handle login, token refresh, and other @@ -35,6 +39,9 @@ const std::string& robot_email, const std::string& user_email) = 0; virtual void OnInvalidCredentials() = 0; + virtual scoped_refptr<network::SharedURLLoaderFactory> + GetURLLoaderFactory() = 0; + protected: virtual ~Client() {} };
diff --git a/chrome/service/cloud_print/cloud_print_proxy_backend.cc b/chrome/service/cloud_print/cloud_print_proxy_backend.cc index f8b4da12..d2d5729 100644 --- a/chrome/service/cloud_print/cloud_print_proxy_backend.cc +++ b/chrome/service/cloud_print/cloud_print_proxy_backend.cc
@@ -34,6 +34,8 @@ #include "jingle/notifier/listener/push_client.h" #include "jingle/notifier/listener/push_client_observer.h" #include "net/traffic_annotation/network_traffic_annotation.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" +#include "services/network/transitional_url_loader_factory_owner.h" #include "url/gurl.h" namespace cloud_print { @@ -104,6 +106,7 @@ const std::string& robot_email, const std::string& user_email) override; void OnInvalidCredentials() override; + scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override; // CloudPrintConnector::Client implementation. void OnAuthFailed() override; @@ -165,6 +168,10 @@ // Our parent CloudPrintProxyBackend CloudPrintProxyBackend* const backend_; + // Provides access to networking APIs for auth_. + std::unique_ptr<network::TransitionalURLLoaderFactoryOwner> + url_loader_factory_owner_; + // Cloud Print authenticator. scoped_refptr<CloudPrintAuth> auth_; @@ -267,13 +274,13 @@ const ConnectorSettings& settings, const gaia::OAuthClientInfo& oauth_client_info, bool enable_job_poll) - : backend_(backend), - oauth_client_info_(oauth_client_info), - notifications_enabled_(false), - job_poll_scheduled_(false), - enable_job_poll_(enable_job_poll), - xmpp_ping_scheduled_(false), - pending_xmpp_pings_(0) { + : backend_(backend), + oauth_client_info_(oauth_client_info), + notifications_enabled_(false), + job_poll_scheduled_(false), + enable_job_poll_(enable_job_poll), + xmpp_ping_scheduled_(false), + pending_xmpp_pings_(0) { settings_.CopyFrom(settings); } @@ -381,6 +388,18 @@ base::Bind(&Core::NotifyAuthenticationFailed, this)); } +scoped_refptr<network::SharedURLLoaderFactory> +CloudPrintProxyBackend::Core::GetURLLoaderFactory() { + DCHECK(CurrentlyOnCoreThread()); + if (!url_loader_factory_owner_) { + url_loader_factory_owner_ = + std::make_unique<network::TransitionalURLLoaderFactoryOwner>( + g_service_process->GetServiceURLRequestContextGetter()); + } + + return url_loader_factory_owner_->GetURLLoaderFactory(); +} + void CloudPrintProxyBackend::Core::OnAuthFailed() { VLOG(1) << "CP_CONNECTOR: Authentication failed in connector."; // Let's stop connecter and refresh token. We'll restart connecter once @@ -438,6 +457,7 @@ notifications_enabled_ = false; notifications_enabled_since_ = base::TimeTicks(); token_store_.reset(); + url_loader_factory_owner_.reset(); DestroyAuthAndConnector(); }
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 092c8d5c..3d8d7b4b 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -1972,8 +1972,6 @@ "../browser/ui/cocoa/apps/app_shim_menu_controller_mac_browsertest.mm", "../browser/ui/cocoa/apps/native_app_window_cocoa_browsertest.mm", "../browser/ui/cocoa/dev_tools_controller_browsertest.mm", - "../browser/ui/cocoa/extensions/extension_install_prompt_test_utils.h", - "../browser/ui/cocoa/extensions/extension_install_prompt_test_utils.mm", "../browser/ui/cocoa/extensions/media_galleries_dialog_cocoa_browsertest.mm", "../browser/ui/cocoa/find_bar/find_bar_browsertest.mm", "../browser/ui/cocoa/location_bar/content_setting_decoration_browsertest.mm", @@ -1998,8 +1996,6 @@ ## not compile and should be removed (along with test file) when the ## corresponding release code is deleted. # "../browser/ui/cocoa/constrained_window/constrained_window_mac_browsertest.mm", - # "../browser/ui/cocoa/extensions/extension_install_dialog_controller_browsertest.mm", - # "../browser/ui/cocoa/extensions/windowed_install_dialog_controller_browsertest.mm", # "../browser/ui/cocoa/page_info/page_info_bubble_views_mac_browsertest.mm", ] } @@ -4160,10 +4156,6 @@ "../browser/ui/cocoa/draggable_button_unittest.mm", "../browser/ui/cocoa/extensions/browser_actions_container_view_unittest.mm", "../browser/ui/cocoa/extensions/chooser_dialog_cocoa_controller_unittest.mm", - "../browser/ui/cocoa/extensions/extension_install_prompt_test_utils.h", - "../browser/ui/cocoa/extensions/extension_install_prompt_test_utils.mm", - "../browser/ui/cocoa/extensions/extension_install_view_controller_unittest.mm", - "../browser/ui/cocoa/extensions/extension_installed_bubble_controller_unittest.mm", "../browser/ui/cocoa/extensions/media_galleries_dialog_cocoa_unittest.mm", "../browser/ui/cocoa/extensions/toolbar_actions_bar_bubble_mac_unittest.mm", "../browser/ui/cocoa/find_bar/find_bar_bridge_unittest.mm", @@ -4264,8 +4256,6 @@ if (mac_views_browser) { sources -= [ "../browser/ui/cocoa/extensions/chooser_dialog_cocoa_controller_unittest.mm", - "../browser/ui/cocoa/extensions/extension_install_view_controller_unittest.mm", - "../browser/ui/cocoa/extensions/extension_installed_bubble_controller_unittest.mm", "../browser/ui/cocoa/extensions/media_galleries_dialog_cocoa_unittest.mm", "../browser/ui/cocoa/page_info/page_info_bubble_controller_unittest.mm", ]
diff --git a/chrome/test/chromedriver/BUILD.gn b/chrome/test/chromedriver/BUILD.gn index cb16c26..b27dd4a 100644 --- a/chrome/test/chromedriver/BUILD.gn +++ b/chrome/test/chromedriver/BUILD.gn
@@ -150,6 +150,8 @@ "chrome/web_view.h", "chrome/web_view_impl.cc", "chrome/web_view_impl.h", + "log_replay/devtools_log_reader.cc", + "log_replay/devtools_log_reader.h", "net/adb_client_socket.cc", "net/adb_client_socket.h", "net/net_util.cc", @@ -386,6 +388,7 @@ "chrome_launcher_unittest.cc", "command_listener_proxy_unittest.cc", "commands_unittest.cc", + "log_replay/devtools_log_reader_unittest.cc", "logging_unittest.cc", "net/adb_client_socket_unittest.cc", "net/timeout_unittest.cc", @@ -402,6 +405,7 @@ data = [ "//chrome/test/data/chromedriver/", + "//chrome/test/chromedriver/log_replay/test_data", ] deps = [
diff --git a/chrome/test/chromedriver/chrome/devtools_client_impl.cc b/chrome/test/chromedriver/chrome/devtools_client_impl.cc index d6372ee..dde4f5ca 100644 --- a/chrome/test/chromedriver/chrome/devtools_client_impl.cc +++ b/chrome/test/chromedriver/chrome/devtools_client_impl.cc
@@ -310,8 +310,10 @@ command.SetKey("params", params.Clone()); std::string message = SerializeValue(&command); if (IsVLogOn(1)) { - VLOG(1) << "DEVTOOLS COMMAND " << method << " (id=" << command_id << ") " - << FormatValueForDisplay(params); + // Note: ChromeDriver log-replay depends on the format of this logging. + // see chromedriver/log_replay/devtools_log_reader.cc. + VLOG(1) << "DevTools WebSocket Command: " << method << " (id=" << command_id + << ") " << FormatValueForDisplay(params); } if (parent_ != nullptr) { base::DictionaryValue params2; @@ -433,7 +435,9 @@ Status DevToolsClientImpl::ProcessEvent(const internal::InspectorEvent& event) { if (IsVLogOn(1)) { - VLOG(1) << "DEVTOOLS EVENT " << event.method << " " + // Note: ChromeDriver log-replay depends on the format of this logging. + // see chromedriver/log_replay/devtools_log_reader.cc. + VLOG(1) << "DevTools WebSocket Event: " << event.method << " " << FormatValueForDisplay(*event.params); } unnotified_event_listeners_ = listeners_; @@ -507,8 +511,10 @@ result = FormatValueForDisplay(*response.result); else result = response.error; - VLOG(1) << "DEVTOOLS RESPONSE " << method << " (id=" << response.id - << ") " << result; + // Note: ChromeDriver log-replay depends on the format of this logging. + // see chromedriver/log_replay/devtools_log_reader.cc. + VLOG(1) << "DevTools WebSocket Response: " << method + << " (id=" << response.id << ") " << result; } if (iter == response_info_map_.end())
diff --git a/chrome/test/chromedriver/chrome/devtools_http_client.cc b/chrome/test/chromedriver/chrome/devtools_http_client.cc index 760da07..7c9d0e9 100644 --- a/chrome/test/chromedriver/chrome/devtools_http_client.cc +++ b/chrome/test/chromedriver/chrome/devtools_http_client.cc
@@ -241,12 +241,12 @@ bool DevToolsHttpClient::FetchUrlAndLog(const std::string& url, URLRequestContextGetter* getter, std::string* response) { - VLOG(1) << "DevTools request: " << url; + VLOG(1) << "DevTools HTTP Request: " << url; bool ok = FetchUrl(url, getter, response); if (ok) { - VLOG(1) << "DevTools response: " << *response; + VLOG(1) << "DevTools HTTP Response: " << *response; } else { - VLOG(1) << "DevTools request failed"; + VLOG(1) << "DevTools HTTP Request failed"; } return ok; }
diff --git a/chrome/test/chromedriver/commands.cc b/chrome/test/chromedriver/commands.cc index 553ef3d..cc8dc833 100644 --- a/chrome/test/chromedriver/commands.cc +++ b/chrome/test/chromedriver/commands.cc
@@ -220,6 +220,8 @@ if (IsVLogOn(0)) { if (!session->driver_log || session->driver_log->min_level() != Log::Level::kOff) { + // Note: ChromeDriver log-replay depends on the format of this logging. + // see chromedriver/log_replay/client_replay.py VLOG(0) << "[" << session->id << "] " << "COMMAND " << command_name << " " << FormatValueForDisplay(*params); @@ -277,6 +279,8 @@ } if (!session->driver_log || session->driver_log->min_level() != Log::Level::kOff) { + // Note: ChromeDriver log-replay depends on the format of this logging. + // see chromedriver/log_replay/client_replay.py VLOG(0) << "[" << session->id << "] " << "RESPONSE " << command_name << (result.length() ? " " + result : "");
diff --git a/chrome/test/chromedriver/log_replay/devtools_log_reader.cc b/chrome/test/chromedriver/log_replay/devtools_log_reader.cc new file mode 100644 index 0000000..58986b28 --- /dev/null +++ b/chrome/test/chromedriver/log_replay/devtools_log_reader.cc
@@ -0,0 +1,164 @@ +// 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. +#include "chrome/test/chromedriver/log_replay/devtools_log_reader.h" + +#include <iostream> +#include <string> + +#include "base/logging.h" +#include "base/strings/pattern.h" + +namespace { +// Parses the word (id=X) and just returns the id number +int GetId(std::istringstream& header_stream) { + int id = 0; + header_stream.ignore(5); // ignore the " (id=" characters + header_stream >> id; + header_stream.ignore(1); // ignore the final parenthesis + return id; +} +} // namespace + +LogEntry::LogEntry(std::istringstream& header_stream) { + error = false; + std::string protocol_type_string; + header_stream >> protocol_type_string; // "HTTP" or "WebSocket" + if (protocol_type_string == "HTTP") { + protocol_type = HTTP; + } else if (protocol_type_string == "WebSocket") { + protocol_type = WebSocket; + } else { + error = true; + LOG(ERROR) << "Could not read protocol from log entry header."; + return; + } + + std::string event_type_string; + header_stream >> event_type_string; + + if (event_type_string == "Response:") { + event_type = response; + } else if (event_type_string == "Command:" || + event_type_string == "Request:") { + event_type = request; + } else if (event_type_string == "Event:") { + event_type = event; + } else { + error = true; + LOG(ERROR) << "Could not read event type from log entry header."; + return; + } + + if (!(protocol_type == HTTP && event_type == response)) { + header_stream >> command_name; + if (command_name == "") { + error = true; + LOG(ERROR) << "Could not read command name from log entry header"; + return; + } + if (protocol_type != HTTP) { + id = GetId(header_stream); + if (id == 0) { + error = true; + LOG(ERROR) << "Could not read sequential id from log entry header."; + return; + } + } + } +} + +LogEntry::~LogEntry() {} + +DevToolsLogReader::DevToolsLogReader(const base::FilePath& log_path) + : log_file(log_path.value().c_str(), std::ios::in) {} + +DevToolsLogReader::~DevToolsLogReader() {} + +bool DevToolsLogReader::IsHeader(std::istringstream& header_stream) { + std::string word; + header_stream >> word; // preamble + if (!base::MatchPattern(word, "[??????????.???][DEBUG]:")) { + return false; + } + header_stream >> word; // "DevTools" for DevTools commands/responses/events + bool result = word == "DevTools"; + return result; +} + +std::unique_ptr<LogEntry> DevToolsLogReader::GetNext( + LogEntry::Protocol protocol_type) { + std::string next_line; + while (true) { + if (log_file.eof()) + return nullptr; + std::getline(log_file, next_line); + + std::istringstream next_line_stream(next_line); + if (IsHeader(next_line_stream)) { + std::unique_ptr<LogEntry> log_entry = + std::make_unique<LogEntry>(next_line_stream); + if (log_entry->error) { + return nullptr; // helpful error message already logged + } + if (log_entry->protocol_type != protocol_type) + continue; + if (!(log_entry->event_type == LogEntry::EventType::request && + log_entry->protocol_type == LogEntry::Protocol::HTTP)) { + log_entry->payload = GetJSONString(next_line_stream); + if (log_entry->payload == "") { + LOG(ERROR) << "Problem parsing JSON from log file"; + return nullptr; + } + } + return log_entry; + } + } +} + +std::string DevToolsLogReader::GetJSONString( + std::istringstream& header_stream) { + std::string next_line, json; + + int opening_char_count = 0; + std::getline(header_stream, next_line); + next_line = next_line.substr(1); + char opening_char = next_line[0]; + char closing_char; + switch (opening_char) { + case '{': + closing_char = '}'; + break; + case '[': + closing_char = ']'; + break; + default: + return ""; + } + while (true) { + json += next_line; + opening_char_count += CountChar(next_line, opening_char, closing_char); + if (opening_char_count == 0) + break; + if (log_file.eof()) + return ""; + getline(log_file, next_line); + } + return json; +} + +int DevToolsLogReader::CountChar(const std::string& line, + char opening_char, + char closing_char) const { + bool in_quote = false; + int total = 0; + for (size_t i = 0; i < line.length(); i++) { + if (!in_quote && line[i] == opening_char) + total++; + if (!in_quote && line[i] == closing_char) + total--; + if (line[i] == '"' && (i == 0 || line[i - 1] != '\\')) + in_quote = !in_quote; + } + return total; +}
diff --git a/chrome/test/chromedriver/log_replay/devtools_log_reader.h b/chrome/test/chromedriver/log_replay/devtools_log_reader.h new file mode 100644 index 0000000..0fb734d8d --- /dev/null +++ b/chrome/test/chromedriver/log_replay/devtools_log_reader.h
@@ -0,0 +1,95 @@ +// 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_TEST_CHROMEDRIVER_LOG_REPLAY_DEVTOOLS_LOG_READER_H_ +#define CHROME_TEST_CHROMEDRIVER_LOG_REPLAY_DEVTOOLS_LOG_READER_H_ + +#include <fstream> +#include <memory> +#include <string> + +#include "base/files/file_path.h" + +// Represents one DevTools entry (command or response) in the log. +// +// These appear in the log in the following format: +// [<timestamp>][DEBUG]: DevTools <protocol_type> <event_type> <command_name> +// (id=<id>) <payload> +// where: +// +// <protocol_type> is either HTTP or WebSocket +// +// <event_type> is either "Command:" (for WebSocket only), "Request:" (for HTTP +// only), "Response:", or "Event:" +// +// <command_name> is the command for WebSocket (like "DOM.getDocument") or a url +// for HTTP (like "http://localhost:38845/json") +// +// <id> is a sequential number to identify WebSocket commands with their +// responses +// +// <payload> is either the parameters in case of a WebSocket command, or the +// response in case of any response. It is always a JSON, and always spans +// multiple lines. +class LogEntry { + public: + // Build this LogEntry using the header line of an entry in the log. This + // doesn't initialize the payload member. The payload must be parsed from + // lines after the header. + explicit LogEntry(std::istringstream& header_stream); + ~LogEntry(); + + enum EventType { + request, // Command or Request depending on HTTP or WebSocket client + response, + event + }; + enum Protocol { HTTP, WebSocket }; + + EventType event_type; + Protocol protocol_type; + std::string command_name; + std::string payload; + int id; + bool error; +}; + +// Reads a log file for DevTools entries. +class DevToolsLogReader { + public: + // Initialize the log reader using a path to a log file to read from. + explicit DevToolsLogReader(const base::FilePath& log_path); + ~DevToolsLogReader(); + + // Get the next DevTools entry in the log of the specified protocol type. + // + // This returns commands, responses, and events separately. If there are + // no remaining entries of the specified type, or if there is some other + // problem encountered like a truncated JSON, nullptr is returned. + std::unique_ptr<LogEntry> GetNext(LogEntry::Protocol protocol_type); + + private: + std::ifstream log_file; + // Starting with |header_line|, parse a JSON string out of the log file. + // + // will parse either list or dictionary-type JSON strings, depending on the + // starting character. + std::string GetJSONString(std::istringstream& header_line); + + // Return whether |line| is a header of a DevTools entry. + // + // This only parses out the first two words of the line, meaning that the + // stream can be re-used to parse the specifics of the entry after calling + // this. + bool IsHeader(std::istringstream& line); + + // Count (number of opening_char) - (number of closing_char) in |line|. + // + // Used to check for the end of JSON parameters. Ignores characters inside of + // non-escaped quotes. + int CountChar(const std::string& line, + char opening_char, + char closing_char) const; +}; + +#endif // CHROME_TEST_CHROMEDRIVER_LOG_REPLAY_DEVTOOLS_LOG_READER_H_
diff --git a/chrome/test/chromedriver/log_replay/devtools_log_reader_unittest.cc b/chrome/test/chromedriver/log_replay/devtools_log_reader_unittest.cc new file mode 100644 index 0000000..d653c88 --- /dev/null +++ b/chrome/test/chromedriver/log_replay/devtools_log_reader_unittest.cc
@@ -0,0 +1,111 @@ +// 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. +#include "chrome/test/chromedriver/log_replay/devtools_log_reader.h" + +#include "base/base_paths.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/path_service.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace { +// Log files to test the reader against +const char* const kTestDataPath[] = {"chrome", "test", "chromedriver", + "log_replay", "test_data"}; +const char kTestGetTitlePath[] = "testGetTitle_simple.log"; +const char kOneEntryPath[] = "oneDevToolsEntry.log"; +const char kTruncatedJSONPath[] = "truncatedJSON.log"; + +base::FilePath GetLogFileFromLiteral(const char literal[]) { + base::FilePath root_dir; + CHECK(base::PathService::Get(base::DIR_SOURCE_ROOT, &root_dir)); + for (int i = 0; i < 5; i++) + root_dir = root_dir.AppendASCII(kTestDataPath[i]); + base::FilePath result = root_dir.AppendASCII(literal); + CHECK(base::PathExists(result)); + return result; +} +} // namespace + +TEST(DevToolsLogReaderTest, Basic) { + base::FilePath path = GetLogFileFromLiteral(kTestGetTitlePath); + DevToolsLogReader reader(path); + std::unique_ptr<LogEntry> next = reader.GetNext(LogEntry::Protocol::HTTP); + EXPECT_TRUE(next != nullptr); + EXPECT_EQ(next->protocol_type, LogEntry::Protocol::HTTP); + EXPECT_EQ(next->command_name, "http://localhost:38845/json/version"); + next = reader.GetNext(LogEntry::Protocol::HTTP); + EXPECT_TRUE(next != nullptr); + EXPECT_EQ(next->payload, "{ \"string_key\": \"string_value\"}"); +} + +TEST(DevToolsLogReaderTest, Multiple) { + base::FilePath path = GetLogFileFromLiteral(kTestGetTitlePath); + DevToolsLogReader reader(path); + std::unique_ptr<LogEntry> next; + for (int i = 0; i < 3; i++) + next = reader.GetNext(LogEntry::Protocol::HTTP); + + EXPECT_TRUE(next != nullptr); + EXPECT_EQ(next->command_name, "http://localhost:38845/json"); + next = reader.GetNext(LogEntry::Protocol::HTTP); + EXPECT_EQ(next->payload, + "[ { \"string_key1\": \"string_value1\"}, { " + "\"string_key2\": \"string_value2\"} ]"); +} + +TEST(DevToolsLogReaderTest, EndOfFile) { + base::FilePath path = GetLogFileFromLiteral(kOneEntryPath); + DevToolsLogReader reader(path); + std::unique_ptr<LogEntry> next = reader.GetNext(LogEntry::Protocol::HTTP); + EXPECT_TRUE(next != nullptr); + next = reader.GetNext(LogEntry::Protocol::HTTP); + EXPECT_TRUE(next == nullptr); +} + +TEST(DevToolsLogReaderTest, WebSocketBasic) { + base::FilePath path = GetLogFileFromLiteral(kTestGetTitlePath); + DevToolsLogReader reader(path); + std::unique_ptr<LogEntry> next = + reader.GetNext(LogEntry::Protocol::WebSocket); + EXPECT_TRUE(next != nullptr); + EXPECT_EQ(next->protocol_type, LogEntry::Protocol::WebSocket); + EXPECT_EQ(next->event_type, LogEntry::EventType::request); + EXPECT_EQ(next->command_name, "Log.enable"); + EXPECT_EQ(next->id, 1); +} + +TEST(DevToolsLogReaderTest, WebSocketMultiple) { + base::FilePath path = GetLogFileFromLiteral(kTestGetTitlePath); + DevToolsLogReader reader(path); + std::unique_ptr<LogEntry> next = + reader.GetNext(LogEntry::Protocol::WebSocket); + next = reader.GetNext(LogEntry::Protocol::WebSocket); + EXPECT_TRUE(next != nullptr); + EXPECT_EQ(next->event_type, LogEntry::EventType::request); + EXPECT_EQ(next->command_name, "DOM.getDocument"); + EXPECT_EQ(next->id, 2); +} + +TEST(DevToolsLogReaderTest, WebSocketPayload) { + base::FilePath path = GetLogFileFromLiteral(kTestGetTitlePath); + DevToolsLogReader reader(path); + std::unique_ptr<LogEntry> next; + for (int i = 0; i < 3; i++) + next = reader.GetNext(LogEntry::Protocol::WebSocket); + EXPECT_TRUE(next != nullptr); + EXPECT_EQ(next->command_name, "Target.setAutoAttach"); + EXPECT_EQ(next->id, 3); + EXPECT_EQ(next->payload, + "{ \"autoAttach\": true, \"waitForDebuggerOnStart\": false}"); +} + +TEST(DevToolsLogReaderTest, TruncatedJSON) { + base::FilePath path = GetLogFileFromLiteral(kTruncatedJSONPath); + DevToolsLogReader reader(path); + std::unique_ptr<LogEntry> next = + reader.GetNext(LogEntry::Protocol::WebSocket); + EXPECT_TRUE(next == nullptr); +}
diff --git a/chrome/test/chromedriver/log_replay/test_data/oneDevToolsEntry.log b/chrome/test/chromedriver/log_replay/test_data/oneDevToolsEntry.log new file mode 100644 index 0000000..df207fe --- /dev/null +++ b/chrome/test/chromedriver/log_replay/test_data/oneDevToolsEntry.log
@@ -0,0 +1 @@ +[1533082321.074][DEBUG]: DevTools HTTP Request: http://localhost:38845/json/version \ No newline at end of file
diff --git a/chrome/test/chromedriver/log_replay/test_data/testGetTitle_simple.log b/chrome/test/chromedriver/log_replay/test_data/testGetTitle_simple.log new file mode 100644 index 0000000..26a190b --- /dev/null +++ b/chrome/test/chromedriver/log_replay/test_data/testGetTitle_simple.log
@@ -0,0 +1,480 @@ +[1533082318.791][INFO]: [37ab6acf4be79d7e368e3260482cd6a2] COMMAND InitSession { + "desiredCapabilities": { + "chromeOptions": { + "args": [ "no-sandbox", "disable-gpu" ], + "binary": "/usr/local/google/home/cwinstanley/chromium/src/out/Default/chrome" + }, + "goog:testName": "__main__.ChromeDriverTest.testGetTitle", + "loggingPrefs": { + + } + } +} +[1533082318.792][INFO]: Populating Preferences file: { + "alternate_error_pages": { + "enabled": false + }, + "autofill": { + "enabled": false + }, + "browser": { + "check_default_browser": false + }, + "distribution": { + "import_bookmarks": false, + "import_history": false, + "import_search_engine": false, + "make_chrome_default_for_user": false, + "skip_first_run_ui": true + }, + "dns_prefetching": { + "enabled": false + }, + "profile": { + "content_settings": { + "pattern_pairs": { + "https://*,*": { + "media-stream": { + "audio": "Default", + "video": "Default" + } + } + } + }, + "default_content_setting_values": { + "geolocation": 1 + }, + "default_content_settings": { + "geolocation": 1, + "mouselock": 1, + "notifications": 1, + "popups": 1, + "ppapi-broker": 1 + }, + "password_manager_enabled": false + }, + "safebrowsing": { + "enabled": false + }, + "search": { + "suggest_enabled": false + }, + "translate": { + "enabled": false + } +} +[1533082318.792][INFO]: Populating Local State file: { + "background_mode": { + "enabled": false + }, + "ssl": { + "rev_checking": { + "enabled": false + } + } +} +[1533082318.793][INFO]: Launching chrome: /usr/local/google/home/cwinstanley/chromium/src/out/Default/chrome --disable-background-networking --disable-client-side-phishing-detection --disable-default-apps --disable-gpu --disable-hang-monitor --disable-popup-blocking --disable-prompt-on-repost --disable-sync --disable-web-resources --enable-automation --enable-logging --force-fieldtrials=SiteIsolationExtensions/Control --ignore-certificate-errors --load-extension=/tmp/.org.chromium.Chromium.EUcaSh/internal --log-level=0 --metrics-recording-only --no-first-run --no-sandbox --password-store=basic --remote-debugging-port=0 --test-type=webdriver --use-mock-keychain --user-data-dir=/tmp/.org.chromium.Chromium.E0v4OG data:, +[47071:47071:0731/171200.838032:ERROR:gpu_process_transport_factory.cc(642)] Switching to software compositing. +[47071:47071:0731/171200.838096:ERROR:gpu_process_transport_factory.cc(1007)] Lost UI shared context. +[47071:47071:0731/171200.917972:WARNING:account_consistency_mode_manager.cc(290)] Desktop Identity Consistency cannot be enabled as no OAuth client ID and client secret have been configured. +[47071:47071:0731/171200.918086:WARNING:account_consistency_mode_manager.cc(290)] Desktop Identity Consistency cannot be enabled as no OAuth client ID and client secret have been configured. +[47071:47071:0731/171200.918141:WARNING:account_consistency_mode_manager.cc(290)] Desktop Identity Consistency cannot be enabled as no OAuth client ID and client secret have been configured. +[47071:47071:0731/171200.918194:WARNING:account_consistency_mode_manager.cc(290)] Desktop Identity Consistency cannot be enabled as no OAuth client ID and client secret have been configured. +[47071:47071:0731/171200.919405:WARNING:account_consistency_mode_manager.cc(290)] Desktop Identity Consistency cannot be enabled as no OAuth client ID and client secret have been configured. +[47071:47071:0731/171200.926168:WARNING:account_consistency_mode_manager.cc(290)] Desktop Identity Consistency cannot be enabled as no OAuth client ID and client secret have been configured. +[47071:47071:0731/171200.968513:WARNING:account_consistency_mode_manager.cc(290)] Desktop Identity Consistency cannot be enabled as no OAuth client ID and client secret have been configured. +[47071:47071:0731/171200.998394:WARNING:account_consistency_mode_manager.cc(290)] Desktop Identity Consistency cannot be enabled as no OAuth client ID and client secret have been configured. +[47071:47071:0731/171200.998472:WARNING:account_consistency_mode_manager.cc(290)] Desktop Identity Consistency cannot be enabled as no OAuth client ID and client secret have been configured. + +DevTools listening on ws://127.0.0.1:38845/devtools/browser/1ea90138-ad2b-4281-a528-a07943a64ba8 +[1533082321.074][DEBUG]: DevTools HTTP Request: http://localhost:38845/json/version +[47071:47071:0731/171201.142350:WARNING:password_store_factory.cc(253)] Using basic (unencrypted) store for password storage. See https://chromium.googlesource.com/chromium/src/+/master/docs/linux_password_storage.md for more information about password storage options. +[47071:47071:0731/171201.145247:WARNING:account_consistency_mode_manager.cc(290)] Desktop Identity Consistency cannot be enabled as no OAuth client ID and client secret have been configured. +[1533082321.383][DEBUG]: DevTools HTTP Response: { + "string_key": "string_value" +} + +[1533082321.434][DEBUG]: DevTools HTTP Request: http://localhost:38845/json +[1533082321.483][DEBUG]: DevTools HTTP Response: [ { + "string_key1": "string_value1" +}, { + "string_key2": "string_value2" +} ] + +[1533082321.484][DEBUG]: DevTools HTTP Request: http://localhost:38845/json +[1533082321.489][DEBUG]: DevTools HTTP Response: [ { + "description": "", + "devtoolsFrontendUrl": "/devtools/inspector.html?ws=localhost:38845/devtools/page/AA1E6CEE168988EC3C52DF53EAE73BD6", + "id": "AA1E6CEE168988EC3C52DF53EAE73BD6", + "title": "Chrome Automation Extension", + "type": "background_page", + "url": "chrome-extension://aapnijgdinlhnhlmodcfapnahmbfebeb/_generated_background_page.html", + "webSocketDebuggerUrl": "ws://localhost:38845/devtools/page/AA1E6CEE168988EC3C52DF53EAE73BD6" +}, { + "description": "", + "devtoolsFrontendUrl": "/devtools/inspector.html?ws=localhost:38845/devtools/page/68B1DB93B848C3F618D9304F7FE26D99", + "id": "68B1DB93B848C3F618D9304F7FE26D99", + "title": "", + "type": "page", + "url": "data:,", + "webSocketDebuggerUrl": "ws://localhost:38845/devtools/page/68B1DB93B848C3F618D9304F7FE26D99" +} ] + +[1533082321.491][INFO]: resolved localhost to ["::1","127.0.0.1"] +[1533082321.495][DEBUG]: DevTools WebSocket Command: Log.enable (id=1) { + +} +[1533082321.495][DEBUG]: DevTools WebSocket Command: DOM.getDocument (id=2) { + +} +[1533082321.495][DEBUG]: DevTools WebSocket Command: Target.setAutoAttach (id=3) { + "autoAttach": true, + "waitForDebuggerOnStart": false +} +[1533082321.495][DEBUG]: DevTools WebSocket Command: Page.enable (id=4) { + +} +[1533082321.496][DEBUG]: DevTools WebSocket Command: Page.enable (id=5) { + +} +[1533082321.587][DEBUG]: DevTools WebSocket Response: Log.enable (id=1) { + +} +[1533082321.588][DEBUG]: DevTools WebSocket Response: DOM.getDocument (id=2) { + "root": { + "backendNodeId": 2, + "baseURL": "data:,", + "childNodeCount": 1, + "children": [ { + "attributes": [ ], + "backendNodeId": 3, + "childNodeCount": 2, + "children": [ { + "attributes": [ ], + "backendNodeId": 4, + "childNodeCount": 0, + "localName": "head", + "nodeId": 3, + "nodeName": "HEAD", + "nodeType": 1, + "nodeValue": "", + "parentId": 2 + }, { + "attributes": [ ], + "backendNodeId": 5, + "childNodeCount": 0, + "localName": "body", + "nodeId": 4, + "nodeName": "BODY", + "nodeType": 1, + "nodeValue": "", + "parentId": 2 + } ], + "frameId": "68B1DB93B848C3F618D9304F7FE26D99", + "localName": "html", + "nodeId": 2, + "nodeName": "HTML", + "nodeType": 1, + "nodeValue": "", + "parentId": 1 + } ], + "documentURL": "data:,", + "localName": "", + "nodeId": 1, + "nodeName": "#document", + "nodeType": 9, + "nodeValue": "", + "xmlVersion": "" + } +} +[1533082321.588][DEBUG]: DevTools WebSocket Response: Target.setAutoAttach (id=3) { + +} +[1533082321.588][DEBUG]: DevTools WebSocket Response: Page.enable (id=4) { + +} +[1533082321.589][DEBUG]: DevTools WebSocket Response: Page.enable (id=5) { + +} +[1533082321.589][DEBUG]: DevTools WebSocket Command: Runtime.enable (id=6) { + +} +[1533082321.589][DEBUG]: DevTools WebSocket Event: Page.frameResized { + +} +[1533082321.631][DEBUG]: DevTools WebSocket Event: Runtime.executionContextCreated { + "context": { + "auxData": { + "frameId": "68B1DB93B848C3F618D9304F7FE26D99", + "isDefault": true + }, + "id": 1, + "name": "", + "origin": "://" + } +} +[1533082321.632][DEBUG]: DevTools WebSocket Response: Runtime.enable (id=6) { + +} +[1533082321.632][DEBUG]: DevTools WebSocket Command: Page.enable (id=7) { + +} +[1533082321.653][DEBUG]: DevTools WebSocket Response: Page.enable (id=7) { + +} +[1533082321.653][DEBUG]: DevTools WebSocket Command: Runtime.enable (id=8) { + +} +[1533082321.655][DEBUG]: DevTools WebSocket Response: Runtime.enable (id=8) { + +} +[1533082321.656][DEBUG]: DevTools WebSocket Command: Runtime.evaluate (id=9) { + "expression": "(function() { // Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/**\n * Enum f...", + "returnByValue": true +} +[1533082321.684][DEBUG]: DevTools WebSocket Response: Runtime.evaluate (id=9) { + "result": { + "type": "object", + "value": { + "status": 0, + "value": 1 + } + } +} +[1533082321.684][INFO]: [37ab6acf4be79d7e368e3260482cd6a2] RESPONSE InitSession { + "acceptInsecureCerts": false, + "acceptSslCerts": false, + "applicationCacheEnabled": false, + "browserConnectionEnabled": false, + "browserName": "chrome", + "chrome": { + "chromedriverVersion": "2.40 (2e6092eb527be36e741f68341db300e257ec4c6d)", + "userDataDir": "/tmp/.org.chromium.Chromium.E0v4OG" + }, + "cssSelectorsEnabled": true, + "databaseEnabled": false, + "goog:chromeOptions": { + "debuggerAddress": "localhost:38845" + }, + "handlesAlerts": true, + "hasTouchScreen": false, + "javascriptEnabled": true, + "locationContextEnabled": true, + "mobileEmulationEnabled": false, + "nativeEvents": true, + "networkConnectionEnabled": false, + "pageLoadStrategy": "normal", + "platform": "Linux", + "rotatable": false, + "~~~": "..." +} +[1533082321.686][INFO]: [37ab6acf4be79d7e368e3260482cd6a2] COMMAND ExecuteScript { + "args": [ ], + "script": "document.title = \"title\"; return 1;" +} +[1533082321.686][INFO]: Waiting for pending navigations... +[1533082321.686][DEBUG]: DevTools WebSocket Command: Runtime.evaluate (id=10) { + "expression": "1" +} +[1533082321.697][DEBUG]: DevTools WebSocket Response: Runtime.evaluate (id=10) { + "result": { + "description": "1", + "type": "number", + "value": 1 + } +} +[1533082321.697][DEBUG]: DevTools WebSocket Command: DOM.getDocument (id=11) { + +} +[1533082321.701][DEBUG]: DevTools WebSocket Response: DOM.getDocument (id=11) { + "root": { + "backendNodeId": 2, + "baseURL": "data:,", + "childNodeCount": 1, + "children": [ { + "attributes": [ ], + "backendNodeId": 3, + "childNodeCount": 2, + "children": [ { + "attributes": [ ], + "backendNodeId": 4, + "childNodeCount": 0, + "localName": "head", + "nodeId": 7, + "nodeName": "HEAD", + "nodeType": 1, + "nodeValue": "", + "parentId": 6 + }, { + "attributes": [ ], + "backendNodeId": 5, + "childNodeCount": 0, + "localName": "body", + "nodeId": 8, + "nodeName": "BODY", + "nodeType": 1, + "nodeValue": "", + "parentId": 6 + } ], + "frameId": "68B1DB93B848C3F618D9304F7FE26D99", + "localName": "html", + "nodeId": 6, + "nodeName": "HTML", + "nodeType": 1, + "nodeValue": "", + "parentId": 5 + } ], + "documentURL": "data:,", + "localName": "", + "nodeId": 5, + "nodeName": "#document", + "nodeType": 9, + "nodeValue": "", + "xmlVersion": "" + } +} +[1533082321.701][DEBUG]: DevTools WebSocket Command: Runtime.evaluate (id=12) { + "expression": "var frame = document.createElement('iframe');frame.name = 'chromedriver dummy frame';frame.src = 'about:blank';document.body.appendChild(frame);window.setTimeout(function() { document.body.removeC..." +} +[1533082321.716][DEBUG]: DevTools WebSocket Event: DOM.childNodeCountUpdated { + "childNodeCount": 1, + "nodeId": 8 +} +[1533082321.716][DEBUG]: DevTools WebSocket Event: Page.frameAttached { + "frameId": "F5F7DB3E16F8067CB249702C3F197C2F", + "parentFrameId": "68B1DB93B848C3F618D9304F7FE26D99", + "stack": { + "callFrames": [ { + "columnNumber": 125, + "functionName": "", + "lineNumber": 0, + "scriptId": "20", + "url": "" + } ] + } +} +[1533082321.751][DEBUG]: DevTools WebSocket Event: Page.frameStartedLoading { + "frameId": "F5F7DB3E16F8067CB249702C3F197C2F" +} +[1533082321.751][DEBUG]: DevTools WebSocket Event: Page.frameNavigated { + "frame": { + "id": "F5F7DB3E16F8067CB249702C3F197C2F", + "loaderId": "C386F2CD5A0B681ED28D85257B599C1B", + "mimeType": "text/html", + "name": "chromedriver dummy frame", + "parentId": "68B1DB93B848C3F618D9304F7FE26D99", + "securityOrigin": "://", + "url": "about:blank" + } +} +[1533082321.751][DEBUG]: DevTools WebSocket Event: Runtime.executionContextCreated { + "context": { + "auxData": { + "frameId": "F5F7DB3E16F8067CB249702C3F197C2F", + "isDefault": true + }, + "id": 2, + "name": "", + "origin": "://" + } +} +[1533082321.751][DEBUG]: DevTools WebSocket Event: Page.frameStoppedLoading { + "frameId": "F5F7DB3E16F8067CB249702C3F197C2F" +} +[1533082321.752][DEBUG]: DevTools WebSocket Response: Runtime.evaluate (id=12) { + "result": { + "description": "1", + "type": "number", + "value": 1 + } +} +[1533082321.752][INFO]: Done waiting for pending navigations. Status: ok +[1533082321.753][DEBUG]: DevTools WebSocket Command: Runtime.evaluate (id=13) { + "expression": "(function() { // Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/**\n * Enum f...", + "returnByValue": true +} +[1533082321.931][DEBUG]: DevTools WebSocket Event: DOM.childNodeCountUpdated { + "childNodeCount": 0, + "nodeId": 8 +} +[1533082321.931][DEBUG]: DevTools WebSocket Event: Runtime.executionContextDestroyed { + "executionContextId": 2 +} +[1533082321.931][DEBUG]: DevTools WebSocket Event: Page.frameDetached { + "frameId": "F5F7DB3E16F8067CB249702C3F197C2F" +} +[1533082321.935][DEBUG]: DevTools WebSocket Event: DOM.childNodeCountUpdated { + "childNodeCount": 1, + "nodeId": 7 +} +[1533082321.935][DEBUG]: DevTools WebSocket Response: Runtime.evaluate (id=13) { + "result": { + "type": "object", + "value": { + "status": 0, + "value": 1 + } + } +} +[1533082321.935][INFO]: Waiting for pending navigations... +[1533082321.935][DEBUG]: DevTools WebSocket Command: Runtime.evaluate (id=14) { + "expression": "1" +} +[1533082321.952][DEBUG]: DevTools WebSocket Response: Runtime.evaluate (id=14) { + "result": { + "description": "1", + "type": "number", + "value": 1 + } +} +[1533082321.952][INFO]: Done waiting for pending navigations. Status: ok +[1533082321.952][INFO]: [37ab6acf4be79d7e368e3260482cd6a2] RESPONSE ExecuteScript 1 +[1533082321.954][INFO]: [37ab6acf4be79d7e368e3260482cd6a2] COMMAND GetTitle { + +} +[1533082321.954][INFO]: Waiting for pending navigations... +[1533082321.954][DEBUG]: DevTools WebSocket Command: Runtime.evaluate (id=15) { + "expression": "1" +} +[1533082321.955][DEBUG]: DevTools WebSocket Response: Runtime.evaluate (id=15) { + "result": { + "description": "1", + "type": "number", + "value": 1 + } +} +[1533082321.955][INFO]: Done waiting for pending navigations. Status: ok +[1533082321.956][DEBUG]: DevTools WebSocket Command: Runtime.evaluate (id=16) { + "expression": "(function() { // Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/**\n * Enum f...", + "returnByValue": true +} +[1533082321.961][DEBUG]: DevTools WebSocket Response: Runtime.evaluate (id=16) { + "result": { + "type": "object", + "value": { + "status": 0, + "value": "title" + } + } +} +[1533082321.961][INFO]: Waiting for pending navigations... +[1533082321.961][DEBUG]: DevTools WebSocket Command: Runtime.evaluate (id=17) { + "expression": "1" +} +[1533082321.962][DEBUG]: DevTools WebSocket Response: Runtime.evaluate (id=17) { + "result": { + "description": "1", + "type": "number", + "value": 1 + } +} +[1533082321.963][INFO]: Done waiting for pending navigations. Status: ok +[1533082321.963][INFO]: [37ab6acf4be79d7e368e3260482cd6a2] RESPONSE GetTitle "title" +[1533082321.964][INFO]: [37ab6acf4be79d7e368e3260482cd6a2] COMMAND Quit { + +} +[0731/171201.978986:ERROR:nacl_helper_linux.cc(310)] NaCl helper process running without a sandbox! +Most likely you need to configure your SUID sandbox correctly +[1533082322.014][INFO]: [37ab6acf4be79d7e368e3260482cd6a2] RESPONSE Quit +[1533082322.014][DEBUG]: Log type 'driver' lost 0 entries on destruction +[1533082322.014][DEBUG]: Log type 'browser' lost 0 entries on destruction
diff --git a/chrome/test/chromedriver/log_replay/test_data/truncatedJSON.log b/chrome/test/chromedriver/log_replay/test_data/truncatedJSON.log new file mode 100644 index 0000000..6f94031 --- /dev/null +++ b/chrome/test/chromedriver/log_replay/test_data/truncatedJSON.log
@@ -0,0 +1,3 @@ +[1533082321.495][DEBUG]: DevTools WebSocket Command: Target.setAutoAttach (id=3) { + "autoAttach": true, + "waitForDebuggerOnStart": false, \ No newline at end of file
diff --git a/chrome/test/data/webui/settings/multidevice_page_container_tests.js b/chrome/test/data/webui/settings/multidevice_page_container_tests.js index 952fc9373..5166ba57 100644 --- a/chrome/test/data/webui/settings/multidevice_page_container_tests.js +++ b/chrome/test/data/webui/settings/multidevice_page_container_tests.js
@@ -36,7 +36,7 @@ function getFakePageContentData(mode) { return { mode: mode, - hostDevice: HOST_SET_MODES.includes(mode) ? {name: 'Pixel XL'} : null, + hostDeviceName: HOST_SET_MODES.includes(mode) ? 'Pixel XL' : undefined, }; }
diff --git a/chrome/test/data/webui/settings/multidevice_page_tests.js b/chrome/test/data/webui/settings/multidevice_page_tests.js index 2083422..4ebeabb 100644 --- a/chrome/test/data/webui/settings/multidevice_page_tests.js +++ b/chrome/test/data/webui/settings/multidevice_page_tests.js
@@ -25,14 +25,12 @@ let multidevicePage = null; let browserProxy = null; let HOST_SET_MODES; - const HOST_DEVICE = { - name: 'Pixel XL', - }; + const HOST_DEVICE = 'Pixel XL'; - function setPageContentData(newMode, newHostDevice) { + function setPageContentData(newMode, newHostDeviceName) { multidevicePage.pageContentData = { mode: newMode, - hostDevice: newHostDevice, + hostDeviceName: newHostDeviceName, }; Polymer.dom.flush(); } @@ -66,7 +64,7 @@ const getSubpage = () => multidevicePage.$$('settings-multidevice-subpage'); test('clicking setup shows multidevice setup dialog', function() { - setPageContentData(settings.MultiDeviceSettingsMode.NO_HOST_SET, null); + setPageContentData(settings.MultiDeviceSettingsMode.NO_HOST_SET, undefined); const button = multidevicePage.$$('paper-button'); assertTrue(!!button); button.click(); @@ -76,25 +74,24 @@ test('headings render based on mode and host', function() { for (let mode of HOST_SET_MODES) { setPageContentData(mode, HOST_DEVICE); - assertEquals(getLabel(), HOST_DEVICE.name); + assertEquals(getLabel(), HOST_DEVICE); } - setPageContentData(settings.MultiDeviceSettingsMode.NO_HOST_SET, null); - assertNotEquals(getLabel(), HOST_DEVICE.name); + setPageContentData(settings.MultiDeviceSettingsMode.NO_HOST_SET, undefined); + assertNotEquals(getLabel(), HOST_DEVICE); }); test('changing host device and fixing mode changes header', function() { setPageContentData( settings.MultiDeviceSettingsMode.HOST_SET_VERIFIED, HOST_DEVICE); - assertEquals(getLabel(), HOST_DEVICE.name); - const anotherHost = - Object.assign(HOST_DEVICE, {name: 'Super Duper ' + HOST_DEVICE.name}); + assertEquals(getLabel(), HOST_DEVICE); + const anotherHost = 'Super Duper ' + HOST_DEVICE; setPageContentData( settings.MultiDeviceSettingsMode.HOST_SET_VERIFIED, anotherHost); - assertEquals(getLabel(), anotherHost.name); + assertEquals(getLabel(), anotherHost); }); test('item is actionable if and only if a host is set', function() { - setPageContentData(settings.MultiDeviceSettingsMode.NO_HOST_SET, null); + setPageContentData(settings.MultiDeviceSettingsMode.NO_HOST_SET, undefined); assertFalse( multidevicePage.$$('#multidevice-item').hasAttribute('actionable')); for (let mode of HOST_SET_MODES) {
diff --git a/chrome/test/data/webui/settings/multidevice_subpage_tests.js b/chrome/test/data/webui/settings/multidevice_subpage_tests.js index e2998aa..aa566783 100644 --- a/chrome/test/data/webui/settings/multidevice_subpage_tests.js +++ b/chrome/test/data/webui/settings/multidevice_subpage_tests.js
@@ -8,14 +8,11 @@ // enum settings.MultiDeviceSettingsMode from here so its initialization is // deferred to the suiteSetup function. let HOST_SET_MODES; - const HOST_DEVICE = { - name: 'Pixel XL', - }; function setPageContentData(newMode) { multideviceSubpage.pageContentData = { mode: newMode, - hostDevice: HOST_DEVICE, + hostDeviceName: 'Pixel XL', }; Polymer.dom.flush(); }
diff --git a/chromecast/browser/accessibility/accessibility_manager.cc b/chromecast/browser/accessibility/accessibility_manager.cc index 0afd97f4..446972a 100644 --- a/chromecast/browser/accessibility/accessibility_manager.cc +++ b/chromecast/browser/accessibility/accessibility_manager.cc
@@ -75,6 +75,16 @@ void AccessibilityManager::SetScreenReader(bool enable) { touch_exploration_manager_->Enable(enable); + + // TODO(rdaum): Until we can fix triple-tap and two finger gesture conflicts + // between TouchExplorationController, FullscreenMagnifier, and + // TripleTapDetector, we have to make sure magnification is not on while + // screenreader is active. + // The triple-tap gesture can still be enabled, but will not do anything until + // screenreader is disabled again. + if (enable) { + magnification_controller_->SetEnabled(false); + } } void AccessibilityManager::SetTouchAccessibilityAnchorPoint(
diff --git a/chromecast/browser/cast_web_view.h b/chromecast/browser/cast_web_view.h index 415b41e..99d746b 100644 --- a/chromecast/browser/cast_web_view.h +++ b/chromecast/browser/cast_web_view.h
@@ -101,6 +101,9 @@ // True if this CastWebView is for running a remote control app. bool is_remote_control_mode = false; + // Whether this CastWebView should be managed by web ui window manager. + bool managed = true; + CreateParams(); };
diff --git a/chromecast/graphics/cast_window_manager.h b/chromecast/graphics/cast_window_manager.h index b17de4f3..906ae276 100644 --- a/chromecast/graphics/cast_window_manager.h +++ b/chromecast/graphics/cast_window_manager.h
@@ -27,7 +27,10 @@ // Note: these window IDs are ordered by z-order. enum WindowId { BOTTOM = -1, + // Base layer for WebUiManager and apps and activities managed by it. APP = BOTTOM, + // Apps running in this layer won't be managed by WebUiManager. + UNMANAGED_APP, DEBUG_OVERLAY, INFO_OVERLAY, SOFT_KEYBOARD,
diff --git a/chromeos/dbus/services/chrome_features_service_provider.cc b/chromeos/dbus/services/chrome_features_service_provider.cc index 52c0e4be9..4cd0d1f 100644 --- a/chromeos/dbus/services/chrome_features_service_provider.cc +++ b/chromeos/dbus/services/chrome_features_service_provider.cc
@@ -35,6 +35,14 @@ weak_ptr_factory_.GetWeakPtr()), base::BindRepeating(&ChromeFeaturesServiceProvider::OnExported, weak_ptr_factory_.GetWeakPtr())); + exported_object->ExportMethod( + kChromeFeaturesServiceInterface, + kChromeFeaturesServiceIsShillSandboxingEnabledMethod, + base::BindRepeating( + &ChromeFeaturesServiceProvider::IsShillSandboxingEnabled, + weak_ptr_factory_.GetWeakPtr()), + base::BindRepeating(&ChromeFeaturesServiceProvider::OnExported, + weak_ptr_factory_.GetWeakPtr())); } void ChromeFeaturesServiceProvider::OnExported( @@ -76,4 +84,14 @@ response_sender.Run(std::move(response)); } +void ChromeFeaturesServiceProvider::IsShillSandboxingEnabled( + dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + std::unique_ptr<dbus::Response> response = + dbus::Response::FromMethodCall(method_call); + dbus::MessageWriter writer(response.get()); + writer.AppendBool(delegate_->IsShillSandboxingEnabled()); + response_sender.Run(std::move(response)); +} + } // namespace chromeos
diff --git a/chromeos/dbus/services/chrome_features_service_provider.h b/chromeos/dbus/services/chrome_features_service_provider.h index b6cc6fa..d668064 100644 --- a/chromeos/dbus/services/chrome_features_service_provider.h +++ b/chromeos/dbus/services/chrome_features_service_provider.h
@@ -42,6 +42,7 @@ virtual bool IsCrostiniEnabled(const std::string& user_id_hash) = 0; virtual bool IsUsbguardEnabled() = 0; + virtual bool IsShillSandboxingEnabled() = 0; private: DISALLOW_COPY_AND_ASSIGN(Delegate); @@ -65,6 +66,9 @@ dbus::ExportedObject::ResponseSender response_sender); void IsUsbguardEnabled(dbus::MethodCall* method_call, dbus::ExportedObject::ResponseSender response_sender); + void IsShillSandboxingEnabled( + dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender); std::unique_ptr<Delegate> delegate_; // Keep this last so that all weak pointers will be invalidated at the
diff --git a/chromeos/services/multidevice_setup/multidevice_setup_impl.cc b/chromeos/services/multidevice_setup/multidevice_setup_impl.cc index 42d59f5..0d0191da 100644 --- a/chromeos/services/multidevice_setup/multidevice_setup_impl.cc +++ b/chromeos/services/multidevice_setup/multidevice_setup_impl.cc
@@ -45,15 +45,18 @@ MultiDeviceSetupImpl::Factory::BuildInstance( PrefService* pref_service, device_sync::DeviceSyncClient* device_sync_client, - secure_channel::SecureChannelClient* secure_channel_client) { - return base::WrapUnique(new MultiDeviceSetupImpl( - pref_service, device_sync_client, secure_channel_client)); + secure_channel::SecureChannelClient* secure_channel_client, + AuthTokenValidator* auth_token_validator) { + return base::WrapUnique( + new MultiDeviceSetupImpl(pref_service, device_sync_client, + secure_channel_client, auth_token_validator)); } MultiDeviceSetupImpl::MultiDeviceSetupImpl( PrefService* pref_service, device_sync::DeviceSyncClient* device_sync_client, - secure_channel::SecureChannelClient* secure_channel_client) + secure_channel::SecureChannelClient* secure_channel_client, + AuthTokenValidator* auth_token_validator) : eligible_host_devices_provider_( EligibleHostDevicesProviderImpl::Factory::Get()->BuildInstance( device_sync_client)), @@ -124,6 +127,9 @@ void MultiDeviceSetupImpl::SetHostDevice(const std::string& host_device_id, SetHostDeviceCallback callback) { + // TODO(crbug.com/870122): Use AuthTokenValidator to verify that the + // user is authenticated. + cryptauth::RemoteDeviceRefList eligible_devices = eligible_host_devices_provider_->GetEligibleHostDevices(); auto it =
diff --git a/chromeos/services/multidevice_setup/multidevice_setup_impl.h b/chromeos/services/multidevice_setup/multidevice_setup_impl.h index 6194779..9a06e57 100644 --- a/chromeos/services/multidevice_setup/multidevice_setup_impl.h +++ b/chromeos/services/multidevice_setup/multidevice_setup_impl.h
@@ -29,6 +29,7 @@ namespace multidevice_setup { class AccountStatusChangeDelegateNotifier; +class AuthTokenValidator; class HostBackendDelegate; class HostStatusProvider; class HostVerifier; @@ -48,7 +49,8 @@ virtual std::unique_ptr<mojom::MultiDeviceSetup> BuildInstance( PrefService* pref_service, device_sync::DeviceSyncClient* device_sync_client, - secure_channel::SecureChannelClient* secure_channel_client); + secure_channel::SecureChannelClient* secure_channel_client, + AuthTokenValidator* auth_token_validator); private: static Factory* test_factory_; @@ -62,7 +64,8 @@ MultiDeviceSetupImpl( PrefService* pref_service, device_sync::DeviceSyncClient* device_sync_client, - secure_channel::SecureChannelClient* secure_channel_client); + secure_channel::SecureChannelClient* secure_channel_client, + AuthTokenValidator* auth_token_validator); // mojom::MultiDeviceSetup: void SetAccountStatusChangeDelegate(
diff --git a/chromeos/services/multidevice_setup/multidevice_setup_impl_unittest.cc b/chromeos/services/multidevice_setup/multidevice_setup_impl_unittest.cc index abd860a..d607c6cf 100644 --- a/chromeos/services/multidevice_setup/multidevice_setup_impl_unittest.cc +++ b/chromeos/services/multidevice_setup/multidevice_setup_impl_unittest.cc
@@ -26,6 +26,7 @@ #include "chromeos/services/multidevice_setup/host_status_provider_impl.h" #include "chromeos/services/multidevice_setup/host_verifier_impl.h" #include "chromeos/services/multidevice_setup/multidevice_setup_impl.h" +#include "chromeos/services/multidevice_setup/public/cpp/fake_auth_token_validator.h" #include "chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom.h" #include "chromeos/services/multidevice_setup/setup_flow_completion_recorder_impl.h" #include "chromeos/services/secure_channel/public/cpp/client/fake_secure_channel_client.h" @@ -361,6 +362,7 @@ std::make_unique<device_sync::FakeDeviceSyncClient>(); fake_secure_channel_client_ = std::make_unique<secure_channel::FakeSecureChannelClient>(); + fake_auth_token_validator_ = std::make_unique<FakeAuthTokenValidator>(); fake_eligible_host_devices_provider_factory_ = std::make_unique<FakeEligibleHostDevicesProviderFactory>( @@ -411,7 +413,7 @@ multidevice_setup_ = MultiDeviceSetupImpl::Factory::Get()->BuildInstance( test_pref_service_.get(), fake_device_sync_client_.get(), - fake_secure_channel_client_.get()); + fake_secure_channel_client_.get(), fake_auth_token_validator_.get()); } void TearDown() override { @@ -662,6 +664,7 @@ std::unique_ptr<device_sync::FakeDeviceSyncClient> fake_device_sync_client_; std::unique_ptr<secure_channel::FakeSecureChannelClient> fake_secure_channel_client_; + std::unique_ptr<FakeAuthTokenValidator> fake_auth_token_validator_; std::unique_ptr<FakeEligibleHostDevicesProviderFactory> fake_eligible_host_devices_provider_factory_;
diff --git a/chromeos/services/multidevice_setup/multidevice_setup_initializer.cc b/chromeos/services/multidevice_setup/multidevice_setup_initializer.cc index 308e7777..320cbc4 100644 --- a/chromeos/services/multidevice_setup/multidevice_setup_initializer.cc +++ b/chromeos/services/multidevice_setup/multidevice_setup_initializer.cc
@@ -40,18 +40,22 @@ MultiDeviceSetupInitializer::Factory::BuildInstance( PrefService* pref_service, device_sync::DeviceSyncClient* device_sync_client, - secure_channel::SecureChannelClient* secure_channel_client) { + secure_channel::SecureChannelClient* secure_channel_client, + AuthTokenValidator* auth_token_validator) { return base::WrapUnique(new MultiDeviceSetupInitializer( - pref_service, device_sync_client, secure_channel_client)); + pref_service, device_sync_client, secure_channel_client, + auth_token_validator)); } MultiDeviceSetupInitializer::MultiDeviceSetupInitializer( PrefService* pref_service, device_sync::DeviceSyncClient* device_sync_client, - secure_channel::SecureChannelClient* secure_channel_client) + secure_channel::SecureChannelClient* secure_channel_client, + AuthTokenValidator* auth_token_validator) : pref_service_(pref_service), device_sync_client_(device_sync_client), - secure_channel_client_(secure_channel_client) { + secure_channel_client_(secure_channel_client), + auth_token_validator_(auth_token_validator) { if (device_sync_client_->is_ready()) { InitializeImplementation(); return; @@ -205,7 +209,8 @@ DCHECK(!multidevice_setup_impl_); multidevice_setup_impl_ = MultiDeviceSetupImpl::Factory::Get()->BuildInstance( - pref_service_, device_sync_client_, secure_channel_client_); + pref_service_, device_sync_client_, secure_channel_client_, + auth_token_validator_); if (pending_delegate_) { multidevice_setup_impl_->SetAccountStatusChangeDelegate(
diff --git a/chromeos/services/multidevice_setup/multidevice_setup_initializer.h b/chromeos/services/multidevice_setup/multidevice_setup_initializer.h index ad44cea7..baf7f1a 100644 --- a/chromeos/services/multidevice_setup/multidevice_setup_initializer.h +++ b/chromeos/services/multidevice_setup/multidevice_setup_initializer.h
@@ -24,6 +24,8 @@ namespace multidevice_setup { +class AuthTokenValidator; + // Initializes the MultiDeviceSetup service. This class is responsible for // waiting for asynchronous initialization steps to complete before creating // the concrete implementation of the mojom::MultiDeviceSetup interface. @@ -39,7 +41,8 @@ virtual std::unique_ptr<MultiDeviceSetupBase> BuildInstance( PrefService* pref_service, device_sync::DeviceSyncClient* device_sync_client, - secure_channel::SecureChannelClient* secure_channel_client); + secure_channel::SecureChannelClient* secure_channel_client, + AuthTokenValidator* auth_token_validator); private: static Factory* test_factory_; @@ -51,7 +54,8 @@ MultiDeviceSetupInitializer( PrefService* pref_service, device_sync::DeviceSyncClient* device_sync_client, - secure_channel::SecureChannelClient* secure_channel_client); + secure_channel::SecureChannelClient* secure_channel_client, + AuthTokenValidator* auth_token_validator); // mojom::MultiDeviceSetup: void SetAccountStatusChangeDelegate( @@ -81,6 +85,7 @@ PrefService* pref_service_; device_sync::DeviceSyncClient* device_sync_client_; secure_channel::SecureChannelClient* secure_channel_client_; + AuthTokenValidator* auth_token_validator_; std::unique_ptr<mojom::MultiDeviceSetup> multidevice_setup_impl_;
diff --git a/chromeos/services/multidevice_setup/multidevice_setup_service.cc b/chromeos/services/multidevice_setup/multidevice_setup_service.cc index 6974980f..b3e45c3 100644 --- a/chromeos/services/multidevice_setup/multidevice_setup_service.cc +++ b/chromeos/services/multidevice_setup/multidevice_setup_service.cc
@@ -28,12 +28,14 @@ MultiDeviceSetupService::MultiDeviceSetupService( PrefService* pref_service, device_sync::DeviceSyncClient* device_sync_client, - secure_channel::SecureChannelClient* secure_channel_client) + secure_channel::SecureChannelClient* secure_channel_client, + AuthTokenValidator* auth_token_validator) : multidevice_setup_( MultiDeviceSetupInitializer::Factory::Get()->BuildInstance( pref_service, device_sync_client, - secure_channel_client)) {} + secure_channel_client, + auth_token_validator)) {} MultiDeviceSetupService::~MultiDeviceSetupService() = default;
diff --git a/chromeos/services/multidevice_setup/multidevice_setup_service.h b/chromeos/services/multidevice_setup/multidevice_setup_service.h index f3ae2e8d..820dd0f 100644 --- a/chromeos/services/multidevice_setup/multidevice_setup_service.h +++ b/chromeos/services/multidevice_setup/multidevice_setup_service.h
@@ -26,6 +26,7 @@ namespace multidevice_setup { +class AuthTokenValidator; class MultiDeviceSetupBase; // Service which provides an implementation for mojom::MultiDeviceSetup. This @@ -36,7 +37,8 @@ MultiDeviceSetupService( PrefService* pref_service, device_sync::DeviceSyncClient* device_sync_client, - secure_channel::SecureChannelClient* secure_channel_client); + secure_channel::SecureChannelClient* secure_channel_client, + AuthTokenValidator* auth_token_validator); ~MultiDeviceSetupService() override; static void RegisterProfilePrefs(PrefRegistrySimple* registry);
diff --git a/chromeos/services/multidevice_setup/multidevice_setup_service_unittest.cc b/chromeos/services/multidevice_setup/multidevice_setup_service_unittest.cc index ca55e78..1832d47 100644 --- a/chromeos/services/multidevice_setup/multidevice_setup_service_unittest.cc +++ b/chromeos/services/multidevice_setup/multidevice_setup_service_unittest.cc
@@ -11,6 +11,7 @@ #include "chromeos/services/multidevice_setup/fake_host_status_observer.h" #include "chromeos/services/multidevice_setup/multidevice_setup_impl.h" #include "chromeos/services/multidevice_setup/multidevice_setup_service.h" +#include "chromeos/services/multidevice_setup/public/cpp/fake_auth_token_validator.h" #include "chromeos/services/multidevice_setup/public/cpp/fake_multidevice_setup.h" #include "chromeos/services/multidevice_setup/public/mojom/constants.mojom.h" #include "chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom.h" @@ -34,10 +35,12 @@ sync_preferences::TestingPrefServiceSyncable* expected_testing_pref_service, device_sync::FakeDeviceSyncClient* expected_device_sync_client, - secure_channel::FakeSecureChannelClient* expected_secure_channel_client) + secure_channel::FakeSecureChannelClient* expected_secure_channel_client, + FakeAuthTokenValidator* expected_auth_token_validator) : expected_testing_pref_service_(expected_testing_pref_service), expected_device_sync_client_(expected_device_sync_client), - expected_secure_channel_client_(expected_secure_channel_client) {} + expected_secure_channel_client_(expected_secure_channel_client), + expected_auth_token_validator_(expected_auth_token_validator) {} ~FakeMultiDeviceSetupFactory() override = default; @@ -47,11 +50,13 @@ std::unique_ptr<mojom::MultiDeviceSetup> BuildInstance( PrefService* pref_service, device_sync::DeviceSyncClient* device_sync_client, - secure_channel::SecureChannelClient* secure_channel_client) override { + secure_channel::SecureChannelClient* secure_channel_client, + AuthTokenValidator* auth_token_validator) override { EXPECT_FALSE(instance_); EXPECT_EQ(expected_testing_pref_service_, pref_service); EXPECT_EQ(expected_device_sync_client_, device_sync_client); EXPECT_EQ(expected_secure_channel_client_, secure_channel_client); + EXPECT_EQ(expected_auth_token_validator_, auth_token_validator); auto instance = std::make_unique<FakeMultiDeviceSetup>(); instance_ = instance.get(); @@ -61,6 +66,7 @@ sync_preferences::TestingPrefServiceSyncable* expected_testing_pref_service_; device_sync::FakeDeviceSyncClient* expected_device_sync_client_; secure_channel::FakeSecureChannelClient* expected_secure_channel_client_; + FakeAuthTokenValidator* expected_auth_token_validator_; FakeMultiDeviceSetup* instance_ = nullptr; @@ -84,11 +90,13 @@ std::make_unique<device_sync::FakeDeviceSyncClient>(); fake_secure_channel_client_ = std::make_unique<secure_channel::FakeSecureChannelClient>(); + fake_auth_token_validator_ = std::make_unique<FakeAuthTokenValidator>(); fake_multidevice_setup_factory_ = std::make_unique<FakeMultiDeviceSetupFactory>( test_pref_service_.get(), fake_device_sync_client_.get(), - fake_secure_channel_client_.get()); + fake_secure_channel_client_.get(), + fake_auth_token_validator_.get()); MultiDeviceSetupImpl::Factory::SetFactoryForTesting( fake_multidevice_setup_factory_.get()); @@ -96,7 +104,8 @@ service_manager::TestConnectorFactory::CreateForUniqueService( std::make_unique<MultiDeviceSetupService>( test_pref_service_.get(), fake_device_sync_client_.get(), - fake_secure_channel_client_.get())); + fake_secure_channel_client_.get(), + fake_auth_token_validator_.get())); auto connector = connector_factory_->CreateConnector(); connector->BindInterface(mojom::kServiceName, &multidevice_setup_ptr_); @@ -152,6 +161,7 @@ std::unique_ptr<device_sync::FakeDeviceSyncClient> fake_device_sync_client_; std::unique_ptr<secure_channel::FakeSecureChannelClient> fake_secure_channel_client_; + std::unique_ptr<FakeAuthTokenValidator> fake_auth_token_validator_; std::unique_ptr<FakeMultiDeviceSetupFactory> fake_multidevice_setup_factory_;
diff --git a/chromeos/services/multidevice_setup/public/cpp/BUILD.gn b/chromeos/services/multidevice_setup/public/cpp/BUILD.gn index 337bc13..3f12e322 100644 --- a/chromeos/services/multidevice_setup/public/cpp/BUILD.gn +++ b/chromeos/services/multidevice_setup/public/cpp/BUILD.gn
@@ -20,6 +20,16 @@ ] } +source_set("auth_token_validator") { + sources = [ + "auth_token_validator.h", + ] + + deps = [ + "//base", + ] +} + source_set("prefs") { sources = [ "prefs.cc", @@ -36,6 +46,8 @@ testonly = true sources = [ + "fake_auth_token_validator.cc", + "fake_auth_token_validator.h", "fake_multidevice_setup.cc", "fake_multidevice_setup.h", "fake_multidevice_setup_client.cc", @@ -43,6 +55,7 @@ ] public_deps = [ + ":auth_token_validator", ":cpp", "//chromeos/services/multidevice_setup", "//chromeos/services/multidevice_setup/public/mojom",
diff --git a/chromeos/services/multidevice_setup/public/cpp/auth_token_validator.h b/chromeos/services/multidevice_setup/public/cpp/auth_token_validator.h new file mode 100644 index 0000000..2618c49 --- /dev/null +++ b/chromeos/services/multidevice_setup/public/cpp/auth_token_validator.h
@@ -0,0 +1,32 @@ +// 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 CHROMEOS_SERVICES_MULTIDEVICE_SETUP_PUBLIC_CPP_AUTH_TOKEN_VALIDATOR_H_ +#define CHROMEOS_SERVICES_MULTIDEVICE_SETUP_PUBLIC_CPP_AUTH_TOKEN_VALIDATOR_H_ + +#include <string> + +#include "base/macros.h" + +namespace chromeos { + +namespace multidevice_setup { + +// Validates a given auth token. +class AuthTokenValidator { + public: + AuthTokenValidator() = default; + virtual ~AuthTokenValidator() = default; + + virtual bool IsAuthTokenValid(const std::string& auth_token) = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(AuthTokenValidator); +}; + +} // namespace multidevice_setup + +} // namespace chromeos + +#endif // CHROMEOS_SERVICES_MULTIDEVICE_SETUP_PUBLIC_CPP_AUTH_TOKEN_VALIDATOR_H_
diff --git a/chromeos/services/multidevice_setup/public/cpp/fake_auth_token_validator.cc b/chromeos/services/multidevice_setup/public/cpp/fake_auth_token_validator.cc new file mode 100644 index 0000000..2e209a7f --- /dev/null +++ b/chromeos/services/multidevice_setup/public/cpp/fake_auth_token_validator.cc
@@ -0,0 +1,24 @@ +// 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. + +#include "chromeos/services/multidevice_setup/public/cpp/fake_auth_token_validator.h" + +namespace chromeos { + +namespace multidevice_setup { + +FakeAuthTokenValidator::FakeAuthTokenValidator() = default; + +FakeAuthTokenValidator::~FakeAuthTokenValidator() = default; + +bool FakeAuthTokenValidator::IsAuthTokenValid(const std::string& auth_token) { + if (!expected_auth_token_) + return false; + + return *expected_auth_token_ == auth_token; +} + +} // namespace multidevice_setup + +} // namespace chromeos
diff --git a/chromeos/services/multidevice_setup/public/cpp/fake_auth_token_validator.h b/chromeos/services/multidevice_setup/public/cpp/fake_auth_token_validator.h new file mode 100644 index 0000000..7ecff04d --- /dev/null +++ b/chromeos/services/multidevice_setup/public/cpp/fake_auth_token_validator.h
@@ -0,0 +1,41 @@ +// 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 CHROMEOS_SERVICES_MULTIDEVICE_SETUP_PUBLIC_CPP_FAKE_AUTH_TOKEN_VALIDATOR_H_ +#define CHROMEOS_SERVICES_MULTIDEVICE_SETUP_PUBLIC_CPP_FAKE_AUTH_TOKEN_VALIDATOR_H_ + +#include <string> + +#include "base/macros.h" +#include "base/optional.h" +#include "chromeos/services/multidevice_setup/public/cpp/auth_token_validator.h" + +namespace chromeos { + +namespace multidevice_setup { + +// Fake AuthTokenValidator implementation for tests. +class FakeAuthTokenValidator : public AuthTokenValidator { + public: + FakeAuthTokenValidator(); + ~FakeAuthTokenValidator() override; + + // AuthTokenValidator: + bool IsAuthTokenValid(const std::string& auth_token) override; + + void set_expected_auth_token(const std::string& expected_auth_token) { + expected_auth_token_ = expected_auth_token; + } + + private: + base::Optional<std::string> expected_auth_token_; + + DISALLOW_COPY_AND_ASSIGN(FakeAuthTokenValidator); +}; + +} // namespace multidevice_setup + +} // namespace chromeos + +#endif // CHROMEOS_SERVICES_MULTIDEVICE_SETUP_PUBLIC_CPP_AUTH_TOKEN_VALIDATOR_H_
diff --git a/chromeos/services/multidevice_setup/public/cpp/multidevice_setup_client_impl_unittest.cc b/chromeos/services/multidevice_setup/public/cpp/multidevice_setup_client_impl_unittest.cc index 3cecf25..483140fe 100644 --- a/chromeos/services/multidevice_setup/public/cpp/multidevice_setup_client_impl_unittest.cc +++ b/chromeos/services/multidevice_setup/public/cpp/multidevice_setup_client_impl_unittest.cc
@@ -42,7 +42,8 @@ std::unique_ptr<MultiDeviceSetupBase> BuildInstance( PrefService* pref_service, device_sync::DeviceSyncClient* device_sync_client, - secure_channel::SecureChannelClient* secure_channel_client) override { + secure_channel::SecureChannelClient* secure_channel_client, + AuthTokenValidator* auth_token_validator) override { EXPECT_TRUE(fake_multidevice_setup_); return std::move(fake_multidevice_setup_); } @@ -97,7 +98,8 @@ auto multidevice_setup_service = std::make_unique<MultiDeviceSetupService>( nullptr /* pref_service */, nullptr /* device_sync_client */, - nullptr /* secure_channel_client */); + nullptr /* secure_channel_client */, + nullptr /* auth_token_validator */); connector_factory_ = service_manager::TestConnectorFactory::CreateForUniqueService(
diff --git a/components/crash/core/browser/resources/crashes.css b/components/crash/core/browser/resources/crashes.css index 05687c1..f923db7 100644 --- a/components/crash/core/browser/resources/crashes.css +++ b/components/crash/core/browser/resources/crashes.css
@@ -7,6 +7,7 @@ } h1 { + -webkit-padding-start: 75px; background-image: url(../../../../resources/sadtab.svg); background-position: left; background-repeat: no-repeat;
diff --git a/components/gcm_driver/account_tracker.cc b/components/gcm_driver/account_tracker.cc index d95e936..254c65a 100644 --- a/components/gcm_driver/account_tracker.cc +++ b/components/gcm_driver/account_tracker.cc
@@ -8,15 +8,15 @@ #include "base/memory/ptr_util.h" #include "base/stl_util.h" #include "base/trace_event/trace_event.h" -#include "net/url_request/url_request_context_getter.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" namespace gcm { AccountTracker::AccountTracker( identity::IdentityManager* identity_manager, - net::URLRequestContextGetter* request_context_getter) + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) : identity_manager_(identity_manager), - request_context_getter_(request_context_getter), + url_loader_factory_(std::move(url_loader_factory)), shutdown_called_(false) { identity_manager_->AddObserver(this); } @@ -169,7 +169,7 @@ DVLOG(1) << "StartFetching " << account_key; AccountIdFetcher* fetcher = new AccountIdFetcher( - identity_manager_, request_context_getter_.get(), this, account_key); + identity_manager_, url_loader_factory_, this, account_key); user_info_requests_[account_key] = base::WrapUnique(fetcher); fetcher->Start(); } @@ -205,11 +205,11 @@ AccountIdFetcher::AccountIdFetcher( identity::IdentityManager* identity_manager, - net::URLRequestContextGetter* request_context_getter, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, AccountTracker* tracker, const std::string& account_key) : identity_manager_(identity_manager), - request_context_getter_(request_context_getter), + url_loader_factory_(std::move(url_loader_factory)), tracker_(tracker), account_key_(account_key) { TRACE_EVENT_ASYNC_BEGIN1("identity", "AccountIdFetcher", this, "account_key", @@ -247,7 +247,7 @@ TRACE_EVENT_ASYNC_STEP_PAST0("identity", "AccountIdFetcher", this, "AccessTokenFetched"); - gaia_oauth_client_.reset(new gaia::GaiaOAuthClient(request_context_getter_)); + gaia_oauth_client_.reset(new gaia::GaiaOAuthClient(url_loader_factory_)); const int kMaxGetUserIdRetries = 3; gaia_oauth_client_->GetUserId(access_token_info.token, kMaxGetUserIdRetries,
diff --git a/components/gcm_driver/account_tracker.h b/components/gcm_driver/account_tracker.h index 2eb3a63..7b670aa 100644 --- a/components/gcm_driver/account_tracker.h +++ b/components/gcm_driver/account_tracker.h
@@ -10,6 +10,7 @@ #include <string> #include <vector> +#include "base/memory/scoped_refptr.h" #include "base/observer_list.h" #include "google_apis/gaia/gaia_oauth_client.h" #include "services/identity/public/cpp/access_token_fetcher.h" @@ -17,8 +18,8 @@ class GoogleServiceAuthError; -namespace net { -class URLRequestContextGetter; +namespace network { +class SharedURLLoaderFactory; } namespace gcm { @@ -42,8 +43,9 @@ // 4. If there is no primary account, there are no other accounts. class AccountTracker : public identity::IdentityManager::Observer { public: - AccountTracker(identity::IdentityManager* identity_manager, - net::URLRequestContextGetter* request_context_getter); + AccountTracker( + identity::IdentityManager* identity_manager, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory); ~AccountTracker() override; class Observer { @@ -103,7 +105,7 @@ void DeleteFetcher(AccountIdFetcher* fetcher); identity::IdentityManager* identity_manager_; - scoped_refptr<net::URLRequestContextGetter> request_context_getter_; + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; std::map<std::string, std::unique_ptr<AccountIdFetcher>> user_info_requests_; std::map<std::string, AccountState> accounts_; base::ObserverList<Observer> observer_list_; @@ -112,10 +114,11 @@ class AccountIdFetcher : public gaia::GaiaOAuthClient::Delegate { public: - AccountIdFetcher(identity::IdentityManager* identity_manager, - net::URLRequestContextGetter* request_context_getter, - AccountTracker* tracker, - const std::string& account_key); + AccountIdFetcher( + identity::IdentityManager* identity_manager, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, + AccountTracker* tracker, + const std::string& account_key); ~AccountIdFetcher() override; const std::string& account_key() { return account_key_; } @@ -132,7 +135,7 @@ private: identity::IdentityManager* identity_manager_; - net::URLRequestContextGetter* request_context_getter_; + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; AccountTracker* tracker_; const std::string account_key_;
diff --git a/components/gcm_driver/account_tracker_unittest.cc b/components/gcm_driver/account_tracker_unittest.cc index d12abec2..9e8bd38 100644 --- a/components/gcm_driver/account_tracker_unittest.cc +++ b/components/gcm_driver/account_tracker_unittest.cc
@@ -12,14 +12,15 @@ #include "build/build_config.h" #include "google_apis/gaia/gaia_oauth_client.h" #include "net/http/http_status_code.h" -#include "net/url_request/test_url_fetcher_factory.h" -#include "net/url_request/url_fetcher_delegate.h" -#include "net/url_request/url_request_test_util.h" #include "services/identity/public/cpp/identity_test_environment.h" +#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" +#include "services/network/test/test_url_loader_factory.h" +#include "services/network/test/test_utils.h" #include "testing/gtest/include/gtest/gtest.h" namespace { +const char kOAuthURL[] = "https://www.googleapis.com/oauth2/v1/userinfo"; const char kPrimaryAccountEmail[] = "primary_account@example.com"; enum TrackingEventType { SIGN_IN, SIGN_OUT }; @@ -243,7 +244,8 @@ void SetUp() override { account_tracker_.reset(new AccountTracker( identity_test_env_.identity_manager(), - new net::TestURLRequestContextGetter(message_loop_.task_runner()))); + base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( + &test_url_loader_factory_))); account_tracker_->AddObserver(&observer_); } @@ -308,8 +310,7 @@ "\" }"; } - void ReturnOAuthUrlFetchResults(int fetcher_id, - net::HttpStatusCode response_code, + void ReturnOAuthUrlFetchResults(net::HttpStatusCode response_code, const std::string& response_string); void ReturnOAuthUrlFetchSuccess(const std::string& account_key); @@ -325,9 +326,13 @@ return primary_account_id; } + network::TestURLLoaderFactory* test_url_loader_factory() { + return &test_url_loader_factory_; + } + private: base::MessageLoopForIO message_loop_; // net:: stuff needs IO message loop. - net::TestURLFetcherFactory test_fetcher_factory_; + network::TestURLLoaderFactory test_url_loader_factory_; identity::IdentityTestEnvironment identity_test_env_; std::unique_ptr<AccountTracker> account_tracker_; @@ -335,29 +340,24 @@ }; void AccountTrackerTest::ReturnOAuthUrlFetchResults( - int fetcher_id, net::HttpStatusCode response_code, const std::string& response_string) { - net::TestURLFetcher* fetcher = - test_fetcher_factory_.GetFetcherByID(fetcher_id); - ASSERT_TRUE(fetcher); - fetcher->set_response_code(response_code); - fetcher->SetResponseString(response_string); - fetcher->delegate()->OnURLFetchComplete(fetcher); + EXPECT_TRUE(test_url_loader_factory()->SimulateResponseForPendingRequest( + GURL(kOAuthURL), network::URLLoaderCompletionStatus(net::OK), + network::CreateResourceResponseHead(response_code), response_string)); } void AccountTrackerTest::ReturnOAuthUrlFetchSuccess( const std::string& account_id) { IssueAccessToken(account_id); - ReturnOAuthUrlFetchResults(gaia::GaiaOAuthClient::kUrlFetcherId, net::HTTP_OK, + ReturnOAuthUrlFetchResults(net::HTTP_OK, GetValidTokenInfoResponse(account_id)); } void AccountTrackerTest::ReturnOAuthUrlFetchFailure( const std::string& account_id) { IssueAccessToken(account_id); - ReturnOAuthUrlFetchResults(gaia::GaiaOAuthClient::kUrlFetcherId, - net::HTTP_BAD_REQUEST, ""); + ReturnOAuthUrlFetchResults(net::HTTP_BAD_REQUEST, ""); } // Primary tests just involve the Active account
diff --git a/components/gcm_driver/gcm_account_tracker_unittest.cc b/components/gcm_driver/gcm_account_tracker_unittest.cc index 2abba16..8fbfd44 100644 --- a/components/gcm_driver/gcm_account_tracker_unittest.cc +++ b/components/gcm_driver/gcm_account_tracker_unittest.cc
@@ -13,16 +13,20 @@ #include "base/message_loop/message_loop.h" #include "components/gcm_driver/fake_gcm_driver.h" #include "google_apis/gaia/google_service_auth_error.h" +#include "net/base/ip_endpoint.h" #include "net/http/http_status_code.h" -#include "net/url_request/test_url_fetcher_factory.h" -#include "net/url_request/url_request_test_util.h" #include "services/identity/public/cpp/identity_test_environment.h" +#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" +#include "services/network/test/test_url_loader_factory.h" +#include "services/network/test/test_utils.h" #include "testing/gtest/include/gtest/gtest.h" namespace gcm { namespace { +const char kOAuthURL[] = "https://www.googleapis.com/oauth2/v1/userinfo"; + const char kEmail1[] = "account_1@me.com"; const char kEmail2[] = "account_2@me.com"; @@ -194,19 +198,25 @@ bool IsTokenReportingRequired() const; base::TimeDelta GetTimeToNextTokenReporting() const; + network::TestURLLoaderFactory* test_url_loader_factory() { + return &test_url_loader_factory_; + } + private: CustomFakeGCMDriver driver_; base::MessageLoop message_loop_; - net::TestURLFetcherFactory test_fetcher_factory_; + network::TestURLLoaderFactory test_url_loader_factory_; identity::IdentityTestEnvironment identity_test_env_; + std::unique_ptr<GCMAccountTracker> tracker_; }; GCMAccountTrackerTest::GCMAccountTrackerTest() { std::unique_ptr<AccountTracker> gaia_account_tracker(new AccountTracker( identity_test_env_.identity_manager(), - new net::TestURLRequestContextGetter(message_loop_.task_runner()))); + base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( + &test_url_loader_factory_))); tracker_.reset(new GCMAccountTracker(std::move(gaia_account_tracker), identity_test_env_.identity_manager(), @@ -239,12 +249,13 @@ const std::string& account_id) { IssueAccessToken(account_id); - net::TestURLFetcher* fetcher = test_fetcher_factory_.GetFetcherByID( - gaia::GaiaOAuthClient::kUrlFetcherId); - ASSERT_TRUE(fetcher); - fetcher->set_response_code(net::HTTP_OK); - fetcher->SetResponseString(GetValidTokenInfoResponse(account_id)); - fetcher->delegate()->OnURLFetchComplete(fetcher); + EXPECT_TRUE(test_url_loader_factory()->IsPending(kOAuthURL)); + test_url_loader_factory()->SimulateResponseForPendingRequest( + GURL(kOAuthURL), network::URLLoaderCompletionStatus(net::OK), + network::CreateResourceResponseHead(net::HTTP_OK), + GetValidTokenInfoResponse(account_id)); + + GetValidTokenInfoResponse(account_id); } std::string GCMAccountTrackerTest::AddPrimaryAccount(const std::string& email) {
diff --git a/components/gcm_driver/gcm_profile_service.cc b/components/gcm_driver/gcm_profile_service.cc index 47bd3d00..26f18ce 100644 --- a/components/gcm_driver/gcm_profile_service.cc +++ b/components/gcm_driver/gcm_profile_service.cc
@@ -28,7 +28,6 @@ #include "components/gcm_driver/gcm_client_factory.h" #include "components/gcm_driver/gcm_desktop_utils.h" #include "components/gcm_driver/gcm_driver_desktop.h" -#include "net/url_request/url_request_context_getter.h" #include "services/identity/public/cpp/identity_manager.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #endif @@ -41,9 +40,10 @@ class GCMProfileService::IdentityObserver : public identity::IdentityManager::Observer { public: - IdentityObserver(identity::IdentityManager* identity_manager, - net::URLRequestContextGetter* request_context, - GCMDriver* driver); + IdentityObserver( + identity::IdentityManager* identity_manager, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, + GCMDriver* driver); ~IdentityObserver() override; // identity::IdentityManager::Observer: @@ -52,7 +52,8 @@ const AccountInfo& previous_primary_account_info) override; private: - void StartAccountTracker(net::URLRequestContextGetter* request_context); + void StartAccountTracker( + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory); GCMDriver* driver_; identity::IdentityManager* identity_manager_; @@ -69,7 +70,7 @@ GCMProfileService::IdentityObserver::IdentityObserver( identity::IdentityManager* identity_manager, - net::URLRequestContextGetter* request_context, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, GCMDriver* driver) : driver_(driver), identity_manager_(identity_manager), @@ -77,7 +78,7 @@ identity_manager_->AddObserver(this); OnPrimaryAccountSet(identity_manager_->GetPrimaryAccountInfo()); - StartAccountTracker(request_context); + StartAccountTracker(std::move(url_loader_factory)); } GCMProfileService::IdentityObserver::~IdentityObserver() { @@ -106,12 +107,12 @@ } void GCMProfileService::IdentityObserver::StartAccountTracker( - net::URLRequestContextGetter* request_context) { + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) { if (gcm_account_tracker_) return; std::unique_ptr<AccountTracker> gaia_account_tracker( - new AccountTracker(identity_manager_, request_context)); + new AccountTracker(identity_manager_, std::move(url_loader_factory))); gcm_account_tracker_.reset(new GCMAccountTracker( std::move(gaia_account_tracker), identity_manager_, driver_)); @@ -154,7 +155,8 @@ const scoped_refptr<base::SequencedTaskRunner>& ui_task_runner, const scoped_refptr<base::SequencedTaskRunner>& io_task_runner, scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner) - : identity_manager_(identity_manager), request_context_(request_context) { + : identity_manager_(identity_manager), + url_loader_factory_(url_loader_factory) { driver_ = CreateGCMDriverDesktop( std::move(gcm_client_factory), prefs, path.Append(gcm_driver::kGCMStoreDirname), @@ -163,8 +165,8 @@ url_loader_factory, channel, product_category_for_subtypes, ui_task_runner, io_task_runner, blocking_task_runner); - identity_observer_.reset( - new IdentityObserver(identity_manager_, request_context_, driver_.get())); + identity_observer_.reset(new IdentityObserver( + identity_manager_, url_loader_factory, driver_.get())); } #endif // BUILDFLAG(USE_GCM_FROM_PLATFORM) @@ -188,7 +190,7 @@ #if !BUILDFLAG(USE_GCM_FROM_PLATFORM) if (identity_observer_) { identity_observer_ = std::make_unique<IdentityObserver>( - identity_manager_, request_context_, driver.get()); + identity_manager_, url_loader_factory_, driver.get()); } #endif // !BUILDFLAG(USE_GCM_FROM_PLATFORM) }
diff --git a/components/gcm_driver/gcm_profile_service.h b/components/gcm_driver/gcm_profile_service.h index 0da5c055..90b40e1b 100644 --- a/components/gcm_driver/gcm_profile_service.h +++ b/components/gcm_driver/gcm_profile_service.h
@@ -94,7 +94,7 @@ #if !BUILDFLAG(USE_GCM_FROM_PLATFORM) identity::IdentityManager* identity_manager_; - net::URLRequestContextGetter* request_context_ = nullptr; + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; // Used for both account tracker and GCM.UserSignedIn UMA. class IdentityObserver;
diff --git a/components/omnibox/browser/omnibox_field_trial.cc b/components/omnibox/browser/omnibox_field_trial.cc index 7c72336..55cf1e69 100644 --- a/components/omnibox/browser/omnibox_field_trial.cc +++ b/components/omnibox/browser/omnibox_field_trial.cc
@@ -106,6 +106,11 @@ "OmniboxUIExperimentMaxAutocompleteMatches", base::FEATURE_DISABLED_BY_DEFAULT}; +// Feature used to display the search terms instead of the URL in the Omnibox +// when the user is on the search results page of the default search provider. +const base::Feature kQueryInOmnibox{"QueryInOmnibox", + base::FEATURE_DISABLED_BY_DEFAULT}; + // Feature used for eliding the suggestion URL after the host as a UI // experiment. const base::Feature kUIExperimentElideSuggestionUrlAfterHost{
diff --git a/components/omnibox/browser/omnibox_field_trial.h b/components/omnibox/browser/omnibox_field_trial.h index 2c2a83f..a92568f3 100644 --- a/components/omnibox/browser/omnibox_field_trial.h +++ b/components/omnibox/browser/omnibox_field_trial.h
@@ -35,6 +35,7 @@ extern const base::Feature kZeroSuggestRedirectToChrome; extern const base::Feature kZeroSuggestSwapTitleAndUrl; extern const base::Feature kDisplayTitleForCurrentUrl; +extern const base::Feature kQueryInOmnibox; extern const base::Feature kUIExperimentElideSuggestionUrlAfterHost; extern const base::Feature kUIExperimentHideSteadyStateUrlSchemeAndSubdomains; extern const base::Feature kUIExperimentJogTextfieldOnPopup;
diff --git a/components/signin/core/browser/account_fetcher_service.cc b/components/signin/core/browser/account_fetcher_service.cc index 66dc8bee..e830cb0f 100644 --- a/components/signin/core/browser/account_fetcher_service.cc +++ b/components/signin/core/browser/account_fetcher_service.cc
@@ -20,7 +20,6 @@ #include "components/signin/core/browser/child_account_info_fetcher.h" #include "components/signin/core/browser/signin_client.h" #include "components/signin/core/browser/signin_switches.h" -#include "net/url_request/url_request_context_getter.h" #include "services/network/public/cpp/shared_url_loader_factory.h" namespace { @@ -210,7 +209,7 @@ DVLOG(1) << "StartFetching " << account_id; std::unique_ptr<AccountInfoFetcher> fetcher = std::make_unique<AccountInfoFetcher>( - token_service_, signin_client_->GetURLRequestContext(), this, + token_service_, signin_client_->GetURLLoaderFactory(), this, account_id); request = std::move(fetcher); request->Start();
diff --git a/components/signin/core/browser/account_info_fetcher.cc b/components/signin/core/browser/account_info_fetcher.cc index 75575bd..33e601d 100644 --- a/components/signin/core/browser/account_info_fetcher.cc +++ b/components/signin/core/browser/account_info_fetcher.cc
@@ -9,15 +9,16 @@ #include "base/trace_event/trace_event.h" #include "components/signin/core/browser/account_fetcher_service.h" #include "google_apis/gaia/gaia_constants.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" AccountInfoFetcher::AccountInfoFetcher( OAuth2TokenService* token_service, - net::URLRequestContextGetter* request_context_getter, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, AccountFetcherService* service, const std::string& account_id) : OAuth2TokenService::Consumer("gaia_account_tracker"), token_service_(token_service), - request_context_getter_(request_context_getter), + url_loader_factory_(std::move(url_loader_factory)), service_(service), account_id_(account_id) { TRACE_EVENT_ASYNC_BEGIN1("AccountFetcherService", "AccountIdFetcher", this, @@ -44,7 +45,7 @@ this, "OnGetTokenSuccess"); DCHECK_EQ(request, login_token_request_.get()); - gaia_oauth_client_.reset(new gaia::GaiaOAuthClient(request_context_getter_)); + gaia_oauth_client_.reset(new gaia::GaiaOAuthClient(url_loader_factory_)); const int kMaxRetries = 3; gaia_oauth_client_->GetUserInfo(access_token, kMaxRetries, this); }
diff --git a/components/signin/core/browser/account_info_fetcher.h b/components/signin/core/browser/account_info_fetcher.h index 071b790f..89bc919 100644 --- a/components/signin/core/browser/account_info_fetcher.h +++ b/components/signin/core/browser/account_info_fetcher.h
@@ -8,12 +8,13 @@ #include <memory> #include "base/macros.h" +#include "base/memory/scoped_refptr.h" #include "google_apis/gaia/gaia_auth_consumer.h" #include "google_apis/gaia/gaia_oauth_client.h" #include "google_apis/gaia/oauth2_token_service.h" -namespace net { -class URLRequestContextGetter; +namespace network { +class SharedURLLoaderFactory; } class AccountFetcherService; @@ -24,10 +25,11 @@ class AccountInfoFetcher : public OAuth2TokenService::Consumer, public gaia::GaiaOAuthClient::Delegate { public: - AccountInfoFetcher(OAuth2TokenService* token_service, - net::URLRequestContextGetter* request_context_getter, - AccountFetcherService* service, - const std::string& account_id); + AccountInfoFetcher( + OAuth2TokenService* token_service, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, + AccountFetcherService* service, + const std::string& account_id); ~AccountInfoFetcher() override; const std::string& account_id() { return account_id_; } @@ -50,7 +52,7 @@ private: OAuth2TokenService* token_service_; - net::URLRequestContextGetter* request_context_getter_; + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; AccountFetcherService* service_; const std::string account_id_;
diff --git a/components/signin/core/browser/account_tracker_service_unittest.cc b/components/signin/core/browser/account_tracker_service_unittest.cc index 9d0d5ad..9f13eb0 100644 --- a/components/signin/core/browser/account_tracker_service_unittest.cc +++ b/components/signin/core/browser/account_tracker_service_unittest.cc
@@ -25,10 +25,9 @@ #include "components/signin/core/browser/test_signin_client.h" #include "google_apis/gaia/fake_oauth2_token_service.h" #include "google_apis/gaia/gaia_oauth_client.h" +#include "google_apis/gaia/gaia_urls.h" #include "net/http/http_status_code.h" -#include "net/url_request/test_url_fetcher_factory.h" -#include "net/url_request/url_fetcher_delegate.h" -#include "net/url_request/url_request_test_util.h" +#include "services/network/test/test_utils.h" #include "testing/gtest/include/gtest/gtest.h" namespace { @@ -350,9 +349,6 @@ void ReturnAccountImageFetchSuccess(const std::string& account_id); void ReturnAccountImageFetchFailure(const std::string& account_id); - net::TestURLFetcherFactory* test_fetcher_factory() { - return &test_fetcher_factory_; - } AccountFetcherService* account_fetcher() { return account_fetcher_.get(); } AccountTrackerService* account_tracker() { return account_tracker_.get(); } OAuth2TokenService* token_service() { @@ -360,8 +356,6 @@ } SigninClient* signin_client() { return signin_client_.get(); } - // Images go through test_url_loader_factory(); others use - // |test_fetcher_factory_| for now. network::TestURLLoaderFactory* test_url_loader_factory() { return signin_client_->test_url_loader_factory(); } @@ -370,11 +364,9 @@ base::test::ScopedTaskEnvironment scoped_task_environment_; private: - void ReturnFetchResults(int fetcher_id, - net::HttpStatusCode response_code, + void ReturnFetchResults(net::HttpStatusCode response_code, const std::string& response_string); - net::TestURLFetcherFactory test_fetcher_factory_; std::unique_ptr<FakeOAuth2TokenService> fake_oauth2_token_service_; TestingPrefServiceSimple pref_service_; std::unique_ptr<AccountFetcherService> account_fetcher_; @@ -383,36 +375,40 @@ }; void AccountTrackerServiceTest::ReturnFetchResults( - int fetcher_id, net::HttpStatusCode response_code, const std::string& response_string) { - net::TestURLFetcher* fetcher = - test_fetcher_factory_.GetFetcherByID(fetcher_id); - ASSERT_TRUE(fetcher); - fetcher->set_response_code(response_code); - fetcher->SetResponseString(response_string); - fetcher->delegate()->OnURLFetchComplete(fetcher); + GURL url = GaiaUrls::GetInstance()->oauth_user_info_url(); + EXPECT_TRUE(test_url_loader_factory()->IsPending(url.spec())); + + // It's possible for multiple requests to be pending, since some tests have + // a local AccountFetcherService which shares token_service() with fixture's + // |account_fetcher_service_|, so when they make tokens available, both end up + // doing fetches. Respond to all of them. + while (test_url_loader_factory()->IsPending(url.spec())) { + test_url_loader_factory()->SimulateResponseForPendingRequest( + url, network::URLLoaderCompletionStatus(net::OK), + network::CreateResourceResponseHead(response_code), response_string, + network::TestURLLoaderFactory::kMostRecentMatch); + } } void AccountTrackerServiceTest::ReturnAccountInfoFetchSuccess( const std::string& account_id) { IssueAccessToken(account_id); - ReturnFetchResults(gaia::GaiaOAuthClient::kUrlFetcherId, net::HTTP_OK, - GenerateValidTokenInfoResponse(account_id)); + ReturnFetchResults(net::HTTP_OK, GenerateValidTokenInfoResponse(account_id)); } void AccountTrackerServiceTest::ReturnAccountInfoFetchSuccessIncomplete( const std::string& account_id) { IssueAccessToken(account_id); - ReturnFetchResults(gaia::GaiaOAuthClient::kUrlFetcherId, net::HTTP_OK, + ReturnFetchResults(net::HTTP_OK, GenerateIncompleteTokenInfoResponse(account_id)); } void AccountTrackerServiceTest::ReturnAccountInfoFetchFailure( const std::string& account_id) { IssueAccessToken(account_id); - ReturnFetchResults(gaia::GaiaOAuthClient::kUrlFetcherId, - net::HTTP_BAD_REQUEST, ""); + ReturnFetchResults(net::HTTP_BAD_REQUEST, ""); } void AccountTrackerServiceTest::ReturnAccountImageFetchSuccess( @@ -616,9 +612,7 @@ SimulateTokenAvailable("alpha"); IssueAccessToken("alpha"); // No fetcher has been created yet. - net::TestURLFetcher* fetcher = test_fetcher_factory()->GetFetcherByID( - gaia::GaiaOAuthClient::kUrlFetcherId); - ASSERT_FALSE(fetcher); + EXPECT_EQ(0, test_url_loader_factory()->NumPending()); // Enable the network to create the fetcher then issue the access token. fetcher_service.EnableNetworkFetchesForTest();
diff --git a/components/sync/base/enum_set.h b/components/sync/base/enum_set.h index a6c14c0..9aa7554 100644 --- a/components/sync/base/enum_set.h +++ b/components/sync/base/enum_set.h
@@ -8,6 +8,7 @@ #include <bitset> #include <cstddef> #include <string> +#include <utility> #include "base/logging.h" @@ -52,31 +53,34 @@ using EnumBitSet = std::bitset<kValueCount>; public: - // Iterator is a forward-only read-only iterator for EnumSet. Its - // interface is deliberately distinct from an STL iterator as its - // semantics are substantially different. + // Iterator is a forward-only read-only iterator for EnumSet. It follows the + // common STL input iterator interface (like std::unordered_set). // - // Example usage: + // Example usage, using a range-based for loop: // - // for (EnumSet<...>::Iterator it = enums.First(); it.Good(); it.Inc()) { - // Process(it.Get()); + // EnumSet<SomeType> enums; + // for (SomeType val : enums) { + // Process(val); // } // - // The iterator must not be outlived by the set. In particular, the - // following is an error: + // Or using an explicit iterator (not recommended): + // + // for (EnumSet<...>::Iterator it = enums.begin(); it != enums.end(); it++) { + // Process(*it); + // } + // + // The iterator must not be outlived by the set. In particular, the following + // is an error: // // EnumSet<...> SomeFn() { ... } // // /* ERROR */ - // for (EnumSet<...>::Iterator it = SomeFun().First(); ... + // for (EnumSet<...>::Iterator it = SomeFun().begin(); ... // // Also, there are no guarantees as to what will happen if you // modify an EnumSet while traversing it with an iterator. class Iterator { public: - // A default-constructed iterator can't do anything except check - // Good(). You need to call First() on an EnumSet to get a usable - // iterator. Iterator() : enums_(nullptr), i_(kValueCount) {} ~Iterator() {} @@ -93,15 +97,45 @@ return FromIndex(i_); } - // Moves the iterator to the next value in the EnumSet. Good() - // must hold. Takes linear time. + // Moves the iterator to the next value in the EnumSet. Good() + // must hold. Takes linear time. void Inc() { DCHECK(Good()); i_ = FindNext(i_ + 1); } + bool operator==(const Iterator& other) const { return i_ == other.i_; } + + bool operator!=(const Iterator& other) const { return !(*this == other); } + + E operator*() const { + DCHECK(Good()); + return FromIndex(i_); + } + + Iterator& operator++() { + DCHECK(Good()); + // If there are no more set elements in the bitset, this will result in an + // index equal to kValueCount, which is equivalent to EnumSet.end(). + i_ = FindNext(i_ + 1); + + return *this; + } + + Iterator operator++(int) { + DCHECK(Good()); + Iterator old(*this); + + // If there are no more set elements in the bitset, this will result in an + // index equal to kValueCount, which is equivalent to EnumSet.end(). + i_ = FindNext(i_ + 1); + + return std::move(old); + } + private: friend Iterator EnumSet::First() const; + friend Iterator EnumSet::begin() const; explicit Iterator(const EnumBitSet& enums) : enums_(&enums), i_(FindNext(0)) {} @@ -209,6 +243,12 @@ // Returns an iterator pointing to the first element (if any). Iterator First() const { return Iterator(enums_); } + Iterator begin() const { return Iterator(enums_); } + + // Returns an iterator that does not point to any element, but to the position + // that follows the last element in the set. + Iterator end() const { return Iterator(); } + // Returns true iff our set and the given set contain exactly the same values. bool operator==(const EnumSet& other) const { return enums_ == other.enums_; }
diff --git a/components/sync/base/enum_set_unittest.cc b/components/sync/base/enum_set_unittest.cc index 1865f34..b8cf466 100644 --- a/components/sync/base/enum_set_unittest.cc +++ b/components/sync/base/enum_set_unittest.cc
@@ -203,6 +203,67 @@ EXPECT_EQ(enums2, enums1); } +TEST_F(EnumSetTest, RangeBasedForLoop) { + const TestEnumSet enums1(TEST_1, TEST_4, TEST_5); + TestEnumSet enums2; + for (TestEnum e : enums1) { + enums2.Put(e); + } + EXPECT_EQ(enums2, enums1); +} + +TEST_F(EnumSetTest, IteratorComparisonOperators) { + const TestEnumSet enums(TEST_1, TEST_3, TEST_5); + const auto first_it = enums.begin(); + const auto second_it = ++enums.begin(); + + // Copy for equality testing. + const auto first_it_copy = first_it; + + // Sanity check, as the rest of the test relies on |first_it| and + // |first_it_copy| pointing to the same element and |first_it| and |second_it| + // pointing to different elements. + ASSERT_EQ(*first_it, *first_it_copy); + ASSERT_NE(*first_it, *second_it); + + EXPECT_TRUE(first_it == first_it_copy); + EXPECT_FALSE(first_it != first_it_copy); + + EXPECT_TRUE(first_it != second_it); + EXPECT_FALSE(first_it == second_it); +} + +TEST_F(EnumSetTest, IteratorIncrementOperators) { + const TestEnumSet enums(TEST_1, TEST_3, TEST_5); + const auto begin = enums.begin(); + + auto post_inc_it = begin; + auto pre_inc_it = begin; + + auto post_inc_return_it = post_inc_it++; + auto pre_inc_return_it = ++pre_inc_it; + + // |pre_inc_it| and |post_inc_it| should point to the same element. + EXPECT_EQ(pre_inc_it, post_inc_it); + EXPECT_EQ(*pre_inc_it, *post_inc_it); + + // |pre_inc_it| should NOT point to the first element. + EXPECT_NE(begin, pre_inc_it); + EXPECT_NE(*begin, *pre_inc_it); + + // |post_inc_it| should NOT point to the first element. + EXPECT_NE(begin, post_inc_it); + EXPECT_NE(*begin, *post_inc_it); + + // Prefix increment should return new iterator. + EXPECT_EQ(pre_inc_return_it, post_inc_it); + EXPECT_EQ(*pre_inc_return_it, *post_inc_it); + + // Postfix increment should return original iterator. + EXPECT_EQ(post_inc_return_it, begin); + EXPECT_EQ(*post_inc_return_it, *begin); +} + TEST_F(EnumSetTest, Union) { const TestEnumSet enums1(TEST_3, TEST_4); const TestEnumSet enums2(TEST_2, TEST_3);
diff --git a/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc b/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc index 56808832..596b7d7e 100644 --- a/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc +++ b/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc
@@ -56,6 +56,43 @@ acc_obj->GetNode()->AddAccessibilityTreeProperties(dict); } +const char* const ATK_OBJECT_ATTRIBUTES[] = { + "atomic", + "autocomplete", + "busy", + "checkable", + "class", + "colcount", + "colindex", + "container-atomic", + "container-busy", + "container-live", + "container-relevant", + "display", + "explicit-name", + "haspopup", + "id", + "keyshortcuts", + "level", + "live", + "placeholder", + "posinset", + "relevant", + "roledescription", + "rowcount", + "rowindex", + "setsize", + "src", + "table-cell-index", + "tag", + "text-input-type", + "valuemin", + "valuemax", + "valuenow", + "valuetext", + "xml-roles", +}; + base::string16 AccessibilityTreeFormatterAuraLinux::ProcessTreeForOutput( const base::DictionaryValue& node, base::DictionaryValue* filtered_dict_result) { @@ -87,14 +124,24 @@ it != states_value->end(); ++it) { std::string state_value; if (it->GetAsString(&state_value)) - WriteAttribute(true, state_value, &line); + WriteAttribute(false, state_value, &line); } int id_value; node.GetInteger("id", &id_value); WriteAttribute(false, base::StringPrintf("id=%d", id_value), &line); - return line + base::ASCIIToUTF16("\n"); + for (const char* attribute_name : ATK_OBJECT_ATTRIBUTES) { + std::string attribute_value; + if (node.GetString(attribute_name, &attribute_value)) { + WriteAttribute( + false, + base::StringPrintf("%s:%s", attribute_name, attribute_value.c_str()), + &line); + } + } + + return line; } const base::FilePath::StringType
diff --git a/content/browser/bluetooth/bluetooth_metrics.cc b/content/browser/bluetooth/bluetooth_metrics.cc index d6368e6..8b68152 100644 --- a/content/browser/bluetooth/bluetooth_metrics.cc +++ b/content/browser/bluetooth/bluetooth_metrics.cc
@@ -33,8 +33,7 @@ // should be migrated to a dedicated histogram macro for hashed strings. uint32_t data = base::PersistentHash(canonical_uuid); - // Strip off the sign bit because UMA doesn't support negative values, - // but takes a signed int as input. + // Strip off the sign bit to make the hash look nicer. return static_cast<int>(data & 0x7fffffff); }
diff --git a/content/browser/browser_child_process_host_impl.cc b/content/browser/browser_child_process_host_impl.cc index b199dab..faf2e2d 100644 --- a/content/browser/browser_child_process_host_impl.cc +++ b/content/browser/browser_child_process_host_impl.cc
@@ -178,6 +178,7 @@ // Create a persistent memory segment for subprocess histograms. CreateMetricsAllocator(); + ShareMetricsAllocatorToProcess(); } BrowserChildProcessHostImpl::~BrowserChildProcessHostImpl() { @@ -389,7 +390,6 @@ delegate_->OnChannelConnected(peer_pid); if (IsProcessLaunched()) { - ShareMetricsAllocatorToProcess(); BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::BindOnce(&NotifyProcessLaunchedAndConnected, data_.Duplicate())); @@ -608,7 +608,6 @@ delegate_->OnProcessLaunched(); if (is_channel_connected_) { - ShareMetricsAllocatorToProcess(); BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::BindOnce(&NotifyProcessLaunchedAndConnected, data_.Duplicate()));
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index 30a40a9..b04021fe 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc
@@ -1213,7 +1213,7 @@ // CompositingModeReporter. return; #else - if (!features::IsAshInBrowserProcess()) { + if (features::IsUsingWindowService()) { // Mash == ChromeOS, which doesn't support software compositing, so no need // to report compositing mode. return; @@ -1248,7 +1248,7 @@ InitializeMojo(); #if BUILDFLAG(ENABLE_MUS) - if (!features::IsAshInBrowserProcess()) { + if (features::IsUsingWindowService()) { base::CommandLine::ForCurrentProcess()->AppendSwitch( switches::kEnableSurfaceSynchronization); }
diff --git a/content/browser/browser_plugin/browser_plugin_guest.cc b/content/browser/browser_plugin/browser_plugin_guest.cc index a58286b..55d20d95 100644 --- a/content/browser/browser_plugin/browser_plugin_guest.cc +++ b/content/browser/browser_plugin/browser_plugin_guest.cc
@@ -408,7 +408,7 @@ void BrowserPluginGuest::FirstSurfaceActivation( const viz::SurfaceInfo& surface_info) { - if (features::IsAshInBrowserProcess()) { + if (!features::IsUsingWindowService()) { SendMessageToEmbedder( std::make_unique<BrowserPluginMsg_FirstSurfaceActivation>( browser_plugin_instance_id(), surface_info)); @@ -665,7 +665,7 @@ // In case we've created a new guest render process after a crash, let the // associated BrowserPlugin know. We only need to send this if we're attached, // as guest_crashed_ is cleared automatically on attach anyways. - if (attached() && features::IsAshInBrowserProcess()) { + if (attached() && !features::IsUsingWindowService()) { RenderWidgetHostViewGuest* rwhv = static_cast<RenderWidgetHostViewGuest*>( web_contents()->GetRenderWidgetHostView()); if (rwhv) {
diff --git a/content/browser/compositor/gpu_process_transport_factory.cc b/content/browser/compositor/gpu_process_transport_factory.cc index 21171afa..7936dc67 100644 --- a/content/browser/compositor/gpu_process_transport_factory.cc +++ b/content/browser/compositor/gpu_process_transport_factory.cc
@@ -217,7 +217,7 @@ return base::WrapUnique(new viz::SoftwareOutputDevice); #if defined(USE_AURA) - if (!features::IsAshInBrowserProcess()) { + if (features::IsUsingWindowService()) { NOTREACHED(); return nullptr; }
diff --git a/content/browser/frame_host/cross_process_frame_connector.cc b/content/browser/frame_host/cross_process_frame_connector.cc index b881d77b..57bd126 100644 --- a/content/browser/frame_host/cross_process_frame_connector.cc +++ b/content/browser/frame_host/cross_process_frame_connector.cc
@@ -118,7 +118,7 @@ if (is_hidden_) OnVisibilityChanged(false); FrameMsg_ViewChanged_Params params; - if (features::IsAshInBrowserProcess()) + if (!features::IsUsingWindowService()) params.frame_sink_id = view_->GetFrameSinkId(); frame_proxy_in_parent_renderer_->Send(new FrameMsg_ViewChanged( frame_proxy_in_parent_renderer_->GetRoutingID(), params));
diff --git a/content/browser/frame_host/navigation_controller_impl.cc b/content/browser/frame_host/navigation_controller_impl.cc index 51bfe73..d8aca9e2 100644 --- a/content/browser/frame_host/navigation_controller_impl.cc +++ b/content/browser/frame_host/navigation_controller_impl.cc
@@ -1022,6 +1022,10 @@ return NAVIGATION_TYPE_NAV_IGNORE; // This is history.replaceState() or history.reload(). + // TODO(nasko): With error page isolation, reloading an existing session + // history entry can result in change of SiteInstance. Check for such a case + // here and classify it as NEW_PAGE, as such navigations should be treated + // as new with replacement. return NAVIGATION_TYPE_EXISTING_PAGE; }
diff --git a/content/browser/frame_host/render_frame_host_manager.cc b/content/browser/frame_host/render_frame_host_manager.cc index b20dcd6..2484bfa 100644 --- a/content/browser/frame_host/render_frame_host_manager.cc +++ b/content/browser/frame_host/render_frame_host_manager.cc
@@ -1138,22 +1138,35 @@ // If the entry has an instance already we should use it, unless it is no // longer suitable. if (dest_instance) { - SiteInstanceImpl* dest_instance_impl = - static_cast<SiteInstanceImpl*>(dest_instance); - // TODO(nasko,creis): The check whether data: or about: URLs are allowed - // to commit in the current process should be in HasWrongProcessForURL. - // However, making this change has further implications and needs more - // investigation of what behavior changes. For now, use a conservative - // approach and explicitly check before calling HasWrongProcessForURL. - if (IsDataOrAbout(dest_url) || - !dest_instance_impl->HasWrongProcessForURL(dest_url)) { - // If we are forcing a swap, this should be in a different - // BrowsingInstance. - if (force_browsing_instance_swap) { - CHECK(!dest_instance->IsRelatedSiteInstance( - render_frame_host_->GetSiteInstance())); + // When error page isolation is enabled, don't reuse |dest_instance| if it's + // an error page SiteInstance, but the navigation will no longer fail. + // Similarly, don't reuse |dest_instance| if it's not an error page + // SiteInstance but the navigation will fail and actually need an error page + // SiteInstance. + // Note: The later call to HasWrongProcessForURL does not have context about + // error page navigaions, so we cannot rely on it to return correct value + // when error pages are involved. + if (!SiteIsolationPolicy::IsErrorPageIsolationEnabled( + frame_tree_node_->IsMainFrame()) || + ((dest_instance->GetSiteURL() == GURL(kUnreachableWebDataURL)) == + is_failure)) { + // TODO(nasko,creis): The check whether data: or about: URLs are allowed + // to commit in the current process should be in HasWrongProcessForURL. + // However, making this change has further implications and needs more + // investigation of what behavior changes. For now, use a conservative + // approach and explicitly check before calling HasWrongProcessForURL. + SiteInstanceImpl* dest_instance_impl = + static_cast<SiteInstanceImpl*>(dest_instance); + if (IsDataOrAbout(dest_url) || + !dest_instance_impl->HasWrongProcessForURL(dest_url)) { + // If we are forcing a swap, this should be in a different + // BrowsingInstance. + if (force_browsing_instance_swap) { + CHECK(!dest_instance->IsRelatedSiteInstance( + render_frame_host_->GetSiteInstance())); + } + return SiteInstanceDescriptor(dest_instance); } - return SiteInstanceDescriptor(dest_instance); } }
diff --git a/content/browser/frame_host/render_frame_host_manager_browsertest.cc b/content/browser/frame_host/render_frame_host_manager_browsertest.cc index f97ec5a..986d87e8 100644 --- a/content/browser/frame_host/render_frame_host_manager_browsertest.cc +++ b/content/browser/frame_host/render_frame_host_manager_browsertest.cc
@@ -4312,45 +4312,87 @@ return; StartEmbeddedServer(); - GURL url(embedded_test_server()->GetURL("/title1.html")); + GURL start_url(embedded_test_server()->GetURL("/title1.html")); GURL error_url(embedded_test_server()->GetURL("/empty.html")); - std::unique_ptr<URLLoaderInterceptor> url_interceptor = - SetupRequestFailForURL(error_url); + GURL end_url(embedded_test_server()->GetURL("/title2.html")); NavigationControllerImpl& nav_controller = static_cast<NavigationControllerImpl&>( shell()->web_contents()->GetController()); auto* policy = ChildProcessSecurityPolicyImpl::GetInstance(); - // Start with a successful navigation to a document and verify there is - // only one entry in session history. - EXPECT_TRUE(NavigateToURL(shell(), url)); + // Build session history with three entries, where the middle one will be + // tested for successful and failed reloads. This allows checking whether + // reload accidentally clears the forward session history if it is + // incorrectly classified. + EXPECT_TRUE(NavigateToURL(shell(), start_url)); + EXPECT_TRUE(NavigateToURL(shell(), error_url)); + EXPECT_TRUE(NavigateToURL(shell(), end_url)); + { + TestNavigationObserver back_observer(shell()->web_contents()); + shell()->web_contents()->GetController().GoBack(); + back_observer.Wait(); + EXPECT_TRUE(back_observer.last_navigation_succeeded()); + } + EXPECT_EQ(3, nav_controller.GetEntryCount()); + EXPECT_EQ(1, nav_controller.GetLastCommittedEntryIndex()); + EXPECT_EQ(error_url, shell()->web_contents()->GetLastCommittedURL()); + scoped_refptr<SiteInstance> success_site_instance = shell()->web_contents()->GetMainFrame()->GetSiteInstance(); - EXPECT_EQ(1, nav_controller.GetEntryCount()); - // Navigate to an url resulting in an error page and ensure a new entry - // was added to session history. - EXPECT_FALSE(NavigateToURL(shell(), error_url)); - EXPECT_EQ(2, nav_controller.GetEntryCount()); + // Install an interceptor which will cause network failure for |error_url|, + // reload the existing entry and verify. + std::unique_ptr<URLLoaderInterceptor> url_interceptor = + SetupRequestFailForURL(error_url); + { + TestNavigationObserver reload_observer(shell()->web_contents()); + shell()->web_contents()->GetController().Reload(ReloadType::NORMAL, false); + reload_observer.Wait(); + EXPECT_FALSE(reload_observer.last_navigation_succeeded()); + // TODO(nasko): Investigate making a failing reload of a successful + // navigation be classified as NEW_PAGE instead, since with error page + // isolation it involves a SiteInstance swap. + EXPECT_EQ(NavigationType::NAVIGATION_TYPE_EXISTING_PAGE, + reload_observer.last_navigation_type()); + } + EXPECT_EQ(3, nav_controller.GetEntryCount()); + EXPECT_EQ(1, nav_controller.GetLastCommittedEntryIndex()); EXPECT_EQ( GURL(kUnreachableWebDataURL), shell()->web_contents()->GetMainFrame()->GetSiteInstance()->GetSiteURL()); - EXPECT_EQ( - GURL(kUnreachableWebDataURL), - policy->GetOriginLock( - shell()->web_contents()->GetSiteInstance()->GetProcess()->GetID())); + int process_id = + shell()->web_contents()->GetMainFrame()->GetProcess()->GetID(); + EXPECT_EQ(GURL(kUnreachableWebDataURL), policy->GetOriginLock(process_id)); + + // Reload while it will still fail to ensure it stays in the same process. + { + TestNavigationObserver reload_observer(shell()->web_contents()); + shell()->web_contents()->GetController().Reload(ReloadType::NORMAL, false); + reload_observer.Wait(); + EXPECT_FALSE(reload_observer.last_navigation_succeeded()); + EXPECT_EQ(NavigationType::NAVIGATION_TYPE_EXISTING_PAGE, + reload_observer.last_navigation_type()); + } + EXPECT_EQ(process_id, + shell()->web_contents()->GetMainFrame()->GetProcess()->GetID()); // Reload the error page after clearing the error condition, such that the // navigation is successful and verify that no new entry was added to - // session history. + // session history and forward history is not pruned. url_interceptor.reset(); { TestNavigationObserver reload_observer(shell()->web_contents()); shell()->web_contents()->GetController().Reload(ReloadType::NORMAL, false); reload_observer.Wait(); EXPECT_TRUE(reload_observer.last_navigation_succeeded()); + // The successful reload should be classified as a NEW_PAGE navigation + // with replacement, since it needs to stay at the same entry in session + // history, but needs a new entry because of the change in SiteInstance. + EXPECT_EQ(NavigationType::NAVIGATION_TYPE_NEW_PAGE, + reload_observer.last_navigation_type()); } - EXPECT_EQ(2, nav_controller.GetEntryCount()); + EXPECT_EQ(3, nav_controller.GetEntryCount()); + EXPECT_EQ(1, nav_controller.GetLastCommittedEntryIndex()); EXPECT_NE( GURL(kUnreachableWebDataURL), shell()->web_contents()->GetMainFrame()->GetSiteInstance()->GetSiteURL()); @@ -4362,8 +4404,19 @@ // Test the same scenario as above, but this time initiated by the // renderer process. url_interceptor = SetupRequestFailForURL(error_url); - EXPECT_FALSE(NavigateToURL(shell(), error_url)); - EXPECT_EQ(2, nav_controller.GetEntryCount()); + { + TestNavigationObserver reload_observer(shell()->web_contents()); + shell()->web_contents()->GetController().Reload(ReloadType::NORMAL, false); + reload_observer.Wait(); + EXPECT_FALSE(reload_observer.last_navigation_succeeded()); + // TODO(nasko): Investigate making a failing reload of a successful + // navigation be classified as NEW_PAGE instead, since with error page + // isolation it involves a SiteInstance swap. + EXPECT_EQ(NavigationType::NAVIGATION_TYPE_EXISTING_PAGE, + reload_observer.last_navigation_type()); + } + EXPECT_EQ(3, nav_controller.GetEntryCount()); + EXPECT_EQ(1, nav_controller.GetLastCommittedEntryIndex()); EXPECT_EQ( GURL(kUnreachableWebDataURL), shell()->web_contents()->GetMainFrame()->GetSiteInstance()->GetSiteURL()); @@ -4378,8 +4431,13 @@ EXPECT_TRUE(ExecuteScript(shell(), "location.reload();")); reload_observer.Wait(); EXPECT_TRUE(reload_observer.last_navigation_succeeded()); + // TODO(nasko): Investigate making renderer initiated reloads that change + // SiteInstance be classified as NEW_PAGE as well. + EXPECT_EQ(NavigationType::NAVIGATION_TYPE_EXISTING_PAGE, + reload_observer.last_navigation_type()); } - EXPECT_EQ(2, nav_controller.GetEntryCount()); + EXPECT_EQ(3, nav_controller.GetEntryCount()); + EXPECT_EQ(1, nav_controller.GetLastCommittedEntryIndex()); EXPECT_NE( GURL(kUnreachableWebDataURL), shell()->web_contents()->GetMainFrame()->GetSiteInstance()->GetSiteURL()); @@ -4459,6 +4517,64 @@ shell()->web_contents()->GetMainFrame()->GetSiteInstance()->GetSiteURL()); } +// Test to verify that when an error page is hit and its process is terminated, +// a successful reload correctly commits in a different process. +// See https://crbug.com/866549. +IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, + ErrorPageNavigationReloadWithTerminatedProcess) { + // This test is only valid if error page isolation is enabled. + if (!SiteIsolationPolicy::IsErrorPageIsolationEnabled(true)) + return; + + StartEmbeddedServer(); + GURL url(embedded_test_server()->GetURL("/title1.html")); + GURL error_url(embedded_test_server()->GetURL("/empty.html")); + std::unique_ptr<URLLoaderInterceptor> url_interceptor = + SetupRequestFailForURL(error_url); + WebContents* web_contents = shell()->web_contents(); + NavigationControllerImpl& nav_controller = + static_cast<NavigationControllerImpl&>(web_contents->GetController()); + + // Start with a successful navigation to a document. + EXPECT_TRUE(NavigateToURL(shell(), url)); + scoped_refptr<SiteInstance> success_site_instance = + web_contents->GetMainFrame()->GetSiteInstance(); + EXPECT_EQ(1, nav_controller.GetEntryCount()); + + // Navigate to an url resulting in an error page. + EXPECT_FALSE(NavigateToURL(shell(), error_url)); + EXPECT_EQ(GURL(kUnreachableWebDataURL), + web_contents->GetMainFrame()->GetSiteInstance()->GetSiteURL()); + EXPECT_EQ(GURL(kUnreachableWebDataURL), + ChildProcessSecurityPolicyImpl::GetInstance()->GetOriginLock( + web_contents->GetSiteInstance()->GetProcess()->GetID())); + EXPECT_EQ(2, nav_controller.GetEntryCount()); + + // Terminate the renderer process. + { + RenderProcessHostWatcher termination_observer( + web_contents->GetMainFrame()->GetProcess(), + RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); + web_contents->GetMainFrame()->GetProcess()->Shutdown(0); + termination_observer.Wait(); + } + + // Clear the interceptor so the navigation will succeed on reload. + url_interceptor.reset(); + + // Reload the URL and execute a Javascript statement to verify that the + // renderer process is still around and responsive. + TestNavigationObserver reload_observer(shell()->web_contents()); + nav_controller.Reload(ReloadType::NORMAL, false); + reload_observer.Wait(); + EXPECT_TRUE(reload_observer.last_navigation_succeeded()); + + std::string result; + EXPECT_TRUE(ExecuteScriptAndExtractString( + shell(), "window.domAutomationController.send(location.href);", &result)); + EXPECT_EQ(error_url.spec(), result); +} + // A NavigationThrottle implementation that blocks all outgoing navigation // requests for a specific WebContents. It is used to block navigations to // WebUI URLs in the following test.
diff --git a/content/browser/frame_host/render_widget_host_view_guest.cc b/content/browser/frame_host/render_widget_host_view_guest.cc index 09d512f..0cd7cef 100644 --- a/content/browser/frame_host/render_widget_host_view_guest.cc +++ b/content/browser/frame_host/render_widget_host_view_guest.cc
@@ -396,7 +396,7 @@ void RenderWidgetHostViewGuest::OnAttached() { RegisterFrameSinkId(); #if defined(USE_AURA) - if (!features::IsAshInBrowserProcess()) { + if (features::IsUsingWindowService()) { aura::Env::GetInstance()->ScheduleEmbed( GetWindowTreeClientFromRenderer(), base::BindOnce(&RenderWidgetHostViewGuest::OnGotEmbedToken,
diff --git a/content/browser/frame_host/render_widget_host_view_guest_unittest.cc b/content/browser/frame_host/render_widget_host_view_guest_unittest.cc index 4864b1b..bfa0b5f3c 100644 --- a/content/browser/frame_host/render_widget_host_view_guest_unittest.cc +++ b/content/browser/frame_host/render_widget_host_view_guest_unittest.cc
@@ -201,7 +201,7 @@ // Early out because RenderWidgetHostViewChildFrame::SendSurfaceInfoToEmbedder // is no-op on mash and the test expects it call into FirstSurfaceActivation // of BrowserPluginGuest. - if (!features::IsAshInBrowserProcess()) + if (features::IsUsingWindowService()) return; gfx::Size view_size(100, 100);
diff --git a/content/browser/oop_browsertest.cc b/content/browser/oop_browsertest.cc index 390c7340..eaf658ca 100644 --- a/content/browser/oop_browsertest.cc +++ b/content/browser/oop_browsertest.cc
@@ -38,7 +38,7 @@ command_line->AppendSwitch(switches::kEnablePixelOutputInTests); command_line->AppendSwitch(switches::kEnableOopRasterization); - const bool use_gpu_in_tests = features::IsAshInBrowserProcess(); + const bool use_gpu_in_tests = !features::IsUsingWindowService(); if (use_gpu_in_tests) command_line->AppendSwitch(switches::kUseGpuInTests); }
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 7bc55c57..e07459a 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -1463,7 +1463,7 @@ InitializeChannelProxy(); - if (features::IsAshInBrowserProcess()) { + if (!features::IsUsingWindowService()) { const int id = GetID(); const uint64_t tracing_id = ChildProcessHostImpl::ChildProcessUniqueIdToTracingProcessId(id);
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc index ecb3cda..e78fc2b 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -364,7 +364,7 @@ is_guest_view_hack_(is_guest_view_hack), device_scale_factor_(0.0f), event_handler_(new RenderWidgetHostViewEventHandler(host(), this, this)), - frame_sink_id_(!features::IsAshInBrowserProcess() + frame_sink_id_(features::IsUsingWindowService() ? viz::FrameSinkId() : is_guest_view_hack_ ? AllocateFrameSinkIdForGuestViewHack() @@ -1699,7 +1699,7 @@ void RenderWidgetHostViewAura::ScheduleEmbed( ui::mojom::WindowTreeClientPtr client, base::OnceCallback<void(const base::UnguessableToken&)> callback) { - DCHECK(!features::IsAshInBrowserProcess()); + DCHECK(features::IsUsingWindowService()); aura::Env::GetInstance()->ScheduleEmbed(std::move(client), std::move(callback)); } @@ -1921,7 +1921,7 @@ if (frame_sink_id_.is_valid()) window_->SetEmbedFrameSinkId(frame_sink_id_); - if (features::IsAshInBrowserProcess()) + if (!features::IsUsingWindowService()) return; // Embed the renderer into the Window.
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc index 68888a5..421d192 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -3044,7 +3044,7 @@ // This test verifies that returned resources do not require a pending ack. TEST_F(RenderWidgetHostViewAuraTest, ReturnedResources) { // TODO: fix for mash. - if (!features::IsAshInBrowserProcess()) + if (features::IsUsingWindowService()) return; gfx::Size view_size(100, 100); @@ -3078,7 +3078,7 @@ // TODO(jonross): Delete this test once Viz launches as it will be obsolete. // https://crbug.com/844469 if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor) || - !features::IsAshInBrowserProcess()) { + features::IsUsingWindowService()) { return; } @@ -3220,7 +3220,7 @@ TEST_F(RenderWidgetHostViewAuraTest, BackgroundColorMatchesCompositorFrame) { // TODO: fix for mash. - if (!features::IsAshInBrowserProcess()) + if (features::IsUsingWindowService()) return; gfx::Size frame_size(100, 100); @@ -3385,7 +3385,7 @@ // TODO(jonross): Delete this test once Viz launches as it will be obsolete. // https://crbug.com/844469 if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor) || - !features::IsAshInBrowserProcess()) { + features::IsUsingWindowService()) { return; } @@ -3446,7 +3446,7 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest, DropFallbackWhenHidden) { // Early out because DelegatedFrameHost is not used in mash. - if (!features::IsAshInBrowserProcess()) + if (features::IsUsingWindowService()) return; view_->InitAsChild(nullptr); @@ -3474,7 +3474,7 @@ // the fallback SurfaceId is populated in OnFirstSurfaceActivation. TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest, SurfaceChanges) { // Early out because DelegatedFrameHost is not used in mash. - if (!features::IsAshInBrowserProcess()) + if (features::IsUsingWindowService()) return; view_->InitAsChild(nullptr); @@ -3513,7 +3513,7 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest, DeviceScaleFactorChanges) { // TODO: fix for mash. - if (!features::IsAshInBrowserProcess()) + if (features::IsUsingWindowService()) return; view_->InitAsChild(nullptr); @@ -3543,7 +3543,7 @@ // TODO(jonross): Delete this test once Viz launches as it will be obsolete. // https://crbug.com/844469 if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor) || - !features::IsAshInBrowserProcess()) { + features::IsUsingWindowService()) { return; } @@ -3578,7 +3578,7 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest, DiscardDelegatedFrames) { // Early out because DelegatedFrameHost is not used in mash. - if (!features::IsAshInBrowserProcess()) + if (features::IsUsingWindowService()) return; view_->InitAsChild(nullptr); @@ -3718,7 +3718,7 @@ TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFramesWithLocking) { // Early out because DelegatedFrameHost is not used in mash. - if (!features::IsAshInBrowserProcess()) + if (features::IsUsingWindowService()) return; view_->InitAsChild(nullptr); @@ -3792,7 +3792,7 @@ // only applies to ChromeOS. TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFramesWithMemoryPressure) { // Early out because DelegatedFrameHost is not used in mash. - if (!features::IsAshInBrowserProcess()) + if (features::IsUsingWindowService()) return; view_->InitAsChild(nullptr); @@ -3899,7 +3899,7 @@ // TODO(jonross): Delete this test once Viz launches as it will be obsolete. // https://crbug.com/844469 if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor) || - !features::IsAshInBrowserProcess()) { + features::IsUsingWindowService()) { return; } @@ -5840,7 +5840,7 @@ // TODO(jonross): Delete this test once Viz launches as it will be obsolete. // https://crbug.com/844469 if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor) || - !features::IsAshInBrowserProcess()) { + features::IsUsingWindowService()) { return; } @@ -5882,7 +5882,7 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest, NewContentRenderingTimeout) { // TODO: fix for mash. - if (!features::IsAshInBrowserProcess()) + if (features::IsUsingWindowService()) return; constexpr base::TimeDelta kTimeout = base::TimeDelta::FromMicroseconds(10); @@ -5960,7 +5960,7 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest, AllocateLocalSurfaceIdOnEviction) { // TODO: fix for mash. - if (!features::IsAshInBrowserProcess()) + if (features::IsUsingWindowService()) return; view_->InitAsChild(nullptr); @@ -5983,7 +5983,7 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest, DropFallbackIfResizedWhileHidden) { // Early out because DelegatedFrameHost is not used in mash. - if (!features::IsAshInBrowserProcess()) + if (features::IsUsingWindowService()) return; view_->InitAsChild(nullptr); @@ -6006,7 +6006,7 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest, DontDropFallbackIfNotResizedWhileHidden) { // Early out because DelegatedFrameHost is not used in mash. - if (!features::IsAshInBrowserProcess()) + if (features::IsUsingWindowService()) return; view_->InitAsChild(nullptr); @@ -6028,7 +6028,7 @@ TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest, TakeFallbackContent) { // Early out because DelegatedFrameHost is not used in mash. - if (!features::IsAshInBrowserProcess()) + if (features::IsUsingWindowService()) return; // Initialize the first view.
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame.cc b/content/browser/renderer_host/render_widget_host_view_child_frame.cc index 9ececcc3..45dd9ba4 100644 --- a/content/browser/renderer_host/render_widget_host_view_child_frame.cc +++ b/content/browser/renderer_host/render_widget_host_view_child_frame.cc
@@ -74,7 +74,7 @@ enable_viz_( base::FeatureList::IsEnabled(features::kVizDisplayCompositor)), weak_factory_(this) { - if (!features::IsAshInBrowserProcess()) { + if (features::IsUsingWindowService()) { // In Mus the RenderFrameProxy will eventually assign a viz::FrameSinkId // until then set ours invalid, as operations using it will be disregarded. frame_sink_id_ = viz::FrameSinkId(); @@ -93,7 +93,7 @@ if (frame_connector_) DetachFromTouchSelectionClientManagerIfNecessary(); - if (features::IsAshInBrowserProcess()) { + if (!features::IsUsingWindowService()) { ResetCompositorFrameSinkSupport(); if (GetHostFrameSinkManager()) GetHostFrameSinkManager()->InvalidateFrameSinkId(frame_sink_id_); @@ -147,7 +147,7 @@ if (parent_view) { DCHECK(parent_view->GetFrameSinkId().is_valid() || - !features::IsAshInBrowserProcess()); + features::IsUsingWindowService()); SetParentFrameSinkId(parent_view->GetFrameSinkId()); } @@ -168,7 +168,7 @@ } #if defined(USE_AURA) - if (!features::IsAshInBrowserProcess()) { + if (features::IsUsingWindowService()) { frame_connector_->EmbedRendererWindowTreeClientInParent( GetWindowTreeClientFromRenderer()); } @@ -180,7 +180,7 @@ #if defined(USE_AURA) void RenderWidgetHostViewChildFrame::SetFrameSinkId( const viz::FrameSinkId& frame_sink_id) { - if (!features::IsAshInBrowserProcess()) + if (features::IsUsingWindowService()) frame_sink_id_ = frame_sink_id; } #endif // defined(USE_AURA) @@ -582,7 +582,7 @@ void RenderWidgetHostViewChildFrame::SetParentFrameSinkId( const viz::FrameSinkId& parent_frame_sink_id) { if (parent_frame_sink_id_ == parent_frame_sink_id || - !features::IsAshInBrowserProcess()) + features::IsUsingWindowService()) return; auto* host_frame_sink_manager = GetHostFrameSinkManager(); @@ -603,7 +603,7 @@ } void RenderWidgetHostViewChildFrame::SendSurfaceInfoToEmbedder() { - if (!features::IsAshInBrowserProcess()) + if (features::IsUsingWindowService()) return; if (!last_activated_surface_info_.is_valid()) return; @@ -1070,7 +1070,7 @@ } void RenderWidgetHostViewChildFrame::CreateCompositorFrameSinkSupport() { - if (!features::IsAshInBrowserProcess() || enable_viz_) + if (features::IsUsingWindowService() || enable_viz_) return; DCHECK(!support_);
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc b/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc index 6c9a0a1b..96d0d448 100644 --- a/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc +++ b/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc
@@ -160,7 +160,7 @@ IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewChildFrameTest, ChildFrameSinkId) { // Only when mus hosts viz do we expect a RenderFrameProxy to provide the // FrameSinkId. - if (features::IsAshInBrowserProcess()) + if (!features::IsUsingWindowService()) return; GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html"));
diff --git a/content/browser/service_manager/common_browser_interfaces.cc b/content/browser/service_manager/common_browser_interfaces.cc index bb155a0..86941e4 100644 --- a/content/browser/service_manager/common_browser_interfaces.cc +++ b/content/browser/service_manager/common_browser_interfaces.cc
@@ -51,7 +51,7 @@ #elif defined(OS_MACOSX) registry_.AddInterface(base::BindRepeating(&FontLoaderDispatcher::Create)); #endif - if (features::IsAshInBrowserProcess()) { + if (!features::IsUsingWindowService()) { // For mus, the mojom::discardable_memory::DiscardableSharedMemoryManager // is exposed from ui::Service. So we don't need bind the interface here. auto* browser_main_loop = BrowserMainLoop::GetInstance(); @@ -63,8 +63,6 @@ base::Unretained(manager))); } } - } - if (features::IsAshInBrowserProcess()) { registry_.AddInterface(base::BindRepeating( &ConnectionFilterImpl::BindGpuRequest, base::Unretained(this))); }
diff --git a/content/browser/site_per_process_hit_test_browsertest.cc b/content/browser/site_per_process_hit_test_browsertest.cc index 68cdf8a..b46ebd6 100644 --- a/content/browser/site_per_process_hit_test_browsertest.cc +++ b/content/browser/site_per_process_hit_test_browsertest.cc
@@ -1328,15 +1328,8 @@ RunTest(ShowPressHasTouchID); } -#if defined(OS_CHROMEOS) -// Flaky: https://crbug.com/833380 -#define MAYBE_EmulatedTouchScrollBubbles DISABLED_EmulatedTouchScrollBubbles -#else -#define MAYBE_EmulatedTouchScrollBubbles EmulatedTouchScrollBubbles -#endif - IN_PROC_BROWSER_TEST_P(SitePerProcessEmulatedTouchBrowserTest, - MAYBE_EmulatedTouchScrollBubbles) { + EmulatedTouchScrollBubbles) { RunTest(ScrollBubbling); } @@ -1345,15 +1338,8 @@ RunTest(PinchGoesToMainFrame); } -#if defined(OS_CHROMEOS) -// Flaky timeouts: https://crbug.com/833380 -#define MAYBE_EmulatedGestureScrollBubbles DISABLED_EmulatedGestureScrollBubbles -#else -#define MAYBE_EmulatedGestureScrollBubbles EmulatedGestureScrollBubbles -#endif - IN_PROC_BROWSER_TEST_P(SitePerProcessEmulatedTouchBrowserTest, - MAYBE_EmulatedGestureScrollBubbles) { + EmulatedGestureScrollBubbles) { RunTest(TouchActionBubbling); }
diff --git a/content/browser/web_contents/web_contents_view_aura.cc b/content/browser/web_contents/web_contents_view_aura.cc index 8aff250..732c011 100644 --- a/content/browser/web_contents/web_contents_view_aura.cc +++ b/content/browser/web_contents/web_contents_view_aura.cc
@@ -467,7 +467,7 @@ WebContentsViewDelegate* delegate) : is_mus_browser_plugin_guest_(web_contents->GetBrowserPluginGuest() != nullptr && - !features::IsAshInBrowserProcess()), + features::IsUsingWindowService()), web_contents_(web_contents), delegate_(delegate), current_drag_op_(blink::kWebDragOperationNone),
diff --git a/content/browser/web_contents/web_contents_view_guest.cc b/content/browser/web_contents/web_contents_view_guest.cc index 44c68ed..12f6817 100644 --- a/content/browser/web_contents/web_contents_view_guest.cc +++ b/content/browser/web_contents/web_contents_view_guest.cc
@@ -72,14 +72,14 @@ // view hierarchy. We add this view as embedder's child here. // This would go in WebContentsViewGuest::CreateView, but that is too early to // access embedder_web_contents(). Therefore, we do it here. - if (features::IsAshInBrowserProcess()) + if (!features::IsUsingWindowService()) parent_view->GetNativeView()->AddChild(platform_view_->GetNativeView()); #endif // defined(USE_AURA) } void WebContentsViewGuest::OnGuestDetached(WebContentsView* old_parent_view) { #if defined(USE_AURA) - if (features::IsAshInBrowserProcess()) { + if (!features::IsUsingWindowService()) { old_parent_view->GetNativeView()->RemoveChild( platform_view_->GetNativeView()); }
diff --git a/content/browser/webauth/authenticator_impl.cc b/content/browser/webauth/authenticator_impl.cc index b6978d1..04da603 100644 --- a/content/browser/webauth/authenticator_impl.cc +++ b/content/browser/webauth/authenticator_impl.cc
@@ -379,38 +379,16 @@ std::string AuthenticatorImpl::SerializeCollectedClientDataToJson( const std::string& type, const url::Origin& origin, - base::span<const uint8_t> challenge, - base::Optional<base::span<const uint8_t>> token_binding) { + base::span<const uint8_t> challenge) { static constexpr char kTypeKey[] = "type"; static constexpr char kChallengeKey[] = "challenge"; static constexpr char kOriginKey[] = "origin"; - static constexpr char kTokenBindingKey[] = "tokenBinding"; base::DictionaryValue client_data; client_data.SetKey(kTypeKey, base::Value(type)); client_data.SetKey(kChallengeKey, base::Value(Base64UrlEncode(challenge))); client_data.SetKey(kOriginKey, base::Value(origin.Serialize())); - if (token_binding) { - base::DictionaryValue token_binding_dict; - static constexpr char kTokenBindingStatusKey[] = "status"; - static constexpr char kTokenBindingIdKey[] = "id"; - static constexpr char kTokenBindingSupportedStatus[] = "supported"; - static constexpr char kTokenBindingPresentStatus[] = "present"; - - if (token_binding->empty()) { - token_binding_dict.SetKey(kTokenBindingStatusKey, - base::Value(kTokenBindingSupportedStatus)); - } else { - token_binding_dict.SetKey(kTokenBindingStatusKey, - base::Value(kTokenBindingPresentStatus)); - token_binding_dict.SetKey(kTokenBindingIdKey, - base::Value(Base64UrlEncode(*token_binding))); - } - - client_data.SetKey(kTokenBindingKey, std::move(token_binding_dict)); - } - if (base::RandDouble() < 0.2) { // An extra key is sometimes added to ensure that RPs do not make // unreasonably specific assumptions about the clientData JSON. This is @@ -488,8 +466,7 @@ // TODO(kpaulhamus): Fetch and add the Token Binding ID public key used to // communicate with the origin. client_data_json_ = SerializeCollectedClientDataToJson( - client_data::kCreateType, caller_origin, std::move(options->challenge), - base::nullopt); + client_data::kCreateType, caller_origin, std::move(options->challenge)); const bool individual_attestation = options->attestation == @@ -587,8 +564,7 @@ // TODO(kpaulhamus): Fetch and add the Token Binding ID public key used to // communicate with the origin. client_data_json_ = SerializeCollectedClientDataToJson( - client_data::kGetType, caller_origin, std::move(options->challenge), - base::nullopt); + client_data::kGetType, caller_origin, std::move(options->challenge)); request_ = std::make_unique<device::GetAssertionRequestHandler>( connector_, protocols_,
diff --git a/content/browser/webauth/authenticator_impl.h b/content/browser/webauth/authenticator_impl.h index 9637a3b..50b4c55a 100644 --- a/content/browser/webauth/authenticator_impl.h +++ b/content/browser/webauth/authenticator_impl.h
@@ -104,8 +104,7 @@ static std::string SerializeCollectedClientDataToJson( const std::string& type, const url::Origin& origin, - base::span<const uint8_t> challenge, - base::Optional<base::span<const uint8_t>> token_binding); + base::span<const uint8_t> challenge); // mojom:Authenticator void MakeCredential(
diff --git a/content/browser/webauth/authenticator_impl_unittest.cc b/content/browser/webauth/authenticator_impl_unittest.cc index 80cbb9c..8208ae3 100644 --- a/content/browser/webauth/authenticator_impl_unittest.cc +++ b/content/browser/webauth/authenticator_impl_unittest.cc
@@ -361,15 +361,7 @@ std::string GetTestClientDataJSON(std::string type) { return AuthenticatorImpl::SerializeCollectedClientDataToJson( - std::move(type), GetTestOrigin(), GetTestChallengeBytes(), - base::nullopt); - } - - std::string GetTokenBindingTestClientDataJSON( - base::Optional<base::span<const uint8_t>> token_binding) { - return AuthenticatorImpl::SerializeCollectedClientDataToJson( - client_data::kGetType, GetTestOrigin(), GetTestChallengeBytes(), - token_binding); + std::move(type), GetTestOrigin(), GetTestChallengeBytes()); } AuthenticatorStatus TryAuthenticationWithAppId(const std::string& origin, @@ -611,34 +603,6 @@ GetTestClientDataJSON(client_data::kGetType)); } -TEST_F(AuthenticatorImplTest, TestTokenBindingClientData) { - const std::vector< - std::pair<base::Optional<std::vector<uint8_t>>, const char*>> - kTestCases = { - std::make_pair(base::nullopt, ""), - std::make_pair(std::vector<uint8_t>{}, - R"({"tokenBinding":{"status":"supported"}})"), - std::make_pair( - std::vector<uint8_t>{1, 2, 3, 4}, - R"({"tokenBinding":{"status":"present","id":"AQIDBA"}})"), - }; - - for (const auto& test : kTestCases) { - const auto& token_binding = test.first; - const std::string expected_json_subset = test.second; - SCOPED_TRACE(expected_json_subset); - const std::string client_data = - GetTokenBindingTestClientDataJSON(token_binding); - - if (!expected_json_subset.empty()) { - CheckJSONIsSubsetOfJSON(expected_json_subset, client_data); - } else { - EXPECT_TRUE(client_data.find("tokenBinding") == std::string::npos) - << client_data; - } - } -} - TEST_F(AuthenticatorImplTest, TestMakeCredentialTimeout) { SimulateNavigation(GURL(kTestOrigin1)); PublicKeyCredentialCreationOptionsPtr options =
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc index 10776fb..6d7d038 100644 --- a/content/child/runtime_features.cc +++ b/content/child/runtime_features.cc
@@ -343,9 +343,6 @@ if (base::FeatureList::IsEnabled(network::features::kOutOfBlinkCORS)) WebRuntimeFeatures::EnableOutOfBlinkCORS(true); - if (base::FeatureList::IsEnabled(features::kOriginPolicy)) - WebRuntimeFeatures::EnableOriginPolicy(true); - WebRuntimeFeatures::EnableMediaCastOverlayButton( base::FeatureList::IsEnabled(media::kMediaCastOverlayButton)); @@ -490,6 +487,9 @@ FeaturesFromSwitch(command_line, switches::kDisableBlinkFeatures)) { WebRuntimeFeatures::EnableFeatureFromString(feature, false); } + + WebRuntimeFeatures::EnablePortals( + base::FeatureList::IsEnabled(blink::features::kPortals)); }; } // namespace content
diff --git a/content/common/content_param_traits.cc b/content/common/content_param_traits.cc index ad9a9821..cac6c15 100644 --- a/content/common/content_param_traits.cc +++ b/content/common/content_param_traits.cc
@@ -148,7 +148,7 @@ void ParamTraits<content::FrameMsg_ViewChanged_Params>::Write( base::Pickle* m, const param_type& p) { - DCHECK(!features::IsAshInBrowserProcess() || + DCHECK(features::IsUsingWindowService() || (p.frame_sink_id.has_value() && p.frame_sink_id->is_valid())); WriteParam(m, p.frame_sink_id); } @@ -159,7 +159,7 @@ param_type* r) { if (!ReadParam(m, iter, &(r->frame_sink_id))) return false; - if (features::IsAshInBrowserProcess() && + if (!features::IsUsingWindowService() && (!r->frame_sink_id || !r->frame_sink_id->is_valid())) { NOTREACHED(); return false;
diff --git a/content/ppapi_plugin/ppapi_thread.cc b/content/ppapi_plugin/ppapi_thread.cc index 40926064..8b4fe965 100644 --- a/content/ppapi_plugin/ppapi_thread.cc +++ b/content/ppapi_plugin/ppapi_thread.cc
@@ -120,7 +120,7 @@ // allocator. if (!command_line.HasSwitch(switches::kSingleProcess)) { discardable_memory::mojom::DiscardableSharedMemoryManagerPtr manager_ptr; - if (!features::IsAshInBrowserProcess()) { + if (features::IsUsingWindowService()) { #if defined(USE_AURA) GetServiceManagerConnection()->GetConnector()->BindInterface( ui::mojom::kServiceName, &manager_ptr);
diff --git a/content/public/test/navigation_simulator.cc b/content/public/test/navigation_simulator.cc index 4c0b09d..436f1b4 100644 --- a/content/public/test/navigation_simulator.cc +++ b/content/public/test/navigation_simulator.cc
@@ -512,6 +512,7 @@ params.origin = url::Origin::Create(navigation_url_); params.referrer = referrer_; params.transition = transition_; + params.redirects.push_back(navigation_url_); params.should_update_history = true; params.did_create_new_entry = DidCreateNewEntry(); params.gesture =
diff --git a/content/public/test/test_navigation_observer.cc b/content/public/test/test_navigation_observer.cc index fbebfa0..0def396 100644 --- a/content/public/test/test_navigation_observer.cc +++ b/content/public/test/test_navigation_observer.cc
@@ -5,8 +5,8 @@ #include "content/public/test/test_navigation_observer.h" #include "base/bind.h" +#include "content/browser/frame_host/navigation_handle_impl.h" #include "content/browser/web_contents/web_contents_impl.h" -#include "content/public/browser/navigation_handle.h" #include "content/public/browser/web_contents_observer.h" namespace content { @@ -186,6 +186,8 @@ last_navigation_url_ = navigation_handle->GetURL(); last_navigation_succeeded_ = !navigation_handle->IsErrorPage(); last_net_error_code_ = navigation_handle->GetNetErrorCode(); + last_navigation_type_ = + static_cast<NavigationHandleImpl*>(navigation_handle)->navigation_type(); if (wait_event_ == WaitEvent::kNavigationFinished) EventTriggered();
diff --git a/content/public/test/test_navigation_observer.h b/content/public/test/test_navigation_observer.h index d2f9c84..fdbfae4 100644 --- a/content/public/test/test_navigation_observer.h +++ b/content/public/test/test_navigation_observer.h
@@ -10,6 +10,7 @@ #include "base/callback.h" #include "base/macros.h" +#include "content/public/browser/navigation_type.h" #include "content/public/test/test_utils.h" #include "net/base/net_errors.h" #include "url/gurl.h" @@ -68,6 +69,8 @@ net::Error last_net_error_code() const { return last_net_error_code_; } + NavigationType last_navigation_type() const { return last_navigation_type_; } + protected: // Register this TestNavigationObserver as an observer of the |web_contents|. void RegisterAsObserver(WebContents* web_contents); @@ -123,6 +126,9 @@ // The net error code of the last navigation. net::Error last_net_error_code_; + // The NavigationType of the last navigation. + NavigationType last_navigation_type_; + // The MessageLoopRunner used to spin the message loop. scoped_refptr<MessageLoopRunner> message_loop_runner_;
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn index 5b73e127..b383c5f 100644 --- a/content/renderer/BUILD.gn +++ b/content/renderer/BUILD.gn
@@ -382,8 +382,6 @@ "media/webrtc/peer_connection_remote_audio_source.h", "media/webrtc/peer_connection_tracker.cc", "media/webrtc/peer_connection_tracker.h", - "media/webrtc/rtc_certificate.cc", - "media/webrtc/rtc_certificate.h", "media/webrtc/rtc_certificate_generator.cc", "media/webrtc/rtc_certificate_generator.h", "media/webrtc/rtc_data_channel_handler.cc",
diff --git a/content/renderer/browser_plugin/browser_plugin.cc b/content/renderer/browser_plugin/browser_plugin.cc index 4d82510..963702e 100644 --- a/content/renderer/browser_plugin/browser_plugin.cc +++ b/content/renderer/browser_plugin/browser_plugin.cc
@@ -145,7 +145,7 @@ void BrowserPlugin::OnFirstSurfaceActivation( int browser_plugin_instance_id, const viz::SurfaceInfo& surface_info) { - if (!attached() || !features::IsAshInBrowserProcess()) + if (!attached() || features::IsUsingWindowService()) return; if (!enable_surface_synchronization_) { @@ -320,7 +320,7 @@ sent_visual_properties_ = pending_visual_properties_; #if defined(USE_AURA) - if (!features::IsAshInBrowserProcess() && mus_embedded_frame_) { + if (features::IsUsingWindowService() && mus_embedded_frame_) { mus_embedded_frame_->SetWindowBounds(GetLocalSurfaceId(), FrameRectInPixels()); } @@ -414,7 +414,7 @@ void BrowserPlugin::OnSetMusEmbedToken( int instance_id, const base::UnguessableToken& embed_token) { - DCHECK(!features::IsAshInBrowserProcess()); + DCHECK(features::IsUsingWindowService()); if (!attached_) { pending_embed_token_ = embed_token; } else { @@ -861,7 +861,7 @@ void BrowserPlugin::OnMusEmbeddedFrameSinkIdAllocated( const viz::FrameSinkId& frame_sink_id) { // RendererWindowTreeClient should only call this when mus is hosting viz. - DCHECK(!features::IsAshInBrowserProcess()); + DCHECK(features::IsUsingWindowService()); OnGuestReady(browser_plugin_instance_id_, frame_sink_id); } #endif
diff --git a/content/renderer/media/webrtc/rtc_certificate.cc b/content/renderer/media/webrtc/rtc_certificate.cc deleted file mode 100644 index 316b602..0000000 --- a/content/renderer/media/webrtc/rtc_certificate.cc +++ /dev/null
@@ -1,66 +0,0 @@ -// Copyright (c) 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. - -#include "content/renderer/media/webrtc/rtc_certificate.h" - -#include <vector> - -#include "base/memory/ptr_util.h" -#include "base/strings/string_util.h" -#include "third_party/webrtc/rtc_base/sslidentity.h" -#include "url/gurl.h" - -namespace content { - -RTCCertificate::RTCCertificate( - const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) - : certificate_(certificate) { - DCHECK(certificate_); -} - -RTCCertificate::~RTCCertificate() { -} - -std::unique_ptr<blink::WebRTCCertificate> RTCCertificate::ShallowCopy() const { - return base::WrapUnique(new RTCCertificate(certificate_)); -} - -uint64_t RTCCertificate::Expires() const { - return certificate_->Expires(); -} - -blink::WebVector<blink::WebRTCDtlsFingerprint> RTCCertificate::GetFingerprints() - const { - std::vector<blink::WebRTCDtlsFingerprint> fingerprints; - std::unique_ptr<rtc::SSLCertificateStats> first_certificate_stats = - certificate_->identity()->certificate().GetStats(); - for (rtc::SSLCertificateStats* certificate_stats = - first_certificate_stats.get(); - certificate_stats; certificate_stats = certificate_stats->issuer.get()) { - fingerprints.push_back(blink::WebRTCDtlsFingerprint( - blink::WebString::FromUTF8(certificate_stats->fingerprint_algorithm), - blink::WebString::FromUTF8( - base::ToLowerASCII(certificate_stats->fingerprint)))); - } - return blink::WebVector<blink::WebRTCDtlsFingerprint>(fingerprints); -} - -blink::WebRTCCertificatePEM RTCCertificate::ToPEM() const { - rtc::RTCCertificatePEM pem = certificate_->ToPEM(); - return blink::WebRTCCertificatePEM( - blink::WebString::FromUTF8(pem.private_key()), - blink::WebString::FromUTF8(pem.certificate())); -} - -bool RTCCertificate::Equals(const blink::WebRTCCertificate& other) const { - return *certificate_ == - *static_cast<const RTCCertificate&>(other).certificate_; -} - -const rtc::scoped_refptr<rtc::RTCCertificate>& -RTCCertificate::rtcCertificate() const { - return certificate_; -} - -} // namespace content
diff --git a/content/renderer/media/webrtc/rtc_certificate.h b/content/renderer/media/webrtc/rtc_certificate.h deleted file mode 100644 index 5210e8f4..0000000 --- a/content/renderer/media/webrtc/rtc_certificate.h +++ /dev/null
@@ -1,45 +0,0 @@ -// Copyright (c) 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 CONTENT_RENDERER_MEDIA_WEBRTC_RTC_CERTIFICATE_H_ -#define CONTENT_RENDERER_MEDIA_WEBRTC_RTC_CERTIFICATE_H_ - -#include <stdint.h> - -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "content/common/content_export.h" -#include "third_party/blink/public/platform/web_rtc_certificate.h" -#include "third_party/webrtc/rtc_base/rtccertificate.h" -#include "third_party/webrtc/rtc_base/scoped_ref_ptr.h" - -namespace content { - -// Chromium's WebRTCCertificate implementation; wraps a rtc::scoped_refptr to an -// rtc::RTCCertificate. This abstraction layer is necessary because blink does -// not have direct access to WebRTC. -class CONTENT_EXPORT RTCCertificate : public blink::WebRTCCertificate { - public: - RTCCertificate(const rtc::scoped_refptr<rtc::RTCCertificate>& certificate); - ~RTCCertificate() override; - - // blink::WebRTCCertificate implementation. - std::unique_ptr<blink::WebRTCCertificate> ShallowCopy() const override; - uint64_t Expires() const override; - blink::WebVector<blink::WebRTCDtlsFingerprint> GetFingerprints() - const override; - blink::WebRTCCertificatePEM ToPEM() const override; - bool Equals(const blink::WebRTCCertificate& other) const override; - - const rtc::scoped_refptr<rtc::RTCCertificate>& rtcCertificate() const; - - private: - rtc::scoped_refptr<rtc::RTCCertificate> certificate_; - - DISALLOW_COPY_AND_ASSIGN(RTCCertificate); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_MEDIA_WEBRTC_RTC_CERTIFICATE_H_
diff --git a/content/renderer/media/webrtc/rtc_certificate_generator.cc b/content/renderer/media/webrtc/rtc_certificate_generator.cc index 4f5ff47..2b3924b 100644 --- a/content/renderer/media/webrtc/rtc_certificate_generator.cc +++ b/content/renderer/media/webrtc/rtc_certificate_generator.cc
@@ -12,7 +12,6 @@ #include "base/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "content/renderer/media/webrtc/peer_connection_dependency_factory.h" -#include "content/renderer/media/webrtc/rtc_certificate.h" #include "content/renderer/render_thread_impl.h" #include "media/media_buildflags.h" #include "third_party/webrtc/rtc_base/rtccertificate.h" @@ -91,15 +90,12 @@ main_thread_->PostTask( FROM_HERE, base::BindOnce(&RTCCertificateGeneratorRequest::DoCallbackOnMainThread, - this, std::move(observer), - certificate - ? std::make_unique<RTCCertificate>(certificate) - : nullptr)); + this, std::move(observer), certificate)); } void DoCallbackOnMainThread( CertificateCallbackPtr observer, - std::unique_ptr<blink::WebRTCCertificate> certificate) { + rtc::scoped_refptr<rtc::RTCCertificate> certificate) { DCHECK(main_thread_->BelongsToCurrentThread()); DCHECK(observer); if (certificate) @@ -155,7 +151,7 @@ return WebRTCKeyParamsToKeyParams(key_params).IsValid(); } -std::unique_ptr<blink::WebRTCCertificate> RTCCertificateGenerator::FromPEM( +rtc::scoped_refptr<rtc::RTCCertificate> RTCCertificateGenerator::FromPEM( blink::WebString pem_private_key, blink::WebString pem_certificate) { rtc::scoped_refptr<rtc::RTCCertificate> certificate = @@ -163,7 +159,7 @@ pem_private_key.Utf8(), pem_certificate.Utf8())); if (!certificate) return nullptr; - return std::make_unique<RTCCertificate>(certificate); + return certificate; } } // namespace content
diff --git a/content/renderer/media/webrtc/rtc_certificate_generator.h b/content/renderer/media/webrtc/rtc_certificate_generator.h index 5e29c7f..f3fa2ce 100644 --- a/content/renderer/media/webrtc/rtc_certificate_generator.h +++ b/content/renderer/media/webrtc/rtc_certificate_generator.h
@@ -7,9 +7,9 @@ #include "base/macros.h" #include "base/single_thread_task_runner.h" -#include "third_party/blink/public/platform/web_rtc_certificate.h" #include "third_party/blink/public/platform/web_rtc_certificate_generator.h" #include "third_party/blink/public/platform/web_rtc_key_params.h" +#include "third_party/webrtc/api/peerconnectioninterface.h" namespace content { @@ -32,7 +32,7 @@ std::unique_ptr<blink::WebRTCCertificateCallback> observer, scoped_refptr<base::SingleThreadTaskRunner> task_runner) override; bool IsSupportedKeyParams(const blink::WebRTCKeyParams& key_params) override; - std::unique_ptr<blink::WebRTCCertificate> FromPEM( + rtc::scoped_refptr<rtc::RTCCertificate> FromPEM( blink::WebString pem_private_key, blink::WebString pem_certificate) override;
diff --git a/content/renderer/media/webrtc/rtc_peer_connection_handler.cc b/content/renderer/media/webrtc/rtc_peer_connection_handler.cc index e9b8755e..b41ed0ff 100644 --- a/content/renderer/media/webrtc/rtc_peer_connection_handler.cc +++ b/content/renderer/media/webrtc/rtc_peer_connection_handler.cc
@@ -30,7 +30,6 @@ #include "content/renderer/media/stream/media_stream_track.h" #include "content/renderer/media/webrtc/peer_connection_dependency_factory.h" #include "content/renderer/media/webrtc/peer_connection_tracker.h" -#include "content/renderer/media/webrtc/rtc_certificate.h" #include "content/renderer/media/webrtc/rtc_data_channel_handler.h" #include "content/renderer/media/webrtc/rtc_dtmf_sender_handler.h" #include "content/renderer/media/webrtc/rtc_event_log_output_sink.h" @@ -214,11 +213,8 @@ } webrtc_config->certificates.clear(); - for (const std::unique_ptr<blink::WebRTCCertificate>& blink_certificate : - blink_config.certificates) { - webrtc_config->certificates.push_back( - static_cast<RTCCertificate*>(blink_certificate.get()) - ->rtcCertificate()); + for (const auto& blink_certificate : blink_config.certificates) { + webrtc_config->certificates.push_back(blink_certificate); } webrtc_config->ice_candidate_pool_size = blink_config.ice_candidate_pool_size;
diff --git a/content/renderer/mus/renderer_window_tree_client.cc b/content/renderer/mus/renderer_window_tree_client.cc index 516c37f6b..50d6f1b 100644 --- a/content/renderer/mus/renderer_window_tree_client.cc +++ b/content/renderer/mus/renderer_window_tree_client.cc
@@ -32,7 +32,7 @@ // static void RendererWindowTreeClient::CreateIfNecessary(int routing_id) { - if (features::IsAshInBrowserProcess() || Get(routing_id)) + if (!features::IsUsingWindowService() || Get(routing_id)) return; RendererWindowTreeClient* connection = new RendererWindowTreeClient(routing_id); @@ -237,7 +237,7 @@ const viz::FrameSinkId& frame_sink_id) { // When mus is not hosting viz FrameSinkIds come from the browser, so we // ignore them here. - if (features::IsAshInBrowserProcess()) + if (!features::IsUsingWindowService()) return; for (MusEmbeddedFrame* embedded_frame : embedded_frames_) { @@ -331,7 +331,7 @@ void RendererWindowTreeClient::OnWindowSurfaceChanged( ui::Id window_id, const viz::SurfaceInfo& surface_info) { - DCHECK(!features::IsAshInBrowserProcess()); + DCHECK(features::IsUsingWindowService()); for (MusEmbeddedFrame* embedded_frame : embedded_frames_) { if (embedded_frame->window_id_ == window_id) { embedded_frame->delegate_->OnMusEmbeddedFrameSurfaceChanged(surface_info);
diff --git a/content/renderer/render_frame_proxy.cc b/content/renderer/render_frame_proxy.cc index 9cc1fdc..183177b 100644 --- a/content/renderer/render_frame_proxy.cc +++ b/content/renderer/render_frame_proxy.cc
@@ -249,7 +249,7 @@ render_widget_->GetOriginalScreenInfo(); #if defined(USE_AURA) - if (!features::IsAshInBrowserProcess()) { + if (features::IsUsingWindowService()) { RendererWindowTreeClient* renderer_window_tree_client = RendererWindowTreeClient::Get(render_widget_->routing_id()); // It's possible a MusEmbeddedFrame has already been scheduled for creation @@ -491,7 +491,7 @@ const FrameMsg_ViewChanged_Params& params) { crashed_ = false; // In mash the FrameSinkId comes from RendererWindowTreeClient. - if (features::IsAshInBrowserProcess()) + if (!features::IsUsingWindowService()) frame_sink_id_ = *params.frame_sink_id; // Resend the FrameRects and allocate a new viz::LocalSurfaceId when the view @@ -883,7 +883,7 @@ void RenderFrameProxy::OnMusEmbeddedFrameSinkIdAllocated( const viz::FrameSinkId& frame_sink_id) { // RendererWindowTreeClient should only call this when mus is hosting viz. - DCHECK(!features::IsAshInBrowserProcess()); + DCHECK(features::IsUsingWindowService()); frame_sink_id_ = frame_sink_id; // Resend the FrameRects and allocate a new viz::LocalSurfaceId when the view // changes.
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index db2edf8..6357e06 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -745,9 +745,9 @@ main_thread_runner(), GetConnector())); gpu_ = ui::Gpu::Create(GetConnector(), - features::IsAshInBrowserProcess() - ? mojom::kBrowserServiceName - : ui::mojom::kServiceName, + features::IsUsingWindowService() + ? ui::mojom::kServiceName + : mojom::kBrowserServiceName, GetIOTaskRunner()); resource_dispatcher_.reset(new ResourceDispatcher()); @@ -801,7 +801,7 @@ AddFilter(midi_message_filter_.get()); #if defined(USE_AURA) - if (!features::IsAshInBrowserProcess()) + if (features::IsUsingWindowService()) CreateRenderWidgetWindowTreeClientFactory(GetServiceManagerConnection()); #endif @@ -956,7 +956,7 @@ categorized_worker_pool_->Start(num_raster_threads); discardable_memory::mojom::DiscardableSharedMemoryManagerPtr manager_ptr; - if (!features::IsAshInBrowserProcess()) { + if (features::IsUsingWindowService()) { #if defined(USE_AURA) GetServiceManagerConnection()->GetConnector()->BindInterface( ui::mojom::kServiceName, &manager_ptr); @@ -1948,7 +1948,7 @@ params.synthetic_begin_frame_source = CreateSyntheticBeginFrameSource(); #if defined(USE_AURA) - if (!features::IsAshInBrowserProcess()) { + if (features::IsUsingWindowService()) { if (!RendererWindowTreeClient::Get(routing_id)) { std::move(callback).Run(nullptr); return;
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index bf4fc27..3f35799 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -452,7 +452,7 @@ } #if defined(USE_AURA) RendererWindowTreeClient::CreateIfNecessary(routing_id_); - if (!features::IsAshInBrowserProcess()) + if (features::IsUsingWindowService()) RendererWindowTreeClient::Get(routing_id_)->SetVisible(!is_hidden_); #endif @@ -2244,7 +2244,7 @@ is_hidden_ = hidden; #if defined(USE_AURA) - if (!features::IsAshInBrowserProcess()) + if (features::IsUsingWindowService()) RendererWindowTreeClient::Get(routing_id_)->SetVisible(!hidden); #endif
diff --git a/content/test/data/accessibility/aria/aria-blockquote-expected-auralinux.txt b/content/test/data/accessibility/aria/aria-blockquote-expected-auralinux.txt index 1b90db26..8997e80f 100644 --- a/content/test/data/accessibility/aria/aria-blockquote-expected-auralinux.txt +++ b/content/test/data/accessibility/aria/aria-blockquote-expected-auralinux.txt
@@ -1,3 +1,3 @@ -[document web] enabled focusable focused sensitive showing visible<newline> -++[block quote] enabled sensitive showing visible<newline> -++++[text] name='Blockquote' enabled sensitive showing visible<newline> +[document web] +++[block quote] xml-roles:blockquote +++++[text] name='Blockquote'
diff --git a/content/test/data/accessibility/aria/aria-blockquote.html b/content/test/data/accessibility/aria/aria-blockquote.html index 895bbfa..0b325ca 100644 --- a/content/test/data/accessibility/aria/aria-blockquote.html +++ b/content/test/data/accessibility/aria/aria-blockquote.html
@@ -1,6 +1,7 @@ <!-- @MAC-ALLOW:AXRole* @WIN-ALLOW:xml-roles* +@AURALINUX-ALLOW:xml-roles* --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/aria/aria-caption-expected-auralinux.txt b/content/test/data/accessibility/aria/aria-caption-expected-auralinux.txt index a652cae..8370b6a 100644 --- a/content/test/data/accessibility/aria/aria-caption-expected-auralinux.txt +++ b/content/test/data/accessibility/aria/aria-caption-expected-auralinux.txt
@@ -1,3 +1,3 @@ -[document web] enabled focusable focused sensitive showing visible<newline> -++[caption] enabled sensitive showing visible<newline> -++++[text] name='Caption' enabled sensitive showing visible<newline> +[document web] +++[caption] xml-roles:caption +++++[text] name='Caption'
diff --git a/content/test/data/accessibility/aria/aria-caption.html b/content/test/data/accessibility/aria/aria-caption.html index c353764..c2cd66b78 100644 --- a/content/test/data/accessibility/aria/aria-caption.html +++ b/content/test/data/accessibility/aria/aria-caption.html
@@ -1,6 +1,7 @@ <!-- @MAC-ALLOW:AXRole* @WIN-ALLOW:xml-roles* +@AURALINUX-ALLOW:xml-roles* --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/aria/aria-paragraph-expected-auralinux.txt b/content/test/data/accessibility/aria/aria-paragraph-expected-auralinux.txt index b1fe1873..8d532173 100644 --- a/content/test/data/accessibility/aria/aria-paragraph-expected-auralinux.txt +++ b/content/test/data/accessibility/aria/aria-paragraph-expected-auralinux.txt
@@ -1,3 +1,3 @@ -[document web] enabled focusable focused sensitive showing visible<newline> -++[paragraph] enabled sensitive showing visible<newline> -++++[text] name='Paragraph' enabled sensitive showing visible<newline> +[document web] +++[paragraph] xml-roles:paragraph +++++[text] name='Paragraph'
diff --git a/content/test/data/accessibility/aria/aria-paragraph.html b/content/test/data/accessibility/aria/aria-paragraph.html index ca5a12b..df762fdd 100644 --- a/content/test/data/accessibility/aria/aria-paragraph.html +++ b/content/test/data/accessibility/aria/aria-paragraph.html
@@ -1,6 +1,7 @@ <!-- @MAC-ALLOW:AXRole* @WIN-ALLOW:xml-roles* +@AURALINUX-ALLOW:xml-roles* --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/aria/dpub-roles-expected-auralinux.txt b/content/test/data/accessibility/aria/dpub-roles-expected-auralinux.txt index e0e10c8..22ef39e 100644 --- a/content/test/data/accessibility/aria/dpub-roles-expected-auralinux.txt +++ b/content/test/data/accessibility/aria/dpub-roles-expected-auralinux.txt
@@ -1,40 +1,40 @@ -[document web] enabled focusable focused sensitive showing visible<newline> -++[section] name='doc-abstract' enabled sensitive showing visible<newline> -++[landmark] name='doc-acknowledgments' enabled sensitive showing visible<newline> -++[landmark] name='doc-afterword' enabled sensitive showing visible<newline> -++[landmark] name='doc-appendix' enabled sensitive showing visible<newline> -++[link] name='doc-backlink' enabled sensitive showing visible<newline> -++[list item] name='doc-biblioentry' enabled sensitive showing visible<newline> -++[landmark] name='doc-bibliography' enabled sensitive showing visible<newline> -++[link] name='doc-biblioref' enabled sensitive showing visible<newline> -++[landmark] name='doc-chapter' enabled sensitive showing visible<newline> -++[section] name='doc-colophon' enabled sensitive showing visible<newline> -++[landmark] name='doc-conclusion' enabled sensitive showing visible<newline> -++[image] name='doc-cover' enabled sensitive showing visible<newline> -++[section] name='doc-credit' enabled sensitive showing visible<newline> -++[landmark] name='doc-credits' enabled sensitive showing visible<newline> -++[section] name='doc-dedication' enabled sensitive showing visible<newline> -++[list item] name='doc-endnote' enabled sensitive showing visible<newline> -++[landmark] name='doc-endnotes' enabled sensitive showing visible<newline> -++[section] name='doc-epigraph' enabled sensitive showing visible<newline> -++[landmark] name='doc-epilogue' enabled sensitive showing visible<newline> -++[landmark] name='doc-errata' enabled sensitive showing visible<newline> -++[section] name='doc-example' enabled sensitive showing visible<newline> -++[footnote] name='doc-footnote' enabled sensitive showing visible<newline> -++[landmark] name='doc-foreword' enabled sensitive showing visible<newline> -++[landmark] name='doc-glossary' enabled sensitive showing visible<newline> -++[link] name='doc-glossref' enabled sensitive showing visible<newline> -++[landmark] name='doc-index' enabled sensitive showing visible<newline> -++[landmark] name='doc-introduction' enabled sensitive showing visible<newline> -++[link] name='doc-noteref' enabled sensitive showing visible<newline> -++[comment] name='doc-notice' enabled sensitive showing visible<newline> -++[separator] name='doc-pagebreak' enabled sensitive showing visible<newline> -++[landmark] name='doc-pagelist' enabled sensitive showing visible<newline> -++[landmark] name='doc-part' enabled sensitive showing visible<newline> -++[landmark] name='doc-preface' enabled sensitive showing visible<newline> -++[landmark] name='doc-prologue' enabled sensitive showing visible<newline> -++[section] name='doc-pullquote' enabled sensitive showing visible<newline> -++[section] name='doc-qna' enabled sensitive showing visible<newline> -++[heading] name='doc-subtitle' enabled sensitive showing visible<newline> -++[comment] name='doc-tip' enabled sensitive showing visible<newline> -++[landmark] name='doc-toc' enabled sensitive showing visible<newline> +[document web] +++[section] name='doc-abstract' xml-roles:doc-abstract +++[landmark] name='doc-acknowledgments' xml-roles:doc-acknowledgments +++[landmark] name='doc-afterword' xml-roles:doc-afterword +++[landmark] name='doc-appendix' xml-roles:doc-appendix +++[link] name='doc-backlink' xml-roles:doc-backlink +++[list item] name='doc-biblioentry' xml-roles:doc-biblioentry +++[landmark] name='doc-bibliography' xml-roles:doc-bibliography +++[link] name='doc-biblioref' xml-roles:doc-biblioref +++[landmark] name='doc-chapter' xml-roles:doc-chapter +++[section] name='doc-colophon' xml-roles:doc-colophon +++[landmark] name='doc-conclusion' xml-roles:doc-conclusion +++[image] name='doc-cover' xml-roles:doc-cover +++[section] name='doc-credit' xml-roles:doc-credit +++[landmark] name='doc-credits' xml-roles:doc-credits +++[section] name='doc-dedication' xml-roles:doc-dedication +++[list item] name='doc-endnote' xml-roles:doc-endnote +++[landmark] name='doc-endnotes' xml-roles:doc-endnotes +++[section] name='doc-epigraph' xml-roles:doc-epigraph +++[landmark] name='doc-epilogue' xml-roles:doc-epilogue +++[landmark] name='doc-errata' xml-roles:doc-errata +++[section] name='doc-example' xml-roles:doc-example +++[footnote] name='doc-footnote' xml-roles:doc-footnote +++[landmark] name='doc-foreword' xml-roles:doc-foreword +++[landmark] name='doc-glossary' xml-roles:doc-glossary +++[link] name='doc-glossref' xml-roles:doc-glossref +++[landmark] name='doc-index' xml-roles:doc-index +++[landmark] name='doc-introduction' xml-roles:doc-introduction +++[link] name='doc-noteref' xml-roles:doc-noteref +++[comment] name='doc-notice' xml-roles:doc-notice +++[separator] name='doc-pagebreak' xml-roles:doc-pagebreak +++[landmark] name='doc-pagelist' xml-roles:doc-pagelist +++[landmark] name='doc-part' xml-roles:doc-part +++[landmark] name='doc-preface' xml-roles:doc-preface +++[landmark] name='doc-prologue' xml-roles:doc-prologue +++[section] name='doc-pullquote' xml-roles:doc-pullquote +++[section] name='doc-qna' xml-roles:doc-qna +++[heading] name='doc-subtitle' xml-roles:doc-subtitle +++[comment] name='doc-tip' xml-roles:doc-tip +++[landmark] name='doc-toc' xml-roles:doc-toc
diff --git a/content/test/data/accessibility/aria/dpub-roles.html b/content/test/data/accessibility/aria/dpub-roles.html index 28c142de..a6699d13 100644 --- a/content/test/data/accessibility/aria/dpub-roles.html +++ b/content/test/data/accessibility/aria/dpub-roles.html
@@ -2,6 +2,7 @@ @MAC-ALLOW:AXRole* @MAC-ALLOW:AXSubrole* @WIN-ALLOW:xml-roles:* +@AURALINUX-ALLOW:xml-roles* --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/aria/graphics-roles-expected-auralinux.txt b/content/test/data/accessibility/aria/graphics-roles-expected-auralinux.txt index 9372606f..25541cc3 100644 --- a/content/test/data/accessibility/aria/graphics-roles-expected-auralinux.txt +++ b/content/test/data/accessibility/aria/graphics-roles-expected-auralinux.txt
@@ -1,4 +1,4 @@ -[document web] enabled focusable focused sensitive showing visible<newline> -++[document web] name='graphics-document' enabled sensitive showing visible<newline> -++[panel] name='graphics-object' enabled sensitive showing visible<newline> -++[image] name='graphics-symbol' enabled sensitive showing visible<newline> +[document web] +++[document web] name='graphics-document' xml-roles:graphics-document +++[panel] name='graphics-object' xml-roles:graphics-object +++[image] name='graphics-symbol' xml-roles:graphics-symbol
diff --git a/content/test/data/accessibility/aria/graphics-roles.html b/content/test/data/accessibility/aria/graphics-roles.html index cdde367..457e605 100644 --- a/content/test/data/accessibility/aria/graphics-roles.html +++ b/content/test/data/accessibility/aria/graphics-roles.html
@@ -2,6 +2,7 @@ @MAC-ALLOW:AXRole* @MAC-ALLOW:AXSubrole* @WIN-ALLOW:xml-roles:* +@AURALINUX-ALLOW:xml-roles* --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/html/a-expected-auralinux.txt b/content/test/data/accessibility/html/a-expected-auralinux.txt index cb5e5d3a..d4be624a 100644 --- a/content/test/data/accessibility/html/a-expected-auralinux.txt +++ b/content/test/data/accessibility/html/a-expected-auralinux.txt
@@ -1,4 +1,4 @@ -[document web] enabled focusable focused sensitive showing visible<newline> -++[panel] enabled sensitive showing visible<newline> -++++[link] name='normal link' enabled focusable sensitive showing visible<newline> -++++++[text] name='normal link' enabled sensitive showing visible<newline> +[document web] focusable focused +++[section] +++++[link] name='normal link' focusable +++++++[text] name='normal link'
diff --git a/content/test/data/accessibility/html/a-name-calc-expected-auralinux.txt b/content/test/data/accessibility/html/a-name-calc-expected-auralinux.txt new file mode 100644 index 0000000..afdb01b --- /dev/null +++ b/content/test/data/accessibility/html/a-name-calc-expected-auralinux.txt
@@ -0,0 +1,15 @@ +[document web] +++[link] name='InnerText0' +++++[text] name='InnerText0' +++[text] name=' ' +++[link] name='InnerText1' description='Title1' +++++[text] name='InnerText1' +++[text] name=' ' +++[link] name='Title2' explicit-name:true +++++[text] name='InnerText2' +++[text] name=' ' +++[link] name='LabelledBy3' explicit-name:true +++++[text] name='InnerText3' +++[link] name='Title4' explicit-name:true +++[link] name='Label5' explicit-name:true +++[link] name='LabelledBy6' explicit-name:true
diff --git a/content/test/data/accessibility/html/a-name-calc.html b/content/test/data/accessibility/html/a-name-calc.html index 10467ad..ce2e7875 100644 --- a/content/test/data/accessibility/html/a-name-calc.html +++ b/content/test/data/accessibility/html/a-name-calc.html
@@ -5,6 +5,8 @@ @MAC-ALLOW:AXHelp* @MAC-DENY:AXValue* @BLINK-ALLOW:nameFrom* +@AURALINUX-ALLOW:description* +@AURALINUX-ALLOW:explicit-name* --> <html> <body>
diff --git a/content/test/data/accessibility/html/a-name-expected-auralinux.txt b/content/test/data/accessibility/html/a-name-expected-auralinux.txt new file mode 100644 index 0000000..4b4260bb6 --- /dev/null +++ b/content/test/data/accessibility/html/a-name-expected-auralinux.txt
@@ -0,0 +1,5 @@ +[document web] +++[link] name='named anchor' +++++[text] name='named anchor' +++[link] name='both a named anchor and a link' +++++[text] name='both a named anchor and a link'
diff --git a/content/test/data/accessibility/html/a-with-img-expected-auralinux.txt b/content/test/data/accessibility/html/a-with-img-expected-auralinux.txt new file mode 100644 index 0000000..515332a --- /dev/null +++ b/content/test/data/accessibility/html/a-with-img-expected-auralinux.txt
@@ -0,0 +1,19 @@ +[document web] +++[section] +++++[link] name='Link with image at start.' +++++++[image] name='Link' +++++++[text] name=' with image at start.' +++++[text] name=' ' +++++[link] name='Link with image in the middle.' +++++++[text] name='Link with ' +++++++[image] name='image' +++++++[text] name=' in the middle.' +++++[text] name=' ' +++++[link] name='Link with broken in the middle.' +++++++[text] name='Link with ' +++++++[image] name='broken' +++++++[text] name=' in the middle.' +++++[text] name=' ' +++++[link] name='Link with image at the end' +++++++[text] name='Link with image at the ' +++++++[image] name='end'
diff --git a/content/test/data/accessibility/html/a.html b/content/test/data/accessibility/html/a.html index 7b0bf21..4d164f3 100644 --- a/content/test/data/accessibility/html/a.html +++ b/content/test/data/accessibility/html/a.html
@@ -2,6 +2,7 @@ @BLINK-ALLOW:inPageLinkTargetId=* @BLINK-ALLOW:linked @WIN-ALLOW:LINKED +@AURALINUX-ALLOW:focus* --> <html> <body>
diff --git a/content/test/data/accessibility/html/abbr-expected-auralinux.txt b/content/test/data/accessibility/html/abbr-expected-auralinux.txt new file mode 100644 index 0000000..1b168654 --- /dev/null +++ b/content/test/data/accessibility/html/abbr-expected-auralinux.txt
@@ -0,0 +1,6 @@ +[document web] +++[paragraph] +++++[text] name='The ' +++++[static] name='World Health Organization' +++++++[text] name='WHO' +++++[text] name=' was founded in 1948.'
diff --git a/content/test/data/accessibility/html/address-expected-auralinux.txt b/content/test/data/accessibility/html/address-expected-auralinux.txt new file mode 100644 index 0000000..1216a6af --- /dev/null +++ b/content/test/data/accessibility/html/address-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] +++[landmark] +++++[text] name='Please contact John Citizen for more information.'
diff --git a/content/test/data/accessibility/html/area-expected-auralinux.txt b/content/test/data/accessibility/html/area-expected-auralinux.txt new file mode 100644 index 0000000..a7e76218 --- /dev/null +++ b/content/test/data/accessibility/html/area-expected-auralinux.txt
@@ -0,0 +1,5 @@ +[document web] +++[section] +++++[image map] name='pipe' +++++++[link] name='pipe1' +++++++[link] name='pipe2'
diff --git a/content/test/data/accessibility/html/article-expected-auralinux.txt b/content/test/data/accessibility/html/article-expected-auralinux.txt new file mode 100644 index 0000000..2ab5917 --- /dev/null +++ b/content/test/data/accessibility/html/article-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] +++[article] xml-roles:article +++++[text] name='This is an article element.'
diff --git a/content/test/data/accessibility/html/article.html b/content/test/data/accessibility/html/article.html index 532f72a73..10af48b 100644 --- a/content/test/data/accessibility/html/article.html +++ b/content/test/data/accessibility/html/article.html
@@ -3,6 +3,7 @@ @MAC-ALLOW:AXSubrole=AXDocumentArticle @MAC-DENY:AXTitle* @WIN-ALLOW:xml-roles:article +@AURALINUX-ALLOW:xml-roles:article --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/html/aside-expected-auralinux.txt b/content/test/data/accessibility/html/aside-expected-auralinux.txt new file mode 100644 index 0000000..b3c13bf --- /dev/null +++ b/content/test/data/accessibility/html/aside-expected-auralinux.txt
@@ -0,0 +1,8 @@ +[document web] +++[paragraph] +++++[text] name='The aside tag defines some content aside from the content it is placed in.' +++[landmark] xml-roles:complementary +++++[heading] name='Aside tag' xml-roles:heading +++++++[text] name='Aside tag' +++++[paragraph] +++++++[text] name='The aside content should be related to the surrounding content.'
diff --git a/content/test/data/accessibility/html/aside.html b/content/test/data/accessibility/html/aside.html index 37e3e9a..be71103d 100644 --- a/content/test/data/accessibility/html/aside.html +++ b/content/test/data/accessibility/html/aside.html
@@ -2,6 +2,7 @@ @MAC-ALLOW:AXRole* @MAC-ALLOW:AXSubrole=* @WIN-ALLOW:xml-roles* +@AURALINUX-ALLOW:xml-roles* --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/html/audio-expected-auralinux.txt b/content/test/data/accessibility/html/audio-expected-auralinux.txt new file mode 100644 index 0000000..a0d4367 --- /dev/null +++ b/content/test/data/accessibility/html/audio-expected-auralinux.txt
@@ -0,0 +1,11 @@ +[document web] +++[section] +++++[audio] +++++++[section] +++++++++[tool bar] name='audio' description='audio' horizontal +++++++++++[tool bar] name='audio' description='audio' horizontal +++++++++++++[push button] name='play' description='begin playback' xml-roles:button +++++++++++++[text] name='0:00' +++++++++++++[text] name='/ 0:00' +++++++++++++[slider] description='audio time scrubber' horizontal xml-roles:slider +++++++++++++[push button] name='mute' description='mute audio track' xml-roles:button
diff --git a/content/test/data/accessibility/html/audio.html b/content/test/data/accessibility/html/audio.html index 4ae0f3b..105c1da 100644 --- a/content/test/data/accessibility/html/audio.html +++ b/content/test/data/accessibility/html/audio.html
@@ -1,6 +1,10 @@ <!-- @WIN-ALLOW:xml-roles* @WIN-ALLOW:description* +@AURALINUX-ALLOW:xml-roles* +@AURALINUX-ALLOW:description* +@AURALINUX-ALLOW:horizontal +@AURALINUX-ALLOW:vertical --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/html/b-expected-auralinux.txt b/content/test/data/accessibility/html/b-expected-auralinux.txt new file mode 100644 index 0000000..644c967 --- /dev/null +++ b/content/test/data/accessibility/html/b-expected-auralinux.txt
@@ -0,0 +1,5 @@ +[document web] +++[paragraph] +++++[text] name='Some ' +++++[text] name='bold' +++++[text] name=' text'
diff --git a/content/test/data/accessibility/html/base-expected-auralinux.txt b/content/test/data/accessibility/html/base-expected-auralinux.txt new file mode 100644 index 0000000..19b9c9f --- /dev/null +++ b/content/test/data/accessibility/html/base-expected-auralinux.txt
@@ -0,0 +1 @@ +[document web]
diff --git a/content/test/data/accessibility/html/bdo-expected-auralinux.txt b/content/test/data/accessibility/html/bdo-expected-auralinux.txt new file mode 100644 index 0000000..17fc34d --- /dev/null +++ b/content/test/data/accessibility/html/bdo-expected-auralinux.txt
@@ -0,0 +1,6 @@ +[document web] +++[section] +++++[text] name='Some LTR text' +++++[text] name=' ' +++++[text] name='Some RTL text ' +++++[text] name='with some LTR text embedded'
diff --git a/content/test/data/accessibility/html/blockquote-expected-auralinux.txt b/content/test/data/accessibility/html/blockquote-expected-auralinux.txt index 2b0a264..6266276 100644 --- a/content/test/data/accessibility/html/blockquote-expected-auralinux.txt +++ b/content/test/data/accessibility/html/blockquote-expected-auralinux.txt
@@ -1,6 +1,6 @@ -[document web] enabled focusable focused sensitive showing visible<newline> -++[block quote] enabled sensitive showing visible<newline> -++++[paragraph] enabled sensitive showing visible<newline> -++++++[text] name='First blockquote has a child element.' enabled sensitive showing visible<newline> -++[block quote] enabled sensitive showing visible<newline> -++++[text] name='Second blockquote has no child.' enabled sensitive showing visible<newline> +[document web] +++[block quote] +++++[paragraph] +++++++[text] name='First blockquote has a child element.' +++[block quote] +++++[text] name='Second blockquote has no child.'
diff --git a/content/test/data/accessibility/html/body-expected-auralinux.txt b/content/test/data/accessibility/html/body-expected-auralinux.txt new file mode 100644 index 0000000..89b5fee --- /dev/null +++ b/content/test/data/accessibility/html/body-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] +++[paragraph] +++++[text] name='This test is for body tag'
diff --git a/content/test/data/accessibility/html/br-expected-auralinux.txt b/content/test/data/accessibility/html/br-expected-auralinux.txt new file mode 100644 index 0000000..b8f61444 --- /dev/null +++ b/content/test/data/accessibility/html/br-expected-auralinux.txt
@@ -0,0 +1,8 @@ +[document web] +++[text] name='<newline>' +++[text] name='Text line 1' +++[paragraph] +++++[text] name='Text line 2' +++++[text] name='<newline>' +++++[text] name='Text line 3' +++[text] name='<newline>'
diff --git a/content/test/data/accessibility/html/button-expected-auralinux.txt b/content/test/data/accessibility/html/button-expected-auralinux.txt new file mode 100644 index 0000000..574bb6ef7 --- /dev/null +++ b/content/test/data/accessibility/html/button-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] +++[section] +++++[push button] name='Click me!'
diff --git a/content/test/data/accessibility/html/button-name-calc-expected-auralinux.txt b/content/test/data/accessibility/html/button-name-calc-expected-auralinux.txt new file mode 100644 index 0000000..39002bd --- /dev/null +++ b/content/test/data/accessibility/html/button-name-calc-expected-auralinux.txt
@@ -0,0 +1,10 @@ +[document web] +++[push button] name='InnerText0' +++[push button] name='InnerText1' description='Title1' +++[push button] name='AriaLabel2' description='Title2' explicit-name:true +++[push button] name='LabelledBy3' description='Title3' explicit-name:true +++[push button] name='LabelledBy4' description='DescribedBy4' explicit-name:true +++[push button] name='InnerText5' description='DescribedBy5' +++[push button] name='Outer inner' +++[push button] name='Outer inner1' +++[push button] name='Outer grandchild'
diff --git a/content/test/data/accessibility/html/button-name-calc.html b/content/test/data/accessibility/html/button-name-calc.html index 7c783b9..bd8170c2 100644 --- a/content/test/data/accessibility/html/button-name-calc.html +++ b/content/test/data/accessibility/html/button-name-calc.html
@@ -1,6 +1,8 @@ <!-- @WIN-ALLOW:description* @WIN-ALLOW:explicit-name* +@AURALINUX-ALLOW:description* +@AURALINUX-ALLOW:explicit-name* @MAC-ALLOW:AXDescription* @MAC-ALLOW:AXHelp* @MAC-DENY:AXValue*
diff --git a/content/test/data/accessibility/html/canvas-expected-auralinux.txt b/content/test/data/accessibility/html/canvas-expected-auralinux.txt new file mode 100644 index 0000000..36378eb --- /dev/null +++ b/content/test/data/accessibility/html/canvas-expected-auralinux.txt
@@ -0,0 +1,7 @@ +[document web] +++[section] +++++[canvas] +++++++[text] name='Static fallback' +++++[canvas] +++++++[link] name='Interactive fallback' +++++++++[text] name='Interactive fallback'
diff --git a/content/test/data/accessibility/html/caption-expected-auralinux.txt b/content/test/data/accessibility/html/caption-expected-auralinux.txt index 7f46e58..c238565 100644 --- a/content/test/data/accessibility/html/caption-expected-auralinux.txt +++ b/content/test/data/accessibility/html/caption-expected-auralinux.txt
@@ -1,19 +1,19 @@ -[document web] enabled focusable focused sensitive showing visible<newline> -++[table] name='Browser and Engine' enabled sensitive showing visible<newline> -++++[caption] enabled sensitive showing visible<newline> -++++++[text] name='Browser and Engine' enabled sensitive showing visible<newline> -++++[table row] enabled sensitive showing visible<newline> -++++++[column header] name='Browser' enabled sensitive showing visible<newline> -++++++++[text] name='Browser' enabled sensitive showing visible<newline> -++++++[column header] name='Engine' enabled sensitive showing visible<newline> -++++++++[text] name='Engine' enabled sensitive showing visible<newline> -++++[table row] enabled sensitive showing visible<newline> -++++++[table cell] name='Chrome' enabled sensitive showing visible<newline> -++++++++[text] name='Chrome' enabled sensitive showing visible<newline> -++++++[table cell] name='Blink' enabled sensitive showing visible<newline> -++++++++[text] name='Blink' enabled sensitive showing visible<newline> -++++[table row] enabled sensitive showing visible<newline> -++++++[table cell] name='Safari' enabled sensitive showing visible<newline> -++++++++[text] name='Safari' enabled sensitive showing visible<newline> -++++++[table cell] name='WebKit' enabled sensitive showing visible<newline> -++++++++[text] name='WebKit' enabled sensitive showing visible<newline> +[document web] +++[table] name='Browser and Engine' +++++[caption] +++++++[text] name='Browser and Engine' +++++[table row] +++++++[column header] name='Browser' +++++++++[text] name='Browser' +++++++[column header] name='Engine' +++++++++[text] name='Engine' +++++[table row] +++++++[table cell] name='Chrome' +++++++++[text] name='Chrome' +++++++[table cell] name='Blink' +++++++++[text] name='Blink' +++++[table row] +++++++[table cell] name='Safari' +++++++++[text] name='Safari' +++++++[table cell] name='WebKit' +++++++++[text] name='WebKit'
diff --git a/content/test/data/accessibility/html/checkbox-name-calc-expected-auralinux.txt b/content/test/data/accessibility/html/checkbox-name-calc-expected-auralinux.txt new file mode 100644 index 0000000..6a5596a5 --- /dev/null +++ b/content/test/data/accessibility/html/checkbox-name-calc-expected-auralinux.txt
@@ -0,0 +1,7 @@ +[document web] +++[check box] name='Title0' checkable:true explicit-name:true +++[check box] name='Label1' description='Title1' checkable:true explicit-name:true +++[check box] name='AriaLabel2' description='Title2' checkable:true explicit-name:true +++[check box] name='LabelledBy3' description='Title3' checkable:true explicit-name:true +++[check box] name='LabelledBy4' description='DescribedBy4' checkable:true explicit-name:true +++[check box] description='DescribedBy5' checkable:true
diff --git a/content/test/data/accessibility/html/checkbox-name-calc.html b/content/test/data/accessibility/html/checkbox-name-calc.html index c1c96d3b..7d78725 100644 --- a/content/test/data/accessibility/html/checkbox-name-calc.html +++ b/content/test/data/accessibility/html/checkbox-name-calc.html
@@ -1,6 +1,10 @@ <!-- @WIN-ALLOW:description* @WIN-ALLOW:explicit-name* +@AURALINUX-ALLOW:description* +@AURALINUX-ALLOW:explicit-name* +@AURALINUX-DENY:checkable +@AURALINUX-DENY:last-defined @MAC-ALLOW:AXDescription* @MAC-ALLOW:AXHelp* @MAC-DENY:AXValue*
diff --git a/content/test/data/accessibility/html/cite-expected-auralinux.txt b/content/test/data/accessibility/html/cite-expected-auralinux.txt new file mode 100644 index 0000000..29e849c2 --- /dev/null +++ b/content/test/data/accessibility/html/cite-expected-auralinux.txt
@@ -0,0 +1,5 @@ +[document web] +++[image] name='Pipe' +++[paragraph] +++++[text] name='The pipe' +++++[text] name=' clicked by SomeOne.'
diff --git a/content/test/data/accessibility/html/code-expected-auralinux.txt b/content/test/data/accessibility/html/code-expected-auralinux.txt new file mode 100644 index 0000000..c1366e3 --- /dev/null +++ b/content/test/data/accessibility/html/code-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] +++[section] +++++[text] name='A piece of computer code'
diff --git a/content/test/data/accessibility/html/col-expected-auralinux.txt b/content/test/data/accessibility/html/col-expected-auralinux.txt new file mode 100644 index 0000000..6481413 --- /dev/null +++ b/content/test/data/accessibility/html/col-expected-auralinux.txt
@@ -0,0 +1,12 @@ +[document web] +++[table] +++++[table row] +++++++[column header] name='Browser' +++++++++[text] name='Browser' +++++++[column header] name='Rendering Engine' +++++++++[text] name='Rendering Engine' +++++[table row] +++++++[table cell] name='Chrome' +++++++++[text] name='Chrome' +++++++[table cell] name='Blink' +++++++++[text] name='Blink'
diff --git a/content/test/data/accessibility/html/colgroup-expected-auralinux.txt b/content/test/data/accessibility/html/colgroup-expected-auralinux.txt new file mode 100644 index 0000000..8861fab --- /dev/null +++ b/content/test/data/accessibility/html/colgroup-expected-auralinux.txt
@@ -0,0 +1,12 @@ +[document web] +++[table] +++++[table row] +++++++[column header] name='Single' +++++++++[text] name='Single' +++++++[column header] name='Pair' +++++++++[text] name='Pair' +++++[table row] +++++++[table cell] name='A' +++++++++[text] name='A' +++++++[table cell] name='AA' +++++++++[text] name='AA'
diff --git a/content/test/data/accessibility/html/contenteditable-descendants-expected-auralinux.txt b/content/test/data/accessibility/html/contenteditable-descendants-expected-auralinux.txt new file mode 100644 index 0000000..05caaf2 --- /dev/null +++ b/content/test/data/accessibility/html/contenteditable-descendants-expected-auralinux.txt
@@ -0,0 +1,23 @@ +[document web] +++[section] editable multi-line selectable-text +++++[paragraph] editable +++++++[text] name='A contenteditable with a ' editable +++++++[link] name='link' editable +++++++++[text] name='link' editable +++++++[text] name=' and an ' editable +++++++[image] name='Image' editable +++++++[text] name=' and a ' editable +++++++[push button] name='Button' editable +++++++[text] name='.' editable +++++[table] editable +++++++[table row] editable +++++++++[table cell] name='Always expose editable tables as tables.' editable +++++++++++[text] name='Always expose editable tables as tables.' editable +++++[list] editable +++++++[list item] editable +++++++++[static] name='1. ' +++++++++[text] name='Editable list item.' editable +++[paragraph] +++++[text] name='Non-editable paragraph.' +++[paragraph] editable multi-line selectable-text +++++[text] name='Should keep the role but change the state.' editable
diff --git a/content/test/data/accessibility/html/contenteditable-descendants-with-selection-expected-auralinux.txt b/content/test/data/accessibility/html/contenteditable-descendants-with-selection-expected-auralinux.txt new file mode 100644 index 0000000..ee77eb7 --- /dev/null +++ b/content/test/data/accessibility/html/contenteditable-descendants-with-selection-expected-auralinux.txt
@@ -0,0 +1,19 @@ +[document web] +++[section] editable multi-line selectable-text +++++[paragraph] editable +++++++[text] name='A contenteditable with a ' editable +++++++[link] name='link' editable +++++++++[text] name='link' editable +++++++[text] name=' and an ' editable +++++++[image] name='Image' editable +++++++[text] name=' and a ' editable +++++++[push button] name='Button' editable +++++++[text] name='.' editable +++++[table] editable +++++++[table row] editable +++++++++[table cell] name='Always expose editable tables as tables.' editable +++++++++++[text] name='Always expose editable tables as tables.' editable +++++[list] editable +++++++[list item] editable +++++++++[static] name='1. ' +++++++++[text] name='Editable list item.' editable
diff --git a/content/test/data/accessibility/html/contenteditable-descendants-with-selection.html b/content/test/data/accessibility/html/contenteditable-descendants-with-selection.html index ee1d1931..3f91d75 100644 --- a/content/test/data/accessibility/html/contenteditable-descendants-with-selection.html +++ b/content/test/data/accessibility/html/contenteditable-descendants-with-selection.html
@@ -11,6 +11,8 @@ @BLINK-ALLOW:editable* @BLINK-ALLOW:richlyEditable* @BLINK-ALLOW:*textSel* +@AURALINUX-ALLOW:editable +@AURALINUX-ALLOW:multi-line --> <div id="contenteditable" tabindex="0" contenteditable> <p>A contenteditable with a
diff --git a/content/test/data/accessibility/html/contenteditable-descendants.html b/content/test/data/accessibility/html/contenteditable-descendants.html index 93a6e4e..c95f25d 100644 --- a/content/test/data/accessibility/html/contenteditable-descendants.html +++ b/content/test/data/accessibility/html/contenteditable-descendants.html
@@ -14,6 +14,8 @@ @BLINK-ALLOW:editable* @BLINK-ALLOW:richlyEditable* @BLINK-ALLOW:textSel* +@AURALINUX-ALLOW:editable +@AURALINUX-ALLOW:multi-line --> <div contenteditable> <p>A contenteditable with a
diff --git a/content/test/data/accessibility/html/contenteditable-with-embedded-contenteditables-expected-auralinux.txt b/content/test/data/accessibility/html/contenteditable-with-embedded-contenteditables-expected-auralinux.txt new file mode 100644 index 0000000..e2aa623 --- /dev/null +++ b/content/test/data/accessibility/html/contenteditable-with-embedded-contenteditables-expected-auralinux.txt
@@ -0,0 +1,10 @@ +[document web] +++[section] editable multi-line selectable-text +++++[paragraph] editable +++++++[text] name='This is editable.' editable +++++[text] name='This is not editable.' +++++[text] name='<newline>' +++++[paragraph] editable multi-line selectable-text +++++++[text] name='But this one is.' editable +++++[paragraph] editable +++++++[text] name='So is this one.' editable
diff --git a/content/test/data/accessibility/html/contenteditable-with-embedded-contenteditables.html b/content/test/data/accessibility/html/contenteditable-with-embedded-contenteditables.html index 47a9ff5..aaa3c91 100644 --- a/content/test/data/accessibility/html/contenteditable-with-embedded-contenteditables.html +++ b/content/test/data/accessibility/html/contenteditable-with-embedded-contenteditables.html
@@ -8,6 +8,8 @@ @BLINK-ALLOW:editable* @BLINK-ALLOW:richlyEditable* @BLINK-ALLOW:textSel* +@AURALINUX-ALLOW:editable +@AURALINUX-ALLOW:multi-line --> <div contenteditable> <p>This is editable.</p>
diff --git a/content/test/data/accessibility/html/contenteditable-with-no-descendants-expected-auralinux.txt b/content/test/data/accessibility/html/contenteditable-with-no-descendants-expected-auralinux.txt new file mode 100644 index 0000000..38f5649 --- /dev/null +++ b/content/test/data/accessibility/html/contenteditable-with-no-descendants-expected-auralinux.txt
@@ -0,0 +1,6 @@ +[document web] +++[section] name='label' editable selectable-text +++[section] description='description' editable selectable-text +++[section] name='title' editable selectable-text +++[paragraph] +++++[text] name='description'
diff --git a/content/test/data/accessibility/html/contenteditable-with-no-descendants.html b/content/test/data/accessibility/html/contenteditable-with-no-descendants.html index 21693473..7236b6c9 100644 --- a/content/test/data/accessibility/html/contenteditable-with-no-descendants.html +++ b/content/test/data/accessibility/html/contenteditable-with-no-descendants.html
@@ -2,8 +2,10 @@ @WIN-ALLOW:description* @WIN-ALLOW:IA2_STATE_EDITABLE @WIN-ALLOW:ia2_hypertext=* +@AURALINUX-ALLOW:description* @BLINK-ALLOW:editable @BLINK-ALLOW:richlyEditable +@AURALINUX-ALLOW:editable --> <div contenteditable aria-label="label"></div> <div contenteditable aria-describedby="description"></div>
diff --git a/content/test/data/accessibility/html/dd-expected-auralinux.txt b/content/test/data/accessibility/html/dd-expected-auralinux.txt new file mode 100644 index 0000000..083192e --- /dev/null +++ b/content/test/data/accessibility/html/dd-expected-auralinux.txt
@@ -0,0 +1,6 @@ +[document web] +++[description list] +++++[description term] +++++++[text] name='Coffee' +++++[description value] +++++++[text] name='Black hot drink'
diff --git a/content/test/data/accessibility/html/del-expected-auralinux.txt b/content/test/data/accessibility/html/del-expected-auralinux.txt new file mode 100644 index 0000000..83ed3cd --- /dev/null +++ b/content/test/data/accessibility/html/del-expected-auralinux.txt
@@ -0,0 +1,5 @@ +[document web] +++[paragraph] +++++[text] name='I am ' +++++[section] +++++++[text] name='vegetarian'
diff --git a/content/test/data/accessibility/html/details-expected-auralinux.txt b/content/test/data/accessibility/html/details-expected-auralinux.txt new file mode 100644 index 0000000..5bb55e5 --- /dev/null +++ b/content/test/data/accessibility/html/details-expected-auralinux.txt
@@ -0,0 +1,9 @@ +[document web] focusable focused +++[panel] +++++[toggle button] name='details tag' expandable focusable +++++++[text] name='details tag' +++[panel] +++++[toggle button] name='details tag open' expandable expanded focusable +++++++[text] name='details tag open' +++++[paragraph] +++++++[text] name='The details tag with open specifies that the details should be visible (open) to the user.'
diff --git a/content/test/data/accessibility/html/details.html b/content/test/data/accessibility/html/details.html index b0612d5..d65dcaa7 100644 --- a/content/test/data/accessibility/html/details.html +++ b/content/test/data/accessibility/html/details.html
@@ -3,6 +3,8 @@ @MAC-ALLOW:AXExpanded=* @WIN-ALLOW:EXPANDED @WIN-ALLOW:COLLAPSED +@AURALINUX-ALLOW:expand* +@AURALINUX-ALLOW:focus* --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/html/dfn-expected-auralinux.txt b/content/test/data/accessibility/html/dfn-expected-auralinux.txt new file mode 100644 index 0000000..1563d67 --- /dev/null +++ b/content/test/data/accessibility/html/dfn-expected-auralinux.txt
@@ -0,0 +1,4 @@ +[document web] tag:#document +++[section] tag:body +++++[text] name='Web Browser' +++++[text] name=' A computer program with a graphical user interface for displaying HTML files, used to navigate the World Wide Web.'
diff --git a/content/test/data/accessibility/html/dfn.html b/content/test/data/accessibility/html/dfn.html index a453e4c..b2511922 100644 --- a/content/test/data/accessibility/html/dfn.html +++ b/content/test/data/accessibility/html/dfn.html
@@ -1,3 +1,7 @@ +<!-- +@AURALINUX-ALLOW:tag* +@AURALINUX-ALLOW:xml-roles* +--> <!DOCTYPE html> <html> <body>
diff --git a/content/test/data/accessibility/html/dialog-expected-auralinux.txt b/content/test/data/accessibility/html/dialog-expected-auralinux.txt new file mode 100644 index 0000000..82d3f36 --- /dev/null +++ b/content/test/data/accessibility/html/dialog-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] +++[dialog] +++++[text] name='Text in dialog'
diff --git a/content/test/data/accessibility/html/div-expected-auralinux.txt b/content/test/data/accessibility/html/div-expected-auralinux.txt new file mode 100644 index 0000000..a7e4408 --- /dev/null +++ b/content/test/data/accessibility/html/div-expected-auralinux.txt
@@ -0,0 +1,5 @@ +[document web] +++[section] +++++[text] name='Unfocusable div' +++[section] name='Focusable div' +++++[text] name='Focusable div'
diff --git a/content/test/data/accessibility/html/dl-expected-auralinux.txt b/content/test/data/accessibility/html/dl-expected-auralinux.txt new file mode 100644 index 0000000..959d890 --- /dev/null +++ b/content/test/data/accessibility/html/dl-expected-auralinux.txt
@@ -0,0 +1,8 @@ +[document web] +++[description list] +++++[description term] +++++++[text] name='Term' +++++[description value] +++++++[text] name='Description' +++[description value] +++++[text] name='Definition'
diff --git a/content/test/data/accessibility/html/dt-expected-auralinux.txt b/content/test/data/accessibility/html/dt-expected-auralinux.txt new file mode 100644 index 0000000..083192e --- /dev/null +++ b/content/test/data/accessibility/html/dt-expected-auralinux.txt
@@ -0,0 +1,6 @@ +[document web] +++[description list] +++++[description term] +++++++[text] name='Coffee' +++++[description value] +++++++[text] name='Black hot drink'
diff --git a/content/test/data/accessibility/html/element-class-id-src-attr-expected-auralinux.txt b/content/test/data/accessibility/html/element-class-id-src-attr-expected-auralinux.txt new file mode 100644 index 0000000..b8a871ce --- /dev/null +++ b/content/test/data/accessibility/html/element-class-id-src-attr-expected-auralinux.txt
@@ -0,0 +1,4 @@ +[document web] tag:#document +++[heading] name='Image' class:headerClass id:headerID tag:h1 +++++[text] name='Image' +++[image] name='ImageAlt' class:imageClass id:imageID src:greenbox.png tag:img
diff --git a/content/test/data/accessibility/html/element-class-id-src-attr.html b/content/test/data/accessibility/html/element-class-id-src-attr.html index bd77a95..a3194c1e 100644 --- a/content/test/data/accessibility/html/element-class-id-src-attr.html +++ b/content/test/data/accessibility/html/element-class-id-src-attr.html
@@ -3,6 +3,10 @@ @WIN-ALLOW:id:* @WIN-ALLOW:src:* @WIN-ALLOW:tag:* +@AURALINUX-ALLOW:class:* +@AURALINUX-ALLOW:id:* +@AURALINUX-ALLOW:src:* +@AURALINUX-ALLOW:tag:* @BLINK-ALLOW:htmlTag* --> <!DOCTYPE html> @@ -11,4 +15,4 @@ <h1 id="headerID" class="headerClass">Image</h1> <img id="imageID" class="imageClass" src="greenbox.png" alt="ImageAlt" height="100" width="200"> </body> -</html> \ No newline at end of file +</html>
diff --git a/content/test/data/accessibility/html/em-expected-auralinux.txt b/content/test/data/accessibility/html/em-expected-auralinux.txt new file mode 100644 index 0000000..8d7fdb04 --- /dev/null +++ b/content/test/data/accessibility/html/em-expected-auralinux.txt
@@ -0,0 +1,5 @@ +[document web] +++[section] +++++[text] name='One word is ' +++++[text] name='emphasized' +++++[text] name='.'
diff --git a/content/test/data/accessibility/html/embed-expected-auralinux.txt b/content/test/data/accessibility/html/embed-expected-auralinux.txt new file mode 100644 index 0000000..1b84d9f1 --- /dev/null +++ b/content/test/data/accessibility/html/embed-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] +++[section] +++++[embedded component]
diff --git a/content/test/data/accessibility/html/fieldset-expected-auralinux.txt b/content/test/data/accessibility/html/fieldset-expected-auralinux.txt new file mode 100644 index 0000000..8a630803 --- /dev/null +++ b/content/test/data/accessibility/html/fieldset-expected-auralinux.txt
@@ -0,0 +1,5 @@ +[document web] +++[form] +++++[panel] name='Browser Engines:' +++++++[label] +++++++++[text] name='Browser Engines:'
diff --git a/content/test/data/accessibility/html/figcaption-expected-auralinux.txt b/content/test/data/accessibility/html/figcaption-expected-auralinux.txt new file mode 100644 index 0000000..5667be1 --- /dev/null +++ b/content/test/data/accessibility/html/figcaption-expected-auralinux.txt
@@ -0,0 +1,5 @@ +[document web] +++[panel] name='Fig.1 - A green Box' +++++[image] name='This is a green box.' +++++[caption] +++++++[text] name='Fig.1 - A green Box'
diff --git a/content/test/data/accessibility/html/figure-expected-auralinux.txt b/content/test/data/accessibility/html/figure-expected-auralinux.txt new file mode 100644 index 0000000..0803594 --- /dev/null +++ b/content/test/data/accessibility/html/figure-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] +++[panel] xml-roles:figure +++++[image] name='Sunspots' xml-roles:img
diff --git a/content/test/data/accessibility/html/figure.html b/content/test/data/accessibility/html/figure.html index 43f60b8..49dfa3550 100644 --- a/content/test/data/accessibility/html/figure.html +++ b/content/test/data/accessibility/html/figure.html
@@ -1,6 +1,7 @@ <!-- @MAC-ALLOW:AXRole* @WIN-ALLOW:xml-roles* +@AURALINUX-ALLOW:xml-roles* --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/html/footer-expected-auralinux.txt b/content/test/data/accessibility/html/footer-expected-auralinux.txt new file mode 100644 index 0000000..a127933 --- /dev/null +++ b/content/test/data/accessibility/html/footer-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] +++[footer] +++++[text] name='Footer element'
diff --git a/content/test/data/accessibility/html/footer-inside-other-section-expected-auralinux.txt b/content/test/data/accessibility/html/footer-inside-other-section-expected-auralinux.txt new file mode 100644 index 0000000..f5d6a1b --- /dev/null +++ b/content/test/data/accessibility/html/footer-inside-other-section-expected-auralinux.txt
@@ -0,0 +1,13 @@ +[document web] +++[article] xml-roles:article +++++[section] +++++++[paragraph] +++++++++[text] name='footer inside article.' +++[section] xml-roles:region +++++[section] +++++++[paragraph] +++++++++[text] name='footer inside section.' +++[landmark] xml-roles:main +++++[section] +++++++[paragraph] +++++++++[text] name='footer inside main.'
diff --git a/content/test/data/accessibility/html/footer-inside-other-section.html b/content/test/data/accessibility/html/footer-inside-other-section.html index 6012e34..428f727 100644 --- a/content/test/data/accessibility/html/footer-inside-other-section.html +++ b/content/test/data/accessibility/html/footer-inside-other-section.html
@@ -3,6 +3,7 @@ @MAC-ALLOW:AXRole* @MAC-ALLOW:AXSubrole* @WIN-ALLOW:xml-roles:* +@AURALINUX-ALLOW:xml-roles:* --> <article> <footer>
diff --git a/content/test/data/accessibility/html/form-expected-auralinux.txt b/content/test/data/accessibility/html/form-expected-auralinux.txt new file mode 100644 index 0000000..4300939 --- /dev/null +++ b/content/test/data/accessibility/html/form-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] +++[form] +++++[push button] name='Submit'
diff --git a/content/test/data/accessibility/html/frameset-expected-auralinux.txt b/content/test/data/accessibility/html/frameset-expected-auralinux.txt new file mode 100644 index 0000000..f4e80c4b --- /dev/null +++ b/content/test/data/accessibility/html/frameset-expected-auralinux.txt
@@ -0,0 +1,18 @@ +[document web] +++[internal frame] +++++[document web] +++++++[paragraph] +++++++++[text] name='My favorite browser is ' +++++++++[section] +++++++++++[text] name='ABC' +++++++++[text] name=' ' +++++++++[section] +++++++++++[text] name='Chrome' +++++++++[text] name='!' +++[internal frame] +++++[document web] +++++++[paragraph] +++++++++[text] name='This test is to check ' +++++++++[static] +++++++++++[text] name='mark tag' +++++++++[text] name='.'
diff --git a/content/test/data/accessibility/html/head-expected-auralinux.txt b/content/test/data/accessibility/html/head-expected-auralinux.txt new file mode 100644 index 0000000..19b9c9f --- /dev/null +++ b/content/test/data/accessibility/html/head-expected-auralinux.txt
@@ -0,0 +1 @@ +[document web]
diff --git a/content/test/data/accessibility/html/header-expected-auralinux.txt b/content/test/data/accessibility/html/header-expected-auralinux.txt new file mode 100644 index 0000000..228a02f --- /dev/null +++ b/content/test/data/accessibility/html/header-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] +++[landmark] xml-roles:banner +++++[text] name='Chromium Browser'
diff --git a/content/test/data/accessibility/html/header-inside-other-section-expected-auralinux.txt b/content/test/data/accessibility/html/header-inside-other-section-expected-auralinux.txt new file mode 100644 index 0000000..77cbdf4 --- /dev/null +++ b/content/test/data/accessibility/html/header-inside-other-section-expected-auralinux.txt
@@ -0,0 +1,13 @@ +[document web] +++[article] xml-roles:article +++++[section] +++++++[paragraph] +++++++++[text] name='Header inside article.' +++[section] xml-roles:region +++++[section] +++++++[paragraph] +++++++++[text] name='Header inside section.' +++[landmark] xml-roles:main +++++[section] +++++++[paragraph] +++++++++[text] name='Header inside main.'
diff --git a/content/test/data/accessibility/html/header-inside-other-section.html b/content/test/data/accessibility/html/header-inside-other-section.html index 9cf97a0..0ef757fc 100644 --- a/content/test/data/accessibility/html/header-inside-other-section.html +++ b/content/test/data/accessibility/html/header-inside-other-section.html
@@ -3,6 +3,7 @@ @MAC-ALLOW:AXRole* @MAC-ALLOW:AXSubrole* @WIN-ALLOW:xml-roles:* +@AURALINUX-ALLOW:xml-roles:* --> <article> <header>
diff --git a/content/test/data/accessibility/html/header.html b/content/test/data/accessibility/html/header.html index bef095c8..6234446 100644 --- a/content/test/data/accessibility/html/header.html +++ b/content/test/data/accessibility/html/header.html
@@ -2,6 +2,7 @@ @MAC-ALLOW:AXRole* @MAC-ALLOW:AXSubrole* @WIN-ALLOW:xml-roles:* +@AURALINUX-ALLOW:xml-roles:* --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/html/heading-expected-auralinux.txt b/content/test/data/accessibility/html/heading-expected-auralinux.txt new file mode 100644 index 0000000..b67d197 --- /dev/null +++ b/content/test/data/accessibility/html/heading-expected-auralinux.txt
@@ -0,0 +1,13 @@ +[document web] +++[heading] name='Heading 1' level:1 xml-roles:heading +++++[text] name='Heading 1' +++[heading] name='Heading 2' level:2 xml-roles:heading +++++[text] name='Heading 2' +++[heading] name='Heading 3' level:3 xml-roles:heading +++++[text] name='Heading 3' +++[heading] name='Heading 4' level:4 xml-roles:heading +++++[text] name='Heading 4' +++[heading] name='Heading 5' level:5 xml-roles:heading +++++[text] name='Heading 5' +++[heading] name='Heading 6' level:6 xml-roles:heading +++++[text] name='Heading 6'
diff --git a/content/test/data/accessibility/html/heading.html b/content/test/data/accessibility/html/heading.html index 51e7ef53..bac08e4 100644 --- a/content/test/data/accessibility/html/heading.html +++ b/content/test/data/accessibility/html/heading.html
@@ -1,6 +1,8 @@ <!-- @WIN-ALLOW:level:* @WIN-ALLOW:xml-roles* +@AURALINUX-ALLOW:level:* +@AURALINUX-ALLOW:xml-roles* --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/html/hr-expected-auralinux.txt b/content/test/data/accessibility/html/hr-expected-auralinux.txt new file mode 100644 index 0000000..91f6f2b1 --- /dev/null +++ b/content/test/data/accessibility/html/hr-expected-auralinux.txt
@@ -0,0 +1,9 @@ +[document web] +++[paragraph] +++++[text] name='Before.' +++[separator] name='Dividing line' horizontal +++[paragraph] +++++[text] name='Middle.' +++[separator] horizontal +++[paragraph] +++++[text] name='After.'
diff --git a/content/test/data/accessibility/html/hr.html b/content/test/data/accessibility/html/hr.html index c804cb71..78c177f 100644 --- a/content/test/data/accessibility/html/hr.html +++ b/content/test/data/accessibility/html/hr.html
@@ -1,6 +1,8 @@ <!-- @MAC-ALLOW:AXRole* @MAC-ALLOW:AXDescription* +@AURALINUX-ALLOW:horizontal +@AURALINUX-ALLOW:vertical --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/html/html-expected-auralinux.txt b/content/test/data/accessibility/html/html-expected-auralinux.txt new file mode 100644 index 0000000..19b9c9f --- /dev/null +++ b/content/test/data/accessibility/html/html-expected-auralinux.txt
@@ -0,0 +1 @@ +[document web]
diff --git a/content/test/data/accessibility/html/i-expected-auralinux.txt b/content/test/data/accessibility/html/i-expected-auralinux.txt new file mode 100644 index 0000000..b65c3435 --- /dev/null +++ b/content/test/data/accessibility/html/i-expected-auralinux.txt
@@ -0,0 +1,5 @@ +[document web] +++[paragraph] +++++[text] name='This is to check ' +++++[text] name='italic property' +++++[text] name=' using i tag.'
diff --git a/content/test/data/accessibility/html/iframe-coordinates-cross-process.html b/content/test/data/accessibility/html/iframe-coordinates-cross-process.html index 2c0cf087..3279f55 100644 --- a/content/test/data/accessibility/html/iframe-coordinates-cross-process.html +++ b/content/test/data/accessibility/html/iframe-coordinates-cross-process.html
@@ -12,6 +12,8 @@ @WIN-ALLOW:size=(150, 50) @WIN-ALLOW:IA2_STATE_EDITABLE +@AURALINUX-ALLOW:location* + @BLINK-ALLOW:location* @BLINK-ALLOW:scrollX=* @BLINK-ALLOW:scrollY=*
diff --git a/content/test/data/accessibility/html/iframe-cross-process-expected-auralinux.txt b/content/test/data/accessibility/html/iframe-cross-process-expected-auralinux.txt new file mode 100644 index 0000000..c9c7795 --- /dev/null +++ b/content/test/data/accessibility/html/iframe-cross-process-expected-auralinux.txt
@@ -0,0 +1,10 @@ +[document web] +++[paragraph] +++++[text] name='Before frame' +++[section] +++++[internal frame] name='Cross-process iframe' +++++++[document web] +++++++++[section] +++++++++++[text] name='Text in iframe' +++[paragraph] +++++[text] name='After frame'
diff --git a/content/test/data/accessibility/html/iframe-expected-auralinux.txt b/content/test/data/accessibility/html/iframe-expected-auralinux.txt new file mode 100644 index 0000000..b2783ab --- /dev/null +++ b/content/test/data/accessibility/html/iframe-expected-auralinux.txt
@@ -0,0 +1,4 @@ +[document web] +++[section] +++++[internal frame] name='Empty iframe' +++++++[document web]
diff --git a/content/test/data/accessibility/html/iframe-presentational-expected-auralinux.txt b/content/test/data/accessibility/html/iframe-presentational-expected-auralinux.txt new file mode 100644 index 0000000..1b326de0 --- /dev/null +++ b/content/test/data/accessibility/html/iframe-presentational-expected-auralinux.txt
@@ -0,0 +1,4 @@ +[document web] +++[section] +++++[internal frame] +++++++[document web]
diff --git a/content/test/data/accessibility/html/img-empty-alt-expected-auralinux.txt b/content/test/data/accessibility/html/img-empty-alt-expected-auralinux.txt new file mode 100644 index 0000000..3fec5e3 --- /dev/null +++ b/content/test/data/accessibility/html/img-empty-alt-expected-auralinux.txt
@@ -0,0 +1,6 @@ +[document web] +++[section] +++++[image] name='' +++++[image] name='' +++++[image] +++++[image] name='full'
diff --git a/content/test/data/accessibility/html/img-expected-auralinux.txt b/content/test/data/accessibility/html/img-expected-auralinux.txt new file mode 100644 index 0000000..24def55 --- /dev/null +++ b/content/test/data/accessibility/html/img-expected-auralinux.txt
@@ -0,0 +1,7 @@ +[document web] +++[section] +++++[image] name='pipe' xml-roles:img +++++[text] name=' ' +++++[image] name='' xml-roles:img +++++[text] name=' ' +++++[image] name=' ' xml-roles:img
diff --git a/content/test/data/accessibility/html/img-link-empty-alt-expected-auralinux.txt b/content/test/data/accessibility/html/img-link-empty-alt-expected-auralinux.txt new file mode 100644 index 0000000..abb430c6 --- /dev/null +++ b/content/test/data/accessibility/html/img-link-empty-alt-expected-auralinux.txt
@@ -0,0 +1,13 @@ +[document web] +++[section] +++++[link] name='unread ' +++++++[text] name='unread ' +++++[link] name='read ' +++++++[image] name='' +++++++[text] name='read ' +++++[link] name='read ' +++++++[image] name='' +++++++[text] name='read ' +++++[link] name='read' +++++++[image] +++++++[text] name='read'
diff --git a/content/test/data/accessibility/html/img.html b/content/test/data/accessibility/html/img.html index 8e7671f..39cea3a 100644 --- a/content/test/data/accessibility/html/img.html +++ b/content/test/data/accessibility/html/img.html
@@ -1,6 +1,7 @@ <!-- @MAC-ALLOW:AXRoleDescription='image' @WIN-ALLOW:xml-roles:* +@AURALINUX-ALLOW:xml-roles:* @ANDROID-ALLOW:has_image --> <html>
diff --git a/content/test/data/accessibility/html/in-page-links-expected-auralinux.txt b/content/test/data/accessibility/html/in-page-links-expected-auralinux.txt new file mode 100644 index 0000000..2ecd2ae --- /dev/null +++ b/content/test/data/accessibility/html/in-page-links-expected-auralinux.txt
@@ -0,0 +1,35 @@ +[document web] +++[link] name='Empty anchor' +++++[text] name='Empty anchor' +++[text] name=' ' +++[link] name='Anchor with content' +++++[text] name='Anchor with content' +++[text] name=' ' +++[link] name='Anchor with ID' +++++[text] name='Anchor with ID' +++[text] name=' ' +++[link] name='Empty span' +++++[text] name='Empty span' +++[text] name=' ' +++[link] name='Span with content' +++++[text] name='Span with content' +++[text] name=' ' +++[link] name='Paragraph with content' +++++[text] name='Paragraph with content' +++[paragraph] +++++[link] +++++[text] name='After empty anchor' +++[paragraph] +++++[link] name='Anchor with content' +++++++[text] name='Anchor with content' +++[paragraph] +++++[link] name='Anchor with ID' +++++++[text] name='Anchor with ID' +++[paragraph] +++++[section] +++++[text] name='After empty span' +++[paragraph] +++++[section] +++++++[text] name='Span with content' +++[paragraph] +++++[text] name='Paragraph with content'
diff --git a/content/test/data/accessibility/html/input-button-expected-auralinux.txt b/content/test/data/accessibility/html/input-button-expected-auralinux.txt new file mode 100644 index 0000000..9d338be1 --- /dev/null +++ b/content/test/data/accessibility/html/input-button-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] +++[section] +++++[push button] name='Button' xml-roles:button
diff --git a/content/test/data/accessibility/html/input-button-in-menu-expected-auralinux.txt b/content/test/data/accessibility/html/input-button-in-menu-expected-auralinux.txt new file mode 100644 index 0000000..a597cac --- /dev/null +++ b/content/test/data/accessibility/html/input-button-in-menu-expected-auralinux.txt
@@ -0,0 +1,5 @@ +[document web] +++[section] +++++[menu item] name='Button in menu element' +++[menu] vertical xml-roles:menu +++++[menu item] name='Button in element with menu role'
diff --git a/content/test/data/accessibility/html/input-button-in-menu.html b/content/test/data/accessibility/html/input-button-in-menu.html index 0b8834b8..4902889 100644 --- a/content/test/data/accessibility/html/input-button-in-menu.html +++ b/content/test/data/accessibility/html/input-button-in-menu.html
@@ -1,6 +1,10 @@ <!-- @WIN-ALLOW:ia2_hypertext=* @WIN-ALLOW:xml-roles:* +@AURALINUX-ALLOW:xml-roles:* +@AURALINUX-ALLOW:horizontal +@AURALINUX-ALLOW:vertical +@AURALINUX-ALLOW:focus --> <html> <body>
diff --git a/content/test/data/accessibility/html/input-button.html b/content/test/data/accessibility/html/input-button.html index 4360fcd..23fd744 100644 --- a/content/test/data/accessibility/html/input-button.html +++ b/content/test/data/accessibility/html/input-button.html
@@ -1,6 +1,7 @@ <!-- @WIN-ALLOW:ia2_hypertext=* @WIN-ALLOW:xml-roles:* +@AURALINUX-ALLOW:xml-roles:* --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/html/input-checkbox-expected-auralinux.txt b/content/test/data/accessibility/html/input-checkbox-expected-auralinux.txt new file mode 100644 index 0000000..aafb5ef --- /dev/null +++ b/content/test/data/accessibility/html/input-checkbox-expected-auralinux.txt
@@ -0,0 +1,7 @@ +[document web] +++[section] +++++[check box] name='Checkbox0' checkable:true +++++[check box] name='Checkbox1' checked checkable:true +++++[check box] name='Checkbox2' checked checkable:true +++++[check box] name='Checkbox3' checked checkable:true xml-roles:checkbox +++++[check box] name='Checkbox4' indeterminate checkable:true
diff --git a/content/test/data/accessibility/html/input-checkbox-in-menu-expected-auralinux.txt b/content/test/data/accessibility/html/input-checkbox-in-menu-expected-auralinux.txt new file mode 100644 index 0000000..79f1eb1 --- /dev/null +++ b/content/test/data/accessibility/html/input-checkbox-in-menu-expected-auralinux.txt
@@ -0,0 +1,7 @@ +[document web] +++[section] +++++[check box] name='Checkbox1' checkable:true +++++[check box] name='Checkbox2' checked checkable:true +++[menu] xml-roles:menu +++++[check box] name='Checkbox3' checked checkable:true +++++[check box] name='Checkbox4' indeterminate checkable:true
diff --git a/content/test/data/accessibility/html/input-checkbox-in-menu.html b/content/test/data/accessibility/html/input-checkbox-in-menu.html index f89cffe..f6649a1 100644 --- a/content/test/data/accessibility/html/input-checkbox-in-menu.html +++ b/content/test/data/accessibility/html/input-checkbox-in-menu.html
@@ -5,6 +5,11 @@ @WIN-ALLOW:IA2_STATE_CHECKABLE* @WIN-ALLOW:MIXED @WIN-ALLOW:xml-roles:* +@AURALINUX-ALLOW:xml-roles:* +@AURALINUX-ALLOW:indeterminate +@AURALINUX-ALLOW:checked +@AURALINUX-DENY:checkable +@AURALINUX-DENY:last-defined --> <html> <body>
diff --git a/content/test/data/accessibility/html/input-checkbox.html b/content/test/data/accessibility/html/input-checkbox.html index e5ccb2e..7a0bc7c 100644 --- a/content/test/data/accessibility/html/input-checkbox.html +++ b/content/test/data/accessibility/html/input-checkbox.html
@@ -5,6 +5,11 @@ @WIN-ALLOW:IA2_STATE_* @WIN-ALLOW:MIXED @WIN-ALLOW:xml-roles:* +@AURALINUX-ALLOW:xml-roles:* +@AURALINUX-ALLOW:indeterminate +@AURALINUX-ALLOW:checked +@AURALINUX-DENY:checkable +@AURALINUX-DENY:last-defined --> <html> <body>
diff --git a/content/test/data/accessibility/html/input-color-expected-auralinux.txt b/content/test/data/accessibility/html/input-color-expected-auralinux.txt new file mode 100644 index 0000000..5678eaf --- /dev/null +++ b/content/test/data/accessibility/html/input-color-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] +++[section] +++++[push button]
diff --git a/content/test/data/accessibility/html/input-date-expected-auralinux.txt b/content/test/data/accessibility/html/input-date-expected-auralinux.txt new file mode 100644 index 0000000..ab9ca6c --- /dev/null +++ b/content/test/data/accessibility/html/input-date-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] +++[section] +++++[dateeditor] name='@NO_CHILDREN_DUMP'
diff --git a/content/test/data/accessibility/html/input-datetime-expected-auralinux.txt b/content/test/data/accessibility/html/input-datetime-expected-auralinux.txt new file mode 100644 index 0000000..05223202 --- /dev/null +++ b/content/test/data/accessibility/html/input-datetime-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] focusable focused +++[section] +++++[entry] editable focusable selectable-text text-input-type:datetime
diff --git a/content/test/data/accessibility/html/input-datetime-local-expected-auralinux.txt b/content/test/data/accessibility/html/input-datetime-local-expected-auralinux.txt new file mode 100644 index 0000000..697e413 --- /dev/null +++ b/content/test/data/accessibility/html/input-datetime-local-expected-auralinux.txt
@@ -0,0 +1,23 @@ +[document web] +++[section] +++++[dateeditor] +++++++[section] +++++++++[section] +++++++++++[spin button] name='Month' +++++++++++++[text] name='mm' +++++++++++[text] name='/' +++++++++++[spin button] name='Day' +++++++++++++[text] name='dd' +++++++++++[text] name='/' +++++++++++[spin button] name='Year' +++++++++++++[text] name='yyyy' +++++++++++[text] name=', ' +++++++++++[spin button] name='Hours' +++++++++++++[text] name='--' +++++++++++[text] name=':' +++++++++++[spin button] name='Minutes' +++++++++++++[text] name='--' +++++++++++[text] name=' ' +++++++++++[spin button] name='AM/PM' +++++++++++++[text] name='--' +++++++[push button] name='Show date picker' haspopup:menu
diff --git a/content/test/data/accessibility/html/input-datetime-local.html b/content/test/data/accessibility/html/input-datetime-local.html index 8bdddda..3e2e4f4 100644 --- a/content/test/data/accessibility/html/input-datetime-local.html +++ b/content/test/data/accessibility/html/input-datetime-local.html
@@ -3,6 +3,8 @@ @WIN-ALLOW:description=* @WIN-ALLOW:haspopup* @WIN-ALLOW:ia2_hypertext=* +@AURALINUX-ALLOW:description=* +@AURALINUX-ALLOW:haspopup* --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/html/input-datetime.html b/content/test/data/accessibility/html/input-datetime.html index 8ba14ff..4556e3a3 100644 --- a/content/test/data/accessibility/html/input-datetime.html +++ b/content/test/data/accessibility/html/input-datetime.html
@@ -1,6 +1,10 @@ <!-- @MAC-ALLOW:AXRole* @WIN-ALLOW:ia2_hypertext=* +@AURALINUX-ALLOW:xml-roles:* +@AURALINUX-ALLOW:text-input-type:* +@AURALINUX-ALLOW:focus* +@AURALINUX-ALLOW:editable --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/html/input-email-expected-auralinux.txt b/content/test/data/accessibility/html/input-email-expected-auralinux.txt new file mode 100644 index 0000000..7c3849cb --- /dev/null +++ b/content/test/data/accessibility/html/input-email-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] focusable focused +++[section] +++++[entry] editable focusable selectable-text text-input-type:email
diff --git a/content/test/data/accessibility/html/input-email.html b/content/test/data/accessibility/html/input-email.html index e091778..8ec892b 100644 --- a/content/test/data/accessibility/html/input-email.html +++ b/content/test/data/accessibility/html/input-email.html
@@ -7,6 +7,10 @@ @WIN-ALLOW:selection_start* @WIN-ALLOW:selection_end* @WIN-ALLOW:text-input-type* +@AURALINUX-ALLOW:xml-roles:* +@AURALINUX-ALLOW:text-input-type:* +@AURALINUX-ALLOW:focus* +@AURALINUX-ALLOW:editable --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/html/input-file-expected-auralinux.txt b/content/test/data/accessibility/html/input-file-expected-auralinux.txt new file mode 100644 index 0000000..3e067c5c --- /dev/null +++ b/content/test/data/accessibility/html/input-file-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] +++[section] +++++[push button] name='Choose File'
diff --git a/content/test/data/accessibility/html/input-hidden-expected-auralinux.txt b/content/test/data/accessibility/html/input-hidden-expected-auralinux.txt new file mode 100644 index 0000000..19b9c9f --- /dev/null +++ b/content/test/data/accessibility/html/input-hidden-expected-auralinux.txt
@@ -0,0 +1 @@ +[document web]
diff --git a/content/test/data/accessibility/html/input-image-button-in-menu-expected-auralinux.txt b/content/test/data/accessibility/html/input-image-button-in-menu-expected-auralinux.txt new file mode 100644 index 0000000..a8c5250 --- /dev/null +++ b/content/test/data/accessibility/html/input-image-button-in-menu-expected-auralinux.txt
@@ -0,0 +1,5 @@ +[document web] +++[section] +++++[push button] name='Bullet' +++[menu] +++++[push button] name='Bullet'
diff --git a/content/test/data/accessibility/html/input-image-expected-auralinux.txt b/content/test/data/accessibility/html/input-image-expected-auralinux.txt new file mode 100644 index 0000000..cadf6d6 --- /dev/null +++ b/content/test/data/accessibility/html/input-image-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] +++[section] +++++[push button] name='Submit' xml-roles:button
diff --git a/content/test/data/accessibility/html/input-image.html b/content/test/data/accessibility/html/input-image.html index 12e7af7..eb09cbc4 100644 --- a/content/test/data/accessibility/html/input-image.html +++ b/content/test/data/accessibility/html/input-image.html
@@ -1,6 +1,7 @@ <!-- @MAC-ALLOW:AXRole* @WIN-ALLOW:xml-roles* +@AURALINUX-ALLOW:xml-roles* --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/html/input-list-expected-auralinux.txt b/content/test/data/accessibility/html/input-list-expected-auralinux.txt new file mode 100644 index 0000000..b326e16 --- /dev/null +++ b/content/test/data/accessibility/html/input-list-expected-auralinux.txt
@@ -0,0 +1,5 @@ +[document web] focusable focused +++[section] +++++[label] +++++++[text] name='Choose a pokemon ' +++++++[combo box] name='Choose a pokemon ' editable focusable selectable-text autocomplete:list haspopup:listbox
diff --git a/content/test/data/accessibility/html/input-list.html b/content/test/data/accessibility/html/input-list.html index c67d33d..b5f8c768 100644 --- a/content/test/data/accessibility/html/input-list.html +++ b/content/test/data/accessibility/html/input-list.html
@@ -1,6 +1,10 @@ <!-- @WIN-ALLOW:autocomplete:* @WIN-ALLOW:haspopup* +@AURALINUX-ALLOW:autocomplete* +@AURALINUX-ALLOW:editable +@AURALINUX-ALLOW:focus* +@AURALINUX-ALLOW:haspopup* @BLINK-ALLOW:editable @BLINK-ALLOW:focusable @BLINK-ALLOW:haspopup*
diff --git a/content/test/data/accessibility/html/input-month-expected-auralinux.txt b/content/test/data/accessibility/html/input-month-expected-auralinux.txt new file mode 100644 index 0000000..1e397ca --- /dev/null +++ b/content/test/data/accessibility/html/input-month-expected-auralinux.txt
@@ -0,0 +1,11 @@ +[document web] +++[section] +++++[dateeditor] +++++++[section] +++++++++[section] +++++++++++[spin button] name='Month' valuetext:0 +++++++++++++[text] name='---------' +++++++++++[text] name=' ' +++++++++++[spin button] name='Year' valuetext:0 +++++++++++++[text] name='----' +++++++[push button] name='Show date picker' haspopup:menu
diff --git a/content/test/data/accessibility/html/input-month.html b/content/test/data/accessibility/html/input-month.html index 9d262bc..66fff2fd 100644 --- a/content/test/data/accessibility/html/input-month.html +++ b/content/test/data/accessibility/html/input-month.html
@@ -7,6 +7,9 @@ @WIN-ALLOW:haspopup* @WIN-ALLOW:ia2_hypertext=* @WIN-ALLOW:value* +@AURALINUX-ALLOW:description* +@AURALINUX-ALLOW:haspopup* +@AURALINUX-ALLOW:value* --> <html> <body>
diff --git a/content/test/data/accessibility/html/input-number-expected-auralinux.txt b/content/test/data/accessibility/html/input-number-expected-auralinux.txt new file mode 100644 index 0000000..8eb0c9a --- /dev/null +++ b/content/test/data/accessibility/html/input-number-expected-auralinux.txt
@@ -0,0 +1,4 @@ +[document web] +++[section] +++++[spin button] selectable-text text-input-type:number valuetext:1 +++++[spin button] selectable-text text-input-type:number valuetext:6
diff --git a/content/test/data/accessibility/html/input-number.html b/content/test/data/accessibility/html/input-number.html index 78e7e8c..ca1dd90 100644 --- a/content/test/data/accessibility/html/input-number.html +++ b/content/test/data/accessibility/html/input-number.html
@@ -11,6 +11,8 @@ @WIN-ALLOW:maximumValue* @WIN-ALLOW:minimumValue* @WIN-ALLOW:valuetext* +@AURALINUX-ALLOW:text-input-type* +@AURALINUX-ALLOW:valuetext* --> <html> <body>
diff --git a/content/test/data/accessibility/html/input-password-expected-auralinux.txt b/content/test/data/accessibility/html/input-password-expected-auralinux.txt new file mode 100644 index 0000000..d482f55d --- /dev/null +++ b/content/test/data/accessibility/html/input-password-expected-auralinux.txt
@@ -0,0 +1,4 @@ +[document web] focusable +++[section] +++++[password text] editable focusable focused selectable-text +
diff --git a/content/test/data/accessibility/html/input-password.html b/content/test/data/accessibility/html/input-password.html index d765b46..73ee1c3 100644 --- a/content/test/data/accessibility/html/input-password.html +++ b/content/test/data/accessibility/html/input-password.html
@@ -10,6 +10,8 @@ @WIN-ALLOW:n_selections* @WIN-ALLOW:selection_start* @WIN-ALLOW:selection_end* +@AURALINUX-ALLOW:focus* +@AURALINUX-ALLOW:editable --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/html/input-radio-expected-auralinux.txt b/content/test/data/accessibility/html/input-radio-expected-auralinux.txt new file mode 100644 index 0000000..8b447953 --- /dev/null +++ b/content/test/data/accessibility/html/input-radio-expected-auralinux.txt
@@ -0,0 +1,13 @@ +[document web] +++[form] +++++[radio button] checkable:true +++++[text] name='Radio1' +++++[text] name='<newline>' +++++[radio button] checkable:true +++++[text] name='Radio2' +++[form] +++++[radio button] name='Radio3' checkable:true +++++[radio button] name='Radio4' checked checkable:true +++[form] +++++[radio button] name='Radio5' checkable:true +++++[radio button] name='Radio6' checked checkable:true
diff --git a/content/test/data/accessibility/html/input-radio-in-menu-expected-auralinux.txt b/content/test/data/accessibility/html/input-radio-in-menu-expected-auralinux.txt new file mode 100644 index 0000000..93ae1dc --- /dev/null +++ b/content/test/data/accessibility/html/input-radio-in-menu-expected-auralinux.txt
@@ -0,0 +1,11 @@ +[document web] +++[section] +++++[radio menu item] checked checkable:true +++++[text] name='Radio0 ' +++++[radio menu item] checkable:true +++++[text] name='Radio1 ' +++++[radio button] name='Radio2' checkable:true xml-roles:radio +++[menu] xml-roles:menu +++++[radio button] name='Radio3' checkable:true xml-roles:radio +++++[radio menu item] checkable:true +++++[radio menu item] checked checkable:true
diff --git a/content/test/data/accessibility/html/input-radio-in-menu.html b/content/test/data/accessibility/html/input-radio-in-menu.html index 3b82375..ef51ca2 100644 --- a/content/test/data/accessibility/html/input-radio-in-menu.html +++ b/content/test/data/accessibility/html/input-radio-in-menu.html
@@ -3,6 +3,11 @@ @WIN-ALLOW:MIXED* @WIN-ALLOW:checkable* @WIN-ALLOW:ia2_hypertext=* +@AURALINUX-ALLOW:xml-roles:* +@AURALINUX-ALLOW:indeterminate +@AURALINUX-ALLOW:checked +@AURALINUX-DENY:checkable +@AURALINUX-DENY:last-defined --> <html> <body>
diff --git a/content/test/data/accessibility/html/input-radio.html b/content/test/data/accessibility/html/input-radio.html index dadba4d8..248ce2e 100644 --- a/content/test/data/accessibility/html/input-radio.html +++ b/content/test/data/accessibility/html/input-radio.html
@@ -6,6 +6,8 @@ @WIN-ALLOW:checkable:* @WIN-ALLOW:ia2_hypertext=* @WIN-ALLOW:IA2_STATE_CHECKABLE* +@AURALINUX-DENY:checkable +@AURALINUX-DENY:last-defined --> <html> <body>
diff --git a/content/test/data/accessibility/html/input-range-expected-auralinux.txt b/content/test/data/accessibility/html/input-range-expected-auralinux.txt new file mode 100644 index 0000000..173a32b --- /dev/null +++ b/content/test/data/accessibility/html/input-range-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] +++[section] +++++[slider] horizontal valuetext:5 xml-roles:slider
diff --git a/content/test/data/accessibility/html/input-range.html b/content/test/data/accessibility/html/input-range.html index 4ac86e07..f976e79 100644 --- a/content/test/data/accessibility/html/input-range.html +++ b/content/test/data/accessibility/html/input-range.html
@@ -11,6 +11,10 @@ @WIN-ALLOW:ia2_hypertext=* @WIN-ALLOW:valuetext* @WIN-ALLOW:xml-roles:* +@AURALINUX-ALLOW:valuetext* +@AURALINUX-ALLOW:xml-roles:* +@AURALINUX-ALLOW:horizontal +@AURALINUX-ALLOW:vertical --> <html> <body>
diff --git a/content/test/data/accessibility/html/input-reset-expected-auralinux.txt b/content/test/data/accessibility/html/input-reset-expected-auralinux.txt new file mode 100644 index 0000000..10272f2c --- /dev/null +++ b/content/test/data/accessibility/html/input-reset-expected-auralinux.txt
@@ -0,0 +1,4 @@ +[document web] focusable focused +++[section] +++++[entry] editable focusable selectable-text +++++[push button] name='Reset' focusable
diff --git a/content/test/data/accessibility/html/input-reset.html b/content/test/data/accessibility/html/input-reset.html index 49771d63..7e61221c 100644 --- a/content/test/data/accessibility/html/input-reset.html +++ b/content/test/data/accessibility/html/input-reset.html
@@ -1,5 +1,7 @@ <!-- @MAC-ALLOW:AXRole* +@AURALINUX-ALLOW:focus* +@AURALINUX-ALLOW:editable --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/html/input-search-expected-auralinux.txt b/content/test/data/accessibility/html/input-search-expected-auralinux.txt new file mode 100644 index 0000000..6ff961eb --- /dev/null +++ b/content/test/data/accessibility/html/input-search-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] focusable focused +++[section] +++++[entry] editable focusable selectable-text text-input-type:search
diff --git a/content/test/data/accessibility/html/input-search.html b/content/test/data/accessibility/html/input-search.html index 8f1cadb9..8e8b20a 100644 --- a/content/test/data/accessibility/html/input-search.html +++ b/content/test/data/accessibility/html/input-search.html
@@ -7,6 +7,9 @@ @WIN-ALLOW:selection_start* @WIN-ALLOW:selection_end* @WIN-ALLOW:textSel* +@AURALINUX-ALLOW:focus* +@AURALINUX-ALLOW:editable +@AURALINUX-ALLOW:text-input-type* --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/html/input-submit-expected-auralinux.txt b/content/test/data/accessibility/html/input-submit-expected-auralinux.txt new file mode 100644 index 0000000..d206ebc --- /dev/null +++ b/content/test/data/accessibility/html/input-submit-expected-auralinux.txt
@@ -0,0 +1,4 @@ +[document web] focusable focused +++[form] +++++[entry] editable focusable selectable-text text-input-type:text +++++[push button] name='Submit' focusable
diff --git a/content/test/data/accessibility/html/input-submit.html b/content/test/data/accessibility/html/input-submit.html index 14be9210..34729f1 100644 --- a/content/test/data/accessibility/html/input-submit.html +++ b/content/test/data/accessibility/html/input-submit.html
@@ -1,5 +1,8 @@ <!-- @MAC-ALLOW:AXRole* +@AURALINUX-ALLOW:focus* +@AURALINUX-ALLOW:editable +@AURALINUX-ALLOW:text-input-type* --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/html/input-suggestions-source-element-expected-auralinux.txt b/content/test/data/accessibility/html/input-suggestions-source-element-expected-auralinux.txt new file mode 100644 index 0000000..498f9a0a --- /dev/null +++ b/content/test/data/accessibility/html/input-suggestions-source-element-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] focusable focused +++[section] +++++[combo box] editable focusable supports-autocompletion selectable-text haspopup:listbox
diff --git a/content/test/data/accessibility/html/input-suggestions-source-element.html b/content/test/data/accessibility/html/input-suggestions-source-element.html index f696935..038e853 100644 --- a/content/test/data/accessibility/html/input-suggestions-source-element.html +++ b/content/test/data/accessibility/html/input-suggestions-source-element.html
@@ -2,6 +2,10 @@ @MAC-ALLOW:AXRole* @MAC-ALLOW:AXHasPopup* @WIN-ALLOW:haspopup* +@AURALINUX-ALLOW:haspopup* +@AURALINUX-ALLOW:supports-autocompletion +@AURALINUX-ALLOW:editable +@AURALINUX-ALLOW:focus* @BLINK-ALLOW:haspopup* --> <!DOCTYPE html>
diff --git a/content/test/data/accessibility/html/input-tel-expected-auralinux.txt b/content/test/data/accessibility/html/input-tel-expected-auralinux.txt new file mode 100644 index 0000000..c488983 --- /dev/null +++ b/content/test/data/accessibility/html/input-tel-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] focusable focused +++[section] +++++[entry] editable focusable selectable-text text-input-type:tel
diff --git a/content/test/data/accessibility/html/input-tel.html b/content/test/data/accessibility/html/input-tel.html index 1129b81..5e13ef03 100644 --- a/content/test/data/accessibility/html/input-tel.html +++ b/content/test/data/accessibility/html/input-tel.html
@@ -6,6 +6,9 @@ @WIN-ALLOW:selection_end* @WIN-ALLOW:text-input-type* @WIN-ALLOW:textSel* +@AURALINUX-ALLOW:text-input-type* +@AURALINUX-ALLOW:editable +@AURALINUX-ALLOW:focus* --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/html/input-text-expected-auralinux.txt b/content/test/data/accessibility/html/input-text-expected-auralinux.txt new file mode 100644 index 0000000..0b64ce28 --- /dev/null +++ b/content/test/data/accessibility/html/input-text-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] focusable +++[section] +++++[entry] name='Name' editable focusable focused single-line selectable-text text-input-type:text
diff --git a/content/test/data/accessibility/html/input-text-name-calc-expected-auralinux.txt b/content/test/data/accessibility/html/input-text-name-calc-expected-auralinux.txt new file mode 100644 index 0000000..ec4da370 --- /dev/null +++ b/content/test/data/accessibility/html/input-text-name-calc-expected-auralinux.txt
@@ -0,0 +1,10 @@ +[document web] +++[entry] name='Title0' explicit-name:true +++[entry] name='Label1' description='Title1' explicit-name:true +++[entry] name='AriaLabel2' description='Title2' explicit-name:true +++[entry] name='LabelledBy3' description='Title3' explicit-name:true +++[entry] name='Placeholder4' explicit-name:true +++[entry] name='ARIA Placeholder4a' explicit-name:true +++[entry] name='Placeholder4b' explicit-name:true +++[entry] name='Placeholder5' description='Title5' explicit-name:true +++[entry] name='LabelledBy6' description='DescribedBy6' explicit-name:true
diff --git a/content/test/data/accessibility/html/input-text-name-calc.html b/content/test/data/accessibility/html/input-text-name-calc.html index 04ca17a..cb62129 100644 --- a/content/test/data/accessibility/html/input-text-name-calc.html +++ b/content/test/data/accessibility/html/input-text-name-calc.html
@@ -1,6 +1,9 @@ <!-- @WIN-ALLOW:description* @WIN-ALLOW:explicit-name* +@AURALINUX-ALLOW:description* +@AURALINUX-ALLOW:explicit-name* +@AURALINUX-DENY:selectable-text --> <html> <body>
diff --git a/content/test/data/accessibility/html/input-text-read-only-expected-auralinux.txt b/content/test/data/accessibility/html/input-text-read-only-expected-auralinux.txt new file mode 100644 index 0000000..0fa1ad2 --- /dev/null +++ b/content/test/data/accessibility/html/input-text-read-only-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] focusable +++[section] +++++[entry] name='Name' focusable focused single-line text-input-type:text
diff --git a/content/test/data/accessibility/html/input-text-read-only.html b/content/test/data/accessibility/html/input-text-read-only.html index 98d35e1..9622a7e 100644 --- a/content/test/data/accessibility/html/input-text-read-only.html +++ b/content/test/data/accessibility/html/input-text-read-only.html
@@ -9,6 +9,12 @@ @WIN-ALLOW:selection_start* @WIN-ALLOW:selection_end* @WIN-ALLOW:text-input-type* +@AURALINUX-ALLOW:text-input-type* +@AURALINUX-ALLOW:*-line +@AURALINUX-ALLOW:editable +@AURALINUX-ALLOW:focus* +@AURALINUX-DENY:read-only +@AURALINUX-DENY:selectable-text --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/html/input-text-value-expected-auralinux.txt b/content/test/data/accessibility/html/input-text-value-expected-auralinux.txt new file mode 100644 index 0000000..3c9a5e55 --- /dev/null +++ b/content/test/data/accessibility/html/input-text-value-expected-auralinux.txt
@@ -0,0 +1,18 @@ +[document web] +++[section] +++++[label] +++++++[text] name='l1' +++++[entry] name='l1' single-line +++++[label] +++++++[text] name='l2' +++++[entry] name='l2' single-line +++++[entry] name='l2' single-line +++++[entry] name='l2' single-line +++++[label] +++++++[text] name='Email' +++++[section] +++++[entry] name='Email' single-line +++++[entry] name='Email' single-line +++++[entry] name='l5' multi-line +++++[entry] name='l6' multi-line +++++[entry] name='Name' description='Description' single-line
diff --git a/content/test/data/accessibility/html/input-text-value.html b/content/test/data/accessibility/html/input-text-value.html index 9db750a..687ace1d 100644 --- a/content/test/data/accessibility/html/input-text-value.html +++ b/content/test/data/accessibility/html/input-text-value.html
@@ -1,9 +1,12 @@ <!-- +@AURALINUX-ALLOW:description* @WIN-ALLOW:description* @WIN-ALLOW:IA2_STATE_MULTI_LINE @BLINK-ALLOW:description* @BLINK-ALLOW:focusable* @BLINK-ALLOW:multiline +@AURALINUX-ALLOW:*-line +@AURALINUX-DENY:selectable-text --> <html> <!-- Width/font adds consistency -->
diff --git a/content/test/data/accessibility/html/input-text-with-selection-expected-auralinux.txt b/content/test/data/accessibility/html/input-text-with-selection-expected-auralinux.txt new file mode 100644 index 0000000..a09dae2 --- /dev/null +++ b/content/test/data/accessibility/html/input-text-with-selection-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] focusable +++[section] +++++[entry] editable focusable focused single-line selectable-text text-input-type:text
diff --git a/content/test/data/accessibility/html/input-text-with-selection.html b/content/test/data/accessibility/html/input-text-with-selection.html index 60bcfb66..5ad4be4c 100644 --- a/content/test/data/accessibility/html/input-text-with-selection.html +++ b/content/test/data/accessibility/html/input-text-with-selection.html
@@ -8,6 +8,10 @@ @WIN-ALLOW:selection_start* @WIN-ALLOW:selection_end* @WIN-ALLOW:text-input-type* +@AURALINUX-ALLOW:text-input-type* +@AURALINUX-ALLOW:*-line +@AURALINUX-ALLOW:editable +@AURALINUX-ALLOW:focus* @BLINK-ALLOW:textSel* --> <!DOCTYPE html>
diff --git a/content/test/data/accessibility/html/input-text.html b/content/test/data/accessibility/html/input-text.html index 8c01462..eda91b0 100644 --- a/content/test/data/accessibility/html/input-text.html +++ b/content/test/data/accessibility/html/input-text.html
@@ -12,6 +12,10 @@ @WIN-ALLOW:selection_start* @WIN-ALLOW:selection_end* @WIN-ALLOW:text-input-type* +@AURALINUX-ALLOW:text-input-type* +@AURALINUX-ALLOW:editable +@AURALINUX-ALLOW:focus* +@AURALINUX-ALLOW:*-line --> <html> <body>
diff --git a/content/test/data/accessibility/html/input-time-expected-auralinux.txt b/content/test/data/accessibility/html/input-time-expected-auralinux.txt new file mode 100644 index 0000000..5d169fbe --- /dev/null +++ b/content/test/data/accessibility/html/input-time-expected-auralinux.txt
@@ -0,0 +1,13 @@ +[document web] +++[section] +++++[dateeditor] +++++++[section] +++++++++[section] +++++++++++[spin button] name='Hours' xml-roles:spinbutton +++++++++++++[text] name='12' +++++++++++[text] name=':' +++++++++++[spin button] name='Minutes' xml-roles:spinbutton +++++++++++++[text] name='00' +++++++++++[text] name=' ' +++++++++++[spin button] name='AM/PM' xml-roles:spinbutton +++++++++++++[text] name='AM'
diff --git a/content/test/data/accessibility/html/input-time.html b/content/test/data/accessibility/html/input-time.html index af75a6b8..b31c121a 100644 --- a/content/test/data/accessibility/html/input-time.html +++ b/content/test/data/accessibility/html/input-time.html
@@ -3,6 +3,8 @@ @WIN-ALLOW:ia2_hypertext=* @WIN-ALLOW:xml-roles* @WIN-ALLOW:description* +@AURALINUX-ALLOW:xml-roles* +@AURALINUX-ALLOW:description* --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/html/input-types-expected-auralinux.txt b/content/test/data/accessibility/html/input-types-expected-auralinux.txt new file mode 100644 index 0000000..d67ced67 --- /dev/null +++ b/content/test/data/accessibility/html/input-types-expected-auralinux.txt
@@ -0,0 +1,49 @@ +[document web] +++[section] +++++[label] +++++++[text] name='Default: ' +++++++[entry] name='Default: ' selectable-text +++++[label] +++++++[text] name='Button: ' +++++++[push button] name='Button: ' +++++[check box] name='Checkbox: ' checkable:true +++++[label] +++++++[text] name='Color: ' +++++++[push button] name='Color: ' +++++[label] +++++++[text] name='Email: ' +++++++[entry] name='Email: ' selectable-text text-input-type:email +++++[label] +++++++[text] name='File: ' +++++++[push button] name='File: ' +++++[label] +++++++[text] name='Image: ' +++++++[push button] name='Image: ' +++++[label] +++++++[text] name='Number: ' +++++++[spin button] name='Number: ' selectable-text text-input-type:number +++++[label] +++++++[text] name='Password: ' +++++++[password text] name='Password: ' selectable-text text-input-type:password +++++[radio button] name='Radio: ' checkable:true +++++[label] +++++++[text] name='Range: ' +++++++[slider] name='Range: ' horizontal +++++[label] +++++++[text] name='Reset: ' +++++++[push button] name='Reset: ' +++++[label] +++++++[text] name='Search: ' +++++++[entry] name='Search: ' selectable-text text-input-type:search +++++[label] +++++++[text] name='Submit: ' +++++++[push button] name='Submit: ' +++++[label] +++++++[text] name='Tel: ' +++++++[entry] name='Tel: ' selectable-text text-input-type:tel +++++[label] +++++++[text] name='Text: ' +++++++[entry] name='Text: ' selectable-text text-input-type:text +++++[label] +++++++[text] name='Url: ' +++++++[entry] name='Url: ' selectable-text text-input-type:url
diff --git a/content/test/data/accessibility/html/input-types.html b/content/test/data/accessibility/html/input-types.html index 22821bb4..78e1a5ef 100644 --- a/content/test/data/accessibility/html/input-types.html +++ b/content/test/data/accessibility/html/input-types.html
@@ -1,5 +1,8 @@ <!-- @WIN-ALLOW:text-input-type* +@AURALINUX-ALLOW:text-input-type* +@AURALINUX-DENY:checkable +@AURALINUX-DENY:last-defined --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/html/input-url-expected-auralinux.txt b/content/test/data/accessibility/html/input-url-expected-auralinux.txt new file mode 100644 index 0000000..04cd01b --- /dev/null +++ b/content/test/data/accessibility/html/input-url-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] focusable focused +++[section] +++++[entry] editable focusable selectable-text text-input-type:url
diff --git a/content/test/data/accessibility/html/input-url.html b/content/test/data/accessibility/html/input-url.html index e8d6b59..fe496c5 100644 --- a/content/test/data/accessibility/html/input-url.html +++ b/content/test/data/accessibility/html/input-url.html
@@ -6,6 +6,9 @@ @WIN-ALLOW:selection_start* @WIN-ALLOW:selection_end* @WIN-ALLOW:text-input-type* +@AURALINUX-ALLOW:text-input-type:* +@AURALINUX-ALLOW:focus* +@AURALINUX-ALLOW:editable @BLINK-ALLOW:textSel* --> <!DOCTYPE html>
diff --git a/content/test/data/accessibility/html/input-week-expected-auralinux.txt b/content/test/data/accessibility/html/input-week-expected-auralinux.txt new file mode 100644 index 0000000..eb44d4f --- /dev/null +++ b/content/test/data/accessibility/html/input-week-expected-auralinux.txt
@@ -0,0 +1,12 @@ +[document web] +++[section] +++++[dateeditor] +++++++[section] +++++++++[section] +++++++++++[text] name='Week ' +++++++++++[spin button] name='Week' +++++++++++++[text] name='--' +++++++++++[text] name=', ' +++++++++++[spin button] name='Year' +++++++++++++[text] name='----' +++++++[push button] name='Show date picker' haspopup:menu
diff --git a/content/test/data/accessibility/html/input-week.html b/content/test/data/accessibility/html/input-week.html index 75c3a1c2..ba7e5e2 100644 --- a/content/test/data/accessibility/html/input-week.html +++ b/content/test/data/accessibility/html/input-week.html
@@ -4,6 +4,8 @@ @WIN-ALLOW:ia2_hypertext=* @WIN-ALLOW:description* @WIN-ALLOW:haspopup* +@AURALINUX-ALLOW:description* +@AURALINUX-ALLOW:haspopup* --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/html/ins-expected-auralinux.txt b/content/test/data/accessibility/html/ins-expected-auralinux.txt new file mode 100644 index 0000000..51661fa --- /dev/null +++ b/content/test/data/accessibility/html/ins-expected-auralinux.txt
@@ -0,0 +1,9 @@ +[document web] +++[paragraph] +++++[text] name='My favorite browser is ' +++++[section] +++++++[text] name='ABC' +++++[text] name=' ' +++++[section] +++++++[text] name='Chrome' +++++[text] name='!'
diff --git a/content/test/data/accessibility/html/label-expected-auralinux.txt b/content/test/data/accessibility/html/label-expected-auralinux.txt new file mode 100644 index 0000000..ea3c90b --- /dev/null +++ b/content/test/data/accessibility/html/label-expected-auralinux.txt
@@ -0,0 +1,4 @@ +[document web] +++[section] +++++[label] +++++++[text] name='Label'
diff --git a/content/test/data/accessibility/html/landmark-expected-auralinux.txt b/content/test/data/accessibility/html/landmark-expected-auralinux.txt new file mode 100644 index 0000000..185c954c --- /dev/null +++ b/content/test/data/accessibility/html/landmark-expected-auralinux.txt
@@ -0,0 +1,149 @@ +[document web] +++[landmark] xml-roles:banner +++++[text] name='This is a header element.' +++[landmark] xml-roles:complementary +++++[text] name='This is an aside element.' +++[landmark] +++++[text] name='This is an address element.' +++[footer] xml-roles:contentinfo +++++[text] name='This is a footer element.' +++[form] +++++[text] name='This is a form element.' +++[landmark] xml-roles:main +++++[text] name='This is a main element.' +++[landmark] xml-roles:navigation +++++[text] name='This is a nav element.' +++[embedded component] xml-roles:application +++++[text] name='This is an ARIA application landmark.' +++[landmark] xml-roles:banner +++++[text] name='This is an ARIA banner landmark.' +++[landmark] xml-roles:complementary +++++[text] name='This is an ARIA complementary landmark.' +++[landmark] xml-roles:contentinfo +++++[text] name='This is an ARIA contentinfo landmark.' +++[form] xml-roles:form +++++[text] name='This is an ARIA form landmark.' +++[landmark] xml-roles:main +++++[text] name='This is an ARIA main landmark.' +++[landmark] xml-roles:navigation +++++[text] name='This is an ARIA navigation landmark.' +++[landmark] xml-roles:search +++++[text] name='This is an ARIA search landmark.' +++[article] xml-roles:article +++++[section] +++++++[text] name='This should NOT banner role.' +++[landmark] xml-roles:complementary +++++[section] +++++++[text] name='This should NOT have banner role.' +++[landmark] xml-roles:navigation +++++[section] +++++++[text] name='This should NOT have banner role.' +++[section] xml-roles:region +++++[section] +++++++[text] name='This should NOT have banner role.' +++[block quote] +++++[section] +++++++[text] name='This should NOT have banner role.' +++[panel] +++++[toggle button] name='Details' +++++++[text] name='Details' +++[panel] +++++[section] +++++++[text] name='This should NOT have banner role.' +++[panel] xml-roles:figure +++++[section] +++++++[text] name='This should NOT have banner role.' +++[panel] xml-roles:group +++++[section] +++++++[text] name='This should NOT have banner role.' +++[landmark] xml-roles:main +++++[section] +++++++[text] name='This should NOT have banner role.' +++[article] xml-roles:article +++++[section] +++++++[text] name='This should NOT banner role.' +++[landmark] xml-roles:complementary +++++[section] +++++++[text] name='This should NOT have banner role.' +++[landmark] xml-roles:navigation +++++[section] +++++++[text] name='This should NOT have banner role.' +++[section] xml-roles:region +++++[section] +++++++[text] name='This should NOT have banner role.' +++[block quote] +++++[section] +++++++[text] name='This should NOT have banner role.' +++[panel] +++++[toggle button] name='Details' +++++++[text] name='Details' +++[panel] +++++[section] +++++++[text] name='This should NOT have banner role.' +++[panel] xml-roles:figure +++++[section] +++++++[text] name='This should NOT have banner role.' +++[section] +++++[text] name='This should NOT have banner role.' +++[landmark] xml-roles:main +++++[section] +++++++[text] name='This should NOT have banner role.' +++[article] xml-roles:article +++++[section] +++++++[text] name='This should NOT footer role.' +++[landmark] xml-roles:complementary +++++[section] +++++++[text] name='This should NOT have footer role.' +++[landmark] xml-roles:navigation +++++[section] +++++++[text] name='This should NOT have footer role.' +++[section] xml-roles:region +++++[section] +++++++[text] name='This should NOT have footer role.' +++[block quote] +++++[section] +++++++[text] name='This should NOT have footer role.' +++[panel] +++++[toggle button] name='Details' +++++++[text] name='Details' +++[panel] +++++[section] +++++++[text] name='This should NOT have footer role.' +++[panel] xml-roles:figure +++++[section] +++++++[text] name='This should NOT have footer role.' +++[section] +++++[text] name='This should NOT have footer role.' +++[landmark] xml-roles:main +++++[section] +++++++[text] name='This should NOT have footer role.' +++[article] xml-roles:article +++++[section] +++++++[text] name='This should NOT footer role.' +++[landmark] xml-roles:complementary +++++[section] +++++++[text] name='This should NOT have footer role.' +++[landmark] xml-roles:navigation +++++[section] +++++++[text] name='This should NOT have footer role.' +++[section] xml-roles:region +++++[section] +++++++[text] name='This should NOT have footer role.' +++[block quote] +++++[section] +++++++[text] name='This should NOT have footer role.' +++[panel] +++++[toggle button] name='Details' +++++++[text] name='Details' +++[panel] +++++[section] +++++++[text] name='This should NOT have footer role.' +++[panel] xml-roles:figure +++++[section] +++++++[text] name='This should NOT have footer role.' +++[panel] xml-roles:group +++++[section] +++++++[text] name='This should NOT have footer role.' +++[landmark] xml-roles:main +++++[section] +++++++[text] name='This should NOT have footer role.'
diff --git a/content/test/data/accessibility/html/landmark.html b/content/test/data/accessibility/html/landmark.html index 2d26215..3218097 100644 --- a/content/test/data/accessibility/html/landmark.html +++ b/content/test/data/accessibility/html/landmark.html
@@ -2,6 +2,7 @@ @MAC-ALLOW:AXRole* @MAC-ALLOW:AXSubrole=* @WIN-ALLOW:xml-roles:* +@AURALINUX-ALLOW:xml-roles:* --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/html/legend-expected-auralinux.txt b/content/test/data/accessibility/html/legend-expected-auralinux.txt new file mode 100644 index 0000000..2368ebf --- /dev/null +++ b/content/test/data/accessibility/html/legend-expected-auralinux.txt
@@ -0,0 +1,9 @@ +[document web] focusable focused +++[form] +++++[panel] name='Browser Engines:' +++++++[label] +++++++++[text] name='Browser Engines:' +++++++[text] name='Browser: ' +++++++[entry] editable focusable single-line selectable-text +++++++[text] name=' Rendering Engine: ' +++++++[entry] editable focusable single-line selectable-text
diff --git a/content/test/data/accessibility/html/legend.html b/content/test/data/accessibility/html/legend.html index b08b24a..96c06a2 100644 --- a/content/test/data/accessibility/html/legend.html +++ b/content/test/data/accessibility/html/legend.html
@@ -1,5 +1,8 @@ <!-- @MAC-ALLOW:AXTitleUIElement* +@AURALINUX-ALLOW:*-line +@AURALINUX-ALLOW:editable +@AURALINUX-ALLOW:focus* --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/html/li-expected-auralinux.txt b/content/test/data/accessibility/html/li-expected-auralinux.txt new file mode 100644 index 0000000..ef3966a7 --- /dev/null +++ b/content/test/data/accessibility/html/li-expected-auralinux.txt
@@ -0,0 +1,11 @@ +[document web] +++[list] display:block +++++[list item] display:list-item posinset:1 setsize:3 +++++++[static] name='• ' +++++++[text] name='Item 1' display:list-item +++++[list item] display:list-item posinset:2 setsize:3 +++++++[static] name='• ' +++++++[text] name='Item 2' display:list-item +++++[list item] display:list-item posinset:3 setsize:3 +++++++[static] name='• ' +++++++[text] name='Item 3' display:list-item
diff --git a/content/test/data/accessibility/html/li.html b/content/test/data/accessibility/html/li.html index 93ea363..328a73f 100644 --- a/content/test/data/accessibility/html/li.html +++ b/content/test/data/accessibility/html/li.html
@@ -1,6 +1,9 @@ <!-- @MAC-ALLOW:AXSubrole* @WIN-ALLOW:display* +@AURALINUX-ALLOW:display* +@AURALINUX-ALLOW:posinset* +@AURALINUX-ALLOW:setsize* @BLINK-ALLOW:display* @BLINK-ALLOW:setSize* @BLINK-ALLOW:posInSet*
diff --git a/content/test/data/accessibility/html/link-expected-auralinux.txt b/content/test/data/accessibility/html/link-expected-auralinux.txt new file mode 100644 index 0000000..19b9c9f --- /dev/null +++ b/content/test/data/accessibility/html/link-expected-auralinux.txt
@@ -0,0 +1 @@ +[document web]
diff --git a/content/test/data/accessibility/html/link-inside-heading-expected-auralinux.txt b/content/test/data/accessibility/html/link-inside-heading-expected-auralinux.txt new file mode 100644 index 0000000..981ca104 --- /dev/null +++ b/content/test/data/accessibility/html/link-inside-heading-expected-auralinux.txt
@@ -0,0 +1,4 @@ +[document web] +++[heading] name='Link In Heading' +++++[link] name='Link In Heading' +++++++[text] name='Link In Heading'
diff --git a/content/test/data/accessibility/html/list-expected-auralinux.txt b/content/test/data/accessibility/html/list-expected-auralinux.txt new file mode 100644 index 0000000..5979c752 --- /dev/null +++ b/content/test/data/accessibility/html/list-expected-auralinux.txt
@@ -0,0 +1,20 @@ +[document web] +++[list] +++++[list item] +++++++[static] name='• ' +++++++[text] name='tic' +++++[list item] +++++++[static] name='• ' +++++++[text] name='tac' +++++[list item] +++++++[static] name='• ' +++++++[text] name='toe' +++[list] +++++[list item] +++++++[text] name='tic' +++++[text] name=' ' +++++[list item] +++++++[text] name='tac' +++++[text] name=' ' +++++[list item] +++++++[text] name='toe'
diff --git a/content/test/data/accessibility/html/list-markers-expected-auralinux.txt b/content/test/data/accessibility/html/list-markers-expected-auralinux.txt new file mode 100644 index 0000000..189d8a4 --- /dev/null +++ b/content/test/data/accessibility/html/list-markers-expected-auralinux.txt
@@ -0,0 +1,17 @@ +[document web] +++[list] +++++[list item] +++++++[static] name='• ' +++++++[text] name='First item properly groups itself despite ' +++++++[text] name='bolded' +++++++[text] name=' text.' +++++[list item] +++++++[static] name='• ' +++++++[text] name='This should also be ' +++++++[text] name='seen' +++++++[text] name=' as a group.' +++++[list item] +++++++[static] name='• ' +++++++[text] name='Some ' +++++++[text] name='more' +++++++[text] name=' text.'
diff --git a/content/test/data/accessibility/html/main-expected-auralinux.txt b/content/test/data/accessibility/html/main-expected-auralinux.txt new file mode 100644 index 0000000..385eb48 --- /dev/null +++ b/content/test/data/accessibility/html/main-expected-auralinux.txt
@@ -0,0 +1,5 @@ +[document web] +++[landmark] xml-roles:main +++++[text] name='This is main element.' +++[landmark] xml-roles:main +++++[text] name='This is an ARIA role main.'
diff --git a/content/test/data/accessibility/html/main.html b/content/test/data/accessibility/html/main.html index 1bb6060..d421ca1b 100644 --- a/content/test/data/accessibility/html/main.html +++ b/content/test/data/accessibility/html/main.html
@@ -2,6 +2,7 @@ @MAC-ALLOW:AXRole* @MAC-ALLOW:AXSubrole=* @WIN-ALLOW:xml-roles:* +@AURALINUX-ALLOW:xml-roles:* --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/html/mark-expected-auralinux.txt b/content/test/data/accessibility/html/mark-expected-auralinux.txt new file mode 100644 index 0000000..6a5eeb9d --- /dev/null +++ b/content/test/data/accessibility/html/mark-expected-auralinux.txt
@@ -0,0 +1,6 @@ +[document web] +++[paragraph] +++++[text] name='This test is to check ' +++++[static] +++++++[text] name='mark tag' +++++[text] name='.'
diff --git a/content/test/data/accessibility/html/math-expected-auralinux.txt b/content/test/data/accessibility/html/math-expected-auralinux.txt new file mode 100644 index 0000000..e9f3a6d --- /dev/null +++ b/content/test/data/accessibility/html/math-expected-auralinux.txt
@@ -0,0 +1,10 @@ +[document web] +++[section] +++++[math] +++++++[text] name='a' +++++++[text] name='2' +++++++[text] name=' ' +++++++[text] name='+' +++++++[text] name=' ' +++++++[text] name='b' +++++++[text] name='2'
diff --git a/content/test/data/accessibility/html/meter-expected-auralinux.txt b/content/test/data/accessibility/html/meter-expected-auralinux.txt new file mode 100644 index 0000000..808dec7 --- /dev/null +++ b/content/test/data/accessibility/html/meter-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] +++[section] +++++[level bar]
diff --git a/content/test/data/accessibility/html/modal-dialog-closed-expected-auralinux.txt b/content/test/data/accessibility/html/modal-dialog-closed-expected-auralinux.txt new file mode 100644 index 0000000..8b14944 --- /dev/null +++ b/content/test/data/accessibility/html/modal-dialog-closed-expected-auralinux.txt
@@ -0,0 +1,7 @@ +[document web] +++[text] name='Test that elements respawn in the accessibility tree after a modal dialog closes.' +++[section] +++++[combo box] expandable haspopup:menu +++++++[menu] +++++++++[menu item] name='This should be in the tree.' selectable selected +++[push button]
diff --git a/content/test/data/accessibility/html/modal-dialog-closed.html b/content/test/data/accessibility/html/modal-dialog-closed.html index a870db86..04953d7 100644 --- a/content/test/data/accessibility/html/modal-dialog-closed.html +++ b/content/test/data/accessibility/html/modal-dialog-closed.html
@@ -1,6 +1,9 @@ <!-- @MAC-ALLOW:AXSubrole=* @WIN-ALLOW:haspopup* +@AURALINUX-ALLOW:haspopup* +@AURALINUX-ALLOW:expand* +@AURALINUX-ALLOW:select* @BLINK-ALLOW:haspopup* --> <html>
diff --git a/content/test/data/accessibility/html/modal-dialog-opened-expected-auralinux.txt b/content/test/data/accessibility/html/modal-dialog-opened-expected-auralinux.txt new file mode 100644 index 0000000..6a184f3 --- /dev/null +++ b/content/test/data/accessibility/html/modal-dialog-opened-expected-auralinux.txt
@@ -0,0 +1,6 @@ +[document web] +++[section] +++[dialog] modal +++++[text] name='The dialog subtree should be the only text content in the accessibility tree. ' +++++[link] name='Link inside the dialog.' +++++++[text] name='Link inside the dialog.'
diff --git a/content/test/data/accessibility/html/modal-dialog-opened.html b/content/test/data/accessibility/html/modal-dialog-opened.html index 47da0581..92741e4 100644 --- a/content/test/data/accessibility/html/modal-dialog-opened.html +++ b/content/test/data/accessibility/html/modal-dialog-opened.html
@@ -1,5 +1,6 @@ <!-- @MAC-ALLOW:AXSubrole=* +@AURALINUX-ALLOW:modal --> <html> <body>
diff --git a/content/test/data/accessibility/html/modal-dialog-stack-expected-auralinux.txt b/content/test/data/accessibility/html/modal-dialog-stack-expected-auralinux.txt new file mode 100644 index 0000000..7a0a189 --- /dev/null +++ b/content/test/data/accessibility/html/modal-dialog-stack-expected-auralinux.txt
@@ -0,0 +1,5 @@ +[document web] +++[section] +++[dialog] modal +++++[text] name='This is the now active dialog. Of course it should be in the tree. ' +++++[push button] name='This is in the active dialog and should be in the tree.'
diff --git a/content/test/data/accessibility/html/modal-dialog-stack.html b/content/test/data/accessibility/html/modal-dialog-stack.html index 5e15665e..0f35db3 100644 --- a/content/test/data/accessibility/html/modal-dialog-stack.html +++ b/content/test/data/accessibility/html/modal-dialog-stack.html
@@ -1,5 +1,6 @@ <!-- @MAC-ALLOW:AXSubrole=* +@AURALINUX-ALLOW:modal --> <html> <body>
diff --git a/content/test/data/accessibility/html/navigation-expected-auralinux.txt b/content/test/data/accessibility/html/navigation-expected-auralinux.txt new file mode 100644 index 0000000..2e306a7a --- /dev/null +++ b/content/test/data/accessibility/html/navigation-expected-auralinux.txt
@@ -0,0 +1,4 @@ +[document web] +++[landmark] xml-roles:navigation +++++[link] name='Don't click on me' +++++++[text] name='Don't click on me'
diff --git a/content/test/data/accessibility/html/navigation.html b/content/test/data/accessibility/html/navigation.html index 5c6ffb32..f71df39 100644 --- a/content/test/data/accessibility/html/navigation.html +++ b/content/test/data/accessibility/html/navigation.html
@@ -2,6 +2,7 @@ @MAC-ALLOW:AXRole* @MAC-ALLOW:AXSubrole=* @WIN-ALLOW:xml-roles* +@AURALINUX-ALLOW:xml-roles* --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/html/noscript-expected-auralinux.txt b/content/test/data/accessibility/html/noscript-expected-auralinux.txt new file mode 100644 index 0000000..19b9c9f --- /dev/null +++ b/content/test/data/accessibility/html/noscript-expected-auralinux.txt
@@ -0,0 +1 @@ +[document web]
diff --git a/content/test/data/accessibility/html/object-expected-auralinux.txt b/content/test/data/accessibility/html/object-expected-auralinux.txt new file mode 100644 index 0000000..1b84d9f1 --- /dev/null +++ b/content/test/data/accessibility/html/object-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] +++[section] +++++[embedded component]
diff --git a/content/test/data/accessibility/html/ol-expected-auralinux.txt b/content/test/data/accessibility/html/ol-expected-auralinux.txt new file mode 100644 index 0000000..7ba3e99f --- /dev/null +++ b/content/test/data/accessibility/html/ol-expected-auralinux.txt
@@ -0,0 +1,21 @@ +[document web] +++[list] +++++[list item] +++++++[static] name='1. ' +++++++[text] name='Chrome' +++++[list item] +++++++[static] name='2. ' +++++++[text] name='Safari' +++++[list item] +++++++[static] name='3. ' +++++++[text] name='IE' +++[list] +++++[list item] +++++++[static] name='10. ' +++++++[text] name='Android' +++++[list item] +++++++[static] name='11. ' +++++++[text] name='Mac' +++++[list item] +++++++[static] name='12. ' +++++++[text] name='Windows'
diff --git a/content/test/data/accessibility/html/optgroup-expected-auralinux.txt b/content/test/data/accessibility/html/optgroup-expected-auralinux.txt new file mode 100644 index 0000000..aecbdeed --- /dev/null +++ b/content/test/data/accessibility/html/optgroup-expected-auralinux.txt
@@ -0,0 +1,15 @@ +[document web] enabled +++[section] enabled +++++[list box] enabled +++++++[panel] name='Enabled' enabled xml-roles:group +++++++++[text] name='Enabled' enabled +++++++[list item] name='One' enabled posinset:1 setsize:4 +++++++[list item] name='Two' enabled posinset:2 setsize:4 +++++++[list item] name='Three' enabled posinset:3 setsize:4 +++++++[list item] name='Four' enabled posinset:4 setsize:4 +++++++[panel] name='Disabled' enabled xml-roles:group +++++++++[text] name='Disabled' enabled +++++++[list item] name='One' posinset:1 setsize:4 +++++++[list item] name='Two' posinset:2 setsize:4 +++++++[list item] name='Three' posinset:3 setsize:4 +++++++[list item] name='Four' posinset:4 setsize:4
diff --git a/content/test/data/accessibility/html/optgroup.html b/content/test/data/accessibility/html/optgroup.html index 4623396..1600fbc 100644 --- a/content/test/data/accessibility/html/optgroup.html +++ b/content/test/data/accessibility/html/optgroup.html
@@ -5,6 +5,10 @@ @WIN-ALLOW:SELECTABLE @BLINK-ALLOW:setSize* @BLINK-ALLOW:posInSet* +@AURALINUX-ALLOW:xml-roles* +@AURALINUX-ALLOW:posinset* +@AURALINUX-ALLOW:setsize* +@AURALINUX-ALLOW:enabled --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/html/p-expected-auralinux.txt b/content/test/data/accessibility/html/p-expected-auralinux.txt index 86b022b..718bc482 100644 --- a/content/test/data/accessibility/html/p-expected-auralinux.txt +++ b/content/test/data/accessibility/html/p-expected-auralinux.txt
@@ -1,6 +1,5 @@ -[document web] enabled focusable focused sensitive showing visible<newline> -++[text] name='Before' enabled sensitive showing visible<newline> -++[paragraph] enabled sensitive showing visible<newline> -++++[text] name='Paragraph' enabled sensitive showing visible<newline> -++[text] name='After' enabled sensitive showing visible<newline> - +[document web] +++[text] name='Before' +++[paragraph] +++++[text] name='Paragraph' +++[text] name='After'
diff --git a/content/test/data/accessibility/html/param-expected-auralinux.txt b/content/test/data/accessibility/html/param-expected-auralinux.txt new file mode 100644 index 0000000..1b84d9f1 --- /dev/null +++ b/content/test/data/accessibility/html/param-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] +++[section] +++++[embedded component]
diff --git a/content/test/data/accessibility/html/pre-expected-auralinux.txt b/content/test/data/accessibility/html/pre-expected-auralinux.txt new file mode 100644 index 0000000..098f82cb --- /dev/null +++ b/content/test/data/accessibility/html/pre-expected-auralinux.txt
@@ -0,0 +1,9 @@ +[document web] +++[section] +++++[text] name='This test is to check pre<newline>formatting.' +++[section] +++++[text] name='This test is to check pre<newline>formatting' +++[section] +++++[text] name='This test is to check pre<newline>formatting.' +++[section] +++++[text] name='This test is to check pre formatting.'
diff --git a/content/test/data/accessibility/html/progress-expected-auralinux.txt b/content/test/data/accessibility/html/progress-expected-auralinux.txt new file mode 100644 index 0000000..6ed6be0 --- /dev/null +++ b/content/test/data/accessibility/html/progress-expected-auralinux.txt
@@ -0,0 +1,4 @@ +[document web] +++[section] +++++[progress bar] valuetext:22 +++++[progress bar]
diff --git a/content/test/data/accessibility/html/progress.html b/content/test/data/accessibility/html/progress.html index 6bf6cdc1..13df22b4 100644 --- a/content/test/data/accessibility/html/progress.html +++ b/content/test/data/accessibility/html/progress.html
@@ -4,6 +4,7 @@ @WIN-ALLOW:currentValue=* @WIN-ALLOW:minimumValue=* @WIN-ALLOW:maximumValue=* +@AURALINUX-ALLOW:valuetext* --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/html/q-expected-auralinux.txt b/content/test/data/accessibility/html/q-expected-auralinux.txt new file mode 100644 index 0000000..7100a91 --- /dev/null +++ b/content/test/data/accessibility/html/q-expected-auralinux.txt
@@ -0,0 +1,7 @@ +[document web] +++[paragraph] +++++[text] name='This is ' +++++[text] name='"' +++++[text] name='Chromium Blink' +++++[text] name='"' +++++[text] name=' based browser.'
diff --git a/content/test/data/accessibility/html/ruby-expected-auralinux.txt b/content/test/data/accessibility/html/ruby-expected-auralinux.txt new file mode 100644 index 0000000..5c8f462 --- /dev/null +++ b/content/test/data/accessibility/html/ruby-expected-auralinux.txt
@@ -0,0 +1,6 @@ +[document web] +++[section] +++++[static] +++++++[panel] +++++++++[text] name='ruby text' +++++++[text] name='ruby base'
diff --git a/content/test/data/accessibility/html/s-expected-auralinux.txt b/content/test/data/accessibility/html/s-expected-auralinux.txt new file mode 100644 index 0000000..39d97b1 --- /dev/null +++ b/content/test/data/accessibility/html/s-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] +++[section] +++++[text] name='My car is blue.'
diff --git a/content/test/data/accessibility/html/samp-expected-auralinux.txt b/content/test/data/accessibility/html/samp-expected-auralinux.txt new file mode 100644 index 0000000..b2de3eff --- /dev/null +++ b/content/test/data/accessibility/html/samp-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] +++[section] +++++[text] name='Sample output from a computer program'
diff --git a/content/test/data/accessibility/html/script-expected-auralinux.txt b/content/test/data/accessibility/html/script-expected-auralinux.txt new file mode 100644 index 0000000..cbc7ff7c --- /dev/null +++ b/content/test/data/accessibility/html/script-expected-auralinux.txt
@@ -0,0 +1,2 @@ +[document web] +
diff --git a/content/test/data/accessibility/html/section-expected-auralinux.txt b/content/test/data/accessibility/html/section-expected-auralinux.txt new file mode 100644 index 0000000..4e52b05 --- /dev/null +++ b/content/test/data/accessibility/html/section-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] +++[section] xml-roles:region +++++[text] name='This is a section element.'
diff --git a/content/test/data/accessibility/html/section.html b/content/test/data/accessibility/html/section.html index 281a61771..e5976bbe 100644 --- a/content/test/data/accessibility/html/section.html +++ b/content/test/data/accessibility/html/section.html
@@ -2,6 +2,7 @@ @MAC-ALLOW:AXRole* @MAC-ALLOW:AXSubrole* @WIN-ALLOW:xml-roles:* +@AURALINUX-ALLOW:xml-roles:* --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/html/select-expected-auralinux.txt b/content/test/data/accessibility/html/select-expected-auralinux.txt new file mode 100644 index 0000000..09d3988 --- /dev/null +++ b/content/test/data/accessibility/html/select-expected-auralinux.txt
@@ -0,0 +1,25 @@ +[document web] +++[section] +++++[combo box] expandable haspopup:menu +++++++[menu] +++++++++[menu item] name='Placeholder option' selectable selected posinset:1 setsize:3 +++++++++[menu item] name='Option 1' posinset:2 setsize:3 +++++++++[menu item] name='Option 2' posinset:3 setsize:3 +++++[combo box] expandable haspopup:menu +++++++[menu] +++++++++[menu item] name='Option 1' posinset:1 setsize:3 +++++++++[menu item] name='Option 2' selectable selected posinset:2 setsize:3 +++++++++[menu item] name='Option 3' posinset:3 setsize:3 +++++[combo box] expandable required haspopup:menu +++++++[menu] +++++++++[menu item] name='Option 1' selectable selected posinset:1 setsize:3 +++++++++[menu item] name='Option 2' posinset:2 setsize:3 +++++++++[menu item] name='Option 3' posinset:3 setsize:3 +++++[list box] multiselectable +++++++[list item] name='Option 1' posinset:1 setsize:3 +++++++[list item] name='Option 2' posinset:2 setsize:3 +++++++[list item] name='Option 3' posinset:3 setsize:3 +++++[list box] +++++++[list item] name='Option 1' posinset:1 setsize:3 +++++++[list item] name='Option 2' posinset:2 setsize:3 +++++++[list item] name='Option 3' posinset:3 setsize:3
diff --git a/content/test/data/accessibility/html/select.html b/content/test/data/accessibility/html/select.html index 17d690e..fc2ca669 100644 --- a/content/test/data/accessibility/html/select.html +++ b/content/test/data/accessibility/html/select.html
@@ -11,6 +11,11 @@ @BLINK-ALLOW:setSize* @BLINK-ALLOW:posInSet* @BLINK-ALLOW:haspopup* +@AURALINUX-ALLOW:haspopup* +@AURALINUX-ALLOW:posinset* +@AURALINUX-ALLOW:setsize* +@AURALINUX-ALLOW:expand* +@AURALINUX-ALLOW:required --> <html> <body>
diff --git a/content/test/data/accessibility/html/small-expected-auralinux.txt b/content/test/data/accessibility/html/small-expected-auralinux.txt new file mode 100644 index 0000000..140e0d4 --- /dev/null +++ b/content/test/data/accessibility/html/small-expected-auralinux.txt
@@ -0,0 +1,4 @@ +[document web] +++[paragraph] +++++[text] name='Chromium' +++++[text] name='open source project'
diff --git a/content/test/data/accessibility/html/source-expected-auralinux.txt b/content/test/data/accessibility/html/source-expected-auralinux.txt new file mode 100644 index 0000000..da6f0cd --- /dev/null +++ b/content/test/data/accessibility/html/source-expected-auralinux.txt
@@ -0,0 +1,11 @@ +[document web] focusable focused +++[section] +++++[audio] focusable +++++++[section] +++++++++[tool bar] name='audio' description='audio' horizontal +++++++++++[tool bar] name='audio' description='audio' horizontal +++++++++++++[push button] name='play' description='begin playback' focusable +++++++++++++[text] name='0:00' +++++++++++++[text] name='/ 0:00' +++++++++++++[slider] description='audio time scrubber' focusable horizontal +++++++++++++[push button] name='mute' description='mute audio track'
diff --git a/content/test/data/accessibility/html/source.html b/content/test/data/accessibility/html/source.html index c902fb7..238e8b7e7 100644 --- a/content/test/data/accessibility/html/source.html +++ b/content/test/data/accessibility/html/source.html
@@ -1,3 +1,8 @@ +<!-- +@AURALINUX-ALLOW:focus* +@AURALINUX-ALLOW:horizontal +@AURALINUX-ALLOW:vertical +--> <!DOCTYPE html> <html> <body>
diff --git a/content/test/data/accessibility/html/span-expected-auralinux.txt b/content/test/data/accessibility/html/span-expected-auralinux.txt new file mode 100644 index 0000000..e8bdc30 --- /dev/null +++ b/content/test/data/accessibility/html/span-expected-auralinux.txt
@@ -0,0 +1,70 @@ +[document web] +++[paragraph] +++++[text] name='This' +++++[text] name=' ' +++++[text] name='paragraph has ' +++++[text] name='text' +++++[text] name=' ' +++++[text] name='in' +++++[text] name=' ' +++++[text] name='spans' +++++[text] name='.' +++[paragraph] +++++[text] name='E1. Eat' +++++[text] name=' ' +++++[link] name='space' +++++++[text] name='space' +++[paragraph] +++++[text] name='E2. Eat' +++++[text] name=' ' +++++[link] name='space' +++++++[text] name='space' +++[paragraph] +++++[text] name='E3. Eat' +++++[text] name=' ' +++++[link] name='space' +++++++[text] name='space' +++[paragraph] +++++[link] name='E4. Eat' +++++++[text] name='E4. Eat' +++++[text] name=' ' +++++[text] name='space' +++[paragraph] +++++[link] name='E5. Eat' +++++++[text] name='E5. Eat' +++++[text] name=' ' +++++[text] name='space' +++[paragraph] +++++[link] name='E6. Eat' +++++++[text] name='E6. Eat' +++++[text] name=' ' +++++[text] name='space' +++[paragraph] +++++[text] name='K1. Keep' +++++[text] name=' ' +++++[text] name='space' +++[paragraph] +++++[text] name='K2. Keep' +++++[text] name=' ' +++++[text] name='space' +++[paragraph] +++++[text] name='K3. Keep' +++++[text] name=' ' +++++[text] name='space' +++[paragraph] +++++[text] name='K4. Keep ' +++++[text] name='space' +++[paragraph] +++++[text] name='K5. Keep' +++++[text] name=' ' +++++[text] name='space' +++[paragraph] +++++[text] name='K6. Keep ' +++++[text] name='space' +++[paragraph] +++++[text] name='K7. Keep' +++++[text] name=' space' +++[paragraph] +++++[text] name='K8. Keep' +++++[text] name=' ' +++++[text] name='space'
diff --git a/content/test/data/accessibility/html/strong-expected-auralinux.txt b/content/test/data/accessibility/html/strong-expected-auralinux.txt new file mode 100644 index 0000000..c056af1e --- /dev/null +++ b/content/test/data/accessibility/html/strong-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] +++[section] +++++[text] name='Strong text'
diff --git a/content/test/data/accessibility/html/style-expected-auralinux.txt b/content/test/data/accessibility/html/style-expected-auralinux.txt new file mode 100644 index 0000000..19b9c9f --- /dev/null +++ b/content/test/data/accessibility/html/style-expected-auralinux.txt
@@ -0,0 +1 @@ +[document web]
diff --git a/content/test/data/accessibility/html/sub-expected-auralinux.txt b/content/test/data/accessibility/html/sub-expected-auralinux.txt new file mode 100644 index 0000000..5d75f9c --- /dev/null +++ b/content/test/data/accessibility/html/sub-expected-auralinux.txt
@@ -0,0 +1,5 @@ +[document web] +++[paragraph] +++++[text] name='This text contains ' +++++[subscript] name='subscript' +++++[text] name=' text.'
diff --git a/content/test/data/accessibility/html/summary-expected-auralinux.txt b/content/test/data/accessibility/html/summary-expected-auralinux.txt new file mode 100644 index 0000000..a4032a4 --- /dev/null +++ b/content/test/data/accessibility/html/summary-expected-auralinux.txt
@@ -0,0 +1,4 @@ +[document web] +++[panel] +++++[toggle button] name='details tag' +++++++[text] name='details tag'
diff --git a/content/test/data/accessibility/html/sup-expected-auralinux.txt b/content/test/data/accessibility/html/sup-expected-auralinux.txt new file mode 100644 index 0000000..50beb15 --- /dev/null +++ b/content/test/data/accessibility/html/sup-expected-auralinux.txt
@@ -0,0 +1,5 @@ +[document web] +++[paragraph] +++++[text] name='This text contains' +++++[superscript] name='superscript' +++++[text] name='text.'
diff --git a/content/test/data/accessibility/html/svg-expected-auralinux.txt b/content/test/data/accessibility/html/svg-expected-auralinux.txt new file mode 100644 index 0000000..d7ff00d3 --- /dev/null +++ b/content/test/data/accessibility/html/svg-expected-auralinux.txt
@@ -0,0 +1,5 @@ +[document web] +++[section] +++++[document frame] name='svg' +++++++[section] +++++++++[text] name='Test'
diff --git a/content/test/data/accessibility/html/table-layout-expected-auralinux.txt b/content/test/data/accessibility/html/table-layout-expected-auralinux.txt new file mode 100644 index 0000000..7be2ccc --- /dev/null +++ b/content/test/data/accessibility/html/table-layout-expected-auralinux.txt
@@ -0,0 +1,23 @@ +[document web] name='Table example #2' +++[section] +++++[section] +++++++[section] name='1' +++++++++[text] name='1' +++++++[section] name='2' +++++++++[text] name='2' +++++++[section] name='3' +++++++++[text] name='3' +++++[section] +++++++[section] name='4' +++++++++[text] name='4' +++++++[section] name='5' +++++++++[text] name='5' +++++++[section] name='6' +++++++++[text] name='6' +++++[section] +++++++[section] name='7' +++++++++[text] name='7' +++++++[section] name='8' +++++++++[text] name='8' +++++++[section] name='9' +++++++++[text] name='9'
diff --git a/content/test/data/accessibility/html/table-presentation-expected-auralinux.txt b/content/test/data/accessibility/html/table-presentation-expected-auralinux.txt new file mode 100644 index 0000000..a4d0af5 --- /dev/null +++ b/content/test/data/accessibility/html/table-presentation-expected-auralinux.txt
@@ -0,0 +1,9 @@ +[document web] name='Table with role=presentation' +++[section] +++++[text] name='1' +++[section] +++++[text] name='2' +++[section] +++++[text] name='4' +++[section] +++++[text] name='5'
diff --git a/content/test/data/accessibility/html/table-simple-expected-auralinux.txt b/content/test/data/accessibility/html/table-simple-expected-auralinux.txt new file mode 100644 index 0000000..1e1cb95 --- /dev/null +++ b/content/test/data/accessibility/html/table-simple-expected-auralinux.txt
@@ -0,0 +1,17 @@ +[document web] name='Table example' +++[table] +++++[table row] +++++++[column header] name='Pair' +++++++++[text] name='Pair' +++++++[column header] name='Single' +++++++++[text] name='Single' +++++[table row] +++++++[table cell] name='AB' +++++++++[text] name='AB' +++++++[table cell] name='B' +++++++++[text] name='B' +++++[table row] +++++++[table cell] name='CD' +++++++++[text] name='CD' +++++++[table cell] name='D' +++++++++[text] name='D'
diff --git a/content/test/data/accessibility/html/table-spans-expected-auralinux.txt b/content/test/data/accessibility/html/table-spans-expected-auralinux.txt new file mode 100644 index 0000000..06d542a4 --- /dev/null +++ b/content/test/data/accessibility/html/table-spans-expected-auralinux.txt
@@ -0,0 +1,21 @@ +[document web] name='Table example with rowspan and colspan' +++[table] +++++[table row] +++++++[table cell] name='AD' +++++++++[text] name='AD' +++++++[table cell] name='BC' +++++++++[text] name='BC' +++++[table row] +++++++[table cell] name='EF' +++++++++[text] name='EF' +++[table] +++++[table row] +++++++[table cell] name='AD' +++++++++[text] name='AD' +++++++[table cell] name='BC' +++++++++[text] name='BC' +++++[table row] +++++++[table cell] name='EF' +++++++++[text] name='EF' +++++++[table cell] name='GH' +++++++++[text] name='GH'
diff --git a/content/test/data/accessibility/html/table-th-colheader-expected-auralinux.txt b/content/test/data/accessibility/html/table-th-colheader-expected-auralinux.txt new file mode 100644 index 0000000..1de731f --- /dev/null +++ b/content/test/data/accessibility/html/table-th-colheader-expected-auralinux.txt
@@ -0,0 +1,12 @@ +[document web] +++[table] +++++[table row] posinset:1 setsize:2 +++++++[column header] name='Firstname' table-cell-index:0 +++++++++[text] name='Firstname' +++++++[column header] name='Lastname' table-cell-index:1 +++++++++[text] name='Lastname' +++++[table row] posinset:2 setsize:2 +++++++[table cell] name='Jill' table-cell-index:2 +++++++++[text] name='Jill' +++++++[table cell] name='Smith' table-cell-index:3 +++++++++[text] name='Smith'
diff --git a/content/test/data/accessibility/html/table-th-colheader.html b/content/test/data/accessibility/html/table-th-colheader.html index bbdaf7a..298a669 100644 --- a/content/test/data/accessibility/html/table-th-colheader.html +++ b/content/test/data/accessibility/html/table-th-colheader.html
@@ -1,4 +1,7 @@ <!-- +@AURALINUX-ALLOW:table-cell-index* +@AURALINUX-ALLOW:posinset* +@AURALINUX-ALLOW:setsize* @WIN-ALLOW:row_* @WIN-ALLOW:column_* @MAC-ALLOW:AXIndex=*
diff --git a/content/test/data/accessibility/html/table-th-rowheader-expected-auralinux.txt b/content/test/data/accessibility/html/table-th-rowheader-expected-auralinux.txt new file mode 100644 index 0000000..39622ccd --- /dev/null +++ b/content/test/data/accessibility/html/table-th-rowheader-expected-auralinux.txt
@@ -0,0 +1,12 @@ +[document web] name='Table example - th rowheader' +++[table] +++++[table row] +++++++[row header] name='Firstname' +++++++++[text] name='Firstname' +++++++[table cell] name='Jill' +++++++++[text] name='Jill' +++++[table row] +++++++[row header] name='Lastname' +++++++++[text] name='Lastname' +++++++[table cell] name='Smith' +++++++++[text] name='Smith'
diff --git a/content/test/data/accessibility/html/table-thead-tbody-tfoot-expected-auralinux.txt b/content/test/data/accessibility/html/table-thead-tbody-tfoot-expected-auralinux.txt new file mode 100644 index 0000000..36aeba2 --- /dev/null +++ b/content/test/data/accessibility/html/table-thead-tbody-tfoot-expected-auralinux.txt
@@ -0,0 +1,22 @@ +[document web] name='Table example - thead, tbody, tfoot' +++[table] +++++[table row] +++++++[column header] name='Sum' +++++++++[text] name='Sum' +++++++[column header] name='Subtraction' +++++++++[text] name='Subtraction' +++++[table row] +++++++[table cell] name='10' +++++++++[text] name='10' +++++++[table cell] name='7' +++++++++[text] name='7' +++++[table row] +++++++[table cell] name='2' +++++++++[text] name='2' +++++++[table cell] name='4' +++++++++[text] name='4' +++++[table row] +++++++[table cell] name='12' +++++++++[text] name='12' +++++++[table cell] name='3' +++++++++[text] name='3'
diff --git a/content/test/data/accessibility/html/textarea-expected-auralinux.txt b/content/test/data/accessibility/html/textarea-expected-auralinux.txt new file mode 100644 index 0000000..614277c --- /dev/null +++ b/content/test/data/accessibility/html/textarea-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] focusable focused +++[section] +++++[entry] editable focusable multi-line selectable-text
diff --git a/content/test/data/accessibility/html/textarea-read-only-expected-auralinux.txt b/content/test/data/accessibility/html/textarea-read-only-expected-auralinux.txt new file mode 100644 index 0000000..ee6fd8a --- /dev/null +++ b/content/test/data/accessibility/html/textarea-read-only-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] focusable focused +++[section] +++++[entry] focusable multi-line selectable-text
diff --git a/content/test/data/accessibility/html/textarea-read-only.html b/content/test/data/accessibility/html/textarea-read-only.html index ffa31da..675b5c5 100644 --- a/content/test/data/accessibility/html/textarea-read-only.html +++ b/content/test/data/accessibility/html/textarea-read-only.html
@@ -7,6 +7,10 @@ @WIN-ALLOW:selection_start* @WIN-ALLOW:selection_end* @BLINK-ALLOW:textSel* +@AURALINUX-ALLOW:text-input-type* +@AURALINUX-ALLOW:editable +@AURALINUX-ALLOW:focus* +@AURALINUX-ALLOW:*-line --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/html/textarea-with-selection-expected-auralinux.txt b/content/test/data/accessibility/html/textarea-with-selection-expected-auralinux.txt new file mode 100644 index 0000000..c9caf30e9 --- /dev/null +++ b/content/test/data/accessibility/html/textarea-with-selection-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] focusable +++[section] +++++[entry] editable focusable focused multi-line selectable-text
diff --git a/content/test/data/accessibility/html/textarea-with-selection.html b/content/test/data/accessibility/html/textarea-with-selection.html index 07b6e82e..b758be14 100644 --- a/content/test/data/accessibility/html/textarea-with-selection.html +++ b/content/test/data/accessibility/html/textarea-with-selection.html
@@ -7,6 +7,10 @@ @WIN-ALLOW:selection_start* @WIN-ALLOW:selection_end* @BLINK-ALLOW:textSel* +@AURALINUX-ALLOW:text-input-type* +@AURALINUX-ALLOW:editable +@AURALINUX-ALLOW:focus* +@AURALINUX-ALLOW:*-line --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/html/textarea.html b/content/test/data/accessibility/html/textarea.html index 694bab7a..c540d6705 100644 --- a/content/test/data/accessibility/html/textarea.html +++ b/content/test/data/accessibility/html/textarea.html
@@ -10,6 +10,10 @@ @WIN-ALLOW:selection_start* @WIN-ALLOW:selection_end* @BLINK-ALLOW:textSel* +@AURALINUX-ALLOW:text-input-type* +@AURALINUX-ALLOW:editable +@AURALINUX-ALLOW:focus* +@AURALINUX-ALLOW:*-line --> <html> <body>
diff --git a/content/test/data/accessibility/html/time-expected-auralinux.txt b/content/test/data/accessibility/html/time-expected-auralinux.txt new file mode 100644 index 0000000..4d2f4b2 --- /dev/null +++ b/content/test/data/accessibility/html/time-expected-auralinux.txt
@@ -0,0 +1,7 @@ +[document web] +++[section] +++++[static] +++++++[text] name='10:00' +++++[text] name=' ' +++++[static] +++++++[text] name='Valentines day'
diff --git a/content/test/data/accessibility/html/title-expected-auralinux.txt b/content/test/data/accessibility/html/title-expected-auralinux.txt new file mode 100644 index 0000000..17f87dd --- /dev/null +++ b/content/test/data/accessibility/html/title-expected-auralinux.txt
@@ -0,0 +1 @@ +[document web] name='Title of the document'
diff --git a/content/test/data/accessibility/html/transition-expected-auralinux.txt b/content/test/data/accessibility/html/transition-expected-auralinux.txt new file mode 100644 index 0000000..dc212f2 --- /dev/null +++ b/content/test/data/accessibility/html/transition-expected-auralinux.txt
@@ -0,0 +1,4 @@ +[document web] +++[section] +++++[push button] name='GrowButton' +++++[text] name='Done'
diff --git a/content/test/data/accessibility/html/ul-expected-auralinux.txt b/content/test/data/accessibility/html/ul-expected-auralinux.txt new file mode 100644 index 0000000..56f58a6e --- /dev/null +++ b/content/test/data/accessibility/html/ul-expected-auralinux.txt
@@ -0,0 +1,11 @@ +[document web] +++[list] +++++[list item] +++++++[static] name='• ' +++++++[text] name='Item 1' +++++[list item] +++++++[static] name='• ' +++++++[text] name='Item 2' +++++[list item] +++++++[static] name='• ' +++++++[text] name='Item 3'
diff --git a/content/test/data/accessibility/html/var-expected-auralinux.txt b/content/test/data/accessibility/html/var-expected-auralinux.txt new file mode 100644 index 0000000..0523b56 --- /dev/null +++ b/content/test/data/accessibility/html/var-expected-auralinux.txt
@@ -0,0 +1,3 @@ +[document web] +++[section] +++++[text] name='Variable'
diff --git a/content/test/data/accessibility/html/wbr-expected-auralinux.txt b/content/test/data/accessibility/html/wbr-expected-auralinux.txt new file mode 100644 index 0000000..2fef7a07 --- /dev/null +++ b/content/test/data/accessibility/html/wbr-expected-auralinux.txt
@@ -0,0 +1,5 @@ +[document web] +++[section] +++++[text] name='Supercali' +++++[text] name='fragilistic' +++++[text] name='expialidocious'
diff --git a/content/test/test_blink_web_unit_test_support.cc b/content/test/test_blink_web_unit_test_support.cc index b3d52deb..bee17f25 100644 --- a/content/test/test_blink_web_unit_test_support.cc +++ b/content/test/test_blink_web_unit_test_support.cc
@@ -50,7 +50,6 @@ #include "gin/v8_initializer.h" // nogncheck #endif -#include "content/renderer/media/webrtc/rtc_certificate.h" #include "third_party/webrtc/rtc_base/rtccertificate.h" // nogncheck using blink::WebString; @@ -145,7 +144,6 @@ gin::V8Initializer::LoadV8Natives(); #endif - scoped_refptr<base::SingleThreadTaskRunner> dummy_task_runner; std::unique_ptr<base::ThreadTaskRunnerHandle> dummy_task_runner_handle; if (!base::ThreadTaskRunnerHandle::IsSet()) { @@ -332,15 +330,13 @@ bool IsSupportedKeyParams(const blink::WebRTCKeyParams& key_params) override { return false; } - std::unique_ptr<blink::WebRTCCertificate> FromPEM( + rtc::scoped_refptr<rtc::RTCCertificate> FromPEM( blink::WebString pem_private_key, blink::WebString pem_certificate) override { rtc::scoped_refptr<rtc::RTCCertificate> certificate = rtc::RTCCertificate::FromPEM(rtc::RTCCertificatePEM( pem_private_key.Utf8(), pem_certificate.Utf8())); - if (!certificate) - return nullptr; - return std::make_unique<RTCCertificate>(certificate); + return certificate; } };
diff --git a/extensions/browser/api/bluetooth_socket/bluetooth_socket_api.cc b/extensions/browser/api/bluetooth_socket/bluetooth_socket_api.cc index c8e0ba40..3984d81 100644 --- a/extensions/browser/api/bluetooth_socket/bluetooth_socket_api.cc +++ b/extensions/browser/api/bluetooth_socket/bluetooth_socket_api.cc
@@ -7,6 +7,8 @@ #include <stdint.h> #include <utility> +#include "base/hash.h" +#include "base/metrics/histogram_functions.h" #include "content/public/browser/browser_context.h" #include "device/bluetooth/bluetooth_adapter.h" #include "device/bluetooth/bluetooth_adapter_factory.h" @@ -113,6 +115,19 @@ return true; } +// Generates a hash from a UUID suitable for +// base::UmaHistogramSparse(positive int). +// +// Hash values can be produced manually using tool: bluetooth_metrics_hash. +int HashUUID(const device::BluetoothUUID& uuid) { + // TODO(520284): Other than verifying that |uuid| contains a value, this logic + // should be migrated to a dedicated histogram macro for hashed strings. + uint32_t data = base::PersistentHash(uuid.canonical_value()); + + // Strip off the sign bit to make the hash look nicer. + return static_cast<int>(data & 0x7fffffff); +} + } // namespace BluetoothSocketAsyncApiFunction::BluetoothSocketAsyncApiFunction() {} @@ -342,6 +357,9 @@ service_options.channel.reset(new int(*(options->channel))); } + base::UmaHistogramSparse("Extensions.BluetoothSocket.ListenRFCOMM.Service", + HashUUID(uuid)); + adapter->CreateRfcommService(uuid, service_options, callback, error_callback); } @@ -392,6 +410,9 @@ } } + base::UmaHistogramSparse("Extensions.BluetoothSocket.ListenL2CAP.Service", + HashUUID(uuid)); + adapter->CreateL2capService(uuid, service_options, callback, error_callback); } @@ -492,6 +513,9 @@ void BluetoothSocketConnectFunction::ConnectToService( device::BluetoothDevice* device, const device::BluetoothUUID& uuid) { + base::UmaHistogramSparse("Extensions.BluetoothSocket.Connect.Service", + HashUUID(uuid)); + device->ConnectToService( uuid, base::Bind(&BluetoothSocketConnectFunction::OnConnect, this),
diff --git a/google_apis/gaia/gaia_auth_util.cc b/google_apis/gaia/gaia_auth_util.cc index 7acc27650..e2bb6147 100644 --- a/google_apis/gaia/gaia_auth_util.cc +++ b/google_apis/gaia/gaia_auth_util.cc
@@ -30,21 +30,19 @@ std::string CanonicalizeEmailImpl(const std::string& email_address, bool change_googlemail_to_gmail) { + std::string lower_case_email = base::ToLowerASCII(email_address); std::vector<std::string> parts = base::SplitString( - email_address, "@", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); - if (parts.size() != 2U) { - NOTREACHED() << "expecting exactly one @, but got " - << (parts.empty() ? 0 : parts.size() - 1) - << " : " << email_address; - } else { - if (change_googlemail_to_gmail && parts[1] == kGooglemailDomain) - parts[1] = kGmailDomain; + lower_case_email, "@", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); + if (parts.size() != 2U) + return lower_case_email; - if (parts[1] == kGmailDomain) // only strip '.' for gmail accounts. - base::RemoveChars(parts[0], ".", &parts[0]); - } + if (change_googlemail_to_gmail && parts[1] == kGooglemailDomain) + parts[1] = kGmailDomain; - std::string new_email = base::ToLowerASCII(base::JoinString(parts, "@")); + if (parts[1] == kGmailDomain) // only strip '.' for gmail accounts. + base::RemoveChars(parts[0], ".", &parts[0]); + + std::string new_email = base::JoinString(parts, "@"); VLOG(1) << "Canonicalized " << email_address << " to " << new_email; return new_email; }
diff --git a/google_apis/gaia/gaia_auth_util.h b/google_apis/gaia/gaia_auth_util.h index 4322a36..175a41d 100644 --- a/google_apis/gaia/gaia_auth_util.h +++ b/google_apis/gaia/gaia_auth_util.h
@@ -36,6 +36,8 @@ // Perform basic canonicalization of |email_address|, taking into account that // gmail does not consider '.' or caps inside a username to matter. +// If |email_address| is not a valid, returns it in lower case without +// additional canonicalization. std::string CanonicalizeEmail(const std::string& email_address); // Returns the canonical form of the given domain.
diff --git a/google_apis/gaia/gaia_auth_util_unittest.cc b/google_apis/gaia/gaia_auth_util_unittest.cc index 51d1a7af..9eb1308 100644 --- a/google_apis/gaia/gaia_auth_util_unittest.cc +++ b/google_apis/gaia/gaia_auth_util_unittest.cc
@@ -14,6 +14,14 @@ EXPECT_EQ(lower_case, CanonicalizeEmail(lower_case)); } +TEST(GaiaAuthUtilTest, InvalidEmailAddress) { + const char invalid_email1[] = "user"; + const char invalid_email2[] = "user@@what.com"; + EXPECT_EQ(invalid_email1, CanonicalizeEmail(invalid_email1)); + EXPECT_EQ(invalid_email2, CanonicalizeEmail(invalid_email2)); + EXPECT_EQ("user", CanonicalizeEmail("USER")); +} + TEST(GaiaAuthUtilTest, EmailAddressIgnoreCaps) { EXPECT_EQ(CanonicalizeEmail("user@what.com"), CanonicalizeEmail("UsEr@what.com")); @@ -39,6 +47,11 @@ CanonicalizeEmail("UsEr@gmail.com")); } +TEST(GaiaAuthUtilTest, EmailAddressIgnoreOneUsernameDotAndIgnoreCaps) { + EXPECT_EQ(CanonicalizeEmail("user@gmail.com"), + CanonicalizeEmail("US.ER@GMAIL.COM")); +} + TEST(GaiaAuthUtilTest, EmailAddressIgnoreManyUsernameDots) { EXPECT_EQ(CanonicalizeEmail("u.ser@gmail.com"), CanonicalizeEmail("Us.E.r@gmail.com"));
diff --git a/google_apis/gaia/gaia_oauth_client.cc b/google_apis/gaia/gaia_oauth_client.cc index 40e866b..c6c0221 100644 --- a/google_apis/gaia/gaia_oauth_client.cc +++ b/google_apis/gaia/gaia_oauth_client.cc
@@ -9,17 +9,20 @@ #include "base/json/json_reader.h" #include "base/logging.h" +#include "base/memory/weak_ptr.h" #include "base/strings/string_util.h" #include "base/values.h" #include "google_apis/gaia/gaia_auth_util.h" #include "google_apis/gaia/gaia_urls.h" +#include "net/base/backoff_entry.h" #include "net/base/escape.h" #include "net/base/load_flags.h" #include "net/http/http_status_code.h" #include "net/traffic_annotation/network_traffic_annotation.h" -#include "net/url_request/url_fetcher.h" -#include "net/url_request/url_fetcher_delegate.h" -#include "net/url_request/url_request_context_getter.h" +#include "net/url_request/url_request_throttler_entry.h" +#include "services/network/public/cpp/resource_request.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" +#include "services/network/public/cpp/simple_url_loader.h" #include "url/gurl.h" namespace { @@ -30,19 +33,30 @@ namespace gaia { -// Use a non-zero number, so unit tests can differentiate the URLFetcher used by -// this class from other fetchers (most other code just hardcodes the ID to 0). -const int GaiaOAuthClient::kUrlFetcherId = 17109006; - class GaiaOAuthClient::Core - : public base::RefCountedThreadSafe<GaiaOAuthClient::Core>, - public net::URLFetcherDelegate { + : public base::RefCountedThreadSafe<GaiaOAuthClient::Core> { public: - Core(net::URLRequestContextGetter* request_context_getter) - : num_retries_(0), - request_context_getter_(request_context_getter), + Core(scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) + : backoff_entry_(&backoff_policy_), + num_retries_(0), + max_retries_(0), + url_loader_factory_(url_loader_factory), delegate_(NULL), - request_type_(NO_PENDING_REQUEST) { + request_type_(NO_PENDING_REQUEST), + weak_ptr_factory_(this) { + backoff_policy_.num_errors_to_ignore = + net::URLRequestThrottlerEntry::kDefaultNumErrorsToIgnore; + backoff_policy_.initial_delay_ms = + net::URLRequestThrottlerEntry::kDefaultInitialDelayMs; + backoff_policy_.multiply_factor = + net::URLRequestThrottlerEntry::kDefaultMultiplyFactor; + backoff_policy_.jitter_factor = + net::URLRequestThrottlerEntry::kDefaultJitterFactor; + backoff_policy_.maximum_backoff_ms = + net::URLRequestThrottlerEntry::kDefaultMaximumBackoffMs; + backoff_policy_.entry_lifetime_ms = + net::URLRequestThrottlerEntry::kDefaultEntryLifetimeMs; + backoff_policy_.always_use_initial_delay = false; } void GetTokensFromAuthCode(const OAuthClientInfo& oauth_client_info, @@ -68,8 +82,8 @@ int max_retries, Delegate* delegate); - // net::URLFetcherDelegate implementation. - void OnURLFetchComplete(const net::URLFetcher* source) override; + // Called as a SimpleURLLoader callback + void OnURLLoadComplete(std::unique_ptr<std::string> body); private: friend class base::RefCountedThreadSafe<Core>; @@ -84,26 +98,50 @@ USER_INFO, }; - ~Core() override {} + ~Core() {} void GetUserInfoImpl(RequestType type, const std::string& oauth_access_token, int max_retries, Delegate* delegate); - void MakeGaiaRequest( + + // Stores request settings into |this| and calls SendRequest(). + void MakeRequest( + RequestType type, const GURL& url, - const std::string& post_body, + std::string post_body /* may be empty if not needed*/, + std::string authorization_header /* empty if not needed */, int max_retries, GaiaOAuthClient::Delegate* delegate, - const net::NetworkTrafficAnnotationTag& traffic_annotation); - void HandleResponse(const net::URLFetcher* source, + const net::MutableNetworkTrafficAnnotationTag& traffic_annotation); + + // Sends out a request based on things MakeRequest() stored... + // once |backoff_entry_| says it's OK. Can be called many times to retry, + // assuming |request_| is destroyed first. + void SendRequest(); + + // Actually sends the request. + void SendRequestImpl(); + + void HandleResponse(std::unique_ptr<std::string> body, bool* should_retry_request); + net::BackoffEntry::Policy backoff_policy_; + net::BackoffEntry backoff_entry_; + int num_retries_; - scoped_refptr<net::URLRequestContextGetter> request_context_getter_; + int max_retries_; + GURL url_; + net::MutableNetworkTrafficAnnotationTag traffic_annotation_; + std::string post_body_; + std::string authorization_header_; + + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; GaiaOAuthClient::Delegate* delegate_; - std::unique_ptr<net::URLFetcher> request_; + std::unique_ptr<network::SimpleURLLoader> request_; RequestType request_type_; + + base::WeakPtrFactory<Core> weak_ptr_factory_; }; void GaiaOAuthClient::Core::GetTokensFromAuthCode( @@ -111,8 +149,6 @@ const std::string& auth_code, int max_retries, GaiaOAuthClient::Delegate* delegate) { - DCHECK_EQ(request_type_, NO_PENDING_REQUEST); - request_type_ = TOKENS_FROM_AUTH_CODE; std::string post_body = "code=" + net::EscapeUrlEncodedData(auth_code, true) + "&client_id=" + net::EscapeUrlEncodedData(oauth_client_info.client_id, @@ -122,7 +158,7 @@ "&redirect_uri=" + net::EscapeUrlEncodedData(oauth_client_info.redirect_uri, true) + "&grant_type=authorization_code"; - net::NetworkTrafficAnnotationTag traffic_annotation = + net::MutableNetworkTrafficAnnotationTag traffic_annotation( net::DefineNetworkTrafficAnnotation("gaia_oauth_client_get_tokens", R"( semantics { sender: "OAuth 2.0 calls" @@ -151,9 +187,11 @@ SigninAllowed: false } } - })"); - MakeGaiaRequest(GURL(GaiaUrls::GetInstance()->oauth2_token_url()), post_body, - max_retries, delegate, traffic_annotation); + })")); + MakeRequest(TOKENS_FROM_AUTH_CODE, + GURL(GaiaUrls::GetInstance()->oauth2_token_url()), post_body, + /* authorization_header = */ std::string(), max_retries, delegate, + traffic_annotation); } void GaiaOAuthClient::Core::RefreshToken( @@ -162,8 +200,6 @@ const std::vector<std::string>& scopes, int max_retries, GaiaOAuthClient::Delegate* delegate) { - DCHECK_EQ(request_type_, NO_PENDING_REQUEST); - request_type_ = REFRESH_TOKEN; std::string post_body = "refresh_token=" + net::EscapeUrlEncodedData(refresh_token, true) + "&client_id=" + net::EscapeUrlEncodedData(oauth_client_info.client_id, @@ -177,7 +213,7 @@ post_body += "&scope=" + net::EscapeUrlEncodedData(scopes_string, true); } - net::NetworkTrafficAnnotationTag traffic_annotation = + net::MutableNetworkTrafficAnnotationTag traffic_annotation( net::DefineNetworkTrafficAnnotation("gaia_oauth_client_refresh_token", R"( semantics { sender: "OAuth 2.0 calls" @@ -204,9 +240,11 @@ SigninAllowed: false } } - })"); - MakeGaiaRequest(GURL(GaiaUrls::GetInstance()->oauth2_token_url()), post_body, - max_retries, delegate, traffic_annotation); + })")); + MakeRequest(REFRESH_TOKEN, GURL(GaiaUrls::GetInstance()->oauth2_token_url()), + post_body, + /* authorization_header = */ std::string(), max_retries, delegate, + traffic_annotation); } void GaiaOAuthClient::Core::GetUserEmail(const std::string& oauth_access_token, @@ -232,12 +270,7 @@ const std::string& oauth_access_token, int max_retries, Delegate* delegate) { - DCHECK_EQ(request_type_, NO_PENDING_REQUEST); - DCHECK(!request_.get()); - request_type_ = type; - delegate_ = delegate; - num_retries_ = 0; - net::NetworkTrafficAnnotationTag traffic_annotation = + net::MutableNetworkTrafficAnnotationTag traffic_annotation( net::DefineNetworkTrafficAnnotation("gaia_oauth_client_get_user_info", R"( semantics { sender: "OAuth 2.0 calls" @@ -263,35 +296,20 @@ SigninAllowed: false } } - })"); - request_ = net::URLFetcher::Create( - kUrlFetcherId, GURL(GaiaUrls::GetInstance()->oauth_user_info_url()), - net::URLFetcher::GET, this, traffic_annotation); - request_->SetRequestContext(request_context_getter_.get()); - request_->AddExtraRequestHeader("Authorization: OAuth " + oauth_access_token); - request_->SetMaxRetriesOn5xx(max_retries); - request_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | - net::LOAD_DO_NOT_SAVE_COOKIES); - MarkURLFetcherAsGaia(request_.get()); - - // Fetchers are sometimes cancelled because a network change was detected, - // especially at startup and after sign-in on ChromeOS. Retrying once should - // be enough in those cases; let the fetcher retry up to 3 times just in case. - // http://crbug.com/163710 - request_->SetAutomaticallyRetryOnNetworkChanges(3); - request_->Start(); + })")); + std::string auth = "OAuth " + oauth_access_token; + MakeRequest(type, GaiaUrls::GetInstance()->oauth_user_info_url(), + /* post_body = */ std::string(), auth, max_retries, delegate, + traffic_annotation); } void GaiaOAuthClient::Core::GetTokenInfo(const std::string& qualifier, const std::string& query, int max_retries, Delegate* delegate) { - DCHECK_EQ(request_type_, NO_PENDING_REQUEST); - DCHECK(!request_.get()); - request_type_ = TOKEN_INFO; std::string post_body = qualifier + "=" + net::EscapeUrlEncodedData(query, true); - net::NetworkTrafficAnnotationTag traffic_annotation = + net::MutableNetworkTrafficAnnotationTag traffic_annotation( net::DefineNetworkTrafficAnnotation("gaia_oauth_client_get_token_info", R"( semantics { @@ -323,65 +341,111 @@ SigninAllowed: false } } - })"); - MakeGaiaRequest(GURL(GaiaUrls::GetInstance()->oauth2_token_info_url()), - post_body, max_retries, delegate, traffic_annotation); + })")); + MakeRequest(TOKEN_INFO, + GURL(GaiaUrls::GetInstance()->oauth2_token_info_url()), post_body, + /* authorization_header = */ std::string(), max_retries, delegate, + traffic_annotation); } -void GaiaOAuthClient::Core::MakeGaiaRequest( +void GaiaOAuthClient::Core::MakeRequest( + RequestType type, const GURL& url, - const std::string& post_body, + std::string post_body, + std::string authorization_header, int max_retries, GaiaOAuthClient::Delegate* delegate, - const net::NetworkTrafficAnnotationTag& traffic_annotation) { - DCHECK(!request_.get()) << "Tried to fetch two things at once!"; + const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) { + DCHECK_EQ(request_type_, NO_PENDING_REQUEST); + request_type_ = type; delegate_ = delegate; num_retries_ = 0; - request_ = net::URLFetcher::Create(kUrlFetcherId, url, net::URLFetcher::POST, - this, traffic_annotation); - request_->SetRequestContext(request_context_getter_.get()); - request_->SetUploadData("application/x-www-form-urlencoded", post_body); - request_->SetMaxRetriesOn5xx(max_retries); - request_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | - net::LOAD_DO_NOT_SAVE_COOKIES); - MarkURLFetcherAsGaia(request_.get()); - // See comment on SetAutomaticallyRetryOnNetworkChanges() above. - request_->SetAutomaticallyRetryOnNetworkChanges(3); - request_->Start(); + max_retries_ = max_retries; + url_ = url; + traffic_annotation_ = traffic_annotation; + post_body_ = std::move(post_body); + authorization_header_ = std::move(authorization_header); + SendRequest(); } -// URLFetcher::Delegate implementation. -void GaiaOAuthClient::Core::OnURLFetchComplete( - const net::URLFetcher* source) { - bool should_retry = false; - HandleResponse(source, &should_retry); - if (should_retry) { - // Explicitly call ReceivedContentWasMalformed() to ensure the current - // request gets counted as a failure for calculation of the back-off - // period. If it was already a failure by status code, this call will - // be ignored. - request_->ReceivedContentWasMalformed(); - num_retries_++; - // We must set our request_context_getter_ again because - // URLFetcher::Core::RetryOrCompleteUrlFetch resets it to NULL... - request_->SetRequestContext(request_context_getter_.get()); - request_->Start(); +void GaiaOAuthClient::Core::SendRequest() { + if (backoff_entry_.ShouldRejectRequest()) { + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&GaiaOAuthClient::Core::SendRequestImpl, + weak_ptr_factory_.GetWeakPtr()), + backoff_entry_.GetTimeUntilRelease()); + } else { + SendRequestImpl(); } } -void GaiaOAuthClient::Core::HandleResponse( - const net::URLFetcher* source, - bool* should_retry_request) { +void GaiaOAuthClient::Core::SendRequestImpl() { + DCHECK(!request_.get()) << "Tried to fetch two things at once!"; + + auto resource_request = std::make_unique<network::ResourceRequest>(); + resource_request->url = url_; + resource_request->method = post_body_.empty() ? "GET" : "POST"; + resource_request->load_flags = + net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES; + if (!authorization_header_.empty()) + resource_request->headers.SetHeader("Authorization", authorization_header_); + + request_ = network::SimpleURLLoader::Create( + std::move(resource_request), + static_cast<net::NetworkTrafficAnnotationTag>(traffic_annotation_)); + + if (!post_body_.empty()) { + request_->AttachStringForUpload(post_body_, + "application/x-www-form-urlencoded"); + } + + // Retry is implemented internally. + request_->SetRetryOptions(0, network::SimpleURLLoader::RETRY_NEVER); + + // TODO(https://crbug.com/808498) re-add data use measurement once + // SimpleURLLoader supports it. Previous way of setting it was: + // MarkURLFetcherAsGaia(request_.get()); + + request_->DownloadToStringOfUnboundedSizeUntilCrashAndDie( + url_loader_factory_.get(), + // Unretained(this) is safe since |this| owns |request_|, and its deletion + // will cancel the callback. + base::BindOnce(&GaiaOAuthClient::Core::OnURLLoadComplete, + base::Unretained(this))); +} + +void GaiaOAuthClient::Core::OnURLLoadComplete( + std::unique_ptr<std::string> body) { + bool should_retry = false; + base::WeakPtr<GaiaOAuthClient::Core> weak_this = + weak_ptr_factory_.GetWeakPtr(); + // HandleResponse() may delete |this| if it assigns |should_retry| == false. + HandleResponse(std::move(body), &should_retry); + if (should_retry) { + num_retries_++; + backoff_entry_.InformOfRequest(false); + SendRequest(); + } else { + if (weak_this) + backoff_entry_.InformOfRequest(true); + } +} + +void GaiaOAuthClient::Core::HandleResponse(std::unique_ptr<std::string> body, + bool* should_retry_request) { + *should_retry_request = false; // Move ownership of the request fetcher into a local scoped_ptr which - // will be nuked when we're done handling the request, unless we need - // to retry, in which case ownership will be returned to request_. - std::unique_ptr<net::URLFetcher> old_request = std::move(request_); - DCHECK_EQ(source, old_request.get()); + // will be nuked when we're done handling the request. + std::unique_ptr<network::SimpleURLLoader> source = std::move(request_); + + int response_code = -1; + if (source->ResponseInfo() && source->ResponseInfo()->headers) + response_code = source->ResponseInfo()->headers->response_code(); // HTTP_BAD_REQUEST means the arguments are invalid. HTTP_UNAUTHORIZED means // the access or refresh token is invalid. No point retrying. We are // done here. - int response_code = source->GetResponseCode(); if (response_code == net::HTTP_BAD_REQUEST || response_code == net::HTTP_UNAUTHORIZED) { delegate_->OnOAuthError(); @@ -389,9 +453,8 @@ } std::unique_ptr<base::DictionaryValue> response_dict; - if (source->GetResponseCode() == net::HTTP_OK) { - std::string data; - source->GetResponseAsString(&data); + if (response_code == net::HTTP_OK && body) { + std::string data = std::move(*body); std::unique_ptr<base::Value> message_value = base::JSONReader::Read(data); if (message_value.get() && message_value->is_dict()) { response_dict.reset( @@ -402,13 +465,11 @@ if (!response_dict.get()) { // If we don't have an access token yet and the the error was not // RC_BAD_REQUEST, we may need to retry. - if ((source->GetMaxRetriesOn5xx() != -1) && - (num_retries_ >= source->GetMaxRetriesOn5xx())) { + if ((max_retries_ != -1) && (num_retries_ >= max_retries_)) { // Retry limit reached. Give up. request_type_ = NO_PENDING_REQUEST; - delegate_->OnNetworkError(source->GetResponseCode()); + delegate_->OnNetworkError(response_code); } else { - request_ = std::move(old_request); *should_retry_request = true; } return; @@ -471,8 +532,9 @@ } } -GaiaOAuthClient::GaiaOAuthClient(net::URLRequestContextGetter* context_getter) { - core_ = new Core(context_getter); +GaiaOAuthClient::GaiaOAuthClient( + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) { + core_ = new Core(std::move(url_loader_factory)); } GaiaOAuthClient::~GaiaOAuthClient() {
diff --git a/google_apis/gaia/gaia_oauth_client.h b/google_apis/gaia/gaia_oauth_client.h index 1d5f525..46415c4 100644 --- a/google_apis/gaia/gaia_oauth_client.h +++ b/google_apis/gaia/gaia_oauth_client.h
@@ -13,8 +13,8 @@ #include "base/memory/ref_counted.h" #include "base/values.h" -namespace net { -class URLRequestContextGetter; +namespace network { +class SharedURLLoaderFactory; } // A helper class to get and refresh OAuth2 refresh and access tokens. @@ -32,8 +32,6 @@ class GaiaOAuthClient { public: - const static int kUrlFetcherId; - class Delegate { public: // Invoked on a successful response to the GetTokensFromAuthCode request. @@ -64,7 +62,8 @@ virtual ~Delegate() {} }; - GaiaOAuthClient(net::URLRequestContextGetter* context_getter); + GaiaOAuthClient( + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory); ~GaiaOAuthClient(); // In the below methods, |max_retries| specifies the maximum number of times
diff --git a/google_apis/gaia/gaia_oauth_client_unittest.cc b/google_apis/gaia/gaia_oauth_client_unittest.cc index 0de4893..4b53e0a 100644 --- a/google_apis/gaia/gaia_oauth_client_unittest.cc +++ b/google_apis/gaia/gaia_oauth_client_unittest.cc
@@ -9,17 +9,17 @@ #include "base/json/json_reader.h" #include "base/macros.h" -#include "base/message_loop/message_loop.h" #include "base/strings/string_number_conversions.h" +#include "base/test/scoped_task_environment.h" +#include "base/time/tick_clock.h" #include "base/values.h" #include "google_apis/gaia/gaia_oauth_client.h" #include "net/base/net_errors.h" #include "net/http/http_status_code.h" #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" -#include "net/url_request/test_url_fetcher_factory.h" -#include "net/url_request/url_fetcher_delegate.h" -#include "net/url_request/url_request_status.h" -#include "net/url_request/url_request_test_util.h" +#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" +#include "services/network/test/test_url_loader_factory.h" +#include "services/network/test/test_utils.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" @@ -32,103 +32,87 @@ namespace { -// Responds as though OAuth returned from the server. -class MockOAuthFetcher : public net::TestURLFetcher { +// Simulates some number of failures, followed by an optional success. +// Does not distinguish between different URLs. +class ResponseInjector { public: - MockOAuthFetcher(int response_code, - int max_failure_count, - bool complete_immediately, - const GURL& url, - const std::string& results, - net::URLFetcher::RequestType request_type, - net::URLFetcherDelegate* d) - : net::TestURLFetcher(0, url, d), - max_failure_count_(max_failure_count), + explicit ResponseInjector(network::TestURLLoaderFactory* url_loader_factory) + : url_loader_factory_(url_loader_factory), + response_code_(net::HTTP_OK), + complete_immediately_(true), current_failure_count_(0), - complete_immediately_(complete_immediately) { - set_url(url); - set_response_code(response_code); - SetResponseString(results); + max_failure_count_(0) { + url_loader_factory->SetInterceptor( + base::BindRepeating(&ResponseInjector::AdjustResponseBasedOnSettings, + base::Unretained(this))); } - ~MockOAuthFetcher() override {} + ~ResponseInjector() { + url_loader_factory_->SetInterceptor( + base::BindRepeating([](const network::ResourceRequest& request) { + ADD_FAILURE() << "Unexpected fetch of:" << request.url; + })); + } - void Start() override { - if ((GetResponseCode() != net::HTTP_OK) && (max_failure_count_ != -1) && - (current_failure_count_ == max_failure_count_)) { - set_response_code(net::HTTP_OK); + void AdjustResponseBasedOnSettings(const network::ResourceRequest& request) { + url_loader_factory_->ClearResponses(); + DCHECK(pending_url_.is_empty()); + pending_url_ = request.url; + if (complete_immediately_) { + Finish(); } - - net::Error error = net::OK; - if (GetResponseCode() != net::HTTP_OK) { - error = net::ERR_FAILED; - current_failure_count_++; - } - set_status(net::URLRequestStatus::FromError(error)); - - if (complete_immediately_) - delegate()->OnURLFetchComplete(this); } void Finish() { - ASSERT_FALSE(complete_immediately_); - delegate()->OnURLFetchComplete(this); + net::HttpStatusCode response_code = response_code_; + if (response_code_ != net::HTTP_OK && (max_failure_count_ != -1) && + (current_failure_count_ == max_failure_count_)) + response_code = net::HTTP_OK; + + if (response_code != net::HTTP_OK) + ++current_failure_count_; + + url_loader_factory_->AddResponse(pending_url_.spec(), results_, + response_code); + pending_url_ = GURL(); } - private: - int max_failure_count_; - int current_failure_count_; - bool complete_immediately_; - DISALLOW_COPY_AND_ASSIGN(MockOAuthFetcher); -}; + std::string GetUploadData() { + const std::vector<network::TestURLLoaderFactory::PendingRequest>& pending = + *url_loader_factory_->pending_requests(); + if (pending.size() == 1) { + return network::GetUploadData(pending[0].request); + } else { + ADD_FAILURE() << "Unexpected state in GetUploadData"; + return ""; + } + } -class MockOAuthFetcherFactory : public net::URLFetcherFactory, - public net::ScopedURLFetcherFactory { - public: - MockOAuthFetcherFactory() - : net::ScopedURLFetcherFactory(this), - response_code_(net::HTTP_OK), - complete_immediately_(true) { - } - ~MockOAuthFetcherFactory() override {} - std::unique_ptr<net::URLFetcher> CreateURLFetcher( - int id, - const GURL& url, - net::URLFetcher::RequestType request_type, - net::URLFetcherDelegate* d, - net::NetworkTrafficAnnotationTag traffic_annotation) override { - url_fetcher_ = new MockOAuthFetcher( - response_code_, - max_failure_count_, - complete_immediately_, - url, - results_, - request_type, - d); - return std::unique_ptr<net::URLFetcher>(url_fetcher_); - } void set_response_code(int response_code) { - response_code_ = response_code; + response_code_ = static_cast<net::HttpStatusCode>(response_code); } + void set_max_failure_count(int count) { max_failure_count_ = count; } + void set_results(const std::string& results) { results_ = results; } - MockOAuthFetcher* get_url_fetcher() { - return url_fetcher_; - } + void set_complete_immediately(bool complete_immediately) { complete_immediately_ = complete_immediately; } private: - MockOAuthFetcher* url_fetcher_; - int response_code_; + network::TestURLLoaderFactory* url_loader_factory_; + GURL pending_url_; + + net::HttpStatusCode response_code_; bool complete_immediately_; + int current_failure_count_; int max_failure_count_; std::string results_; - DISALLOW_COPY_AND_ASSIGN(MockOAuthFetcherFactory); + DISALLOW_COPY_AND_ASSIGN(ResponseInjector); }; const std::string kTestAccessToken = "1/fFAGRNJru1FTz70BzhT3Zg"; @@ -182,23 +166,33 @@ class GaiaOAuthClientTest : public testing::Test { protected: + GaiaOAuthClientTest() + : scoped_task_environment_( + base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {} + void SetUp() override { client_info_.client_id = "test_client_id"; client_info_.client_secret = "test_client_secret"; client_info_.redirect_uri = "test_redirect_uri"; }; - protected: - net::TestURLRequestContextGetter* GetRequestContext() { - if (!request_context_getter_.get()) { - request_context_getter_ = new net::TestURLRequestContextGetter( - message_loop_.task_runner()); - } - return request_context_getter_.get(); + scoped_refptr<network::SharedURLLoaderFactory> GetSharedURLLoaderFactory() { + return base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( + &url_loader_factory_); } - base::MessageLoop message_loop_; - scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_; + void FlushNetwork() { + // An event loop spin is required for things to be delivered from + // TestURLLoaderFactory to its clients via mojo pipes. In addition, + // some retries may have back off, so may need to advance (mock) time + // for them to finish, too. + scoped_task_environment_.FastForwardUntilNoTasksRemain(); + } + + protected: + base::test::ScopedTaskEnvironment scoped_task_environment_; + network::TestURLLoaderFactory url_loader_factory_; + OAuthClientInfo client_info_; }; @@ -249,12 +243,13 @@ EXPECT_CALL(delegate, OnNetworkError(response_code)) .Times(1); - MockOAuthFetcherFactory factory; - factory.set_response_code(response_code); - factory.set_max_failure_count(4); + ResponseInjector injector(&url_loader_factory_); + injector.set_response_code(response_code); + injector.set_max_failure_count(4); - GaiaOAuthClient auth(GetRequestContext()); + GaiaOAuthClient auth(GetSharedURLLoaderFactory()); auth.GetTokensFromAuthCode(client_info_, "auth_code", 2, &delegate); + FlushNetwork(); } TEST_F(GaiaOAuthClientTest, NetworkFailureRecover) { @@ -264,13 +259,47 @@ EXPECT_CALL(delegate, OnGetTokensResponse(kTestRefreshToken, kTestAccessToken, kTestExpiresIn)).Times(1); - MockOAuthFetcherFactory factory; - factory.set_response_code(response_code); - factory.set_max_failure_count(4); - factory.set_results(kDummyGetTokensResult); + ResponseInjector injector(&url_loader_factory_); + injector.set_response_code(response_code); + injector.set_max_failure_count(4); + injector.set_results(kDummyGetTokensResult); - GaiaOAuthClient auth(GetRequestContext()); + GaiaOAuthClient auth(GetSharedURLLoaderFactory()); auth.GetTokensFromAuthCode(client_info_, "auth_code", -1, &delegate); + FlushNetwork(); +} + +TEST_F(GaiaOAuthClientTest, NetworkFailureRecoverBackoff) { + // Make sure long backoffs are expontential. + int response_code = net::HTTP_INTERNAL_SERVER_ERROR; + + MockGaiaOAuthClientDelegate delegate; + EXPECT_CALL(delegate, OnGetTokensResponse(kTestRefreshToken, kTestAccessToken, + kTestExpiresIn)) + .Times(1); + + ResponseInjector injector(&url_loader_factory_); + injector.set_response_code(response_code); + injector.set_max_failure_count(21); + injector.set_results(kDummyGetTokensResult); + + base::TimeTicks start = + scoped_task_environment_.GetMockTickClock()->NowTicks(); + + GaiaOAuthClient auth(GetSharedURLLoaderFactory()); + auth.GetTokensFromAuthCode(client_info_, "auth_code", -1, &delegate); + FlushNetwork(); + + // Default params are: + // 40% jitter, 700ms initial, 1.4 exponent, ignore first 2 failures. + // So after 19 retries, delay is at least: + // 0.6 * 700ms * 1.4^(19-2) ~ 128s + // After 20: + // 0.6 * 700ms * 1.4^(20-2) ~ 179s + // + // ... so the whole thing should take at least 307s + EXPECT_GE(scoped_task_environment_.GetMockTickClock()->NowTicks() - start, + base::TimeDelta::FromSeconds(307)); } TEST_F(GaiaOAuthClientTest, OAuthFailure) { @@ -279,13 +308,14 @@ MockGaiaOAuthClientDelegate delegate; EXPECT_CALL(delegate, OnOAuthError()).Times(1); - MockOAuthFetcherFactory factory; - factory.set_response_code(response_code); - factory.set_max_failure_count(-1); - factory.set_results(kDummyGetTokensResult); + ResponseInjector injector(&url_loader_factory_); + injector.set_response_code(response_code); + injector.set_max_failure_count(-1); + injector.set_results(kDummyGetTokensResult); - GaiaOAuthClient auth(GetRequestContext()); + GaiaOAuthClient auth(GetSharedURLLoaderFactory()); auth.GetTokensFromAuthCode(client_info_, "auth_code", -1, &delegate); + FlushNetwork(); } @@ -294,11 +324,12 @@ EXPECT_CALL(delegate, OnGetTokensResponse(kTestRefreshToken, kTestAccessToken, kTestExpiresIn)).Times(1); - MockOAuthFetcherFactory factory; - factory.set_results(kDummyGetTokensResult); + ResponseInjector injector(&url_loader_factory_); + injector.set_results(kDummyGetTokensResult); - GaiaOAuthClient auth(GetRequestContext()); + GaiaOAuthClient auth(GetSharedURLLoaderFactory()); auth.GetTokensFromAuthCode(client_info_, "auth_code", -1, &delegate); + FlushNetwork(); } TEST_F(GaiaOAuthClientTest, GetTokensAfterNetworkFailure) { @@ -311,14 +342,16 @@ EXPECT_CALL(success_delegate, OnGetTokensResponse(kTestRefreshToken, kTestAccessToken, kTestExpiresIn)).Times(1); - MockOAuthFetcherFactory factory; - factory.set_response_code(response_code); - factory.set_max_failure_count(4); - factory.set_results(kDummyGetTokensResult); + ResponseInjector injector(&url_loader_factory_); + injector.set_response_code(response_code); + injector.set_max_failure_count(4); + injector.set_results(kDummyGetTokensResult); - GaiaOAuthClient auth(GetRequestContext()); + GaiaOAuthClient auth(GetSharedURLLoaderFactory()); auth.GetTokensFromAuthCode(client_info_, "auth_code", 2, &failure_delegate); + FlushNetwork(); auth.GetTokensFromAuthCode(client_info_, "auth_code", -1, &success_delegate); + FlushNetwork(); } TEST_F(GaiaOAuthClientTest, RefreshTokenSuccess) { @@ -326,16 +359,16 @@ EXPECT_CALL(delegate, OnRefreshTokenResponse(kTestAccessToken, kTestExpiresIn)).Times(1); - MockOAuthFetcherFactory factory; - factory.set_results(kDummyRefreshTokenResult); - factory.set_complete_immediately(false); + ResponseInjector injector(&url_loader_factory_); + injector.set_results(kDummyRefreshTokenResult); + injector.set_complete_immediately(false); - GaiaOAuthClient auth(GetRequestContext()); + GaiaOAuthClient auth(GetSharedURLLoaderFactory()); auth.RefreshToken(client_info_, "refresh_token", std::vector<std::string>(), -1, &delegate); - EXPECT_THAT(factory.get_url_fetcher()->upload_data(), - Not(HasSubstr("scope"))); - factory.get_url_fetcher()->Finish(); + EXPECT_THAT(injector.GetUploadData(), Not(HasSubstr("scope"))); + injector.Finish(); + FlushNetwork(); } TEST_F(GaiaOAuthClientTest, RefreshTokenDownscopingSuccess) { @@ -343,39 +376,40 @@ EXPECT_CALL(delegate, OnRefreshTokenResponse(kTestAccessToken, kTestExpiresIn)).Times(1); - MockOAuthFetcherFactory factory; - factory.set_results(kDummyRefreshTokenResult); - factory.set_complete_immediately(false); + ResponseInjector injector(&url_loader_factory_); + injector.set_results(kDummyRefreshTokenResult); + injector.set_complete_immediately(false); - GaiaOAuthClient auth(GetRequestContext()); + GaiaOAuthClient auth(GetSharedURLLoaderFactory()); auth.RefreshToken(client_info_, "refresh_token", std::vector<std::string>(1, "scope4test"), -1, &delegate); - EXPECT_THAT(factory.get_url_fetcher()->upload_data(), - HasSubstr("&scope=scope4test")); - factory.get_url_fetcher()->Finish(); + EXPECT_THAT(injector.GetUploadData(), HasSubstr("&scope=scope4test")); + injector.Finish(); + FlushNetwork(); } - TEST_F(GaiaOAuthClientTest, GetUserEmail) { MockGaiaOAuthClientDelegate delegate; EXPECT_CALL(delegate, OnGetUserEmailResponse(kTestUserEmail)).Times(1); - MockOAuthFetcherFactory factory; - factory.set_results(kDummyUserInfoResult); + ResponseInjector injector(&url_loader_factory_); + injector.set_results(kDummyUserInfoResult); - GaiaOAuthClient auth(GetRequestContext()); + GaiaOAuthClient auth(GetSharedURLLoaderFactory()); auth.GetUserEmail("access_token", 1, &delegate); + FlushNetwork(); } TEST_F(GaiaOAuthClientTest, GetUserId) { MockGaiaOAuthClientDelegate delegate; EXPECT_CALL(delegate, OnGetUserIdResponse(kTestUserId)).Times(1); - MockOAuthFetcherFactory factory; - factory.set_results(kDummyUserIdResult); + ResponseInjector injector(&url_loader_factory_); + injector.set_results(kDummyUserIdResult); - GaiaOAuthClient auth(GetRequestContext()); + GaiaOAuthClient auth(GetSharedURLLoaderFactory()); auth.GetUserId("access_token", 1, &delegate); + FlushNetwork(); } TEST_F(GaiaOAuthClientTest, GetUserInfo) { @@ -385,11 +419,12 @@ EXPECT_CALL(delegate, OnGetUserInfoResponsePtr(_)) .WillOnce(SaveArg<0>(&captured_result)); - MockOAuthFetcherFactory factory; - factory.set_results(kDummyFullUserInfoResult); + ResponseInjector injector(&url_loader_factory_); + injector.set_results(kDummyFullUserInfoResult); - GaiaOAuthClient auth(GetRequestContext()); + GaiaOAuthClient auth(GetSharedURLLoaderFactory()); auth.GetUserInfo("access_token", 1, &delegate); + FlushNetwork(); std::unique_ptr<base::Value> value = base::JSONReader::Read(kDummyFullUserInfoResult); @@ -408,11 +443,12 @@ EXPECT_CALL(delegate, OnGetTokenInfoResponsePtr(_)) .WillOnce(SaveArg<0>(&captured_result)); - MockOAuthFetcherFactory factory; - factory.set_results(kDummyTokenInfoResult); + ResponseInjector injector(&url_loader_factory_); + injector.set_results(kDummyTokenInfoResult); - GaiaOAuthClient auth(GetRequestContext()); + GaiaOAuthClient auth(GetSharedURLLoaderFactory()); auth.GetTokenInfo("some_token", 1, &delegate); + FlushNetwork(); std::string issued_to; ASSERT_TRUE(captured_result->GetString("issued_to", &issued_to)); @@ -426,11 +462,12 @@ EXPECT_CALL(delegate, OnGetTokenInfoResponsePtr(_)) .WillOnce(SaveArg<0>(&captured_result)); - MockOAuthFetcherFactory factory; - factory.set_results(kDummyTokenHandleInfoResult); + ResponseInjector injector(&url_loader_factory_); + injector.set_results(kDummyTokenHandleInfoResult); - GaiaOAuthClient auth(GetRequestContext()); + GaiaOAuthClient auth(GetSharedURLLoaderFactory()); auth.GetTokenHandleInfo("some_handle", 1, &delegate); + FlushNetwork(); std::string audience; ASSERT_TRUE(captured_result->GetString("audience", &audience));
diff --git a/infra/config/global/cr-buildbucket.cfg b/infra/config/global/cr-buildbucket.cfg index b01f2546..dde7505 100644 --- a/infra/config/global/cr-buildbucket.cfg +++ b/infra/config/global/cr-buildbucket.cfg
@@ -739,6 +739,66 @@ } builders { + name: "android-cronet-arm-dbg" + mixins: "android-ci" + dimensions: "os:Ubuntu-14.04" + } + + builders { + name: "android-cronet-arm-rel" + mixins: "android-ci" + dimensions: "os:Ubuntu-14.04" + } + + builders { + name: "android-cronet-arm64-dbg" + mixins: "android-ci" + dimensions: "os:Ubuntu-14.04" + } + + builders { + name: "android-cronet-arm64-rel" + mixins: "android-ci" + dimensions: "os:Ubuntu-14.04" + } + + builders { + name: "android-cronet-asan-arm-rel" + mixins: "android-ci" + dimensions: "os:Ubuntu-14.04" + } + + builders { + name: "android-cronet-kitkat-arm-rel" + mixins: "android-ci" + dimensions: "os:Ubuntu-14.04" + } + + builders { + name: "android-cronet-lollipop-arm-rel" + mixins: "android-ci" + dimensions: "os:Ubuntu-14.04" + } + + builders { + name: "android-cronet-marshmallow-arm64-rel" + mixins: "android-ci" + dimensions: "os:Ubuntu-14.04" + } + + builders { + name: "android-cronet-x86-dbg" + mixins: "android-ci" + dimensions: "os:Ubuntu-14.04" + } + + builders { + name: "android-cronet-x86-rel" + mixins: "android-ci" + dimensions: "os:Ubuntu-14.04" + } + + builders { name: "android-kitkat-arm-rel" mixins: "android-ci" dimensions: "os:Ubuntu-14.04"
diff --git a/infra/config/global/luci-milo.cfg b/infra/config/global/luci-milo.cfg index df7281a9..397f4c0 100644 --- a/infra/config/global/luci-milo.cfg +++ b/infra/config/global/luci-milo.cfg
@@ -1534,6 +1534,55 @@ short_name: "dbg" } builders { + name: "buildbucket/luci.chromium.ci/android-cronet-arm-dbg" + category: "cronet|luci|arm" + short_name: "dbg" + } + builders { + name: "buildbucket/luci.chromium.ci/android-cronet-arm-rel" + category: "cronet|luci|arm" + short_name: "rel" + } + builders { + name: "buildbucket/luci.chromium.ci/android-cronet-arm64-dbg" + category: "cronet|luci|arm64" + short_name: "dbg" + } + builders { + name: "buildbucket/luci.chromium.ci/android-cronet-arm64-rel" + category: "cronet|luci|arm64" + short_name: "rel" + } + builders { + name: "buildbucket/luci.chromium.ci/android-cronet-asan-arm-rel" + category: "cronet|luci|asan" + } + builders { + name: "buildbucket/luci.chromium.ci/android-cronet-kitkat-arm-rel" + category: "cronet|luci|test" + short_name: "k" + } + builders { + name: "buildbucket/luci.chromium.ci/android-cronet-lollipop-arm-rel" + category: "cronet|luci|test" + short_name: "l" + } + builders { + name: "buildbucket/luci.chromium.ci/android-cronet-marshmallow-arm64-rel" + category: "cronet|luci|test" + short_name: "m" + } + builders { + name: "buildbucket/luci.chromium.ci/android-cronet-x86-dbg" + category: "cronet|luci|x86" + short_name: "dbg" + } + builders { + name: "buildbucket/luci.chromium.ci/android-cronet-x86-rel" + category: "cronet|luci|x86" + short_name: "rel" + } + builders { name: "buildbucket/luci.chromium.ci/Android arm Builder (dbg)" category: "builder|arm" short_name: "32"
diff --git a/infra/config/global/luci-scheduler.cfg b/infra/config/global/luci-scheduler.cfg index 6db45a2..7cb47dc 100644 --- a/infra/config/global/luci-scheduler.cfg +++ b/infra/config/global/luci-scheduler.cfg
@@ -205,6 +205,16 @@ triggers: "WinMSVC64 Goma Canary" triggers: "Windows Clang deterministic" triggers: "Windows deterministic" + triggers: "android-cronet-arm-dbg" + triggers: "android-cronet-arm-rel" + triggers: "android-cronet-arm64-dbg" + triggers: "android-cronet-arm64-rel" + triggers: "android-cronet-asan-arm-rel" + triggers: "android-cronet-kitkat-arm-rel" + triggers: "android-cronet-lollipop-arm-rel" + triggers: "android-cronet-marshmallow-arm64-rel" + triggers: "android-cronet-x86-dbg" + triggers: "android-cronet-x86-rel" triggers: "android-kitkat-arm-rel" triggers: "android-marshmallow-arm64-rel" triggers: "android-mojo-webview-rel" @@ -539,6 +549,116 @@ } job { + id: "android-cronet-arm-dbg" + acl_sets: "default" + buildbucket: { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "android-cronet-arm-dbg" + } +} + +job { + id: "android-cronet-arm-rel" + acl_sets: "default" + buildbucket: { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "android-cronet-arm-rel" + } +} + +job { + id: "android-cronet-arm64-dbg" + acl_sets: "default" + buildbucket: { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "android-cronet-arm64-dbg" + } +} + +job { + id: "android-cronet-arm64-rel" + acl_sets: "default" + buildbucket: { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "android-cronet-arm64-rel" + } +} + +job { + id: "android-cronet-asan-arm-rel" + acl_sets: "default" + buildbucket: { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "android-cronet-asan-arm-rel" + } +} + +job { + id: "android-cronet-kitkat-arm-rel" + acl_sets: "default" + buildbucket: { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "android-cronet-kitkat-arm-rel" + } +} + +job { + id: "android-cronet-lollipop-arm-rel" + acl_sets: "default" + buildbucket: { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "android-cronet-lollipop-arm-rel" + } +} + +job { + id: "android-cronet-marshmallow-arm64-rel" + acl_sets: "default" + buildbucket: { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "android-cronet-marshmallow-arm64-rel" + } +} + +job { + id: "android-cronet-x86-dbg" + acl_sets: "default" + buildbucket: { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "android-cronet-x86-dbg" + } +} + +job { + id: "android-cronet-x86-rel" + acl_sets: "default" + buildbucket: { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "android-cronet-x86-rel" + } +} + +job { + id: "android-kitkat-arm-rel" + acl_sets: "default" + buildbucket: { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "android-kitkat-arm-rel" + } +} + +job { id: "android-kitkat-arm-rel" acl_sets: "default" buildbucket: {
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd index 9193f5a..dc0ee53 100644 --- a/ios/chrome/app/strings/ios_strings.grd +++ b/ios/chrome/app/strings/ios_strings.grd
@@ -219,15 +219,6 @@ <message name="IDS_IOS_APP_LAUNCHER_OPEN_APP_BUTTON_LABEL" desc="Label of a button to open an application. [Length: 10em] [iOS only]"> Open </message> - <message name="IDS_IOS_AUTOFILL" desc="Title for the view in Settings for enabling/disabling Autofill. [Length: 15em] [iOS only]"> - Autofill Forms - </message> - <message name="IDS_IOS_ENABLE_AUTOFILL_PROFILES" desc="Title for the the toggle in Autofill Settings for enabling/disabling Autofill Addresses. Title case. [Length: unlimited] [iOS only]"> - Save and Fill Addresses - </message> - <message name="IDS_IOS_ENABLE_AUTOFILL_CREDIT_CARDS" desc="Title for the toggle in Autofill Settings for enabling/disabling Autofill Credit Cards. Title case. [Length: unlimited] [iOS only]"> - Save and Fill Credit Cards - </message> <message name="IDS_IOS_AUTOFILL_ACCNAME_HIDE_KEYBOARD" desc="The accessible name for the hide keyboard button in the keyboard accessory shown when filling out forms. [Length: unlimited] [iOS only]"> Hide keyboard </message> @@ -246,9 +237,6 @@ <message name="IDS_IOS_AUTOFILL_ADDRESS2" desc="Title of the field of a profile address representing the second line of the address. [Length: 15em] [iOS only]"> Address 2 </message> - <message name="IDS_IOS_AUTOFILL_ADDRESSES_GROUP_NAME" desc="The name of the Addresses group of the Autofill settings. Title case. [Length: 20em] [iOS only]"> - Addresses - </message> <message name="IDS_IOS_AUTOFILL_CARDHOLDER" desc="Title of the field representing the full name of a credit card holder. [Length: 15em] [iOS only]"> Name on Card </message> @@ -264,9 +252,6 @@ <message name="IDS_IOS_AUTOFILL_COUNTRY" desc="Title of the field of a profile address representing the country/nation of the address. [Length: 15em] [iOS only]"> Country </message> - <message name="IDS_IOS_AUTOFILL_CREDITCARDS_GROUP_NAME" desc="The name of the Credit Cards group of the Autofill dialog. Title case. [Length: 20em] [iOS only]"> - Credit Cards - </message> <message name="IDS_IOS_AUTOFILL_DIALOG_PLACEHOLDER_EXPIRY_MONTH" desc="The placeholder text for credit card expiration month in the payments card unmask dialog. [Length: 4em] [iOS only]"> MM </message>
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm b/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm index dc6cd67..ca92c95 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm
@@ -1380,17 +1380,17 @@ target:nil action:nil]; - // Set Select button. - titleString = l10n_util::GetNSString(IDS_IOS_BOOKMARK_CONTEXT_BAR_SELECT); - UIBarButtonItem* selectButton = + // Set Edit button. + titleString = l10n_util::GetNSString(IDS_IOS_BOOKMARK_CONTEXT_BAR_EDIT); + UIBarButtonItem* editButton = [[UIBarButtonItem alloc] initWithTitle:titleString style:UIBarButtonItemStylePlain target:self action:@selector(trailingButtonClicked)]; - selectButton.accessibilityIdentifier = kBookmarkHomeTrailingButtonIdentifier; - selectButton.enabled = [self hasBookmarksOrFolders]; + editButton.accessibilityIdentifier = kBookmarkHomeTrailingButtonIdentifier; + editButton.enabled = [self hasBookmarksOrFolders]; - [self setToolbarItems:@[ newFolderButton, spaceButton, selectButton ] + [self setToolbarItems:@[ newFolderButton, spaceButton, editButton ] animated:NO]; }
diff --git a/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm b/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm index 3e8c698c2..335c675 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm
@@ -1717,7 +1717,7 @@ } + (NSString*)contextBarSelectString { - return l10n_util::GetNSString(IDS_IOS_BOOKMARK_CONTEXT_BAR_SELECT); + return l10n_util::GetNSString(IDS_IOS_BOOKMARK_CONTEXT_BAR_EDIT); } + (NSString*)contextBarMoreString {
diff --git a/ios/chrome/browser/ui/settings/BUILD.gn b/ios/chrome/browser/ui/settings/BUILD.gn index 3939e7b8..11dd18f5 100644 --- a/ios/chrome/browser/ui/settings/BUILD.gn +++ b/ios/chrome/browser/ui/settings/BUILD.gn
@@ -9,13 +9,15 @@ "about_chrome_collection_view_controller.mm", "accounts_collection_view_controller.h", "accounts_collection_view_controller.mm", - "autofill_collection_view_controller.h", - "autofill_collection_view_controller.mm", + "autofill_credit_card_collection_view_controller.h", + "autofill_credit_card_collection_view_controller.mm", "autofill_credit_card_edit_collection_view_controller.h", "autofill_credit_card_edit_collection_view_controller.mm", "autofill_edit_collection_view_controller+protected.h", "autofill_edit_collection_view_controller.h", "autofill_edit_collection_view_controller.mm", + "autofill_profile_collection_view_controller.h", + "autofill_profile_collection_view_controller.mm", "autofill_profile_edit_collection_view_controller.h", "autofill_profile_edit_collection_view_controller.mm", "bandwidth_management_collection_view_controller.h", @@ -104,13 +106,14 @@ "resources:encryption_error", "resources:settings_about_chrome", "resources:settings_accounts_add_account", + "resources:settings_addresses", "resources:settings_article_suggestions", - "resources:settings_autofill_forms", "resources:settings_bandwidth", "resources:settings_content_settings", "resources:settings_debug", "resources:settings_error", "resources:settings_passwords", + "resources:settings_payment_methods", "resources:settings_privacy", "resources:settings_search_engine", "resources:settings_sync", @@ -263,7 +266,8 @@ testonly = true sources = [ "about_chrome_collection_view_controller_unittest.mm", - "autofill_collection_view_controller_unittest.mm", + "autofill_credit_card_collection_view_controller_unittest.mm", + "autofill_profile_collection_view_controller_unittest.mm", "autofill_profile_edit_collection_view_controller_unittest.mm", "bandwidth_management_collection_view_controller_unittest.mm", "block_popups_collection_view_controller_unittest.mm", @@ -365,7 +369,8 @@ testonly = true sources = [ "accounts_collection_egtest.mm", - "autofill_settings_egtest.mm", + "autofill_credit_card_settings_egtest.mm", + "autofill_profile_settings_egtest.mm", "block_popups_egtest.mm", "clear_browsing_data_egtest.mm", "passwords_settings_egtest.mm",
diff --git a/ios/chrome/browser/ui/settings/autofill_collection_view_controller.h b/ios/chrome/browser/ui/settings/autofill_credit_card_collection_view_controller.h similarity index 69% copy from ios/chrome/browser/ui/settings/autofill_collection_view_controller.h copy to ios/chrome/browser/ui/settings/autofill_credit_card_collection_view_controller.h index 1d192fd..edf12822 100644 --- a/ios/chrome/browser/ui/settings/autofill_collection_view_controller.h +++ b/ios/chrome/browser/ui/settings/autofill_credit_card_collection_view_controller.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_SETTINGS_AUTOFILL_COLLECTION_VIEW_CONTROLLER_H_ -#define IOS_CHROME_BROWSER_UI_SETTINGS_AUTOFILL_COLLECTION_VIEW_CONTROLLER_H_ +#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_AUTOFILL_CREDIT_CARD_COLLECTION_VIEW_CONTROLLER_H_ +#define IOS_CHROME_BROWSER_UI_SETTINGS_AUTOFILL_CREDIT_CARD_COLLECTION_VIEW_CONTROLLER_H_ #import "ios/chrome/browser/ui/settings/settings_root_collection_view_controller.h" @@ -12,7 +12,7 @@ } // namespace ios // The collection view for the Autofill settings. -@interface AutofillCollectionViewController +@interface AutofillCreditCardCollectionViewController : SettingsRootCollectionViewController // The designated initializer. |browserState| must not be nil. @@ -24,4 +24,4 @@ @end -#endif // IOS_CHROME_BROWSER_UI_SETTINGS_AUTOFILL_COLLECTION_VIEW_CONTROLLER_H_ +#endif // IOS_CHROME_BROWSER_UI_SETTINGS_AUTOFILL_CREDIT_CARD_COLLECTION_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/settings/autofill_collection_view_controller.mm b/ios/chrome/browser/ui/settings/autofill_credit_card_collection_view_controller.mm similarity index 61% copy from ios/chrome/browser/ui/settings/autofill_collection_view_controller.mm copy to ios/chrome/browser/ui/settings/autofill_credit_card_collection_view_controller.mm index bbd765f..a8a6c3a8 100644 --- a/ios/chrome/browser/ui/settings/autofill_collection_view_controller.mm +++ b/ios/chrome/browser/ui/settings/autofill_credit_card_collection_view_controller.mm
@@ -1,8 +1,8 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. +// Copyright 2018 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/ui/settings/autofill_collection_view_controller.h" +#import "ios/chrome/browser/ui/settings/autofill_credit_card_collection_view_controller.h" #include "base/logging.h" #include "base/mac/foundation_util.h" @@ -12,13 +12,13 @@ #import "components/autofill/ios/browser/credit_card_util.h" #import "components/autofill/ios/browser/personal_data_manager_observer_bridge.h" #include "components/prefs/pref_service.h" +#include "components/strings/grit/components_strings.h" #include "ios/chrome/browser/application_context.h" #include "ios/chrome/browser/autofill/personal_data_manager_factory.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #import "ios/chrome/browser/ui/collection_view/cells/MDCCollectionViewCell+Chrome.h" #import "ios/chrome/browser/ui/collection_view/collection_view_model.h" #import "ios/chrome/browser/ui/settings/autofill_credit_card_edit_collection_view_controller.h" -#import "ios/chrome/browser/ui/settings/autofill_profile_edit_collection_view_controller.h" #import "ios/chrome/browser/ui/settings/cells/autofill_data_item.h" #import "ios/chrome/browser/ui/settings/cells/settings_switch_item.h" #import "ios/chrome/browser/ui/settings/cells/settings_text_item.h" @@ -34,47 +34,40 @@ typedef NS_ENUM(NSInteger, SectionIdentifier) { SectionIdentifierSwitches = kSectionIdentifierEnumZero, - SectionIdentifierProfiles, SectionIdentifierCards, }; typedef NS_ENUM(NSInteger, ItemType) { - ItemTypeAutofillSwitch = kItemTypeEnumZero, - ItemTypeAutofillAddressSwitch, - ItemTypeAutofillCardSwitch, - ItemTypeAddress, + ItemTypeAutofillCardSwitch = kItemTypeEnumZero, ItemTypeCard, ItemTypeHeader, }; } // namespace -#pragma mark - AutofillCollectionViewController +#pragma mark - AutofillCreditCardCollectionViewController -@interface AutofillCollectionViewController ()<PersonalDataManagerObserver> { - std::string _locale; // User locale. +@interface AutofillCreditCardCollectionViewController ()< + PersonalDataManagerObserver> { autofill::PersonalDataManager* _personalDataManager; ios::ChromeBrowserState* _browserState; std::unique_ptr<autofill::PersonalDataManagerObserverBridge> _observer; - // Deleting profiles and credit cards updates PersonalDataManager resulting in - // an observer callback, which handles general data updates with a reloadData. + // Deleting credit cards updates PersonalDataManager resulting in an observer + // callback, which handles general data updates with a reloadData. // It is better to handle user-initiated changes with more specific actions // such as inserting or removing items/sections. This boolean is used to // stop the observer callback from acting on user-initiated changes. BOOL _deletionInProgress; } -@property(nonatomic, getter=isAutofillEnabled) BOOL autofillEnabled; -@property(nonatomic, getter=isAutofillProfileEnabled) - BOOL autofillProfileEnabled; @property(nonatomic, getter=isAutofillCreditCardEnabled) BOOL autofillCreditCardEnabled; @end -@implementation AutofillCollectionViewController +@implementation AutofillCreditCardCollectionViewController - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState { DCHECK(browserState); @@ -83,10 +76,9 @@ [super initWithLayout:layout style:CollectionViewControllerStyleAppBar]; if (self) { self.collectionViewAccessibilityIdentifier = @"kAutofillCollectionViewId"; - self.title = l10n_util::GetNSString(IDS_IOS_AUTOFILL); + self.title = l10n_util::GetNSString(IDS_AUTOFILL_PAYMENT_METHODS); self.shouldHideDoneButton = YES; _browserState = browserState; - _locale = GetApplicationContext()->GetApplicationLocale(); _personalDataManager = autofill::PersonalDataManagerFactory::GetForBrowserState(_browserState); _observer.reset(new autofill::PersonalDataManagerObserverBridge(self)); @@ -111,36 +103,14 @@ CollectionViewModel* model = self.collectionViewModel; [model addSectionWithIdentifier:SectionIdentifierSwitches]; - [model addItem:[self autofillSwitchItem] - toSectionWithIdentifier:SectionIdentifierSwitches]; - [model addItem:[self addressSwitchItem] - toSectionWithIdentifier:SectionIdentifierSwitches]; [model addItem:[self cardSwitchItem] toSectionWithIdentifier:SectionIdentifierSwitches]; - [self populateProfileSection]; [self populateCardSection]; } #pragma mark - LoadModel Helpers -// Populates profile section using personalDataManager. -- (void)populateProfileSection { - CollectionViewModel* model = self.collectionViewModel; - const std::vector<autofill::AutofillProfile*> autofillProfiles = - _personalDataManager->GetProfiles(); - if (!autofillProfiles.empty()) { - [model addSectionWithIdentifier:SectionIdentifierProfiles]; - [model setHeader:[self profileSectionHeader] - forSectionWithIdentifier:SectionIdentifierProfiles]; - for (autofill::AutofillProfile* autofillProfile : autofillProfiles) { - DCHECK(autofillProfile); - [model addItem:[self itemForProfile:*autofillProfile] - toSectionWithIdentifier:SectionIdentifierProfiles]; - } - } -} - // Populates card section using personalDataManager. - (void)populateCardSection { CollectionViewModel* model = self.collectionViewModel; @@ -158,43 +128,19 @@ } } -- (CollectionViewItem*)autofillSwitchItem { - SettingsSwitchItem* switchItem = - [[SettingsSwitchItem alloc] initWithType:ItemTypeAutofillSwitch]; - switchItem.text = l10n_util::GetNSString(IDS_IOS_AUTOFILL); - switchItem.on = [self isAutofillEnabled]; - switchItem.accessibilityIdentifier = @"autofillItem_switch"; - return switchItem; -} - -- (CollectionViewItem*)addressSwitchItem { - SettingsSwitchItem* switchItem = - [[SettingsSwitchItem alloc] initWithType:ItemTypeAutofillAddressSwitch]; - switchItem.text = l10n_util::GetNSString(IDS_IOS_ENABLE_AUTOFILL_PROFILES); - switchItem.on = [self isAutofillProfileEnabled]; - switchItem.accessibilityIdentifier = @"addressItem_switch"; - return switchItem; -} - - (CollectionViewItem*)cardSwitchItem { SettingsSwitchItem* switchItem = [[SettingsSwitchItem alloc] initWithType:ItemTypeAutofillCardSwitch]; switchItem.text = - l10n_util::GetNSString(IDS_IOS_ENABLE_AUTOFILL_CREDIT_CARDS); + l10n_util::GetNSString(IDS_AUTOFILL_ENABLE_CREDIT_CARDS_TOGGLE_LABEL); switchItem.on = [self isAutofillCreditCardEnabled]; switchItem.accessibilityIdentifier = @"cardItem_switch"; return switchItem; } -- (CollectionViewItem*)profileSectionHeader { - SettingsTextItem* header = [self genericHeader]; - header.text = l10n_util::GetNSString(IDS_IOS_AUTOFILL_ADDRESSES_GROUP_NAME); - return header; -} - - (CollectionViewItem*)cardSectionHeader { SettingsTextItem* header = [self genericHeader]; - header.text = l10n_util::GetNSString(IDS_IOS_AUTOFILL_CREDITCARDS_GROUP_NAME); + header.text = l10n_util::GetNSString(IDS_AUTOFILL_PAYMENT_METHODS); return header; } @@ -205,35 +151,11 @@ return header; } -- (CollectionViewItem*)itemForProfile: - (const autofill::AutofillProfile&)autofillProfile { - std::string guid(autofillProfile.guid()); - NSString* title = base::SysUTF16ToNSString(autofillProfile.GetInfo( - autofill::AutofillType(autofill::NAME_FULL), _locale)); - NSString* subTitle = base::SysUTF16ToNSString(autofillProfile.GetInfo( - autofill::AutofillType(autofill::ADDRESS_HOME_LINE1), _locale)); - bool isServerProfile = autofillProfile.record_type() == - autofill::AutofillProfile::SERVER_PROFILE; - - AutofillDataItem* item = - [[AutofillDataItem alloc] initWithType:ItemTypeAddress]; - item.text = title; - item.leadingDetailText = subTitle; - item.accessoryType = MDCCollectionViewCellAccessoryDisclosureIndicator; - item.accessibilityIdentifier = title; - item.GUID = guid; - item.deletable = !isServerProfile; - if (isServerProfile) { - item.trailingDetailText = - l10n_util::GetNSString(IDS_IOS_AUTOFILL_WALLET_SERVER_NAME); - } - return item; -} - - (CollectionViewItem*)itemForCreditCard: (const autofill::CreditCard&)creditCard { std::string guid(creditCard.guid()); - NSString* creditCardName = autofill::GetCreditCardName(creditCard, _locale); + NSString* creditCardName = autofill::GetCreditCardName( + creditCard, GetApplicationContext()->GetApplicationLocale()); AutofillDataItem* item = [[AutofillDataItem alloc] initWithType:ItemTypeCard]; item.text = creditCardName; @@ -249,9 +171,8 @@ return item; } -- (BOOL)localProfilesOrCreditCardsExist { - return !_personalDataManager->GetProfiles().empty() || - !_personalDataManager->GetLocalCreditCards().empty(); +- (BOOL)localCreditCardsExist { + return !_personalDataManager->GetLocalCreditCards().empty(); } #pragma mark - SettingsRootCollectionViewController @@ -261,7 +182,7 @@ } - (BOOL)editButtonEnabled { - return [self localProfilesOrCreditCardsExist]; + return [self localCreditCardsExist]; } #pragma mark - UICollectionViewDataSource @@ -273,54 +194,19 @@ ItemType itemType = static_cast<ItemType>( [self.collectionViewModel itemTypeForIndexPath:indexPath]); - - if (![cell isKindOfClass:[SettingsSwitchCell class]]) - return cell; - - SEL action = nil; - switch (itemType) { - case ItemTypeAutofillSwitch: - action = @selector(autofillSwitchChanged:); - break; - case ItemTypeAutofillAddressSwitch: - action = @selector(autofillAddressSwitchChanged:); - break; - case ItemTypeAutofillCardSwitch: - action = @selector(autofillCardSwitchChanged:); - break; - default: - NOTREACHED() << "Unknown Switch cell item type."; - break; + if (itemType == ItemTypeAutofillCardSwitch) { + SettingsSwitchCell* switchCell = + base::mac::ObjCCastStrict<SettingsSwitchCell>(cell); + [switchCell.switchView addTarget:self + action:@selector(autofillCardSwitchChanged:) + forControlEvents:UIControlEventValueChanged]; } - SettingsSwitchCell* switchCell = - base::mac::ObjCCastStrict<SettingsSwitchCell>(cell); - [switchCell.switchView addTarget:self - action:action - forControlEvents:UIControlEventValueChanged]; return cell; } #pragma mark - Switch Callbacks -- (void)autofillSwitchChanged:(UISwitch*)switchView { - BOOL switchIsOn = [switchView isOn]; - [self setSwitchItemOn:switchIsOn itemType:ItemTypeAutofillSwitch]; - [self setAutofillEnabled:switchIsOn]; - [self setSwitchItemEnabled:switchIsOn itemType:ItemTypeAutofillAddressSwitch]; - [self setSwitchItemEnabled:switchIsOn itemType:ItemTypeAutofillCardSwitch]; - if (switchIsOn) { - [self autofillAddressSwitchChanged:switchView]; - [self autofillCardSwitchChanged:switchView]; - } -} - -- (void)autofillAddressSwitchChanged:(UISwitch*)switchView { - [self setSwitchItemOn:[switchView isOn] - itemType:ItemTypeAutofillAddressSwitch]; - [self setAutofillProfileEnabled:[switchView isOn]]; -} - - (void)autofillCardSwitchChanged:(UISwitch*)switchView { [self setSwitchItemOn:[switchView isOn] itemType:ItemTypeAutofillCardSwitch]; [self setAutofillCreditCardEnabled:[switchView isOn]]; @@ -374,14 +260,7 @@ - (BOOL)collectionView:(UICollectionView*)collectionView hidesInkViewAtIndexPath:(NSIndexPath*)indexPath { NSInteger type = [self.collectionViewModel itemTypeForIndexPath:indexPath]; - switch (type) { - case ItemTypeAutofillSwitch: - case ItemTypeAutofillAddressSwitch: - case ItemTypeAutofillCardSwitch: - return YES; - default: - return NO; - } + return type == ItemTypeAutofillCardSwitch; } #pragma mark - UICollectionViewDelegate @@ -398,32 +277,18 @@ } CollectionViewModel* model = self.collectionViewModel; - SettingsRootCollectionViewController* controller; - switch ([model itemTypeForIndexPath:indexPath]) { - case ItemTypeAddress: { - const std::vector<autofill::AutofillProfile*> autofillProfiles = - _personalDataManager->GetProfiles(); - controller = [AutofillProfileEditCollectionViewController - controllerWithProfile:*autofillProfiles[indexPath.item] - personalDataManager:_personalDataManager]; - break; - } - case ItemTypeCard: { - const std::vector<autofill::CreditCard*>& creditCards = - _personalDataManager->GetCreditCards(); - controller = [[AutofillCreditCardEditCollectionViewController alloc] + NSInteger type = [model itemTypeForIndexPath:indexPath]; + if (type != ItemTypeCard) + return; + + const std::vector<autofill::CreditCard*>& creditCards = + _personalDataManager->GetCreditCards(); + AutofillCreditCardEditCollectionViewController* controller = + [[AutofillCreditCardEditCollectionViewController alloc] initWithCreditCard:*creditCards[indexPath.item] personalDataManager:_personalDataManager]; - break; - } - default: - break; - } - - if (controller) { - controller.dispatcher = self.dispatcher; - [self.navigationController pushViewController:controller animated:YES]; - } + controller.dispatcher = self.dispatcher; + [self.navigationController pushViewController:controller animated:YES]; } #pragma mark - MDCCollectionViewEditingDelegate @@ -435,16 +300,12 @@ - (void)collectionViewWillBeginEditing:(UICollectionView*)collectionView { [super collectionViewWillBeginEditing:collectionView]; - [self setSwitchItemEnabled:NO itemType:ItemTypeAutofillSwitch]; - [self setSwitchItemEnabled:NO itemType:ItemTypeAutofillAddressSwitch]; [self setSwitchItemEnabled:NO itemType:ItemTypeAutofillCardSwitch]; } - (void)collectionViewWillEndEditing:(UICollectionView*)collectionView { [super collectionViewWillEndEditing:collectionView]; - [self setSwitchItemEnabled:YES itemType:ItemTypeAutofillSwitch]; - [self setSwitchItemEnabled:YES itemType:ItemTypeAutofillAddressSwitch]; [self setSwitchItemEnabled:YES itemType:ItemTypeAutofillCardSwitch]; } @@ -481,7 +342,6 @@ return; // TODO(crbug.com/650390) Generalize removing empty sections - [self removeSectionIfEmptyForSectionWithIdentifier:SectionIdentifierProfiles]; [self removeSectionIfEmptyForSectionWithIdentifier:SectionIdentifierCards]; } @@ -497,10 +357,10 @@ [self.collectionViewModel sectionForSectionIdentifier:sectionIdentifier]; if ([self.collectionView numberOfItemsInSection:section] == 0) { // Avoid reference cycle in block. - __weak AutofillCollectionViewController* weakSelf = self; + __weak AutofillCreditCardCollectionViewController* weakSelf = self; [self.collectionView performBatchUpdates:^{ // Obtain strong reference again. - AutofillCollectionViewController* strongSelf = weakSelf; + AutofillCreditCardCollectionViewController* strongSelf = weakSelf; if (!strongSelf) { return; } @@ -513,13 +373,13 @@ } completion:^(BOOL finished) { // Obtain strong reference again. - AutofillCollectionViewController* strongSelf = weakSelf; + AutofillCreditCardCollectionViewController* strongSelf = weakSelf; if (!strongSelf) { return; } // Turn off edit mode if there is nothing to edit. - if (![strongSelf localProfilesOrCreditCardsExist] && + if (![strongSelf localCreditCardsExist] && [strongSelf.editor isEditing]) { [[strongSelf editor] setEditing:NO]; } @@ -535,7 +395,7 @@ if (_deletionInProgress) return; - if (![self localProfilesOrCreditCardsExist] && [self.editor isEditing]) { + if (![self localCreditCardsExist] && [self.editor isEditing]) { // Turn off edit mode if there exists nothing to edit. [self.editor setEditing:NO]; } @@ -546,24 +406,6 @@ #pragma mark - Getters and Setter -- (BOOL)isAutofillEnabled { - return autofill::prefs::IsAutofillEnabled(_browserState->GetPrefs()); -} - -- (void)setAutofillEnabled:(BOOL)isEnabled { - return autofill::prefs::SetAutofillEnabled(_browserState->GetPrefs(), - isEnabled); -} - -- (BOOL)isAutofillProfileEnabled { - return autofill::prefs::IsProfileAutofillEnabled(_browserState->GetPrefs()); -} - -- (void)setAutofillProfileEnabled:(BOOL)isEnabled { - return autofill::prefs::SetProfileAutofillEnabled(_browserState->GetPrefs(), - isEnabled); -} - - (BOOL)isAutofillCreditCardEnabled { return autofill::prefs::IsCreditCardAutofillEnabled( _browserState->GetPrefs());
diff --git a/ios/chrome/browser/ui/settings/autofill_credit_card_collection_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/autofill_credit_card_collection_view_controller_unittest.mm new file mode 100644 index 0000000..3072f85 --- /dev/null +++ b/ios/chrome/browser/ui/settings/autofill_credit_card_collection_view_controller_unittest.mm
@@ -0,0 +1,139 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/settings/autofill_credit_card_collection_view_controller.h" + +#include "base/guid.h" +#include "base/mac/foundation_util.h" +#include "base/strings/utf_string_conversions.h" +#import "base/test/ios/wait_util.h" +#include "components/autofill/core/browser/credit_card.h" +#include "components/autofill/core/browser/personal_data_manager.h" +#include "ios/chrome/browser/autofill/personal_data_manager_factory.h" +#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" +#import "ios/chrome/browser/ui/collection_view/collection_view_controller_test.h" +#include "ios/chrome/browser/ui/settings/personal_data_manager_data_changed_observer.h" +#include "ios/web/public/test/test_web_thread_bundle.h" +#include "testing/gtest/include/gtest/gtest.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@interface SettingsRootCollectionViewController (ExposedForTesting) +- (void)editButtonPressed; +@end + +namespace { + +class AutofillCreditCardCollectionViewControllerTest + : public CollectionViewControllerTest { + protected: + AutofillCreditCardCollectionViewControllerTest() { + TestChromeBrowserState::Builder test_cbs_builder; + chrome_browser_state_ = test_cbs_builder.Build(); + // Credit card import requires a PersonalDataManager which itself needs the + // WebDataService; this is not initialized on a TestChromeBrowserState by + // default. + chrome_browser_state_->CreateWebDataService(); + } + + CollectionViewController* InstantiateController() override { + return [[AutofillCreditCardCollectionViewController alloc] + initWithBrowserState:chrome_browser_state_.get()]; + } + + void AddCreditCard(const std::string& origin, + const std::string& card_holder_name, + const std::string& card_number) { + autofill::PersonalDataManager* personal_data_manager = + autofill::PersonalDataManagerFactory::GetForBrowserState( + chrome_browser_state_.get()); + PersonalDataManagerDataChangedObserver observer(personal_data_manager); + + autofill::CreditCard credit_card(base::GenerateGUID(), origin); + credit_card.SetRawInfo(autofill::CREDIT_CARD_NAME_FULL, + base::ASCIIToUTF16(card_holder_name)); + credit_card.SetRawInfo(autofill::CREDIT_CARD_NUMBER, + base::ASCIIToUTF16(card_number)); + personal_data_manager->OnAcceptedLocalCreditCardSave(credit_card); + observer.Wait(); // Wait for completion of the asynchronous operation. + } + + web::TestWebThreadBundle thread_bundle_; + std::unique_ptr<TestChromeBrowserState> chrome_browser_state_; +}; + +// Default test case of no addresses or credit cards. +TEST_F(AutofillCreditCardCollectionViewControllerTest, TestInitialization) { + CreateController(); + CheckController(); + + // Expect one header section. + EXPECT_EQ(1, NumberOfSections()); + // Expect header section to contain one row (the credit card Autofill toggle). + EXPECT_EQ(1, NumberOfItemsInSection(0)); +} + +// Adding a single credit card results in a credit card section. +TEST_F(AutofillCreditCardCollectionViewControllerTest, TestOneCreditCard) { + AddCreditCard("https://www.example.com/", "John Doe", "378282246310005"); + CreateController(); + CheckController(); + + // Expect two sections (header and credit cards section). + EXPECT_EQ(2, NumberOfSections()); + // Expect address section to contain one row (the credit card itself). + EXPECT_EQ(1, NumberOfItemsInSection(1)); +} + +// Deleting the only credit card results in item deletion and section deletion. +TEST_F(AutofillCreditCardCollectionViewControllerTest, + TestOneCreditCardItemDeleted) { + AddCreditCard("https://www.example.com/", "John Doe", "378282246310005"); + CreateController(); + CheckController(); + + // Expect two sections (header and credit cards section). + EXPECT_EQ(2, NumberOfSections()); + // Expect address section to contain one row (the credit card itself). + EXPECT_EQ(1, NumberOfItemsInSection(1)); + + AutofillCreditCardCollectionViewController* view_controller = + base::mac::ObjCCastStrict<AutofillCreditCardCollectionViewController>( + controller()); + // Put the collectionView in 'edit' mode. + [view_controller editButtonPressed]; + + // This is a bit of a shortcut, since actually clicking on the 'delete' + // button would be tough. + void (^delete_item_with_wait)(int, int) = ^(int i, int j) { + __block BOOL completion_called = NO; + this->DeleteItem(i, j, ^{ + completion_called = YES; + }); + EXPECT_TRUE(base::test::ios::WaitUntilConditionOrTimeout( + base::test::ios::kWaitForUIElementTimeout, ^bool() { + return completion_called; + })); + }; + + autofill::PersonalDataManager* personal_data_manager = + autofill::PersonalDataManagerFactory::GetForBrowserState( + chrome_browser_state_.get()); + PersonalDataManagerDataChangedObserver observer(personal_data_manager); + + // This call cause a modification of the PersonalDataManager, so wait until + // the asynchronous task complete in addition to waiting for the UI update. + delete_item_with_wait(1, 0); + observer.Wait(); // Wait for completion of the asynchronous operation. + + // Exit 'edit' mode. + [view_controller editButtonPressed]; + + // Expect one header section only. + EXPECT_EQ(1, NumberOfSections()); +} + +} // namespace
diff --git a/ios/chrome/browser/ui/settings/autofill_credit_card_settings_egtest.mm b/ios/chrome/browser/ui/settings/autofill_credit_card_settings_egtest.mm new file mode 100644 index 0000000..026fc43 --- /dev/null +++ b/ios/chrome/browser/ui/settings/autofill_credit_card_settings_egtest.mm
@@ -0,0 +1,224 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import <XCTest/XCTest.h> + +#import "base/test/ios/wait_util.h" +#include "components/autofill/core/browser/autofill_test_utils.h" +#include "components/autofill/core/browser/credit_card.h" +#include "components/autofill/core/browser/personal_data_manager.h" +#include "components/strings/grit/components_strings.h" +#include "ios/chrome/browser/autofill/personal_data_manager_factory.h" +#include "ios/chrome/browser/ui/tools_menu/public/tools_menu_constants.h" +#include "ios/chrome/grit/ios_strings.h" +#import "ios/chrome/test/app/chrome_test_util.h" +#import "ios/chrome/test/app/web_view_interaction_test_util.h" +#include "ios/chrome/test/earl_grey/accessibility_util.h" +#import "ios/chrome/test/earl_grey/chrome_actions.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" +#include "ui/base/l10n/l10n_util.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +using chrome_test_util::ButtonWithAccessibilityLabel; +using chrome_test_util::ButtonWithAccessibilityLabelId; +using chrome_test_util::NavigationBarDoneButton; +using chrome_test_util::SettingsDoneButton; +using chrome_test_util::SettingsMenuBackButton; + +namespace { + +// Expectation of how the saved Autofill credit card looks like, a map from cell +// name IDs to expected contents. +struct DisplayStringIDToExpectedResult { + int display_string_id; + NSString* expected_result; +}; + +const DisplayStringIDToExpectedResult kExpectedFields[] = { + {IDS_IOS_AUTOFILL_CARDHOLDER, @"Test User"}, + {IDS_IOS_AUTOFILL_CARD_NUMBER, @"4111111111111111"}, + {IDS_IOS_AUTOFILL_EXP_MONTH, @"11"}, + {IDS_IOS_AUTOFILL_EXP_YEAR, @"2022"}}; + +NSString* const kCreditCardLabel = + @"Test User, Visa ‪• • • • 1111‬"; + +} // namespace + +// Various tests for the Autofill credit cards section of the settings. +@interface AutofillCreditCardSettingsTestCase : ChromeTestCase +@end + +@implementation AutofillCreditCardSettingsTestCase { + // The PersonalDataManager instance for the current browser state. + autofill::PersonalDataManager* _personalDataManager; +} + +- (void)setUp { + [super setUp]; + + _personalDataManager = + autofill::PersonalDataManagerFactory::GetForBrowserState( + chrome_test_util::GetOriginalBrowserState()); + _personalDataManager->SetSyncingForTest(true); +} + +- (void)tearDown { + // Clear existing credit cards. + for (const auto* creditCard : _personalDataManager->GetCreditCards()) { + _personalDataManager->RemoveByGUID(creditCard->guid()); + } + + [super tearDown]; +} + +- (autofill::CreditCard)addCreditCard { + autofill::CreditCard creditCard = autofill::test::GetCreditCard(); + size_t creditCardCount = _personalDataManager->GetCreditCards().size(); + _personalDataManager->AddCreditCard(creditCard); + GREYAssert(base::test::ios::WaitUntilConditionOrTimeout( + base::test::ios::kWaitForActionTimeout, + ^bool() { + return creditCardCount < + _personalDataManager->GetCreditCards().size(); + }), + @"Failed to add credit card."); + return creditCard; +} + +// Helper to open the settings page for Autofill credit cards. +- (void)openCreditCardsSettings { + [ChromeEarlGreyUI openSettingsMenu]; + [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabel( + l10n_util::GetNSString( + IDS_AUTOFILL_PAYMENT_METHODS))] + performAction:grey_tap()]; +} + +// Helper to open the settings page for the Autofill credit card with |label|. +- (void)openEditCreditCard:(NSString*)label { + [self openCreditCardsSettings]; + + [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(label)] + performAction:grey_tap()]; +} + +// Close the settings. +- (void)exitSettingsMenu { + [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] + performAction:grey_tap()]; + [[EarlGrey selectElementWithMatcher:SettingsDoneButton()] + performAction:grey_tap()]; + // Wait for UI components to finish loading. + [[GREYUIThreadExecutor sharedInstance] drainUntilIdle]; +} + +// Test that the page for viewing Autofill credit card details is as expected. +- (void)testCreditCardViewPage { + autofill::CreditCard creditCard = [self addCreditCard]; + [self openEditCreditCard:kCreditCardLabel]; + + // Check that all fields and values match the expectations. + for (const DisplayStringIDToExpectedResult& expectation : kExpectedFields) { + [[EarlGrey selectElementWithMatcher: + grey_accessibilityLabel([NSString + stringWithFormat:@"%@, %@", + l10n_util::GetNSString( + expectation.display_string_id), + expectation.expected_result])] + assertWithMatcher:grey_notNil()]; + } + + // Go back to the list view page. + [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] + performAction:grey_tap()]; + + [self exitSettingsMenu]; +} + +// Test that the page for viewing Autofill credit card details is accessible. +- (void)testAccessibilityOnCreditCardViewPage { + autofill::CreditCard creditCard = [self addCreditCard]; + [self openEditCreditCard:kCreditCardLabel]; + + chrome_test_util::VerifyAccessibilityForCurrentScreen(); + + // Go back to the list view page. + [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] + performAction:grey_tap()]; + + [self exitSettingsMenu]; +} + +// Test that the page for editing Autofill credit card details is accessible. +- (void)testAccessibilityOnCreditCardEditPage { + autofill::CreditCard creditCard = [self addCreditCard]; + [self openEditCreditCard:kCreditCardLabel]; + + // Switch on edit mode. + [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabelId( + IDS_IOS_NAVIGATION_BAR_EDIT_BUTTON)] + performAction:grey_tap()]; + chrome_test_util::VerifyAccessibilityForCurrentScreen(); + + // Go back to the list view page. + [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] + performAction:grey_tap()]; + + [self exitSettingsMenu]; +} + +// Checks that the Autofill credit cards list view is in edit mode and the +// Autofill credit cards switch is disabled. +- (void)testListViewEditMode { + autofill::CreditCard creditCard = [self addCreditCard]; + [self openCreditCardsSettings]; + + // Switch on edit mode. + [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabelId( + IDS_IOS_NAVIGATION_BAR_EDIT_BUTTON)] + performAction:grey_tap()]; + + // Check the Autofill credit card switch is disabled. + [[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsSwitchCell( + @"cardItem_switch", YES, NO)] + assertWithMatcher:grey_notNil()]; + + [self exitSettingsMenu]; +} + +// Checks that the Autofill credit card switch can be toggled on/off and the +// list of Autofill credit cards is not affected by it. +- (void)testToggleCreditCardSwitch { + autofill::CreditCard creditCard = [self addCreditCard]; + [self openCreditCardsSettings]; + + // Toggle the Autofill credit cards switch off. + [[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsSwitchCell( + @"cardItem_switch", YES, YES)] + performAction:chrome_test_util::TurnSettingsSwitchOn(NO)]; + + // Expect Autofill credit cards to remain visible. + [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(kCreditCardLabel)] + assertWithMatcher:grey_notNil()]; + + // Toggle the Autofill credit cards switch back on. + [[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsSwitchCell( + @"cardItem_switch", NO, YES)] + performAction:chrome_test_util::TurnSettingsSwitchOn(YES)]; + + // Expect Autofill credit cards to remain visible. + [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(kCreditCardLabel)] + assertWithMatcher:grey_notNil()]; + + [self exitSettingsMenu]; +} + +@end
diff --git a/ios/chrome/browser/ui/settings/autofill_collection_view_controller.h b/ios/chrome/browser/ui/settings/autofill_profile_collection_view_controller.h similarity index 70% rename from ios/chrome/browser/ui/settings/autofill_collection_view_controller.h rename to ios/chrome/browser/ui/settings/autofill_profile_collection_view_controller.h index 1d192fd..16794cb 100644 --- a/ios/chrome/browser/ui/settings/autofill_collection_view_controller.h +++ b/ios/chrome/browser/ui/settings/autofill_profile_collection_view_controller.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_SETTINGS_AUTOFILL_COLLECTION_VIEW_CONTROLLER_H_ -#define IOS_CHROME_BROWSER_UI_SETTINGS_AUTOFILL_COLLECTION_VIEW_CONTROLLER_H_ +#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_AUTOFILL_PROFILE_COLLECTION_VIEW_CONTROLLER_H_ +#define IOS_CHROME_BROWSER_UI_SETTINGS_AUTOFILL_PROFILE_COLLECTION_VIEW_CONTROLLER_H_ #import "ios/chrome/browser/ui/settings/settings_root_collection_view_controller.h" @@ -12,7 +12,7 @@ } // namespace ios // The collection view for the Autofill settings. -@interface AutofillCollectionViewController +@interface AutofillProfileCollectionViewController : SettingsRootCollectionViewController // The designated initializer. |browserState| must not be nil. @@ -24,4 +24,4 @@ @end -#endif // IOS_CHROME_BROWSER_UI_SETTINGS_AUTOFILL_COLLECTION_VIEW_CONTROLLER_H_ +#endif // IOS_CHROME_BROWSER_UI_SETTINGS_AUTOFILL_PROFILE_COLLECTION_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/settings/autofill_collection_view_controller.mm b/ios/chrome/browser/ui/settings/autofill_profile_collection_view_controller.mm similarity index 62% rename from ios/chrome/browser/ui/settings/autofill_collection_view_controller.mm rename to ios/chrome/browser/ui/settings/autofill_profile_collection_view_controller.mm index bbd765f..2ad7f63e 100644 --- a/ios/chrome/browser/ui/settings/autofill_collection_view_controller.mm +++ b/ios/chrome/browser/ui/settings/autofill_profile_collection_view_controller.mm
@@ -2,22 +2,21 @@ // 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/settings/autofill_collection_view_controller.h" +#import "ios/chrome/browser/ui/settings/autofill_profile_collection_view_controller.h" #include "base/logging.h" #include "base/mac/foundation_util.h" #include "base/strings/sys_string_conversions.h" #include "components/autofill/core/browser/personal_data_manager.h" #include "components/autofill/core/common/autofill_prefs.h" -#import "components/autofill/ios/browser/credit_card_util.h" #import "components/autofill/ios/browser/personal_data_manager_observer_bridge.h" #include "components/prefs/pref_service.h" +#include "components/strings/grit/components_strings.h" #include "ios/chrome/browser/application_context.h" #include "ios/chrome/browser/autofill/personal_data_manager_factory.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #import "ios/chrome/browser/ui/collection_view/cells/MDCCollectionViewCell+Chrome.h" #import "ios/chrome/browser/ui/collection_view/collection_view_model.h" -#import "ios/chrome/browser/ui/settings/autofill_credit_card_edit_collection_view_controller.h" #import "ios/chrome/browser/ui/settings/autofill_profile_edit_collection_view_controller.h" #import "ios/chrome/browser/ui/settings/cells/autofill_data_item.h" #import "ios/chrome/browser/ui/settings/cells/settings_switch_item.h" @@ -35,46 +34,39 @@ typedef NS_ENUM(NSInteger, SectionIdentifier) { SectionIdentifierSwitches = kSectionIdentifierEnumZero, SectionIdentifierProfiles, - SectionIdentifierCards, }; typedef NS_ENUM(NSInteger, ItemType) { - ItemTypeAutofillSwitch = kItemTypeEnumZero, - ItemTypeAutofillAddressSwitch, - ItemTypeAutofillCardSwitch, + ItemTypeAutofillAddressSwitch = kItemTypeEnumZero, ItemTypeAddress, - ItemTypeCard, ItemTypeHeader, }; } // namespace -#pragma mark - AutofillCollectionViewController +#pragma mark - AutofillProfileCollectionViewController -@interface AutofillCollectionViewController ()<PersonalDataManagerObserver> { - std::string _locale; // User locale. +@interface AutofillProfileCollectionViewController ()< + PersonalDataManagerObserver> { autofill::PersonalDataManager* _personalDataManager; ios::ChromeBrowserState* _browserState; std::unique_ptr<autofill::PersonalDataManagerObserverBridge> _observer; - // Deleting profiles and credit cards updates PersonalDataManager resulting in - // an observer callback, which handles general data updates with a reloadData. + // Deleting profiles updates PersonalDataManager resulting in an observer + // callback, which handles general data updates with a reloadData. // It is better to handle user-initiated changes with more specific actions // such as inserting or removing items/sections. This boolean is used to // stop the observer callback from acting on user-initiated changes. BOOL _deletionInProgress; } -@property(nonatomic, getter=isAutofillEnabled) BOOL autofillEnabled; @property(nonatomic, getter=isAutofillProfileEnabled) BOOL autofillProfileEnabled; -@property(nonatomic, getter=isAutofillCreditCardEnabled) - BOOL autofillCreditCardEnabled; @end -@implementation AutofillCollectionViewController +@implementation AutofillProfileCollectionViewController - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState { DCHECK(browserState); @@ -83,10 +75,9 @@ [super initWithLayout:layout style:CollectionViewControllerStyleAppBar]; if (self) { self.collectionViewAccessibilityIdentifier = @"kAutofillCollectionViewId"; - self.title = l10n_util::GetNSString(IDS_IOS_AUTOFILL); + self.title = l10n_util::GetNSString(IDS_AUTOFILL_ADDRESSES); self.shouldHideDoneButton = YES; _browserState = browserState; - _locale = GetApplicationContext()->GetApplicationLocale(); _personalDataManager = autofill::PersonalDataManagerFactory::GetForBrowserState(_browserState); _observer.reset(new autofill::PersonalDataManagerObserverBridge(self)); @@ -111,15 +102,10 @@ CollectionViewModel* model = self.collectionViewModel; [model addSectionWithIdentifier:SectionIdentifierSwitches]; - [model addItem:[self autofillSwitchItem] - toSectionWithIdentifier:SectionIdentifierSwitches]; [model addItem:[self addressSwitchItem] toSectionWithIdentifier:SectionIdentifierSwitches]; - [model addItem:[self cardSwitchItem] - toSectionWithIdentifier:SectionIdentifierSwitches]; [self populateProfileSection]; - [self populateCardSection]; } #pragma mark - LoadModel Helpers @@ -141,60 +127,19 @@ } } -// Populates card section using personalDataManager. -- (void)populateCardSection { - CollectionViewModel* model = self.collectionViewModel; - const std::vector<autofill::CreditCard*>& creditCards = - _personalDataManager->GetCreditCards(); - if (!creditCards.empty()) { - [model addSectionWithIdentifier:SectionIdentifierCards]; - [model setHeader:[self cardSectionHeader] - forSectionWithIdentifier:SectionIdentifierCards]; - for (autofill::CreditCard* creditCard : creditCards) { - DCHECK(creditCard); - [model addItem:[self itemForCreditCard:*creditCard] - toSectionWithIdentifier:SectionIdentifierCards]; - } - } -} - -- (CollectionViewItem*)autofillSwitchItem { - SettingsSwitchItem* switchItem = - [[SettingsSwitchItem alloc] initWithType:ItemTypeAutofillSwitch]; - switchItem.text = l10n_util::GetNSString(IDS_IOS_AUTOFILL); - switchItem.on = [self isAutofillEnabled]; - switchItem.accessibilityIdentifier = @"autofillItem_switch"; - return switchItem; -} - - (CollectionViewItem*)addressSwitchItem { SettingsSwitchItem* switchItem = [[SettingsSwitchItem alloc] initWithType:ItemTypeAutofillAddressSwitch]; - switchItem.text = l10n_util::GetNSString(IDS_IOS_ENABLE_AUTOFILL_PROFILES); + switchItem.text = + l10n_util::GetNSString(IDS_AUTOFILL_ENABLE_PROFILES_TOGGLE_LABEL); switchItem.on = [self isAutofillProfileEnabled]; switchItem.accessibilityIdentifier = @"addressItem_switch"; return switchItem; } -- (CollectionViewItem*)cardSwitchItem { - SettingsSwitchItem* switchItem = - [[SettingsSwitchItem alloc] initWithType:ItemTypeAutofillCardSwitch]; - switchItem.text = - l10n_util::GetNSString(IDS_IOS_ENABLE_AUTOFILL_CREDIT_CARDS); - switchItem.on = [self isAutofillCreditCardEnabled]; - switchItem.accessibilityIdentifier = @"cardItem_switch"; - return switchItem; -} - - (CollectionViewItem*)profileSectionHeader { SettingsTextItem* header = [self genericHeader]; - header.text = l10n_util::GetNSString(IDS_IOS_AUTOFILL_ADDRESSES_GROUP_NAME); - return header; -} - -- (CollectionViewItem*)cardSectionHeader { - SettingsTextItem* header = [self genericHeader]; - header.text = l10n_util::GetNSString(IDS_IOS_AUTOFILL_CREDITCARDS_GROUP_NAME); + header.text = l10n_util::GetNSString(IDS_AUTOFILL_ADDRESSES); return header; } @@ -208,10 +153,12 @@ - (CollectionViewItem*)itemForProfile: (const autofill::AutofillProfile&)autofillProfile { std::string guid(autofillProfile.guid()); - NSString* title = base::SysUTF16ToNSString(autofillProfile.GetInfo( - autofill::AutofillType(autofill::NAME_FULL), _locale)); + NSString* title = base::SysUTF16ToNSString( + autofillProfile.GetInfo(autofill::AutofillType(autofill::NAME_FULL), + GetApplicationContext()->GetApplicationLocale())); NSString* subTitle = base::SysUTF16ToNSString(autofillProfile.GetInfo( - autofill::AutofillType(autofill::ADDRESS_HOME_LINE1), _locale)); + autofill::AutofillType(autofill::ADDRESS_HOME_LINE1), + GetApplicationContext()->GetApplicationLocale())); bool isServerProfile = autofillProfile.record_type() == autofill::AutofillProfile::SERVER_PROFILE; @@ -230,28 +177,8 @@ return item; } -- (CollectionViewItem*)itemForCreditCard: - (const autofill::CreditCard&)creditCard { - std::string guid(creditCard.guid()); - NSString* creditCardName = autofill::GetCreditCardName(creditCard, _locale); - - AutofillDataItem* item = [[AutofillDataItem alloc] initWithType:ItemTypeCard]; - item.text = creditCardName; - item.leadingDetailText = autofill::GetCreditCardObfuscatedNumber(creditCard); - item.accessoryType = MDCCollectionViewCellAccessoryDisclosureIndicator; - item.accessibilityIdentifier = creditCardName; - item.deletable = autofill::IsCreditCardLocal(creditCard); - item.GUID = guid; - if (![item isDeletable]) { - item.trailingDetailText = - l10n_util::GetNSString(IDS_IOS_AUTOFILL_WALLET_SERVER_NAME); - } - return item; -} - -- (BOOL)localProfilesOrCreditCardsExist { - return !_personalDataManager->GetProfiles().empty() || - !_personalDataManager->GetLocalCreditCards().empty(); +- (BOOL)localProfilesExist { + return !_personalDataManager->GetProfiles().empty(); } #pragma mark - SettingsRootCollectionViewController @@ -261,7 +188,7 @@ } - (BOOL)editButtonEnabled { - return [self localProfilesOrCreditCardsExist]; + return [self localProfilesExist]; } #pragma mark - UICollectionViewDataSource @@ -273,59 +200,25 @@ ItemType itemType = static_cast<ItemType>( [self.collectionViewModel itemTypeForIndexPath:indexPath]); - - if (![cell isKindOfClass:[SettingsSwitchCell class]]) - return cell; - - SEL action = nil; - switch (itemType) { - case ItemTypeAutofillSwitch: - action = @selector(autofillSwitchChanged:); - break; - case ItemTypeAutofillAddressSwitch: - action = @selector(autofillAddressSwitchChanged:); - break; - case ItemTypeAutofillCardSwitch: - action = @selector(autofillCardSwitchChanged:); - break; - default: - NOTREACHED() << "Unknown Switch cell item type."; - break; + if (itemType == ItemTypeAutofillAddressSwitch) { + SettingsSwitchCell* switchCell = + base::mac::ObjCCastStrict<SettingsSwitchCell>(cell); + [switchCell.switchView addTarget:self + action:@selector(autofillAddressSwitchChanged:) + forControlEvents:UIControlEventValueChanged]; } - SettingsSwitchCell* switchCell = - base::mac::ObjCCastStrict<SettingsSwitchCell>(cell); - [switchCell.switchView addTarget:self - action:action - forControlEvents:UIControlEventValueChanged]; return cell; } #pragma mark - Switch Callbacks -- (void)autofillSwitchChanged:(UISwitch*)switchView { - BOOL switchIsOn = [switchView isOn]; - [self setSwitchItemOn:switchIsOn itemType:ItemTypeAutofillSwitch]; - [self setAutofillEnabled:switchIsOn]; - [self setSwitchItemEnabled:switchIsOn itemType:ItemTypeAutofillAddressSwitch]; - [self setSwitchItemEnabled:switchIsOn itemType:ItemTypeAutofillCardSwitch]; - if (switchIsOn) { - [self autofillAddressSwitchChanged:switchView]; - [self autofillCardSwitchChanged:switchView]; - } -} - - (void)autofillAddressSwitchChanged:(UISwitch*)switchView { [self setSwitchItemOn:[switchView isOn] itemType:ItemTypeAutofillAddressSwitch]; [self setAutofillProfileEnabled:[switchView isOn]]; } -- (void)autofillCardSwitchChanged:(UISwitch*)switchView { - [self setSwitchItemOn:[switchView isOn] itemType:ItemTypeAutofillCardSwitch]; - [self setAutofillCreditCardEnabled:[switchView isOn]]; -} - #pragma mark - Switch Helpers // Sets switchItem's state to |on|. It is important that there is only one item @@ -374,14 +267,7 @@ - (BOOL)collectionView:(UICollectionView*)collectionView hidesInkViewAtIndexPath:(NSIndexPath*)indexPath { NSInteger type = [self.collectionViewModel itemTypeForIndexPath:indexPath]; - switch (type) { - case ItemTypeAutofillSwitch: - case ItemTypeAutofillAddressSwitch: - case ItemTypeAutofillCardSwitch: - return YES; - default: - return NO; - } + return type == ItemTypeAutofillAddressSwitch; } #pragma mark - UICollectionViewDelegate @@ -398,32 +284,17 @@ } CollectionViewModel* model = self.collectionViewModel; - SettingsRootCollectionViewController* controller; - switch ([model itemTypeForIndexPath:indexPath]) { - case ItemTypeAddress: { - const std::vector<autofill::AutofillProfile*> autofillProfiles = - _personalDataManager->GetProfiles(); - controller = [AutofillProfileEditCollectionViewController + if ([model itemTypeForIndexPath:indexPath] != ItemTypeAddress) + return; + + const std::vector<autofill::AutofillProfile*> autofillProfiles = + _personalDataManager->GetProfiles(); + AutofillProfileEditCollectionViewController* controller = + [AutofillProfileEditCollectionViewController controllerWithProfile:*autofillProfiles[indexPath.item] personalDataManager:_personalDataManager]; - break; - } - case ItemTypeCard: { - const std::vector<autofill::CreditCard*>& creditCards = - _personalDataManager->GetCreditCards(); - controller = [[AutofillCreditCardEditCollectionViewController alloc] - initWithCreditCard:*creditCards[indexPath.item] - personalDataManager:_personalDataManager]; - break; - } - default: - break; - } - - if (controller) { - controller.dispatcher = self.dispatcher; - [self.navigationController pushViewController:controller animated:YES]; - } + controller.dispatcher = self.dispatcher; + [self.navigationController pushViewController:controller animated:YES]; } #pragma mark - MDCCollectionViewEditingDelegate @@ -435,17 +306,13 @@ - (void)collectionViewWillBeginEditing:(UICollectionView*)collectionView { [super collectionViewWillBeginEditing:collectionView]; - [self setSwitchItemEnabled:NO itemType:ItemTypeAutofillSwitch]; [self setSwitchItemEnabled:NO itemType:ItemTypeAutofillAddressSwitch]; - [self setSwitchItemEnabled:NO itemType:ItemTypeAutofillCardSwitch]; } - (void)collectionViewWillEndEditing:(UICollectionView*)collectionView { [super collectionViewWillEndEditing:collectionView]; - [self setSwitchItemEnabled:YES itemType:ItemTypeAutofillSwitch]; [self setSwitchItemEnabled:YES itemType:ItemTypeAutofillAddressSwitch]; - [self setSwitchItemEnabled:YES itemType:ItemTypeAutofillCardSwitch]; } - (BOOL)collectionView:(UICollectionView*)collectionView @@ -482,7 +349,6 @@ // TODO(crbug.com/650390) Generalize removing empty sections [self removeSectionIfEmptyForSectionWithIdentifier:SectionIdentifierProfiles]; - [self removeSectionIfEmptyForSectionWithIdentifier:SectionIdentifierCards]; } // Remove the section from the model and collectionView if there are no more @@ -497,10 +363,10 @@ [self.collectionViewModel sectionForSectionIdentifier:sectionIdentifier]; if ([self.collectionView numberOfItemsInSection:section] == 0) { // Avoid reference cycle in block. - __weak AutofillCollectionViewController* weakSelf = self; + __weak AutofillProfileCollectionViewController* weakSelf = self; [self.collectionView performBatchUpdates:^{ // Obtain strong reference again. - AutofillCollectionViewController* strongSelf = weakSelf; + AutofillProfileCollectionViewController* strongSelf = weakSelf; if (!strongSelf) { return; } @@ -513,13 +379,13 @@ } completion:^(BOOL finished) { // Obtain strong reference again. - AutofillCollectionViewController* strongSelf = weakSelf; + AutofillProfileCollectionViewController* strongSelf = weakSelf; if (!strongSelf) { return; } // Turn off edit mode if there is nothing to edit. - if (![strongSelf localProfilesOrCreditCardsExist] && + if (![strongSelf localProfilesExist] && [strongSelf.editor isEditing]) { [[strongSelf editor] setEditing:NO]; } @@ -535,7 +401,7 @@ if (_deletionInProgress) return; - if (![self localProfilesOrCreditCardsExist] && [self.editor isEditing]) { + if (![self localProfilesExist] && [self.editor isEditing]) { // Turn off edit mode if there exists nothing to edit. [self.editor setEditing:NO]; } @@ -546,15 +412,6 @@ #pragma mark - Getters and Setter -- (BOOL)isAutofillEnabled { - return autofill::prefs::IsAutofillEnabled(_browserState->GetPrefs()); -} - -- (void)setAutofillEnabled:(BOOL)isEnabled { - return autofill::prefs::SetAutofillEnabled(_browserState->GetPrefs(), - isEnabled); -} - - (BOOL)isAutofillProfileEnabled { return autofill::prefs::IsProfileAutofillEnabled(_browserState->GetPrefs()); } @@ -564,14 +421,4 @@ isEnabled); } -- (BOOL)isAutofillCreditCardEnabled { - return autofill::prefs::IsCreditCardAutofillEnabled( - _browserState->GetPrefs()); -} - -- (void)setAutofillCreditCardEnabled:(BOOL)isEnabled { - return autofill::prefs::SetCreditCardAutofillEnabled( - _browserState->GetPrefs(), isEnabled); -} - @end
diff --git a/ios/chrome/browser/ui/settings/autofill_collection_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/autofill_profile_collection_view_controller_unittest.mm similarity index 64% rename from ios/chrome/browser/ui/settings/autofill_collection_view_controller_unittest.mm rename to ios/chrome/browser/ui/settings/autofill_profile_collection_view_controller_unittest.mm index fefccb4..59166596 100644 --- a/ios/chrome/browser/ui/settings/autofill_collection_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/settings/autofill_profile_collection_view_controller_unittest.mm
@@ -2,14 +2,13 @@ // 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/settings/autofill_collection_view_controller.h" +#import "ios/chrome/browser/ui/settings/autofill_profile_collection_view_controller.h" #include "base/guid.h" #include "base/mac/foundation_util.h" #include "base/strings/utf_string_conversions.h" #import "base/test/ios/wait_util.h" #include "components/autofill/core/browser/autofill_profile.h" -#include "components/autofill/core/browser/credit_card.h" #include "components/autofill/core/browser/personal_data_manager.h" #include "ios/chrome/browser/autofill/personal_data_manager_factory.h" #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" @@ -28,10 +27,10 @@ namespace { -class AutofillCollectionViewControllerTest +class AutofillProfileCollectionViewControllerTest : public CollectionViewControllerTest { protected: - AutofillCollectionViewControllerTest() { + AutofillProfileCollectionViewControllerTest() { TestChromeBrowserState::Builder test_cbs_builder; chrome_browser_state_ = test_cbs_builder.Build(); // Profile import requires a PersonalDataManager which itself needs the @@ -41,7 +40,7 @@ } CollectionViewController* InstantiateController() override { - return [[AutofillCollectionViewController alloc] + return [[AutofillProfileCollectionViewController alloc] initWithBrowserState:chrome_browser_state_.get()]; } @@ -65,67 +64,43 @@ std::unique_ptr<TestChromeBrowserState> chrome_browser_state_; }; -// Default test case of no addresses or credit cards. -TEST_F(AutofillCollectionViewControllerTest, TestInitialization) { +// Default test case of no addresses. +TEST_F(AutofillProfileCollectionViewControllerTest, TestInitialization) { CreateController(); CheckController(); // Expect one header section. EXPECT_EQ(1, NumberOfSections()); - // Expect header section to contain three rows. - EXPECT_EQ(3, NumberOfItemsInSection(0)); + // Expect header section to contain one row (the address Autofill toggle). + EXPECT_EQ(1, NumberOfItemsInSection(0)); } // Adding a single address results in an address section. -TEST_F(AutofillCollectionViewControllerTest, TestOneProfile) { +TEST_F(AutofillProfileCollectionViewControllerTest, TestOneProfile) { AddProfile("https://www.example.com/", "John Doe", "1 Main Street"); CreateController(); + CheckController(); + // Expect two sections (header and addresses section). EXPECT_EQ(2, NumberOfSections()); - // Expect header section to contain three rows. - EXPECT_EQ(3, NumberOfItemsInSection(0)); - // Expect address section to contain 1 row (the address itself). - EXPECT_EQ(1, NumberOfItemsInSection(1)); -} - -// Adding a single credit card results in a credit card section. -TEST_F(AutofillCollectionViewControllerTest, TestOneCreditCard) { - autofill::PersonalDataManager* personal_data_manager = - autofill::PersonalDataManagerFactory::GetForBrowserState( - chrome_browser_state_.get()); - PersonalDataManagerDataChangedObserver observer(personal_data_manager); - - autofill::CreditCard credit_card(base::GenerateGUID(), - "https://www.example.com/"); - credit_card.SetRawInfo(autofill::CREDIT_CARD_NAME_FULL, - base::ASCIIToUTF16("Alan Smithee")); - credit_card.SetRawInfo(autofill::CREDIT_CARD_NUMBER, - base::ASCIIToUTF16("378282246310005")); - personal_data_manager->OnAcceptedLocalCreditCardSave(credit_card); - observer.Wait(); // Wait for completion of the asynchronous operation. - - CreateController(); - // Expect two sections (header and credit card section). - EXPECT_EQ(2, NumberOfSections()); - // Expect header section to contain three rows. - EXPECT_EQ(3, NumberOfItemsInSection(0)); - // Expect credit card section to contain 1 row (the credit card itself). + // Expect address section to contain one row (the address itself). EXPECT_EQ(1, NumberOfItemsInSection(1)); } // Deleting the only profile results in item deletion and section deletion. -TEST_F(AutofillCollectionViewControllerTest, TestOneProfileItemDeleted) { +TEST_F(AutofillProfileCollectionViewControllerTest, TestOneProfileItemDeleted) { AddProfile("https://www.example.com/", "John Doe", "1 Main Street"); CreateController(); + CheckController(); + // Expect two sections (header and addresses section). EXPECT_EQ(2, NumberOfSections()); - // Expect header section to contain three rows. - EXPECT_EQ(3, NumberOfItemsInSection(0)); - // Expect address section to contain 1 row (the address itself). + // Expect address section to contain one row (the address itself). EXPECT_EQ(1, NumberOfItemsInSection(1)); - AutofillCollectionViewController* view_controller = - base::mac::ObjCCastStrict<AutofillCollectionViewController>(controller()); + AutofillProfileCollectionViewController* view_controller = + base::mac::ObjCCastStrict<AutofillProfileCollectionViewController>( + controller()); // Put the collectionView in 'edit' mode. [view_controller editButtonPressed]; @@ -155,11 +130,8 @@ // Exit 'edit' mode. [view_controller editButtonPressed]; - // Verify the resulting UI. - // Expect one header section. + // Expect one header section only. EXPECT_EQ(1, NumberOfSections()); - // Expect header section to contain three rows. - EXPECT_EQ(3, NumberOfItemsInSection(0)); } } // namespace
diff --git a/ios/chrome/browser/ui/settings/autofill_profile_settings_egtest.mm b/ios/chrome/browser/ui/settings/autofill_profile_settings_egtest.mm new file mode 100644 index 0000000..71121f91 --- /dev/null +++ b/ios/chrome/browser/ui/settings/autofill_profile_settings_egtest.mm
@@ -0,0 +1,298 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import <XCTest/XCTest.h> + +#import "base/test/ios/wait_util.h" +#include "components/autofill/core/browser/autofill_profile.h" +#include "components/autofill/core/browser/autofill_test_utils.h" +#include "components/autofill/core/browser/personal_data_manager.h" +#include "components/strings/grit/components_strings.h" +#include "ios/chrome/browser/autofill/personal_data_manager_factory.h" +#include "ios/chrome/browser/ui/tools_menu/public/tools_menu_constants.h" +#include "ios/chrome/grit/ios_strings.h" +#import "ios/chrome/test/app/chrome_test_util.h" +#import "ios/chrome/test/app/web_view_interaction_test_util.h" +#include "ios/chrome/test/earl_grey/accessibility_util.h" +#import "ios/chrome/test/earl_grey/chrome_actions.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" +#include "ui/base/l10n/l10n_util.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +using chrome_test_util::ButtonWithAccessibilityLabel; +using chrome_test_util::ButtonWithAccessibilityLabelId; +using chrome_test_util::NavigationBarDoneButton; +using chrome_test_util::SettingsDoneButton; +using chrome_test_util::SettingsMenuBackButton; + +namespace { + +// Expectation of how the saved Autofill profile looks like, a map from cell +// name IDs to expected contents. +struct DisplayStringIDToExpectedResult { + int display_string_id; + NSString* expected_result; +}; + +const DisplayStringIDToExpectedResult kExpectedFields[] = { + {IDS_IOS_AUTOFILL_FULLNAME, @"John H. Doe"}, + {IDS_IOS_AUTOFILL_COMPANY_NAME, @"Underworld"}, + {IDS_IOS_AUTOFILL_ADDRESS1, @"666 Erebus St."}, + {IDS_IOS_AUTOFILL_ADDRESS2, @"Apt 8"}, + {IDS_IOS_AUTOFILL_CITY, @"Elysium"}, + {IDS_IOS_AUTOFILL_STATE, @"CA"}, + {IDS_IOS_AUTOFILL_ZIP, @"91111"}, + {IDS_IOS_AUTOFILL_PHONE, @"16502111111"}, + {IDS_IOS_AUTOFILL_EMAIL, @"johndoe@hades.com"}}; + +NSString* const kProfileLabel = @"John H. Doe, 666 Erebus St."; + +// Expectation of how user-typed country names should be canonicalized. +struct UserTypedCountryExpectedResultPair { + NSString* user_typed_country; + NSString* expected_result; +}; + +const UserTypedCountryExpectedResultPair kCountryTests[] = { + {@"Brasil", @"Brazil"}, + {@"China", @"China"}, + {@"DEUTSCHLAND", @"Germany"}, + {@"GREAT BRITAIN", @"United Kingdom"}, + {@"IN", @"India"}, + {@"JaPaN", @"Japan"}, + {@"JP", @"Japan"}, + {@"Nigeria", @"Nigeria"}, + {@"TW", @"Taiwan"}, + {@"U.S.A.", @"United States"}, + {@"UK", @"United Kingdom"}, + {@"USA", @"United States"}, + {@"Nonexistia", @""}, +}; + +// Given a resource ID of a category of an Autofill profile, it returns a +// NSString consisting of the resource string concatenated with "_textField". +// This is the a11y ID of the text field corresponding to the category in the +// edit dialog of the Autofill profile. +NSString* GetTextFieldForID(int categoryId) { + return [NSString + stringWithFormat:@"%@_textField", l10n_util::GetNSString(categoryId)]; +} + +} // namespace + +// Various tests for the Autofill profiles section of the settings. +@interface AutofillProfileSettingsTestCase : ChromeTestCase +@end + +@implementation AutofillProfileSettingsTestCase { + // The PersonalDataManager instance for the current browser state. + autofill::PersonalDataManager* _personalDataManager; +} + +- (void)setUp { + [super setUp]; + + _personalDataManager = + autofill::PersonalDataManagerFactory::GetForBrowserState( + chrome_test_util::GetOriginalBrowserState()); + _personalDataManager->SetSyncingForTest(true); +} + +- (void)tearDown { + // Clear existing profiles. + for (const auto* profile : _personalDataManager->GetProfiles()) { + _personalDataManager->RemoveByGUID(profile->guid()); + } + + [super tearDown]; +} + +- (autofill::AutofillProfile)addAutofillProfile { + autofill::AutofillProfile profile = autofill::test::GetFullProfile(); + size_t profileCount = _personalDataManager->GetProfiles().size(); + _personalDataManager->AddProfile(profile); + GREYAssert(base::test::ios::WaitUntilConditionOrTimeout( + base::test::ios::kWaitForActionTimeout, + ^bool() { + return profileCount < + _personalDataManager->GetProfiles().size(); + }), + @"Failed to add profile."); + return profile; +} + +// Helper to open the settings page for Autofill profiles. +- (void)openAutofillProfilesSettings { + [ChromeEarlGreyUI openSettingsMenu]; + [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabel( + l10n_util::GetNSString( + IDS_AUTOFILL_ADDRESSES))] + performAction:grey_tap()]; +} + +// Helper to open the settings page for the Autofill profile with |label|. +- (void)openEditProfile:(NSString*)label { + [self openAutofillProfilesSettings]; + + [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(label)] + performAction:grey_tap()]; +} + +// Close the settings. +- (void)exitSettingsMenu { + [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] + performAction:grey_tap()]; + [[EarlGrey selectElementWithMatcher:SettingsDoneButton()] + performAction:grey_tap()]; + // Wait for UI components to finish loading. + [[GREYUIThreadExecutor sharedInstance] drainUntilIdle]; +} + +// Test that the page for viewing Autofill profile details is as expected. +- (void)testAutofillProfileViewPage { + autofill::AutofillProfile profile = [self addAutofillProfile]; + [self openEditProfile:kProfileLabel]; + + // Check that all fields and values match the expectations. + for (const DisplayStringIDToExpectedResult& expectation : kExpectedFields) { + [[EarlGrey selectElementWithMatcher: + grey_accessibilityLabel([NSString + stringWithFormat:@"%@, %@", + l10n_util::GetNSString( + expectation.display_string_id), + expectation.expected_result])] + assertWithMatcher:grey_notNil()]; + } + + // Go back to the list view page. + [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] + performAction:grey_tap()]; + + [self exitSettingsMenu]; +} + +// Test that editing country names is followed by validating the value and +// replacing it with a canonical one. +- (void)testAutofillProfileEditing { + autofill::AutofillProfile profile = [self addAutofillProfile]; + [self openEditProfile:kProfileLabel]; + + // Keep editing the Country field and verify that validation works. + for (const UserTypedCountryExpectedResultPair& expectation : kCountryTests) { + // Switch on edit mode. + [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabelId( + IDS_IOS_NAVIGATION_BAR_EDIT_BUTTON)] + performAction:grey_tap()]; + + // Replace the text field with the user-version of the country. + [[EarlGrey selectElementWithMatcher:grey_accessibilityID(GetTextFieldForID( + IDS_IOS_AUTOFILL_COUNTRY))] + performAction:grey_replaceText(expectation.user_typed_country)]; + + // Switch off edit mode. + [[EarlGrey selectElementWithMatcher:NavigationBarDoneButton()] + performAction:grey_tap()]; + + // Verify that the country value was changed to canonical. + [[EarlGrey selectElementWithMatcher: + grey_accessibilityLabel( + [NSString stringWithFormat:@"%@, %@", + l10n_util::GetNSString( + IDS_IOS_AUTOFILL_COUNTRY), + expectation.expected_result])] + assertWithMatcher:grey_notNil()]; + } + + // Go back to the list view page. + [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] + performAction:grey_tap()]; + + [self exitSettingsMenu]; +} + +// Test that the page for viewing Autofill profile details is accessible. +- (void)testAccessibilityOnAutofillProfileViewPage { + autofill::AutofillProfile profile = [self addAutofillProfile]; + [self openEditProfile:kProfileLabel]; + + chrome_test_util::VerifyAccessibilityForCurrentScreen(); + + // Go back to the list view page. + [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] + performAction:grey_tap()]; + + [self exitSettingsMenu]; +} + +// Test that the page for editing Autofill profile details is accessible. +- (void)testAccessibilityOnAutofillProfileEditPage { + autofill::AutofillProfile profile = [self addAutofillProfile]; + [self openEditProfile:kProfileLabel]; + + // Switch on edit mode. + [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabelId( + IDS_IOS_NAVIGATION_BAR_EDIT_BUTTON)] + performAction:grey_tap()]; + chrome_test_util::VerifyAccessibilityForCurrentScreen(); + + // Go back to the list view page. + [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] + performAction:grey_tap()]; + + [self exitSettingsMenu]; +} + +// Checks that the Autofill profiles list view is in edit mode and the Autofill +// profiles switch is disabled. +- (void)testListViewEditMode { + autofill::AutofillProfile profile = [self addAutofillProfile]; + [self openAutofillProfilesSettings]; + + // Switch on edit mode. + [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabelId( + IDS_IOS_NAVIGATION_BAR_EDIT_BUTTON)] + performAction:grey_tap()]; + + // Check the Autofill profile switch is disabled. + [[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsSwitchCell( + @"addressItem_switch", YES, NO)] + assertWithMatcher:grey_notNil()]; + + [self exitSettingsMenu]; +} + +// Checks that the Autofill profile switch can be toggled on/off and the list of +// Autofill profiles is not affected by it. +- (void)testToggleAutofillProfileSwitch { + autofill::AutofillProfile profile = [self addAutofillProfile]; + [self openAutofillProfilesSettings]; + + // Toggle the Autofill profiles switch off. + [[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsSwitchCell( + @"addressItem_switch", YES, YES)] + performAction:chrome_test_util::TurnSettingsSwitchOn(NO)]; + + // Expect Autofill profiles to remain visible. + [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(kProfileLabel)] + assertWithMatcher:grey_notNil()]; + + // Toggle the Autofill profiles switch back on. + [[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsSwitchCell( + @"addressItem_switch", NO, YES)] + performAction:chrome_test_util::TurnSettingsSwitchOn(YES)]; + + // Expect Autofill profiles to remain visible. + [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(kProfileLabel)] + assertWithMatcher:grey_notNil()]; + + [self exitSettingsMenu]; +} + +@end
diff --git a/ios/chrome/browser/ui/settings/autofill_settings_egtest.mm b/ios/chrome/browser/ui/settings/autofill_settings_egtest.mm deleted file mode 100644 index f8dc8fe..0000000 --- a/ios/chrome/browser/ui/settings/autofill_settings_egtest.mm +++ /dev/null
@@ -1,395 +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 <XCTest/XCTest.h> - -#import "base/test/ios/wait_util.h" -#include "components/autofill/core/browser/autofill_profile.h" -#include "components/autofill/core/browser/autofill_test_utils.h" -#include "components/autofill/core/browser/credit_card.h" -#include "components/autofill/core/browser/personal_data_manager.h" -#include "ios/chrome/browser/autofill/personal_data_manager_factory.h" -#include "ios/chrome/browser/ui/tools_menu/public/tools_menu_constants.h" -#include "ios/chrome/grit/ios_strings.h" -#import "ios/chrome/test/app/chrome_test_util.h" -#import "ios/chrome/test/app/web_view_interaction_test_util.h" -#include "ios/chrome/test/earl_grey/accessibility_util.h" -#import "ios/chrome/test/earl_grey/chrome_actions.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/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" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -using chrome_test_util::ButtonWithAccessibilityLabel; -using chrome_test_util::ButtonWithAccessibilityLabelId; -using chrome_test_util::NavigationBarDoneButton; -using chrome_test_util::SettingsDoneButton; -using chrome_test_util::SettingsMenuBackButton; - -namespace { - -// Expectation of how the saved autofill profile looks like, a map from cell -// name IDs to expected contents. -struct DisplayStringIDToExpectedResult { - int display_string_id; - NSString* expected_result; -}; - -const DisplayStringIDToExpectedResult kExpectedFields[] = { - {IDS_IOS_AUTOFILL_FULLNAME, @"John H. Doe"}, - {IDS_IOS_AUTOFILL_COMPANY_NAME, @"Underworld"}, - {IDS_IOS_AUTOFILL_ADDRESS1, @"666 Erebus St."}, - {IDS_IOS_AUTOFILL_ADDRESS2, @"Apt 8"}, - {IDS_IOS_AUTOFILL_CITY, @"Elysium"}, - {IDS_IOS_AUTOFILL_STATE, @"CA"}, - {IDS_IOS_AUTOFILL_ZIP, @"91111"}, - {IDS_IOS_AUTOFILL_PHONE, @"16502111111"}, - {IDS_IOS_AUTOFILL_EMAIL, @"johndoe@hades.com"}}; - -NSString* const kAddressLabel = @"John H. Doe, 666 Erebus St."; - -// Expectation of how user-typed country names should be canonicalized. -struct UserTypedCountryExpectedResultPair { - NSString* user_typed_country; - NSString* expected_result; -}; - -const UserTypedCountryExpectedResultPair kCountryTests[] = { - {@"Brasil", @"Brazil"}, - {@"China", @"China"}, - {@"DEUTSCHLAND", @"Germany"}, - {@"GREAT BRITAIN", @"United Kingdom"}, - {@"IN", @"India"}, - {@"JaPaN", @"Japan"}, - {@"JP", @"Japan"}, - {@"Nigeria", @"Nigeria"}, - {@"TW", @"Taiwan"}, - {@"U.S.A.", @"United States"}, - {@"UK", @"United Kingdom"}, - {@"USA", @"United States"}, - {@"Nonexistia", @""}, -}; - -// Given a resource ID of a category of an address profile, it returns a -// NSString consisting of the resource string concatenated with "_textField". -// This is the a11y ID of the text field corresponding to the category in the -// edit dialog of the address profile. -NSString* GetTextFieldForID(int categoryId) { - return [NSString - stringWithFormat:@"%@_textField", l10n_util::GetNSString(categoryId)]; -} - -} // namespace - -// Various tests for the Autofill section of the settings. -@interface AutofillSettingsTestCase : ChromeTestCase -@end - -@implementation AutofillSettingsTestCase { - // The PersonalDataManager instance for the current browser state. - autofill::PersonalDataManager* _personalDataManager; -} - -- (void)setUp { - [super setUp]; - - _personalDataManager = - autofill::PersonalDataManagerFactory::GetForBrowserState( - chrome_test_util::GetOriginalBrowserState()); - _personalDataManager->SetSyncingForTest(true); -} - -- (void)tearDown { - // Clear existing profiles and credit cards. - for (const auto* profile : _personalDataManager->GetProfiles()) { - _personalDataManager->RemoveByGUID(profile->guid()); - } - for (const auto* creditCard : _personalDataManager->GetCreditCards()) { - _personalDataManager->RemoveByGUID(creditCard->guid()); - } - - [super tearDown]; -} - -- (autofill::AutofillProfile)addAutofillProfile { - autofill::AutofillProfile profile = autofill::test::GetFullProfile(); - size_t profileCount = _personalDataManager->GetProfiles().size(); - _personalDataManager->AddProfile(profile); - GREYAssert(base::test::ios::WaitUntilConditionOrTimeout( - base::test::ios::kWaitForActionTimeout, - ^bool() { - return profileCount < - _personalDataManager->GetProfiles().size(); - }), - @"Failed to add profile."); - return profile; -} - -- (autofill::CreditCard)addCreditCard { - autofill::CreditCard creditCard = autofill::test::GetCreditCard(); // Visa. - size_t cardCount = _personalDataManager->GetCreditCards().size(); - _personalDataManager->AddCreditCard(creditCard); - GREYAssert(base::test::ios::WaitUntilConditionOrTimeout( - base::test::ios::kWaitForActionTimeout, - ^bool() { - return cardCount < - _personalDataManager->GetCreditCards().size(); - }), - @"Failed to add credit card."); - return creditCard; -} - -// Helper to open the settings page for the record with |address|. -- (void)openEditAddress:(NSString*)address { - // Go to Autofill Settings. - [ChromeEarlGreyUI openSettingsMenu]; - NSString* label = l10n_util::GetNSString(IDS_IOS_AUTOFILL); - [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabel(label)] - performAction:grey_tap()]; - - NSString* cellLabel = address; - [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(cellLabel)] - performAction:grey_tap()]; -} - -// Close the settings. -- (void)exitSettingsMenu { - [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] - performAction:grey_tap()]; - [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] - performAction:grey_tap()]; - [[EarlGrey selectElementWithMatcher:SettingsDoneButton()] - performAction:grey_tap()]; - // Wait for UI components to finish loading. - [[GREYUIThreadExecutor sharedInstance] drainUntilIdle]; -} - -// Test that the page for viewing autofill profile details is as expected. -- (void)testAutofillProfileViewPage { - autofill::AutofillProfile profile = [self addAutofillProfile]; - [self openEditAddress:kAddressLabel]; - - // Check that all fields and values match the expectations. - for (const DisplayStringIDToExpectedResult& expectation : kExpectedFields) { - [[EarlGrey - selectElementWithMatcher: - grey_accessibilityLabel([NSString - stringWithFormat:@"%@, %@", l10n_util::GetNSString( - expectation.display_string_id), - expectation.expected_result])] - assertWithMatcher:grey_notNil()]; - } - - [self exitSettingsMenu]; -} - -// Test that editing country names is followed by validating the value and -// replacing it with a canonical one. -- (void)testAutofillProfileEditing { - autofill::AutofillProfile profile = [self addAutofillProfile]; - [self openEditAddress:kAddressLabel]; - - // Keep editing the Country field and verify that validation works. - for (const UserTypedCountryExpectedResultPair& expectation : kCountryTests) { - // Switch on edit mode. - [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabelId( - IDS_IOS_NAVIGATION_BAR_EDIT_BUTTON)] - performAction:grey_tap()]; - - // Replace the text field with the user-version of the country. - [[EarlGrey selectElementWithMatcher:grey_accessibilityID(GetTextFieldForID( - IDS_IOS_AUTOFILL_COUNTRY))] - performAction:grey_replaceText(expectation.user_typed_country)]; - - // Switch off edit mode. - [[EarlGrey selectElementWithMatcher:NavigationBarDoneButton()] - performAction:grey_tap()]; - - // Verify that the country value was changed to canonical. - [[EarlGrey - selectElementWithMatcher: - grey_accessibilityLabel([NSString - stringWithFormat:@"%@, %@", l10n_util::GetNSString( - IDS_IOS_AUTOFILL_COUNTRY), - expectation.expected_result])] - assertWithMatcher:grey_notNil()]; - } - - [self exitSettingsMenu]; -} - -// Test that the page for viewing autofill profile details is accessible. -- (void)testAccessibilityOnAutofillProfileViewPage { - autofill::AutofillProfile profile = [self addAutofillProfile]; - [self openEditAddress:kAddressLabel]; - - chrome_test_util::VerifyAccessibilityForCurrentScreen(); - - [self exitSettingsMenu]; -} - -// Test that the page for editing autofill profile details is accessible. -- (void)testAccessibilityOnAutofillProfileEditPage { - autofill::AutofillProfile profile = [self addAutofillProfile]; - [self openEditAddress:kAddressLabel]; - - // Switch on edit mode. - [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabelId( - IDS_IOS_NAVIGATION_BAR_EDIT_BUTTON)] - performAction:grey_tap()]; - chrome_test_util::VerifyAccessibilityForCurrentScreen(); - - [self exitSettingsMenu]; -} - -// Checks that if the autofill profiles and credit cards list view is in edit -// mode, the Autofill, address, and credit card switches are disabled. -- (void)testListViewEditMode { - autofill::AutofillProfile profile = [self addAutofillProfile]; - autofill::CreditCard creditCard = [self addCreditCard]; - - // Go to Autofill Settings. - [ChromeEarlGreyUI openSettingsMenu]; - [[EarlGrey - selectElementWithMatcher:ButtonWithAccessibilityLabel( - l10n_util::GetNSString(IDS_IOS_AUTOFILL))] - performAction:grey_tap()]; - - // Switch on edit mode. - [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabelId( - IDS_IOS_NAVIGATION_BAR_EDIT_BUTTON)] - performAction:grey_tap()]; - - // Check the Autofill, address, and credit card switches are disabled. - [[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsSwitchCell( - @"autofillItem_switch", YES, NO)] - assertWithMatcher:grey_notNil()]; - [[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsSwitchCell( - @"addressItem_switch", YES, NO)] - assertWithMatcher:grey_notNil()]; - [[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsSwitchCell( - @"cardItem_switch", YES, NO)] - assertWithMatcher:grey_notNil()]; -} - -// Checks that the autofill address switch can be toggled on/off independently -// and the list of autofill profiles is not affected by it. -- (void)testToggleAutofillAddressSwitch { - autofill::AutofillProfile profile = [self addAutofillProfile]; - - // Go to Autofill Settings. - [ChromeEarlGreyUI openSettingsMenu]; - [[EarlGrey - selectElementWithMatcher:ButtonWithAccessibilityLabel( - l10n_util::GetNSString(IDS_IOS_AUTOFILL))] - performAction:grey_tap()]; - - // Toggle the Autofill address switch off. - [[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsSwitchCell( - @"addressItem_switch", YES, YES)] - performAction:chrome_test_util::TurnSettingsSwitchOn(NO)]; - - // Expect Autofill profiles to remain visible. - [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel( - @"John H. Doe, 666 Erebus St.")] - assertWithMatcher:grey_notNil()]; - - // Toggle the Autofill address switch back on. - [[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsSwitchCell( - @"addressItem_switch", NO, YES)] - performAction:chrome_test_util::TurnSettingsSwitchOn(YES)]; - - // Expect Autofill profiles to remain visible. - [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel( - @"John H. Doe, 666 Erebus St.")] - assertWithMatcher:grey_notNil()]; -} - -// Checks that the autofill credit card switch can be toggled on/off -// independently and the list of autofill credit cards is not affected by it. -- (void)testToggleAutofillCreditCardSwitch { - autofill::CreditCard creditCard = [self addCreditCard]; - - // Go to Autofill Settings. - [ChromeEarlGreyUI openSettingsMenu]; - [[EarlGrey - selectElementWithMatcher:ButtonWithAccessibilityLabel( - l10n_util::GetNSString(IDS_IOS_AUTOFILL))] - performAction:grey_tap()]; - - // Toggle the Autofill credit card switch off. - [[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsSwitchCell( - @"cardItem_switch", YES, YES)] - performAction:chrome_test_util::TurnSettingsSwitchOn(NO)]; - - // Expect Autofill credit cards to remain visible. - [[EarlGrey selectElementWithMatcher: - grey_accessibilityLabel( - @"Test User, Visa ‪• • • • 1111‬")] - assertWithMatcher:grey_notNil()]; - - // Toggle the Autofill credit card switch back on. - [[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsSwitchCell( - @"cardItem_switch", NO, YES)] - performAction:chrome_test_util::TurnSettingsSwitchOn(YES)]; - - // Expect Autofill credit cards to remain visible. - [[EarlGrey selectElementWithMatcher: - grey_accessibilityLabel( - @"Test User, Visa ‪• • • • 1111‬")] - assertWithMatcher:grey_notNil()]; -} - -// Tests that toggling the Autofill switch on and off disables and enables the -// Autofill address and credit card switches respectively and that the list of -// autofill addresses and credit cards is not affected by it. -- (void)testToggleAutofillSwitches { - autofill::AutofillProfile profile = [self addAutofillProfile]; - autofill::CreditCard creditCard = [self addCreditCard]; - - // Go to Autofill Settings. - [ChromeEarlGreyUI openSettingsMenu]; - [[EarlGrey - selectElementWithMatcher:ButtonWithAccessibilityLabel( - l10n_util::GetNSString(IDS_IOS_AUTOFILL))] - performAction:grey_tap()]; - - // Toggle the Autofill switch off and back on. - for (BOOL expectedState : {YES, NO}) { - // Toggle the Autofill switch. - [[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsSwitchCell( - @"autofillItem_switch", - expectedState, YES)] - performAction:chrome_test_util::TurnSettingsSwitchOn(!expectedState)]; - - // Expect address and credit card switches to be off when Autofill toggle is - // off and on when Autofill toggle is on. - [[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsSwitchCell( - @"addressItem_switch", - !expectedState, YES)] - assertWithMatcher:grey_notNil()]; - [[EarlGrey - selectElementWithMatcher:chrome_test_util::SettingsSwitchCell( - @"cardItem_switch", !expectedState, YES)] - assertWithMatcher:grey_notNil()]; - - // Expect Autofill addresses and credit cards to remain visible. - [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel( - @"John H. Doe, 666 Erebus St.")] - assertWithMatcher:grey_notNil()]; - [[EarlGrey selectElementWithMatcher: - grey_accessibilityLabel( - @"Test User, Visa ‪• • • • 1111‬")] - assertWithMatcher:grey_notNil()]; - } -} - -@end
diff --git a/ios/chrome/browser/ui/settings/resources/BUILD.gn b/ios/chrome/browser/ui/settings/resources/BUILD.gn index da19098..2a00f0e6 100644 --- a/ios/chrome/browser/ui/settings/resources/BUILD.gn +++ b/ios/chrome/browser/ui/settings/resources/BUILD.gn
@@ -67,15 +67,6 @@ ] } -imageset("settings_autofill_forms") { - sources = [ - "settings_autofill_forms.imageset/Contents.json", - "settings_autofill_forms.imageset/settings_autofill_forms.png", - "settings_autofill_forms.imageset/settings_autofill_forms@2x.png", - "settings_autofill_forms.imageset/settings_autofill_forms@3x.png", - ] -} - imageset("settings_bandwidth") { sources = [ "settings_bandwidth.imageset/Contents.json", @@ -112,6 +103,24 @@ ] } +imageset("settings_payment_methods") { + sources = [ + "settings_payment_methods.imageset/Contents.json", + "settings_payment_methods.imageset/payment_methods.png", + "settings_payment_methods.imageset/payment_methods@2x.png", + "settings_payment_methods.imageset/payment_methods@3x.png", + ] +} + +imageset("settings_addresses") { + sources = [ + "settings_addresses.imageset/Contents.json", + "settings_addresses.imageset/addresses.png", + "settings_addresses.imageset/addresses@2x.png", + "settings_addresses.imageset/addresses@3x.png", + ] +} + imageset("settings_privacy") { sources = [ "settings_privacy.imageset/Contents.json",
diff --git a/ios/chrome/browser/ui/settings/resources/settings_autofill_forms.imageset/Contents.json b/ios/chrome/browser/ui/settings/resources/settings_addresses.imageset/Contents.json similarity index 66% rename from ios/chrome/browser/ui/settings/resources/settings_autofill_forms.imageset/Contents.json rename to ios/chrome/browser/ui/settings/resources/settings_addresses.imageset/Contents.json index 248316be..5738db13 100644 --- a/ios/chrome/browser/ui/settings/resources/settings_autofill_forms.imageset/Contents.json +++ b/ios/chrome/browser/ui/settings/resources/settings_addresses.imageset/Contents.json
@@ -3,21 +3,21 @@ { "idiom": "universal", "scale": "1x", - "filename": "settings_autofill_forms.png" + "filename": "addresses.png" }, { "idiom": "universal", "scale": "2x", - "filename": "settings_autofill_forms@2x.png" + "filename": "addresses@2x.png" }, { "idiom": "universal", "scale": "3x", - "filename": "settings_autofill_forms@3x.png" + "filename": "addresses@3x.png" } ], "info": { "version": 1, "author": "xcode" } -} +} \ No newline at end of file
diff --git a/ios/chrome/browser/ui/settings/resources/settings_addresses.imageset/addresses.png b/ios/chrome/browser/ui/settings/resources/settings_addresses.imageset/addresses.png new file mode 100644 index 0000000..fc1fb7a --- /dev/null +++ b/ios/chrome/browser/ui/settings/resources/settings_addresses.imageset/addresses.png Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_addresses.imageset/addresses@2x.png b/ios/chrome/browser/ui/settings/resources/settings_addresses.imageset/addresses@2x.png new file mode 100644 index 0000000..6924e8f8 --- /dev/null +++ b/ios/chrome/browser/ui/settings/resources/settings_addresses.imageset/addresses@2x.png Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_addresses.imageset/addresses@3x.png b/ios/chrome/browser/ui/settings/resources/settings_addresses.imageset/addresses@3x.png new file mode 100644 index 0000000..eda1d38 --- /dev/null +++ b/ios/chrome/browser/ui/settings/resources/settings_addresses.imageset/addresses@3x.png Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_autofill_forms.imageset/settings_autofill_forms.png b/ios/chrome/browser/ui/settings/resources/settings_autofill_forms.imageset/settings_autofill_forms.png deleted file mode 100644 index 5b5fb84..0000000 --- a/ios/chrome/browser/ui/settings/resources/settings_autofill_forms.imageset/settings_autofill_forms.png +++ /dev/null Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_autofill_forms.imageset/settings_autofill_forms@2x.png b/ios/chrome/browser/ui/settings/resources/settings_autofill_forms.imageset/settings_autofill_forms@2x.png deleted file mode 100644 index 3f62534..0000000 --- a/ios/chrome/browser/ui/settings/resources/settings_autofill_forms.imageset/settings_autofill_forms@2x.png +++ /dev/null Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_autofill_forms.imageset/settings_autofill_forms@3x.png b/ios/chrome/browser/ui/settings/resources/settings_autofill_forms.imageset/settings_autofill_forms@3x.png deleted file mode 100644 index d65d49d..0000000 --- a/ios/chrome/browser/ui/settings/resources/settings_autofill_forms.imageset/settings_autofill_forms@3x.png +++ /dev/null Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_autofill_forms.imageset/Contents.json b/ios/chrome/browser/ui/settings/resources/settings_payment_methods.imageset/Contents.json similarity index 66% copy from ios/chrome/browser/ui/settings/resources/settings_autofill_forms.imageset/Contents.json copy to ios/chrome/browser/ui/settings/resources/settings_payment_methods.imageset/Contents.json index 248316be..31e25f4 100644 --- a/ios/chrome/browser/ui/settings/resources/settings_autofill_forms.imageset/Contents.json +++ b/ios/chrome/browser/ui/settings/resources/settings_payment_methods.imageset/Contents.json
@@ -3,21 +3,21 @@ { "idiom": "universal", "scale": "1x", - "filename": "settings_autofill_forms.png" + "filename": "payment_methods.png" }, { "idiom": "universal", "scale": "2x", - "filename": "settings_autofill_forms@2x.png" + "filename": "payment_methods@2x.png" }, { "idiom": "universal", "scale": "3x", - "filename": "settings_autofill_forms@3x.png" + "filename": "payment_methods@3x.png" } ], "info": { "version": 1, "author": "xcode" } -} +} \ No newline at end of file
diff --git a/ios/chrome/browser/ui/settings/resources/settings_payment_methods.imageset/payment_methods.png b/ios/chrome/browser/ui/settings/resources/settings_payment_methods.imageset/payment_methods.png new file mode 100644 index 0000000..05cf013 --- /dev/null +++ b/ios/chrome/browser/ui/settings/resources/settings_payment_methods.imageset/payment_methods.png Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_payment_methods.imageset/payment_methods@2x.png b/ios/chrome/browser/ui/settings/resources/settings_payment_methods.imageset/payment_methods@2x.png new file mode 100644 index 0000000..fde276e --- /dev/null +++ b/ios/chrome/browser/ui/settings/resources/settings_payment_methods.imageset/payment_methods@2x.png Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_payment_methods.imageset/payment_methods@3x.png b/ios/chrome/browser/ui/settings/resources/settings_payment_methods.imageset/payment_methods@3x.png new file mode 100644 index 0000000..f2a085a8 --- /dev/null +++ b/ios/chrome/browser/ui/settings/resources/settings_payment_methods.imageset/payment_methods@3x.png Binary files differ
diff --git a/ios/chrome/browser/ui/settings/settings_collection_view_controller.mm b/ios/chrome/browser/ui/settings/settings_collection_view_controller.mm index 25ca899..405df2d 100644 --- a/ios/chrome/browser/ui/settings/settings_collection_view_controller.mm +++ b/ios/chrome/browser/ui/settings/settings_collection_view_controller.mm
@@ -44,7 +44,8 @@ #import "ios/chrome/browser/ui/commands/settings_main_page_commands.h" #import "ios/chrome/browser/ui/settings/about_chrome_collection_view_controller.h" #import "ios/chrome/browser/ui/settings/accounts_collection_view_controller.h" -#import "ios/chrome/browser/ui/settings/autofill_collection_view_controller.h" +#import "ios/chrome/browser/ui/settings/autofill_credit_card_collection_view_controller.h" +#import "ios/chrome/browser/ui/settings/autofill_profile_collection_view_controller.h" #import "ios/chrome/browser/ui/settings/bandwidth_management_collection_view_controller.h" #import "ios/chrome/browser/ui/settings/cells/account_signin_item.h" #import "ios/chrome/browser/ui/settings/cells/settings_detail_item.h" @@ -96,7 +97,9 @@ NSString* const kSyncAndGoogleServicesImageName = @"sync_and_google_services"; NSString* const kSettingsSearchEngineImageName = @"settings_search_engine"; NSString* const kSettingsPasswordsImageName = @"settings_passwords"; -NSString* const kSettingsAutofillFormsImageName = @"settings_autofill_forms"; +NSString* const kSettingsAutofillCreditCardImageName = + @"settings_payment_methods"; +NSString* const kSettingsAutofillProfileImageName = @"settings_addresses"; NSString* const kSettingsVoiceSearchImageName = @"settings_voice_search"; NSString* const kSettingsPrivacyImageName = @"settings_privacy"; NSString* const kSettingsContentSettingsImageName = @@ -124,7 +127,8 @@ ItemTypeHeader, ItemTypeSearchEngine, ItemTypeSavedPasswords, - ItemTypeAutofill, + ItemTypeAutofillCreditCard, + ItemTypeAutofillProfile, ItemTypeVoiceSearch, ItemTypePrivacy, ItemTypeContentSettings, @@ -240,7 +244,8 @@ SettingsDetailItem* _voiceSearchDetailItem; SettingsDetailItem* _defaultSearchEngineItem; SettingsDetailItem* _savePasswordsDetailItem; - SettingsDetailItem* _autoFillDetailItem; + SettingsDetailItem* _autoFillProfileDetailItem; + SettingsDetailItem* _autoFillCreditCardDetailItem; // YES if the user used at least once the sign-in promo view buttons. BOOL _signinStarted; @@ -424,7 +429,9 @@ toSectionWithIdentifier:SectionIdentifierBasics]; [model addItem:[self savePasswordsDetailItem] toSectionWithIdentifier:SectionIdentifierBasics]; - [model addItem:[self autoFillDetailItem] + [model addItem:[self AutoFillCreditCardDetailItem] + toSectionWithIdentifier:SectionIdentifierBasics]; + [model addItem:[self autoFillProfileDetailItem] toSectionWithIdentifier:SectionIdentifierBasics]; // Advanced Section @@ -562,19 +569,34 @@ return _savePasswordsDetailItem; } -- (CollectionViewItem*)autoFillDetailItem { - BOOL autofillEnabled = - autofill::prefs::IsAutofillEnabled(_browserState->GetPrefs()); - NSString* autofillDetail = autofillEnabled - ? l10n_util::GetNSString(IDS_IOS_SETTING_ON) - : l10n_util::GetNSString(IDS_IOS_SETTING_OFF); - _autoFillDetailItem = - [self detailItemWithType:ItemTypeAutofill - text:l10n_util::GetNSString(IDS_IOS_AUTOFILL) - detailText:autofillDetail - iconImageName:kSettingsAutofillFormsImageName]; +- (CollectionViewItem*)AutoFillCreditCardDetailItem { + BOOL autofillCreditCardEnabled = + autofill::prefs::IsCreditCardAutofillEnabled(_browserState->GetPrefs()); + NSString* detailText = autofillCreditCardEnabled + ? l10n_util::GetNSString(IDS_IOS_SETTING_ON) + : l10n_util::GetNSString(IDS_IOS_SETTING_OFF); + _autoFillCreditCardDetailItem = [self + detailItemWithType:ItemTypeAutofillCreditCard + text:l10n_util::GetNSString(IDS_AUTOFILL_PAYMENT_METHODS) + detailText:detailText + iconImageName:kSettingsAutofillCreditCardImageName]; - return _autoFillDetailItem; + return _autoFillCreditCardDetailItem; +} + +- (CollectionViewItem*)autoFillProfileDetailItem { + BOOL autofillProfileEnabled = + autofill::prefs::IsProfileAutofillEnabled(_browserState->GetPrefs()); + NSString* detailText = autofillProfileEnabled + ? l10n_util::GetNSString(IDS_IOS_SETTING_ON) + : l10n_util::GetNSString(IDS_IOS_SETTING_OFF); + _autoFillProfileDetailItem = + [self detailItemWithType:ItemTypeAutofillProfile + text:l10n_util::GetNSString(IDS_AUTOFILL_ADDRESSES) + detailText:detailText + iconImageName:kSettingsAutofillProfileImageName]; + + return _autoFillProfileDetailItem; } - (CollectionViewItem*)voiceSearchDetailItem { @@ -856,8 +878,12 @@ controller = [[SavePasswordsCollectionViewController alloc] initWithBrowserState:_browserState]; break; - case ItemTypeAutofill: - controller = [[AutofillCollectionViewController alloc] + case ItemTypeAutofillCreditCard: + controller = [[AutofillCreditCardCollectionViewController alloc] + initWithBrowserState:_browserState]; + break; + case ItemTypeAutofillProfile: + controller = [[AutofillProfileCollectionViewController alloc] initWithBrowserState:_browserState]; break; case ItemTypeVoiceSearch: @@ -1260,15 +1286,24 @@ [self reconfigureCellsForItems:@[ _savePasswordsDetailItem ]]; } - if (preferenceName == autofill::prefs::kAutofillCreditCardEnabled || - preferenceName == autofill::prefs::kAutofillProfileEnabled) { - BOOL autofillEnabled = - autofill::prefs::IsAutofillEnabled(_browserState->GetPrefs()); - NSString* autofillDetail = - autofillEnabled ? l10n_util::GetNSString(IDS_IOS_SETTING_ON) - : l10n_util::GetNSString(IDS_IOS_SETTING_OFF); - _autoFillDetailItem.detailText = autofillDetail; - [self reconfigureCellsForItems:@[ _autoFillDetailItem ]]; + if (preferenceName == autofill::prefs::kAutofillProfileEnabled) { + BOOL autofillProfileEnabled = + autofill::prefs::IsProfileAutofillEnabled(_browserState->GetPrefs()); + NSString* detailText = autofillProfileEnabled + ? l10n_util::GetNSString(IDS_IOS_SETTING_ON) + : l10n_util::GetNSString(IDS_IOS_SETTING_OFF); + _autoFillProfileDetailItem.detailText = detailText; + [self reconfigureCellsForItems:@[ _autoFillProfileDetailItem ]]; + } + + if (preferenceName == autofill::prefs::kAutofillCreditCardEnabled) { + BOOL autofillCreditCardEnabled = + autofill::prefs::IsCreditCardAutofillEnabled(_browserState->GetPrefs()); + NSString* detailText = autofillCreditCardEnabled + ? l10n_util::GetNSString(IDS_IOS_SETTING_ON) + : l10n_util::GetNSString(IDS_IOS_SETTING_OFF); + _autoFillCreditCardDetailItem.detailText = detailText; + [self reconfigureCellsForItems:@[ _autoFillCreditCardDetailItem ]]; } }
diff --git a/ios/chrome/browser/ui/settings/settings_egtest.mm b/ios/chrome/browser/ui/settings/settings_egtest.mm index ff402e29..2199806 100644 --- a/ios/chrome/browser/ui/settings/settings_egtest.mm +++ b/ios/chrome/browser/ui/settings/settings_egtest.mm
@@ -97,9 +97,13 @@ id<GREYMatcher> SearchEngineButton() { return ButtonWithAccessibilityLabelId(IDS_IOS_SEARCH_ENGINE_SETTING_TITLE); } -// Matcher for the Autofill Forms cell on the main Settings screen. -id<GREYMatcher> AutofillButton() { - return ButtonWithAccessibilityLabelId(IDS_IOS_AUTOFILL); +// Matcher for the payment methods cell on the main Settings screen. +id<GREYMatcher> PaymentMethodsButton() { + return ButtonWithAccessibilityLabelId(IDS_AUTOFILL_PAYMENT_METHODS); +} +// Matcher for the addresses cell on the main Settings screen. +id<GREYMatcher> AddressesButton() { + return ButtonWithAccessibilityLabelId(IDS_AUTOFILL_ADDRESSES); } // Matcher for the Google Chrome cell on the main Settings screen. id<GREYMatcher> GoogleChromeButton() { @@ -709,10 +713,18 @@ [self closeSubSettingsMenu]; } -// Verifies the UI elements are accessible on the Autofill Forms page. -- (void)testAccessibilityOnAutofillForms { +// Verifies the UI elements are accessible on the payment methods page. +- (void)testAccessibilityOnPaymentMethods { [ChromeEarlGreyUI openSettingsMenu]; - [ChromeEarlGreyUI tapSettingsMenuButton:AutofillButton()]; + [ChromeEarlGreyUI tapSettingsMenuButton:PaymentMethodsButton()]; + chrome_test_util::VerifyAccessibilityForCurrentScreen(); + [self closeSubSettingsMenu]; +} + +// Verifies the UI elements are accessible on the addresses page. +- (void)testAccessibilityOnAddresses { + [ChromeEarlGreyUI openSettingsMenu]; + [ChromeEarlGreyUI tapSettingsMenuButton:AddressesButton()]; chrome_test_util::VerifyAccessibilityForCurrentScreen(); [self closeSubSettingsMenu]; }
diff --git a/ios/chrome/browser/ui/settings/settings_navigation_controller.mm b/ios/chrome/browser/ui/settings/settings_navigation_controller.mm index 3d0ebca9..46241fda0c 100644 --- a/ios/chrome/browser/ui/settings/settings_navigation_controller.mm +++ b/ios/chrome/browser/ui/settings/settings_navigation_controller.mm
@@ -15,7 +15,7 @@ #import "ios/chrome/browser/ui/material_components/app_bar_presenting.h" #import "ios/chrome/browser/ui/material_components/utils.h" #import "ios/chrome/browser/ui/settings/accounts_collection_view_controller.h" -#import "ios/chrome/browser/ui/settings/autofill_collection_view_controller.h" +#import "ios/chrome/browser/ui/settings/autofill_profile_collection_view_controller.h" #import "ios/chrome/browser/ui/settings/clear_browsing_data_collection_view_controller.h" #import "ios/chrome/browser/ui/settings/import_data_collection_view_controller.h" #import "ios/chrome/browser/ui/settings/save_passwords_collection_view_controller.h" @@ -248,8 +248,8 @@ + (SettingsNavigationController*) newAutofillController:(ios::ChromeBrowserState*)browserState delegate:(id<SettingsNavigationControllerDelegate>)delegate { - AutofillCollectionViewController* controller = - [[AutofillCollectionViewController alloc] + AutofillProfileCollectionViewController* controller = + [[AutofillProfileCollectionViewController alloc] initWithBrowserState:browserState]; controller.dispatcher = [delegate dispatcherForSettings];
diff --git a/ios/web_view/internal/translate/cwv_translation_controller.mm b/ios/web_view/internal/translate/cwv_translation_controller.mm index 64cf3111..13bee0b 100644 --- a/ios/web_view/internal/translate/cwv_translation_controller.mm +++ b/ios/web_view/internal/translate/cwv_translation_controller.mm
@@ -6,6 +6,7 @@ #include <string> +#include "base/logging.h" #include "base/memory/ptr_util.h" #include "base/strings/string16.h" #include "base/strings/sys_string_conversions.h" @@ -25,26 +26,39 @@ NSErrorDomain const CWVTranslationErrorDomain = @"org.chromium.chromewebview.TranslationErrorDomain"; -const NSInteger CWVTranslationErrorNetwork = - translate::TranslateErrors::NETWORK; -const NSInteger CWVTranslationErrorInitializationError = - translate::TranslateErrors::INITIALIZATION_ERROR; -const NSInteger CWVTranslationErrorUnknownLanguage = - translate::TranslateErrors::UNKNOWN_LANGUAGE; -const NSInteger CWVTranslationErrorUnsupportedLanguage = - translate::TranslateErrors::UNSUPPORTED_LANGUAGE; -const NSInteger CWVTranslationErrorIdenticalLanguages = - translate::TranslateErrors::IDENTICAL_LANGUAGES; -const NSInteger CWVTranslationErrorTranslationError = - translate::TranslateErrors::TRANSLATION_ERROR; -const NSInteger CWVTranslationErrorTranslationTimeout = - translate::TranslateErrors::TRANSLATION_TIMEOUT; -const NSInteger CWVTranslationErrorUnexpectedScriptError = - translate::TranslateErrors::UNEXPECTED_SCRIPT_ERROR; -const NSInteger CWVTranslationErrorBadOrigin = - translate::TranslateErrors::BAD_ORIGIN; -const NSInteger CWVTranslationErrorScriptLoadError = - translate::TranslateErrors::SCRIPT_LOAD_ERROR; +namespace { +// Converts a |translate::TranslateErrors::Type| to a |CWVTranslationError|. +CWVTranslationError CWVConvertTranslateError( + translate::TranslateErrors::Type type) { + switch (type) { + case translate::TranslateErrors::NONE: + return CWVTranslationErrorNone; + case translate::TranslateErrors::NETWORK: + return CWVTranslationErrorNetwork; + case translate::TranslateErrors::INITIALIZATION_ERROR: + return CWVTranslationErrorInitializationError; + case translate::TranslateErrors::UNKNOWN_LANGUAGE: + return CWVTranslationErrorUnknownLanguage; + case translate::TranslateErrors::UNSUPPORTED_LANGUAGE: + return CWVTranslationErrorUnsupportedLanguage; + case translate::TranslateErrors::IDENTICAL_LANGUAGES: + return CWVTranslationErrorIdenticalLanguages; + case translate::TranslateErrors::TRANSLATION_ERROR: + return CWVTranslationErrorTranslationError; + case translate::TranslateErrors::TRANSLATION_TIMEOUT: + return CWVTranslationErrorTranslationTimeout; + case translate::TranslateErrors::UNEXPECTED_SCRIPT_ERROR: + return CWVTranslationErrorUnexpectedScriptError; + case translate::TranslateErrors::BAD_ORIGIN: + return CWVTranslationErrorBadOrigin; + case translate::TranslateErrors::SCRIPT_LOAD_ERROR: + return CWVTranslationErrorScriptLoadError; + case translate::TranslateErrors::TRANSLATE_ERROR_MAX: + NOTREACHED(); + return CWVTranslationErrorNone; + } +} +} // namespace @interface CWVTranslationController () @@ -90,7 +104,7 @@ NSError* error; if (errorType != translate::TranslateErrors::NONE) { error = [NSError errorWithDomain:CWVTranslationErrorDomain - code:errorType + code:CWVConvertTranslateError(errorType) userInfo:nil]; }
diff --git a/ios/web_view/public/cwv_translation_controller.h b/ios/web_view/public/cwv_translation_controller.h index 4fe77e7..3672772 100644 --- a/ios/web_view/public/cwv_translation_controller.h +++ b/ios/web_view/public/cwv_translation_controller.h
@@ -16,29 +16,33 @@ @protocol CWVTranslationControllerDelegate; // The error domain for translation errors. -extern NSErrorDomain const CWVTranslationErrorDomain; +FOUNDATION_EXPORT CWV_EXPORT NSErrorDomain const CWVTranslationErrorDomain; // Possible error codes during translation. -// No connectivity. -extern const NSInteger CWVTranslationErrorNetwork; -// The translation script failed to initialize. -extern const NSInteger CWVTranslationErrorInitializationError; -// The page's language could not be detected. -extern const NSInteger CWVTranslationErrorUnknownLanguage; -// The server detected a language that the browser does not know. -extern const NSInteger CWVTranslationErrorUnsupportedLanguage; -// The original and target languages are the same. -extern const NSInteger CWVTranslationErrorIdenticalLanguages; -// An error was reported by the translation script during translation. -extern const NSInteger CWVTranslationErrorTranslationError; -// The library doesn't finish the translation. -extern const NSInteger CWVTranslationErrorTranslationTimeout; -// The library raises an unexpected exception. -extern const NSInteger CWVTranslationErrorUnexpectedScriptError; -// The library is blocked because of bad origin. -extern const NSInteger CWVTranslationErrorBadOrigin; -// Loader fails to load a dependent JavaScript. -extern const NSInteger CWVTranslationErrorScriptLoadError; +typedef NS_ENUM(NSInteger, CWVTranslationError) { + // No error. + CWVTranslationErrorNone = 0, + // No connectivity. + CWVTranslationErrorNetwork, + // The translation script failed to initialize. + CWVTranslationErrorInitializationError, + // The page's language could not be detected. + CWVTranslationErrorUnknownLanguage, + // The server detected a language that the browser does not know. + CWVTranslationErrorUnsupportedLanguage, + // The original and target languages are the same. + CWVTranslationErrorIdenticalLanguages, + // An error was reported by the translation script during translation. + CWVTranslationErrorTranslationError, + // The library doesn't finish the translation. + CWVTranslationErrorTranslationTimeout, + // The library raises an unexpected exception. + CWVTranslationErrorUnexpectedScriptError, + // The library is blocked because of bad origin. + CWVTranslationErrorBadOrigin, + // Loader fails to load a dependent JavaScript. + CWVTranslationErrorScriptLoadError, +}; // Allows page translation from one language to another. CWV_EXPORT
diff --git a/media/gpu/vaapi/vaapi_jpeg_decode_accelerator.cc b/media/gpu/vaapi/vaapi_jpeg_decode_accelerator.cc index 7c09af1..a8f7023 100644 --- a/media/gpu/vaapi/vaapi_jpeg_decode_accelerator.cc +++ b/media/gpu/vaapi/vaapi_jpeg_decode_accelerator.cc
@@ -80,22 +80,6 @@ } // namespace -// An input buffer and the corresponding output video frame awaiting -// consumption, provided by the client. -struct VaapiJpegDecodeAccelerator::DecodeRequest { - DecodeRequest(int32_t bitstream_buffer_id, - std::unique_ptr<UnalignedSharedMemory> shm, - const scoped_refptr<VideoFrame>& video_frame) - : bitstream_buffer_id(bitstream_buffer_id), - shm(std::move(shm)), - video_frame(video_frame) {} - ~DecodeRequest() = default; - - int32_t bitstream_buffer_id; - std::unique_ptr<UnalignedSharedMemory> shm; - scoped_refptr<VideoFrame> video_frame; -}; - void VaapiJpegDecodeAccelerator::NotifyError(int32_t bitstream_buffer_id, Error error) { DCHECK(task_runner_->BelongsToCurrentThread()); @@ -239,18 +223,18 @@ } void VaapiJpegDecodeAccelerator::DecodeTask( - std::unique_ptr<DecodeRequest> request) { + int32_t bitstream_buffer_id, + std::unique_ptr<UnalignedSharedMemory> shm, + scoped_refptr<VideoFrame> video_frame) { DVLOGF(4); DCHECK(decoder_task_runner_->BelongsToCurrentThread()); TRACE_EVENT0("jpeg", "DecodeTask"); JpegParseResult parse_result; - if (!ParseJpegPicture( - reinterpret_cast<const uint8_t*>(request->shm->memory()), - request->shm->size(), &parse_result)) { + if (!ParseJpegPicture(reinterpret_cast<const uint8_t*>(shm->memory()), + shm->size(), &parse_result)) { VLOGF(1) << "ParseJpegPicture failed"; - NotifyErrorFromDecoderThread(request->bitstream_buffer_id, - PARSE_JPEG_FAILED); + NotifyErrorFromDecoderThread(bitstream_buffer_id, PARSE_JPEG_FAILED); return; } @@ -258,8 +242,7 @@ VaSurfaceFormatForJpeg(parse_result.frame_header); if (!new_va_rt_format) { VLOGF(1) << "Unsupported subsampling"; - NotifyErrorFromDecoderThread(request->bitstream_buffer_id, - UNSUPPORTED_JPEG); + NotifyErrorFromDecoderThread(bitstream_buffer_id, UNSUPPORTED_JPEG); return; } @@ -276,8 +259,7 @@ if (!vaapi_wrapper_->CreateSurfaces(va_rt_format_, new_coded_size, 1, &va_surfaces)) { VLOGF(1) << "Create VA surface failed"; - NotifyErrorFromDecoderThread(request->bitstream_buffer_id, - PLATFORM_FAILURE); + NotifyErrorFromDecoderThread(bitstream_buffer_id, PLATFORM_FAILURE); return; } va_surface_id_ = va_surfaces[0]; @@ -287,16 +269,13 @@ if (!VaapiJpegDecoder::Decode(vaapi_wrapper_.get(), parse_result, va_surface_id_)) { VLOGF(1) << "Decode JPEG failed"; - NotifyErrorFromDecoderThread(request->bitstream_buffer_id, - PLATFORM_FAILURE); + NotifyErrorFromDecoderThread(bitstream_buffer_id, PLATFORM_FAILURE); return; } - if (!OutputPicture(va_surface_id_, request->bitstream_buffer_id, - request->video_frame)) { + if (!OutputPicture(va_surface_id_, bitstream_buffer_id, video_frame)) { VLOGF(1) << "Output picture failed"; - NotifyErrorFromDecoderThread(request->bitstream_buffer_id, - PLATFORM_FAILURE); + NotifyErrorFromDecoderThread(bitstream_buffer_id, PLATFORM_FAILURE); return; } } @@ -326,13 +305,10 @@ return; } - std::unique_ptr<DecodeRequest> request( - new DecodeRequest(bitstream_buffer.id(), std::move(shm), video_frame)); - decoder_task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&VaapiJpegDecodeAccelerator::DecodeTask, - base::Unretained(this), base::Passed(std::move(request)))); + FROM_HERE, base::BindOnce(&VaapiJpegDecodeAccelerator::DecodeTask, + base::Unretained(this), bitstream_buffer.id(), + std::move(shm), std::move(video_frame))); } bool VaapiJpegDecodeAccelerator::IsSupported() {
diff --git a/media/gpu/vaapi/vaapi_jpeg_decode_accelerator.h b/media/gpu/vaapi/vaapi_jpeg_decode_accelerator.h index f3f6e74..472f92f 100644 --- a/media/gpu/vaapi/vaapi_jpeg_decode_accelerator.h +++ b/media/gpu/vaapi/vaapi_jpeg_decode_accelerator.h
@@ -46,16 +46,16 @@ bool IsSupported() override; private: - struct DecodeRequest; - // Notifies the client that an error has occurred and decoding cannot // continue. void NotifyError(int32_t bitstream_buffer_id, Error error); void NotifyErrorFromDecoderThread(int32_t bitstream_buffer_id, Error error); void VideoFrameReady(int32_t bitstream_buffer_id); - // Processes one decode |request|. - void DecodeTask(std::unique_ptr<DecodeRequest> request); + // Processes one decode request. + void DecodeTask(int32_t bitstream_buffer_id, + std::unique_ptr<UnalignedSharedMemory> shm, + scoped_refptr<VideoFrame> video_frame); // Puts contents of |va_surface| into given |video_frame|, releases the // surface and passes the |input_buffer_id| of the resulting picture to
diff --git a/net/log/net_log_event_type_list.h b/net/log/net_log_event_type_list.h index 7df3268..b3ae27543 100644 --- a/net/log/net_log_event_type_list.h +++ b/net/log/net_log_event_type_list.h
@@ -3135,6 +3135,14 @@ // } EVENT_TYPE(COOKIE_STORE_SESSION_PERSISTENCE) +// Event emitted when a particular origin is removed from the persistent +// store on shutdown. +// { +// "origin": <Origin being filtered> +// "is_https": <Secure status of origin> +// } +EVENT_TYPE(COOKIE_PERSISTENT_STORE_ORIGIN_FILTERED) + // Event emitted when the persistent database load is started and completed. // { // }
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc index 03702a71..4a58166e 100644 --- a/net/url_request/url_request_unittest.cc +++ b/net/url_request/url_request_unittest.cc
@@ -6706,14 +6706,7 @@ } } -#if defined(OS_CHROMEOS) -// https://crbug.com/873851. -#define MAYBE_TestPostChunkedDataAfterStart \ - DISABLED_TestPostChunkedDataAfterStart -#else -#define MAYBE_TestPostChunkedDataAfterStart TestPostChunkedDataAfterStart -#endif -TEST_F(URLRequestTestHTTP, MAYBE_TestPostChunkedDataAfterStart) { +TEST_F(URLRequestTestHTTP, TestPostChunkedDataAfterStart) { ASSERT_TRUE(http_test_server()->Start()); TestDelegate d; @@ -6730,9 +6723,14 @@ r->Start(); EXPECT_TRUE(r->is_pending()); + // Pump messages until we start sending headers.. base::RunLoop().RunUntilIdle(); + + // And now wait for completion. + base::RunLoop run_loop; + d.set_on_complete(run_loop.QuitClosure()); AddDataToUpload(writer.get()); - d.RunUntilComplete(); + run_loop.Run(); VerifyReceivedDataMatchesChunks(r.get(), &d); }
diff --git a/remoting/base/DEPS b/remoting/base/DEPS index 7530772..0d4159d 100644 --- a/remoting/base/DEPS +++ b/remoting/base/DEPS
@@ -3,6 +3,7 @@ "+google_apis", "+mojo/core/embedder", "+net", + "+services/network/public/cpp", "+third_party/breakpad", "+third_party/zlib", "+ui/base",
diff --git a/remoting/base/gaia_oauth_client.cc b/remoting/base/gaia_oauth_client.cc index b492b7b..1274347 100644 --- a/remoting/base/gaia_oauth_client.cc +++ b/remoting/base/gaia_oauth_client.cc
@@ -14,8 +14,8 @@ namespace remoting { GaiaOAuthClient::GaiaOAuthClient( - scoped_refptr<net::URLRequestContextGetter> url_request_context_getter) - : gaia_oauth_client_(url_request_context_getter.get()) {} + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) + : gaia_oauth_client_(std::move(url_loader_factory)) {} GaiaOAuthClient::~GaiaOAuthClient() = default;
diff --git a/remoting/base/gaia_oauth_client.h b/remoting/base/gaia_oauth_client.h index 439aa3b1..79737fa 100644 --- a/remoting/base/gaia_oauth_client.h +++ b/remoting/base/gaia_oauth_client.h
@@ -9,7 +9,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "google_apis/gaia/gaia_oauth_client.h" -#include "net/url_request/url_request_context_getter.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" #include "remoting/base/oauth_client.h" @@ -22,7 +22,7 @@ public gaia::GaiaOAuthClient::Delegate { public: GaiaOAuthClient( - scoped_refptr<net::URLRequestContextGetter> url_request_context_getter); + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory); ~GaiaOAuthClient() override;
diff --git a/remoting/base/oauth_token_getter_impl.cc b/remoting/base/oauth_token_getter_impl.cc index 360b4bc..9c8e3ed 100644 --- a/remoting/base/oauth_token_getter_impl.cc +++ b/remoting/base/oauth_token_getter_impl.cc
@@ -11,9 +11,9 @@ #include "base/containers/queue.h" #include "base/strings/string_util.h" #include "google_apis/google_api_keys.h" -#include "net/url_request/url_request_context_getter.h" #include "remoting/base/logging.h" #include "remoting/base/oauth_helper.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" namespace remoting { @@ -30,14 +30,12 @@ OAuthTokenGetterImpl::OAuthTokenGetterImpl( std::unique_ptr<OAuthIntermediateCredentials> intermediate_credentials, const OAuthTokenGetter::CredentialsUpdatedCallback& on_credentials_update, - const scoped_refptr<net::URLRequestContextGetter>& - url_request_context_getter, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, bool auto_refresh) : intermediate_credentials_(std::move(intermediate_credentials)), gaia_oauth_client_( - new gaia::GaiaOAuthClient(url_request_context_getter.get())), - credentials_updated_callback_(on_credentials_update), - url_request_context_getter_(url_request_context_getter) { + new gaia::GaiaOAuthClient(std::move(url_loader_factory))), + credentials_updated_callback_(on_credentials_update) { if (auto_refresh) { refresh_timer_.reset(new base::OneShotTimer()); } @@ -45,13 +43,11 @@ OAuthTokenGetterImpl::OAuthTokenGetterImpl( std::unique_ptr<OAuthAuthorizationCredentials> authorization_credentials, - const scoped_refptr<net::URLRequestContextGetter>& - url_request_context_getter, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, bool auto_refresh) : authorization_credentials_(std::move(authorization_credentials)), gaia_oauth_client_( - new gaia::GaiaOAuthClient(url_request_context_getter.get())), - url_request_context_getter_(url_request_context_getter) { + new gaia::GaiaOAuthClient(std::move(url_loader_factory))) { if (auto_refresh) { refresh_timer_.reset(new base::OneShotTimer()); }
diff --git a/remoting/base/oauth_token_getter_impl.h b/remoting/base/oauth_token_getter_impl.h index a016e9a..bdb20080 100644 --- a/remoting/base/oauth_token_getter_impl.h +++ b/remoting/base/oauth_token_getter_impl.h
@@ -13,9 +13,9 @@ #include "google_apis/gaia/gaia_oauth_client.h" #include "remoting/base/oauth_token_getter.h" -namespace net { -class URLRequestContextGetter; -} // namespace net +namespace network { +class SharedURLLoaderFactory; +} // namespace network namespace remoting { @@ -33,13 +33,11 @@ OAuthTokenGetterImpl( std::unique_ptr<OAuthIntermediateCredentials> intermediate_credentials, const OAuthTokenGetter::CredentialsUpdatedCallback& on_credentials_update, - const scoped_refptr<net::URLRequestContextGetter>& - url_request_context_getter, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, bool auto_refresh); OAuthTokenGetterImpl( std::unique_ptr<OAuthAuthorizationCredentials> authorization_credentials, - const scoped_refptr<net::URLRequestContextGetter>& - url_request_context_getter, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, bool auto_refresh); ~OAuthTokenGetterImpl() override; @@ -72,7 +70,6 @@ std::unique_ptr<OAuthAuthorizationCredentials> authorization_credentials_; std::unique_ptr<gaia::GaiaOAuthClient> gaia_oauth_client_; OAuthTokenGetter::CredentialsUpdatedCallback credentials_updated_callback_; - scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_; bool response_pending_ = false; bool email_verified_ = false;
diff --git a/remoting/client/DEPS b/remoting/client/DEPS index 81ac47553..4f4a49f3 100644 --- a/remoting/client/DEPS +++ b/remoting/client/DEPS
@@ -7,4 +7,5 @@ "+remoting/codec", "+remoting/protocol", "+remoting/signaling", + "+services/network", ]
diff --git a/remoting/client/chromoting_client_runtime.cc b/remoting/client/chromoting_client_runtime.cc index e0d6a59..3bb00f2 100644 --- a/remoting/client/chromoting_client_runtime.cc +++ b/remoting/client/chromoting_client_runtime.cc
@@ -16,6 +16,8 @@ #include "remoting/base/telemetry_log_writer.h" #include "remoting/base/url_request_context_getter.h" #include "remoting/client/oauth_token_getter_proxy.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" +#include "services/network/transitional_url_loader_factory_owner.h" namespace { @@ -57,6 +59,9 @@ network_task_runner_ = AutoThread::CreateWithType( "native_net", ui_task_runner_, base::MessageLoop::TYPE_IO); url_requester_ = new URLRequestContextGetter(network_task_runner_); + url_loader_factory_owner_ = + std::make_unique<network::TransitionalURLLoaderFactoryOwner>( + url_requester_); } ChromotingClientRuntime::~ChromotingClientRuntime() { @@ -91,4 +96,9 @@ delegate_->oauth_token_getter(), ui_task_runner()); } +scoped_refptr<network::SharedURLLoaderFactory> +ChromotingClientRuntime::url_loader_factory() { + return url_loader_factory_owner_->GetURLLoaderFactory(); +} + } // namespace remoting
diff --git a/remoting/client/chromoting_client_runtime.h b/remoting/client/chromoting_client_runtime.h index 071609b..714e502 100644 --- a/remoting/client/chromoting_client_runtime.h +++ b/remoting/client/chromoting_client_runtime.h
@@ -22,6 +22,11 @@ struct DefaultSingletonTraits; } // namespace base +namespace network { +class SharedURLLoaderFactory; +class TransitionalURLLoaderFactoryOwner; +} // namespace network + // Houses the global resources on which the Chromoting components run // (e.g. message loops and task runners). namespace remoting { @@ -72,6 +77,8 @@ return url_requester_; } + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory(); + ChromotingEventLogWriter* log_writer() { return log_writer_.get(); } private: @@ -96,6 +103,8 @@ scoped_refptr<AutoThreadTaskRunner> network_task_runner_; scoped_refptr<net::URLRequestContextGetter> url_requester_; + std::unique_ptr<network::TransitionalURLLoaderFactoryOwner> + url_loader_factory_owner_; // For logging session stage changes and stats. std::unique_ptr<TelemetryLogWriter> log_writer_;
diff --git a/remoting/host/DEPS b/remoting/host/DEPS index f53dd06..b498013 100644 --- a/remoting/host/DEPS +++ b/remoting/host/DEPS
@@ -19,6 +19,7 @@ # //remoting uses device::PowerSaveBlocker directly. See crbug.com/689423 "+services/device/public", "+services/device/wake_lock/power_save_blocker", + "+services/network", "+third_party/jsoncpp", "+third_party/skia", "+third_party/webrtc",
diff --git a/remoting/host/chromoting_host_context.cc b/remoting/host/chromoting_host_context.cc index c95bc23..5c46220 100644 --- a/remoting/host/chromoting_host_context.cc +++ b/remoting/host/chromoting_host_context.cc
@@ -13,6 +13,8 @@ #include "build/build_config.h" #include "remoting/base/auto_thread.h" #include "remoting/base/url_request_context_getter.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" +#include "services/network/transitional_url_loader_factory_owner.h" namespace remoting { @@ -46,7 +48,11 @@ url_request_context_getter_(url_request_context_getter), system_input_injector_factory_(system_input_injector_factory) {} -ChromotingHostContext::~ChromotingHostContext() = default; +ChromotingHostContext::~ChromotingHostContext() { + if (url_loader_factory_owner_) + network_task_runner_->DeleteSoon(FROM_HERE, + url_loader_factory_owner_.release()); +} std::unique_ptr<ChromotingHostContext> ChromotingHostContext::Copy() { return base::WrapUnique(new ChromotingHostContext( @@ -96,6 +102,17 @@ return url_request_context_getter_; } +scoped_refptr<network::SharedURLLoaderFactory> +ChromotingHostContext::url_loader_factory() { + DCHECK(network_task_runner_->RunsTasksInCurrentSequence()); + if (!url_loader_factory_owner_) { + url_loader_factory_owner_ = + std::make_unique<network::TransitionalURLLoaderFactoryOwner>( + url_request_context_getter_); + } + return url_loader_factory_owner_->GetURLLoaderFactory(); +} + ui::SystemInputInjectorFactory* ChromotingHostContext::system_input_injector_factory() const { return system_input_injector_factory_;
diff --git a/remoting/host/chromoting_host_context.h b/remoting/host/chromoting_host_context.h index 47a42dc3..f857b98 100644 --- a/remoting/host/chromoting_host_context.h +++ b/remoting/host/chromoting_host_context.h
@@ -19,6 +19,11 @@ class URLRequestContextGetter; } // namespace net +namespace network { +class SharedURLLoaderFactory; +class TransitionalURLLoaderFactoryOwner; +} // namespace network + namespace ui { class SystemInputInjectorFactory; } // namespace ui @@ -92,6 +97,8 @@ scoped_refptr<net::URLRequestContextGetter> url_request_context_getter() const; + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory(); + // Gives the factory which builds the SystemInputInjector, which takes events // and passes them to the system for dispatch. // @@ -135,6 +142,10 @@ // Serves URLRequestContexts that use the network and UI task runners. scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_; + // Makes a SharedURLLoaderFactory out of |url_request_context_getter_| + std::unique_ptr<network::TransitionalURLLoaderFactoryOwner> + url_loader_factory_owner_; + // A factory which makes a SystemInputInjector. Currently only non-null on // chromeos, though it's intended to be set everywhere mus is used. ui::SystemInputInjectorFactory* system_input_injector_factory_;
diff --git a/remoting/host/linux/BUILD.gn b/remoting/host/linux/BUILD.gn index 32ccdcc..fa24d0b9 100644 --- a/remoting/host/linux/BUILD.gn +++ b/remoting/host/linux/BUILD.gn
@@ -140,6 +140,7 @@ "//remoting/host:remoting_infoplist_strings", "//remoting/host/native_messaging", "//remoting/host/setup", + "//services/network/public/mojom", ] # The |major|, |build| and |patch| versions are inherited from Chrome.
diff --git a/remoting/host/mac/BUILD.gn b/remoting/host/mac/BUILD.gn index f9d46f4..a3fc05b8 100644 --- a/remoting/host/mac/BUILD.gn +++ b/remoting/host/mac/BUILD.gn
@@ -165,6 +165,7 @@ "//remoting/host:remoting_infoplist_strings", "//remoting/host/native_messaging", "//remoting/host/setup", + "//services/network/public/mojom", ] foreach(locale, remoting_locales_with_underscores) { deps += [
diff --git a/remoting/host/remoting_me2me_host.cc b/remoting/host/remoting_me2me_host.cc index 287f3a1..d1063f4f 100644 --- a/remoting/host/remoting_me2me_host.cc +++ b/remoting/host/remoting_me2me_host.cc
@@ -99,6 +99,7 @@ #include "remoting/protocol/transport_context.h" #include "remoting/signaling/push_notification_subscriber.h" #include "remoting/signaling/xmpp_signal_strategy.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" #include "third_party/webrtc/rtc_base/scoped_ref_ptr.h" #if defined(OS_POSIX) @@ -1430,9 +1431,8 @@ oauth_credentials(new OAuthTokenGetter::OAuthAuthorizationCredentials( xmpp_server_config_.username, oauth_refresh_token_, use_service_account_)); - oauth_token_getter_.reset( - new OAuthTokenGetterImpl(std::move(oauth_credentials), - context_->url_request_context_getter(), false)); + oauth_token_getter_.reset(new OAuthTokenGetterImpl( + std::move(oauth_credentials), context_->url_loader_factory(), false)); signaling_connector_.reset(new SignalingConnector( xmpp_signal_strategy, std::move(dns_blackhole_checker), oauth_token_getter_.get(),
diff --git a/remoting/host/setup/BUILD.gn b/remoting/host/setup/BUILD.gn index 2f5da09..9e642c4 100644 --- a/remoting/host/setup/BUILD.gn +++ b/remoting/host/setup/BUILD.gn
@@ -37,6 +37,8 @@ "//remoting/base:authorization", "//remoting/host", "//remoting/host/native_messaging", + "//services/network/public/cpp", + "//services/network/public/mojom", ] if (is_mac || is_ios) {
diff --git a/remoting/host/setup/host_starter.cc b/remoting/host/setup/host_starter.cc index 2b33db7..7790aead 100644 --- a/remoting/host/setup/host_starter.cc +++ b/remoting/host/setup/host_starter.cc
@@ -17,6 +17,7 @@ #include "google_apis/google_api_keys.h" #include "remoting/base/oauth_helper.h" #include "remoting/host/pin_hash.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" namespace { const int kMaxGetTokensRetries = 3; @@ -42,9 +43,10 @@ std::unique_ptr<HostStarter> HostStarter::Create( const std::string& chromoting_hosts_url, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, net::URLRequestContextGetter* url_request_context_getter) { return base::WrapUnique(new HostStarter( - std::make_unique<gaia::GaiaOAuthClient>(url_request_context_getter), + std::make_unique<gaia::GaiaOAuthClient>(url_loader_factory), std::make_unique<remoting::ServiceClient>(chromoting_hosts_url, url_request_context_getter), remoting::DaemonController::Create()));
diff --git a/remoting/host/setup/host_starter.h b/remoting/host/setup/host_starter.h index 52eacfd..32eab3b 100644 --- a/remoting/host/setup/host_starter.h +++ b/remoting/host/setup/host_starter.h
@@ -20,6 +20,10 @@ class URLRequestContextGetter; } +namespace network { +class SharedURLLoaderFactory; +} + namespace remoting { // A helper class that registers and starts a host. @@ -40,6 +44,7 @@ // Creates a HostStarter. static std::unique_ptr<HostStarter> Create( const std::string& chromoting_hosts_url, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, net::URLRequestContextGetter* url_request_context_getter); // Registers a new host with the Chromoting service, and starts it.
diff --git a/remoting/host/setup/me2me_native_messaging_host_main.cc b/remoting/host/setup/me2me_native_messaging_host_main.cc index fef7902..9194571 100644 --- a/remoting/host/setup/me2me_native_messaging_host_main.cc +++ b/remoting/host/setup/me2me_native_messaging_host_main.cc
@@ -33,6 +33,8 @@ #include "remoting/host/setup/me2me_native_messaging_host.h" #include "remoting/host/switches.h" #include "remoting/host/usage_stats_consent.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" +#include "services/network/transitional_url_loader_factory_owner.h" #if defined(OS_MACOSX) #include "base/mac/scoped_nsautorelease_pool.h" @@ -181,8 +183,10 @@ // OAuth client (for credential requests). IO thread is used for blocking scoped_refptr<net::URLRequestContextGetter> url_request_context_getter( new URLRequestContextGetter(io_thread.task_runner())); + network::TransitionalURLLoaderFactoryOwner url_loader_factory_owner( + url_request_context_getter); std::unique_ptr<OAuthClient> oauth_client( - new GaiaOAuthClient(url_request_context_getter)); + new GaiaOAuthClient(url_loader_factory_owner.GetURLLoaderFactory())); net::URLFetcher::SetIgnoreCertificateRequests(true);
diff --git a/remoting/host/setup/start_host_main.cc b/remoting/host/setup/start_host_main.cc index 5190b4d..42e4111c 100644 --- a/remoting/host/setup/start_host_main.cc +++ b/remoting/host/setup/start_host_main.cc
@@ -24,6 +24,8 @@ #include "remoting/base/url_request_context_getter.h" #include "remoting/host/setup/host_starter.h" #include "remoting/host/setup/pin_validator.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" +#include "services/network/transitional_url_loader_factory_owner.h" #if defined(OS_POSIX) #include <termios.h> @@ -221,12 +223,15 @@ scoped_refptr<net::URLRequestContextGetter> url_request_context_getter( new remoting::URLRequestContextGetter(io_thread.task_runner())); + network::TransitionalURLLoaderFactoryOwner url_loader_factory_owner( + url_request_context_getter); net::URLFetcher::SetIgnoreCertificateRequests(true); // Start the host. std::unique_ptr<HostStarter> host_starter(HostStarter::Create( remoting::ServiceUrls::GetInstance()->directory_hosts_url(), + url_loader_factory_owner.GetURLLoaderFactory(), url_request_context_getter.get())); if (redirect_url.empty()) { redirect_url = remoting::GetDefaultOauthRedirectUrl();
diff --git a/remoting/host/win/BUILD.gn b/remoting/host/win/BUILD.gn index 72f12fc6..3e7054e4 100644 --- a/remoting/host/win/BUILD.gn +++ b/remoting/host/win/BUILD.gn
@@ -407,6 +407,7 @@ "//remoting/host/setup", "//remoting/protocol", "//sandbox/win:sandbox", # Should always use Windows version + "//services/network/public/mojom", "//third_party/webrtc/modules/desktop_capture", ]
diff --git a/remoting/ios/DEPS b/remoting/ios/DEPS index a513cf89..3b6691ff 100644 --- a/remoting/ios/DEPS +++ b/remoting/ios/DEPS
@@ -14,4 +14,5 @@ "+third_party/webrtc", "+third_party/ocmock", "+third_party/protobuf/src", + "+services/network/public/cpp", ]
diff --git a/remoting/ios/facade/remoting_oauth_authentication.mm b/remoting/ios/facade/remoting_oauth_authentication.mm index 9549999..7f25698 100644 --- a/remoting/ios/facade/remoting_oauth_authentication.mm +++ b/remoting/ios/facade/remoting_oauth_authentication.mm
@@ -25,6 +25,7 @@ #include "net/url_request/url_request_context_getter.h" #include "remoting/base/oauth_token_getter.h" #include "remoting/base/oauth_token_getter_impl.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" static const char kOauthRedirectUrl[] = "https://chromoting-oauth.talkgadget." @@ -52,7 +53,7 @@ std::unique_ptr<remoting::OAuthTokenGetter> oauth_tokenGetter( new remoting::OAuthTokenGetterImpl( std::move(oauth_credentials), on_credentials_update, - RemotingService.instance.runtime->url_requester(), + RemotingService.instance.runtime->url_loader_factory(), /*auto_refresh=*/true)); return oauth_tokenGetter; } @@ -68,7 +69,7 @@ std::unique_ptr<remoting::OAuthTokenGetter> oauth_tokenGetter( new remoting::OAuthTokenGetterImpl( std::move(oauth_credentials), - RemotingService.instance.runtime->url_requester(), + RemotingService.instance.runtime->url_loader_factory(), /*auto_refresh=*/true)); return oauth_tokenGetter; }
diff --git a/remoting/test/BUILD.gn b/remoting/test/BUILD.gn index fa1b4c3..66c7f18 100644 --- a/remoting/test/BUILD.gn +++ b/remoting/test/BUILD.gn
@@ -243,6 +243,7 @@ ":test_support", "//base", "//net:test_support", + "//services/network:test_support", "//testing/gmock", "//testing/gtest", "//third_party/libyuv",
diff --git a/remoting/test/DEPS b/remoting/test/DEPS index 7a7eb3a..d6d217b 100644 --- a/remoting/test/DEPS +++ b/remoting/test/DEPS
@@ -9,5 +9,6 @@ "+remoting/signaling", "+ui/gfx", "+ui/events/keycodes/dom", + "+services/network", "+third_party/skia", ]
diff --git a/remoting/test/access_token_fetcher.cc b/remoting/test/access_token_fetcher.cc index 34e10af..c8c214bc 100644 --- a/remoting/test/access_token_fetcher.cc +++ b/remoting/test/access_token_fetcher.cc
@@ -15,6 +15,8 @@ #include "google_apis/google_api_keys.h" #include "net/url_request/url_fetcher.h" #include "remoting/base/url_request_context_getter.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" +#include "services/network/transitional_url_loader_factory_owner.h" namespace { const int kMaxGetTokensRetries = 3; @@ -76,12 +78,27 @@ /*delegate=*/this); } -void AccessTokenFetcher::CreateNewGaiaOAuthClientInstance() { - scoped_refptr<remoting::URLRequestContextGetter> request_context_getter; - request_context_getter = new remoting::URLRequestContextGetter( - base::ThreadTaskRunnerHandle::Get()); +void AccessTokenFetcher::SetURLLoaderFactoryForTesting( + scoped_refptr<network::SharedURLLoaderFactory> + url_loader_factory_for_testing) { + url_loader_factory_for_testing_ = url_loader_factory_for_testing; +} - auth_client_.reset(new gaia::GaiaOAuthClient(request_context_getter.get())); +void AccessTokenFetcher::CreateNewGaiaOAuthClientInstance() { + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory; + if (url_loader_factory_for_testing_) { + url_loader_factory = url_loader_factory_for_testing_; + } else { + scoped_refptr<remoting::URLRequestContextGetter> request_context_getter; + request_context_getter = new remoting::URLRequestContextGetter( + base::ThreadTaskRunnerHandle::Get()); + + url_loader_factory_owner_.reset( + new network::TransitionalURLLoaderFactoryOwner(request_context_getter)); + url_loader_factory = url_loader_factory_owner_->GetURLLoaderFactory(); + } + + auth_client_.reset(new gaia::GaiaOAuthClient(url_loader_factory)); } void AccessTokenFetcher::OnGetTokensResponse(const std::string& refresh_token,
diff --git a/remoting/test/access_token_fetcher.h b/remoting/test/access_token_fetcher.h index 46d499c..da0c9e7 100644 --- a/remoting/test/access_token_fetcher.h +++ b/remoting/test/access_token_fetcher.h
@@ -13,6 +13,11 @@ #include "base/memory/ref_counted.h" #include "google_apis/gaia/gaia_oauth_client.h" +namespace network { +class SharedURLLoaderFactory; +class TransitionalURLLoaderFactoryOwner; +}; // namespace network + namespace remoting { namespace test { @@ -41,6 +46,10 @@ const std::string& refresh_token, const AccessTokenCallback& callback); + void SetURLLoaderFactoryForTesting( + scoped_refptr<network::SharedURLLoaderFactory> + url_loader_factory_for_testing); + private: // gaia::GaiaOAuthClient::Delegate Interface. void OnGetTokensResponse(const std::string& refresh_token, @@ -77,6 +86,13 @@ // the Gaia service request. gaia::OAuthClientInfo oauth_client_info_; + // Used to feed network into |auth_client_|. + std::unique_ptr<network::TransitionalURLLoaderFactoryOwner> + url_loader_factory_owner_; + + scoped_refptr<network::SharedURLLoaderFactory> + url_loader_factory_for_testing_; + // Used to make token requests to GAIA. std::unique_ptr<gaia::GaiaOAuthClient> auth_client_;
diff --git a/remoting/test/access_token_fetcher_unittest.cc b/remoting/test/access_token_fetcher_unittest.cc index 9a383f2..12d40288 100644 --- a/remoting/test/access_token_fetcher_unittest.cc +++ b/remoting/test/access_token_fetcher_unittest.cc
@@ -8,11 +8,12 @@ #include "base/bind.h" #include "base/macros.h" -#include "base/message_loop/message_loop.h" -#include "base/message_loop/message_loop_current.h" #include "base/run_loop.h" +#include "base/test/scoped_task_environment.h" #include "google_apis/gaia/gaia_urls.h" -#include "net/url_request/test_url_fetcher_factory.h" +#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" +#include "services/network/test/test_url_loader_factory.h" +#include "services/network/test/test_utils.h" #include "testing/gtest/include/gtest/gtest.h" namespace { @@ -66,28 +67,33 @@ const std::string& refresh_token); protected: - // Test interface. - void SetUp() override; - void SetFakeResponse(const GURL& url, const std::string& data, net::HttpStatusCode code, - net::URLRequestStatus::Status status); + int net_error); + + scoped_refptr<network::SharedURLLoaderFactory> shared_factory() { + return shared_factory_; + } // Used for result verification std::string access_token_retrieved_; std::string refresh_token_retrieved_; private: - net::FakeURLFetcherFactory url_fetcher_factory_; - std::unique_ptr<base::MessageLoopForIO> message_loop_; + base::test::ScopedTaskEnvironment scoped_task_environment_; + network::TestURLLoaderFactory test_url_loader_factory_; + scoped_refptr<network::SharedURLLoaderFactory> shared_factory_; DISALLOW_COPY_AND_ASSIGN(AccessTokenFetcherTest); }; AccessTokenFetcherTest::AccessTokenFetcherTest() - : url_fetcher_factory_(nullptr) { -} + : scoped_task_environment_( + base::test::ScopedTaskEnvironment::MainThreadType::IO), + shared_factory_( + base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( + &test_url_loader_factory_)) {} AccessTokenFetcherTest::~AccessTokenFetcherTest() = default; @@ -101,30 +107,21 @@ done_closure.Run(); } -void AccessTokenFetcherTest::SetUp() { - if (!base::MessageLoopCurrent::Get()) { - // Create a temporary message loop if the current thread does not already - // have one so we can use its task runner to create a request object. - message_loop_.reset(new base::MessageLoopForIO); - } -} - -void AccessTokenFetcherTest::SetFakeResponse( - const GURL& url, - const std::string& data, - net::HttpStatusCode code, - net::URLRequestStatus::Status status) { - url_fetcher_factory_.SetFakeResponse(url, data, code, status); +void AccessTokenFetcherTest::SetFakeResponse(const GURL& url, + const std::string& data, + net::HttpStatusCode code, + int net_error) { + test_url_loader_factory_.AddResponse( + url, network::CreateResourceResponseHead(code), data, + network::URLLoaderCompletionStatus(net_error)); } TEST_F(AccessTokenFetcherTest, ExchangeAuthCodeForAccessToken) { SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(), - kAuthCodeExchangeValidResponse, net::HTTP_OK, - net::URLRequestStatus::SUCCESS); + kAuthCodeExchangeValidResponse, net::HTTP_OK, net::OK); SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_info_url(), - kValidTokenInfoResponse, net::HTTP_OK, - net::URLRequestStatus::SUCCESS); + kValidTokenInfoResponse, net::HTTP_OK, net::OK); base::RunLoop run_loop; AccessTokenCallback access_token_callback = @@ -132,6 +129,7 @@ base::Unretained(this), run_loop.QuitClosure()); AccessTokenFetcher access_token_fetcher; + access_token_fetcher.SetURLLoaderFactoryForTesting(shared_factory()); access_token_fetcher.GetAccessTokenFromAuthCode(kAuthCodeValue, access_token_callback); @@ -143,12 +141,10 @@ TEST_F(AccessTokenFetcherTest, ExchangeRefreshTokenForAccessToken) { SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(), - kRefreshTokenExchangeValidResponse, net::HTTP_OK, - net::URLRequestStatus::SUCCESS); + kRefreshTokenExchangeValidResponse, net::HTTP_OK, net::OK); SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_info_url(), - kValidTokenInfoResponse, net::HTTP_OK, - net::URLRequestStatus::SUCCESS); + kValidTokenInfoResponse, net::HTTP_OK, net::OK); base::RunLoop run_loop; AccessTokenCallback access_token_callback = @@ -156,6 +152,7 @@ base::Unretained(this), run_loop.QuitClosure()); AccessTokenFetcher access_token_fetcher; + access_token_fetcher.SetURLLoaderFactoryForTesting(shared_factory()); access_token_fetcher.GetAccessTokenFromRefreshToken(kRefreshTokenValue, access_token_callback); @@ -167,12 +164,10 @@ TEST_F(AccessTokenFetcherTest, MultipleAccessTokenCalls) { SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(), - kAuthCodeExchangeValidResponse, net::HTTP_OK, - net::URLRequestStatus::SUCCESS); + kAuthCodeExchangeValidResponse, net::HTTP_OK, net::OK); SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_info_url(), - kValidTokenInfoResponse, net::HTTP_OK, - net::URLRequestStatus::SUCCESS); + kValidTokenInfoResponse, net::HTTP_OK, net::OK); std::unique_ptr<base::RunLoop> run_loop; run_loop.reset(new base::RunLoop()); @@ -181,6 +176,7 @@ base::Unretained(this), run_loop->QuitClosure()); AccessTokenFetcher access_token_fetcher; + access_token_fetcher.SetURLLoaderFactoryForTesting(shared_factory()); access_token_fetcher.GetAccessTokenFromAuthCode(kAuthCodeValue, access_token_callback); @@ -195,8 +191,7 @@ // Update the response since we will call the refresh token method next. SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(), - kRefreshTokenExchangeValidResponse, net::HTTP_OK, - net::URLRequestStatus::SUCCESS); + kRefreshTokenExchangeValidResponse, net::HTTP_OK, net::OK); run_loop.reset(new base::RunLoop()); access_token_callback = @@ -232,7 +227,7 @@ TEST_F(AccessTokenFetcherTest, ExchangeAuthCode_Unauthorized_Error) { SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(), kAuthCodeExchangeValidResponse, net::HTTP_UNAUTHORIZED, - net::URLRequestStatus::FAILED); + net::ERR_FAILED); base::RunLoop run_loop; AccessTokenCallback access_token_callback = @@ -240,6 +235,7 @@ base::Unretained(this), run_loop.QuitClosure()); AccessTokenFetcher access_token_fetcher; + access_token_fetcher.SetURLLoaderFactoryForTesting(shared_factory()); access_token_fetcher.GetAccessTokenFromAuthCode(kAuthCodeValue, access_token_callback); @@ -253,7 +249,7 @@ TEST_F(AccessTokenFetcherTest, ExchangeRefreshToken_Unauthorized_Error) { SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(), kRefreshTokenExchangeValidResponse, net::HTTP_UNAUTHORIZED, - net::URLRequestStatus::FAILED); + net::ERR_FAILED); base::RunLoop run_loop; AccessTokenCallback access_token_callback = @@ -261,6 +257,7 @@ base::Unretained(this), run_loop.QuitClosure()); AccessTokenFetcher access_token_fetcher; + access_token_fetcher.SetURLLoaderFactoryForTesting(shared_factory()); access_token_fetcher.GetAccessTokenFromRefreshToken(kRefreshTokenValue, access_token_callback); @@ -274,7 +271,7 @@ TEST_F(AccessTokenFetcherTest, ExchangeAuthCode_NetworkError) { SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(), kAuthCodeExchangeValidResponse, net::HTTP_NOT_FOUND, - net::URLRequestStatus::FAILED); + net::ERR_FAILED); base::RunLoop run_loop; AccessTokenCallback access_token_callback = @@ -282,6 +279,7 @@ base::Unretained(this), run_loop.QuitClosure()); AccessTokenFetcher access_token_fetcher; + access_token_fetcher.SetURLLoaderFactoryForTesting(shared_factory()); access_token_fetcher.GetAccessTokenFromAuthCode(kAuthCodeValue, access_token_callback); @@ -295,7 +293,7 @@ TEST_F(AccessTokenFetcherTest, ExchangeRefreshToken_NetworkError) { SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(), kRefreshTokenExchangeValidResponse, net::HTTP_NOT_FOUND, - net::URLRequestStatus::FAILED); + net::ERR_FAILED); base::RunLoop run_loop; AccessTokenCallback access_token_callback = @@ -303,6 +301,7 @@ base::Unretained(this), run_loop.QuitClosure()); AccessTokenFetcher access_token_fetcher; + access_token_fetcher.SetURLLoaderFactoryForTesting(shared_factory()); access_token_fetcher.GetAccessTokenFromRefreshToken(kRefreshTokenValue, access_token_callback); @@ -315,12 +314,10 @@ TEST_F(AccessTokenFetcherTest, AuthCode_GetTokenInfoResponse_InvalidToken) { SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(), - kAuthCodeExchangeValidResponse, net::HTTP_OK, - net::URLRequestStatus::SUCCESS); + kAuthCodeExchangeValidResponse, net::HTTP_OK, net::OK); SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_info_url(), - kInvalidTokenInfoResponse, net::HTTP_OK, - net::URLRequestStatus::SUCCESS); + kInvalidTokenInfoResponse, net::HTTP_OK, net::OK); base::RunLoop run_loop; AccessTokenCallback access_token_callback = @@ -328,6 +325,7 @@ base::Unretained(this), run_loop.QuitClosure()); AccessTokenFetcher access_token_fetcher; + access_token_fetcher.SetURLLoaderFactoryForTesting(shared_factory()); access_token_fetcher.GetAccessTokenFromAuthCode(kAuthCodeValue, access_token_callback); @@ -340,8 +338,7 @@ TEST_F(AccessTokenFetcherTest, ExchangeAuthCodeForAccessToken_EmptyToken) { SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(), - kAuthCodeExchangeEmptyResponse, net::HTTP_OK, - net::URLRequestStatus::SUCCESS); + kAuthCodeExchangeEmptyResponse, net::HTTP_OK, net::OK); base::RunLoop run_loop; AccessTokenCallback access_token_callback = @@ -349,6 +346,7 @@ base::Unretained(this), run_loop.QuitClosure()); AccessTokenFetcher access_token_fetcher; + access_token_fetcher.SetURLLoaderFactoryForTesting(shared_factory()); access_token_fetcher.GetAccessTokenFromAuthCode(kAuthCodeValue, access_token_callback); @@ -361,12 +359,10 @@ TEST_F(AccessTokenFetcherTest, RefreshToken_GetTokenInfoResponse_InvalidToken) { SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(), - kRefreshTokenExchangeValidResponse, net::HTTP_OK, - net::URLRequestStatus::SUCCESS); + kRefreshTokenExchangeValidResponse, net::HTTP_OK, net::OK); SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_info_url(), - kInvalidTokenInfoResponse, net::HTTP_OK, - net::URLRequestStatus::SUCCESS); + kInvalidTokenInfoResponse, net::HTTP_OK, net::OK); base::RunLoop run_loop; AccessTokenCallback access_token_callback = @@ -374,6 +370,7 @@ base::Unretained(this), run_loop.QuitClosure()); AccessTokenFetcher access_token_fetcher; + access_token_fetcher.SetURLLoaderFactoryForTesting(shared_factory()); access_token_fetcher.GetAccessTokenFromRefreshToken(kRefreshTokenValue, access_token_callback); @@ -386,8 +383,7 @@ TEST_F(AccessTokenFetcherTest, ExchangeRefreshTokenForAccessToken_EmptyToken) { SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(), - kRefreshTokenExchangeEmptyResponse, net::HTTP_OK, - net::URLRequestStatus::SUCCESS); + kRefreshTokenExchangeEmptyResponse, net::HTTP_OK, net::OK); base::RunLoop run_loop; AccessTokenCallback access_token_callback = @@ -395,6 +391,7 @@ base::Unretained(this), run_loop.QuitClosure()); AccessTokenFetcher access_token_fetcher; + access_token_fetcher.SetURLLoaderFactoryForTesting(shared_factory()); access_token_fetcher.GetAccessTokenFromRefreshToken(kRefreshTokenValue, access_token_callback);
diff --git a/services/network/session_cleanup_cookie_store.cc b/services/network/session_cleanup_cookie_store.cc index 7396b34..74939b56 100644 --- a/services/network/session_cleanup_cookie_store.cc +++ b/services/network/session_cleanup_cookie_store.cc
@@ -14,19 +14,41 @@ #include "base/memory/ref_counted.h" #include "base/sequenced_task_runner.h" #include "base/task/post_task.h" +#include "base/values.h" #include "net/cookies/canonical_cookie.h" #include "net/cookies/cookie_constants.h" #include "net/cookies/cookie_util.h" #include "net/extras/sqlite/cookie_crypto_delegate.h" +#include "net/log/net_log.h" #include "url/gurl.h" namespace network { +namespace { + +std::unique_ptr<base::Value> CookieStoreOriginFiltered( + const std::string& origin, + bool is_https, + net::NetLogCaptureMode capture_mode) { + if (!capture_mode.include_cookies_and_credentials()) + return nullptr; + auto dict = std::make_unique<base::DictionaryValue>(); + dict->SetString("origin", origin); + dict->SetBoolean("is_https", is_https); + return dict; +} + +} // namespace + SessionCleanupCookieStore::SessionCleanupCookieStore( const scoped_refptr<net::SQLitePersistentCookieStore>& cookie_store) : persistent_store_(cookie_store) {} -SessionCleanupCookieStore::~SessionCleanupCookieStore() {} +SessionCleanupCookieStore::~SessionCleanupCookieStore() { + net_log_.AddEvent( + net::NetLogEventType::COOKIE_PERSISTENT_STORE_CLOSED, + net::NetLog::StringCallback("type", "SessionCleanupCookieStore")); +} void SessionCleanupCookieStore::DeleteSessionCookies( DeleteCookiePredicate delete_cookie_predicate) { @@ -46,6 +68,10 @@ !delete_cookie_predicate.Run(cookie.first, cookie.second)) { continue; } + net_log_.AddEvent( + net::NetLogEventType::COOKIE_PERSISTENT_STORE_ORIGIN_FILTERED, + base::BindRepeating(&CookieStoreOriginFiltered, cookie.first, + cookie.second)); session_only_cookies.push_back(cookie); } @@ -54,6 +80,7 @@ void SessionCleanupCookieStore::Load(const LoadedCallback& loaded_callback, const net::NetLogWithSource& net_log) { + net_log_ = net_log; persistent_store_->Load( base::BindRepeating(&SessionCleanupCookieStore::OnLoad, this, loaded_callback),
diff --git a/services/network/session_cleanup_cookie_store.h b/services/network/session_cleanup_cookie_store.h index 6c8b9456..2443984 100644 --- a/services/network/session_cleanup_cookie_store.h +++ b/services/network/session_cleanup_cookie_store.h
@@ -78,6 +78,8 @@ // will be kept. bool force_keep_session_state_ = false; + net::NetLogWithSource net_log_; + DISALLOW_COPY_AND_ASSIGN(SessionCleanupCookieStore); };
diff --git a/services/network/session_cleanup_cookie_store_unittest.cc b/services/network/session_cleanup_cookie_store_unittest.cc index 2d2791e..1a9fe536 100644 --- a/services/network/session_cleanup_cookie_store_unittest.cc +++ b/services/network/session_cleanup_cookie_store_unittest.cc
@@ -13,6 +13,9 @@ #include "base/task/task_scheduler/task_scheduler.h" #include "base/test/scoped_task_environment.h" #include "base/time/time.h" +#include "net/log/net_log_capture_mode.h" +#include "net/log/test_net_log.h" +#include "net/log/test_net_log_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" @@ -42,7 +45,7 @@ store_->Load( base::BindRepeating(&SessionCleanupCookieStoreTest::OnLoaded, base::Unretained(this), &run_loop, &cookies), - net::NetLogWithSource()); + net_log_.bound()); run_loop.Run(); return cookies; } @@ -85,6 +88,7 @@ base::CreateSequencedTaskRunnerWithTraits({base::MayBlock()}); base::ScopedTempDir temp_dir_; scoped_refptr<SessionCleanupCookieStore> store_; + net::BoundTestNetLog net_log_; }; TEST_F(SessionCleanupCookieStoreTest, TestPersistence) { @@ -127,6 +131,67 @@ cookies.clear(); } +TEST_F(SessionCleanupCookieStoreTest, TestNetLogIncludeCookies) { + CanonicalCookieVector cookies = CreateAndLoad(); + base::Time t = base::Time::Now(); + AddCookie("A", "B", "nonpersistent.com", "/", t); + + // Cookies from "nonpersistent.com" should be deleted. + store_->DeleteSessionCookies( + base::BindRepeating([](const std::string& domain, bool is_https) { + return domain == "nonpersistent.com"; + })); + DestroyStore(); + + net::TestNetLogEntry::List entries; + net_log_.GetEntries(&entries); + size_t pos = net::ExpectLogContainsSomewhere( + entries, 0, net::NetLogEventType::COOKIE_PERSISTENT_STORE_ORIGIN_FILTERED, + net::NetLogEventPhase::NONE); + std::string cookie_origin; + bool cookie_is_https = true; + EXPECT_TRUE(entries[pos].GetStringValue("origin", &cookie_origin)); + EXPECT_TRUE(entries[pos].GetBooleanValue("is_https", &cookie_is_https)); + EXPECT_EQ("nonpersistent.com", cookie_origin); + EXPECT_EQ(false, cookie_is_https); + pos = net::ExpectLogContainsSomewhere( + entries, pos, net::NetLogEventType::COOKIE_PERSISTENT_STORE_CLOSED, + net::NetLogEventPhase::NONE); + std::string event_type; + EXPECT_TRUE(entries[pos].GetStringValue("type", &event_type)); + EXPECT_EQ("SessionCleanupCookieStore", event_type); +} + +TEST_F(SessionCleanupCookieStoreTest, TestNetLogDoNotIncludeCookies) { + CanonicalCookieVector cookies = CreateAndLoad(); + base::Time t = base::Time::Now(); + AddCookie("A", "B", "nonpersistent.com", "/", t); + + net_log_.SetCaptureMode(net::NetLogCaptureMode::Default()); + // Cookies from "nonpersistent.com" should be deleted. + store_->DeleteSessionCookies( + base::BindRepeating([](const std::string& domain, bool is_https) { + return domain == "nonpersistent.com"; + })); + DestroyStore(); + + net::TestNetLogEntry::List entries; + net_log_.GetEntries(&entries); + size_t pos = net::ExpectLogContainsSomewhere( + entries, 0, net::NetLogEventType::COOKIE_PERSISTENT_STORE_ORIGIN_FILTERED, + net::NetLogEventPhase::NONE); + std::string cookie_origin; + bool cookie_is_https = true; + EXPECT_FALSE(entries[pos].GetStringValue("origin", &cookie_origin)); + EXPECT_FALSE(entries[pos].GetBooleanValue("is_https", &cookie_is_https)); + pos = net::ExpectLogContainsSomewhere( + entries, pos, net::NetLogEventType::COOKIE_PERSISTENT_STORE_CLOSED, + net::NetLogEventPhase::NONE); + std::string event_type; + EXPECT_TRUE(entries[pos].GetStringValue("type", &event_type)); + EXPECT_EQ("SessionCleanupCookieStore", event_type); +} + TEST_F(SessionCleanupCookieStoreTest, TestDeleteSessionCookies) { CanonicalCookieVector cookies = CreateAndLoad(); ASSERT_EQ(0u, cookies.size());
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json index e9486db..c5142a8 100644 --- a/testing/buildbot/chromium.android.json +++ b/testing/buildbot/chromium.android.json
@@ -11604,7 +11604,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -11648,7 +11647,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -11692,7 +11690,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -11736,7 +11733,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -11780,7 +11776,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -11824,7 +11819,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -11868,7 +11862,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -11912,7 +11905,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -11956,7 +11948,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -12000,7 +11991,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -12044,7 +12034,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -12088,7 +12077,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -12132,7 +12120,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -12177,7 +12164,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -12224,7 +12210,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -12269,7 +12254,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -12313,7 +12297,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -12357,7 +12340,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -12402,7 +12384,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -12450,7 +12431,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -12496,7 +12476,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -12543,7 +12522,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -12588,7 +12566,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -12633,7 +12610,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -12678,7 +12654,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -12722,7 +12697,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -12766,7 +12740,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -12810,7 +12783,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -12854,7 +12826,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -12898,7 +12869,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -12942,7 +12912,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -12986,7 +12955,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -13030,7 +12998,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -13074,7 +13041,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -13118,7 +13084,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -13162,7 +13127,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -13206,7 +13170,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -13250,7 +13213,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -13294,7 +13256,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -13338,7 +13299,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -13382,7 +13342,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -13426,7 +13385,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -13470,7 +13428,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -13514,7 +13471,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -13558,7 +13514,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -13602,7 +13557,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -13647,7 +13601,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -13691,7 +13644,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -13735,7 +13687,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -13779,7 +13730,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -13823,7 +13773,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -13867,7 +13816,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -13911,7 +13859,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -13955,7 +13902,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -13999,7 +13945,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -14043,7 +13988,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -14088,7 +14032,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -14132,7 +14075,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -14176,7 +14118,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -14220,7 +14161,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -14309,7 +14249,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -14354,7 +14293,6 @@ "os": "Android" } ], - "hard_timeout": 960, "output_links": [ { "link": [ @@ -17519,6 +17457,857 @@ } ] }, + "android-cronet-arm-dbg": { + "gtest_tests": [ + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "cronet_sample_test_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "cronet_sample_test_apk" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "cronet_smoketests_missing_native_library_instrumentation_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "cronet_smoketests_missing_native_library_instrumentation_apk" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "cronet_smoketests_platform_only_instrumentation_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "cronet_smoketests_platform_only_instrumentation_apk" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "cronet_test_instrumentation_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "cronet_test_instrumentation_apk" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "cronet_unittests_android" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "cronet_unittests_android" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "net_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "shards": 4 + }, + "test": "net_unittests" + } + ] + }, + "android-cronet-arm-rel": {}, + "android-cronet-arm64-dbg": { + "additional_compile_targets": [ + "cronet_package", + "cronet_perf_test_apk", + "cronet_sample_test_apk", + "cronet_smoketests_missing_native_library_instrumentation_apk", + "cronet_smoketests_platform_only_instrumentation_apk", + "cronet_test_instrumentation_apk", + "cronet_unittests_android", + "net_unittests" + ] + }, + "android-cronet-arm64-rel": { + "additional_compile_targets": [ + "cronet_package", + "cronet_perf_test_apk", + "cronet_sample_test_apk", + "cronet_smoketests_missing_native_library_instrumentation_apk", + "cronet_smoketests_platform_only_instrumentation_apk", + "cronet_test_instrumentation_apk", + "cronet_unittests_android", + "net_unittests" + ] + }, + "android-cronet-asan-arm-rel": { + "additional_compile_targets": [ + "cronet_package", + "cronet_perf_test_apk", + "cronet_sample_test_apk", + "cronet_smoketests_missing_native_library_instrumentation_apk", + "cronet_smoketests_platform_only_instrumentation_apk", + "cronet_test_instrumentation_apk", + "cronet_unittests_android", + "net_unittests" + ] + }, + "android-cronet-kitkat-arm-rel": { + "gtest_tests": [ + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "cronet_sample_test_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "cronet_sample_test_apk" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "cronet_smoketests_missing_native_library_instrumentation_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "cronet_smoketests_missing_native_library_instrumentation_apk" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "cronet_smoketests_platform_only_instrumentation_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "cronet_smoketests_platform_only_instrumentation_apk" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "cronet_test_instrumentation_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "cronet_test_instrumentation_apk" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "cronet_unittests_android" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "cronet_unittests_android" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "net_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "shards": 4 + }, + "test": "net_unittests" + } + ] + }, + "android-cronet-lollipop-arm-rel": {}, + "android-cronet-marshmallow-arm64-rel": { + "gtest_tests": [ + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "cronet_sample_test_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "MMB29Q", + "device_type": "bullhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "cronet_sample_test_apk" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "cronet_smoketests_missing_native_library_instrumentation_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "MMB29Q", + "device_type": "bullhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "cronet_smoketests_missing_native_library_instrumentation_apk" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "cronet_smoketests_platform_only_instrumentation_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "MMB29Q", + "device_type": "bullhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "cronet_smoketests_platform_only_instrumentation_apk" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "cronet_test_instrumentation_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "MMB29Q", + "device_type": "bullhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "cronet_test_instrumentation_apk" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "cronet_unittests_android" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "MMB29Q", + "device_type": "bullhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "cronet_unittests_android" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "net_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "MMB29Q", + "device_type": "bullhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "shards": 4 + }, + "test": "net_unittests" + } + ] + }, + "android-cronet-x86-dbg": { + "additional_compile_targets": [ + "cronet_package", + "cronet_perf_test_apk", + "cronet_sample_test_apk", + "cronet_smoketests_missing_native_library_instrumentation_apk", + "cronet_smoketests_platform_only_instrumentation_apk", + "cronet_test_instrumentation_apk", + "cronet_unittests_android", + "net_unittests" + ] + }, + "android-cronet-x86-rel": { + "additional_compile_targets": [ + "cronet_package", + "cronet_perf_test_apk", + "cronet_sample_test_apk", + "cronet_smoketests_missing_native_library_instrumentation_apk", + "cronet_smoketests_platform_only_instrumentation_apk", + "cronet_test_instrumentation_apk", + "cronet_unittests_android", + "net_unittests" + ] + }, "android-kitkat-arm-rel": { "additional_compile_targets": [ "cronet_test_instrumentation_apk",
diff --git a/testing/buildbot/filters/mash.browser_tests.filter b/testing/buildbot/filters/mash.browser_tests.filter index 5199c5b2..d31a67dc 100644 --- a/testing/buildbot/filters/mash.browser_tests.filter +++ b/testing/buildbot/filters/mash.browser_tests.filter
@@ -41,10 +41,10 @@ -BrowserNonClientFrameViewAshTest.TopViewInset/* # Direct access to ash window frames, tablet mode, overview mode, etc. --HostedAppNonClientFrameViewAshTest.* -NonHomeLauncherBrowserNonClientFrameViewAshTest.* # Fix immersive fullscreen mode in mash. https://crbug.com/844748. +# Needs EventGenerator to work across window tree hosts. crbug.com/814675 -ImmersiveModeBrowserViewTest.TestCaptionButtonsReceiveEventsInAppImmersiveMode* -ImmersiveModeBrowserViewTest.TestCaptionButtonsReceiveEventsInBrowserImmersiveMode*
diff --git a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter index 1dc1018..d5022c3e 100644 --- a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter +++ b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
@@ -83,6 +83,7 @@ # https://crbug.com/816684 Track Page Load Metrics. -PageLoadMetricsBrowserTest.LoadingMetricsFailed +-PageLoadMetricsBrowserTest.ReceivedCompleteResources # https://crbug.com/810329 DnsProbe browsertests that rely on delaying requests: -DnsProbeBrowserTest.NxdomainProbeResultWithWorkingSlowCorrections
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl index e7fb72d..fcedc44 100644 --- a/testing/buildbot/gn_isolate_map.pyl +++ b/testing/buildbot/gn_isolate_map.pyl
@@ -448,6 +448,10 @@ "label": "//components/cronet/android:cronet_package", "type": "additional_compile_target", }, + "cronet_perf_test_apk": { + "label": "//components/cronet/android:cronet_perf_test_apk", + "type": "additional_compile_target", + }, "cronet_sample_test_apk": { "label": "//components/cronet/android:cronet_sample_test_apk", "type": "console_test_launcher",
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index 8d57650..1693da1 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -173,6 +173,115 @@ 'use_swarming': False, 'os_type': 'android', }, + 'android-cronet-arm-dbg': { + 'test_suites': { + 'gtest_tests': 'cronet_gtests', + }, + 'swarming': { + 'dimension_sets': [ + { + 'device_os': 'KTU84P', + 'device_type': 'hammerhead', + 'os': 'Android', + }, + ], + }, + 'os_type': 'android', + }, + 'android-cronet-arm-rel': {}, + 'android-cronet-arm64-dbg': { + 'additional_compile_targets': [ + 'cronet_package', + 'cronet_perf_test_apk', + 'cronet_sample_test_apk', + 'cronet_smoketests_missing_native_library_instrumentation_apk', + 'cronet_smoketests_platform_only_instrumentation_apk', + 'cronet_test_instrumentation_apk', + 'cronet_unittests_android', + 'net_unittests', + ], + }, + 'android-cronet-arm64-rel': { + 'additional_compile_targets': [ + 'cronet_package', + 'cronet_perf_test_apk', + 'cronet_sample_test_apk', + 'cronet_smoketests_missing_native_library_instrumentation_apk', + 'cronet_smoketests_platform_only_instrumentation_apk', + 'cronet_test_instrumentation_apk', + 'cronet_unittests_android', + 'net_unittests', + ], + }, + 'android-cronet-asan-arm-rel': { + # TODO(jbudorick): Run tests on this on swarming after + # implementing a reasonable mechanism for doing so w/ asan. + 'additional_compile_targets': [ + 'cronet_package', + 'cronet_perf_test_apk', + 'cronet_sample_test_apk', + 'cronet_smoketests_missing_native_library_instrumentation_apk', + 'cronet_smoketests_platform_only_instrumentation_apk', + 'cronet_test_instrumentation_apk', + 'cronet_unittests_android', + 'net_unittests', + ], + }, + 'android-cronet-kitkat-arm-rel': { + 'test_suites': { + 'gtest_tests': 'cronet_gtests', + }, + 'swarming': { + 'dimension_sets': [ + { + 'device_os': 'KTU84P', + 'device_type': 'hammerhead', + 'os': 'Android', + }, + ], + }, + 'os_type': 'android', + }, + 'android-cronet-lollipop-arm-rel': {}, + 'android-cronet-marshmallow-arm64-rel': { + 'test_suites': { + 'gtest_tests': 'cronet_gtests', + }, + 'swarming': { + 'dimension_sets': [ + { + 'device_os': 'MMB29Q', + 'device_type': 'bullhead', + 'os': 'Android', + }, + ], + }, + 'os_type': 'android', + }, + 'android-cronet-x86-dbg': { + 'additional_compile_targets': [ + 'cronet_package', + 'cronet_perf_test_apk', + 'cronet_sample_test_apk', + 'cronet_smoketests_missing_native_library_instrumentation_apk', + 'cronet_smoketests_platform_only_instrumentation_apk', + 'cronet_test_instrumentation_apk', + 'cronet_unittests_android', + 'net_unittests', + ], + }, + 'android-cronet-x86-rel': { + 'additional_compile_targets': [ + 'cronet_package', + 'cronet_perf_test_apk', + 'cronet_sample_test_apk', + 'cronet_smoketests_missing_native_library_instrumentation_apk', + 'cronet_smoketests_platform_only_instrumentation_apk', + 'cronet_test_instrumentation_apk', + 'cronet_unittests_android', + 'net_unittests', + ], + }, 'android-kitkat-arm-rel': { 'additional_compile_targets': [ 'cronet_test_instrumentation_apk', @@ -293,7 +402,6 @@ 'os': 'Android', }, ], - 'hard_timeout': 960, }, 'os_type': 'android', },
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG index c3d9e7d..f71972b 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -56,9 +56,137 @@ crbug.com/591099 external/wpt/css/css-writing-modes/two-levels-of-orthogonal-flows-percentage.html [ Pass ] crbug.com/855279 fast/css/text-overflow-ellipsis-vertical-hittest.html [ Pass ] crbug.com/591099 fast/dom/inner-text-first-letter.html [ Pass ] -crbug.com/591099 fast/dom/nodesFromRect/nodesFromRect-basic.html [ Pass ] +crbug.com/591099 fast/dom/nodesFromRect/nodesFromRect-basic.html [ Failure Pass ] # New failures are appended below by the script. +crbug.com/874588 accessibility/adjacent-continuations-cause-assertion-failure.html [ Crash ] +crbug.com/874588 accessibility/anonymous-render-block-in-continuation-causes-crash.html [ Crash ] +crbug.com/874588 accessibility/aom-click-action.html [ Crash ] +crbug.com/874588 accessibility/aom-computed-accessible-node.html [ Crash ] +crbug.com/874588 accessibility/aom-computed-boolean-properties.html [ Crash ] +crbug.com/874588 accessibility/aom-computed-int-properties.html [ Crash ] +crbug.com/874588 accessibility/aom-computed-relation-accessors.html [ Crash ] +crbug.com/874588 accessibility/aom-computed-string-properties.html [ Crash ] +crbug.com/874588 accessibility/aom-relation-list-properties.html [ Crash ] +crbug.com/874588 accessibility/aom-relation-properties.html [ Crash ] +crbug.com/874588 accessibility/aom-string-properties.html [ Crash ] +crbug.com/874588 accessibility/aom.html [ Crash ] +crbug.com/874588 accessibility/appearance-affects-role.html [ Crash ] +crbug.com/874588 accessibility/aria-checkbox-checked-mixed.html [ Crash ] +crbug.com/874588 accessibility/aria-combo-box-with-delay-add.html [ Crash ] +crbug.com/874588 accessibility/aria-combo-box-with-delay.html [ Crash ] +crbug.com/874588 accessibility/aria-combo-box.html [ Crash ] +crbug.com/874588 accessibility/aria-controls.html [ Crash ] +crbug.com/874588 accessibility/aria-disabled.html [ Crash ] +crbug.com/874588 accessibility/aria-flowto.html [ Crash ] +crbug.com/874588 accessibility/aria-grid-readonly-propagation.html [ Crash ] +crbug.com/874588 accessibility/aria-hidden-children-not-in-text-from-content.html [ Crash ] +crbug.com/874588 accessibility/aria-hidden-hides-all-elements.html [ Crash ] +crbug.com/874588 accessibility/aria-hidden-update.html [ Crash ] +crbug.com/874588 accessibility/aria-hidden-updates-alldescendants.html [ Crash ] +crbug.com/874588 accessibility/aria-hidden-with-elements.html [ Crash ] +crbug.com/874588 accessibility/aria-hidden.html [ Crash ] +crbug.com/874588 accessibility/aria-label.html [ Crash ] +crbug.com/874588 accessibility/aria-labelledby-overrides-label.html [ Crash ] +crbug.com/874588 accessibility/aria-modal.html [ Crash ] +crbug.com/874588 accessibility/aria-option-role.html [ Crash ] +crbug.com/874588 accessibility/aria-orientation.html [ Crash ] +crbug.com/874588 accessibility/aria-owns-dynamic-changes.html [ Crash ] +crbug.com/874588 accessibility/aria-owns-ignores-leafs.html [ Crash ] +crbug.com/874588 accessibility/aria-owns-sends-notification.html [ Crash ] +crbug.com/874588 accessibility/aria-owns.html [ Crash ] +crbug.com/874588 accessibility/aria-relations-should-ignore-hidden-targets.html [ Crash ] +crbug.com/874588 accessibility/aria-roles.html [ Crash ] +crbug.com/874588 accessibility/aria-row-name.html [ Crash ] +crbug.com/874588 accessibility/aria-tab-roles.html [ Crash ] +crbug.com/874588 accessibility/aria-tables.html [ Crash ] +crbug.com/874588 accessibility/aria-tree.html [ Crash ] +crbug.com/874588 accessibility/aria-treeitem-checkable.html [ Crash ] +crbug.com/874588 accessibility/aria1.1-combo-box-with-delay.html [ Crash ] +crbug.com/874588 accessibility/aria1.1-combo-box.html [ Crash ] +crbug.com/874588 accessibility/bounds-calc.html [ Crash ] +crbug.com/874588 accessibility/br-element-has-correct-title.html [ Crash ] +crbug.com/874588 accessibility/canvas-fallback-content-labels.html [ Crash ] +crbug.com/874588 accessibility/container-node-delete-causes-crash.html [ Crash ] +crbug.com/874588 accessibility/css-first-letter-children.html [ Crash ] +crbug.com/874588 accessibility/css-generated-content.html [ Crash ] +crbug.com/874588 accessibility/css-styles.html [ Crash ] +crbug.com/874588 accessibility/default-language.html [ Crash ] +crbug.com/874588 accessibility/description-calc-aria-describedby.html [ Crash ] +crbug.com/874588 accessibility/description-calc-inputs.html [ Crash ] +crbug.com/874588 accessibility/description-calc-summary.html [ Crash ] +crbug.com/874588 accessibility/description-calc-table-caption.html [ Crash ] +crbug.com/874588 accessibility/disabled-controls.html [ Crash ] +crbug.com/874588 accessibility/disabled-not-selectable.html [ Crash ] +crbug.com/874588 accessibility/dl-role.html [ Crash ] +crbug.com/874588 accessibility/element-role-mapping-focusable.html [ Crash ] +crbug.com/874588 accessibility/first-letter-text-transform-causes-crash.html [ Crash ] +crbug.com/874588 accessibility/focus-action-clicks-element-in-active-descendant.html [ Crash ] +crbug.com/874588 accessibility/idref-newlines.html [ Crash ] +crbug.com/874588 accessibility/image-map-title-causes-crash.html [ Crash ] +crbug.com/874588 accessibility/image-map-update-parent-crash.html [ Crash ] +crbug.com/874588 accessibility/img-fallsback-to-title.html [ Crash ] +crbug.com/874588 accessibility/in-page-link-target.html [ Crash ] +crbug.com/874588 accessibility/inline-text-bidi-bounds-for-range.html [ Crash ] +crbug.com/874588 accessibility/inline-text-bounds-for-range-br.html [ Crash ] +crbug.com/874588 accessibility/inline-text-change-style.html [ Crash ] +crbug.com/874588 accessibility/inline-text-changes.html [ Crash ] +crbug.com/874588 accessibility/inline-text-word-boundaries.html [ Crash ] +crbug.com/874588 accessibility/inline-text-word-boundary-causes-crash.html [ Crash ] +crbug.com/874588 accessibility/input-aria-required.html [ Crash ] +crbug.com/874588 accessibility/input-mixed.html [ Crash ] +crbug.com/874588 accessibility/input-type-range-aria-value.html [ Crash ] +crbug.com/874588 accessibility/input-type-range-value-change.html [ Crash ] +crbug.com/874588 accessibility/input-type-text-caret-position.html [ Crash ] +crbug.com/874588 accessibility/insert-adjacent-html-causes-crash.xhtml [ Crash ] +crbug.com/874588 accessibility/insert-selected-option-into-select-causes-crash.html [ Crash ] +crbug.com/874588 accessibility/label-for-control-hittest.html [ Crash ] +crbug.com/874588 accessibility/language-meta-tag-dynamically-changing.html [ Crash ] +crbug.com/874588 accessibility/link-inside-button-accessible-text.html [ Crash ] +crbug.com/874588 accessibility/menu-item-crash.html [ Crash ] +crbug.com/874588 accessibility/menu-list-popup-reuses-objects.html [ Crash ] +crbug.com/874588 accessibility/menu-list-selection-changed.html [ Crash ] +crbug.com/874588 accessibility/meter-value.html [ Crash ] +crbug.com/874588 accessibility/name-calc-aria-hidden.html [ Crash ] +crbug.com/874588 accessibility/name-calc-aria-label.html [ Crash ] +crbug.com/874588 accessibility/name-calc-aria-labelledby.html [ Crash ] +crbug.com/874588 accessibility/name-calc-figure.html [ Crash ] +crbug.com/874588 accessibility/name-calc-group-inside-treeitem.html [ Crash ] +crbug.com/874588 accessibility/name-calc-inputs.html [ Crash ] +crbug.com/874588 accessibility/name-calc-native-markup-buttons.html [ Crash ] +crbug.com/874588 accessibility/name-calc-native-markup-input-buttons.html [ Crash ] +crbug.com/874588 accessibility/name-calc-summary.html [ Crash ] +crbug.com/874588 accessibility/name-calc-visibility.html [ Crash ] +crbug.com/874588 accessibility/nochildren-elements.html [ Crash ] +crbug.com/874588 accessibility/other-aria-attribute-change-sends-notification.html [ Crash ] +crbug.com/874588 accessibility/presentation-owned-elements.html [ Crash ] +crbug.com/874588 accessibility/presentational-leaf.html [ Crash ] +crbug.com/874588 accessibility/press-works-on-text-fields.html [ Crash ] +crbug.com/874588 accessibility/removed-anonymous-block-child-causes-crash.html [ Crash ] +crbug.com/874588 accessibility/render-counter-text.html [ Crash ] +crbug.com/874588 accessibility/role-attribute.html [ Crash ] +crbug.com/874588 accessibility/role-change.html [ Crash ] +crbug.com/874588 accessibility/selection-change-notification-aria-textbox.html [ Crash ] +crbug.com/874588 accessibility/selection-change-notification-input.html [ Crash ] +crbug.com/874588 accessibility/selection-change-notification-statictext.html [ Crash ] +crbug.com/874588 accessibility/selection-change-notification-textarea.html [ Crash ] +crbug.com/874588 accessibility/selection-follows-focus.html [ Crash ] +crbug.com/874588 accessibility/set-selection-child-offset.html [ Crash ] +crbug.com/874588 accessibility/table-caption.html [ Crash ] +crbug.com/874588 accessibility/table-cells-with-colspan.html [ Crash ] +crbug.com/874588 accessibility/table-destroyed-crash.html [ Crash ] +crbug.com/874588 accessibility/table-header-column-row.html [ Crash ] +crbug.com/874588 accessibility/table-headers.html [ Crash ] +crbug.com/874588 accessibility/table-row-with-aria-role.html [ Crash ] +crbug.com/874588 accessibility/table-with-empty-thead-causes-crash.html [ Crash ] +crbug.com/874588 accessibility/table-with-grid-roles.html [ Crash ] +crbug.com/874588 accessibility/table-with-hidden-head-section.html [ Crash ] +crbug.com/874588 accessibility/text-change-notification.html [ Crash ] +crbug.com/874588 accessibility/text-changes-with-relations.html [ Crash ] +crbug.com/874588 accessibility/textarea-caret-position.html [ Crash ] +crbug.com/874588 accessibility/textarea-selection.html [ Crash ] +crbug.com/874588 accessibility/title-ui-element-correctness.html [ Crash ] +crbug.com/874588 accessibility/whitespace-in-name-calc.html [ Crash ] crbug.com/591099 animations/rotate-transform-equivalent.html [ Failure ] crbug.com/728378 compositing/culling/tile-occlusion-boundaries.html [ Failure ] crbug.com/591099 compositing/iframes/floating-self-painting-frame.html [ Failure ] @@ -264,7 +392,7 @@ crbug.com/591099 external/wpt/html/browsers/the-window-object/window-open-noopener.html?_parent [ Timeout ] crbug.com/591099 external/wpt/html/browsers/the-window-object/window-open-noopener.html?_self [ Timeout ] crbug.com/591099 external/wpt/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-positive.html [ Timeout ] -crbug.com/591099 external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-domain-success.sub.html [ Failure ] +crbug.com/591099 external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-domain-success.sub.html [ Failure Pass ] crbug.com/591099 external/wpt/html/rendering/non-replaced-elements/the-hr-element-0/color.html [ Failure ] crbug.com/591099 external/wpt/html/rendering/non-replaced-elements/the-page/body-margin-2j.html [ Failure ] crbug.com/591099 external/wpt/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-img-auto.html [ Failure ] @@ -276,7 +404,7 @@ crbug.com/591099 external/wpt/html/semantics/scripting-1/the-script-element/async_010.htm [ Pass ] crbug.com/591099 external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-module.html [ Failure ] crbug.com/591099 external/wpt/html/user-activation/activation-api-iframe.tenative.html [ Failure ] -crbug.com/591099 external/wpt/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/canblock-window.html [ Failure ] +crbug.com/591099 external/wpt/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/canblock-window.html [ Failure Pass ] crbug.com/591099 external/wpt/infrastructure/reftest/reftest_ref_timeout.html [ Timeout ] crbug.com/591099 external/wpt/media-source/mediasource-avtracks.html [ Failure ] crbug.com/591099 external/wpt/media-source/mediasource-config-change-mp4-av-audio-bitrate.html [ Failure ] @@ -292,7 +420,6 @@ crbug.com/591099 external/wpt/requestidlecallback/callback-timeout.html [ Timeout ] crbug.com/591099 external/wpt/service-workers/service-worker/navigation-preload/broken-chunked-encoding.https.html [ Failure ] crbug.com/591099 external/wpt/speech-api/SpeechSynthesis-speak-twice.html [ Timeout ] -crbug.com/591099 external/wpt/svg/painting/reftests/markers-orient-001.svg [ Pass ] crbug.com/591099 external/wpt/svg/painting/reftests/paint-context-001.svg [ Failure ] crbug.com/591099 external/wpt/svg/painting/reftests/paint-context-002.svg [ Failure ] crbug.com/591099 external/wpt/svg/path/bearing/zero.svg [ Failure ] @@ -407,7 +534,7 @@ crbug.com/591099 fast/table/dynamic-descendant-percentage-height.html [ Failure ] crbug.com/591099 fast/table/empty-table-percent-height.html [ Failure ] crbug.com/591099 fast/table/height-percent-test-vertical.html [ Failure ] -crbug.com/591099 fast/table/percent-height-overflow-auto-content-in-cell.html [ Failure Pass ] +crbug.com/591099 fast/table/percent-height-overflow-auto-content-in-cell.html [ Failure ] crbug.com/591099 fast/table/percent-height-overflow-scroll-content-in-cell.html [ Failure ] crbug.com/858998 fast/table/table-continuation-outline-paint-crash.html [ Failure ] crbug.com/591099 fast/table/table-display-types-vertical.html [ Failure ] @@ -447,6 +574,10 @@ crbug.com/591099 http/tests/images/restyle-decode-error.html [ Failure ] crbug.com/591099 http/tests/local/fileapi/select-dragged-file-input.html [ Skip ] crbug.com/591099 http/tests/misc/object-embedding-svg-delayed-size-negotiation.xhtml [ Failure ] +crbug.com/591099 http/tests/navigation/form-targets-cross-site-frame-get.html [ Failure ] +crbug.com/591099 http/tests/navigation/form-targets-cross-site-frame-no-referrer.html [ Failure ] +crbug.com/591099 http/tests/navigation/form-targets-cross-site-frame-post.html [ Failure ] +crbug.com/591099 http/tests/navigation/form-with-enctype-targets-cross-site-frame.html [ Failure ] crbug.com/591099 http/tests/security/cors-rfc1918/addressspace-document-appcache.https.html [ Crash Failure ] crbug.com/591099 http/tests/security/cors-rfc1918/addressspace-document-csp-appcache.https.html [ Crash Failure Pass ] crbug.com/591099 http/tests/security/setDomainRelaxationForbiddenForURLScheme.html [ Crash ] @@ -455,7 +586,7 @@ crbug.com/591099 images/color-profile-image-filter-all.html [ Failure ] crbug.com/714962 inspector-protocol/css/css-get-platform-fonts.js [ Failure ] crbug.com/591099 inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot-pseudo-element.js [ Failure ] -crbug.com/714962 inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot-viewport.js [ Failure ] +crbug.com/714962 inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot-viewport.js [ Failure Pass ] crbug.com/591099 inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot.js [ Failure ] crbug.com/714962 inspector-protocol/layout-fonts/languages-emoji-rare-glyphs.js [ Failure ] crbug.com/591099 inspector-protocol/timeline/page-frames.js [ Failure Pass ] @@ -521,7 +652,7 @@ crbug.com/591099 printing/iframe-svg-in-object-print.html [ Failure ] crbug.com/591099 scrollbars/auto-scrollbar-fit-content.html [ Failure ] crbug.com/591099 scrollbars/overflow-scrollbar-combinations.html [ Failure ] -crbug.com/591099 shadow-dom/imperative-api.html [ Pass ] +crbug.com/591099 shadow-dom/imperative-api.html [ Failure Pass ] crbug.com/591099 storage/indexeddb/mozilla/test_objectStore_openKeyCursor.html [ Pass ] crbug.com/591099 storage/indexeddb/objectstore-cursor.html [ Pass ] crbug.com/591099 svg/custom/object-sizing-no-width-height.xhtml [ Failure ] @@ -550,7 +681,7 @@ crbug.com/591099 virtual/android/ [ Skip ] crbug.com/591099 virtual/exotic-color-space/ [ Skip ] crbug.com/591099 virtual/feature-policy-vibrate/ [ Skip ] -crbug.com/591099 virtual/gpu-rasterization/images/color-profile-image-filter-all.html [ Failure ] +crbug.com/591099 virtual/gpu-rasterization/images/color-profile-image-filter-all.html [ Failure Timeout ] crbug.com/591099 virtual/gpu/fast/canvas/canvas-blending-color-over-image.html [ Pass ] crbug.com/591099 virtual/gpu/fast/canvas/canvas-blending-gradient-over-pattern.html [ Pass Timeout ] crbug.com/591099 virtual/intersection-observer-v2/http/tests/intersection-observer/v2/cross-origin-effects.html [ Failure ] @@ -570,7 +701,7 @@ crbug.com/591099 virtual/paint-touchaction-rects/fast/events/touch/touch-rect-assert-first-layer-special.html [ Failure ] crbug.com/591099 virtual/paint-touchaction-rects/fast/events/touch/touch-rect-crash-on-unpromote-layer.html [ Failure ] crbug.com/591099 virtual/prefer_compositing_to_lcd_text/ [ Skip ] -crbug.com/591099 virtual/reporting-api/external/wpt/content-security-policy/reporting-api/reporting-api-doesnt-send-reports-without-violation.https.sub.html [ Pass Timeout ] +crbug.com/591099 virtual/reporting-api/external/wpt/content-security-policy/reporting-api/reporting-api-doesnt-send-reports-without-violation.https.sub.html [ Pass ] crbug.com/591099 virtual/scroll_customization/ [ Skip ] crbug.com/591099 virtual/scroll_customization/fast/events/touch/compositor-touch-hit-rects.html [ Failure ] crbug.com/591099 virtual/sharedarraybuffer/external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-simple-success.html [ Pass ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees index 967c5da0..1925422 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees
@@ -357,7 +357,6 @@ crbug.com/854192 paint/pagination/composited-paginated-outlined-box.html [ Failure ] # Paint invalidation test failures. Needs investigation. -crbug.com/857322 paint/invalidation/background/obscured-background-no-repaint.html [ Failure Crash ] crbug.com/854196 paint/invalidation/compositing/clipping-should-not-repaint-composited-descendants.html [ Failure ] crbug.com/854196 paint/invalidation/compositing/overlap-test-with-filter.html [ Failure ] crbug.com/854196 paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 index 748065b..c31e6771 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
@@ -1396,3 +1396,5 @@ Bug(none) fast/events/touch/compositor-touch-hit-rects-svg.html [ Failure ] Bug(none) virtual/paint-touchaction-rects/fast/events/touch/compositor-touch-hit-rects-svg.html [ Failure ] +Bug(none) fast/events/touch/compositor-touch-hit-rects-continuation.html [ Failure ] +Bug(none) virtual/paint-touchaction-rects/fast/events/touch/compositor-touch-hit-rects-continuation.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 6255b1b..315f82a 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -3925,6 +3925,9 @@ crbug.com/874567 [ Mac ] svg/custom/getscreenctm-in-scrollable-div-area-nested.xhtml [ Pass Failure ] crbug.com/874837 [ Win ] ietestcenter/css3/bordersbackgrounds/background-attachment-local-scrolling.htm [ Pass Failure ] crbug.com/874866 [ Mac ] virtual/new-remote-playback-pipeline/media/controls/modern/doubletap-to-jump-backwards-at-start.html [ Pass Timeout ] +crbug.com/874931 virtual/threaded/fast/scroll-behavior/smooth-scroll/mousewheel-scroll.html [ Pass Failure ] +crbug.com/875003 [ Win ] editing/caret/caret-is-hidden-when-no-focus.html [ Pass Failure ] +crbug.com/875009 virtual/enable_wasm_streaming/http/tests/wasm_streaming/wasm_response_apis.html [ Crash Pass ] crbug.com/715718 external/wpt/media-source/mediasource-activesourcebuffers.html [ Failure Pass ] crbug.com/715718 external/wpt/media-source/mediasource-remove.html [ Failure Pass ] @@ -4895,11 +4898,6 @@ crbug.com/871578 [ Mac ] virtual/outofblink-cors/external/wpt/xhr/timeout-multiple-fetches.html [ Failure Pass ] crbug.com/871578 [ Mac ] virtual/outofblink-cors-ns/external/wpt/xhr/timeout-multiple-fetches.html [ Failure Pass ] -# Flaky on various bots -crbug.com/869470 external/wpt/background-fetch/fetch.https.window.html [ Pass Failure ] -crbug.com/869470 external/wpt/background-fetch/get.https.window.html [ Pass Failure ] -crbug.com/869470 external/wpt/background-fetch/get-ids.https.window.html [ Pass Failure Crash ] - # Flaky middleClinkAutoscroll increased flakiness on Mac crbug.com/851090 [ Mac ] fast/events/middleClickAutoscroll-click-hyperlink.html [ Failure Pass ] crbug.com/851090 [ Mac ] virtual/mouseevent_fractional/fast/events/middleClickAutoscroll-nested-divs.html [ Failure Pass Timeout ]
diff --git a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/fetch.https.window.js b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/fetch.https.window.js index f146212..84350694 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/fetch.https.window.js +++ b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/fetch.https.window.js
@@ -8,8 +8,8 @@ promise_test(async test => { // 6.3.1.9.2: If |registration|’s active worker is null, then reject promise // with a TypeError and abort these steps. - const script = 'resources/sw.js'; - const scope = 'resources/scope' + location.pathname; + const script = 'service_workers/sw.js'; + const scope = 'service_workers/' + location.pathname; const serviceWorkerRegistration = await service_worker_unregister_and_register(test, script, scope); @@ -21,7 +21,7 @@ await promise_rejects( test, new TypeError(), serviceWorkerRegistration.backgroundFetch.fetch( - uniqueId(), ['resources/sw.js']), + uniqueId(), ['resources/feature-name.txt']), 'fetch() must reject on pending and installing workers'); }, 'Background Fetch requires an activated Service Worker'); @@ -44,7 +44,9 @@ // 6.3.1.7.2: If |internalRequest|’s mode is "no-cors", then return a // promise rejected with a TypeError. { - const request = new Request('resources/sw.js', {mode: 'no-cors'}); + const request = + new Request('resources/feature-name.txt', {mode: 'no-cors'}); + await promise_rejects( test, new TypeError(), backgroundFetch.fetch(uniqueId(), request), 'Requests must not be in no-cors mode'); @@ -56,8 +58,8 @@ // 6.3.1.9.2: If |bgFetchMap[id]| exists, reject |promise| with a TypeError // and abort these steps. return promise_rejects(test, new TypeError(), Promise.all([ - backgroundFetch.fetch('my-id', 'resources/sw.js'), - backgroundFetch.fetch('my-id', 'resources/feature-name.txt') + backgroundFetch.fetch('my-id', 'resources/feature-name.txt?1'), + backgroundFetch.fetch('my-id', 'resources/feature-name.txt?2') ])); }, 'IDs must be unique among active Background Fetch registrations');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/get-ids.https.window.js b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/get-ids.https.window.js index 28f5bc3..4c8bf26 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/get-ids.https.window.js +++ b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/get-ids.https.window.js
@@ -8,8 +8,8 @@ // https://wicg.github.io/background-fetch/#background-fetch-manager-getIds promise_test(async test => { - const script = 'resources/sw.js'; - const scope = 'resources/scope' + location.pathname; + const script = 'service_workers/sw.js'; + const scope = 'service_workers/' + location.pathname; const serviceWorkerRegistration = await service_worker_unregister_and_register(test, script, scope);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/get.https.window.js b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/get.https.window.js index 0b272db..a0b2acd 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/get.https.window.js +++ b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/get.https.window.js
@@ -8,8 +8,8 @@ // https://wicg.github.io/background-fetch/#background-fetch-manager-get promise_test(async test => { - const script = 'resources/sw.js'; - const scope = 'resources/scope' + location.pathname; + const script = 'service_workers/sw.js'; + const scope = 'service_workers/' + location.pathname; const serviceWorkerRegistration = await service_worker_unregister_and_register(test, script, scope);
diff --git a/third_party/WebKit/LayoutTests/fast/events/touch/compositor-touch-hit-rects-continuation-expected.txt b/third_party/WebKit/LayoutTests/fast/events/touch/compositor-touch-hit-rects-continuation-expected.txt new file mode 100644 index 0000000..f054ef4 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/events/touch/compositor-touch-hit-rects-continuation-expected.txt
@@ -0,0 +1,7 @@ +This tests verifies the hit test regions given to the compositor specifically for continuation case. It can only be run in DumpRenderTree. + +continuation: #document scrolling (13, 79, 101, 11) +continuation: #document scrolling (13, 90, 290, 12) +continuation: #document scrolling (13, 102, 121, 11) + +
diff --git a/third_party/WebKit/LayoutTests/fast/events/touch/compositor-touch-hit-rects-continuation.html b/third_party/WebKit/LayoutTests/fast/events/touch/compositor-touch-hit-rects-continuation.html new file mode 100644 index 0000000..c28f97168 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/events/touch/compositor-touch-hit-rects-continuation.html
@@ -0,0 +1,23 @@ +<!DOCTYPE html> +<html> +<head> +<link rel="stylesheet" href="resources/compositor-touch-hit-rects.css"> +</head> +<body> +<p id="description"> +This tests verifies the hit test regions given to the compositor specifically for +continuation case. It can only be run in DumpRenderTree.</p> + +<div id="tests"> + <div> + <b class="testcase" id="continuation"> + This b tag + <div>causes a</div> + continuation + </b> + </div> +</div> + +<div id="console"></div> +<script src="resources/compositor-touch-hit-rects.js"></script> +</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/position/containing-block-position-change-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/position/containing-block-position-change-expected.txt index 47bdeea0..d581392f 100644 --- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/position/containing-block-position-change-expected.txt +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/position/containing-block-position-change-expected.txt
@@ -20,12 +20,12 @@ { "object": "LayoutNGBlockFlow (positioned) DIV", "rect": [158, 74, 50, 50], - "reason": "style change" + "reason": "subtree" }, { "object": "LayoutNGBlockFlow (positioned) DIV", "rect": [100, 74, 50, 50], - "reason": "style change" + "reason": "subtree" } ] }
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/text-pattern-update-2-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/text-pattern-update-2-expected.txt index 3332943..e25edd7 100644 --- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/text-pattern-update-2-expected.txt +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/text-pattern-update-2-expected.txt
@@ -9,17 +9,17 @@ { "object": "InlineTextBox 'X'", "rect": [8, 8, 300, 100], - "reason": "SVG resource change" + "reason": "subtree" }, { "object": "InlineTextBox 'Y'", "rect": [8, 8, 300, 100], - "reason": "SVG resource change" + "reason": "subtree" }, { "object": "InlineTextBox 'Z'", "rect": [8, 8, 300, 100], - "reason": "SVG resource change" + "reason": "subtree" } ] }
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/text-pattern-update-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/text-pattern-update-expected.txt index edbb1e6..b9b5dc3 100644 --- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/text-pattern-update-expected.txt +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/text-pattern-update-expected.txt
@@ -9,7 +9,7 @@ { "object": "InlineTextBox 'X'", "rect": [8, 8, 100, 100], - "reason": "SVG resource change" + "reason": "subtree" } ] }
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/tspan-pattern-update-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/tspan-pattern-update-expected.txt index 42cd41e..bfa78fa 100644 --- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/tspan-pattern-update-expected.txt +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/tspan-pattern-update-expected.txt
@@ -9,7 +9,7 @@ { "object": "InlineTextBox 'Y'", "rect": [8, 8, 300, 100], - "reason": "SVG resource change" + "reason": "subtree" } ] }
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/table/animated-row-background-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/table/animated-row-background-expected.txt index 80e1961..49aa880e 100644 --- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/table/animated-row-background-expected.txt +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/table/animated-row-background-expected.txt
@@ -9,12 +9,12 @@ { "object": "LayoutTableRow TR id='row'", "rect": [8, 10, 210, 102], - "reason": "full" + "reason": "background" }, { "object": "LayoutImage IMG id='image'", "rect": [8, 114, 50, 50], - "reason": "full" + "reason": "image" } ] }
diff --git a/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_AdobeRGB_opaque.png b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_AdobeRGB_opaque.png new file mode 100644 index 0000000..c4496db --- /dev/null +++ b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_AdobeRGB_opaque.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_AdobeRGB_transparent.png b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_AdobeRGB_transparent.png new file mode 100644 index 0000000..3b4cfda5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_AdobeRGB_transparent.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_DisplayP3_opaque.png b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_DisplayP3_opaque.png new file mode 100644 index 0000000..e7a142c --- /dev/null +++ b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_DisplayP3_opaque.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_DisplayP3_transparent.png b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_DisplayP3_transparent.png new file mode 100644 index 0000000..0b03531 --- /dev/null +++ b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_DisplayP3_transparent.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_ProPhoto_opaque.png b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_ProPhoto_opaque.png new file mode 100644 index 0000000..a1dc7dd --- /dev/null +++ b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_ProPhoto_opaque.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_ProPhoto_transparent.png b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_ProPhoto_transparent.png new file mode 100644 index 0000000..be2eb12 --- /dev/null +++ b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_ProPhoto_transparent.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_Rec2020_opaque.png b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_Rec2020_opaque.png new file mode 100644 index 0000000..e2a2d14 --- /dev/null +++ b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_Rec2020_opaque.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_Rec2020_transparent.png b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_Rec2020_transparent.png new file mode 100644 index 0000000..960d7d8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_Rec2020_transparent.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_e-sRGB_opaque.png b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_e-sRGB_opaque.png new file mode 100644 index 0000000..557e947 --- /dev/null +++ b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_e-sRGB_opaque.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_e-sRGB_transparent.png b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_e-sRGB_transparent.png new file mode 100644 index 0000000..b9a7806 --- /dev/null +++ b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_e-sRGB_transparent.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_interlaced_AdobeRGB_opaque.png b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_interlaced_AdobeRGB_opaque.png new file mode 100644 index 0000000..80cf978 --- /dev/null +++ b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_interlaced_AdobeRGB_opaque.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_interlaced_AdobeRGB_transparent.png b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_interlaced_AdobeRGB_transparent.png new file mode 100644 index 0000000..3ec565f8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_interlaced_AdobeRGB_transparent.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_interlaced_DisplayP3_opaque.png b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_interlaced_DisplayP3_opaque.png new file mode 100644 index 0000000..5f3134b --- /dev/null +++ b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_interlaced_DisplayP3_opaque.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_interlaced_DisplayP3_transparent.png b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_interlaced_DisplayP3_transparent.png new file mode 100644 index 0000000..500a70e --- /dev/null +++ b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_interlaced_DisplayP3_transparent.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_interlaced_ProPhoto_opaque.png b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_interlaced_ProPhoto_opaque.png new file mode 100644 index 0000000..b5d0e07 --- /dev/null +++ b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_interlaced_ProPhoto_opaque.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_interlaced_ProPhoto_transparent.png b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_interlaced_ProPhoto_transparent.png new file mode 100644 index 0000000..e4ec3e4 --- /dev/null +++ b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_interlaced_ProPhoto_transparent.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_interlaced_Rec2020_opaque.png b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_interlaced_Rec2020_opaque.png new file mode 100644 index 0000000..c487d584 --- /dev/null +++ b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_interlaced_Rec2020_opaque.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_interlaced_Rec2020_transparent.png b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_interlaced_Rec2020_transparent.png new file mode 100644 index 0000000..78fe202 --- /dev/null +++ b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_interlaced_Rec2020_transparent.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_interlaced_e-sRGB_opaque.png b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_interlaced_e-sRGB_opaque.png new file mode 100644 index 0000000..c9d9e77 --- /dev/null +++ b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_interlaced_e-sRGB_opaque.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_interlaced_e-sRGB_transparent.png b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_interlaced_e-sRGB_transparent.png new file mode 100644 index 0000000..3016404 --- /dev/null +++ b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_interlaced_e-sRGB_transparent.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_interlaced_sRGB_opaque.png b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_interlaced_sRGB_opaque.png new file mode 100644 index 0000000..babf232a --- /dev/null +++ b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_interlaced_sRGB_opaque.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_interlaced_sRGB_transparent.png b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_interlaced_sRGB_transparent.png new file mode 100644 index 0000000..3016404 --- /dev/null +++ b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_interlaced_sRGB_transparent.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_sRGB_opaque.png b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_sRGB_opaque.png new file mode 100644 index 0000000..8a66534 --- /dev/null +++ b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_sRGB_opaque.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_sRGB_transparent.png b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_sRGB_transparent.png new file mode 100644 index 0000000..e51cda7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_16bit_sRGB_transparent.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_8bit_AdobeRGB_opaque.png b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_8bit_AdobeRGB_opaque.png new file mode 100644 index 0000000..8b787b5c --- /dev/null +++ b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_8bit_AdobeRGB_opaque.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_8bit_AdobeRGB_transparent.png b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_8bit_AdobeRGB_transparent.png new file mode 100644 index 0000000..727028e --- /dev/null +++ b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_8bit_AdobeRGB_transparent.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_8bit_DisplayP3_opaque.png b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_8bit_DisplayP3_opaque.png new file mode 100644 index 0000000..fe8bdd49 --- /dev/null +++ b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_8bit_DisplayP3_opaque.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_8bit_DisplayP3_transparent.png b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_8bit_DisplayP3_transparent.png new file mode 100644 index 0000000..b836afeb --- /dev/null +++ b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_8bit_DisplayP3_transparent.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_8bit_ProPhoto_opaque.png b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_8bit_ProPhoto_opaque.png new file mode 100644 index 0000000..5ecd868 --- /dev/null +++ b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_8bit_ProPhoto_opaque.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_8bit_ProPhoto_transparent.png b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_8bit_ProPhoto_transparent.png new file mode 100644 index 0000000..85a349dc --- /dev/null +++ b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_8bit_ProPhoto_transparent.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_8bit_Rec2020_opaque.png b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_8bit_Rec2020_opaque.png new file mode 100644 index 0000000..599cd34 --- /dev/null +++ b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_8bit_Rec2020_opaque.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_8bit_Rec2020_transparent.png b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_8bit_Rec2020_transparent.png new file mode 100644 index 0000000..ecf65c3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_8bit_Rec2020_transparent.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_8bit_e-sRGB_opaque.png b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_8bit_e-sRGB_opaque.png new file mode 100644 index 0000000..4b20278e --- /dev/null +++ b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_8bit_e-sRGB_opaque.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_8bit_e-sRGB_transparent.png b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_8bit_e-sRGB_transparent.png new file mode 100644 index 0000000..e38b29d --- /dev/null +++ b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_8bit_e-sRGB_transparent.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_8bit_sRGB_opaque.png b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_8bit_sRGB_opaque.png new file mode 100644 index 0000000..9cab6d1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_8bit_sRGB_opaque.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_8bit_sRGB_transparent.png b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_8bit_sRGB_transparent.png new file mode 100644 index 0000000..5fa01e6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/images/resources/png-16bit/2x2_8bit_sRGB_transparent.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/background/obscured-background-no-repaint.html b/third_party/WebKit/LayoutTests/paint/invalidation/background/obscured-background-no-repaint.html index 5552f12..12dd6c9 100644 --- a/third_party/WebKit/LayoutTests/paint/invalidation/background/obscured-background-no-repaint.html +++ b/third_party/WebKit/LayoutTests/paint/invalidation/background/obscured-background-no-repaint.html
@@ -49,29 +49,18 @@ testRunner.dumpAsText(); } - if (window.internals) - internals.runtimeFlags.paintUnderInvalidationCheckingEnabled = true; - function finish() { var layerTree = internals.layerTreeAsText(document, internals.LAYER_TREE_INCLUDES_PAINT_INVALIDATIONS); - var invalidations = JSON.parse(layerTree)["objectPaintInvalidations"]; - // Passes if there is no invalidations other than imgForAdvanceImageAnimation, - // or only invalidations because of background obscuration change. - // This is because before the delayed image decoder finishes decoding the image, - // we first assume the image is not opaque. If the image is found actually opaque - // after decoding, the background obscuration status of covered elements will - // change and cause paint invalidation. var invalidatedObjects = {}; - if (invalidations) { - for (var i = 0; i < invalidations.length; ++i) { - var object = invalidations[i].object; - if (object.indexOf('imgForAdvanceImageAnimation') != -1) - continue; - invalidatedObjects[object] = true; + for (var layer of JSON.parse(layerTree).layers) { + if (layer.paintInvalidations) { + for (var invalidation of layer.paintInvalidations) + invalidatedObjects[invalidation.object] = true; } } - - if (Object.keys(invalidatedObjects).length) + // Passes if there is no invalidations other than imgForAdvanceImageAnimation. + if (Object.keys(invalidatedObjects).length != 1 || + !Object.keys(invalidatedObjects)[0].includes('imgForAdvanceImageAnimation')) output.textContent = 'FAIL: Unexpected paint invalidations: ' + JSON.stringify(invalidatedObjects) + '\n' + layerTree; else output.textContent = 'PASS';
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/svg/text-pattern-update-2-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/svg/text-pattern-update-2-expected.txt index 1647bf07..076c09be 100644 --- a/third_party/WebKit/LayoutTests/paint/invalidation/svg/text-pattern-update-2-expected.txt +++ b/third_party/WebKit/LayoutTests/paint/invalidation/svg/text-pattern-update-2-expected.txt
@@ -20,17 +20,17 @@ { "object": "InlineTextBox 'X'", "rect": [8, 8, 300, 100], - "reason": "SVG resource change" + "reason": "subtree" }, { "object": "InlineTextBox 'Y'", "rect": [8, 8, 300, 100], - "reason": "SVG resource change" + "reason": "subtree" }, { "object": "InlineTextBox 'Z'", "rect": [8, 8, 300, 100], - "reason": "SVG resource change" + "reason": "subtree" } ] }
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/svg/text-pattern-update-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/svg/text-pattern-update-expected.txt index 55354ee..7a6bf3c 100644 --- a/third_party/WebKit/LayoutTests/paint/invalidation/svg/text-pattern-update-expected.txt +++ b/third_party/WebKit/LayoutTests/paint/invalidation/svg/text-pattern-update-expected.txt
@@ -20,7 +20,7 @@ { "object": "InlineTextBox 'X'", "rect": [8, 8, 100, 100], - "reason": "SVG resource change" + "reason": "subtree" } ] }
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/svg/tspan-pattern-update-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/svg/tspan-pattern-update-expected.txt index c84442f..4d76df4d 100644 --- a/third_party/WebKit/LayoutTests/paint/invalidation/svg/tspan-pattern-update-expected.txt +++ b/third_party/WebKit/LayoutTests/paint/invalidation/svg/tspan-pattern-update-expected.txt
@@ -20,7 +20,7 @@ { "object": "InlineTextBox 'Y'", "rect": [8, 8, 300, 100], - "reason": "SVG resource change" + "reason": "subtree" } ] }
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/table/animated-row-background-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/table/animated-row-background-expected.txt index 99018a1..0344b504 100644 --- a/third_party/WebKit/LayoutTests/paint/invalidation/table/animated-row-background-expected.txt +++ b/third_party/WebKit/LayoutTests/paint/invalidation/table/animated-row-background-expected.txt
@@ -20,12 +20,12 @@ { "object": "LayoutTableRow TR id='row'", "rect": [8, 10, 210, 102], - "reason": "full" + "reason": "background" }, { "object": "LayoutImage IMG id='image'", "rect": [8, 114, 50, 50], - "reason": "full" + "reason": "image" } ] }
diff --git a/third_party/WebKit/LayoutTests/portals/portals-api.html b/third_party/WebKit/LayoutTests/portals/portals-api.html new file mode 100644 index 0000000..3aa64eb2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/portals/portals-api.html
@@ -0,0 +1,11 @@ +<!DOCTYPE html> +<title>Portals API test</title> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<body> + <script> + test(function() { + assert_true(document.createElement('portal') instanceof HTMLPortalElement); + }, "portal element exists") + </script> +</body>
diff --git a/third_party/WebKit/LayoutTests/webexposed/element-instance-property-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/element-instance-property-listing-expected.txt index e01e9a0c..ed1e5e2a 100644 --- a/third_party/WebKit/LayoutTests/webexposed/element-instance-property-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/element-instance-property-listing-expected.txt
@@ -863,6 +863,7 @@ property valueType html element picture html element plaintext +html element portal html element pre property width html element progress
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt index 9f79e066..1735d82 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -3416,6 +3416,9 @@ interface HTMLPictureElement : HTMLElement attribute @@toStringTag method constructor +interface HTMLPortalElement : HTMLElement + attribute @@toStringTag + method constructor interface HTMLPreElement : HTMLElement attribute @@toStringTag getter width
diff --git a/third_party/arcore-android-sdk/BUILD.gn b/third_party/arcore-android-sdk/BUILD.gn index 417f8cd2f..c6b23c1 100644 --- a/third_party/arcore-android-sdk/BUILD.gn +++ b/third_party/arcore-android-sdk/BUILD.gn
@@ -10,30 +10,6 @@ jar_path = "libarcore_client_c.jar" } -if (!android_64bit_target_cpu || !build_apk_secondary_abi || - current_toolchain == android_secondary_abi_toolchain) { - copy("libarcore_library") { - if (current_cpu == "arm") { - sources = [ - "libraries/android_arm/libarcore_sdk_c_minimal.so", - ] - } else if (current_cpu == "arm64") { - sources = [ - "libraries/android_arm64/libarcore_sdk_c_minimal.so", - ] - } - outputs = [ - "${root_out_dir}/libarcore_sdk_c_minimal.so", - ] - } -} else { - group("libarcore_library_secondary_abi") { - public_deps = [ - ":libarcore_library($android_secondary_abi_toolchain)", - ] - } -} - config("libarcore_config") { include_dirs = [ "src/libraries/include/" ] }
diff --git a/third_party/arcore-android-sdk/README.chromium b/third_party/arcore-android-sdk/README.chromium index 3221dc8c..dc56206 100644 --- a/third_party/arcore-android-sdk/README.chromium +++ b/third_party/arcore-android-sdk/README.chromium
@@ -29,6 +29,9 @@ * https://github.com/google-ar/arcore-unity-sdk/blob/master/LICENSE Changes: +2018-08-10 - First, removed arcore shim copy target from BUILD.gn since it is no + longer needed. Second, added zero-byte dummy arcore library for AR + module support. 2018-07-26 - Added test-apks/ subdirectory for storing production versions of AR APKs for testing. 2018-07-19 - Updated BUILD.gn to support secondary abi (the previous change for
diff --git a/third_party/arcore-android-sdk/libarcore_dummy.so b/third_party/arcore-android-sdk/libarcore_dummy.so new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/third_party/arcore-android-sdk/libarcore_dummy.so
diff --git a/third_party/blink/public/BUILD.gn b/third_party/blink/public/BUILD.gn index 793b27f..bafa46b 100644 --- a/third_party/blink/public/BUILD.gn +++ b/third_party/blink/public/BUILD.gn
@@ -331,7 +331,6 @@ "platform/web_resource_timing_info.h", "platform/web_rtc_answer_options.h", "platform/web_rtc_api_name.h", - "platform/web_rtc_certificate.h", "platform/web_rtc_certificate_generator.h", "platform/web_rtc_configuration.h", "platform/web_rtc_data_channel_handler.h",
diff --git a/third_party/blink/public/platform/web_rtc_certificate.h b/third_party/blink/public/platform/web_rtc_certificate.h deleted file mode 100644 index 7d73419..0000000 --- a/third_party/blink/public/platform/web_rtc_certificate.h +++ /dev/null
@@ -1,79 +0,0 @@ -// 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 THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_RTC_CERTIFICATE_H_ -#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_RTC_CERTIFICATE_H_ - -#include "third_party/blink/public/platform/web_vector.h" - -#include "third_party/blink/public/platform/web_rtc_key_params.h" -#include "third_party/blink/public/platform/web_string.h" - -#include <memory> - -namespace blink { - -// https://w3c.github.io/webrtc-pc/#rtcdtlsfingerprint* -class WebRTCDtlsFingerprint { - public: - WebRTCDtlsFingerprint(WebString algorithm, WebString value) - : algorithm_(algorithm), value_(value) {} - - WebString Algorithm() const { return algorithm_; } - WebString Value() const { return value_; } - - private: - WebString algorithm_; - WebString value_; -}; - -// Corresponds to |rtc::RTCCertificatePEM| in WebRTC. -// See |WebRTCCertificate::ToPEM| and |WebRTCCertificateGenerator::FromPEM|. -class WebRTCCertificatePEM { - public: - WebRTCCertificatePEM(WebString private_key, WebString certificate) - : private_key_(private_key), certificate_(certificate) {} - - WebString PrivateKey() const { return private_key_; } - WebString Certificate() const { return certificate_; } - - private: - WebString private_key_; - WebString certificate_; -}; - -// WebRTCCertificate is an interface defining what Blink needs to know about -// certificates, hiding Chromium and WebRTC layer implementation details. It is -// possible to create shallow copies of the WebRTCCertificate. When all copies -// are destroyed, the implementation specific data must be freed. -// WebRTCCertificate objects thus act as references to the reference counted -// internal data. -class WebRTCCertificate { - public: - WebRTCCertificate() = default; - virtual ~WebRTCCertificate() = default; - - // Copies the WebRTCCertificate object without copying the underlying - // implementation specific (WebRTC layer) certificate. When all copies are - // destroyed the underlying data is freed. - virtual std::unique_ptr<WebRTCCertificate> ShallowCopy() const = 0; - - // Returns the expiration time in ms relative to epoch, 1970-01-01T00:00:00Z. - virtual uint64_t Expires() const = 0; - virtual WebVector<WebRTCDtlsFingerprint> GetFingerprints() const = 0; - // Creates a PEM strings representation of the certificate. See also - // |WebRTCCertificateGenerator::FromPEM|. - virtual WebRTCCertificatePEM ToPEM() const = 0; - // Checks if the two certificate objects represent the same certificate value, - // as should be the case for a clone and the original. - virtual bool Equals(const WebRTCCertificate& other) const = 0; - - private: - WebRTCCertificate(const WebRTCCertificate&) = delete; - WebRTCCertificate& operator=(const WebRTCCertificate&) = delete; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_RTC_CERTIFICATE_H_
diff --git a/third_party/blink/public/platform/web_rtc_certificate_generator.h b/third_party/blink/public/platform/web_rtc_certificate_generator.h index 4cde8d8..f5940a3d 100644 --- a/third_party/blink/public/platform/web_rtc_certificate_generator.h +++ b/third_party/blink/public/platform/web_rtc_certificate_generator.h
@@ -32,9 +32,9 @@ #define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_RTC_CERTIFICATE_GENERATOR_H_ #include "third_party/blink/public/platform/web_callbacks.h" -#include "third_party/blink/public/platform/web_rtc_certificate.h" #include "third_party/blink/public/platform/web_rtc_key_params.h" #include "third_party/blink/public/platform/web_string.h" +#include "third_party/webrtc/api/peerconnectioninterface.h" #include <memory> @@ -45,7 +45,7 @@ namespace blink { using WebRTCCertificateCallback = - WebCallbacks<std::unique_ptr<WebRTCCertificate>, void>; + WebCallbacks<rtc::scoped_refptr<rtc::RTCCertificate>, void>; // Interface defining a class that can generate WebRTCCertificates // asynchronously. @@ -72,8 +72,8 @@ virtual bool IsSupportedKeyParams(const WebRTCKeyParams&) = 0; // Creates a certificate from the PEM strings. See also - // |WebRTCCertificate::ToPEM|. - virtual std::unique_ptr<WebRTCCertificate> FromPEM( + // |rtc::RTCCertificate::ToPEM|. + virtual rtc::scoped_refptr<rtc::RTCCertificate> FromPEM( blink::WebString pem_private_key, blink::WebString pem_certificate) = 0; };
diff --git a/third_party/blink/public/platform/web_rtc_configuration.h b/third_party/blink/public/platform/web_rtc_configuration.h index 5d4b8da..2e7b75ed 100644 --- a/third_party/blink/public/platform/web_rtc_configuration.h +++ b/third_party/blink/public/platform/web_rtc_configuration.h
@@ -32,7 +32,6 @@ #define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_RTC_CONFIGURATION_H_ #include "third_party/blink/public/platform/web_common.h" -#include "third_party/blink/public/platform/web_rtc_certificate.h" #include "third_party/blink/public/platform/web_vector.h" #include "third_party/webrtc/api/peerconnectioninterface.h" @@ -51,7 +50,7 @@ webrtc::PeerConnectionInterface::kBundlePolicyBalanced; webrtc::PeerConnectionInterface::RtcpMuxPolicy rtcp_mux_policy = webrtc::PeerConnectionInterface::kRtcpMuxPolicyRequire; - WebVector<std::unique_ptr<WebRTCCertificate>> certificates; + WebVector<rtc::scoped_refptr<rtc::RTCCertificate>> certificates; int ice_candidate_pool_size = 0; WebRTCSdpSemantics sdp_semantics = WebRTCSdpSemantics::kDefault; };
diff --git a/third_party/blink/public/platform/web_runtime_features.h b/third_party/blink/public/platform/web_runtime_features.h index a11781d..55a5d0f 100644 --- a/third_party/blink/public/platform/web_runtime_features.h +++ b/third_party/blink/public/platform/web_runtime_features.h
@@ -117,7 +117,6 @@ BLINK_PLATFORM_EXPORT static void EnableNotifications(bool); BLINK_PLATFORM_EXPORT static void EnableOnDeviceChange(bool); BLINK_PLATFORM_EXPORT static void EnableOrientationEvent(bool); - BLINK_PLATFORM_EXPORT static void EnableOriginPolicy(bool); BLINK_PLATFORM_EXPORT static void EnableOverflowIconsForMediaControls(bool); BLINK_PLATFORM_EXPORT static void EnableOverlayScrollbars(bool); BLINK_PLATFORM_EXPORT static void EnableOutOfBlinkCORS(bool); @@ -131,6 +130,7 @@ BLINK_PLATFORM_EXPORT static void EnablePermissionsAPI(bool); BLINK_PLATFORM_EXPORT static void EnablePictureInPicture(bool); BLINK_PLATFORM_EXPORT static void EnablePictureInPictureAPI(bool); + BLINK_PLATFORM_EXPORT static void EnablePortals(bool); BLINK_PLATFORM_EXPORT static void EnablePreciseMemoryInfo(bool); BLINK_PLATFORM_EXPORT static void EnablePreloadDefaultIsMetadata(bool); BLINK_PLATFORM_EXPORT static void EnablePreloadImageSrcSetEnabled(bool);
diff --git a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.cc b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.cc index eb804767..10e3e7af 100644 --- a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.cc +++ b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.cc
@@ -51,7 +51,7 @@ Platform::Current()->CreateRTCCertificateGenerator()); if (!certificate_generator) return nullptr; - std::unique_ptr<WebRTCCertificate> certificate = + rtc::scoped_refptr<rtc::RTCCertificate> certificate = certificate_generator->FromPEM(pem_private_key, pem_certificate); if (!certificate) return nullptr;
diff --git a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.cc b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.cc index 346d8ccf..963f9e0b 100644 --- a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.cc +++ b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.cc
@@ -48,10 +48,10 @@ } if (wrapper_type_info == &V8RTCCertificate::wrapperTypeInfo) { RTCCertificate* certificate = wrappable->ToImpl<RTCCertificate>(); - WebRTCCertificatePEM pem = certificate->Certificate().ToPEM(); + rtc::RTCCertificatePEM pem = certificate->Certificate()->ToPEM(); WriteTag(kRTCCertificateTag); - WriteUTF8String(pem.PrivateKey()); - WriteUTF8String(pem.Certificate()); + WriteUTF8String(pem.private_key().c_str()); + WriteUTF8String(pem.certificate().c_str()); return true; } return false;
diff --git a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules_test.cc b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules_test.cc index 4d56531..6fd7f32 100644 --- a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules_test.cc +++ b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules_test.cc
@@ -157,7 +157,7 @@ V8TestingScope scope; // Make a certificate with the existing key above. - std::unique_ptr<WebRTCCertificate> web_certificate = + rtc::scoped_refptr<rtc::RTCCertificate> web_certificate = certificate_generator->FromPEM( WebString::FromUTF8(kEcdsaPrivateKey, sizeof(kEcdsaPrivateKey)), WebString::FromUTF8(kEcdsaCertificate, sizeof(kEcdsaCertificate))); @@ -171,9 +171,9 @@ ASSERT_TRUE(V8RTCCertificate::hasInstance(result, scope.GetIsolate())); RTCCertificate* new_certificate = V8RTCCertificate::ToImpl(result.As<v8::Object>()); - WebRTCCertificatePEM pem = new_certificate->Certificate().ToPEM(); - EXPECT_EQ(kEcdsaPrivateKey, pem.PrivateKey()); - EXPECT_EQ(kEcdsaCertificate, pem.Certificate()); + rtc::RTCCertificatePEM pem = new_certificate->Certificate()->ToPEM(); + EXPECT_EQ(kEcdsaPrivateKey, pem.private_key()); + EXPECT_EQ(kEcdsaCertificate, pem.certificate()); } TEST(V8ScriptValueSerializerForModulesTest, DecodeRTCCertificate) { @@ -198,9 +198,9 @@ ASSERT_TRUE(V8RTCCertificate::hasInstance(result, scope.GetIsolate())); RTCCertificate* new_certificate = V8RTCCertificate::ToImpl(result.As<v8::Object>()); - WebRTCCertificatePEM pem = new_certificate->Certificate().ToPEM(); - EXPECT_EQ(kEcdsaPrivateKey, pem.PrivateKey()); - EXPECT_EQ(kEcdsaCertificate, pem.Certificate()); + rtc::RTCCertificatePEM pem = new_certificate->Certificate()->ToPEM(); + EXPECT_EQ(kEcdsaPrivateKey, pem.private_key()); + EXPECT_EQ(kEcdsaCertificate, pem.certificate()); } TEST(V8ScriptValueSerializerForModulesTest, DecodeInvalidRTCCertificate) {
diff --git a/third_party/blink/renderer/core/animation/css_image_list_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_image_list_interpolation_type.cc index 51c7777..c1e352f 100644 --- a/third_party/blink/renderer/core/animation/css_image_list_interpolation_type.cc +++ b/third_party/blink/renderer/core/animation/css_image_list_interpolation_type.cc
@@ -152,7 +152,8 @@ return ListInterpolationFunctions::MaybeMergeSingles( std::move(start), std::move(end), ListInterpolationFunctions::LengthMatchingStrategy::kLowestCommonMultiple, - CSSImageInterpolationType::StaticMergeSingleConversions); + WTF::BindRepeating( + CSSImageInterpolationType::StaticMergeSingleConversions)); } InterpolationValue
diff --git a/third_party/blink/renderer/core/animation/css_length_list_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_length_list_interpolation_type.cc index 6afb7f99..dbfcf4af 100644 --- a/third_party/blink/renderer/core/animation/css_length_list_interpolation_type.cc +++ b/third_party/blink/renderer/core/animation/css_length_list_interpolation_type.cc
@@ -128,7 +128,7 @@ return ListInterpolationFunctions::MaybeMergeSingles( std::move(start), std::move(end), ListInterpolationFunctions::LengthMatchingStrategy::kLowestCommonMultiple, - LengthInterpolationFunctions::MergeSingles); + WTF::BindRepeating(LengthInterpolationFunctions::MergeSingles)); } InterpolationValue @@ -149,8 +149,9 @@ ListInterpolationFunctions::Composite( underlying_value_owner, underlying_fraction, *this, value, ListInterpolationFunctions::LengthMatchingStrategy::kLowestCommonMultiple, - LengthInterpolationFunctions::NonInterpolableValuesAreCompatible, - LengthInterpolationFunctions::Composite); + WTF::BindRepeating( + LengthInterpolationFunctions::NonInterpolableValuesAreCompatible), + WTF::BindRepeating(LengthInterpolationFunctions::Composite)); } void CSSLengthListInterpolationType::ApplyStandardPropertyValue(
diff --git a/third_party/blink/renderer/core/animation/css_shadow_list_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_shadow_list_interpolation_type.cc index 056643a..1a060ef 100644 --- a/third_party/blink/renderer/core/animation/css_shadow_list_interpolation_type.cc +++ b/third_party/blink/renderer/core/animation/css_shadow_list_interpolation_type.cc
@@ -133,7 +133,7 @@ return ListInterpolationFunctions::MaybeMergeSingles( std::move(start), std::move(end), ListInterpolationFunctions::LengthMatchingStrategy::kPadToLargest, - ShadowInterpolationFunctions::MaybeMergeSingles); + WTF::BindRepeating(ShadowInterpolationFunctions::MaybeMergeSingles)); } InterpolationValue @@ -151,8 +151,9 @@ ListInterpolationFunctions::Composite( underlying_value_owner, underlying_fraction, *this, value, ListInterpolationFunctions::LengthMatchingStrategy::kPadToLargest, - ShadowInterpolationFunctions::NonInterpolableValuesAreCompatible, - ShadowInterpolationFunctions::Composite); + WTF::BindRepeating( + ShadowInterpolationFunctions::NonInterpolableValuesAreCompatible), + WTF::BindRepeating(ShadowInterpolationFunctions::Composite)); } static scoped_refptr<ShadowList> CreateShadowList(
diff --git a/third_party/blink/renderer/core/animation/css_size_list_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_size_list_interpolation_type.cc index 167a785..04dfbbb 100644 --- a/third_party/blink/renderer/core/animation/css_size_list_interpolation_type.cc +++ b/third_party/blink/renderer/core/animation/css_size_list_interpolation_type.cc
@@ -157,7 +157,7 @@ return ListInterpolationFunctions::MaybeMergeSingles( std::move(start), std::move(end), ListInterpolationFunctions::LengthMatchingStrategy::kLowestCommonMultiple, - SizeInterpolationFunctions::MaybeMergeSingles); + WTF::BindRepeating(SizeInterpolationFunctions::MaybeMergeSingles)); } InterpolationValue @@ -176,9 +176,9 @@ ListInterpolationFunctions::Composite( underlying_value_owner, underlying_fraction, *this, value, ListInterpolationFunctions::LengthMatchingStrategy::kLowestCommonMultiple, - - SizeInterpolationFunctions::NonInterpolableValuesAreCompatible, - SizeInterpolationFunctions::Composite); + WTF::BindRepeating( + SizeInterpolationFunctions::NonInterpolableValuesAreCompatible), + WTF::BindRepeating(SizeInterpolationFunctions::Composite)); } void CSSSizeListInterpolationType::ApplyStandardPropertyValue(
diff --git a/third_party/blink/renderer/core/animation/list_interpolation_functions.cc b/third_party/blink/renderer/core/animation/list_interpolation_functions.cc index 443cb687..5985398 100644 --- a/third_party/blink/renderer/core/animation/list_interpolation_functions.cc +++ b/third_party/blink/renderer/core/animation/list_interpolation_functions.cc
@@ -5,6 +5,7 @@ #include "third_party/blink/renderer/core/animation/list_interpolation_functions.h" #include <memory> +#include "base/callback.h" #include "third_party/blink/renderer/core/animation/underlying_value_owner.h" #include "third_party/blink/renderer/core/css/css_value_list.h" #include "third_party/blink/renderer/platform/wtf/math_extras.h" @@ -132,7 +133,7 @@ InterpolationValue end(end_interpolable_list.Get(i % end_length)->Clone(), end_non_interpolable_list.Get(i % end_length)); PairwiseInterpolationValue result = - merge_single_item_conversions(std::move(start), std::move(end)); + merge_single_item_conversions.Run(std::move(start), std::move(end)); if (!result) return nullptr; result_start_interpolable_list->Set( @@ -242,8 +243,8 @@ ListInterpolationFunctions::LengthMatchingStrategy:: kLowestCommonMultiple || (i < a.length() && i < b.length())) { - if (!non_interpolable_values_are_compatible(a.Get(i % a.length()), - b.Get(i % b.length()))) { + if (!non_interpolable_values_are_compatible.Run(a.Get(i % a.length()), + b.Get(i % b.length()))) { return false; } } @@ -304,11 +305,11 @@ ToNonInterpolableList(*underlying_value.non_interpolable_value); for (size_t i = 0; i < final_length; i++) { - composite_item(underlying_interpolable_list.GetMutable(i), - underlying_non_interpolable_list.GetMutable(i), - underlying_fraction, - *interpolable_list.Get(i % value_length), - non_interpolable_list.Get(i % value_length)); + composite_item.Run(underlying_interpolable_list.GetMutable(i), + underlying_non_interpolable_list.GetMutable(i), + underlying_fraction, + *interpolable_list.Get(i % value_length), + non_interpolable_list.Get(i % value_length)); } } else { DCHECK_EQ(length_matching_strategy, LengthMatchingStrategy::kPadToLargest); @@ -322,10 +323,10 @@ ToNonInterpolableList(*underlying_value.non_interpolable_value); for (size_t i = 0; i < value_length; i++) { - composite_item(underlying_interpolable_list.GetMutable(i), - underlying_non_interpolable_list.GetMutable(i), - underlying_fraction, *interpolable_list.Get(i), - non_interpolable_list.Get(i)); + composite_item.Run(underlying_interpolable_list.GetMutable(i), + underlying_non_interpolable_list.GetMutable(i), + underlying_fraction, *interpolable_list.Get(i), + non_interpolable_list.Get(i)); } for (size_t i = value_length; i < final_length; i++) { underlying_interpolable_list.GetMutable(i)->Scale(underlying_fraction);
diff --git a/third_party/blink/renderer/core/animation/list_interpolation_functions.h b/third_party/blink/renderer/core/animation/list_interpolation_functions.h index 252b2a69..72161040 100644 --- a/third_party/blink/renderer/core/animation/list_interpolation_functions.h +++ b/third_party/blink/renderer/core/animation/list_interpolation_functions.h
@@ -26,8 +26,9 @@ enum class LengthMatchingStrategy { kLowestCommonMultiple, kPadToLargest }; using MergeSingleItemConversionsCallback = - PairwiseInterpolationValue (*)(InterpolationValue&& start, - InterpolationValue&& end); + base::RepeatingCallback<PairwiseInterpolationValue(InterpolationValue&&, + InterpolationValue&&)>; + static PairwiseInterpolationValue MaybeMergeSingles( InterpolationValue&& start, InterpolationValue&& end, @@ -41,12 +42,14 @@ EqualNonInterpolableValuesCallback); using NonInterpolableValuesAreCompatibleCallback = - bool (*)(const NonInterpolableValue*, const NonInterpolableValue*); - using CompositeItemCallback = void (*)(std::unique_ptr<InterpolableValue>&, - scoped_refptr<NonInterpolableValue>&, - double underlying_fraction, - const InterpolableValue&, - const NonInterpolableValue*); + base::RepeatingCallback<bool(const NonInterpolableValue*, + const NonInterpolableValue*)>; + using CompositeItemCallback = + base::RepeatingCallback<void(std::unique_ptr<InterpolableValue>&, + scoped_refptr<NonInterpolableValue>&, + double underlying_fraction, + const InterpolableValue&, + const NonInterpolableValue*)>; static void Composite(UnderlyingValueOwner&, double underlying_fraction, const InterpolationType&,
diff --git a/third_party/blink/renderer/core/core_idl_files.gni b/third_party/blink/renderer/core/core_idl_files.gni index 3dc993e3..062d701 100644 --- a/third_party/blink/renderer/core/core_idl_files.gni +++ b/third_party/blink/renderer/core/core_idl_files.gni
@@ -278,6 +278,7 @@ "html/forms/validity_state.idl", "html/media/html_audio_element.idl", "html/media/media_error.idl", + "html/portal/html_portal_element.idl", "html/track/audio_track_list.idl", "html/track/html_track_element.idl", "html/track/text_track.idl",
diff --git a/third_party/blink/renderer/core/editing/caret_display_item_client.cc b/third_party/blink/renderer/core/editing/caret_display_item_client.cc index 02b2bb4..96a9490 100644 --- a/third_party/blink/renderer/core/editing/caret_display_item_client.cc +++ b/third_party/blink/renderer/core/editing/caret_display_item_client.cc
@@ -143,7 +143,7 @@ LayoutBlock* new_layout_block = CaretLayoutBlock(caret_position.AnchorNode()); if (new_layout_block != layout_block_) { if (layout_block_) - layout_block_->SetMayNeedPaintInvalidation(); + layout_block_->SetShouldCheckForPaintInvalidation(); layout_block_ = new_layout_block; visual_rect_ = LayoutRect(); if (new_layout_block) { @@ -181,7 +181,7 @@ } if (needs_paint_invalidation_) - new_layout_block->SetMayNeedPaintInvalidation(); + new_layout_block->SetShouldCheckForPaintInvalidation(); } void CaretDisplayItemClient::InvalidatePaint( @@ -241,8 +241,7 @@ // The caret may change paint offset without changing visual rect, and we // need to invalidate the display item client if the block is doing full // paint invalidation. - if (IsImmediateFullPaintInvalidationReason( - layout_block_->FullPaintInvalidationReason())) { + if (layout_block_->ShouldDoFullPaintInvalidation()) { object_invalidator.InvalidateDisplayItemClient( *this, PaintInvalidationReason::kCaret); }
diff --git a/third_party/blink/renderer/core/frame/event_handler_registry.cc b/third_party/blink/renderer/core/frame/event_handler_registry.cc index fb49073..21094cf 100644 --- a/third_party/blink/renderer/core/frame/event_handler_registry.cc +++ b/third_party/blink/renderer/core/frame/event_handler_registry.cc
@@ -292,8 +292,14 @@ if (handler_class == kTouchStartOrMoveEventBlocking || handler_class == kTouchStartOrMoveEventBlockingLowLatency) { if (auto* node = target->ToNode()) { - if (auto* layout_object = node->GetLayoutObject()) + if (auto* layout_object = node->GetLayoutObject()) { layout_object->MarkEffectiveWhitelistedTouchActionChanged(); + auto* continuation = layout_object->VirtualContinuation(); + while (continuation) { + continuation->MarkEffectiveWhitelistedTouchActionChanged(); + continuation = continuation->VirtualContinuation(); + } + } } else if (auto* dom_window = target->ToLocalDOMWindow()) { // This event handler is on a window. Ensure the layout view is // invalidated because the layout view tracks the window's blocking
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc index d09a43b..38215ec 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.cc +++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -480,7 +480,7 @@ FrameRectsChanged(); if (auto* layout_view = GetLayoutView()) - layout_view->SetMayNeedPaintInvalidation(); + layout_view->SetShouldCheckForPaintInvalidation(); if (width_changed || height_changed) { ViewportSizeChanged(width_changed, height_changed); @@ -758,7 +758,7 @@ // LayoutView for paint invalidation. This simplifies our code as we // just always do a full tree walk. if (LayoutObject* container = root->Container()) - container->SetMayNeedPaintInvalidation(); + container->SetShouldCheckForPaintInvalidation(); } layout_subtree_root_list_.Clear(); } else { @@ -1391,7 +1391,7 @@ // If the layer has no visible content, then we shouldn't invalidate; but // if we're not compositing-inputs-clean, then we can't query // layer->SubtreeIsInvisible() here. - layout_object->SetMayNeedPaintInvalidationSubtree(); + layout_object->SetSubtreeShouldCheckForPaintInvalidation(); if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled() && !layer->NeedsRepaint()) { // Paint properties of the layer relative to its containing graphics @@ -2567,7 +2567,7 @@ // PrePaintTreeWalk can reach this frame. frame_view.SetNeedsPaintPropertyUpdate(); if (auto* owner = frame_view.GetFrame().OwnerLayoutObject()) - owner->SetMayNeedPaintInvalidation(); + owner->SetShouldCheckForPaintInvalidation(); } }); @@ -4201,7 +4201,7 @@ return; lifecycle_updates_throttled_ = false; if (auto* owner = GetFrame().OwnerLayoutObject()) - owner->SetMayNeedPaintInvalidation(); + owner->SetShouldCheckForPaintInvalidation(); LayoutView* layout_view = GetLayoutView(); bool layout_view_is_empty = layout_view && !layout_view->FirstChild();
diff --git a/third_party/blink/renderer/core/html/BUILD.gn b/third_party/blink/renderer/core/html/BUILD.gn index bcb101f..422cf608 100644 --- a/third_party/blink/renderer/core/html/BUILD.gn +++ b/third_party/blink/renderer/core/html/BUILD.gn
@@ -498,6 +498,8 @@ "media/picture_in_picture_interstitial.h", "plugin_document.cc", "plugin_document.h", + "portal/html_portal_element.cc", + "portal/html_portal_element.h", "rel_list.cc", "rel_list.h", "shadow/details_marker_control.cc",
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc index 63c7907..3e8eb51 100644 --- a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc +++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
@@ -361,7 +361,7 @@ return; canvas_is_clear_ = false; if (GetLayoutObject() && !LowLatencyEnabled()) - GetLayoutObject()->SetMayNeedPaintInvalidation(); + GetLayoutObject()->SetShouldCheckForPaintInvalidation(); if (Is2d() && context_->ShouldAntialias() && GetPage() && GetPage()->DeviceScaleFactorDeprecated() > 1.0f) { FloatRect inflated_rect = rect;
diff --git a/third_party/blink/renderer/core/html/forms/range_input_type.cc b/third_party/blink/renderer/core/html/forms/range_input_type.cc index c709be1..9a69f6a 100644 --- a/third_party/blink/renderer/core/html/forms/range_input_type.cc +++ b/third_party/blink/renderer/core/html/forms/range_input_type.cc
@@ -340,10 +340,8 @@ void RangeInputType::ListAttributeTargetChanged() { tick_mark_values_dirty_ = true; - if (GetElement().GetLayoutObject()) - GetElement() - .GetLayoutObject() - ->SetShouldDoFullPaintInvalidationIncludingNonCompositingDescendants(); + if (auto* object = GetElement().GetLayoutObject()) + object->SetSubtreeShouldDoFullPaintInvalidation(); Element* slider_track_element = SliderTrackElement(); if (slider_track_element->GetLayoutObject()) slider_track_element->GetLayoutObject()->SetNeedsLayout(
diff --git a/third_party/blink/renderer/core/html/html_tag_names.json5 b/third_party/blink/renderer/core/html/html_tag_names.json5 index 8dadbe2..c94a0b9d 100644 --- a/third_party/blink/renderer/core/html/html_tag_names.json5 +++ b/third_party/blink/renderer/core/html/html_tag_names.json5
@@ -358,6 +358,11 @@ name: "plaintext", interfaceName: "HTMLElement", }, + { + name: "portal", + interfaceName: "HTMLPortalElement", + interfaceHeaderDir: "third_party/blink/renderer/core/html/portal", + }, "pre", { name: "progress",
diff --git a/third_party/blink/renderer/core/html/portal/html_portal_element.cc b/third_party/blink/renderer/core/html/portal/html_portal_element.cc new file mode 100644 index 0000000..b93a9d3 --- /dev/null +++ b/third_party/blink/renderer/core/html/portal/html_portal_element.cc
@@ -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. + +#include "third_party/blink/renderer/core/html/portal/html_portal_element.h" + +#include "services/service_manager/public/cpp/interface_provider.h" +#include "third_party/blink/renderer/core/dom/document.h" +#include "third_party/blink/renderer/core/frame/local_frame.h" +#include "third_party/blink/renderer/core/html/html_unknown_element.h" +#include "third_party/blink/renderer/core/html_names.h" +#include "third_party/blink/renderer/platform/runtime_enabled_features.h" + +namespace blink { + +HTMLPortalElement::HTMLPortalElement(Document& document) + : HTMLFrameOwnerElement(HTMLNames::portalTag, document) {} + +HTMLPortalElement::~HTMLPortalElement() {} + +HTMLElement* HTMLPortalElement::Create(Document& document) { + if (RuntimeEnabledFeatures::PortalsEnabled()) + return new HTMLPortalElement(document); + return HTMLUnknownElement::Create(HTMLNames::portalTag, document); +} + +HTMLPortalElement::InsertionNotificationRequest HTMLPortalElement::InsertedInto( + ContainerNode* node) { + auto result = HTMLFrameOwnerElement::InsertedInto(node); + + Document& document = GetDocument(); + + if (node->IsInDocumentTree() && document.IsHTMLDocument()) { + document.GetFrame()->GetInterfaceProvider().GetInterface( + mojo::MakeRequest(&portal_ptr_)); + } + + return result; +} + +void HTMLPortalElement::RemovedFrom(ContainerNode* node) { + HTMLFrameOwnerElement::RemovedFrom(node); + + Document& document = GetDocument(); + + if (node->IsInDocumentTree() && document.IsHTMLDocument()) { + portal_ptr_.reset(); + } +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/html/portal/html_portal_element.h b/third_party/blink/renderer/core/html/portal/html_portal_element.h new file mode 100644 index 0000000..e459eca --- /dev/null +++ b/third_party/blink/renderer/core/html/portal/html_portal_element.h
@@ -0,0 +1,49 @@ +// 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 THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PORTAL_HTML_PORTAL_ELEMENT_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PORTAL_HTML_PORTAL_ELEMENT_H_ + +#include "third_party/blink/public/mojom/portal/portal.mojom-blink.h" +#include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/core/dom/node.h" +#include "third_party/blink/renderer/core/html/html_frame_owner_element.h" + +namespace blink { + +class Document; + +// The HTMLPortalElement implements the <portal> HTML element. The portal +// element can be used to embed another top-level browsing context, which can be +// activated using script. The portal element is still under development and not +// part of the HTML standard. It can be enabled by passing +// --enable-features=Portals. See +// https://github.com/KenjiBaheux/portals/blob/master/explainer.md for more +// details. +class CORE_EXPORT HTMLPortalElement : public HTMLFrameOwnerElement { + DEFINE_WRAPPERTYPEINFO(); + + public: + static HTMLElement* Create(Document&); + + ~HTMLPortalElement() override; + + private: + explicit HTMLPortalElement(Document&); + + // Node overrides + InsertionNotificationRequest InsertedInto(ContainerNode*) override; + void RemovedFrom(ContainerNode*) override; + + // HTMLFrameOwnerElement overrides + ParsedFeaturePolicy ConstructContainerPolicy(Vector<String>*) const override { + return ParsedFeaturePolicy(); + } + + mojom::blink::PortalPtr portal_ptr_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PORTAL_HTML_PORTAL_ELEMENT_H_
diff --git a/third_party/blink/renderer/core/html/portal/html_portal_element.idl b/third_party/blink/renderer/core/html/portal/html_portal_element.idl new file mode 100644 index 0000000..26a4055 --- /dev/null +++ b/third_party/blink/renderer/core/html/portal/html_portal_element.idl
@@ -0,0 +1,9 @@ +// 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. + +// https://github.com/KenjiBaheux/portals/blob/master/explainer.md + +[HTMLConstructor, RuntimeEnabled=Portals] +interface HTMLPortalElement : HTMLElement { +};
diff --git a/third_party/blink/renderer/core/layout/layout_block.cc b/third_party/blink/renderer/core/layout/layout_block.cc index eec4031..252aef8 100644 --- a/third_party/blink/renderer/core/layout/layout_block.cc +++ b/third_party/blink/renderer/core/layout/layout_block.cc
@@ -287,7 +287,7 @@ if (should_clip_overflow != HasOverflowClip()) { if (!should_clip_overflow) GetScrollableArea()->InvalidateAllStickyConstraints(); - SetMayNeedPaintInvalidationSubtree(); + SetSubtreeShouldCheckForPaintInvalidation(); // The overflow clip paint property depends on whether overflow clip is // present so we need to update paint properties if this changes. SetNeedsPaintPropertyUpdate(); @@ -790,7 +790,7 @@ void LayoutBlock::LayoutPositionedObject(LayoutBox* positioned_object, bool relayout_children, PositionedLayoutBehavior info) { - positioned_object->SetMayNeedPaintInvalidation(); + positioned_object->SetShouldCheckForPaintInvalidation(); SubtreeLayoutScope layout_scope(*positioned_object); // If positionedObject is fixed-positioned and moves with an absolute- @@ -950,9 +950,9 @@ parent->MarkContainerNeedsCollectInlines(); } -PaintInvalidationReason LayoutBlock::InvalidatePaint( +void LayoutBlock::InvalidatePaint( const PaintInvalidatorContext& context) const { - return BlockPaintInvalidator(*this).InvalidatePaint(context); + BlockPaintInvalidator(*this).InvalidatePaint(context); } void LayoutBlock::ClearPreviousVisualRects() {
diff --git a/third_party/blink/renderer/core/layout/layout_block.h b/third_party/blink/renderer/core/layout/layout_block.h index d3b523f3..e7cd22d 100644 --- a/third_party/blink/renderer/core/layout/layout_block.h +++ b/third_party/blink/renderer/core/layout/layout_block.h
@@ -481,8 +481,7 @@ } protected: - PaintInvalidationReason InvalidatePaint( - const PaintInvalidatorContext&) const override; + void InvalidatePaint(const PaintInvalidatorContext&) const override; void ClearPreviousVisualRects() override;
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow.cc b/third_party/blink/renderer/core/layout/layout_block_flow.cc index 313f270..0813f20 100644 --- a/third_party/blink/renderer/core/layout/layout_block_flow.cc +++ b/third_party/blink/renderer/core/layout/layout_block_flow.cc
@@ -1522,7 +1522,7 @@ CHECK(!next_sibling || next_sibling->IsBox()); next = ToLayoutBox(next_sibling); - child->SetMayNeedPaintInvalidation(); + child->SetShouldCheckForPaintInvalidation(); if (child_to_exclude == child) continue; // Skip this child, since it will be positioned by the @@ -3868,7 +3868,7 @@ LayoutBox& child = *floating_object.GetLayoutObject(); // FIXME Investigate if this can be removed. crbug.com/370006 - child.SetMayNeedPaintInvalidation(); + child.SetShouldCheckForPaintInvalidation(); logical_top_margin_edge = std::max(logical_top_margin_edge,
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow_line.cc b/third_party/blink/renderer/core/layout/layout_block_flow_line.cc index 5e5e60f..527f2e5 100644 --- a/third_party/blink/renderer/core/layout/layout_block_flow_line.cc +++ b/third_party/blink/renderer/core/layout/layout_block_flow_line.cc
@@ -1955,7 +1955,7 @@ if (o->IsAtomicInlineLevel() || o->IsFloating() || o->IsOutOfFlowPositioned()) { LayoutBox* box = ToLayoutBox(o); - box->SetMayNeedPaintInvalidation(); + box->SetShouldCheckForPaintInvalidation(); UpdateBlockChildDirtyBitsBeforeLayout(relayout_children, *box);
diff --git a/third_party/blink/renderer/core/layout/layout_box.cc b/third_party/blink/renderer/core/layout/layout_box.cc index 8b13b620..06476d1 100644 --- a/third_party/blink/renderer/core/layout/layout_box.cc +++ b/third_party/blink/renderer/core/layout/layout_box.cc
@@ -1781,8 +1781,8 @@ SetNeedsPaintPropertyUpdate(); } - // TODO(chrishtr): support PaintInvalidationReason::kDelayedFull for animated - // border images. + // TODO(chrishtr): support delayed paint invalidation for animated border + // images. if ((StyleRef().BorderImage().GetImage() && StyleRef().BorderImage().GetImage()->Data() == image) || (StyleRef().MaskBoxImage().GetImage() && @@ -1864,14 +1864,14 @@ // The location may change because of layout of other objects. Should check // this object for paint invalidation. if (!NeedsLayout()) - SetMayNeedPaintInvalidation(); + SetShouldCheckForPaintInvalidation(); } void LayoutBox::SizeChanged() { // The size may change because of layout of other objects. Should check this // object for paint invalidation. if (!NeedsLayout()) - SetMayNeedPaintInvalidation(); + SetShouldCheckForPaintInvalidation(); if (GetNode() && GetNode()->IsElementNode()) { Element& element = ToElement(*GetNode()); @@ -1895,25 +1895,23 @@ if (MayNeedPaintInvalidationAnimatedBackgroundImage() && !BackgroundIsKnownToBeObscured()) { SetShouldDoFullPaintInvalidationWithoutGeometryChange( - PaintInvalidationReason::kDelayedFull); + PaintInvalidationReason::kBackground); + SetShouldDelayFullPaintInvalidation(); } - if (FullPaintInvalidationReason() != PaintInvalidationReason::kDelayedFull || - !IntersectsVisibleViewport()) + if (!ShouldDelayFullPaintInvalidation() || !IntersectsVisibleViewport()) return; - // Do regular full paint invalidation if the object with - // PaintInvalidationReason::kDelayedFull is onscreen. - // Conservatively assume the delayed paint invalidation was caused by - // background image change. + // Do regular full paint invalidation if the object with delayed paint + // invalidation is onscreen. Conservatively assume the delayed paint + // invalidation was caused by background image change. SetBackgroundChangedSinceLastPaintInvalidation(); SetShouldDoFullPaintInvalidationWithoutGeometryChange( - PaintInvalidationReason::kFull); + FullPaintInvalidationReason()); } -PaintInvalidationReason LayoutBox::InvalidatePaint( - const PaintInvalidatorContext& context) const { - return BoxPaintInvalidator(*this, context).InvalidatePaint(); +void LayoutBox::InvalidatePaint(const PaintInvalidatorContext& context) const { + BoxPaintInvalidator(*this, context).InvalidatePaint(); } LayoutRect LayoutBox::OverflowClipRect(
diff --git a/third_party/blink/renderer/core/layout/layout_box.h b/third_party/blink/renderer/core/layout/layout_box.h index f38d253..eaebbfe 100644 --- a/third_party/blink/renderer/core/layout/layout_box.h +++ b/third_party/blink/renderer/core/layout/layout_box.h
@@ -1511,8 +1511,7 @@ void ComputeSelfHitTestRects(Vector<LayoutRect>&, const LayoutPoint& layer_offset) const override; - PaintInvalidationReason InvalidatePaint( - const PaintInvalidatorContext&) const override; + void InvalidatePaint(const PaintInvalidatorContext&) const override; bool ColumnFlexItemHasStretchAlignment() const; bool IsStretchingColumnFlexItem() const;
diff --git a/third_party/blink/renderer/core/layout/layout_box_test.cc b/third_party/blink/renderer/core/layout/layout_box_test.cc index 30156c6..22b3c913 100644 --- a/third_party/blink/renderer/core/layout/layout_box_test.cc +++ b/third_party/blink/renderer/core/layout/layout_box_test.cc
@@ -453,7 +453,7 @@ bool MaybeAnimated() override { return true; } }; -TEST_F(LayoutBoxTest, DeferredInvalidation) { +TEST_F(LayoutBoxTest, DelayedInvalidation) { SetBodyInnerHTML("<img id='image' style='width: 100px; height: 100px;'/>"); auto* obj = ToLayoutBox(GetLayoutObjectByElementId("image")); ASSERT_TRUE(obj); @@ -465,19 +465,24 @@ ToLayoutImage(obj)->ImageResource()->SetImageResource(image); ASSERT_TRUE(ToLayoutImage(obj)->CachedImage()->GetImage()->MaybeAnimated()); - // CanDeferInvalidation::kYes results in a deferred invalidation. obj->ClearPaintInvalidationFlags(); + EXPECT_FALSE(obj->ShouldDoFullPaintInvalidation()); EXPECT_EQ(obj->FullPaintInvalidationReason(), PaintInvalidationReason::kNone); - obj->ImageChanged(image, ImageResourceObserver::CanDeferInvalidation::kYes); - EXPECT_EQ(obj->FullPaintInvalidationReason(), - PaintInvalidationReason::kDelayedFull); + EXPECT_FALSE(obj->ShouldDelayFullPaintInvalidation()); - // CanDeferInvalidation::kNo results in a immediate invalidation. - obj->ClearPaintInvalidationFlags(); - EXPECT_EQ(obj->FullPaintInvalidationReason(), PaintInvalidationReason::kNone); - obj->ImageChanged(image, ImageResourceObserver::CanDeferInvalidation::kNo); + // CanDeferInvalidation::kYes results in a deferred invalidation. + obj->ImageChanged(image, ImageResourceObserver::CanDeferInvalidation::kYes); + EXPECT_FALSE(obj->ShouldDoFullPaintInvalidation()); EXPECT_EQ(obj->FullPaintInvalidationReason(), PaintInvalidationReason::kImage); + EXPECT_TRUE(obj->ShouldDelayFullPaintInvalidation()); + + // CanDeferInvalidation::kNo results in a immediate invalidation. + obj->ImageChanged(image, ImageResourceObserver::CanDeferInvalidation::kNo); + EXPECT_TRUE(obj->ShouldDoFullPaintInvalidation()); + EXPECT_EQ(obj->FullPaintInvalidationReason(), + PaintInvalidationReason::kImage); + EXPECT_FALSE(obj->ShouldDelayFullPaintInvalidation()); } TEST_F(LayoutBoxTest, MarkerContainerLayoutOverflowRect) {
diff --git a/third_party/blink/renderer/core/layout/layout_deprecated_flexible_box.cc b/third_party/blink/renderer/core/layout/layout_deprecated_flexible_box.cc index 1d8a9b6e..f7ff1a8a 100644 --- a/third_party/blink/renderer/core/layout/layout_deprecated_flexible_box.cc +++ b/third_party/blink/renderer/core/layout/layout_deprecated_flexible_box.cc
@@ -1260,7 +1260,7 @@ const LayoutPoint& location) { // FIXME Investigate if this can be removed based on other flags. // crbug.com/370010 - child->SetMayNeedPaintInvalidation(); + child->SetShouldCheckForPaintInvalidation(); // Place the child. child->SetLocation(location);
diff --git a/third_party/blink/renderer/core/layout/layout_embedded_content.cc b/third_party/blink/renderer/core/layout/layout_embedded_content.cc index d9de52d..0023ca9 100644 --- a/third_party/blink/renderer/core/layout/layout_embedded_content.cc +++ b/third_party/blink/renderer/core/layout/layout_embedded_content.cc
@@ -278,6 +278,13 @@ EmbeddedContentPainter(*this).PaintReplaced(paint_info, paint_offset); } +void LayoutEmbeddedContent::InvalidatePaint( + const PaintInvalidatorContext& context) const { + LayoutReplaced::InvalidatePaint(context); + if (auto* plugin = Plugin()) + plugin->InvalidatePaint(); +} + CursorDirective LayoutEmbeddedContent::GetCursor(const LayoutPoint& point, Cursor& cursor) const { if (Plugin()) {
diff --git a/third_party/blink/renderer/core/layout/layout_embedded_content.h b/third_party/blink/renderer/core/layout/layout_embedded_content.h index dd85f9b..8f59865 100644 --- a/third_party/blink/renderer/core/layout/layout_embedded_content.h +++ b/third_party/blink/renderer/core/layout/layout_embedded_content.h
@@ -73,6 +73,7 @@ void UpdateLayout() override; void PaintReplaced(const PaintInfo&, const LayoutPoint& paint_offset) const override; + void InvalidatePaint(const PaintInvalidatorContext&) const final; CursorDirective GetCursor(const LayoutPoint&, Cursor&) const final; bool CanBeSelectionLeafInternal() const final { return true; }
diff --git a/third_party/blink/renderer/core/layout/layout_embedded_object.cc b/third_party/blink/renderer/core/layout/layout_embedded_object.cc index 7baf19b..a136627 100644 --- a/third_party/blink/renderer/core/layout/layout_embedded_object.cc +++ b/third_party/blink/renderer/core/layout/layout_embedded_object.cc
@@ -34,7 +34,6 @@ #include "third_party/blink/renderer/core/layout/layout_analyzer.h" #include "third_party/blink/renderer/core/layout/layout_view.h" #include "third_party/blink/renderer/core/page/page.h" -#include "third_party/blink/renderer/core/paint/embedded_object_paint_invalidator.h" #include "third_party/blink/renderer/core/paint/embedded_object_painter.h" #include "third_party/blink/renderer/platform/text/platform_locale.h" @@ -89,11 +88,6 @@ EmbeddedObjectPainter(*this).PaintReplaced(paint_info, paint_offset); } -PaintInvalidationReason LayoutEmbeddedObject::InvalidatePaint( - const PaintInvalidatorContext& context) const { - return EmbeddedObjectPaintInvalidator(*this, context).InvalidatePaint(); -} - void LayoutEmbeddedObject::UpdateLayout() { DCHECK(NeedsLayout()); LayoutAnalyzer::Scope analyzer(*this);
diff --git a/third_party/blink/renderer/core/layout/layout_embedded_object.h b/third_party/blink/renderer/core/layout/layout_embedded_object.h index 8ee32cd..42cd2a20 100644 --- a/third_party/blink/renderer/core/layout/layout_embedded_object.h +++ b/third_party/blink/renderer/core/layout/layout_embedded_object.h
@@ -52,8 +52,6 @@ private: void PaintReplaced(const PaintInfo&, const LayoutPoint& paint_offset) const final; - PaintInvalidationReason InvalidatePaint( - const PaintInvalidatorContext&) const final; void UpdateLayout() final;
diff --git a/third_party/blink/renderer/core/layout/layout_flexible_box.cc b/third_party/blink/renderer/core/layout/layout_flexible_box.cc index 054c5a5a..9131c71 100644 --- a/third_party/blink/renderer/core/layout/layout_flexible_box.cc +++ b/third_party/blink/renderer/core/layout/layout_flexible_box.cc
@@ -1472,7 +1472,7 @@ DCHECK(!flex_item.box->IsOutOfFlowPositioned()); - child->SetMayNeedPaintInvalidation(); + child->SetShouldCheckForPaintInvalidation(); SetOverrideMainAxisContentSizeForChild(*child, flex_item.flexed_content_size);
diff --git a/third_party/blink/renderer/core/layout/layout_html_canvas.cc b/third_party/blink/renderer/core/layout/layout_html_canvas.cc index 6de2e94..ad04b69 100644 --- a/third_party/blink/renderer/core/layout/layout_html_canvas.cc +++ b/third_party/blink/renderer/core/layout/layout_html_canvas.cc
@@ -30,7 +30,6 @@ #include "third_party/blink/renderer/core/html/canvas/html_canvas_element.h" #include "third_party/blink/renderer/core/layout/layout_view.h" #include "third_party/blink/renderer/core/page/page.h" -#include "third_party/blink/renderer/core/paint/html_canvas_paint_invalidator.h" #include "third_party/blink/renderer/core/paint/html_canvas_painter.h" namespace blink { @@ -83,9 +82,13 @@ SetNeedsLayout(LayoutInvalidationReason::kSizeChanged); } -PaintInvalidationReason LayoutHTMLCanvas::InvalidatePaint( +void LayoutHTMLCanvas::InvalidatePaint( const PaintInvalidatorContext& context) const { - return HTMLCanvasPaintInvalidator(*this, context).InvalidatePaint(); + auto* element = ToHTMLCanvasElement(GetNode()); + if (element->IsDirty()) + element->DoDeferredPaintInvalidation(); + + LayoutReplaced::InvalidatePaint(context); } CompositingReasons LayoutHTMLCanvas::AdditionalCompositingReasons() const {
diff --git a/third_party/blink/renderer/core/layout/layout_html_canvas.h b/third_party/blink/renderer/core/layout/layout_html_canvas.h index 5058233..c3e989ed 100644 --- a/third_party/blink/renderer/core/layout/layout_html_canvas.h +++ b/third_party/blink/renderer/core/layout/layout_html_canvas.h
@@ -41,8 +41,7 @@ } PaintLayerType LayerTypeRequired() const override; - PaintInvalidationReason InvalidatePaint( - const PaintInvalidatorContext&) const final; + void InvalidatePaint(const PaintInvalidatorContext&) const final; void CanvasSizeChanged();
diff --git a/third_party/blink/renderer/core/layout/layout_image.cc b/third_party/blink/renderer/core/layout/layout_image.cc index 3ae89ee..1c907c9 100644 --- a/third_party/blink/renderer/core/layout/layout_image.cc +++ b/third_party/blink/renderer/core/layout/layout_image.cc
@@ -239,10 +239,11 @@ } SetShouldDoFullPaintInvalidationWithoutGeometryChange( - defer == CanDeferInvalidation::kYes && ImageResource() && - ImageResource()->MaybeAnimated() - ? PaintInvalidationReason::kDelayedFull - : PaintInvalidationReason::kImage); + PaintInvalidationReason::kImage); + + if (defer == CanDeferInvalidation::kYes && ImageResource() && + ImageResource()->MaybeAnimated()) + SetShouldDelayFullPaintInvalidation(); // Tell any potential compositing layers that the image needs updating. ContentChanged(kImageChanged);
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc index 073dc719..c740feb 100644 --- a/third_party/blink/renderer/core/layout/layout_object.cc +++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -170,7 +170,9 @@ #endif struct SameSizeAsLayoutObject : DisplayItemClient { - ~SameSizeAsLayoutObject() override = default; // Allocate vtable pointer. + // Normally this field uses the gap between DisplayItemClient and + // LayoutObject's other fields. + uint8_t paint_invalidation_reason_; void* pointers[5]; Member<void*> members[1]; #if DCHECK_IS_ON() @@ -178,7 +180,6 @@ #endif unsigned bitfields_; unsigned bitfields2_; - unsigned bitfields3_; // The following fields are in FragmentData. LayoutRect visual_rect_; LayoutPoint paint_offset_; @@ -277,7 +278,8 @@ } LayoutObject::LayoutObject(Node* node) - : style_(nullptr), + : full_paint_invalidation_reason_(PaintInvalidationReason::kNone), + style_(nullptr), node_(node), parent_(nullptr), previous_(nullptr), @@ -1535,7 +1537,7 @@ // Not using the WithoutGeometryChange version because we need to map the // partial invalidated rect to visual rect in backing or the containing // transform node. - SetMayNeedPaintInvalidation(); + SetShouldCheckForPaintInvalidation(); } LayoutRect LayoutObject::AbsoluteSelectionRect() const { @@ -1550,9 +1552,9 @@ } DISABLE_CFI_PERF -PaintInvalidationReason LayoutObject::InvalidatePaint( +void LayoutObject::InvalidatePaint( const PaintInvalidatorContext& context) const { - return ObjectPaintInvalidatorWithContext(*this, context).InvalidatePaint(); + ObjectPaintInvalidatorWithContext(*this, context).InvalidatePaint(); } void LayoutObject::AdjustVisualRectForCompositedScrolling( @@ -1952,7 +1954,7 @@ void LayoutObject::SetNeedsOverflowRecalcAfterStyleChange() { bool needed_recalc = NeedsOverflowRecalcAfterStyleChange(); SetSelfNeedsOverflowRecalcAfterStyleChange(); - SetMayNeedPaintInvalidation(); + SetShouldCheckForPaintInvalidation(); if (!needed_recalc) MarkContainerChainForOverflowRecalcIfNeeded(); } @@ -2057,7 +2059,7 @@ if (diff.NeedsPaintInvalidationSubtree() || updated_diff.NeedsPaintInvalidationSubtree()) { - SetShouldDoFullPaintInvalidationIncludingNonCompositingDescendants(); + SetSubtreeShouldDoFullPaintInvalidation(); } else if (diff.NeedsPaintInvalidationObject() || updated_diff.NeedsPaintInvalidationObject()) { // TODO(wangxianzhu): For now LayoutSVGRoot::localVisualRect() depends on @@ -2074,7 +2076,7 @@ InvalidateClipPathCache(); if (diff.NeedsVisualRectUpdate()) - SetMayNeedPaintInvalidation(); + SetShouldCheckForPaintInvalidation(); // Text nodes share style with their parents but the paint properties don't // apply to them, hence the !isText() check. If property nodes are added or @@ -3783,6 +3785,35 @@ return ObjectIsRelayoutBoundary(this); } +inline void LayoutObject::MarkAncestorsForPaintInvalidation() { + for (LayoutObject* parent = ParentCrossingFrames(); + parent && !parent->ShouldCheckForPaintInvalidation(); + parent = parent->ParentCrossingFrames()) + parent->bitfields_.SetShouldCheckForPaintInvalidation(true); +} + +inline void LayoutObject::SetNeedsPaintOffsetAndVisualRectUpdate() { + DCHECK(ShouldCheckForPaintInvalidation()); + for (auto* object = this; + object && !object->NeedsPaintOffsetAndVisualRectUpdate(); + object = object->ParentCrossingFrames()) { + object->bitfields_.SetNeedsPaintOffsetAndVisualRectUpdate(true); + } +} + +void LayoutObject::SetShouldInvalidateSelection() { + if (!CanUpdateSelectionOnRootLineBoxes()) + return; + bitfields_.SetShouldInvalidateSelection(true); + SetShouldCheckForPaintInvalidation(); +} + +void LayoutObject::SetShouldDoFullPaintInvalidation( + PaintInvalidationReason reason) { + SetShouldDoFullPaintInvalidationWithoutGeometryChange(reason); + SetNeedsPaintOffsetAndVisualRectUpdate(); +} + static PaintInvalidationReason DocumentLifecycleBasedPaintInvalidationReason( const DocumentLifecycle& document_lifecycle) { switch (document_lifecycle.GetState()) { @@ -3799,85 +3830,70 @@ } } -inline void LayoutObject::MarkAncestorsForPaintInvalidation() { - for (LayoutObject* parent = ParentCrossingFrames(); - parent && !parent->ShouldCheckForPaintInvalidation(); - parent = parent->ParentCrossingFrames()) - parent->bitfields_.SetMayNeedPaintInvalidation(true); -} - -inline void LayoutObject::SetNeedsPaintOffsetAndVisualRectUpdate() { - for (auto* object = this; - object && !object->NeedsPaintOffsetAndVisualRectUpdate(); - object = object->ParentCrossingFrames()) { - object->bitfields_.SetNeedsPaintOffsetAndVisualRectUpdate(true); - } -} - -void LayoutObject::SetShouldInvalidateSelection() { - if (!CanUpdateSelectionOnRootLineBoxes()) - return; - bitfields_.SetShouldInvalidateSelection(true); - SetMayNeedPaintInvalidation(); - GetFrameView()->ScheduleVisualUpdateForPaintInvalidationIfNeeded(); -} - -void LayoutObject::SetShouldDoFullPaintInvalidation( - PaintInvalidationReason reason) { - SetNeedsPaintOffsetAndVisualRectUpdate(); - SetShouldDoFullPaintInvalidationWithoutGeometryChange(reason); -} - void LayoutObject::SetShouldDoFullPaintInvalidationWithoutGeometryChange( PaintInvalidationReason reason) { // Only full invalidation reasons are allowed. DCHECK(IsFullPaintInvalidationReason(reason)); + // This is before the early return to ensure visual update is always scheduled + // in case that this is called not during a document lifecycle update. + SetShouldCheckForPaintInvalidationWithoutGeometryChange(); - bool is_upgrading_delayed_full_to_full = - bitfields_.FullPaintInvalidationReason() == - PaintInvalidationReason::kDelayedFull && - reason != PaintInvalidationReason::kDelayedFull; - - if (bitfields_.FullPaintInvalidationReason() == - PaintInvalidationReason::kNone || - is_upgrading_delayed_full_to_full) { - if (reason == PaintInvalidationReason::kFull) { - reason = DocumentLifecycleBasedPaintInvalidationReason( - GetDocument().Lifecycle()); - } - bitfields_.SetFullPaintInvalidationReason(reason); - if (!is_upgrading_delayed_full_to_full) - MarkAncestorsForPaintInvalidation(); + if (ShouldDoFullPaintInvalidation()) + return; + if (reason == PaintInvalidationReason::kFull) { + reason = DocumentLifecycleBasedPaintInvalidationReason( + GetDocument().Lifecycle()); } - - GetFrameView()->ScheduleVisualUpdateForPaintInvalidationIfNeeded(); + full_paint_invalidation_reason_ = reason; + bitfields_.SetShouldDelayFullPaintInvalidation(false); } -void LayoutObject::SetMayNeedPaintInvalidation() { +void LayoutObject::SetShouldCheckForPaintInvalidation() { + SetShouldCheckForPaintInvalidationWithoutGeometryChange(); SetNeedsPaintOffsetAndVisualRectUpdate(); - SetMayNeedPaintInvalidationWithoutGeometryChange(); } -void LayoutObject::SetMayNeedPaintInvalidationWithoutGeometryChange() { - if (MayNeedPaintInvalidation()) - return; - bitfields_.SetMayNeedPaintInvalidation(true); - MarkAncestorsForPaintInvalidation(); +void LayoutObject::SetShouldCheckForPaintInvalidationWithoutGeometryChange() { + // This is before the early return to ensure visual update is always scheduled + // in case that this is called not during a document lifecycle update. GetFrameView()->ScheduleVisualUpdateForPaintInvalidationIfNeeded(); + + if (ShouldCheckForPaintInvalidation()) + return; + bitfields_.SetShouldCheckForPaintInvalidation(true); + MarkAncestorsForPaintInvalidation(); } -void LayoutObject::SetMayNeedPaintInvalidationSubtree() { - if (MayNeedPaintInvalidationSubtree()) +void LayoutObject::SetSubtreeShouldCheckForPaintInvalidation() { + if (SubtreeShouldCheckForPaintInvalidation()) { + DCHECK(ShouldCheckForPaintInvalidation()); return; - bitfields_.SetMayNeedPaintInvalidationSubtree(true); - SetMayNeedPaintInvalidation(); + } + SetShouldCheckForPaintInvalidation(); + bitfields_.SetSubtreeShouldCheckForPaintInvalidation(true); } void LayoutObject::SetMayNeedPaintInvalidationAnimatedBackgroundImage() { if (MayNeedPaintInvalidationAnimatedBackgroundImage()) return; bitfields_.SetMayNeedPaintInvalidationAnimatedBackgroundImage(true); - SetMayNeedPaintInvalidationWithoutGeometryChange(); + SetShouldCheckForPaintInvalidationWithoutGeometryChange(); +} + +void LayoutObject::SetShouldDelayFullPaintInvalidation() { + // Should have already set a full paint invalidation reason. + DCHECK(IsFullPaintInvalidationReason(full_paint_invalidation_reason_)); + + bitfields_.SetShouldDelayFullPaintInvalidation(true); + if (!ShouldCheckForPaintInvalidation()) { + // This will also schedule a visual update. + SetShouldCheckForPaintInvalidationWithoutGeometryChange(); + } else { + // Schedule visual update for the next document cycle in which we will + // check if the delayed invalidation should be promoted to a real + // invalidation. + GetFrameView()->ScheduleVisualUpdateForPaintInvalidationIfNeeded(); + } } void LayoutObject::ClearPaintInvalidationFlags() { @@ -3887,25 +3903,37 @@ DCHECK(!ShouldCheckForPaintInvalidation() || PaintInvalidationStateIsDirty()); #endif fragment_.SetPartialInvalidationLocalRect(LayoutRect()); - ClearShouldDoFullPaintInvalidation(); - bitfields_.SetMayNeedPaintInvalidation(false); - bitfields_.SetMayNeedPaintInvalidationSubtree(false); + if (!ShouldDelayFullPaintInvalidation()) + full_paint_invalidation_reason_ = PaintInvalidationReason::kNone; + bitfields_.SetShouldCheckForPaintInvalidation(false); + bitfields_.SetSubtreeShouldCheckForPaintInvalidation(false); + bitfields_.SetSubtreeShouldDoFullPaintInvalidation(false); bitfields_.SetMayNeedPaintInvalidationAnimatedBackgroundImage(false); bitfields_.SetNeedsPaintOffsetAndVisualRectUpdate(false); bitfields_.SetShouldInvalidateSelection(false); bitfields_.SetBackgroundChangedSinceLastPaintInvalidation(false); } +#if DCHECK_IS_ON() +bool LayoutObject::PaintInvalidationStateIsDirty() const { + return BackgroundChangedSinceLastPaintInvalidation() || + ShouldCheckForPaintInvalidation() || ShouldInvalidateSelection() || + NeedsPaintOffsetAndVisualRectUpdate() || + ShouldDoFullPaintInvalidation() || + SubtreeShouldDoFullPaintInvalidation() || + MayNeedPaintInvalidationAnimatedBackgroundImage() || + !fragment_.PartialInvalidationLocalRect().IsEmpty(); +} +#endif + bool LayoutObject::IsAllowedToModifyLayoutTreeStructure(Document& document) { return document.Lifecycle().StateAllowsLayoutTreeMutations(); } -void LayoutObject:: - SetShouldDoFullPaintInvalidationIncludingNonCompositingDescendants() { - // Clear first because PaintInvalidationSubtree overrides other full paint - // invalidation reasons. - ClearShouldDoFullPaintInvalidation(); - SetShouldDoFullPaintInvalidation(PaintInvalidationReason::kSubtree); +void LayoutObject::SetSubtreeShouldDoFullPaintInvalidation( + PaintInvalidationReason reason) { + SetShouldDoFullPaintInvalidation(reason); + bitfields_.SetSubtreeShouldDoFullPaintInvalidation(true); } void LayoutObject::SetIsBackgroundAttachmentFixedObject( @@ -3974,7 +4002,7 @@ void LayoutObject::InvalidateIfControlStateChanged(ControlState control_state) { if (LayoutTheme::GetTheme().ControlStateChanged(GetNode(), StyleRef(), control_state)) { - SetShouldDoFullPaintInvalidationIncludingNonCompositingDescendants(); + SetSubtreeShouldDoFullPaintInvalidation(); } }
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h index c41cd25d..6bee3a61 100644 --- a/third_party/blink/renderer/core/layout/layout_object.h +++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -237,10 +237,11 @@ // Do not call VisualRect directly outside of the DisplayItemClient // interface, use a per-fragment one on FragmentData instead. private: - // Hide DisplayItemClient methods whose names are too generic for - // LayoutObject. Use LayoutObject methods instead, or explicitly cast. + // Hide DisplayItemClient's methods whose names are too generic for + // LayoutObjects. Should use LayoutObject's methods instead. using DisplayItemClient::Invalidate; using DisplayItemClient::IsValid; + using DisplayItemClient::GetPaintInvalidationReason; LayoutRect VisualRect() const final; @@ -1478,17 +1479,15 @@ // a small region of a canvas changes. void InvalidatePaintRectangle(const LayoutRect&); - void SetShouldDoFullPaintInvalidationIncludingNonCompositingDescendants(); - // Returns the rect that should have paint invalidated whenever this object // changes. The rect is in the view's coordinate space. This method deals with // outlines and overflow. virtual LayoutRect AbsoluteVisualRect() const; - // Returns the rect that should have paint invalidated whenever this object + // Returns the rect that should have raster invalidated whenever this object // changes. The rect is in the object's local coordinate space. This is for // non-SVG objects and LayoutSVGRoot only. SVG objects (except LayoutSVGRoot) - // should use visualRectInLocalSVGCoordinates() and map with SVG transforms + // should use VisualRectInLocalSVGCoordinates() and map with SVG transforms // instead. LayoutRect LocalVisualRect() const { if (StyleRef().Visibility() != EVisibility::kVisible && @@ -1746,32 +1745,34 @@ virtual void ClearPreviousVisualRects(); PaintInvalidationReason FullPaintInvalidationReason() const { - return bitfields_.FullPaintInvalidationReason(); + return full_paint_invalidation_reason_; } bool ShouldDoFullPaintInvalidation() const { - return bitfields_.FullPaintInvalidationReason() != - PaintInvalidationReason::kNone; + if (!ShouldDelayFullPaintInvalidation() && + full_paint_invalidation_reason_ != PaintInvalidationReason::kNone) { + DCHECK(IsFullPaintInvalidationReason(full_paint_invalidation_reason_)); + DCHECK(ShouldCheckForPaintInvalidation()); + return true; + } + return false; } void SetShouldDoFullPaintInvalidation( PaintInvalidationReason = PaintInvalidationReason::kFull); void SetShouldDoFullPaintInvalidationWithoutGeometryChange( PaintInvalidationReason = PaintInvalidationReason::kFull); - void ClearShouldDoFullPaintInvalidation() { - bitfields_.SetFullPaintInvalidationReason(PaintInvalidationReason::kNone); - } void ClearPaintInvalidationFlags(); - bool MayNeedPaintInvalidation() const { - return bitfields_.MayNeedPaintInvalidation(); + bool ShouldCheckForPaintInvalidation() const { + return bitfields_.ShouldCheckForPaintInvalidation(); } - void SetMayNeedPaintInvalidation(); - void SetMayNeedPaintInvalidationWithoutGeometryChange(); + void SetShouldCheckForPaintInvalidation(); + void SetShouldCheckForPaintInvalidationWithoutGeometryChange(); - bool MayNeedPaintInvalidationSubtree() const { - return bitfields_.MayNeedPaintInvalidationSubtree(); + bool SubtreeShouldCheckForPaintInvalidation() const { + return bitfields_.SubtreeShouldCheckForPaintInvalidation(); } - void SetMayNeedPaintInvalidationSubtree(); + void SetSubtreeShouldCheckForPaintInvalidation(); bool NeedsPaintOffsetAndVisualRectUpdate() const { return bitfields_.NeedsPaintOffsetAndVisualRectUpdate(); @@ -1782,20 +1783,33 @@ } void SetMayNeedPaintInvalidationAnimatedBackgroundImage(); + void SetSubtreeShouldDoFullPaintInvalidation( + PaintInvalidationReason reason = PaintInvalidationReason::kSubtree); + bool SubtreeShouldDoFullPaintInvalidation() const { + DCHECK(!bitfields_.SubtreeShouldDoFullPaintInvalidation() || + ShouldDoFullPaintInvalidation()); + return bitfields_.SubtreeShouldDoFullPaintInvalidation(); + } + + // If true, it means that invalidation and repainting of the object can be + // delayed until a future frame. This can be the case for an object whose + // content is not visible to the user. + bool ShouldDelayFullPaintInvalidation() const { + return bitfields_.ShouldDelayFullPaintInvalidation(); + } + void SetShouldDelayFullPaintInvalidation(); + bool ShouldInvalidateSelection() const { return bitfields_.ShouldInvalidateSelection(); } void SetShouldInvalidateSelection(); - bool ShouldCheckForPaintInvalidation() const { - return MayNeedPaintInvalidation() || ShouldDoFullPaintInvalidation(); - } - virtual LayoutRect ViewRect() const; - // New version to replace the above old version. - virtual PaintInvalidationReason InvalidatePaint( - const PaintInvalidatorContext&) const; + // Called by PaintInvalidator during PrePaint. Checks paint invalidation flags + // and other changes that will cause different painting, and invalidate + // display item clients for painting if needed. + virtual void InvalidatePaint(const PaintInvalidatorContext&) const; // When this object is invalidated for paint, this method is called to // invalidate any DisplayItemClients owned by this object, including the @@ -1878,8 +1892,8 @@ layout_object_.bitfields_ .SetDescendantEffectiveWhitelistedTouchActionChanged(false); } - void SetMayNeedPaintInvalidation() { - layout_object_.SetMayNeedPaintInvalidation(); + void SetShouldCheckForPaintInvalidation() { + layout_object_.SetShouldCheckForPaintInvalidation(); } void SetShouldDoFullPaintInvalidation(PaintInvalidationReason reason) { layout_object_.SetShouldDoFullPaintInvalidation(reason); @@ -1892,6 +1906,9 @@ void SetBackgroundChangedSinceLastPaintInvalidation() { layout_object_.SetBackgroundChangedSinceLastPaintInvalidation(); } + void SetShouldDelayFullPaintInvalidation() { + layout_object_.SetShouldDelayFullPaintInvalidation(); + } void EnsureIsReadyForPaintInvalidation() { layout_object_.EnsureIsReadyForPaintInvalidation(); } @@ -2209,12 +2226,7 @@ const LayoutPoint& layer_offset) const {} #if DCHECK_IS_ON() - virtual bool PaintInvalidationStateIsDirty() const { - return BackgroundChangedSinceLastPaintInvalidation() || - ShouldCheckForPaintInvalidation() || ShouldInvalidateSelection() || - NeedsPaintOffsetAndVisualRectUpdate() || - !fragment_.PartialInvalidationLocalRect().IsEmpty(); - } + virtual bool PaintInvalidationStateIsDirty() const; #endif // Called before paint invalidation. @@ -2329,6 +2341,14 @@ void ApplyPseudoStyleChanges(const ComputedStyle& old_style); void ApplyFirstLineChanges(const ComputedStyle& old_style); + // This is set by Set[Subtree]ShouldDoFullPaintInvalidation, and cleared + // during PrePaint in this object's InvalidatePaint(). It's different from + // DisplayItemClient::GetPaintInvalidationReason() which is set during + // PrePaint and cleared in PaintController::FinishCycle(). + // It's defined as the first field so that it can use the memory gap between + // DisplayItemClient and LayoutObject's other fields. + PaintInvalidationReason full_paint_invalidation_reason_; + scoped_refptr<ComputedStyle> style_; // Oilpan: This untraced pointer to the owning Node is considered safe. @@ -2388,10 +2408,12 @@ child_needs_overflow_recalc_after_style_change_(false), preferred_logical_widths_dirty_(false), needs_collect_inlines_(false), - may_need_paint_invalidation_(false), - may_need_paint_invalidation_subtree_(false), + should_check_for_paint_invalidation_(true), + subtree_should_check_for_paint_invalidation_(false), + should_delay_full_paint_invalidation_(false), + subtree_should_do_full_paint_invalidation_(false), may_need_paint_invalidation_animated_background_image_(false), - needs_paint_offset_and_visual_rect_update_(false), + needs_paint_offset_and_visual_rect_update_(true), should_invalidate_selection_(false), floating_(false), is_anonymous_(!node), @@ -2434,9 +2456,7 @@ is_effective_root_scroller_(false), positioned_state_(kIsStaticallyPositioned), selection_state_(static_cast<unsigned>(SelectionState::kNone)), - background_obscuration_state_(kBackgroundObscurationStatusInvalid), - full_paint_invalidation_reason_( - static_cast<unsigned>(PaintInvalidationReason::kNone)) {} + background_obscuration_state_(kBackgroundObscurationStatusInvalid) {} // Self needs layout means that this layout object is marked for a full // layout. This is the default layout but it is expensive as it recomputes @@ -2500,10 +2520,14 @@ // Also maybe set to inline boxes to optimize the propagation. ADD_BOOLEAN_BITFIELD(needs_collect_inlines_, NeedsCollectInlines); - ADD_BOOLEAN_BITFIELD(may_need_paint_invalidation_, - MayNeedPaintInvalidation); - ADD_BOOLEAN_BITFIELD(may_need_paint_invalidation_subtree_, - MayNeedPaintInvalidationSubtree); + ADD_BOOLEAN_BITFIELD(should_check_for_paint_invalidation_, + ShouldCheckForPaintInvalidation); + ADD_BOOLEAN_BITFIELD(subtree_should_check_for_paint_invalidation_, + SubtreeShouldCheckForPaintInvalidation); + ADD_BOOLEAN_BITFIELD(should_delay_full_paint_invalidation_, + ShouldDelayFullPaintInvalidation); + ADD_BOOLEAN_BITFIELD(subtree_should_do_full_paint_invalidation_, + SubtreeShouldDoFullPaintInvalidation); ADD_BOOLEAN_BITFIELD(may_need_paint_invalidation_animated_background_image_, MayNeedPaintInvalidationAnimatedBackgroundImage); ADD_BOOLEAN_BITFIELD(needs_paint_offset_and_visual_rect_update_, @@ -2665,12 +2689,7 @@ unsigned selection_state_ : 3; // SelectionState // Mutable for getter which lazily update this field. mutable unsigned - background_obscuration_state_ : 2; // BackgroundObscurationState - - unsigned full_paint_invalidation_reason_ : 5; // PaintInvalidationReason - static_assert(static_cast<unsigned>(PaintInvalidationReason::kMax) < - (1u << 5), - "PaintInvalidationReason should fit in the bit field"); + background_obscuration_state_ : 2; // BackgroundObscurationState public: bool IsOutOfFlowPositioned() const { @@ -2732,14 +2751,6 @@ BackgroundObscurationState s) const { background_obscuration_state_ = s; } - - PaintInvalidationReason FullPaintInvalidationReason() const { - return static_cast<PaintInvalidationReason>( - full_paint_invalidation_reason_); - } - void SetFullPaintInvalidationReason(PaintInvalidationReason reason) { - full_paint_invalidation_reason_ = static_cast<unsigned>(reason); - } }; #undef ADD_BOOLEAN_BITFIELD @@ -2841,7 +2852,7 @@ inline void LayoutObject::ClearNeedsLayout() { // Set flags for later stages/cycles. SetEverHadLayout(); - SetMayNeedPaintInvalidation(); + SetShouldCheckForPaintInvalidation(); // Clear needsLayout flags. SetSelfNeedsLayout(false);
diff --git a/third_party/blink/renderer/core/layout/layout_object_test.cc b/third_party/blink/renderer/core/layout/layout_object_test.cc index 9f6b920..a40375c 100644 --- a/third_party/blink/renderer/core/layout/layout_object_test.cc +++ b/third_party/blink/renderer/core/layout/layout_object_test.cc
@@ -319,10 +319,10 @@ object->SetShouldDoFullPaintInvalidation(); EXPECT_TRUE(object->ShouldDoFullPaintInvalidation()); EXPECT_TRUE(object->NeedsPaintOffsetAndVisualRectUpdate()); - object->SetMayNeedPaintInvalidation(); - EXPECT_TRUE(object->MayNeedPaintInvalidation()); - object->SetMayNeedPaintInvalidationSubtree(); - EXPECT_TRUE(object->MayNeedPaintInvalidationSubtree()); + object->SetShouldCheckForPaintInvalidation(); + EXPECT_TRUE(object->ShouldCheckForPaintInvalidation()); + object->SetSubtreeShouldCheckForPaintInvalidation(); + EXPECT_TRUE(object->SubtreeShouldCheckForPaintInvalidation()); object->SetMayNeedPaintInvalidationAnimatedBackgroundImage(); EXPECT_TRUE(object->MayNeedPaintInvalidationAnimatedBackgroundImage()); object->SetShouldInvalidateSelection(); @@ -339,8 +339,8 @@ object->GetMutableForPainting().ClearPaintFlags(); EXPECT_FALSE(object->ShouldDoFullPaintInvalidation()); - EXPECT_FALSE(object->MayNeedPaintInvalidation()); - EXPECT_FALSE(object->MayNeedPaintInvalidationSubtree()); + EXPECT_FALSE(object->ShouldCheckForPaintInvalidation()); + EXPECT_FALSE(object->SubtreeShouldCheckForPaintInvalidation()); EXPECT_FALSE(object->MayNeedPaintInvalidationAnimatedBackgroundImage()); EXPECT_FALSE(object->ShouldInvalidateSelection()); EXPECT_FALSE(object->BackgroundChangedSinceLastPaintInvalidation()); @@ -369,55 +369,55 @@ object->SetShouldDoFullPaintInvalidation(); EXPECT_TRUE(object->ShouldDoFullPaintInvalidation()); EXPECT_TRUE(object->NeedsPaintOffsetAndVisualRectUpdate()); - EXPECT_TRUE(parent->MayNeedPaintInvalidation()); + EXPECT_TRUE(parent->ShouldCheckForPaintInvalidation()); EXPECT_TRUE(parent->NeedsPaintOffsetAndVisualRectUpdate()); object->ClearPaintInvalidationFlags(); EXPECT_FALSE(object->ShouldDoFullPaintInvalidation()); EXPECT_FALSE(object->NeedsPaintOffsetAndVisualRectUpdate()); parent->ClearPaintInvalidationFlags(); - EXPECT_FALSE(parent->MayNeedPaintInvalidation()); + EXPECT_FALSE(parent->ShouldCheckForPaintInvalidation()); EXPECT_FALSE(parent->NeedsPaintOffsetAndVisualRectUpdate()); - object->SetMayNeedPaintInvalidation(); - EXPECT_TRUE(object->MayNeedPaintInvalidation()); + object->SetShouldCheckForPaintInvalidation(); + EXPECT_TRUE(object->ShouldCheckForPaintInvalidation()); EXPECT_TRUE(object->NeedsPaintOffsetAndVisualRectUpdate()); - EXPECT_TRUE(parent->MayNeedPaintInvalidation()); + EXPECT_TRUE(parent->ShouldCheckForPaintInvalidation()); EXPECT_TRUE(parent->NeedsPaintOffsetAndVisualRectUpdate()); object->ClearPaintInvalidationFlags(); - EXPECT_FALSE(object->MayNeedPaintInvalidation()); + EXPECT_FALSE(object->ShouldCheckForPaintInvalidation()); EXPECT_FALSE(object->NeedsPaintOffsetAndVisualRectUpdate()); parent->ClearPaintInvalidationFlags(); - EXPECT_FALSE(parent->MayNeedPaintInvalidation()); + EXPECT_FALSE(parent->ShouldCheckForPaintInvalidation()); EXPECT_FALSE(parent->NeedsPaintOffsetAndVisualRectUpdate()); object->SetShouldDoFullPaintInvalidationWithoutGeometryChange(); EXPECT_TRUE(object->ShouldDoFullPaintInvalidation()); EXPECT_FALSE(object->NeedsPaintOffsetAndVisualRectUpdate()); - EXPECT_TRUE(parent->MayNeedPaintInvalidation()); + EXPECT_TRUE(parent->ShouldCheckForPaintInvalidation()); EXPECT_FALSE(parent->NeedsPaintOffsetAndVisualRectUpdate()); - object->SetMayNeedPaintInvalidation(); + object->SetShouldCheckForPaintInvalidation(); EXPECT_TRUE(object->NeedsPaintOffsetAndVisualRectUpdate()); EXPECT_TRUE(parent->NeedsPaintOffsetAndVisualRectUpdate()); object->ClearPaintInvalidationFlags(); - EXPECT_FALSE(object->MayNeedPaintInvalidation()); + EXPECT_FALSE(object->ShouldCheckForPaintInvalidation()); EXPECT_FALSE(object->NeedsPaintOffsetAndVisualRectUpdate()); parent->ClearPaintInvalidationFlags(); - EXPECT_FALSE(parent->MayNeedPaintInvalidation()); + EXPECT_FALSE(parent->ShouldCheckForPaintInvalidation()); EXPECT_FALSE(parent->NeedsPaintOffsetAndVisualRectUpdate()); - object->SetMayNeedPaintInvalidationWithoutGeometryChange(); - EXPECT_TRUE(object->MayNeedPaintInvalidation()); + object->SetShouldCheckForPaintInvalidationWithoutGeometryChange(); + EXPECT_TRUE(object->ShouldCheckForPaintInvalidation()); EXPECT_FALSE(object->NeedsPaintOffsetAndVisualRectUpdate()); - EXPECT_TRUE(parent->MayNeedPaintInvalidation()); + EXPECT_TRUE(parent->ShouldCheckForPaintInvalidation()); EXPECT_FALSE(parent->NeedsPaintOffsetAndVisualRectUpdate()); - object->SetMayNeedPaintInvalidation(); + object->SetShouldCheckForPaintInvalidation(); EXPECT_TRUE(object->NeedsPaintOffsetAndVisualRectUpdate()); EXPECT_TRUE(parent->NeedsPaintOffsetAndVisualRectUpdate()); object->ClearPaintInvalidationFlags(); - EXPECT_FALSE(object->MayNeedPaintInvalidation()); + EXPECT_FALSE(object->ShouldCheckForPaintInvalidation()); EXPECT_FALSE(object->NeedsPaintOffsetAndVisualRectUpdate()); parent->ClearPaintInvalidationFlags(); - EXPECT_FALSE(parent->MayNeedPaintInvalidation()); + EXPECT_FALSE(parent->ShouldCheckForPaintInvalidation()); EXPECT_FALSE(parent->NeedsPaintOffsetAndVisualRectUpdate()); }
diff --git a/third_party/blink/renderer/core/layout/layout_table.cc b/third_party/blink/renderer/core/layout/layout_table.cc index d123137..abc5986 100644 --- a/third_party/blink/renderer/core/layout/layout_table.cc +++ b/third_party/blink/renderer/core/layout/layout_table.cc
@@ -476,7 +476,7 @@ UpdateFragmentationInfoForChild(caption); if (!SelfNeedsLayout()) - caption.SetMayNeedPaintInvalidation(); + caption.SetShouldCheckForPaintInvalidation(); SetLogicalHeight(LogicalHeight() + caption.LogicalHeight() + CollapsedMarginBeforeForChild(caption) + @@ -878,7 +878,7 @@ collapsed_borders_valid_ = false; needs_invalidate_collapsed_borders_for_all_cells_ = true; collapsed_outer_borders_valid_ = false; - SetMayNeedPaintInvalidation(); + SetShouldCheckForPaintInvalidation(); } void LayoutTable::InvalidateCollapsedBordersForAllCellsIfNeeded() { @@ -1638,9 +1638,9 @@ } } -PaintInvalidationReason LayoutTable::InvalidatePaint( +void LayoutTable::InvalidatePaint( const PaintInvalidatorContext& context) const { - return TablePaintInvalidator(*this, context).InvalidatePaint(); + TablePaintInvalidator(*this, context).InvalidatePaint(); } LayoutUnit LayoutTable::PaddingTop() const {
diff --git a/third_party/blink/renderer/core/layout/layout_table.h b/third_party/blink/renderer/core/layout/layout_table.h index 6b9835b..2c5835d 100644 --- a/third_party/blink/renderer/core/layout/layout_table.h +++ b/third_party/blink/renderer/core/layout/layout_table.h
@@ -428,8 +428,7 @@ void SimplifiedNormalFlowLayout() override; bool RecalcOverflowAfterStyleChange() override; void EnsureIsReadyForPaintInvalidation() override; - PaintInvalidationReason InvalidatePaint( - const PaintInvalidatorContext&) const override; + void InvalidatePaint(const PaintInvalidatorContext&) const override; bool PaintedOutputOfObjectHasNoEffectRegardlessOfSize() const override; private:
diff --git a/third_party/blink/renderer/core/layout/layout_table_cell.cc b/third_party/blink/renderer/core/layout/layout_table_cell.cc index e08a856c..07472c7e 100644 --- a/third_party/blink/renderer/core/layout/layout_table_cell.cc +++ b/third_party/blink/renderer/core/layout/layout_table_cell.cc
@@ -1215,9 +1215,9 @@ return LayoutBlock::HasLineIfEmpty(); } -PaintInvalidationReason LayoutTableCell::InvalidatePaint( +void LayoutTableCell::InvalidatePaint( const PaintInvalidatorContext& context) const { - return TableCellPaintInvalidator(*this, context).InvalidatePaint(); + TableCellPaintInvalidator(*this, context).InvalidatePaint(); } } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_table_cell.h b/third_party/blink/renderer/core/layout/layout_table_cell.h index 859bb4f..2299fe6 100644 --- a/third_party/blink/renderer/core/layout/layout_table_cell.h +++ b/third_party/blink/renderer/core/layout/layout_table_cell.h
@@ -356,8 +356,7 @@ const LayoutRect& container_rect, TouchAction container_whitelisted_touch_action) const override; - PaintInvalidationReason InvalidatePaint( - const PaintInvalidatorContext&) const override; + void InvalidatePaint(const PaintInvalidatorContext&) const override; LayoutSize OffsetFromContainerInternal( const LayoutObject*,
diff --git a/third_party/blink/renderer/core/layout/layout_table_section.cc b/third_party/blink/renderer/core/layout/layout_table_section.cc index 07b1f20a..48c2d52 100644 --- a/third_party/blink/renderer/core/layout/layout_table_section.cc +++ b/third_party/blink/renderer/core/layout/layout_table_section.cc
@@ -1271,7 +1271,7 @@ // need a layout. In this case, we know we're going to issue paint // invalidations ourselves (and the child) anyway. if (!Table()->SelfNeedsLayout()) - cell->SetMayNeedPaintInvalidation(); + cell->SetShouldCheckForPaintInvalidation(); } } if (row)
diff --git a/third_party/blink/renderer/core/layout/layout_view.cc b/third_party/blink/renderer/core/layout/layout_view.cc index 9aea5af..3241d32 100644 --- a/third_party/blink/renderer/core/layout/layout_view.cc +++ b/third_party/blink/renderer/core/layout/layout_view.cc
@@ -477,13 +477,13 @@ void LayoutView::SetShouldDoFullPaintInvalidationForViewAndAllDescendants() { if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) - SetShouldDoFullPaintInvalidationIncludingNonCompositingDescendants(); + SetSubtreeShouldDoFullPaintInvalidation(); else SetShouldDoFullPaintInvalidationForViewAndAllDescendantsInternal(this); } void LayoutView::InvalidatePaintForViewAndCompositedLayers() { - SetShouldDoFullPaintInvalidationIncludingNonCompositingDescendants(); + SetSubtreeShouldDoFullPaintInvalidation(); // The only way we know how to hit these ASSERTS below this point is via the // Chromium OS login screen. @@ -886,7 +886,7 @@ if (NeedsLayout()) return result; if (GetFrameView()->VisualViewportSuppliesScrollbars()) - SetMayNeedPaintInvalidation(); + SetShouldCheckForPaintInvalidation(); GetFrameView()->AdjustViewSize(); SetNeedsPaintPropertyUpdate(); if (Layer())
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc b/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc index 2198215..37d63ad 100644 --- a/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc +++ b/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc
@@ -268,7 +268,7 @@ // When paint fragment is replaced, the subtree needs paint invalidation to // re-compute paint properties in NGPaintFragment. - Base::SetShouldDoFullPaintInvalidation(PaintInvalidationReason::kSubtree); + Base::SetSubtreeShouldDoFullPaintInvalidation(); } template <typename Base>
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc index d120691..1c399d52 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
@@ -207,7 +207,7 @@ // -dynamic.html // TODO(layoutng): See if we can optimize this. When we natively // support relative positioning in NG we can probably remove this, - box_->SetMayNeedPaintInvalidation(); + box_->SetShouldCheckForPaintInvalidation(); // We have to re-set the cached result here, because it is used for // LayoutNGMixin::CurrentFragment and therefore has to be up-to-date.
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.cc index c1d14a5..ba9064af 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.cc
@@ -115,7 +115,7 @@ // if the client is one that could have a LayoutSVGInlineText use a // paint invalidation reason that will force paint invalidation of the // entire <text>/<tspan>/... subtree. - client.SetShouldDoFullPaintInvalidation( + client.SetSubtreeShouldDoFullPaintInvalidation( PaintInvalidationReason::kSVGResource); client.InvalidateClipPathCache(); // Invalidate paint properties to update effects if any.
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.cc index 9e256694..659ee17 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.cc
@@ -127,7 +127,6 @@ } void LayoutSVGResourceMarker::SetNeedsTransformUpdate() { - SetMayNeedPaintInvalidationSubtree(); // The transform paint property relies on the SVG transform being up-to-date // (see: PaintPropertyTreeBuilder::updateTransformForNonRootSVG). SetNeedsPaintPropertyUpdate();
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc index af6a5074..6de0dd4 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc
@@ -196,7 +196,7 @@ // mark the entire subtree as needing paint invalidation checking. if (transform_change != SVGTransformChange::kNone || viewport_may_have_changed) { - SetMayNeedPaintInvalidationSubtree(); + SetSubtreeShouldCheckForPaintInvalidation(); SetNeedsPaintPropertyUpdate(); if (Layer())
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_transformable_container.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_transformable_container.cc index 5ed2cc5..9859027 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_transformable_container.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_transformable_container.cc
@@ -68,7 +68,6 @@ } void LayoutSVGTransformableContainer::SetNeedsTransformUpdate() { - SetMayNeedPaintInvalidationSubtree(); // The transform paint property relies on the SVG transform being up-to-date // (see: PaintPropertyTreeBuilder::updateTransformForNonRootSVG). SetNeedsPaintPropertyUpdate();
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.cc index d86c420..e03a672e 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.cc
@@ -56,7 +56,6 @@ } void LayoutSVGViewportContainer::SetNeedsTransformUpdate() { - SetMayNeedPaintInvalidationSubtree(); // The transform paint property relies on the SVG transform being up-to-date // (see: PaintPropertyTreeBuilder::updateTransformForNonRootSVG). SetNeedsPaintPropertyUpdate();
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc index 7ef8deca..5fae42f6 100644 --- a/third_party/blink/renderer/core/loader/document_loader.cc +++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -1160,7 +1160,7 @@ parser_->AsScriptableDocumentParser(); if (scriptable_parser && GetResource()) { scriptable_parser->SetInlineScriptCacheHandler( - ToRawResource(GetResource())->CacheHandler()); + ToRawResource(GetResource())->InlineScriptCacheHandler()); } // FeaturePolicy is reset in the browser process on commit, so this needs to
diff --git a/third_party/blink/renderer/core/page/validation_message_overlay_delegate.cc b/third_party/blink/renderer/core/page/validation_message_overlay_delegate.cc index 248409d..a013c09 100644 --- a/third_party/blink/renderer/core/page/validation_message_overlay_delegate.cc +++ b/third_party/blink/renderer/core/page/validation_message_overlay_delegate.cc
@@ -118,7 +118,7 @@ // This manual invalidation is necessary to avoid a DCHECK failure in // FindVisualRectNeedingUpdateScopeBase::CheckVisualRect(). - FrameView().GetLayoutView()->SetMayNeedPaintInvalidationSubtree(); + FrameView().GetLayoutView()->SetSubtreeShouldCheckForPaintInvalidation(); FrameView().UpdateAllLifecyclePhases(); }
diff --git a/third_party/blink/renderer/core/paint/BUILD.gn b/third_party/blink/renderer/core/paint/BUILD.gn index d8e2d9b4f..e85edd0 100644 --- a/third_party/blink/renderer/core/paint/BUILD.gn +++ b/third_party/blink/renderer/core/paint/BUILD.gn
@@ -78,8 +78,6 @@ "ellipsis_box_painter.h", "embedded_content_painter.cc", "embedded_content_painter.h", - "embedded_object_paint_invalidator.cc", - "embedded_object_paint_invalidator.h", "embedded_object_painter.cc", "embedded_object_painter.h", "fallback_theme.cc", @@ -102,8 +100,6 @@ "frame_set_painter.h", "grid_painter.cc", "grid_painter.h", - "html_canvas_paint_invalidator.cc", - "html_canvas_paint_invalidator.h", "html_canvas_painter.cc", "html_canvas_painter.h", "image_painter.cc",
diff --git a/third_party/blink/renderer/core/paint/block_paint_invalidator.cc b/third_party/blink/renderer/core/paint/block_paint_invalidator.cc index f9a48ba5..633e8e8 100644 --- a/third_party/blink/renderer/core/paint/block_paint_invalidator.cc +++ b/third_party/blink/renderer/core/paint/block_paint_invalidator.cc
@@ -20,15 +20,12 @@ block_.GetFrame()->GetPage()->GetDragCaret().ClearPreviousVisualRect(block_); } -PaintInvalidationReason BlockPaintInvalidator::InvalidatePaint( +void BlockPaintInvalidator::InvalidatePaint( const PaintInvalidatorContext& context) { - PaintInvalidationReason reason = - BoxPaintInvalidator(block_, context).InvalidatePaint(); + BoxPaintInvalidator(block_, context).InvalidatePaint(); block_.GetFrame()->Selection().InvalidatePaint(block_, context); block_.GetFrame()->GetPage()->GetDragCaret().InvalidatePaint(block_, context); - - return reason; } } // namespace blink
diff --git a/third_party/blink/renderer/core/paint/block_paint_invalidator.h b/third_party/blink/renderer/core/paint/block_paint_invalidator.h index 988b0ce2..7101dbdc 100644 --- a/third_party/blink/renderer/core/paint/block_paint_invalidator.h +++ b/third_party/blink/renderer/core/paint/block_paint_invalidator.h
@@ -20,7 +20,7 @@ BlockPaintInvalidator(const LayoutBlock& block) : block_(block) {} void ClearPreviousVisualRects(); - PaintInvalidationReason InvalidatePaint(const PaintInvalidatorContext&); + void InvalidatePaint(const PaintInvalidatorContext&); private: const LayoutBlock& block_;
diff --git a/third_party/blink/renderer/core/paint/box_paint_invalidator.cc b/third_party/blink/renderer/core/paint/box_paint_invalidator.cc index 562dcfd..82ac60a 100644 --- a/third_party/blink/renderer/core/paint/box_paint_invalidator.cc +++ b/third_party/blink/renderer/core/paint/box_paint_invalidator.cc
@@ -225,36 +225,17 @@ } } -PaintInvalidationReason BoxPaintInvalidator::InvalidatePaint() { +void BoxPaintInvalidator::InvalidatePaint() { InvalidateBackground(); - PaintInvalidationReason reason = ComputePaintInvalidationReason(); - if (reason == PaintInvalidationReason::kIncremental) { - if (box_.PreviousSize() != box_.Size()) { - context_.painting_layer->SetNeedsRepaint(); - box_.InvalidateDisplayItemClients(reason); - } else { - reason = PaintInvalidationReason::kNone; - } - - // Though we have done incremental invalidation, we still need to call - // ObjectPaintInvalidator with PaintInvalidationNone to do any other - // required operations. - reason = std::max(reason, ObjectPaintInvalidatorWithContext(box_, context_) - .InvalidatePaintWithComputedReason( - PaintInvalidationReason::kNone)); - } else { - reason = ObjectPaintInvalidatorWithContext(box_, context_) - .InvalidatePaintWithComputedReason(reason); - } + ObjectPaintInvalidatorWithContext(box_, context_) + .InvalidatePaintWithComputedReason(ComputePaintInvalidationReason()); if (PaintLayerScrollableArea* area = box_.GetScrollableArea()) area->InvalidatePaintOfScrollControlsIfNeeded(context_); // This is for the next invalidatePaintIfNeeded so must be at the end. SavePreviousBoxGeometriesIfNeeded(); - - return reason; } bool BoxPaintInvalidator::
diff --git a/third_party/blink/renderer/core/paint/box_paint_invalidator.h b/third_party/blink/renderer/core/paint/box_paint_invalidator.h index 120692d..9cd71dc 100644 --- a/third_party/blink/renderer/core/paint/box_paint_invalidator.h +++ b/third_party/blink/renderer/core/paint/box_paint_invalidator.h
@@ -25,7 +25,7 @@ static void BoxWillBeDestroyed(const LayoutBox&); - PaintInvalidationReason InvalidatePaint(); + void InvalidatePaint(); private: friend class BoxPaintInvalidatorTest;
diff --git a/third_party/blink/renderer/core/paint/box_paint_invalidator_test.cc b/third_party/blink/renderer/core/paint/box_paint_invalidator_test.cc index 92c92a0..fd7efda 100644 --- a/third_party/blink/renderer/core/paint/box_paint_invalidator_test.cc +++ b/third_party/blink/renderer/core/paint/box_paint_invalidator_test.cc
@@ -46,7 +46,7 @@ GetDocument().View()->UpdateAllLifecyclePhases(); auto& target = *GetDocument().getElementById("target"); - const auto& box = *ToLayoutBox(target.GetLayoutObject()); + auto& box = *ToLayoutBox(target.GetLayoutObject()); LayoutRect visual_rect = box.FirstFragment().VisualRect(); LayoutPoint paint_offset = box.FirstFragment().PaintOffset(); @@ -79,6 +79,9 @@ height: 100px; transform-origin: 0 0; } + .background { + background: blue; + } .border { border-width: 20px 10px; border-style: solid; @@ -105,7 +108,6 @@ EXPECT_TRUE(box.PaintedOutputOfObjectHasNoEffectRegardlessOfSize()); LayoutRect visual_rect = box.FirstFragment().VisualRect(); - EXPECT_EQ(LayoutRect(0, 0, 50, 100), visual_rect); // No geometry change. EXPECT_EQ( @@ -139,7 +141,7 @@ target.setAttribute(HTMLNames::styleAttr, "background: blue"); GetDocument().View()->UpdateAllLifecyclePhases(); - box.SetMayNeedPaintInvalidation(); + box.SetShouldCheckForPaintInvalidation(); LayoutRect visual_rect = box.FirstFragment().VisualRect(); EXPECT_EQ(LayoutRect(0, 0, 50, 100), visual_rect); @@ -186,8 +188,8 @@ // The target initially has border. ExpectFullPaintInvalidationOnGeometryChange("With border"); - // Clear border. - target.setAttribute(HTMLNames::classAttr, ""); + // Clear border, set background. + target.setAttribute(HTMLNames::classAttr, "background"); target.setAttribute(HTMLNames::styleAttr, "border-radius: 5px"); ExpectFullPaintInvalidationOnGeometryChange("With border-radius");
diff --git a/third_party/blink/renderer/core/paint/box_painter.cc b/third_party/blink/renderer/core/paint/box_painter.cc index b856f70..473b45f 100644 --- a/third_party/blink/renderer/core/paint/box_painter.cc +++ b/third_party/blink/renderer/core/paint/box_painter.cc
@@ -111,8 +111,7 @@ // non-delayed-invalidation animated background, which should be ignored. if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled() && (style.Appearance() == kMediaSliderPart || - layout_box_.FullPaintInvalidationReason() == - PaintInvalidationReason::kDelayedFull)) { + layout_box_.ShouldDelayFullPaintInvalidation())) { cache_skipper.emplace(paint_info.context); }
diff --git a/third_party/blink/renderer/core/paint/embedded_object_paint_invalidator.cc b/third_party/blink/renderer/core/paint/embedded_object_paint_invalidator.cc deleted file mode 100644 index c81ef41..0000000 --- a/third_party/blink/renderer/core/paint/embedded_object_paint_invalidator.cc +++ /dev/null
@@ -1,24 +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. - -#include "third_party/blink/renderer/core/paint/embedded_object_paint_invalidator.h" - -#include "third_party/blink/renderer/core/exported/web_plugin_container_impl.h" -#include "third_party/blink/renderer/core/layout/layout_embedded_object.h" -#include "third_party/blink/renderer/core/paint/box_paint_invalidator.h" - -namespace blink { - -PaintInvalidationReason EmbeddedObjectPaintInvalidator::InvalidatePaint() { - PaintInvalidationReason reason = - BoxPaintInvalidator(embedded_object_, context_).InvalidatePaint(); - - WebPluginContainerImpl* plugin = embedded_object_.Plugin(); - if (plugin) - plugin->InvalidatePaint(); - - return reason; -} - -} // namespace blink
diff --git a/third_party/blink/renderer/core/paint/embedded_object_paint_invalidator.h b/third_party/blink/renderer/core/paint/embedded_object_paint_invalidator.h deleted file mode 100644 index d9c0a11..0000000 --- a/third_party/blink/renderer/core/paint/embedded_object_paint_invalidator.h +++ /dev/null
@@ -1,33 +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. - -#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_EMBEDDED_OBJECT_PAINT_INVALIDATOR_H_ -#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_EMBEDDED_OBJECT_PAINT_INVALIDATOR_H_ - -#include "third_party/blink/renderer/platform/graphics/paint_invalidation_reason.h" -#include "third_party/blink/renderer/platform/wtf/allocator.h" - -namespace blink { - -class LayoutEmbeddedObject; -struct PaintInvalidatorContext; - -class EmbeddedObjectPaintInvalidator { - STACK_ALLOCATED(); - - public: - EmbeddedObjectPaintInvalidator(const LayoutEmbeddedObject& embedded_object, - const PaintInvalidatorContext& context) - : embedded_object_(embedded_object), context_(context) {} - - PaintInvalidationReason InvalidatePaint(); - - private: - const LayoutEmbeddedObject& embedded_object_; - const PaintInvalidatorContext& context_; -}; - -} // namespace blink - -#endif
diff --git a/third_party/blink/renderer/core/paint/html_canvas_paint_invalidator.cc b/third_party/blink/renderer/core/paint/html_canvas_paint_invalidator.cc deleted file mode 100644 index c6e78348..0000000 --- a/third_party/blink/renderer/core/paint/html_canvas_paint_invalidator.cc +++ /dev/null
@@ -1,22 +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. - -#include "third_party/blink/renderer/core/paint/html_canvas_paint_invalidator.h" - -#include "third_party/blink/renderer/core/html/canvas/html_canvas_element.h" -#include "third_party/blink/renderer/core/layout/layout_html_canvas.h" -#include "third_party/blink/renderer/core/paint/box_paint_invalidator.h" -#include "third_party/blink/renderer/core/paint/paint_invalidator.h" - -namespace blink { - -PaintInvalidationReason HTMLCanvasPaintInvalidator::InvalidatePaint() { - auto* element = ToHTMLCanvasElement(html_canvas_.GetNode()); - if (element->IsDirty()) - element->DoDeferredPaintInvalidation(); - - return BoxPaintInvalidator(html_canvas_, context_).InvalidatePaint(); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/core/paint/html_canvas_paint_invalidator.h b/third_party/blink/renderer/core/paint/html_canvas_paint_invalidator.h deleted file mode 100644 index fdd94b4..0000000 --- a/third_party/blink/renderer/core/paint/html_canvas_paint_invalidator.h +++ /dev/null
@@ -1,33 +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. - -#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_HTML_CANVAS_PAINT_INVALIDATOR_H_ -#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_HTML_CANVAS_PAINT_INVALIDATOR_H_ - -#include "third_party/blink/renderer/platform/graphics/paint_invalidation_reason.h" -#include "third_party/blink/renderer/platform/wtf/allocator.h" - -namespace blink { - -class LayoutHTMLCanvas; -struct PaintInvalidatorContext; - -class HTMLCanvasPaintInvalidator { - STACK_ALLOCATED(); - - public: - HTMLCanvasPaintInvalidator(const LayoutHTMLCanvas& html_canvas, - const PaintInvalidatorContext& context) - : html_canvas_(html_canvas), context_(context) {} - - PaintInvalidationReason InvalidatePaint(); - - private: - const LayoutHTMLCanvas& html_canvas_; - const PaintInvalidatorContext& context_; -}; - -} // namespace blink - -#endif
diff --git a/third_party/blink/renderer/core/paint/object_paint_invalidator.cc b/third_party/blink/renderer/core/paint/object_paint_invalidator.cc index 88f1a5c6..eb66fe4 100644 --- a/third_party/blink/renderer/core/paint/object_paint_invalidator.cc +++ b/third_party/blink/renderer/core/paint/object_paint_invalidator.cc
@@ -285,7 +285,7 @@ } DISABLE_CFI_PERF -void ObjectPaintInvalidatorWithContext::InvalidateSelection( +PaintInvalidationReason ObjectPaintInvalidatorWithContext::InvalidateSelection( PaintInvalidationReason reason) { // In LayoutNG, if NGPaintFragment paints the selection, we invalidate for // selection change in PaintInvalidator. @@ -294,15 +294,15 @@ !object_.IsLayoutReplaced() && NGPaintFragment::InlineFragmentsFor(&object_) .IsInLayoutNGInlineFormattingContext()) - return; + return reason; // Update selection rect when we are doing full invalidation with geometry // change (in case that the object is moved, composite status changed, etc.) // or shouldInvalidationSelection is set (in case that the selection itself // changed). - bool full_invalidation = IsImmediateFullPaintInvalidationReason(reason); + bool full_invalidation = IsFullPaintInvalidationReason(reason); if (!full_invalidation && !object_.ShouldInvalidateSelection()) - return; + return reason; LayoutRect old_selection_rect = object_.SelectionVisualRect(); LayoutRect new_selection_rect; @@ -320,70 +320,50 @@ object_.GetMutableForPainting().SetSelectionVisualRect(new_selection_rect); if (full_invalidation) - return; + return reason; object_.GetMutableForPainting().SetPartialInvalidationVisualRect( UnionRect(object_.PartialInvalidationVisualRect(), UnionRect(new_selection_rect, old_selection_rect))); - context_.painting_layer->SetNeedsRepaint(); - object_.InvalidateDisplayItemClients(PaintInvalidationReason::kSelection); -} - -DISABLE_CFI_PERF -void ObjectPaintInvalidatorWithContext::InvalidatePartialRect( - PaintInvalidationReason reason) { - if (IsImmediateFullPaintInvalidationReason(reason)) - return; - - auto rect = object_.PartialInvalidationLocalRect(); - if (rect.IsEmpty()) - return; - - context_.MapLocalRectToVisualRect(object_, rect); - if (rect.IsEmpty()) - return; - - object_.GetMutableForPainting().SetPartialInvalidationVisualRect( - UnionRect(object_.PartialInvalidationVisualRect(), rect)); - - context_.painting_layer->SetNeedsRepaint(); - object_.InvalidateDisplayItemClients(PaintInvalidationReason::kRectangle); + return PaintInvalidationReason::kSelection; } DISABLE_CFI_PERF PaintInvalidationReason -ObjectPaintInvalidatorWithContext::InvalidatePaintWithComputedReason( +ObjectPaintInvalidatorWithContext::InvalidatePartialRect( + PaintInvalidationReason reason) { + if (IsFullPaintInvalidationReason(reason)) + return reason; + + auto rect = object_.PartialInvalidationLocalRect(); + if (rect.IsEmpty()) + return reason; + + context_.MapLocalRectToVisualRect(object_, rect); + if (rect.IsEmpty()) + return reason; + + object_.GetMutableForPainting().SetPartialInvalidationVisualRect( + UnionRect(object_.PartialInvalidationVisualRect(), rect)); + + return PaintInvalidationReason::kRectangle; +} + +DISABLE_CFI_PERF +void ObjectPaintInvalidatorWithContext::InvalidatePaintWithComputedReason( PaintInvalidationReason reason) { DCHECK(!(context_.subtree_flags & PaintInvalidatorContext::kSubtreeNoInvalidation)); - // This is before InvalidateSelection before the latter will accumulate - // selection visual rects to the partial rect mapped in the former. - InvalidatePartialRect(reason); - - // We need to invalidate the selection before checking for whether we are - // doing a full invalidation. This is because we need to update the previous - // selection rect regardless. - InvalidateSelection(reason); - - switch (reason) { - case PaintInvalidationReason::kNone: - if (object_.IsSVG() && - (context_.subtree_flags & - PaintInvalidatorContext::kSubtreeSVGResourceChange)) { - reason = PaintInvalidationReason::kSVGResource; - break; - } - return PaintInvalidationReason::kNone; - case PaintInvalidationReason::kDelayedFull: - return PaintInvalidationReason::kDelayedFull; - default: - DCHECK(IsImmediateFullPaintInvalidationReason(reason)); - } + // InvalidatePartialRect is before InvalidateSelection because the latter will + // accumulate selection visual rects to the partial rect mapped in the former. + reason = InvalidatePartialRect(reason); + reason = InvalidateSelection(reason); + if (reason == PaintInvalidationReason::kNone) + return; context_.painting_layer->SetNeedsRepaint(); object_.InvalidateDisplayItemClients(reason); - return reason; } } // namespace blink
diff --git a/third_party/blink/renderer/core/paint/object_paint_invalidator.h b/third_party/blink/renderer/core/paint/object_paint_invalidator.h index af5aad1..a0605c26 100644 --- a/third_party/blink/renderer/core/paint/object_paint_invalidator.h +++ b/third_party/blink/renderer/core/paint/object_paint_invalidator.h
@@ -56,17 +56,16 @@ const PaintInvalidatorContext& context) : ObjectPaintInvalidator(object), context_(context) {} - PaintInvalidationReason InvalidatePaint() { - return InvalidatePaintWithComputedReason(ComputePaintInvalidationReason()); + void InvalidatePaint() { + InvalidatePaintWithComputedReason(ComputePaintInvalidationReason()); } PaintInvalidationReason ComputePaintInvalidationReason(); - PaintInvalidationReason InvalidatePaintWithComputedReason( - PaintInvalidationReason); + void InvalidatePaintWithComputedReason(PaintInvalidationReason); private: - void InvalidateSelection(PaintInvalidationReason); - void InvalidatePartialRect(PaintInvalidationReason); + PaintInvalidationReason InvalidateSelection(PaintInvalidationReason); + PaintInvalidationReason InvalidatePartialRect(PaintInvalidationReason); const PaintInvalidatorContext& context_; };
diff --git a/third_party/blink/renderer/core/paint/object_paint_invalidator_test.cc b/third_party/blink/renderer/core/paint/object_paint_invalidator_test.cc index 5f053347..88c8cfd 100644 --- a/third_party/blink/renderer/core/paint/object_paint_invalidator_test.cc +++ b/third_party/blink/renderer/core/paint/object_paint_invalidator_test.cc
@@ -272,7 +272,7 @@ EXPECT_EQ(LayoutRect(10, 10, 50, 50), target->PartialInvalidationLocalRect()); target->InvalidatePaintRectangle(LayoutRect(30, 30, 60, 60)); EXPECT_EQ(LayoutRect(10, 10, 80, 80), target->PartialInvalidationLocalRect()); - EXPECT_TRUE(target->MayNeedPaintInvalidation()); + EXPECT_TRUE(target->ShouldCheckForPaintInvalidation()); GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint(); EXPECT_EQ(LayoutRect(), target->PartialInvalidationLocalRect()); @@ -331,7 +331,7 @@ // Simulate a change without full invalidation or selection change. GetDocument().View()->SetTracksPaintInvalidations(true); - target->SetMayNeedPaintInvalidation(); + target->SetShouldCheckForPaintInvalidation(); GetDocument().View()->UpdateAllLifecyclePhases(); EXPECT_TRUE(graphics_layer->GetRasterInvalidationTracking() ->Invalidations()
diff --git a/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.cc b/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.cc index b602bf0..367fbce 100644 --- a/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.cc +++ b/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.cc
@@ -645,7 +645,8 @@ ScrollableArea* scrollable_area = GetDocument().View()->LayoutViewport(); ASSERT_EQ(scrollable_area->MaximumScrollOffset().Height(), 0); - EXPECT_FALSE(GetDocument().GetLayoutView()->MayNeedPaintInvalidation()); + EXPECT_FALSE( + GetDocument().GetLayoutView()->ShouldCheckForPaintInvalidation()); Element* container = GetDocument().getElementById("container"); container->setAttribute(HTMLNames::styleAttr, @@ -653,7 +654,7 @@ GetDocument().UpdateStyleAndLayoutTree(); EXPECT_EQ(scrollable_area->MaximumScrollOffset().Height(), 1000); - EXPECT_TRUE(GetDocument().GetLayoutView()->MayNeedPaintInvalidation()); + EXPECT_TRUE(GetDocument().GetLayoutView()->ShouldCheckForPaintInvalidation()); } TEST_P(PaintAndRasterInvalidationTest, @@ -696,17 +697,26 @@ auto* target = GetLayoutObjectByElementId("target"); target->SetShouldDoFullPaintInvalidationWithoutGeometryChange( - PaintInvalidationReason::kDelayedFull); - EXPECT_EQ(PaintInvalidationReason::kDelayedFull, + PaintInvalidationReason::kForTesting); + target->SetShouldDelayFullPaintInvalidation(); + EXPECT_FALSE(target->ShouldDoFullPaintInvalidation()); + EXPECT_TRUE(target->ShouldDelayFullPaintInvalidation()); + EXPECT_EQ(PaintInvalidationReason::kForTesting, target->FullPaintInvalidationReason()); EXPECT_FALSE(target->NeedsPaintOffsetAndVisualRectUpdate()); + EXPECT_TRUE(target->ShouldCheckForPaintInvalidation()); + EXPECT_TRUE(target->Parent()->ShouldCheckForPaintInvalidation()); GetDocument().View()->SetTracksPaintInvalidations(true); GetDocument().View()->UpdateAllLifecyclePhases(); EXPECT_FALSE(GetRasterInvalidationTracking()->HasInvalidations()); - EXPECT_EQ(PaintInvalidationReason::kDelayedFull, + EXPECT_FALSE(target->ShouldDoFullPaintInvalidation()); + EXPECT_TRUE(target->ShouldDelayFullPaintInvalidation()); + EXPECT_EQ(PaintInvalidationReason::kForTesting, target->FullPaintInvalidationReason()); EXPECT_FALSE(target->NeedsPaintOffsetAndVisualRectUpdate()); + EXPECT_TRUE(target->ShouldCheckForPaintInvalidation()); + EXPECT_TRUE(target->Parent()->ShouldCheckForPaintInvalidation()); GetDocument().View()->SetTracksPaintInvalidations(false); GetDocument().View()->SetTracksPaintInvalidations(true); @@ -716,9 +726,12 @@ EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(), UnorderedElementsAre(RasterInvalidationInfo{ target, target->DebugName(), IntRect(0, 4000, 100, 100), - PaintInvalidationReason::kFull})); + PaintInvalidationReason::kForTesting})); EXPECT_EQ(PaintInvalidationReason::kNone, target->FullPaintInvalidationReason()); + EXPECT_FALSE(target->ShouldDelayFullPaintInvalidation()); + EXPECT_FALSE(target->ShouldCheckForPaintInvalidation()); + EXPECT_FALSE(target->Parent()->ShouldCheckForPaintInvalidation()); EXPECT_FALSE(target->NeedsPaintOffsetAndVisualRectUpdate()); GetDocument().View()->SetTracksPaintInvalidations(false); }; @@ -748,14 +761,6 @@ GetDocument().View()->SetTracksPaintInvalidations(true); ToElement(mask_rect->GetNode())->setAttribute("x", "20"); - GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint(); - - EXPECT_EQ(PaintInvalidationReason::kFull, - real_rect->GetPaintInvalidationReason()); - // mask_rect is not cached and validated by any PaintController. - EXPECT_EQ(PaintInvalidationReason::kJustCreated, - mask_rect->GetPaintInvalidationReason()); - GetDocument().View()->UpdateAllLifecyclePhases(); EXPECT_EQ(LayoutRect(), mask_rect->FirstFragment().VisualRect());
diff --git a/third_party/blink/renderer/core/paint/paint_invalidator.cc b/third_party/blink/renderer/core/paint/paint_invalidator.cc index 26487286..29de612ed 100644 --- a/third_party/blink/renderer/core/paint/paint_invalidator.cc +++ b/third_party/blink/renderer/core/paint/paint_invalidator.cc
@@ -501,27 +501,22 @@ UpdateVisualRect(object, *fragment_data, context); } - PaintInvalidationReason reason = object.InvalidatePaint(context); - switch (reason) { - case PaintInvalidationReason::kDelayedFull: - pending_delayed_paint_invalidations_.push_back(&object); - break; - case PaintInvalidationReason::kSubtree: - context.subtree_flags |= - (PaintInvalidatorContext::kSubtreeFullInvalidation | - PaintInvalidatorContext:: - kSubtreeFullInvalidationForStackedContents); - break; - case PaintInvalidationReason::kSVGResource: - context.subtree_flags |= - PaintInvalidatorContext::kSubtreeSVGResourceChange; - break; - default: - break; - } + object.InvalidatePaint(context); } - if (object.MayNeedPaintInvalidationSubtree()) { + auto reason = static_cast<const DisplayItemClient&>(object) + .GetPaintInvalidationReason(); + if (object.ShouldDelayFullPaintInvalidation() && + !IsFullPaintInvalidationReason(reason)) + pending_delayed_paint_invalidations_.push_back(&object); + + if (object.SubtreeShouldDoFullPaintInvalidation()) { + context.subtree_flags |= + PaintInvalidatorContext::kSubtreeFullInvalidation | + PaintInvalidatorContext::kSubtreeFullInvalidationForStackedContents; + } + + if (object.SubtreeShouldCheckForPaintInvalidation()) { context.subtree_flags |= PaintInvalidatorContext::kSubtreeInvalidationChecking; } @@ -547,16 +542,13 @@ // TODO(wangxianzhu): Do we need this for SPv2? if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled() && !context.paint_invalidation_container->IsPaintInvalidationContainer() && - object.GetPaintInvalidationReason() != PaintInvalidationReason::kNone) + reason != PaintInvalidationReason::kNone) InvalidateChromeClient(*context.paint_invalidation_container); } void PaintInvalidator::ProcessPendingDelayedPaintInvalidations() { - for (auto* target : pending_delayed_paint_invalidations_) { - target->GetMutableForPainting() - .SetShouldDoFullPaintInvalidationWithoutGeometryChange( - PaintInvalidationReason::kDelayedFull); - } + for (auto* target : pending_delayed_paint_invalidations_) + target->GetMutableForPainting().SetShouldDelayFullPaintInvalidation(); } } // namespace blink
diff --git a/third_party/blink/renderer/core/paint/paint_invalidator.h b/third_party/blink/renderer/core/paint/paint_invalidator.h index 7cb3e82..d6e96c5 100644 --- a/third_party/blink/renderer/core/paint/paint_invalidator.h +++ b/third_party/blink/renderer/core/paint/paint_invalidator.h
@@ -8,6 +8,7 @@ #include "third_party/blink/renderer/core/layout/layout_object.h" #include "third_party/blink/renderer/core/paint/paint_property_tree_builder.h" #include "third_party/blink/renderer/platform/geometry/layout_rect.h" +#include "third_party/blink/renderer/platform/graphics/paint_invalidation_reason.h" #include "third_party/blink/renderer/platform/wtf/vector.h" namespace blink { @@ -58,8 +59,7 @@ return subtree_flags & (kSubtreeInvalidationChecking | kSubtreeVisualRectUpdate | kSubtreeFullInvalidation | - kSubtreeFullInvalidationForStackedContents | - kSubtreeSVGResourceChange); + kSubtreeFullInvalidationForStackedContents); } const PaintInvalidatorContext* ParentContext() const { @@ -78,10 +78,9 @@ kSubtreeVisualRectUpdate = 1 << 1, kSubtreeFullInvalidation = 1 << 2, kSubtreeFullInvalidationForStackedContents = 1 << 3, - kSubtreeSVGResourceChange = 1 << 4, // For repeated objects inside multicolumn. - kSubtreeSlowPathRect = 1 << 5, + kSubtreeSlowPathRect = 1 << 4, // When this flag is set, no paint or raster invalidation will be issued // for the subtree.
diff --git a/third_party/blink/renderer/core/paint/paint_layer.cc b/third_party/blink/renderer/core/paint/paint_layer.cc index 77b9981..a881988 100644 --- a/third_party/blink/renderer/core/paint/paint_layer.cc +++ b/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -811,11 +811,11 @@ if (HasVisibleContent() != previously_has_visible_content) { SetNeedsCompositingInputsUpdateInternal(); - // We need to tell m_layoutObject to recheck its rect because we + // We need to tell layout_object_ to recheck its rect because we // pretend that invisible LayoutObjects have 0x0 rects. Changing // visibility therefore changes our rect and we need to visit - // this LayoutObject during the invalidateTreeIfNeeded walk. - layout_object_.SetMayNeedPaintInvalidation(); + // this LayoutObject during the PrePaintTreeWalk. + layout_object_.SetShouldCheckForPaintInvalidation(); } Update3DTransformedDescendantStatus(); @@ -1455,8 +1455,7 @@ // can't see this layer (which has been removed) so won't do this for us. ObjectPaintInvalidator(GetLayoutObject()) .InvalidatePaintIncludingNonCompositingDescendants(); - GetLayoutObject() - .SetShouldDoFullPaintInvalidationIncludingNonCompositingDescendants(); + GetLayoutObject().SetSubtreeShouldDoFullPaintInvalidation(); did_set_paint_invalidation = true; } }
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc index 5455935c..adea385 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc +++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
@@ -565,7 +565,7 @@ if (requires_paint_invalidation) { GetLayoutBox()->SetShouldDoFullPaintInvalidation(); - GetLayoutBox()->SetMayNeedPaintInvalidationSubtree(); + GetLayoutBox()->SetSubtreeShouldCheckForPaintInvalidation(); } else if (!UsesCompositedScrolling()) { // If any scrolling content might have ben clipped by a cull rect, then // that cull rect could be affected by scroll offset. For composited @@ -1892,10 +1892,8 @@ void PaintLayerScrollableArea::InvalidatePaintForStickyDescendants() { if (PaintLayerScrollableAreaRareData* d = RareData()) { - for (PaintLayer* sticky_layer : d->sticky_constraints_map_.Keys()) { - sticky_layer->GetLayoutObject() - .SetShouldDoFullPaintInvalidationIncludingNonCompositingDescendants(); - } + for (PaintLayer* sticky_layer : d->sticky_constraints_map_.Keys()) + sticky_layer->GetLayoutObject().SetSubtreeShouldDoFullPaintInvalidation(); } } @@ -2779,7 +2777,7 @@ } void PaintLayerScrollableArea::ScrollControlWasSetNeedsPaintInvalidation() { - GetLayoutBox()->SetMayNeedPaintInvalidation(); + GetLayoutBox()->SetShouldCheckForPaintInvalidation(); } void PaintLayerScrollableArea::DidScrollWithScrollbar(
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc index 76a55ce6..7b7403e5 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc +++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -1806,7 +1806,7 @@ // the entire subtree on paint offset changes. full_context_.force_subtree_update = true; - object_.GetMutableForPainting().SetMayNeedPaintInvalidation(); + object_.GetMutableForPainting().SetShouldCheckForPaintInvalidation(); fragment_data_.SetPaintOffset(context_.current.paint_offset); fragment_data_.InvalidateClipPathCache();
diff --git a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc index 78fa248..38354e90 100644 --- a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc +++ b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc
@@ -167,6 +167,12 @@ } auto* node = object.GetNode(); + if (!node && object.IsLayoutBlockFlow() && + ToLayoutBlockFlow(object).IsAnonymousBlockContinuation()) { + // An anonymous continuation does not have handlers so we need to check the + // DOM ancestor for handlers using |NodeForHitTest|. + node = object.NodeForHitTest(); + } if (!node) return false; return HasBlockingTouchEventHandler(*object.GetFrame(), *node);
diff --git a/third_party/blink/renderer/core/paint/table_cell_paint_invalidator.cc b/third_party/blink/renderer/core/paint/table_cell_paint_invalidator.cc index db26d502..f15db7c6 100644 --- a/third_party/blink/renderer/core/paint/table_cell_paint_invalidator.cc +++ b/third_party/blink/renderer/core/paint/table_cell_paint_invalidator.cc
@@ -16,12 +16,16 @@ namespace blink { +static bool DisplayItemClientIsFullyInvalidated( + const DisplayItemClient& client) { + return IsFullPaintInvalidationReason(client.GetPaintInvalidationReason()); +} + void TableCellPaintInvalidator::InvalidateContainerForCellGeometryChange( const LayoutObject& container, const PaintInvalidatorContext& container_context) { // We only need to do this if the container hasn't been fully invalidated. - DCHECK( - !IsFullPaintInvalidationReason(container.GetPaintInvalidationReason())); + DCHECK(!DisplayItemClientIsFullyInvalidated(container)); // At this time we have already walked the container for paint invalidation, // so we should invalidate the container immediately here instead of setting @@ -30,7 +34,7 @@ container.InvalidateDisplayItemClients(PaintInvalidationReason::kGeometry); } -PaintInvalidationReason TableCellPaintInvalidator::InvalidatePaint() { +void TableCellPaintInvalidator::InvalidatePaint() { // The cell's containing row and section paint backgrounds behind the cell, // and the row or table paints collapsed borders. If the cell's geometry // changed and the containers which will paint backgrounds and/or collapsed @@ -40,7 +44,7 @@ const auto& row = *cell_.Row(); const auto& section = *row.Section(); const auto& table = *section.Table(); - if (!IsFullPaintInvalidationReason(row.GetPaintInvalidationReason()) && + if (!DisplayItemClientIsFullyInvalidated(row) && (row.StyleRef().HasBackground() || (table.HasCollapsedBorders() && LIKELY(!table.ShouldPaintAllCollapsedBorders())))) { @@ -48,13 +52,13 @@ } if (UNLIKELY(table.ShouldPaintAllCollapsedBorders()) && - !IsFullPaintInvalidationReason(table.GetPaintInvalidationReason())) { + !DisplayItemClientIsFullyInvalidated(table)) { DCHECK(table.HasCollapsedBorders()); InvalidateContainerForCellGeometryChange( table, *context_.ParentContext()->ParentContext()->ParentContext()); } - if (!IsFullPaintInvalidationReason(section.GetPaintInvalidationReason())) { + if (!DisplayItemClientIsFullyInvalidated(section)) { bool section_paints_background = section.StyleRef().HasBackground(); if (!section_paints_background) { auto col_and_colgroup = section.Table()->ColElementAtAbsoluteColumn( @@ -72,7 +76,7 @@ } } - return BlockPaintInvalidator(cell_).InvalidatePaint(context_); + BlockPaintInvalidator(cell_).InvalidatePaint(context_); } } // namespace blink
diff --git a/third_party/blink/renderer/core/paint/table_cell_paint_invalidator.h b/third_party/blink/renderer/core/paint/table_cell_paint_invalidator.h index b2d129e1..e5a3086 100644 --- a/third_party/blink/renderer/core/paint/table_cell_paint_invalidator.h +++ b/third_party/blink/renderer/core/paint/table_cell_paint_invalidator.h
@@ -22,7 +22,7 @@ const PaintInvalidatorContext& context) : cell_(cell), context_(context) {} - PaintInvalidationReason InvalidatePaint(); + void InvalidatePaint(); private: void InvalidateContainerForCellGeometryChange(
diff --git a/third_party/blink/renderer/core/paint/table_paint_invalidator.cc b/third_party/blink/renderer/core/paint/table_paint_invalidator.cc index ac25e88..51529225 100644 --- a/third_party/blink/renderer/core/paint/table_paint_invalidator.cc +++ b/third_party/blink/renderer/core/paint/table_paint_invalidator.cc
@@ -14,9 +14,8 @@ namespace blink { -PaintInvalidationReason TablePaintInvalidator::InvalidatePaint() { - PaintInvalidationReason reason = - BoxPaintInvalidator(table_, context_).InvalidatePaint(); +void TablePaintInvalidator::InvalidatePaint() { + BoxPaintInvalidator(table_, context_).InvalidatePaint(); // If any col changed background, we need to invalidate all sections because // col background paints into section's background display item. @@ -29,7 +28,7 @@ // LayoutTableCol uses the table's localVisualRect(). Should check column // for paint invalidation when table's visual rect changed. if (visual_rect_changed) - col->SetMayNeedPaintInvalidation(); + col->SetShouldCheckForPaintInvalidation(); // This ensures that the backgroundChangedSinceLastPaintInvalidation flag // is up-to-date. col->EnsureIsReadyForPaintInvalidation(); @@ -52,8 +51,6 @@ *section, PaintInvalidationReason::kStyle); } } - - return reason; } } // namespace blink
diff --git a/third_party/blink/renderer/core/paint/table_paint_invalidator.h b/third_party/blink/renderer/core/paint/table_paint_invalidator.h index 315a9bd3..2bcadfb 100644 --- a/third_party/blink/renderer/core/paint/table_paint_invalidator.h +++ b/third_party/blink/renderer/core/paint/table_paint_invalidator.h
@@ -21,7 +21,7 @@ const PaintInvalidatorContext& context) : table_(table), context_(context) {} - PaintInvalidationReason InvalidatePaint(); + void InvalidatePaint(); private: const LayoutTable& table_;
diff --git a/third_party/blink/renderer/core/scheduler/frame_throttling_test.cc b/third_party/blink/renderer/core/scheduler/frame_throttling_test.cc index f739924..dd9ee9b 100644 --- a/third_party/blink/renderer/core/scheduler/frame_throttling_test.cc +++ b/third_party/blink/renderer/core/scheduler/frame_throttling_test.cc
@@ -204,10 +204,9 @@ inner_view->SetShouldDoFullPaintInvalidation( PaintInvalidationReason::kForTesting); inner_view->Layer()->SetNeedsRepaint(); - EXPECT_FALSE(inner_frame_document->View() - ->GetLayoutView() - ->FullPaintInvalidationReason() == - PaintInvalidationReason::kNone); + EXPECT_TRUE(inner_frame_document->View() + ->GetLayoutView() + ->ShouldDoFullPaintInvalidation()); inner_view->Compositor()->SetNeedsCompositingUpdate( kCompositingUpdateRebuildTree); EXPECT_EQ(kCompositingUpdateRebuildTree, @@ -219,10 +218,9 @@ EXPECT_TRUE(inner_frame_document->View()->ShouldThrottleRendering()); EXPECT_FALSE(inner_view->NeedsLayout()); - EXPECT_FALSE(inner_frame_document->View() - ->GetLayoutView() - ->FullPaintInvalidationReason() == - PaintInvalidationReason::kNone); + EXPECT_TRUE(inner_frame_document->View() + ->GetLayoutView() + ->ShouldDoFullPaintInvalidation()); EXPECT_EQ(kCompositingUpdateRebuildTree, inner_view->Compositor()->pending_update_type_); EXPECT_TRUE(inner_view->Layer()->NeedsRepaint());
diff --git a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc index eb8b539e..b384e8e8 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
@@ -312,15 +312,16 @@ if (!layout_object_) return kUnknownRole; + native_role_ = NativeAccessibilityRoleIgnoringAria(); + if ((aria_role_ = DetermineAriaRoleAttribute()) != kUnknownRole) return aria_role_; - AccessibilityRole role = NativeAccessibilityRoleIgnoringAria(); // Anything that needs to still be exposed but doesn't have a more specific // role should be considered a generic container. Examples are // layout blocks with no node, in-page link targets, and plain elements // such as a <span> with ARIA markup. - return role == kUnknownRole ? kGenericContainerRole : role; + return native_role_ == kUnknownRole ? kGenericContainerRole : native_role_; } Node* AXLayoutObject::GetNodeOrContainingBlockNode() const {
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc index 7dca85c..04f04f1 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
@@ -87,6 +87,7 @@ AXNodeObject::AXNodeObject(Node* node, AXObjectCacheImpl& ax_object_cache) : AXObject(ax_object_cache), children_dirty_(false), + native_role_(kUnknownRole), node_(node) {} AXNodeObject* AXNodeObject::Create(Node* node, @@ -453,6 +454,7 @@ if (GetNode()->HasTagName(sectionTag)) return kRegionRole; + // TODO(accessibility): http://crbug.com/873118 if (GetNode()->HasTagName(addressTag)) return kContentInfoRole; @@ -519,13 +521,14 @@ if (!GetNode()) return kUnknownRole; + native_role_ = NativeAccessibilityRoleIgnoringAria(); + if ((aria_role_ = DetermineAriaRoleAttribute()) != kUnknownRole) return aria_role_; if (GetNode()->IsTextNode()) return kStaticTextRole; - AccessibilityRole role = NativeAccessibilityRoleIgnoringAria(); - return role == kUnknownRole ? kGenericContainerRole : role; + return native_role_ == kUnknownRole ? kGenericContainerRole : native_role_; } void AXNodeObject::AccessibilityChildrenFromAOMProperty( @@ -2156,7 +2159,7 @@ return false; } - switch (NativeAccessibilityRoleIgnoringAria()) { + switch (native_role_) { case kButtonRole: case kCheckBoxRole: case kImageRole:
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.h b/third_party/blink/renderer/modules/accessibility/ax_node_object.h index 840aa9c..a36cf324 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_node_object.h +++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.h
@@ -54,6 +54,8 @@ #if DCHECK_IS_ON() bool initialized_ = false; #endif + // The accessibility role, not taking ARIA into account. + AccessibilityRole native_role_; bool ComputeAccessibilityIsIgnored(IgnoredReasons* = nullptr) const override; const AXObject* InheritsPresentationalRoleFrom() const override;
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_certificate.cc b/third_party/blink/renderer/modules/peerconnection/rtc_certificate.cc index 317ee0b..4fd68ad6 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_certificate.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_certificate.cc
@@ -36,29 +36,31 @@ namespace blink { -RTCCertificate::RTCCertificate(std::unique_ptr<WebRTCCertificate> certificate) - : certificate_(base::WrapUnique(certificate.release())) {} - -std::unique_ptr<WebRTCCertificate> RTCCertificate::CertificateShallowCopy() - const { - return certificate_->ShallowCopy(); -} +RTCCertificate::RTCCertificate( + rtc::scoped_refptr<rtc::RTCCertificate> certificate) + : certificate_(std::move(certificate)) {} DOMTimeStamp RTCCertificate::expires() const { return static_cast<DOMTimeStamp>(certificate_->Expires()); } HeapVector<RTCDtlsFingerprint> RTCCertificate::getFingerprints() { - WebVector<WebRTCDtlsFingerprint> web_fingerprints = - certificate_->GetFingerprints(); - DCHECK(!web_fingerprints.IsEmpty()); - HeapVector<RTCDtlsFingerprint> fingerprints(web_fingerprints.size()); - for (size_t i = 0; i < fingerprints.size(); ++i) { - DCHECK(!web_fingerprints[i].Algorithm().IsEmpty()); - DCHECK(!web_fingerprints[i].Value().IsEmpty()); - fingerprints[i].setAlgorithm(web_fingerprints[i].Algorithm()); - fingerprints[i].setValue(web_fingerprints[i].Value()); + std::unique_ptr<rtc::SSLCertificateStats> first_certificate_stats = + certificate_->ssl_certificate().GetStats(); + + HeapVector<RTCDtlsFingerprint> fingerprints; + for (rtc::SSLCertificateStats* certificate_stats = + first_certificate_stats.get(); + certificate_stats; certificate_stats = certificate_stats->issuer.get()) { + fingerprints.emplace_back(); + auto& fingerprint = fingerprints.back(); + fingerprint.setAlgorithm(WTF::String::FromUTF8( + certificate_stats->fingerprint_algorithm.c_str())); + fingerprint.setValue( + WTF::String::FromUTF8(certificate_stats->fingerprint.c_str()) + .LowerASCII()); } + return fingerprints; }
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_certificate.h b/third_party/blink/renderer/modules/peerconnection/rtc_certificate.h index 47fcbf5aa..4b3aa2e 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_certificate.h +++ b/third_party/blink/renderer/modules/peerconnection/rtc_certificate.h
@@ -33,7 +33,6 @@ #include <memory> -#include "third_party/blink/public/platform/web_rtc_certificate.h" #include "third_party/blink/renderer/core/dom/dom_time_stamp.h" #include "third_party/blink/renderer/modules/modules_export.h" #include "third_party/blink/renderer/modules/peerconnection/rtc_dtls_fingerprint.h" @@ -41,6 +40,7 @@ #include "third_party/blink/renderer/platform/heap/garbage_collected.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" #include "third_party/blink/renderer/platform/wtf/vector.h" +#include "third_party/webrtc/rtc_base/rtccertificate.h" namespace blink { @@ -49,18 +49,18 @@ public: // Takes ownership of the certificate. - RTCCertificate(std::unique_ptr<WebRTCCertificate>); + RTCCertificate(rtc::scoped_refptr<rtc::RTCCertificate>); - // Returns a new WebRTCCertificate shallow copy. - std::unique_ptr<WebRTCCertificate> CertificateShallowCopy() const; - const WebRTCCertificate& Certificate() const { return *certificate_; } + const rtc::scoped_refptr<rtc::RTCCertificate>& Certificate() const { + return certificate_; + } // Returns the expiration time in ms relative to epoch, 1970-01-01T00:00:00Z. DOMTimeStamp expires() const; HeapVector<RTCDtlsFingerprint> getFingerprints(); private: - std::unique_ptr<WebRTCCertificate> certificate_; + rtc::scoped_refptr<rtc::RTCCertificate> certificate_; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc index c50af6c..63ab728 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
@@ -43,7 +43,6 @@ #include "third_party/blink/public/platform/web_crypto_algorithm_params.h" #include "third_party/blink/public/platform/web_media_stream.h" #include "third_party/blink/public/platform/web_rtc_answer_options.h" -#include "third_party/blink/public/platform/web_rtc_certificate.h" #include "third_party/blink/public/platform/web_rtc_certificate_generator.h" #include "third_party/blink/public/platform/web_rtc_configuration.h" #include "third_party/blink/public/platform/web_rtc_data_channel_handler.h" @@ -114,6 +113,7 @@ #include "third_party/blink/renderer/platform/peerconnection/rtc_offer_options_platform.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/wtf/time.h" +#include "third_party/webrtc/api/peerconnectioninterface.h" namespace blink { @@ -241,7 +241,7 @@ explicit WebRTCCertificateObserver(ScriptPromiseResolver* resolver) : resolver_(resolver) {} - void OnSuccess(std::unique_ptr<WebRTCCertificate> certificate) override { + void OnSuccess(rtc::scoped_refptr<rtc::RTCCertificate> certificate) override { resolver_->Resolve(new RTCCertificate(std::move(certificate))); } @@ -364,10 +364,10 @@ if (configuration.hasCertificates()) { const HeapVector<Member<RTCCertificate>>& certificates = configuration.certificates(); - WebVector<std::unique_ptr<WebRTCCertificate>> certificates_copy( + WebVector<rtc::scoped_refptr<rtc::RTCCertificate>> certificates_copy( certificates.size()); for (size_t i = 0; i < certificates.size(); ++i) { - certificates_copy[i] = certificates[i]->CertificateShallowCopy(); + certificates_copy[i] = certificates[i]->Certificate(); } web_configuration.certificates = std::move(certificates_copy); } @@ -496,7 +496,7 @@ // Make sure no certificates have expired. if (configuration.certificates.size() > 0) { DOMTimeStamp now = ConvertSecondsToDOMTimeStamp(CurrentTime()); - for (const std::unique_ptr<WebRTCCertificate>& certificate : + for (const rtc::scoped_refptr<rtc::RTCCertificate>& certificate : configuration.certificates) { DOMTimeStamp expires = certificate->Expires(); if (expires <= now) {
diff --git a/third_party/blink/renderer/modules/peerconnection/testing/internals_rtc_certificate.cc b/third_party/blink/renderer/modules/peerconnection/testing/internals_rtc_certificate.cc index 0b28fec..8853bde 100644 --- a/third_party/blink/renderer/modules/peerconnection/testing/internals_rtc_certificate.cc +++ b/third_party/blink/renderer/modules/peerconnection/testing/internals_rtc_certificate.cc
@@ -9,7 +9,7 @@ bool InternalsRTCCertificate::rtcCertificateEquals(Internals& internals, RTCCertificate* a, RTCCertificate* b) { - return a->Certificate().Equals(b->Certificate()); + return a->Certificate() == b->Certificate(); } } // namespace blink
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn index 5b18e7b..2d5d1db 100644 --- a/third_party/blink/renderer/platform/BUILD.gn +++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -1861,6 +1861,7 @@ "//services/viz/public/interfaces", "//services/viz/public/interfaces:interfaces_blink", "//skia", + "//skia:skcms", "//testing/gmock", "//testing/gtest", "//third_party:freetype_harfbuzz",
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 5f5687c..2d22e00 100644 --- a/third_party/blink/renderer/platform/exported/web_runtime_features.cc +++ b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
@@ -76,10 +76,6 @@ RuntimeEnabledFeatures::SetOriginTrialControlledFeaturesEnabled(enable); } -void WebRuntimeFeatures::EnableOriginPolicy(bool enable) { - RuntimeEnabledFeatures::SetOriginPolicyEnabled(enable); -} - void WebRuntimeFeatures::EnableOutOfBlinkCORS(bool enable) { RuntimeEnabledFeatures::SetOutOfBlinkCORSEnabled(enable); } @@ -320,6 +316,10 @@ RuntimeEnabledFeatures::SetPictureInPictureAPIEnabled(enable); } +void WebRuntimeFeatures::EnablePortals(bool enable) { + RuntimeEnabledFeatures::SetPortalsEnabled(enable); +} + void WebRuntimeFeatures::EnablePreloadDefaultIsMetadata(bool enable) { RuntimeEnabledFeatures::SetPreloadDefaultIsMetadataEnabled(enable); }
diff --git a/third_party/blink/renderer/platform/graphics/paint_invalidation_reason.cc b/third_party/blink/renderer/platform/graphics/paint_invalidation_reason.cc index 37861d19..8fd5c50d 100644 --- a/third_party/blink/renderer/platform/graphics/paint_invalidation_reason.cc +++ b/third_party/blink/renderer/platform/graphics/paint_invalidation_reason.cc
@@ -72,8 +72,6 @@ return "full layer"; case PaintInvalidationReason::kForTesting: return "for testing"; - case PaintInvalidationReason::kDelayedFull: - return "delayed full"; } NOTREACHED(); return "";
diff --git a/third_party/blink/renderer/platform/graphics/paint_invalidation_reason.h b/third_party/blink/renderer/platform/graphics/paint_invalidation_reason.h index 8afacba3..c81b0d2 100644 --- a/third_party/blink/renderer/platform/graphics/paint_invalidation_reason.h +++ b/third_party/blink/renderer/platform/graphics/paint_invalidation_reason.h
@@ -31,6 +31,8 @@ // Scroll bars, scroll corner, etc. kScrollControl, kOutline, + // The object is invalidated as a part of a subtree full invalidation (forced + // by LayoutObject::SetSubtreeShouldDoFullPaintInvalidation()). kSubtree, kSVGResource, kBackground, @@ -51,13 +53,7 @@ // invalidation may be implicit, e.g. when a layer is created. kFullLayer, kForTesting, - // kDelayedFull means that kFull is needed in order to fully paint the - // content, but that painting of the object can be delayed until a future - // frame. This can be the case for an object whose content is not visible to - // the user. - kDelayedFull, - - kMax = kDelayedFull + kMax = kForTesting, }; PLATFORM_EXPORT const char* PaintInvalidationReasonToString( @@ -71,12 +67,6 @@ return reason >= PaintInvalidationReason::kFull; } -inline bool IsImmediateFullPaintInvalidationReason( - PaintInvalidationReason reason) { - return IsFullPaintInvalidationReason(reason) && - reason != PaintInvalidationReason::kDelayedFull; -} - PLATFORM_EXPORT std::ostream& operator<<(std::ostream&, PaintInvalidationReason);
diff --git a/third_party/blink/renderer/platform/graphics/paint_invalidation_reason_test.cc b/third_party/blink/renderer/platform/graphics/paint_invalidation_reason_test.cc index 7ecdd389..547928a 100644 --- a/third_party/blink/renderer/platform/graphics/paint_invalidation_reason_test.cc +++ b/third_party/blink/renderer/platform/graphics/paint_invalidation_reason_test.cc
@@ -9,18 +9,25 @@ namespace blink { +TEST(PaintInvalidationReasonTest, ToString) { + for (auto i = PaintInvalidationReason::kNone; + i <= PaintInvalidationReason::kMax; + i = static_cast<PaintInvalidationReason>(static_cast<int>(i) + 1)) + EXPECT_STRNE("", PaintInvalidationReasonToString(i)); + + EXPECT_STREQ("none", + PaintInvalidationReasonToString(PaintInvalidationReason::kNone)); + EXPECT_STREQ("full", + PaintInvalidationReasonToString(PaintInvalidationReason::kFull)); +} + TEST(PaintInvalidationReasonTest, StreamOutput) { - { + for (auto i = PaintInvalidationReason::kNone; + i <= PaintInvalidationReason::kMax; + i = static_cast<PaintInvalidationReason>(static_cast<int>(i) + 1)) { std::stringstream string_stream; - PaintInvalidationReason reason = PaintInvalidationReason::kNone; - string_stream << reason; - EXPECT_EQ("none", string_stream.str()); - } - { - std::stringstream string_stream; - PaintInvalidationReason reason = PaintInvalidationReason::kDelayedFull; - string_stream << reason; - EXPECT_EQ("delayed full", string_stream.str()); + string_stream << i; + EXPECT_EQ(PaintInvalidationReasonToString(i), string_stream.str()); } }
diff --git a/third_party/blink/renderer/platform/image-decoders/image_decoder.cc b/third_party/blink/renderer/platform/image-decoders/image_decoder.cc index 0f74520..b4de4a17 100644 --- a/third_party/blink/renderer/platform/image-decoders/image_decoder.cc +++ b/third_party/blink/renderer/platform/image-decoders/image_decoder.cc
@@ -64,6 +64,8 @@ } static constexpr size_t kLongestSignatureLength = sizeof("RIFF????WEBPVP") - 1; +static const size_t k4BytesPerPixel = 4; +static const size_t k8BytesPerPixel = 8; std::unique_ptr<ImageDecoder> ImageDecoder::Create( scoped_refptr<SegmentReader> data, @@ -75,15 +77,24 @@ // At least kLongestSignatureLength bytes are needed to sniff the signature. if (data->size() < kLongestSignatureLength) return nullptr; + // On low end devices, always decode to 8888. + if (high_bit_depth_decoding_option == kHighBitDepthToHalfFloat && + Platform::Current() && Platform::Current()->IsLowEndDevice()) { + high_bit_depth_decoding_option = kDefaultBitDepth; + } size_t max_decoded_bytes = Platform::Current() ? Platform::Current()->MaxDecodedImageBytes() : kNoDecodedImageByteLimit; if (!desired_size.isEmpty()) { - static const size_t kBytesPerPixels = 4; - size_t requested_decoded_bytes = - kBytesPerPixels * desired_size.width() * desired_size.height(); - max_decoded_bytes = std::min(requested_decoded_bytes, max_decoded_bytes); + size_t num_pixels = desired_size.width() * desired_size.height(); + if (high_bit_depth_decoding_option == kDefaultBitDepth) { + max_decoded_bytes = + std::min(k4BytesPerPixel * num_pixels, max_decoded_bytes); + } else { // kHighBitDepthToHalfFloat + max_decoded_bytes = + std::min(k8BytesPerPixel * num_pixels, max_decoded_bytes); + } } // Access the first kLongestSignatureLength chars to sniff the signature. @@ -188,8 +199,12 @@ uint64_t area; }; - return ImageSize(FrameSizeAtIndex(index)).area * - sizeof(ImageFrame::PixelData); + size_t decoded_bytes_per_pixel = k4BytesPerPixel; + if (frame_buffer_cache_[index].GetPixelFormat() == + ImageFrame::PixelFormat::kRGBA_F16) { + decoded_bytes_per_pixel = k8BytesPerPixel; + } + return ImageSize(FrameSizeAtIndex(index)).area * decoded_bytes_per_pixel; } size_t ImageDecoder::ClearCacheExceptFrame(size_t clear_except_frame) { @@ -391,12 +406,18 @@ // As we decode we will learn the total number of frames, and thus total // possible image memory used. + size_t decoded_bytes_per_pixel = k4BytesPerPixel; + + if (frame_buffer_cache_.size() && frame_buffer_cache_[0].GetPixelFormat() == + ImageFrame::PixelFormat::kRGBA_F16) { + decoded_bytes_per_pixel = k8BytesPerPixel; + } const uint64_t frame_memory_usage = - DecodedSize().Area() * 4; // 4 bytes per pixel + DecodedSize().Area() * decoded_bytes_per_pixel; // This condition never fails in the current code. Our existing image decoders // parse for the image size and SetFailed() if that size overflows - DCHECK_EQ(frame_memory_usage / 4, DecodedSize().Area()); + DCHECK_EQ(frame_memory_usage / decoded_bytes_per_pixel, DecodedSize().Area()); const uint64_t total_memory_usage = frame_memory_usage * index; if (total_memory_usage / frame_memory_usage != index) { // overflow occurred
diff --git a/third_party/blink/renderer/platform/image-decoders/image_decoder.h b/third_party/blink/renderer/platform/image-decoders/image_decoder.h index dff162e..1242a2e 100644 --- a/third_party/blink/renderer/platform/image-decoders/image_decoder.h +++ b/third_party/blink/renderer/platform/image-decoders/image_decoder.h
@@ -153,6 +153,12 @@ bool IsAllDataReceived() const { return is_all_data_received_; } + // Returns true if the decoder supports decoding to high bit depth. The + // decoded output will be high bit depth (half float backed bitmap) iff + // encoded image is high bit depth and high_bit_depth_decoding_option_ is set + // to kHighBitDepthToHalfFloat. + virtual bool ImageIsHighBitDepth() { return false; } + // Returns true if the buffer holds enough data to instantiate a decoder. // This is useful for callers to determine whether a decoder instantiation // failure is due to insufficient or bad data. @@ -214,7 +220,11 @@ // Returns whether the size is legal (i.e. not going to result in // overflow elsewhere). If not, marks decoding as failed. virtual bool SetSize(unsigned width, unsigned height) { - if (SizeCalculationMayOverflow(width, height)) + unsigned decoded_bytes_per_pixel = 4; + if (ImageIsHighBitDepth() && + high_bit_depth_decoding_option_ == kHighBitDepthToHalfFloat) + decoded_bytes_per_pixel = 8; + if (SizeCalculationMayOverflow(width, height, decoded_bytes_per_pixel)) return SetFailed(); size_ = IntSize(width, height); @@ -447,12 +457,16 @@ } private: - // Some code paths compute the size of the image as "width * height * 4" + // Some code paths compute the size of the image as "width * height * 4 or 8" // and return it as a (signed) int. Avoid overflow. - static bool SizeCalculationMayOverflow(unsigned width, unsigned height) { + static bool SizeCalculationMayOverflow(unsigned width, + unsigned height, + unsigned decoded_bytes_per_pixel) { unsigned long long total_size = static_cast<unsigned long long>(width) * static_cast<unsigned long long>(height); - return total_size > ((1 << 29) - 1); + if (decoded_bytes_per_pixel == 4) + return total_size > ((1 << 29) - 1); + return total_size > ((1 << 28) - 1); } bool purge_aggressively_;
diff --git a/third_party/blink/renderer/platform/image-decoders/image_decoder_test.cc b/third_party/blink/renderer/platform/image-decoders/image_decoder_test.cc index c6fc45b..0ae6fa60 100644 --- a/third_party/blink/renderer/platform/image-decoders/image_decoder_test.cc +++ b/third_party/blink/renderer/platform/image-decoders/image_decoder_test.cc
@@ -39,12 +39,15 @@ class TestImageDecoder : public ImageDecoder { public: - TestImageDecoder() + TestImageDecoder( + ImageDecoder::HighBitDepthDecodingOption high_bit_depth_decoding_option) : ImageDecoder(kAlphaNotPremultiplied, - ImageDecoder::kDefaultBitDepth, + high_bit_depth_decoding_option, ColorBehavior::TransformToSRGB(), kNoDecodedImageByteLimit) {} + TestImageDecoder() : TestImageDecoder(ImageDecoder::kDefaultBitDepth) {} + String FilenameExtension() const override { return ""; } Vector<ImageFrame, 1>& FrameBufferCache() { return frame_buffer_cache_; } @@ -64,20 +67,52 @@ frame_buffer_cache_[i].SetOriginalFrameRect(IntRect(0, 0, width, height)); } + bool ImageIsHighBitDepth() override { return image_is_high_bit_depth_; } + void SetImageToHighBitDepthForTest() { image_is_high_bit_depth_ = true; } + private: + bool image_is_high_bit_depth_ = false; void DecodeSize() override {} void Decode(size_t index) override {} }; TEST(ImageDecoderTest, sizeCalculationMayOverflow) { - std::unique_ptr<TestImageDecoder> decoder( - std::make_unique<TestImageDecoder>()); - EXPECT_FALSE(decoder->SetSize(1 << 29, 1)); - EXPECT_FALSE(decoder->SetSize(1, 1 << 29)); - EXPECT_FALSE(decoder->SetSize(1 << 15, 1 << 15)); - EXPECT_TRUE(decoder->SetSize(1 << 28, 1)); - EXPECT_TRUE(decoder->SetSize(1, 1 << 28)); - EXPECT_TRUE(decoder->SetSize(1 << 14, 1 << 14)); + // Test coverage: + // Regular bit depth image with regular decoder + // Regular bit depth image with high bit depth decoder + // High bit depth image with regular decoder + // High bit depth image with high bit depth decoder + bool high_bit_depth_decoder_status[] = {false, true}; + bool high_bit_depth_image_status[] = {false, true}; + + for (bool high_bit_depth_decoder : high_bit_depth_decoder_status) { + for (bool high_bit_depth_image : high_bit_depth_image_status) { + std::unique_ptr<TestImageDecoder> decoder; + if (high_bit_depth_decoder) { + decoder = std::make_unique<TestImageDecoder>( + ImageDecoder::kHighBitDepthToHalfFloat); + } else { + decoder = std::make_unique<TestImageDecoder>(); + } + if (high_bit_depth_image) + decoder->SetImageToHighBitDepthForTest(); + + unsigned log_pixel_size = 2; // pixel is 4 bytes + if (high_bit_depth_decoder && high_bit_depth_image) + log_pixel_size = 3; // pixel is 8 byts + unsigned overflow_dim_shift = 31 - log_pixel_size; + unsigned overflow_dim_shift_half = (overflow_dim_shift + 1) / 2; + + EXPECT_FALSE(decoder->SetSize(1 << overflow_dim_shift, 1)); + EXPECT_FALSE(decoder->SetSize(1, 1 << overflow_dim_shift)); + EXPECT_FALSE(decoder->SetSize(1 << overflow_dim_shift_half, + 1 << overflow_dim_shift_half)); + EXPECT_TRUE(decoder->SetSize(1 << (overflow_dim_shift - 1), 1)); + EXPECT_TRUE(decoder->SetSize(1, 1 << (overflow_dim_shift - 1))); + EXPECT_TRUE(decoder->SetSize(1 << (overflow_dim_shift_half - 1), + 1 << (overflow_dim_shift_half - 1))); + } + } } TEST(ImageDecoderTest, requiredPreviousFrameIndex) {
diff --git a/third_party/blink/renderer/platform/image-decoders/image_frame.cc b/third_party/blink/renderer/platform/image-decoders/image_frame.cc index b93d6f1..02ed602 100644 --- a/third_party/blink/renderer/platform/image-decoders/image_frame.cc +++ b/third_party/blink/renderer/platform/image-decoders/image_frame.cc
@@ -86,6 +86,7 @@ bool ImageFrame::CopyBitmapData(const ImageFrame& other) { DCHECK_NE(this, &other); has_alpha_ = other.has_alpha_; + pixel_format_ = other.pixel_format_; bitmap_.reset(); SkImageInfo info = other.bitmap_.info(); return bitmap_.tryAllocPixels(info) && @@ -101,6 +102,7 @@ if (other->bitmap_.isImmutable()) return false; has_alpha_ = other->has_alpha_; + pixel_format_ = other->pixel_format_; bitmap_.reset(); bitmap_.swap(other->bitmap_); other->status_ = kFrameEmpty; @@ -157,24 +159,6 @@ SetHasAlpha(true); } -void ImageFrame::SetRGBAPremultiplyF16Buffer(PixelDataF16* dst, - PixelDataF16* src, - size_t num_pixels) { - sk_sp<SkColorSpace> color_space = SkColorSpace::MakeSRGBLinear(); - auto color_format = SkColorSpaceXform::ColorFormat::kRGBA_F16_ColorFormat; - SkColorSpaceXform::Apply(color_space.get(), color_format, dst, - color_space.get(), color_format, src, num_pixels, - SkColorSpaceXform::AlphaOp::kPremul_AlphaOp); -} - -void ImageFrame::SetPixelsOpaqueF16Buffer(PixelDataF16* dst, - PixelDataF16* src, - size_t num_pixels) { - // We set the alpha half float to 0x3c00, which is equal to 1. - while (num_pixels-- > 0) - *dst++ = (*src++ & 0x0000ffffffffffff) | 0x3c00000000000000; -} - static void BlendRGBAF16Buffer(ImageFrame::PixelDataF16* dst, ImageFrame::PixelDataF16* src, size_t num_pixels,
diff --git a/third_party/blink/renderer/platform/image-decoders/image_frame.h b/third_party/blink/renderer/platform/image-decoders/image_frame.h index 0aec08e..9562391d 100644 --- a/third_party/blink/renderer/platform/image-decoders/image_frame.h +++ b/third_party/blink/renderer/platform/image-decoders/image_frame.h
@@ -81,10 +81,6 @@ ImageFrame(); - ImageFrame(PixelFormat pixel_format) : ImageFrame() { - pixel_format_ = pixel_format; - } - // The assignment operator reads has_alpha_ (inside SetStatus()) before it // sets it (in SetHasAlpha()). This doesn't cause any problems, since the // SetHasAlpha() call ensures all state is set correctly, but it means we @@ -157,6 +153,7 @@ return required_previous_frame_index_; } void SetHasAlpha(bool alpha); + void SetPixelFormat(PixelFormat format) { pixel_format_ = format; } void SetOriginalFrameRect(const IntRect& r) { original_frame_rect_ = r; } void SetStatus(Status); void SetDuration(TimeDelta duration) { duration_ = duration; } @@ -234,10 +231,6 @@ *dest = SkPackARGB32NoCheck(a, r, g, b); } - static void SetRGBAPremultiplyF16Buffer(PixelDataF16* dst, - PixelDataF16* src, - size_t num_pixels); - static inline void SetRGBARaw(PixelData* dest, unsigned r, unsigned g, @@ -246,10 +239,6 @@ *dest = SkPackARGB32NoCheck(a, r, g, b); } - static void SetPixelsOpaqueF16Buffer(PixelDataF16* dst, - PixelDataF16* src, - size_t num_pixels); - // Blend the RGBA pixel provided by |red|, |green|, |blue| and |alpha| over // the pixel in |dest|, without premultiplication, and overwrite |dest| with // the result.
diff --git a/third_party/blink/renderer/platform/image-decoders/image_frame_test.cc b/third_party/blink/renderer/platform/image-decoders/image_frame_test.cc index 07a506a..908a772 100644 --- a/third_party/blink/renderer/platform/image-decoders/image_frame_test.cc +++ b/third_party/blink/renderer/platform/image-decoders/image_frame_test.cc
@@ -65,80 +65,6 @@ } }; -TEST_F(ImageFrameTest, TestF16API) { - ImageFrame::PixelFormat kN32 = ImageFrame::PixelFormat::kN32; - ImageFrame::PixelFormat kRGBA_F16 = ImageFrame::PixelFormat::kRGBA_F16; - - ImageFrame frame_no_pixel_format; - ASSERT_EQ(kN32, frame_no_pixel_format.GetPixelFormat()); - - ImageFrame frame_pixel_format_n32(kN32); - ASSERT_EQ(kN32, frame_pixel_format_n32.GetPixelFormat()); - - ImageFrame frame_pixel_format_f16(kRGBA_F16); - ASSERT_EQ(kRGBA_F16, frame_pixel_format_f16.GetPixelFormat()); - - ImageFrame frame_copy_ctor_n32(frame_pixel_format_n32); - ASSERT_EQ(kN32, frame_copy_ctor_n32.GetPixelFormat()); - - ImageFrame frame_copy_ctor_f16(frame_pixel_format_f16); - ASSERT_EQ(kRGBA_F16, frame_copy_ctor_f16.GetPixelFormat()); - - ImageFrame frame_test_assignment; - frame_test_assignment = frame_pixel_format_n32; - ASSERT_EQ(kN32, frame_test_assignment.GetPixelFormat()); - frame_test_assignment = frame_pixel_format_f16; - ASSERT_EQ(kRGBA_F16, frame_test_assignment.GetPixelFormat()); - - SkBitmap bitmap(frame_pixel_format_f16.Bitmap()); - ASSERT_EQ(0, bitmap.width()); - ASSERT_EQ(0, bitmap.height()); - ASSERT_EQ(nullptr, bitmap.colorSpace()); - - TestAllocator allocator; - frame_pixel_format_f16.SetMemoryAllocator(&allocator); - sk_sp<SkColorSpace> srgb_linear = SkColorSpace::MakeSRGBLinear(); - - ASSERT_TRUE(frame_pixel_format_f16.AllocatePixelData(2, 2, srgb_linear)); - bitmap = frame_pixel_format_f16.Bitmap(); - ASSERT_EQ(2, bitmap.width()); - ASSERT_EQ(2, bitmap.height()); - ASSERT_TRUE(SkColorSpace::Equals(srgb_linear.get(), bitmap.colorSpace())); -} - -TEST_F(ImageFrameTest, SetRGBAPremultiplyF16Buffer) { - ImageFrame::PixelDataF16 premul_f16; - ImageFrame::SetRGBAPremultiplyF16Buffer(&premul_f16, &src_f16, 1); - - float f32_from_src_f16[4]; - ConvertF16ToF32(f32_from_src_f16, src_f16); - for (int i = 0; i < 3; i++) - f32_from_src_f16[i] *= f32_from_src_f16[3]; - - float f32_from_premul_f16[4]; - ConvertF16ToF32(f32_from_premul_f16, premul_f16); - - for (int i = 0; i < 4; i++) { - ASSERT_TRUE(fabs(f32_from_src_f16[i] - f32_from_premul_f16[i]) < - color_compoenent_tolerance); - } -} - -TEST_F(ImageFrameTest, SetPixelsOpaqueF16Buffer) { - ImageFrame::PixelDataF16 opaque_f16; - ImageFrame::SetPixelsOpaqueF16Buffer(&opaque_f16, &src_f16, 1); - - float f32_from_src_f16[4]; - ConvertF16ToF32(f32_from_src_f16, src_f16); - - float f32_from_opaque_f16[4]; - ConvertF16ToF32(f32_from_opaque_f16, opaque_f16); - - for (int i = 0; i < 3; i++) - ASSERT_EQ(f32_from_src_f16[i], f32_from_opaque_f16[i]); - ASSERT_EQ(1.0f, f32_from_opaque_f16[3]); -} - TEST_F(ImageFrameTest, BlendRGBARawF16Buffer) { ImageFrame::PixelData blended_8888(dst_8888); ImageFrame::BlendRGBARaw(&blended_8888, src_8888_r, src_8888_g, src_8888_b,
diff --git a/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder.cc b/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder.cc index 67e0bba5..f81c0fe0 100644 --- a/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder.cc +++ b/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder.cc
@@ -39,6 +39,7 @@ #include "third_party/blink/renderer/platform/image-decoders/png/png_image_decoder.h" #include <memory> +#include "third_party/skia/third_party/skcms/skcms.h" #if (defined(__ARM_NEON__) || defined(__ARM_NEON)) #include <arm_neon.h> @@ -63,7 +64,9 @@ // never be respected. repetition_count_(kAnimationLoopOnce), has_alpha_channel_(false), - current_buffer_saw_alpha_(false) {} + current_buffer_saw_alpha_(false), + decode_to_half_float_(false), + bit_depth_(0) {} PNGImageDecoder::~PNGImageDecoder() = default; @@ -139,6 +142,8 @@ void PNGImageDecoder::InitializeNewFrame(size_t index) { const PNGImageReader::FrameInfo& frame_info = reader_->GetFrameInfo(index); ImageFrame& buffer = frame_buffer_cache_[index]; + if (decode_to_half_float_) + buffer.SetPixelFormat(ImageFrame::PixelFormat::kRGBA_F16); DCHECK(IntRect(IntPoint(), Size()).Contains(frame_info.frame_rect)); buffer.SetOriginalFrameRect(frame_info.frame_rect); @@ -226,6 +231,26 @@ } } +void PNGImageDecoder::SetBitDepth() { + if (bit_depth_) + return; + png_structp png = reader_->PngPtr(); + png_infop info = reader_->InfoPtr(); + bit_depth_ = png_get_bit_depth(png, info); + decode_to_half_float_ = + (bit_depth_ == 16) && + (high_bit_depth_decoding_option_ == kHighBitDepthToHalfFloat) && + // TODO(zakerinasab): https://crbug.com/874057 + // Due to a lack of 16 bit APNG encoders, multi-frame 16 bit APNGs are not + // supported. In this case the decoder falls back to 8888 decode mode. + (repetition_count_ == kAnimationNone); +} + +bool PNGImageDecoder::ImageIsHighBitDepth() { + SetBitDepth(); + return bit_depth_ == 16; +} + bool PNGImageDecoder::SetSize(unsigned width, unsigned height) { DCHECK(!IsDecodedSizeAvailable()); // Protect against large PNGs. See http://bugzil.la/251381 for more details. @@ -255,7 +280,7 @@ if (png_get_valid(png, info, PNG_INFO_tRNS)) png_set_expand(png); - if (bit_depth == 16) + if (!decode_to_half_float_) png_set_strip_16(png); if (color_type == PNG_COLOR_TYPE_GRAY || @@ -503,7 +528,10 @@ if (PNG_INTERLACE_ADAM7 == png_get_interlace_type(png, reader_->InfoPtr())) { unsigned color_channels = has_alpha_channel_ ? 4 : 3; - reader_->CreateInterlaceBuffer(color_channels * Size().Area()); + unsigned interlace_buffer_size = color_channels * Size().Area(); + if (decode_to_half_float_) + interlace_buffer_size *= 2; + reader_->CreateInterlaceBuffer(interlace_buffer_size); if (!reader_->InterlaceBuffer()) { longjmp(JMPBUF(png), 1); return; @@ -575,120 +603,143 @@ // Write the decoded row pixels to the frame buffer. The repetitive // form of the row write loops is for speed. - ImageFrame::PixelData* const dst_row = buffer.GetAddr(frame_rect.X(), y); const int width = frame_rect.Width(); - png_bytep src_ptr = row; - if (has_alpha) { - // Here we apply the color space transformation to the dst space. - // It does not really make sense to transform to a gamma-encoded - // space and then immediately after, perform a linear premultiply. - // Ideally we would pass kPremul_SkAlphaType to xform->apply(), - // instructing SkColorSpaceXform to perform the linear premultiply - // while the pixels are a linear space. - // We cannot do this because when we apply the gamma encoding after - // the premultiply, we will very likely end up with valid pixels - // where R, G, and/or B are greater than A. The legacy drawing - // pipeline does not know how to handle this. - if (ColorProfileTransform* xform = ColorTransform()) { - ImageFrame::PixelData* xform_dst = dst_row; - // If we're blending over the previous frame, we can't overwrite that - // when we do the color transform. So we allocate another row of pixels - // to hold the temporary result before blending. In all other cases, - // we can safely transform directly to the destination buffer, then do - // any operations in-place (premul, swizzle). + + if (!decode_to_half_float_) { + ImageFrame::PixelData* const dst_row = buffer.GetAddr(frame_rect.X(), y); + if (has_alpha) { + if (ColorProfileTransform* xform = ColorTransform()) { + ImageFrame::PixelData* xform_dst = dst_row; + // If we're blending over the previous frame, we can't overwrite that + // when we do the color transform. So we allocate another row of pixels + // to hold the temporary result before blending. In all other cases, + // we can safely transform directly to the destination buffer, then do + // any operations in-place (premul, swizzle). + if (frame_buffer_cache_[current_frame_].GetAlphaBlendSource() == + ImageFrame::kBlendAtopPreviousFrame) { + if (!color_transform_scanline_) { + // This buffer may be wider than necessary for this frame, but by + // allocating the full width of the PNG, we know it will be able to + // hold temporary data for any subsequent frame. + color_transform_scanline_.reset( + new ImageFrame::PixelData[Size().Width()]); + } + xform_dst = color_transform_scanline_.get(); + } + skcms_PixelFormat color_format = skcms_PixelFormat_RGBA_8888; + skcms_AlphaFormat alpha_format = skcms_AlphaFormat_Unpremul; + bool color_conversion_successful = skcms_Transform( + src_ptr, color_format, alpha_format, xform->SrcProfile(), xform_dst, + color_format, alpha_format, xform->DstProfile(), width); + DCHECK(color_conversion_successful); + src_ptr = png_bytep(xform_dst); + } + + unsigned alpha_mask = 255; if (frame_buffer_cache_[current_frame_].GetAlphaBlendSource() == - ImageFrame::kBlendAtopPreviousFrame) { - if (!color_transform_scanline_) { - // This buffer may be wider than necessary for this frame, but by - // allocating the full width of the PNG, we know it will be able to - // hold temporary data for any subsequent frame. - color_transform_scanline_.reset( - new ImageFrame::PixelData[Size().Width()]); - } - xform_dst = color_transform_scanline_.get(); - } - skcms_PixelFormat color_format = skcms_PixelFormat_RGBA_8888; - skcms_AlphaFormat alpha_format = skcms_AlphaFormat_Unpremul; - bool color_conversion_successful = skcms_Transform( - src_ptr, color_format, alpha_format, xform->SrcProfile(), xform_dst, - color_format, alpha_format, xform->DstProfile(), width); - DCHECK(color_conversion_successful); - src_ptr = png_bytep(xform_dst); - } - - unsigned alpha_mask = 255; - if (frame_buffer_cache_[current_frame_].GetAlphaBlendSource() == - ImageFrame::kBlendAtopBgcolor) { - if (buffer.PremultiplyAlpha()) { + ImageFrame::kBlendAtopBgcolor) { + if (buffer.PremultiplyAlpha()) { #if (defined(__ARM_NEON__) || defined(__ARM_NEON)) - SetRGBAPremultiplyRowNeon(src_ptr, width, dst_row, &alpha_mask); + SetRGBAPremultiplyRowNeon(src_ptr, width, dst_row, &alpha_mask); #else - for (auto *dst_pixel = dst_row; dst_pixel < dst_row + width; - dst_pixel++, src_ptr += 4) { - ImageFrame::SetRGBAPremultiply(dst_pixel, src_ptr[0], src_ptr[1], - src_ptr[2], src_ptr[3]); - alpha_mask &= src_ptr[3]; - } + for (auto *dst_pixel = dst_row; dst_pixel < dst_row + width; + dst_pixel++, src_ptr += 4) { + ImageFrame::SetRGBAPremultiply(dst_pixel, src_ptr[0], src_ptr[1], + src_ptr[2], src_ptr[3]); + alpha_mask &= src_ptr[3]; + } #endif - } else { + } else { #if (defined(__ARM_NEON__) || defined(__ARM_NEON)) - SetRGBARawRowNeon(src_ptr, width, dst_row, &alpha_mask); + SetRGBARawRowNeon(src_ptr, width, dst_row, &alpha_mask); #else - for (auto *dst_pixel = dst_row; dst_pixel < dst_row + width; - dst_pixel++, src_ptr += 4) { - ImageFrame::SetRGBARaw(dst_pixel, src_ptr[0], src_ptr[1], src_ptr[2], - src_ptr[3]); - alpha_mask &= src_ptr[3]; - } -#endif - } - } else { - // Now, the blend method is ImageFrame::BlendAtopPreviousFrame. Since the - // frame data of the previous frame is copied at InitFrameBuffer, we can - // blend the pixel of this frame, stored in |src_ptr|, over the previous - // pixel stored in |dst_pixel|. - if (buffer.PremultiplyAlpha()) { - for (auto *dst_pixel = dst_row; dst_pixel < dst_row + width; - dst_pixel++, src_ptr += 4) { - ImageFrame::BlendRGBAPremultiplied(dst_pixel, src_ptr[0], src_ptr[1], - src_ptr[2], src_ptr[3]); - alpha_mask &= src_ptr[3]; - } - } else { - for (auto *dst_pixel = dst_row; dst_pixel < dst_row + width; - dst_pixel++, src_ptr += 4) { - ImageFrame::BlendRGBARaw(dst_pixel, src_ptr[0], src_ptr[1], + for (auto *dst_pixel = dst_row; dst_pixel < dst_row + width; + dst_pixel++, src_ptr += 4) { + ImageFrame::SetRGBARaw(dst_pixel, src_ptr[0], src_ptr[1], src_ptr[2], src_ptr[3]); - alpha_mask &= src_ptr[3]; + alpha_mask &= src_ptr[3]; + } +#endif + } + } else { + // Now, the blend method is ImageFrame::BlendAtopPreviousFrame. Since + // the frame data of the previous frame is copied at InitFrameBuffer, we + // can blend the pixel of this frame, stored in |src_ptr|, over the + // previous pixel stored in |dst_pixel|. + if (buffer.PremultiplyAlpha()) { + for (auto *dst_pixel = dst_row; dst_pixel < dst_row + width; + dst_pixel++, src_ptr += 4) { + ImageFrame::BlendRGBAPremultiplied( + dst_pixel, src_ptr[0], src_ptr[1], src_ptr[2], src_ptr[3]); + alpha_mask &= src_ptr[3]; + } + } else { + for (auto *dst_pixel = dst_row; dst_pixel < dst_row + width; + dst_pixel++, src_ptr += 4) { + ImageFrame::BlendRGBARaw(dst_pixel, src_ptr[0], src_ptr[1], + src_ptr[2], src_ptr[3]); + alpha_mask &= src_ptr[3]; + } } } - } - if (alpha_mask != 255) - current_buffer_saw_alpha_ = true; + if (alpha_mask != 255) + current_buffer_saw_alpha_ = true; - } else { + } else { #if (defined(__ARM_NEON__) || defined(__ARM_NEON)) - SetRGBARawRowNoAlphaNeon(src_ptr, width, dst_row); + SetRGBARawRowNoAlphaNeon(src_ptr, width, dst_row); #else - for (auto *dst_pixel = dst_row; dst_pixel < dst_row + width; - src_ptr += 3, ++dst_pixel) { - ImageFrame::SetRGBARaw(dst_pixel, src_ptr[0], src_ptr[1], src_ptr[2], - 255); - } + for (auto *dst_pixel = dst_row; dst_pixel < dst_row + width; + src_ptr += 3, ++dst_pixel) { + ImageFrame::SetRGBARaw(dst_pixel, src_ptr[0], src_ptr[1], src_ptr[2], + 255); + } #endif - // We'll apply the color space xform to opaque pixels after they have been - // written to the ImageFrame. - // TODO: Apply the xform to the RGB pixels, skipping second pass over data. - if (ColorProfileTransform* xform = ColorTransform()) { - skcms_AlphaFormat alpha_format = skcms_AlphaFormat_Opaque; - bool color_conversion_successful = - skcms_Transform(dst_row, XformColorFormat(), alpha_format, - xform->SrcProfile(), dst_row, XformColorFormat(), - alpha_format, xform->DstProfile(), width); - DCHECK(color_conversion_successful); + // We'll apply the color space xform to opaque pixels after they have been + // written to the ImageFrame. + // TODO: Apply the xform to the RGB pixels, skipping second pass over + // data. + if (ColorProfileTransform* xform = ColorTransform()) { + skcms_AlphaFormat alpha_format = skcms_AlphaFormat_Opaque; + bool color_conversion_successful = + skcms_Transform(dst_row, XformColorFormat(), alpha_format, + xform->SrcProfile(), dst_row, XformColorFormat(), + alpha_format, xform->DstProfile(), width); + DCHECK(color_conversion_successful); + } } + } else { // for if (!decode_to_half_float_) + ImageFrame::PixelDataF16* const dst_row_f16 = + buffer.GetAddrF16(frame_rect.X(), y); + + // TODO(zakerinasab): https://crbug.com/874057 + // Due to a lack of 16 bit APNG encoders, multi-frame 16 bit APNGs are not + // supported. Hence, we expect the blending mode always be + // kBlendAtopBgcolor. + DCHECK(frame_buffer_cache_[current_frame_].GetAlphaBlendSource() == + ImageFrame::kBlendAtopBgcolor); + + // Color space transformation to the dst space and converting the decoded + // color componenets from uint16 to float16. + auto* xform = ColorTransform(); + auto* src_profile = xform ? xform->SrcProfile() : nullptr; + auto* dst_profile = xform ? xform->DstProfile() : nullptr; + auto src_format = has_alpha ? skcms_PixelFormat_RGBA_16161616 + : skcms_PixelFormat_RGB_161616; + auto src_alpha_format = + has_alpha ? skcms_AlphaFormat_Unpremul : skcms_AlphaFormat_Opaque; + auto dst_alpha_format = has_alpha ? (buffer.PremultiplyAlpha() + ? skcms_AlphaFormat_PremulAsEncoded + : skcms_AlphaFormat_Unpremul) + : skcms_AlphaFormat_Opaque; + bool success = skcms_Transform( + src_ptr, src_format, src_alpha_format, src_profile, dst_row_f16, + skcms_PixelFormat_RGBA_hhhh, dst_alpha_format, dst_profile, width); + DCHECK(success); + + current_buffer_saw_alpha_ = has_alpha; } buffer.SetPixelsChanged(true);
diff --git a/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder.h b/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder.h index a82f8a0..8c44bfe 100644 --- a/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder.h +++ b/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder.h
@@ -48,6 +48,7 @@ String FilenameExtension() const override { return "png"; } bool SetSize(unsigned, unsigned) override; int RepetitionCount() const override; + bool ImageIsHighBitDepth() override; bool FrameIsReceivedAtIndex(size_t) const override; TimeDelta FrameDurationAtIndex(size_t) const override; bool SetFailed() override; @@ -59,6 +60,7 @@ void SetColorSpace(); void SetRepetitionCount(int); + void SetBitDepth(); private: using ParseQuery = PNGImageReader::ParseQuery; @@ -78,6 +80,8 @@ int repetition_count_; bool has_alpha_channel_; bool current_buffer_saw_alpha_; + bool decode_to_half_float_; + size_t bit_depth_; std::unique_ptr<ImageFrame::PixelData[]> color_transform_scanline_; };
diff --git a/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder_test.cc b/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder_test.cc index c24afa1..26ab2543 100644 --- a/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder_test.cc +++ b/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder_test.cc
@@ -9,6 +9,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/renderer/platform/image-decoders/image_decoder_test_helpers.h" #include "third_party/blink/renderer/platform/wtf/time.h" +#include "third_party/skia/include/core/SkImage.h" // /LayoutTests/images/resources/png-animated-idat-part-of-animation.png // is modified in multiple tests to simulate erroneous PNGs. As a reference, @@ -43,6 +44,13 @@ return CreatePNGDecoder(ImageDecoder::kAlphaNotPremultiplied); } +std::unique_ptr<ImageDecoder> Create16BitPNGDecoder() { + return std::make_unique<PNGImageDecoder>( + ImageDecoder::kAlphaNotPremultiplied, + ImageDecoder::kHighBitDepthToHalfFloat, ColorBehavior::Tag(), + ImageDecoder::kNoDecodedImageByteLimit); +} + std::unique_ptr<ImageDecoder> CreatePNGDecoderWithPngData( const char* png_file) { auto decoder = CreatePNGDecoder(); @@ -994,6 +1002,252 @@ "/images/resources/png-simple.png", 1000u); } +struct PNGSample { + String filename; + String color_space; + bool is_transparent; + bool is_high_bit_depth; + scoped_refptr<SharedBuffer> png_contents; + std::vector<float> expected_pixels; +}; + +static void TestHighBitDepthPNGDecoding(const PNGSample& png_sample, + ImageDecoder* decoder) { + scoped_refptr<SharedBuffer> png = png_sample.png_contents; + ASSERT_TRUE(png.get()); + decoder->SetData(png.get(), true); + ASSERT_TRUE(decoder->IsSizeAvailable()); + ASSERT_TRUE(decoder->IsDecodedSizeAvailable()); + + IntSize size(2, 2); + ASSERT_EQ(size, decoder->Size()); + ASSERT_EQ(size, decoder->DecodedSize()); + ASSERT_EQ(true, decoder->ImageIsHighBitDepth()); + + ASSERT_TRUE(decoder->FrameIsReceivedAtIndex(0)); + ASSERT_EQ(size, decoder->FrameSizeAtIndex(0)); + + ASSERT_EQ(1u, decoder->FrameCount()); + ASSERT_EQ(kAnimationNone, decoder->RepetitionCount()); + + auto* frame = decoder->DecodeFrameBufferAtIndex(0); + ASSERT_TRUE(frame); + ASSERT_EQ(ImageFrame::kFrameComplete, frame->GetStatus()); + ASSERT_EQ(ImageFrame::kRGBA_F16, frame->GetPixelFormat()); + + sk_sp<SkImage> image = frame->FinalizePixelsAndGetImage(); + ASSERT_TRUE(image); + + ASSERT_EQ(2, image->width()); + ASSERT_EQ(2, image->height()); + ASSERT_EQ(kRGBA_F16_SkColorType, image->colorType()); + + // Readback pixels and convert color components from half float to float. + SkImageInfo info = + SkImageInfo::Make(2, 2, kRGBA_F16_SkColorType, kUnpremul_SkAlphaType, + image->refColorSpace()); + std::unique_ptr<uint8_t[]> decoded_pixels( + new uint8_t[info.computeMinByteSize()]()); + ASSERT_TRUE( + image->readPixels(info, decoded_pixels.get(), info.minRowBytes(), 0, 0)); + + float decoded_pixels_float_32[16]; + ASSERT_TRUE(skcms_Transform( + decoded_pixels.get(), skcms_PixelFormat_RGBA_hhhh, + skcms_AlphaFormat_Unpremul, nullptr, decoded_pixels_float_32, + skcms_PixelFormat_RGBA_ffff, skcms_AlphaFormat_Unpremul, nullptr, 4)); + + std::vector<float> expected_pixels = png_sample.expected_pixels; + bool test_succeed = true; + const float decoding_tolerance = 0.001; + for (int i = 0; i < 16; i++) { + if (fabs(decoded_pixels_float_32[i] - expected_pixels[i]) > + decoding_tolerance) { + DLOG(DCHECK) << "Pixel comparison failed. File: " << png_sample.filename + << ", component index: " << i + << ", actual: " << decoded_pixels_float_32[i] + << ", expected: " << expected_pixels[i] + << ", tolerance: " << decoding_tolerance; + test_succeed = false; + } + } + ASSERT_TRUE(test_succeed); +} + +static void FillPNGSamplesSourcePixels(std::vector<PNGSample>& png_samples) { + // Color components of opaque and transparent 16 bit PNG, read with libpng + // in BigEndian and scaled to [0,1]. The values are read from non-interlaced + // samples, but used for both interlaced and non-interlaced test cases. + static const std::vector<float> source_pixels_opaque_srgb = { + 0.4986953536, 0.5826657511, 0.7013199054, 1, // Top left pixel + 0.907988098, 0.8309605554, 0.492011902, 1, // Top right pixel + 0.6233157855, 0.9726558328, 0.9766536965, 1, // Bottom left pixel + 0.8946517128, 0.9663080797, 0.9053025101, 1}; // Bottom right pixel + static const std::vector<float> source_pixels_opaque_adobe_rgb = { + 0.4448004883, 0.5216296635, 0.6506294347, 1, // Top left pixel + 0.8830548562, 0.7978179599, 0.4323186084, 1, // Top right pixel + 0.6841992828, 0.9704280156, 0.9711299306, 1, // Bottom left pixel + 0.8874799725, 0.96099794, 0.8875715267, 1}; // Bottom right pixel + static const std::vector<float> source_pixels_opaque_p3 = { + 0.515648127, 0.5802243076, 0.6912489509, 1, // Top left pixel + 0.8954146639, 0.8337987335, 0.5691767758, 1, // Top right pixel + 0.772121767, 0.9671625849, 0.973510338, 1, // Bottom left pixel + 0.9118944076, 0.9645685512, 0.9110704204, 1}; // Bottom right pixel + static const std::vector<float> source_pixels_opaque_e_srgb = { + 0.6414435035, 0.6857862211, 0.747005417, 1, // Top left pixel + 0.877347982, 0.8382848859, 0.6494087129, 1, // Top right pixel + 0.735194934, 0.9353933013, 0.9374380102, 1, // Bottom left pixel + 0.9209277485, 0.9575799191, 0.9264515145, 1}; // Bottom right pixel + static const std::vector<float> source_pixels_opaque_prophoto = { + 0.5032883192, 0.5191271839, 0.6309147784, 1, // Top left pixel + 0.8184176394, 0.8002899214, 0.5526970321, 1, // Top right pixel + 0.842526894, 0.945616846, 0.9667048142, 1, // Bottom left pixel + 0.9119554437, 0.9507133593, 0.9001754788, 1}; // Bottom right pixel + static const std::vector<float> source_pixels_opaque_rec2020 = { + 0.5390554665, 0.5766842145, 0.6851758602, 1, // Top left pixel + 0.871061265, 0.831326772, 0.5805294881, 1, // Top right pixel + 0.8386205844, 0.9599603265, 0.9727168688, 1, // Bottom left pixel + 0.9235217823, 0.9611200122, 0.9112840467, 1}; // Bottom right pixel + + static const std::vector<float> source_pixels_transparent_srgb = { + 0.3733272297, 0.4783093004, 0.6266422522, 0.8, // Top left pixel + 0.8466468299, 0.7182879377, 0.153322652, 0.6, // Top right pixel + 0.05831998169, 0.9316395819, 0.9416495003, 0.4, // Bottom left pixel + 0.4733043412, 0.8316319524, 0.5266346227, 0.2}; // Bottom right pixel + static const std::vector<float> source_pixels_transparent_adobe_rgb = { + 0.305943389, 0.4019836728, 0.5632867933, 0.8, // Top left pixel + 0.8051117723, 0.6630197604, 0.05374227512, 0.6, // Top right pixel + 0.210482948, 0.926115816, 0.9278248264, 0.4, // Bottom left pixel + 0.4374456397, 0.8050812543, 0.4379644465, 0.2}; // Bottom right pixel + static const std::vector<float> source_pixels_transparent_p3 = { + 0.3945372702, 0.475257496, 0.6140383001, 0.8, // Top left pixel + 0.8257114519, 0.7230182345, 0.2819256886, 0.6, // Top right pixel + 0.4302738994, 0.9179064622, 0.933806363, 0.4, // Bottom left pixel + 0.5595330739, 0.8228122377, 0.5554436561, 0.2}; // Bottom right pixel + static const std::vector<float> source_pixels_transparent_e_srgb = { + 0.5517814908, 0.6072327764, 0.6837415122, 0.8, // Top left pixel + 0.7955901427, 0.7304646372, 0.4156557565, 0.6, // Top right pixel + 0.3380178531, 0.8385290303, 0.8435950256, 0.4, // Bottom left pixel + 0.6046997787, 0.7879606317, 0.6323186084, 0.2}; // Bottom right pixel + static const std::vector<float> source_pixels_transparent_prophoto = { + 0.379064622, 0.3988708324, 0.5386282139, 0.8, // Top left pixel + 0.6973525597, 0.6671396963, 0.2544289311, 0.6, // Top right pixel + 0.6063477531, 0.864103151, 0.9168078126, 0.4, // Bottom left pixel + 0.5598077363, 0.7536278325, 0.5009384298, 0.2}; // Bottom right pixel + static const std::vector<float> source_pixels_transparent_rec2020 = { + 0.4237735561, 0.4708323796, 0.6064698253, 0.8, // Top left pixel + 0.7851224537, 0.7188677806, 0.3008468757, 0.6, // Top right pixel + 0.5965819791, 0.8999618524, 0.9318532082, 0.4, // Bottom left pixel + 0.6176699474, 0.805600061, 0.5565117876, 0.2}; // Bottom right pixel + + for (PNGSample& png_sample : png_samples) { + if (png_sample.color_space == "sRGB") { + png_sample.expected_pixels = png_sample.is_transparent + ? source_pixels_transparent_srgb + : source_pixels_opaque_srgb; + } else if (png_sample.color_space == "AdobeRGB") { + png_sample.expected_pixels = png_sample.is_transparent + ? source_pixels_transparent_adobe_rgb + : source_pixels_opaque_adobe_rgb; + } else if (png_sample.color_space == "DisplayP3") { + png_sample.expected_pixels = png_sample.is_transparent + ? source_pixels_transparent_p3 + : source_pixels_opaque_p3; + } else if (png_sample.color_space == "e-sRGB") { + png_sample.expected_pixels = png_sample.is_transparent + ? source_pixels_transparent_e_srgb + : source_pixels_opaque_e_srgb; + } else if (png_sample.color_space == "ProPhoto") { + png_sample.expected_pixels = png_sample.is_transparent + ? source_pixels_transparent_prophoto + : source_pixels_opaque_prophoto; + } else if (png_sample.color_space == "Rec2020") { + png_sample.expected_pixels = png_sample.is_transparent + ? source_pixels_transparent_rec2020 + : source_pixels_opaque_rec2020; + } else { + NOTREACHED(); + } + } +} + +static std::vector<PNGSample> GetPNGSamplesInfo(bool include_8bit_pngs) { + std::vector<PNGSample> png_samples; + std::vector<String> interlace_status = {"", "_interlaced"}; + // TODO(zakerinasab) https://crbug.com/874939: + // e-sRGB decodes fine to 8888, but fails to decode to F16, hence not tested. + std::vector<String> color_spaces = {"sRGB", "AdobeRGB", "DisplayP3", + "ProPhoto", "Rec2020"}; + std::vector<String> alpha_status = {"_opaque", "_transparent"}; + + for (String color_space : color_spaces) { + for (String alpha : alpha_status) { + PNGSample png_sample; + png_sample.filename.append("_"); + png_sample.filename.append(color_space); + png_sample.filename.append(alpha); + png_sample.filename.append(".png"); + png_sample.color_space = color_space; + png_sample.is_transparent = (alpha == "_transparent"); + + for (String interlace : interlace_status) { + PNGSample high_bit_depth_sample(png_sample); + high_bit_depth_sample.filename.insert(interlace, 0); + high_bit_depth_sample.filename.insert("2x2_16bit", 0); + high_bit_depth_sample.is_high_bit_depth = true; + png_samples.push_back(high_bit_depth_sample); + } + if (include_8bit_pngs) { + PNGSample regular_bit_depth_sample(png_sample); + regular_bit_depth_sample.filename.insert("2x2_8bit", 0); + regular_bit_depth_sample.is_high_bit_depth = false; + png_samples.push_back(regular_bit_depth_sample); + } + } + } + + return png_samples; +} + +TEST(StaticPNGTests, DecodeHighBitDepthPngToHalfFloat) { + const bool include_8bit_pngs = false; + std::vector<PNGSample> png_samples = GetPNGSamplesInfo(include_8bit_pngs); + FillPNGSamplesSourcePixels(png_samples); + String path = "/images/resources/png-16bit/"; + for (PNGSample& png_sample : png_samples) { + String full_path = path; + full_path.append(png_sample.filename); + png_sample.png_contents = ReadFile(full_path.Ascii().data()); + auto decoder = Create16BitPNGDecoder(); + TestHighBitDepthPNGDecoding(png_sample, decoder.get()); + } +} + +TEST(StaticPNGTests, ImageIsHighBitDepth) { + const bool include_8bit_pngs = true; + std::vector<PNGSample> png_samples = GetPNGSamplesInfo(include_8bit_pngs); + IntSize size(2, 2); + + String path = "/images/resources/png-16bit/"; + for (PNGSample& png_sample : png_samples) { + String full_path = path; + full_path.append(png_sample.filename); + png_sample.png_contents = ReadFile(full_path.Ascii().data()); + ASSERT_TRUE(png_sample.png_contents.get()); + + std::unique_ptr<ImageDecoder> decoders[] = {CreatePNGDecoder(), + Create16BitPNGDecoder()}; + for (auto& decoder : decoders) { + decoder->SetData(png_sample.png_contents.get(), true); + ASSERT_TRUE(decoder->IsSizeAvailable()); + ASSERT_TRUE(decoder->IsDecodedSizeAvailable()); + ASSERT_EQ(size, decoder->Size()); + ASSERT_EQ(size, decoder->DecodedSize()); + ASSERT_EQ(png_sample.is_high_bit_depth, decoder->ImageIsHighBitDepth()); + } + } +} + TEST(PNGTests, VerifyFrameCompleteBehavior) { struct { const char* name; @@ -1071,14 +1325,15 @@ auto decoder = CreatePNGDecoderWithPngData("/images/resources/crbug807324.png"); - // An update to libpng (without using the libpng-provided workaround) resulted - // in truncating this image. It has no transparency, so no pixel should be - // transparent. + // An update to libpng (without using the libpng-provided workaround) + // resulted in truncating this image. It has no transparency, so no pixel + // should be transparent. auto* frame = decoder->DecodeFrameBufferAtIndex(0); auto size = decoder->Size(); - for (int i = 0; i < size.Width(); ++i) - for (int j = 0; j < size.Height(); ++j) { - ASSERT_NE(SK_ColorTRANSPARENT, *frame->GetAddr(i, j)); + for (int i = 0; i < size.Width(); ++i) { + for (int j = 0; j < size.Height(); ++j) { + ASSERT_NE(SK_ColorTRANSPARENT, *frame->GetAddr(i, j)); + } } }
diff --git a/third_party/blink/renderer/platform/image-decoders/png/png_image_reader.cc b/third_party/blink/renderer/platform/image-decoders/png/png_image_reader.cc index a0b617fb..fe55f76 100644 --- a/third_party/blink/renderer/platform/image-decoders/png/png_image_reader.cc +++ b/third_party/blink/renderer/platform/image-decoders/png/png_image_reader.cc
@@ -543,8 +543,14 @@ fctl_needs_dat_chunk_ = false; if (ignore_animation_) is_animated_ = false; + // SetSize() requires bit depth information to correctly fallback to 8888 + // decoding if there is not enough memory to decode to f16 pixel format. + // SetBitDepth() requires repition count to correctly fallback to 8888 + // decoding for multi-frame APNGs (https://crbug.com/874057). Therefore, + // the order of the next three calls matters. if (!is_animated_ || 1 == reported_frame_count_) decoder_->SetRepetitionCount(kAnimationNone); + decoder_->SetBitDepth(); if (!decoder_->SetSize(width_, height_)) return false; decoder_->SetColorSpace();
diff --git a/third_party/blink/renderer/platform/loader/fetch/raw_resource.cc b/third_party/blink/renderer/platform/loader/fetch/raw_resource.cc index d43122fc6..71f36d3 100644 --- a/third_party/blink/renderer/platform/loader/fetch/raw_resource.cc +++ b/third_party/blink/renderer/platform/loader/fetch/raw_resource.cc
@@ -194,7 +194,8 @@ c->RedirectBlocked(); } -SourceKeyedCachedMetadataHandler* RawResource::CacheHandler() { +SourceKeyedCachedMetadataHandler* RawResource::InlineScriptCacheHandler() { + DCHECK_EQ(kMainResource, GetType()); return static_cast<SourceKeyedCachedMetadataHandler*>( Resource::CacheHandler()); } @@ -227,16 +228,24 @@ CachedMetadataHandler* RawResource::CreateCachedMetadataHandler( std::unique_ptr<CachedMetadataSender> send_callback) { - return new SourceKeyedCachedMetadataHandler(Encoding(), - std::move(send_callback)); + // If this is the document resource, create a cache handler that can handle + // multiple inline scripts. + if (GetType() == kMainResource) { + return new SourceKeyedCachedMetadataHandler(Encoding(), + std::move(send_callback)); + } + return Resource::CreateCachedMetadataHandler(std::move(send_callback)); } void RawResource::SetSerializedCachedMetadata(const char* data, size_t size) { Resource::SetSerializedCachedMetadata(data, size); - SourceKeyedCachedMetadataHandler* cache_handler = CacheHandler(); - if (cache_handler) { - cache_handler->SetSerializedCachedMetadata(data, size); + if (GetType() == kMainResource) { + SourceKeyedCachedMetadataHandler* cache_handler = + InlineScriptCacheHandler(); + if (cache_handler) { + cache_handler->SetSerializedCachedMetadata(data, size); + } } ResourceClientWalker<RawResourceClient> w(Clients());
diff --git a/third_party/blink/renderer/platform/loader/fetch/raw_resource.h b/third_party/blink/renderer/platform/loader/fetch/raw_resource.h index 950e634..88a5f01 100644 --- a/third_party/blink/renderer/platform/loader/fetch/raw_resource.h +++ b/third_party/blink/renderer/platform/loader/fetch/raw_resource.h
@@ -90,8 +90,9 @@ // Used for code caching of scripts with source code inline in the HTML. // Returns a cache handler which can store multiple cache metadata entries, - // keyed by the source code of the script. - SourceKeyedCachedMetadataHandler* CacheHandler(); + // keyed by the source code of the script. This is valid only if type is + // kMainResource. + SourceKeyedCachedMetadataHandler* InlineScriptCacheHandler(); scoped_refptr<BlobDataHandle> DownloadedBlob() const { return downloaded_blob_;
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index a96e2bb8..e732d04 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -843,10 +843,6 @@ name: "OrientationEvent", }, { - name: "OriginPolicy", - status: "test", - }, - { name: "OriginTrials", status: "stable", }, @@ -946,6 +942,10 @@ status: "experimental", }, { + name: "Portals", + status: "test", + }, + { name: "PostMessageOptions", status: "experimental", },
diff --git a/third_party/blink/tools/audit_non_blink_usage.py b/third_party/blink/tools/audit_non_blink_usage.py index 1c0fe38..7b7df05 100755 --- a/third_party/blink/tools/audit_non_blink_usage.py +++ b/third_party/blink/tools/audit_non_blink_usage.py
@@ -260,9 +260,6 @@ # Blink uses UKM for logging e.g. always-on leak detection (crbug/757374) 'ukm::.+', - - # WebRTC classes - 'webrtc::.+', ], 'disallowed': ['.+'], }, @@ -395,6 +392,16 @@ ], 'allowed': ['crypto::.+'], }, + { + 'paths': [ + 'third_party/blink/renderer/modules/peerconnection', + 'third_party/blink/renderer/bindings/modules/v8/serialization', + ], + 'allowed': [ + 'webrtc::.+', + 'rtc::.+', + ] + } ]
diff --git a/tools/binary_size/libsupersize/apkanalyzer.py b/tools/binary_size/libsupersize/apkanalyzer.py index 1efc52f..3dac7ce 100644 --- a/tools/binary_size/libsupersize/apkanalyzer.py +++ b/tools/binary_size/libsupersize/apkanalyzer.py
@@ -111,9 +111,11 @@ else: # Sibling or higher nodes break - assert total_child_size <= size, ( - 'Child node total size exceeded parent node total size') - node_size = size - total_child_size + # Disabled for perf bots: https://crbug.com/874956 + # TODO(wnwen): Investigate reason + #assert total_child_size <= size, ( + # 'Child node total size exceeded parent node total size') + node_size = max(0, size - total_child_size) nodes.append((name, node_size)) return next_idx, size
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index df52ce48..7e3f777 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -51,6 +51,14 @@ 'Cast Android (dbg)': 'android_cast_debug_static_bot', 'Deterministic Android': 'android_without_codecs_release_bot_minimal_symbols', 'Deterministic Android (dbg)': 'android_debug_bot', + + 'android-cronet-arm-dbg': 'android_cronet_debug_static_bot_arm_no_neon', + 'android-cronet-arm-rel': 'android_cronet_release_bot_minimal_symbols_arm_no_neon', + 'android-cronet-arm64-dbg': 'android_cronet_debug_static_bot_arm64', + 'android-cronet-arm64-rel': 'android_cronet_release_bot_minimal_symbols_arm64', + 'android-cronet-asan-arm-rel': 'android_cronet_release_bot_minimal_symbols_arm_no_neon_clang_asan', + 'android-cronet-x86-dbg': 'android_cronet_debug_static_bot_x86', + 'android-cronet-x86-rel': 'android_cronet_release_bot_minimal_symbols_x86', 'android-kitkat-arm-rel': 'android_release_bot_minimal_symbols', 'android-marshmallow-arm64-rel': 'android_release_bot_minimal_symbols_arm64', },
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 1080cd3..65c7164 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -3663,6 +3663,159 @@ <int value="8" label="Unknown or unhandler error"/> </enum> +<enum name="BluetoothSocketServiceHash"> + <summary> + 31-bit hash of the service UUID. Values here are populated from + https://www.bluetooth.com/specifications/assigned-numbers/service-discovery + </summary> + <int value="27577045" + label="SIM_Access; 0000112d-0000-1000-8000-00805f9b34fb"/> + <int value="46048502" + label="VideoSink; 00001304-0000-1000-8000-00805f9b34fb"/> + <int value="53242880" + label="3D Glasses; 00001138-0000-1000-8000-00805f9b34fb"/> + <int value="80025460" + label="AdvancedAudioDistribution; 0000110d-0000-1000-8000-00805f9b34fb"/> + <int value="80662886" + label="A/V_RemoteControlTarget; 0000110c-0000-1000-8000-00805f9b34fb"/> + <int value="89015451" + label="HDP Source; 00001401-0000-1000-8000-00805f9b34fb"/> + <int value="93024408" + label="ReferencePrinting; 00001119-0000-1000-8000-00805f9b34fb"/> + <int value="134662076" label="GN; 00001117-0000-1000-8000-00805f9b34fb"/> + <int value="153517886" + label="DirectPrintingReferenceObjectsService; + 00001120-0000-1000-8000-00805f9b34fb"/> + <int value="164698689" + label="DirectPrinting; 00001118-0000-1000-8000-00805f9b34fb"/> + <int value="181138738" label="WAP; 00001113-0000-1000-8000-00805f9b34fb"/> + <int value="191537385" + label="BasicPrinting; 00001122-0000-1000-8000-00805f9b34fb"/> + <int value="219461847" + label="Basic Imaging Profile; 0000111a-0000-1000-8000-00805f9b34fb"/> + <int value="223205883" + label="HCR_Scan; 00001127-0000-1000-8000-00805f9b34fb"/> + <int value="230869022" + label="ESDP_UPNP_IP_LAP; 00001301-0000-1000-8000-00805f9b34fb"/> + <int value="237750726" + label="AudioSource; 0000110a-0000-1000-8000-00805f9b34fb"/> + <int value="270998158" + label="OBEXFileTransfer; 00001106-0000-1000-8000-00805f9b34fb"/> + <int value="308706592" + label="Handsfree; 0000111e-0000-1000-8000-00805f9b34fb"/> + <int value="312472359" + label="ESDP_UPNP_L2CAP; 00001302-0000-1000-8000-00805f9b34fb"/> + <int value="325643766" + label="CTN Notification Service; 0000113d-0000-1000-8000-00805f9b34fb"/> + <int value="414065238" + label="Headset - HS; 00001131-0000-1000-8000-00805f9b34fb"/> + <int value="414260640" + label="UPNP_IP_Service; 00001206-0000-1000-8000-00805f9b34fb"/> + <int value="474133479" + label="Message Access Server; 00001132-0000-1000-8000-00805f9b34fb"/> + <int value="481017904" + label="GenericNetworking; 00001201-0000-1000-8000-00805f9b34fb"/> + <int value="488312511" + label="Phonebook Access - PCE; 0000112e-0000-1000-8000-00805f9b34fb"/> + <int value="556074802" + label="3D Display; 00001137-0000-1000-8000-00805f9b34fb"/> + <int value="559272304" + label="GenericFileTransfer; 00001202-0000-1000-8000-00805f9b34fb"/> + <int value="575067238" + label="AudioSink; 0000110b-0000-1000-8000-00805f9b34fb"/> + <int value="579644444" + label="PnPInformation; 00001200-0000-1000-8000-00805f9b34fb"/> + <int value="618213861" + label="HCR_Print; 00001126-0000-1000-8000-00805f9b34fb"/> + <int value="687640090" + label="HardcopyCableReplacement; 00001125-0000-1000-8000-00805f9b34fb"/> + <int value="690920522" + label="HumanInterfaceDeviceService; + 00001124-0000-1000-8000-00805f9b34fb"/> + <int value="726709874" + label="MPS SC UUID; 0000113b-0000-1000-8000-00805f9b34fb"/> + <int value="772096015" label="GNSS; 00001135-0000-1000-8000-00805f9b34fb"/> + <int value="788291396" + label="ImagingResponder; 0000111b-0000-1000-8000-00805f9b34fb"/> + <int value="826986046" + label="GenericAudio; 00001203-0000-1000-8000-00805f9b34fb"/> + <int value="917447240" + label="GenericTelephony; 00001204-0000-1000-8000-00805f9b34fb"/> + <int value="932610720" + label="HDP Sink; 00001402-0000-1000-8000-00805f9b34fb"/> + <int value="1048137004" + label="Common_ISDN_Access; 00001128-0000-1000-8000-00805f9b34fb"/> + <int value="1089394723" + label="ReflectedUI; 00001121-0000-1000-8000-00805f9b34fb"/> + <int value="1173742133" + label="Phonebook Access; 00001130-0000-1000-8000-00805f9b34fb"/> + <int value="1185226354" + label="ImagingReferencedObjects; 0000111d-0000-1000-8000-00805f9b34fb"/> + <int value="1269421948" label="NAP; 00001116-0000-1000-8000-00805f9b34fb"/> + <int value="1297730173" + label="PrintingStatus; 00001123-0000-1000-8000-00805f9b34fb"/> + <int value="1322541006" + label="CTN Access Service; 0000113c-0000-1000-8000-00805f9b34fb"/> + <int value="1346822007" + label="A/V_RemoteControl; 0000110e-0000-1000-8000-00805f9b34fb"/> + <int value="1353247390" + label="IrMCSync; 00001104-0000-1000-8000-00805f9b34fb"/> + <int value="1391113544" + label="Intercom; 00001110-0000-1000-8000-00805f9b34fb"/> + <int value="1406818563" + label="MPS Profile UUID; 0000113a-0000-1000-8000-00805f9b34fb"/> + <int value="1416242305" + label="3D Synchronization; 00001139-0000-1000-8000-00805f9b34fb"/> + <int value="1539513745" + label="CTN Profile; 0000113e-0000-1000-8000-00805f9b34fb"/> + <int value="1559400847" + label="Phonebook Access - PSE; 0000112f-0000-1000-8000-00805f9b34fb"/> + <int value="1563279259" + label="GNSS_Server; 00001136-0000-1000-8000-00805f9b34fb"/> + <int value="1564925248" + label="LANAccessUsingPPP; 00001102-0000-1000-8000-00805f9b34fb"/> + <int value="1603721693" + label="ESDP_UPNP_IP_PAN; 00001300-0000-1000-8000-00805f9b34fb"/> + <int value="1608206008" + label="A/V_RemoteControlController; + 0000110f-0000-1000-8000-00805f9b34fb"/> + <int value="1608308139" + label="UPNP_Service; 00001205-0000-1000-8000-00805f9b34fb"/> + <int value="1621920090" + label="ImagingAutomaticArchive; 0000111c-0000-1000-8000-00805f9b34fb"/> + <int value="1642311038" + label="HandsfreeAudioGateway; 0000111f-0000-1000-8000-00805f9b34fb"/> + <int value="1665040985" + label="Message Access Profile; 00001134-0000-1000-8000-00805f9b34fb"/> + <int value="1679985708" + label="SerialPort; 00001101-0000-1000-8000-00805f9b34fb"/> + <int value="1684180024" + label="Headset - Audio Gateway (AG); + 00001112-0000-1000-8000-00805f9b34fb"/> + <int value="1686752071" + label="WAP_CLIENT; 00001114-0000-1000-8000-00805f9b34fb"/> + <int value="1692867207" + label="IrMCSyncCommand; 00001107-0000-1000-8000-00805f9b34fb"/> + <int value="1857661865" label="HDP; 00001400-0000-1000-8000-00805f9b34fb"/> + <int value="1914606342" + label="VideoSource; 00001303-0000-1000-8000-00805f9b34fb"/> + <int value="1917084049" label="PANU; 00001115-0000-1000-8000-00805f9b34fb"/> + <int value="1923026611" + label="OBEXObjectPush; 00001105-0000-1000-8000-00805f9b34fb"/> + <int value="1931905004" + label="Message Notification Server; + 00001133-0000-1000-8000-00805f9b34fb"/> + <int value="1979370118" + label="DialupNetworking; 00001103-0000-1000-8000-00805f9b34fb"/> + <int value="2002893898" + label="Headset; 00001108-0000-1000-8000-00805f9b34fb"/> + <int value="2035822117" label="Fax; 00001111-0000-1000-8000-00805f9b34fb"/> + <int value="2039617417" + label="VideoDistribution; 00001305-0000-1000-8000-00805f9b34fb"/> + <int value="2060171182" + label="CordlessTelephony; 00001109-0000-1000-8000-00805f9b34fb"/> +</enum> + <enum name="BluetoothStatus"> <int value="0" label="Disabled"/> <int value="1" label="Enabled"/> @@ -28857,6 +29010,7 @@ <int value="217455219" label="SyncStandaloneTransport:enabled"/> <int value="218890378" label="ManualSaving:disabled"/> <int value="219117936" label="AllowReaderForAccessibility:enabled"/> + <int value="219682005" label="AutoplaySoundSettings:disabled"/> <int value="222184258" label="AutofillEnforceMinRequiredFieldsForHeuristics:disabled"/> <int value="223662457" label="BackgroundLoadingForDownloads:enabled"/> @@ -29547,6 +29701,7 @@ <int value="1612446645" label="enable-weak-memorycache"/> <int value="1612871297" label="WebPayments:disabled"/> <int value="1612974229" label="allow-insecure-localhost"/> + <int value="1614528057" label="AutoplaySoundSettings:enabled"/> <int value="1614596813" label="CloseButtonsInactiveTabs:disabled"/> <int value="1615988672" label="GrantNotificationsToDSE:enabled"/> <int value="1617187093" label="enable-improved-a2hs"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 709a767..e4c7e87 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -27691,6 +27691,42 @@ </summary> </histogram> +<histogram name="Extensions.BluetoothSocket.Connect.Service" + enum="BluetoothSocketServiceHash" expires_after="M72"> + <owner>ortuno@chromium.org</owner> + <owner>reillyg@chromium.org</owner> + <summary> + Records the UUID of the service to which a Chrome App opens a socket + connection. The recorded value is a 31-bit hash of the UUID. These results + will help us better understand the uses of the API and make changes + according to developers' behavior. + </summary> +</histogram> + +<histogram name="Extensions.BluetoothSocket.ListenL2CAP.Service" + enum="BluetoothSocketServiceHash" expires_after="M72"> + <owner>ortuno@chromium.org</owner> + <owner>reillyg@chromium.org</owner> + <summary> + Records the UUID of a service created by a Chrome App listening for L2CAP + connections. The recorded value is a 31-bit hash of the UUID. These results + will help us better understand the uses of the API and make changes + according to developers' behavior. + </summary> +</histogram> + +<histogram name="Extensions.BluetoothSocket.ListenRFCOMM.Service" + enum="BluetoothSocketServiceHash" expires_after="M72"> + <owner>ortuno@chromium.org</owner> + <owner>reillyg@chromium.org</owner> + <summary> + Records the UUID of a service created by a Chrome App listening for RFCOMM + connections. The recorded value is a 31-bit hash of the UUID. These results + will help us better understand the uses of the API and make changes + according to developers' behavior. + </summary> +</histogram> + <histogram name="Extensions.BookmarkApp.GetAppForCurrentURLDuration" units="ms"> <owner>mgiuca@chromium.org</owner> <owner>ortuno@chromium.org</owner>
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config index d38ec837..468aa9d 100644 --- a/tools/perf/expectations.config +++ b/tools/perf/expectations.config
@@ -164,6 +164,8 @@ crbug.com/338838 [ All ] rendering.mobile/basic_stream [ Skip ] crbug.com/873013 [ Android_Webview ] rendering.mobile/yahoo_answers_mobile_2018 [ Skip ] crbug.com/873014 [ Android_Webview ] rendering.mobile/yahoo_answers_mobile_sync_scroll_2018 [ Skip ] +crbug.com/874935 [ Android_Webview ] rendering.mobile/yahoo_answers_mobile_2018 [ Skip ] +crbug.com/874935 [ Android_Webview ] rendering.mobile/yahoo_answers_mobile_sync_scroll_2018 [ Skip ] # Benchmark: rasterize_and_record_micro.top_25 crbug.com/764543 [ All ] rasterize_and_record_micro.top_25/file://static_top_25/wikipedia.html [ Skip ] @@ -180,6 +182,7 @@ # Benchmark: system_health.common_mobile crbug.com/714650 [ Android ] system_health.common_mobile/browse:news:globo [ Skip ] +crbug.com/787001 [ Android_Webview ] system_health.common_mobile/load:media:soundcloud [ Skip ] crbug.com/708300 [ Android ] system_health.common_mobile/browse:shopping:flipkart [ Skip ] crbug.com/738854 [ Nexus_5X ] system_health.common_mobile/load:tools:drive [ Skip ] crbug.com/738854 [ Android_Webview ] system_health.common_mobile/load:tools:drive [ Skip ]
diff --git a/ui/accessibility/platform/ax_platform_node_auralinux.cc b/ui/accessibility/platform/ax_platform_node_auralinux.cc index ce8dbda..ec91450 100644 --- a/ui/accessibility/platform/ax_platform_node_auralinux.cc +++ b/ui/accessibility/platform/ax_platform_node_auralinux.cc
@@ -185,8 +185,12 @@ #if defined(ATK_216) constexpr AtkRole kStaticRole = ATK_ROLE_STATIC; +constexpr AtkRole kSubscriptRole = ATK_ROLE_SUBSCRIPT; +constexpr AtkRole kSuperscriptRole = ATK_ROLE_SUPERSCRIPT; #else constexpr AtkRole kStaticRole = ATK_ROLE_TEXT; +constexpr AtkRole kSubscriptRole = ATK_ROLE_TEXT; +constexpr AtkRole kSuperscriptRole = ATK_ROLE_TEXT; #endif #if defined(ATK_226) @@ -982,6 +986,8 @@ case ax::mojom::Role::kAnchor: return ATK_ROLE_LINK; case ax::mojom::Role::kAnnotation: + // TODO(accessibility) Panels are generally for containers of widgets. + // This should probably be a section (if a container) or static if text. return ATK_ROLE_PANEL; case ax::mojom::Role::kApplication: // Only use ATK_ROLE_APPLICATION for elements with no parent, since it @@ -1014,7 +1020,7 @@ case ax::mojom::Role::kSwitch: return ATK_ROLE_TOGGLE_BUTTON; case ax::mojom::Role::kColorWell: - return ATK_ROLE_COLOR_CHOOSER; + return ATK_ROLE_PUSH_BUTTON; case ax::mojom::Role::kColumn: return ATK_ROLE_UNKNOWN; case ax::mojom::Role::kColumnHeader: @@ -1026,9 +1032,9 @@ case ax::mojom::Role::kComplementary: return ATK_ROLE_LANDMARK; case ax::mojom::Role::kContentDeletion: - return ATK_ROLE_PANEL; // TODO(accessibility) text attribute diff:del. case ax::mojom::Role::kContentInsertion: - return ATK_ROLE_PANEL; // TODO(accessibility) text attribute diff:ins. + // TODO(accessibility) https://github.com/w3c/html-aam/issues/141 + return ATK_ROLE_SECTION; case ax::mojom::Role::kContentInfo: return ATK_ROLE_LANDMARK; case ax::mojom::Role::kDate: @@ -1101,13 +1107,17 @@ case ax::mojom::Role::kDocument: return ATK_ROLE_DOCUMENT_WEB; case ax::mojom::Role::kEmbeddedObject: - return ATK_ROLE_PANEL; + return ATK_ROLE_EMBEDDED; case ax::mojom::Role::kForm: - return ATK_ROLE_FORM; // Spec says ATK_ROLE_LANDMARK, checking. + // TODO(accessibility) Forms which lack an accessible name are no longer + // exposed as forms. http://crbug.com/874384. Forms which have accessible + // names should be exposed as ATK_ROLE_LANDMARK according to Core AAM. + return ATK_ROLE_FORM; case ax::mojom::Role::kFigure: case ax::mojom::Role::kFeed: - case ax::mojom::Role::kGenericContainer: return ATK_ROLE_PANEL; + case ax::mojom::Role::kGenericContainer: + return ATK_ROLE_SECTION; case ax::mojom::Role::kGraphicsDocument: return ATK_ROLE_DOCUMENT_WEB; case ax::mojom::Role::kGraphicsObject: @@ -1122,7 +1132,7 @@ return ATK_ROLE_HEADING; case ax::mojom::Role::kIframe: case ax::mojom::Role::kIframePresentational: - return ATK_ROLE_DOCUMENT_WEB; + return ATK_ROLE_INTERNAL_FRAME; case ax::mojom::Role::kIgnored: return ATK_ROLE_REDUNDANT_OBJECT; case ax::mojom::Role::kImage: @@ -1134,17 +1144,19 @@ case ax::mojom::Role::kLabelText: return ATK_ROLE_LABEL; case ax::mojom::Role::kLegend: - return ATK_ROLE_TEXT; + return ATK_ROLE_LABEL; // Layout table objects are treated the same as Role::kGenericContainer. case ax::mojom::Role::kLayoutTable: - return ATK_ROLE_PANEL; + return ATK_ROLE_SECTION; case ax::mojom::Role::kLayoutTableCell: - return ATK_ROLE_PANEL; + return ATK_ROLE_SECTION; case ax::mojom::Role::kLayoutTableColumn: - return ATK_ROLE_PANEL; + return ATK_ROLE_SECTION; case ax::mojom::Role::kLayoutTableRow: - return ATK_ROLE_PANEL; + return ATK_ROLE_SECTION; case ax::mojom::Role::kLineBreak: + // TODO(Accessibility) Having a separate accessible object for line breaks + // is inconsistent with other implementations. http://crbug.com/873144#c1. return ATK_ROLE_TEXT; case ax::mojom::Role::kLink: return ATK_ROLE_LINK; @@ -1157,6 +1169,8 @@ case ax::mojom::Role::kListBoxOption: return ATK_ROLE_LIST_ITEM; case ax::mojom::Role::kListMarker: + // TODO(Accessibility) Having a separate accessible object for the marker + // is inconsistent with other implementations. http://crbug.com/873144. return kStaticRole; case ax::mojom::Role::kListItem: return ATK_ROLE_LIST_ITEM; @@ -1165,7 +1179,7 @@ case ax::mojom::Role::kMain: return ATK_ROLE_LANDMARK; case ax::mojom::Role::kMark: - return ATK_ROLE_TEXT; + return kStaticRole; case ax::mojom::Role::kMath: return ATK_ROLE_MATH; case ax::mojom::Role::kMarquee: @@ -1187,7 +1201,7 @@ case ax::mojom::Role::kMenuListOption: return ATK_ROLE_MENU_ITEM; case ax::mojom::Role::kMeter: - return ATK_ROLE_PROGRESS_BAR; + return ATK_ROLE_LEVEL_BAR; case ax::mojom::Role::kNavigation: return ATK_ROLE_LANDMARK; case ax::mojom::Role::kNote: @@ -1197,10 +1211,15 @@ return ATK_ROLE_PANEL; case ax::mojom::Role::kParagraph: return ATK_ROLE_PARAGRAPH; - case ax::mojom::Role::kPopUpButton: + case ax::mojom::Role::kPopUpButton: { + std::string html_tag = + GetData().GetStringAttribute(ax::mojom::StringAttribute::kHtmlTag); + if (html_tag == "select") + return ATK_ROLE_COMBO_BOX; return ATK_ROLE_PUSH_BUTTON; + } case ax::mojom::Role::kPre: - return ATK_ROLE_TEXT; + return ATK_ROLE_SECTION; case ax::mojom::Role::kProgressIndicator: return ATK_ROLE_PROGRESS_BAR; case ax::mojom::Role::kRadioButton: @@ -1226,9 +1245,9 @@ case ax::mojom::Role::kRow: return ATK_ROLE_TABLE_ROW; case ax::mojom::Role::kRowHeader: - return ATK_ROLE_TABLE_ROW_HEADER; // ATK_ROLE_ROW_HEADER also exists. + return ATK_ROLE_ROW_HEADER; case ax::mojom::Role::kRuby: - return ATK_ROLE_TEXT; + return kStaticRole; case ax::mojom::Role::kScrollBar: return ATK_ROLE_SCROLL_BAR; case ax::mojom::Role::kSearch: @@ -1240,29 +1259,46 @@ return ATK_ROLE_SPIN_BUTTON; case ax::mojom::Role::kSplitter: return ATK_ROLE_SEPARATOR; - case ax::mojom::Role::kStaticText: + case ax::mojom::Role::kStaticText: { + switch (static_cast<ax::mojom::TextPosition>( + GetIntAttribute(ax::mojom::IntAttribute::kTextPosition))) { + case ax::mojom::TextPosition::kSubscript: + return kSubscriptRole; + case ax::mojom::TextPosition::kSuperscript: + return kSuperscriptRole; + default: + break; + } return ATK_ROLE_TEXT; + } case ax::mojom::Role::kStatus: return ATK_ROLE_STATUSBAR; case ax::mojom::Role::kSvgRoot: - return ATK_ROLE_IMAGE; + return ATK_ROLE_DOCUMENT_FRAME; case ax::mojom::Role::kTab: return ATK_ROLE_PAGE_TAB; case ax::mojom::Role::kTable: return ATK_ROLE_TABLE; case ax::mojom::Role::kTableHeaderContainer: + // TODO(accessibility) This mapping is correct, but it doesn't seem to be + // used. We don't necessarily want to always expose these containers, but + // we must do so if they are focusable. http://crbug.com/874043 return ATK_ROLE_PANEL; case ax::mojom::Role::kTabList: return ATK_ROLE_PAGE_TAB_LIST; case ax::mojom::Role::kTabPanel: return ATK_ROLE_SCROLL_PANE; case ax::mojom::Role::kTerm: + // TODO(accessibility) This mapping should also be applied to the dfn + // element. http://crbug.com/874411 return ATK_ROLE_DESCRIPTION_TERM; case ax::mojom::Role::kTitleBar: return ATK_ROLE_TITLE_BAR; case ax::mojom::Role::kInlineTextBox: case ax::mojom::Role::kTextField: case ax::mojom::Role::kSearchBox: + if (GetData().HasState(ax::mojom::State::kProtected)) + return ATK_ROLE_PASSWORD_TEXT; if (!GetStringAttribute(ax::mojom::StringAttribute::kAutoComplete) .empty() || IsFocusedInputWithSuggestions()) { @@ -1273,7 +1309,7 @@ return ATK_ROLE_COMBO_BOX; case ax::mojom::Role::kAbbr: case ax::mojom::Role::kTime: - return ATK_ROLE_TEXT; + return kStaticRole; case ax::mojom::Role::kTimer: return ATK_ROLE_TIMER; case ax::mojom::Role::kToggleButton: @@ -1300,8 +1336,9 @@ return ATK_ROLE_FRAME; case ax::mojom::Role::kClient: case ax::mojom::Role::kDesktop: - case ax::mojom::Role::kFigcaption: return ATK_ROLE_PANEL; + case ax::mojom::Role::kFigcaption: + return ATK_ROLE_CAPTION; case ax::mojom::Role::kFooter: return ATK_ROLE_FOOTER; case ax::mojom::Role::kKeyboard: @@ -1318,8 +1355,10 @@ atk_state_set_add_state(atk_state_set, ATK_STATE_EXPANDABLE); if (data.HasState(ax::mojom::State::kDefault)) atk_state_set_add_state(atk_state_set, ATK_STATE_DEFAULT); - if (data.HasState(ax::mojom::State::kEditable)) + if (data.HasState(ax::mojom::State::kEditable) && + data.GetRestriction() != ax::mojom::Restriction::kReadOnly) { atk_state_set_add_state(atk_state_set, ATK_STATE_EDITABLE); + } if (data.HasState(ax::mojom::State::kExpanded)) { atk_state_set_add_state(atk_state_set, ATK_STATE_EXPANDABLE); atk_state_set_add_state(atk_state_set, ATK_STATE_EXPANDED); @@ -1464,6 +1503,13 @@ states->AppendString(atk_state_type_get_name(state_type)); } dict->Set("states", std::move(states)); + + AtkAttributeSet* attributes = atk_object_get_attributes(atk_object_); + for (AtkAttributeSet* attr = attributes; attr; attr = attr->next) { + AtkAttribute* attribute = static_cast<AtkAttribute*>(attr->data); + dict->SetString(attribute->name, attribute->value); + } + atk_attribute_set_free(attributes); } gfx::NativeViewAccessible AXPlatformNodeAuraLinux::GetNativeViewAccessible() {
diff --git a/ui/ozone/platform/drm/BUILD.gn b/ui/ozone/platform/drm/BUILD.gn index 192df8e..3c2d50c 100644 --- a/ui/ozone/platform/drm/BUILD.gn +++ b/ui/ozone/platform/drm/BUILD.gn
@@ -60,10 +60,10 @@ "gpu/drm_window.h", "gpu/drm_window_proxy.cc", "gpu/drm_window_proxy.h", - "gpu/gbm_overlay_surface.cc", - "gpu/gbm_overlay_surface.h", "gpu/gbm_pixmap.cc", "gpu/gbm_pixmap.h", + "gpu/gbm_overlay_surface.cc", + "gpu/gbm_overlay_surface.h", "gpu/gbm_surface.cc", "gpu/gbm_surface.h", "gpu/gbm_surface_factory.cc", @@ -90,6 +90,8 @@ "gpu/page_flip_request.h", "gpu/proxy_helpers.cc", "gpu/proxy_helpers.h", + "gpu/drm_framebuffer.h", + "gpu/drm_framebuffer_generator.h", "gpu/screen_manager.cc", "gpu/screen_manager.h", "host/drm_cursor.cc", @@ -182,8 +184,10 @@ "gpu/hardware_display_plane_manager_unittest.cc", "gpu/mock_drm_device.cc", "gpu/mock_drm_device.h", - "gpu/mock_gbm_device.cc", - "gpu/mock_gbm_device.h", + "gpu/mock_dumb_buffer_generator.cc", + "gpu/mock_dumb_buffer_generator.h", + "gpu/mock_drm_framebuffer_generator.cc", + "gpu/mock_drm_framebuffer_generator.h", "gpu/proxy_helpers_unittest.cc", "gpu/screen_manager_unittest.cc", ]
diff --git a/ui/ozone/platform/drm/gpu/drm_framebuffer.cc b/ui/ozone/platform/drm/gpu/drm_framebuffer.cc index b632257..0109b28 100644 --- a/ui/ozone/platform/drm/gpu/drm_framebuffer.cc +++ b/ui/ozone/platform/drm/gpu/drm_framebuffer.cc
@@ -5,7 +5,6 @@ #include "ui/ozone/platform/drm/gpu/drm_framebuffer.h" #include "ui/ozone/common/linux/drm_util_linux.h" -#include "ui/ozone/common/linux/gbm_buffer.h" #include "ui/ozone/platform/drm/common/drm_util.h" #include "ui/ozone/platform/drm/gpu/drm_device.h" @@ -49,35 +48,6 @@ gfx::Size(params.width, params.height)); } -// static -scoped_refptr<DrmFramebuffer> DrmFramebuffer::AddFramebuffer( - scoped_refptr<DrmDevice> drm, - const GbmBuffer* buffer) { - gfx::Size size = buffer->GetSize(); - AddFramebufferParams params; - params.format = buffer->GetFormat(); - params.modifier = buffer->GetFormatModifier(); - params.width = size.width(); - params.height = size.height(); - params.num_planes = buffer->GetNumPlanes(); - for (size_t i = 0; i < params.num_planes; ++i) { - params.handles[i] = buffer->GetPlaneHandle(i); - params.strides[i] = buffer->GetPlaneStride(i); - params.offsets[i] = buffer->GetPlaneOffset(i); - } - - // AddFramebuffer2 only considers the modifiers if addfb_flags has - // DRM_MODE_FB_MODIFIERS set. We only set that when we've created - // a bo with modifiers, otherwise, we rely on the "no modifiers" - // behavior doing the right thing. - params.flags = 0; - if (drm->allow_addfb2_modifiers() && - params.modifier != DRM_FORMAT_MOD_INVALID) - params.flags |= DRM_MODE_FB_MODIFIERS; - - return AddFramebuffer(std::move(drm), params); -} - DrmFramebuffer::DrmFramebuffer(scoped_refptr<DrmDevice> drm_device, uint32_t framebuffer_id, uint32_t framebuffer_pixel_format,
diff --git a/ui/ozone/platform/drm/gpu/drm_framebuffer.h b/ui/ozone/platform/drm/gpu/drm_framebuffer.h index bb5e6e3..c089cb3 100644 --- a/ui/ozone/platform/drm/gpu/drm_framebuffer.h +++ b/ui/ozone/platform/drm/gpu/drm_framebuffer.h
@@ -15,7 +15,6 @@ namespace ui { class DrmDevice; -class GbmBuffer; // Abstraction for a DRM buffer that can be scanned-out of. class DrmFramebuffer : public base::RefCountedThreadSafe<DrmFramebuffer> { @@ -36,10 +35,6 @@ scoped_refptr<DrmDevice> drm_device, AddFramebufferParams params); - static scoped_refptr<DrmFramebuffer> AddFramebuffer( - scoped_refptr<DrmDevice> drm_device, - const GbmBuffer* buffer); - DrmFramebuffer(scoped_refptr<DrmDevice> drm_device, uint32_t framebuffer_id, uint32_t framebuffer_pixel_format,
diff --git a/ui/ozone/platform/drm/gpu/drm_framebuffer_generator.h b/ui/ozone/platform/drm/gpu/drm_framebuffer_generator.h new file mode 100644 index 0000000..04d8847 --- /dev/null +++ b/ui/ozone/platform/drm/gpu/drm_framebuffer_generator.h
@@ -0,0 +1,31 @@ +// 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 UI_OZONE_PLATFORM_DRM_GPU_SCANOUT_BUFFER_GENERATOR_H_ +#define UI_OZONE_PLATFORM_DRM_GPU_SCANOUT_BUFFER_GENERATOR_H_ + +#include <vector> + +#include "base/memory/scoped_refptr.h" +#include "ui/gfx/geometry/size.h" + +namespace ui { + +class DrmDevice; +class DrmFramebuffer; + +class DrmFramebufferGenerator { + public: + virtual ~DrmFramebufferGenerator() {} + + virtual scoped_refptr<DrmFramebuffer> Create( + const scoped_refptr<DrmDevice>& drm, + uint32_t format, + const std::vector<uint64_t>& modifiers, + const gfx::Size& size) = 0; +}; + +} // namespace ui + +#endif // UI_OZONE_PLATFORM_DRM_GPU_SCANOUT_BUFFER_GENERATOR_H_
diff --git a/ui/ozone/platform/drm/gpu/drm_overlay_validator.cc b/ui/ozone/platform/drm/gpu/drm_overlay_validator.cc index ea0947a..300aabe 100644 --- a/ui/ozone/platform/drm/gpu/drm_overlay_validator.cc +++ b/ui/ozone/platform/drm/gpu/drm_overlay_validator.cc
@@ -10,10 +10,10 @@ #include "ui/gfx/geometry/size_conversions.h" #include "ui/gfx/gpu_fence.h" #include "ui/ozone/common/linux/drm_util_linux.h" -#include "ui/ozone/common/linux/gbm_buffer.h" #include "ui/ozone/platform/drm/common/drm_util.h" #include "ui/ozone/platform/drm/gpu/drm_device.h" #include "ui/ozone/platform/drm/gpu/drm_framebuffer.h" +#include "ui/ozone/platform/drm/gpu/drm_framebuffer_generator.h" #include "ui/ozone/platform/drm/gpu/drm_window.h" #include "ui/ozone/platform/drm/gpu/hardware_display_controller.h" @@ -25,6 +25,7 @@ const scoped_refptr<DrmDevice>& drm_device, const gfx::Size& size, uint32_t format, + DrmFramebufferGenerator* buffer_generator, std::vector<scoped_refptr<DrmFramebuffer>>* reusable_buffers) { // Check if we can re-use existing buffers. for (const auto& buffer : *reusable_buffers) { @@ -34,24 +35,22 @@ } } - // TODO(dcastagna): use the right modifiers. - std::unique_ptr<GbmBuffer> buffer = - drm_device->gbm_device()->CreateBuffer(format, size, GBM_BO_USE_SCANOUT); - if (!buffer) - return nullptr; - + const std::vector<uint64_t> + modifiers; // TODO(dcastagna): use the right modifiers. scoped_refptr<DrmFramebuffer> drm_framebuffer = - DrmFramebuffer::AddFramebuffer(drm_device, buffer.get()); - if (!drm_framebuffer) - return nullptr; + buffer_generator->Create(drm_device, format, modifiers, size); + if (drm_framebuffer) + reusable_buffers->push_back(drm_framebuffer); - reusable_buffers->push_back(drm_framebuffer); return drm_framebuffer; } } // namespace -DrmOverlayValidator::DrmOverlayValidator(DrmWindow* window) : window_(window) {} +DrmOverlayValidator::DrmOverlayValidator( + DrmWindow* window, + DrmFramebufferGenerator* buffer_generator) + : window_(window), buffer_generator_(buffer_generator) {} DrmOverlayValidator::~DrmOverlayValidator() {} @@ -83,7 +82,8 @@ scoped_refptr<DrmFramebuffer> buffer = GetBufferForPageFlipTest( drm, params[i].buffer_size, - GetFourCCFormatFromBufferFormat(params[i].format), &reusable_buffers); + GetFourCCFormatFromBufferFormat(params[i].format), buffer_generator_, + &reusable_buffers); DrmOverlayPlane plane(buffer, params[i].plane_z_order, params[i].transform, params[i].display_rect, params[i].crop_rect,
diff --git a/ui/ozone/platform/drm/gpu/drm_overlay_validator.h b/ui/ozone/platform/drm/gpu/drm_overlay_validator.h index 5030650..1304559 100644 --- a/ui/ozone/platform/drm/gpu/drm_overlay_validator.h +++ b/ui/ozone/platform/drm/gpu/drm_overlay_validator.h
@@ -11,12 +11,14 @@ namespace ui { class DrmWindow; +class DrmFramebufferGenerator; struct OverlayCheck_Params; struct OverlayCheckReturn_Params; class DrmOverlayValidator { public: - DrmOverlayValidator(DrmWindow* window); + DrmOverlayValidator(DrmWindow* window, + DrmFramebufferGenerator* buffer_generator); ~DrmOverlayValidator(); // Tests if configurations |params| are compatible with |window_| and finds @@ -28,6 +30,7 @@ private: DrmWindow* window_; // Not owned. + DrmFramebufferGenerator* buffer_generator_; // Not owned. DISALLOW_COPY_AND_ASSIGN(DrmOverlayValidator); };
diff --git a/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc b/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc index c2a99d7..977207d 100644 --- a/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc +++ b/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc
@@ -15,16 +15,14 @@ #include "ui/gfx/gpu_fence.h" #include "ui/ozone/common/gpu/ozone_gpu_message_params.h" #include "ui/ozone/common/linux/drm_util_linux.h" -#include "ui/ozone/common/linux/gbm_buffer.h" #include "ui/ozone/platform/drm/common/drm_util.h" #include "ui/ozone/platform/drm/gpu/crtc_controller.h" #include "ui/ozone/platform/drm/gpu/drm_device_generator.h" #include "ui/ozone/platform/drm/gpu/drm_device_manager.h" -#include "ui/ozone/platform/drm/gpu/drm_framebuffer.h" #include "ui/ozone/platform/drm/gpu/drm_window.h" #include "ui/ozone/platform/drm/gpu/hardware_display_controller.h" #include "ui/ozone/platform/drm/gpu/mock_drm_device.h" -#include "ui/ozone/platform/drm/gpu/mock_gbm_device.h" +#include "ui/ozone/platform/drm/gpu/mock_drm_framebuffer_generator.h" #include "ui/ozone/platform/drm/gpu/screen_manager.h" namespace { @@ -64,16 +62,8 @@ void AddPlane(const ui::OverlayCheck_Params& params); scoped_refptr<ui::DrmFramebuffer> CreateBuffer() { - auto gbm_buffer = drm_->gbm_device()->CreateBuffer( - DRM_FORMAT_XRGB8888, primary_rect_.size(), GBM_BO_USE_SCANOUT); - return ui::DrmFramebuffer::AddFramebuffer(drm_, gbm_buffer.get()); - } - - scoped_refptr<ui::DrmFramebuffer> CreateOverlayBuffer(uint32_t format, - const gfx::Size& size) { - auto gbm_buffer = - drm_->gbm_device()->CreateBuffer(format, size, GBM_BO_USE_SCANOUT); - return ui::DrmFramebuffer::AddFramebuffer(drm_, gbm_buffer.get()); + return buffer_generator_->CreateWithModifier( + drm_, DRM_FORMAT_XRGB8888, DRM_FORMAT_MOD_NONE, primary_rect_.size()); } protected: @@ -89,7 +79,7 @@ std::unique_ptr<base::MessageLoop> message_loop_; scoped_refptr<ui::MockDrmDevice> drm_; - ui::MockGbmDevice* gbm_ = nullptr; + std::unique_ptr<ui::MockDrmFramebufferGenerator> buffer_generator_; std::unique_ptr<ui::ScreenManager> screen_manager_; std::unique_ptr<ui::DrmDeviceManager> drm_device_manager_; ui::DrmWindow* window_; @@ -111,16 +101,15 @@ last_swap_buffers_result_ = gfx::SwapResult::SWAP_FAILED; message_loop_.reset(new base::MessageLoopForUI); - auto gbm = std::make_unique<ui::MockGbmDevice>(); - gbm_ = gbm.get(); - drm_ = new ui::MockDrmDevice(std::move(gbm)); + drm_ = new ui::MockDrmDevice; CrtcState crtc_state = {.planes = { {.formats = {DRM_FORMAT_XRGB8888}}, }}; InitializeDrmState({crtc_state}); - screen_manager_.reset(new ui::ScreenManager()); + buffer_generator_.reset(new ui::MockDrmFramebufferGenerator()); + screen_manager_.reset(new ui::ScreenManager(buffer_generator_.get())); screen_manager_->AddDisplayController(drm_, kCrtcIdBase, kConnectorIdBase); screen_manager_->ConfigureDisplayController( drm_, kCrtcIdBase, kConnectorIdBase, gfx::Point(), kDefaultMode); @@ -129,12 +118,13 @@ std::unique_ptr<ui::DrmWindow> window(new ui::DrmWindow( kDefaultWidgetHandle, drm_device_manager_.get(), screen_manager_.get())); - window->Initialize(); + window->Initialize(buffer_generator_.get()); window->SetBounds( gfx::Rect(gfx::Size(kDefaultMode.hdisplay, kDefaultMode.vdisplay))); screen_manager_->AddWindow(kDefaultWidgetHandle, std::move(window)); window_ = screen_manager_->GetWindow(kDefaultWidgetHandle); - overlay_validator_.reset(new ui::DrmOverlayValidator(window_)); + overlay_validator_.reset( + new ui::DrmOverlayValidator(window_, buffer_generator_.get())); overlay_rect_ = gfx::Rect(0, 0, kDefaultMode.hdisplay / 2, kDefaultMode.vdisplay / 2); @@ -220,9 +210,9 @@ void DrmOverlayValidatorTest::AddPlane(const ui::OverlayCheck_Params& params) { scoped_refptr<ui::DrmDevice> drm = window_->GetController()->GetDrmDevice(); - - scoped_refptr<ui::DrmFramebuffer> drm_framebuffer = CreateOverlayBuffer( - ui::GetFourCCFormatFromBufferFormat(params.format), params.buffer_size); + scoped_refptr<ui::DrmFramebuffer> drm_framebuffer = buffer_generator_->Create( + drm, ui::GetFourCCFormatFromBufferFormat(params.format), {}, + params.buffer_size); plane_list_.push_back(ui::DrmOverlayPlane( std::move(drm_framebuffer), params.plane_z_order, params.transform, params.display_rect, params.crop_rect, true, nullptr)); @@ -479,7 +469,7 @@ TEST_F(DrmOverlayValidatorTest, RejectBufferAllocationFail) { // Buffer allocation for scanout might fail. // In that case we should reject the overlay candidate. - gbm_->set_allocation_failure(true); + buffer_generator_->set_allocation_failure(true); std::vector<ui::OverlayCheckReturn_Params> returns = overlay_validator_->TestPageFlip(overlay_params_,
diff --git a/ui/ozone/platform/drm/gpu/drm_thread.cc b/ui/ozone/platform/drm/gpu/drm_thread.cc index 3205de1..62567655 100644 --- a/ui/ozone/platform/drm/gpu/drm_thread.cc +++ b/ui/ozone/platform/drm/gpu/drm_thread.cc
@@ -22,6 +22,7 @@ #include "ui/ozone/platform/drm/gpu/drm_buffer.h" #include "ui/ozone/platform/drm/gpu/drm_device_generator.h" #include "ui/ozone/platform/drm/gpu/drm_device_manager.h" +#include "ui/ozone/platform/drm/gpu/drm_framebuffer_generator.h" #include "ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h" #include "ui/ozone/platform/drm/gpu/drm_window.h" #include "ui/ozone/platform/drm/gpu/drm_window_proxy.h" @@ -35,6 +36,34 @@ namespace { +scoped_refptr<DrmFramebuffer> AddFramebuffersForBuffer( + const scoped_refptr<DrmDevice>& drm, + GbmBuffer* buffer) { + gfx::Size size = buffer->GetSize(); + DrmFramebuffer::AddFramebufferParams params; + params.format = buffer->GetFormat(); + params.modifier = buffer->GetFormatModifier(); + params.width = size.width(); + params.height = size.height(); + params.num_planes = buffer->GetNumPlanes(); + for (size_t i = 0; i < params.num_planes; ++i) { + params.handles[i] = buffer->GetPlaneHandle(i); + params.strides[i] = buffer->GetPlaneStride(i); + params.offsets[i] = buffer->GetPlaneOffset(i); + } + + // AddFramebuffer2 only considers the modifiers if addfb_flags has + // DRM_MODE_FB_MODIFIERS set. We only set that when we've created + // a bo with modifiers, otherwise, we rely on the "no modifiers" + // behavior doing the right thing. + params.flags = 0; + if (drm->allow_addfb2_modifiers() && + params.modifier != DRM_FORMAT_MOD_INVALID) + params.flags |= DRM_MODE_FB_MODIFIERS; + + return DrmFramebuffer::AddFramebuffer(drm, params); +} + uint32_t BufferUsageToGbmFlags(gfx::BufferUsage usage) { switch (usage) { case gfx::BufferUsage::GPU_READ: @@ -77,7 +106,7 @@ scoped_refptr<DrmFramebuffer> framebuffer; if (flags & GBM_BO_USE_SCANOUT) { - framebuffer = DrmFramebuffer::AddFramebuffer(drm, buffer.get()); + framebuffer = AddFramebuffersForBuffer(drm, buffer.get()); if (!framebuffer) return; } @@ -86,6 +115,36 @@ *out_framebuffer = std::move(framebuffer); } +class GbmBufferGenerator : public DrmFramebufferGenerator { + public: + GbmBufferGenerator() {} + ~GbmBufferGenerator() override {} + + // DrmFramebufferGenerator: + scoped_refptr<DrmFramebuffer> Create(const scoped_refptr<DrmDevice>& drm, + uint32_t format, + const std::vector<uint64_t>& modifiers, + const gfx::Size& size) override { + std::unique_ptr<GbmBuffer> buffer; + + if (modifiers.size() > 0) { + buffer = drm->gbm_device()->CreateBufferWithModifiers( + format, size, GBM_BO_USE_SCANOUT, modifiers); + } else { + buffer = + drm->gbm_device()->CreateBuffer(format, size, GBM_BO_USE_SCANOUT); + } + + if (!buffer) + return nullptr; + + return AddFramebuffersForBuffer(drm, buffer.get()); + } + + protected: + DISALLOW_COPY_AND_ASSIGN(GbmBufferGenerator); +}; + class GbmDeviceGenerator : public DrmDeviceGenerator { public: GbmDeviceGenerator() {} @@ -134,7 +193,8 @@ void DrmThread::Init() { device_manager_.reset( new DrmDeviceManager(std::make_unique<GbmDeviceGenerator>())); - screen_manager_.reset(new ScreenManager()); + buffer_generator_.reset(new GbmBufferGenerator()); + screen_manager_.reset(new ScreenManager(buffer_generator_.get())); display_manager_.reset( new DrmGpuDisplayManager(screen_manager_.get(), device_manager_.get())); @@ -204,7 +264,7 @@ if (buffer->GetFlags() & GBM_BO_USE_SCANOUT) { // NB: This is not required to succeed; framebuffers are added for // imported buffers on a best effort basis. - framebuffer = DrmFramebuffer::AddFramebuffer(drm, buffer.get()); + framebuffer = AddFramebuffersForBuffer(drm, buffer.get()); } *out_buffer = std::move(buffer); @@ -268,7 +328,7 @@ void DrmThread::CreateWindow(gfx::AcceleratedWidget widget) { std::unique_ptr<DrmWindow> window( new DrmWindow(widget, device_manager_.get(), screen_manager_.get())); - window->Initialize(); + window->Initialize(buffer_generator_.get()); screen_manager_->AddWindow(widget, std::move(window)); }
diff --git a/ui/ozone/platform/drm/gpu/drm_thread.h b/ui/ozone/platform/drm/gpu/drm_thread.h index 79685b1..b1c954eb 100644 --- a/ui/ozone/platform/drm/gpu/drm_thread.h +++ b/ui/ozone/platform/drm/gpu/drm_thread.h
@@ -44,6 +44,7 @@ class DrmFramebuffer; class DrmGpuDisplayManager; class GbmBuffer; +class DrmFramebufferGenerator; class ScreenManager; struct DrmOverlayPlane; @@ -154,6 +155,7 @@ std::vector<DrmOverlayPlane> planes); std::unique_ptr<DrmDeviceManager> device_manager_; + std::unique_ptr<DrmFramebufferGenerator> buffer_generator_; std::unique_ptr<ScreenManager> screen_manager_; std::unique_ptr<DrmGpuDisplayManager> display_manager_;
diff --git a/ui/ozone/platform/drm/gpu/drm_window.cc b/ui/ozone/platform/drm/gpu/drm_window.cc index 04f31690..1c0dc3dc 100644 --- a/ui/ozone/platform/drm/gpu/drm_window.cc +++ b/ui/ozone/platform/drm/gpu/drm_window.cc
@@ -37,11 +37,12 @@ DrmWindow::~DrmWindow() { } -void DrmWindow::Initialize() { +void DrmWindow::Initialize(DrmFramebufferGenerator* buffer_generator) { TRACE_EVENT1("drm", "DrmWindow::Initialize", "widget", widget_); device_manager_->UpdateDrmDevice(widget_, nullptr); - overlay_validator_ = std::make_unique<DrmOverlayValidator>(this); + overlay_validator_ = + std::make_unique<DrmOverlayValidator>(this, buffer_generator); } void DrmWindow::Shutdown() {
diff --git a/ui/ozone/platform/drm/gpu/drm_window.h b/ui/ozone/platform/drm/gpu/drm_window.h index b44d416..236eefa0 100644 --- a/ui/ozone/platform/drm/gpu/drm_window.h +++ b/ui/ozone/platform/drm/gpu/drm_window.h
@@ -33,6 +33,7 @@ class HardwareDisplayController; struct OverlayCheck_Params; struct OverlayCheckReturn_Params; +class DrmFramebufferGenerator; class ScreenManager; // The GPU object representing a window. @@ -54,7 +55,7 @@ gfx::Rect bounds() const { return bounds_; } - void Initialize(); + void Initialize(DrmFramebufferGenerator* buffer_generator); void Shutdown();
diff --git a/ui/ozone/platform/drm/gpu/drm_window_unittest.cc b/ui/ozone/platform/drm/gpu/drm_window_unittest.cc index fdd4af7..fd5d379c 100644 --- a/ui/ozone/platform/drm/gpu/drm_window_unittest.cc +++ b/ui/ozone/platform/drm/gpu/drm_window_unittest.cc
@@ -21,13 +21,12 @@ #include "third_party/skia/include/core/SkSurface.h" #include "ui/gfx/gpu_fence.h" #include "ui/gfx/presentation_feedback.h" -#include "ui/ozone/common/linux/gbm_buffer.h" #include "ui/ozone/platform/drm/gpu/drm_device_generator.h" #include "ui/ozone/platform/drm/gpu/drm_device_manager.h" #include "ui/ozone/platform/drm/gpu/drm_framebuffer.h" #include "ui/ozone/platform/drm/gpu/hardware_display_controller.h" #include "ui/ozone/platform/drm/gpu/mock_drm_device.h" -#include "ui/ozone/platform/drm/gpu/mock_gbm_device.h" +#include "ui/ozone/platform/drm/gpu/mock_dumb_buffer_generator.h" #include "ui/ozone/platform/drm/gpu/screen_manager.h" #include "ui/ozone/public/surface_ozone_canvas.h" @@ -86,6 +85,7 @@ protected: std::unique_ptr<base::MessageLoop> message_loop_; scoped_refptr<ui::MockDrmDevice> drm_; + std::unique_ptr<ui::MockDumbBufferGenerator> buffer_generator_; std::unique_ptr<ui::ScreenManager> screen_manager_; std::unique_ptr<ui::DrmDeviceManager> drm_device_manager_; @@ -102,9 +102,9 @@ last_swap_buffers_result_ = gfx::SwapResult::SWAP_FAILED; message_loop_.reset(new base::MessageLoopForUI); - auto gbm_device = std::make_unique<ui::MockGbmDevice>(); - drm_ = new ui::MockDrmDevice(std::move(gbm_device)); - screen_manager_.reset(new ui::ScreenManager()); + drm_ = new ui::MockDrmDevice; + buffer_generator_.reset(new ui::MockDumbBufferGenerator()); + screen_manager_.reset(new ui::ScreenManager(buffer_generator_.get())); screen_manager_->AddDisplayController(drm_, kDefaultCrtc, kDefaultConnector); screen_manager_->ConfigureDisplayController( drm_, kDefaultCrtc, kDefaultConnector, gfx::Point(), kDefaultMode); @@ -113,7 +113,7 @@ std::unique_ptr<ui::DrmWindow> window(new ui::DrmWindow( kDefaultWidgetHandle, drm_device_manager_.get(), screen_manager_.get())); - window->Initialize(); + window->Initialize(buffer_generator_.get()); window->SetBounds( gfx::Rect(gfx::Size(kDefaultMode.hdisplay, kDefaultMode.vdisplay))); screen_manager_->AddWindow(kDefaultWidgetHandle, std::move(window)); @@ -159,9 +159,7 @@ gfx::Point(4, 2), 0); // Add another device. - auto gbm_device = std::make_unique<ui::MockGbmDevice>(); - scoped_refptr<ui::MockDrmDevice> drm = - new ui::MockDrmDevice(std::move(gbm_device)); + scoped_refptr<ui::MockDrmDevice> drm = new ui::MockDrmDevice; screen_manager_->AddDisplayController(drm, kDefaultCrtc, kDefaultConnector); screen_manager_->ConfigureDisplayController( drm, kDefaultCrtc, kDefaultConnector, @@ -179,13 +177,11 @@ TEST_F(DrmWindowTest, CheckDeathOnFailedSwap) { const gfx::Size window_size(6, 4); + ui::MockDumbBufferGenerator buffer_generator; ui::DrmWindow* window = screen_manager_->GetWindow(kDefaultWidgetHandle); - - std::unique_ptr<ui::GbmBuffer> buffer = drm_->gbm_device()->CreateBuffer( - DRM_FORMAT_XRGB8888, window_size, GBM_BO_USE_SCANOUT); - scoped_refptr<ui::DrmFramebuffer> framebuffer = - ui::DrmFramebuffer::AddFramebuffer(drm_, buffer.get()); - ui::DrmOverlayPlane plane(framebuffer, nullptr); + ui::DrmOverlayPlane plane( + buffer_generator.Create(drm_, DRM_FORMAT_XRGB8888, {}, window_size), + nullptr); drm_->set_page_flip_expectation(false);
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_controller_unittest.cc b/ui/ozone/platform/drm/gpu/hardware_display_controller_unittest.cc index 662d7232..0a4c75cb 100644 --- a/ui/ozone/platform/drm/gpu/hardware_display_controller_unittest.cc +++ b/ui/ozone/platform/drm/gpu/hardware_display_controller_unittest.cc
@@ -13,14 +13,12 @@ #include "ui/gfx/gpu_fence.h" #include "ui/gfx/native_pixmap.h" #include "ui/gfx/presentation_feedback.h" -#include "ui/ozone/common/linux/gbm_buffer.h" #include "ui/ozone/platform/drm/gpu/crtc_controller.h" -#include "ui/ozone/platform/drm/gpu/drm_framebuffer.h" #include "ui/ozone/platform/drm/gpu/drm_gpu_util.h" #include "ui/ozone/platform/drm/gpu/hardware_display_controller.h" #include "ui/ozone/platform/drm/gpu/hardware_display_plane.h" #include "ui/ozone/platform/drm/gpu/mock_drm_device.h" -#include "ui/ozone/platform/drm/gpu/mock_gbm_device.h" +#include "ui/ozone/platform/drm/gpu/mock_drm_framebuffer_generator.h" namespace { @@ -59,18 +57,17 @@ const std::string& property_name); scoped_refptr<ui::DrmFramebuffer> CreateBuffer() { - std::unique_ptr<ui::GbmBuffer> buffer = drm_->gbm_device()->CreateBuffer( - DRM_FORMAT_XRGB8888, kDefaultModeSize, GBM_BO_USE_SCANOUT); - return ui::DrmFramebuffer::AddFramebuffer(drm_, buffer.get()); + return buffer_generator_->CreateWithModifier( + drm_, DRM_FORMAT_XRGB8888, DRM_FORMAT_MOD_NONE, kDefaultModeSize); } scoped_refptr<ui::DrmFramebuffer> CreateOverlayBuffer() { - std::unique_ptr<ui::GbmBuffer> buffer = drm_->gbm_device()->CreateBuffer( - DRM_FORMAT_XRGB8888, kOverlaySize, GBM_BO_USE_SCANOUT); - return ui::DrmFramebuffer::AddFramebuffer(drm_, buffer.get()); + return buffer_generator_->CreateWithModifier( + drm_, DRM_FORMAT_XRGB8888, DRM_FORMAT_MOD_NONE, kOverlaySize); } protected: + std::unique_ptr<ui::MockDrmFramebufferGenerator> buffer_generator_; std::unique_ptr<ui::HardwareDisplayController> controller_; scoped_refptr<ui::MockDrmDevice> drm_; @@ -86,10 +83,10 @@ page_flips_ = 0; last_swap_result_ = gfx::SwapResult::SWAP_FAILED; - auto gbm_device = std::make_unique<ui::MockGbmDevice>(); - drm_ = new ui::MockDrmDevice(std::move(gbm_device)); + drm_ = new ui::MockDrmDevice; InitializeDrmDevice(/* use_atomic= */ true); + buffer_generator_.reset(new ui::MockDrmFramebufferGenerator()); controller_.reset(new ui::HardwareDisplayController( std::unique_ptr<ui::CrtcController>( new ui::CrtcController(drm_.get(), kPrimaryCrtc, kPrimaryConnector)),
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc index 177a262..7944c60 100644 --- a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc +++ b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc
@@ -17,15 +17,13 @@ #include "ui/display/types/gamma_ramp_rgb_entry.h" #include "ui/gfx/gpu_fence.h" #include "ui/gfx/gpu_fence_handle.h" -#include "ui/ozone/common/linux/gbm_buffer.h" #include "ui/ozone/platform/drm/gpu/crtc_controller.h" -#include "ui/ozone/platform/drm/gpu/drm_framebuffer.h" #include "ui/ozone/platform/drm/gpu/drm_gpu_util.h" #include "ui/ozone/platform/drm/gpu/hardware_display_plane_atomic.h" #include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.h" #include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.h" #include "ui/ozone/platform/drm/gpu/mock_drm_device.h" -#include "ui/ozone/platform/drm/gpu/mock_gbm_device.h" +#include "ui/ozone/platform/drm/gpu/mock_drm_framebuffer_generator.h" namespace { @@ -64,20 +62,21 @@ void SetUp() override; scoped_refptr<ui::DrmFramebuffer> CreateBuffer(const gfx::Size& size) { - return CreateBufferWithFormat(size, DRM_FORMAT_XRGB8888); + return buffer_generator_->CreateWithModifier(fake_drm_, DRM_FORMAT_XRGB8888, + DRM_FORMAT_MOD_NONE, size); } scoped_refptr<ui::DrmFramebuffer> CreateBufferWithFormat( const gfx::Size& size, uint32_t format) { - std::unique_ptr<ui::GbmBuffer> buffer = - fake_drm_->gbm_device()->CreateBuffer(format, size, GBM_BO_USE_SCANOUT); - return ui::DrmFramebuffer::AddFramebuffer(fake_drm_, buffer.get()); + return buffer_generator_->CreateWithModifier(fake_drm_, format, + DRM_FORMAT_MOD_NONE, size); } protected: ui::HardwareDisplayPlaneList state_; scoped_refptr<ui::DrmFramebuffer> fake_buffer_; + std::unique_ptr<ui::MockDrmFramebufferGenerator> buffer_generator_; scoped_refptr<ui::MockDrmDevice> fake_drm_; std::vector<ui::MockDrmDevice::CrtcProperties> crtc_properties_; @@ -92,9 +91,9 @@ void HardwareDisplayPlaneManagerTest::SetUp() { use_atomic_ = GetParam(); + buffer_generator_.reset(new ui::MockDrmFramebufferGenerator()); - auto gbm_device = std::make_unique<ui::MockGbmDevice>(); - fake_drm_ = new ui::MockDrmDevice(std::move(gbm_device)); + fake_drm_ = new ui::MockDrmDevice; fake_drm_->SetPropertyBlob(ui::MockDrmDevice::AllocateInFormatsBlob( kInFormatsBlobPropId, {DRM_FORMAT_XRGB8888}, {})); @@ -299,7 +298,7 @@ TEST_P(HardwareDisplayPlaneManagerLegacyTest, CheckFramebufferFormatMatch) { ui::DrmOverlayPlaneList assigns; scoped_refptr<ui::DrmFramebuffer> buffer = - CreateBufferWithFormat(kDefaultBufferSize, DRM_FORMAT_UYVY); + CreateBufferWithFormat(kDefaultBufferSize, DRM_FORMAT_NV12); assigns.push_back(ui::DrmOverlayPlane(buffer, nullptr)); InitializeDrmState(/*crtc_count=*/2, /*planes_per_crtc=*/1); @@ -783,8 +782,8 @@ HardwareDisplayPlaneManagerPlanesReadyTest() {} void SetUp() override { - auto gbm_device = std::make_unique<ui::MockGbmDevice>(); - fake_drm_ = new ui::MockDrmDevice(std::move(gbm_device)); + fake_drm_ = new ui::MockDrmDevice; + buffer_generator_.reset(new ui::MockDrmFramebufferGenerator()); drm_framebuffer_ = CreateBuffer(kDefaultBufferSize); planes_without_fences_ = CreatePlanesWithoutFences(); planes_with_fences_ = CreatePlanesWithFences(); @@ -795,10 +794,8 @@ void RequestPlanesReady(ui::DrmOverlayPlaneList planes); scoped_refptr<ui::DrmFramebuffer> CreateBuffer(const gfx::Size& size) { - std::unique_ptr<ui::GbmBuffer> buffer = - fake_drm_->gbm_device()->CreateBuffer(DRM_FORMAT_XRGB8888, size, - GBM_BO_USE_SCANOUT); - return ui::DrmFramebuffer::AddFramebuffer(fake_drm_, buffer.get()); + return buffer_generator_->CreateWithModifier(fake_drm_, DRM_FORMAT_XRGB8888, + DRM_FORMAT_MOD_NONE, size); } ui::DrmOverlayPlaneList CreatePlanesWithoutFences() { @@ -820,6 +817,7 @@ } scoped_refptr<ui::MockDrmDevice> fake_drm_; + std::unique_ptr<ui::MockDrmFramebufferGenerator> buffer_generator_; std::unique_ptr<ui::HardwareDisplayPlaneManager> plane_manager_; bool callback_called = false; base::test::ScopedTaskEnvironment task_env_{ @@ -928,26 +926,24 @@ TEST(HardwareDisplayPlaneManagerAtomic, EnableBlend) { auto plane_manager = std::make_unique<ui::HardwareDisplayPlaneManagerAtomic>(); - auto gbm_device = std::make_unique<ui::MockGbmDevice>(); - auto drm_device = - base::MakeRefCounted<ui::MockDrmDevice>(std::move(gbm_device)); + auto drm_device = base::MakeRefCounted<ui::MockDrmDevice>(); + auto buffer_generator = std::make_unique<ui::MockDrmFramebufferGenerator>(); ui::HardwareDisplayPlaneList plane_list; HardwareDisplayPlaneAtomicMock hw_plane; - std::unique_ptr<ui::GbmBuffer> buffer = - drm_device->gbm_device()->CreateBuffer( - DRM_FORMAT_XRGB8888, kDefaultBufferSize, GBM_BO_USE_SCANOUT); - scoped_refptr<ui::DrmFramebuffer> framebuffer = - ui::DrmFramebuffer::AddFramebuffer(drm_device, buffer.get()); - ui::DrmOverlayPlane overlay(framebuffer, nullptr); + scoped_refptr<ui::DrmFramebuffer> buffer = + buffer_generator->CreateWithModifier( + drm_device.get(), DRM_FORMAT_XRGB8888, DRM_FORMAT_MOD_NONE, + kDefaultBufferSize); + ui::DrmOverlayPlane overlay(buffer, nullptr); overlay.enable_blend = true; plane_manager->SetPlaneData(&plane_list, &hw_plane, overlay, 1, gfx::Rect(), nullptr); - EXPECT_EQ(hw_plane.framebuffer(), framebuffer->framebuffer_id()); + EXPECT_EQ(hw_plane.framebuffer(), buffer->framebuffer_id()); overlay.enable_blend = false; plane_manager->SetPlaneData(&plane_list, &hw_plane, overlay, 1, gfx::Rect(), nullptr); - EXPECT_EQ(hw_plane.framebuffer(), framebuffer->opaque_framebuffer_id()); + EXPECT_EQ(hw_plane.framebuffer(), buffer->opaque_framebuffer_id()); } } // namespace
diff --git a/ui/ozone/platform/drm/gpu/mock_drm_device.cc b/ui/ozone/platform/drm/gpu/mock_drm_device.cc index 4b7f5a46..abdc7adc 100644 --- a/ui/ozone/platform/drm/gpu/mock_drm_device.cc +++ b/ui/ozone/platform/drm/gpu/mock_drm_device.cc
@@ -73,11 +73,11 @@ default; MockDrmDevice::PlaneProperties::~PlaneProperties() = default; -MockDrmDevice::MockDrmDevice(std::unique_ptr<GbmDevice> gbm_device) +MockDrmDevice::MockDrmDevice() : DrmDevice(base::FilePath(), base::File(), true /* is_primary_device */, - std::move(gbm_device)), + nullptr), get_crtc_call_count_(0), set_crtc_call_count_(0), restore_crtc_call_count_(0),
diff --git a/ui/ozone/platform/drm/gpu/mock_drm_device.h b/ui/ozone/platform/drm/gpu/mock_drm_device.h index 2e705d0..95ad0398 100644 --- a/ui/ozone/platform/drm/gpu/mock_drm_device.h +++ b/ui/ozone/platform/drm/gpu/mock_drm_device.h
@@ -44,7 +44,7 @@ std::vector<DrmDevice::Property> properties; }; - MockDrmDevice(std::unique_ptr<GbmDevice> gbm_device); + MockDrmDevice(); static ScopedDrmPropertyBlobPtr AllocateInFormatsBlob( uint32_t id,
diff --git a/ui/ozone/platform/drm/gpu/mock_drm_framebuffer_generator.cc b/ui/ozone/platform/drm/gpu/mock_drm_framebuffer_generator.cc new file mode 100644 index 0000000..41fb7ba --- /dev/null +++ b/ui/ozone/platform/drm/gpu/mock_drm_framebuffer_generator.cc
@@ -0,0 +1,53 @@ +// 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. + +#include "ui/ozone/platform/drm/gpu/mock_drm_framebuffer_generator.h" + +#include <drm_fourcc.h> + +#include "ui/ozone/platform/drm/common/drm_util.h" +#include "ui/ozone/platform/drm/gpu/drm_device.h" + +namespace ui { + +namespace { + +uint32_t g_current_mock_buffer_handle = 0x1111; + +} // namespace + +MockDrmFramebufferGenerator::MockDrmFramebufferGenerator() {} + +MockDrmFramebufferGenerator::~MockDrmFramebufferGenerator() {} + +scoped_refptr<DrmFramebuffer> MockDrmFramebufferGenerator::Create( + const scoped_refptr<DrmDevice>& drm, + uint32_t format, + const std::vector<uint64_t>& modifiers, + const gfx::Size& size) { + return CreateWithModifier( + drm, format, modifiers.empty() ? DRM_FORMAT_MOD_NONE : modifiers.front(), + size); +} + +scoped_refptr<DrmFramebuffer> MockDrmFramebufferGenerator::CreateWithModifier( + const scoped_refptr<DrmDevice>& drm, + uint32_t format, + uint64_t modifier, + const gfx::Size& size) { + if (allocation_failure_) + return nullptr; + + DrmFramebuffer::AddFramebufferParams params; + params.format = format; + params.modifier = modifier; + params.width = size.width(); + params.height = size.height(); + params.num_planes = 1; + params.handles[0] = g_current_mock_buffer_handle++; + + return DrmFramebuffer::AddFramebuffer(drm, params); +} + +} // namespace ui
diff --git a/ui/ozone/platform/drm/gpu/mock_drm_framebuffer_generator.h b/ui/ozone/platform/drm/gpu/mock_drm_framebuffer_generator.h new file mode 100644 index 0000000..4b3e8cb --- /dev/null +++ b/ui/ozone/platform/drm/gpu/mock_drm_framebuffer_generator.h
@@ -0,0 +1,44 @@ +// 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 UI_OZONE_PLATFORM_DRM_GPU_MOCK_SCANOUT_BUFFER_GENERATOR_H_ +#define UI_OZONE_PLATFORM_DRM_GPU_MOCK_SCANOUT_BUFFER_GENERATOR_H_ + +#include "base/macros.h" + +#include "ui/ozone/platform/drm/gpu/drm_framebuffer.h" +#include "ui/ozone/platform/drm/gpu/drm_framebuffer_generator.h" + +namespace ui { + +class MockDrmFramebufferGenerator : public DrmFramebufferGenerator { + public: + MockDrmFramebufferGenerator(); + ~MockDrmFramebufferGenerator() override; + + // DrmFramebufferGenerator: + scoped_refptr<DrmFramebuffer> Create(const scoped_refptr<DrmDevice>& drm, + uint32_t format, + const std::vector<uint64_t>& modifiers, + const gfx::Size& size) override; + + scoped_refptr<DrmFramebuffer> CreateWithModifier( + const scoped_refptr<DrmDevice>& drm, + uint32_t format, + uint64_t modifier, + const gfx::Size& size); + + void set_allocation_failure(bool allocation_failure) { + allocation_failure_ = allocation_failure; + } + + private: + DISALLOW_COPY_AND_ASSIGN(MockDrmFramebufferGenerator); + + bool allocation_failure_ = false; +}; + +} // namespace ui + +#endif // UI_OZONE_PLATFORM_DRM_GPU_MOCK_SCANOUT_BUFFER_GENERATOR_H_
diff --git a/ui/ozone/platform/drm/gpu/mock_dumb_buffer_generator.cc b/ui/ozone/platform/drm/gpu/mock_dumb_buffer_generator.cc new file mode 100644 index 0000000..2934559 --- /dev/null +++ b/ui/ozone/platform/drm/gpu/mock_dumb_buffer_generator.cc
@@ -0,0 +1,69 @@ +// 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. + +#include "ui/ozone/platform/drm/gpu/mock_dumb_buffer_generator.h" + +#include "third_party/skia/include/core/SkImageInfo.h" +#include "ui/ozone/platform/drm/gpu/drm_buffer.h" +#include "ui/ozone/platform/drm/gpu/drm_device.h" + +namespace ui { + +namespace { + +uint32_t GetFourCCCodeForSkColorType(SkColorType type) { + switch (type) { + case kUnknown_SkColorType: + case kAlpha_8_SkColorType: + return 0; + case kRGB_565_SkColorType: + return DRM_FORMAT_RGB565; + case kARGB_4444_SkColorType: + return DRM_FORMAT_ARGB4444; + case kN32_SkColorType: + return DRM_FORMAT_ARGB8888; + default: + NOTREACHED(); + return 0; + } +} + +scoped_refptr<DrmFramebuffer> AddFramebufferForDumbBuffer( + const scoped_refptr<DrmDevice>& drm, + uint32_t handle, + uint32_t stride, + const SkImageInfo& info) { + DrmFramebuffer::AddFramebufferParams params; + params.flags = 0; + params.format = GetFourCCCodeForSkColorType(info.colorType()); + params.modifier = DRM_FORMAT_MOD_INVALID; + params.width = info.width(); + params.height = info.height(); + params.num_planes = 1; + params.handles[0] = handle; + params.strides[0] = stride; + return DrmFramebuffer::AddFramebuffer(drm, params); +} + +} // namespace + +MockDumbBufferGenerator::MockDumbBufferGenerator() {} + +MockDumbBufferGenerator::~MockDumbBufferGenerator() {} + +scoped_refptr<DrmFramebuffer> MockDumbBufferGenerator::Create( + const scoped_refptr<DrmDevice>& drm, + uint32_t format, + const std::vector<uint64_t>& modifiers, + const gfx::Size& size) { + std::unique_ptr<DrmBuffer> buffer(new DrmBuffer(drm)); + SkImageInfo info = SkImageInfo::MakeN32Premul(size.width(), size.height()); + if (!buffer->Initialize(info)) + return NULL; + + return AddFramebufferForDumbBuffer(drm, buffer->GetHandle(), buffer->stride(), + info); +} + +} // namespace ui
diff --git a/ui/ozone/platform/drm/gpu/mock_dumb_buffer_generator.h b/ui/ozone/platform/drm/gpu/mock_dumb_buffer_generator.h new file mode 100644 index 0000000..9fe8f4d --- /dev/null +++ b/ui/ozone/platform/drm/gpu/mock_dumb_buffer_generator.h
@@ -0,0 +1,34 @@ +// 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 UI_OZONE_PLATFORM_DRM_GPU_MOCK_DUMB_BUFFER_GENERATOR_H_ +#define UI_OZONE_PLATFORM_DRM_GPU_MOCK_DUMB_BUFFER_GENERATOR_H_ + +#include "base/macros.h" + +#include "ui/ozone/platform/drm/gpu/drm_framebuffer.h" +#include "ui/ozone/platform/drm/gpu/drm_framebuffer_generator.h" + +namespace ui { + +class DrmFramebuffer; + +class MockDumbBufferGenerator : public DrmFramebufferGenerator { + public: + MockDumbBufferGenerator(); + ~MockDumbBufferGenerator() override; + + // DrmFramebufferGenerator: + scoped_refptr<DrmFramebuffer> Create(const scoped_refptr<DrmDevice>& drm, + uint32_t format, + const std::vector<uint64_t>& modifiers, + const gfx::Size& size) override; + + private: + DISALLOW_COPY_AND_ASSIGN(MockDumbBufferGenerator); +}; + +} // namespace ui + +#endif // UI_OZONE_PLATFORM_DRM_GPU_MOCK_DUMB_BUFFER_GENERATOR_H_
diff --git a/ui/ozone/platform/drm/gpu/mock_gbm_device.cc b/ui/ozone/platform/drm/gpu/mock_gbm_device.cc deleted file mode 100644 index d7b298f..0000000 --- a/ui/ozone/platform/drm/gpu/mock_gbm_device.cc +++ /dev/null
@@ -1,161 +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. - -#include "ui/ozone/platform/drm/gpu/mock_gbm_device.h" - -#include <drm_fourcc.h> -#include <xf86drm.h> - -#include "base/logging.h" -#include "base/numerics/safe_math.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/ozone/common/linux/drm_util_linux.h" -#include "ui/ozone/common/linux/gbm_buffer.h" - -namespace ui { -namespace { - -class MockGbmBuffer final : public ui::GbmBuffer { - public: - MockGbmBuffer(uint32_t format, - uint32_t flags, - uint64_t modifier, - const gfx::Size& size, - std::vector<gfx::NativePixmapPlane> planes, - std::vector<uint32_t> handles) - : format_(format), - format_modifier_(modifier), - flags_(flags), - size_(size), - planes_(std::move(planes)), - handles_(std::move(handles)) {} - - ~MockGbmBuffer() override {} - - uint32_t GetFormat() const override { return format_; } - uint64_t GetFormatModifier() const override { return format_modifier_; } - uint32_t GetFlags() const override { return flags_; } - size_t GetFdCount() const override { return 0; } - gfx::Size GetSize() const override { return size_; } - gfx::BufferFormat GetBufferFormat() const override { - return ui::GetBufferFormatFromFourCCFormat(format_); - } - bool AreFdsValid() const override { return false; } - size_t GetNumPlanes() const override { return planes_.size(); } - int GetPlaneFd(size_t plane) const override { - NOTREACHED(); - return -1; - } - int GetPlaneStride(size_t plane) const override { - DCHECK_LT(plane, planes_.size()); - return planes_[plane].stride; - } - int GetPlaneOffset(size_t plane) const override { - DCHECK_LT(plane, planes_.size()); - return planes_[plane].offset; - } - size_t GetPlaneSize(size_t plane) const override { - DCHECK_LT(plane, planes_.size()); - return planes_[plane].size; - } - uint32_t GetPlaneHandle(size_t plane) const override { - DCHECK_LT(plane, planes_.size()); - return handles_[plane]; - } - uint32_t GetHandle() const override { return GetPlaneHandle(0); } - gfx::NativePixmapHandle ExportHandle() const override { - NOTIMPLEMENTED(); - return gfx::NativePixmapHandle(); - } - - private: - uint32_t format_ = 0; - uint64_t format_modifier_ = 0; - uint32_t flags_ = 0; - std::vector<base::ScopedFD> fds_; - gfx::Size size_; - std::vector<gfx::NativePixmapPlane> planes_; - std::vector<uint32_t> handles_; - - DISALLOW_COPY_AND_ASSIGN(MockGbmBuffer); -}; - -} // namespace - -MockGbmDevice::MockGbmDevice() {} - -MockGbmDevice::~MockGbmDevice() {} - -void MockGbmDevice::set_allocation_failure(bool should_fail_allocations) { - should_fail_allocations_ = should_fail_allocations; -} - -std::unique_ptr<GbmBuffer> MockGbmDevice::CreateBuffer(uint32_t format, - const gfx::Size& size, - uint32_t flags) { - if (should_fail_allocations_) - return nullptr; - - return CreateBufferWithModifiers(format, size, flags, {}); -} - -std::unique_ptr<GbmBuffer> MockGbmDevice::CreateBufferWithModifiers( - uint32_t format, - const gfx::Size& size, - uint32_t flags, - const std::vector<uint64_t>& modifiers) { - uint32_t bytes_per_pixel; - switch (format) { - case DRM_FORMAT_XRGB8888: - case DRM_FORMAT_ARGB8888: - bytes_per_pixel = 4; - break; - case DRM_FORMAT_UYVY: - bytes_per_pixel = 2; - break; - default: - NOTREACHED() << "Unsupported format: " << format; - return nullptr; - } - - if (modifiers.size() > 1) - return nullptr; - - uint64_t format_modifier = - modifiers.size() ? modifiers[0] : DRM_FORMAT_MOD_NONE; - switch (format_modifier) { - case DRM_FORMAT_MOD_NONE: - case I915_FORMAT_MOD_X_TILED: - break; - default: - NOTREACHED() << "Unsupported format modifier: " << format_modifier; - return nullptr; - } - - uint32_t width = base::checked_cast<uint32_t>(size.width()); - uint32_t height = base::checked_cast<uint32_t>(size.height()); - uint32_t plane_stride = base::CheckMul(bytes_per_pixel, width).ValueOrDie(); - uint32_t plane_size = base::CheckMul(plane_stride, height).ValueOrDie(); - uint32_t plane_offset = 0; - - std::vector<gfx::NativePixmapPlane> planes; - planes.push_back(gfx::NativePixmapPlane(plane_stride, plane_offset, - plane_size, format_modifier)); - std::vector<uint32_t> handles; - handles.push_back(next_handle_++); - - return std::make_unique<MockGbmBuffer>(format, flags, format_modifier, size, - std::move(planes), std::move(handles)); -} - -std::unique_ptr<GbmBuffer> MockGbmDevice::CreateBufferFromFds( - uint32_t format, - const gfx::Size& size, - std::vector<base::ScopedFD> fds, - const std::vector<gfx::NativePixmapPlane>& planes) { - NOTREACHED(); - return nullptr; -} - -} // namespace ui
diff --git a/ui/ozone/platform/drm/gpu/mock_gbm_device.h b/ui/ozone/platform/drm/gpu/mock_gbm_device.h deleted file mode 100644 index b07c63e51..0000000 --- a/ui/ozone/platform/drm/gpu/mock_gbm_device.h +++ /dev/null
@@ -1,44 +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 UI_OZONE_PLATFORM_DRM_GPU_MOCK_GBM_DEVICE_H_ -#define UI_OZONE_PLATFORM_DRM_GPU_MOCK_GBM_DEVICE_H_ - -#include "ui/ozone/common/linux/gbm_device.h" - -namespace ui { - -// The real DrmDevice makes actual DRM calls which we can't use in unit tests. -class MockGbmDevice : public GbmDevice { - public: - MockGbmDevice(); - ~MockGbmDevice() override; - - void set_allocation_failure(bool should_fail_allocations); - - // GbmDevice: - std::unique_ptr<GbmBuffer> CreateBuffer(uint32_t format, - const gfx::Size& size, - uint32_t flags) override; - std::unique_ptr<GbmBuffer> CreateBufferWithModifiers( - uint32_t format, - const gfx::Size& size, - uint32_t flags, - const std::vector<uint64_t>& modifiers) override; - std::unique_ptr<GbmBuffer> CreateBufferFromFds( - uint32_t format, - const gfx::Size& size, - std::vector<base::ScopedFD> fds, - const std::vector<gfx::NativePixmapPlane>& planes) override; - - private: - uint32_t next_handle_ = 0; - bool should_fail_allocations_ = false; - - DISALLOW_COPY_AND_ASSIGN(MockGbmDevice); -}; - -} // namespace ui - -#endif // UI_OZONE_PLATFORM_DRM_GPU_MOCK_GBM_DEVICE_H_
diff --git a/ui/ozone/platform/drm/gpu/screen_manager.cc b/ui/ozone/platform/drm/gpu/screen_manager.cc index a228fda..3cd0ad0 100644 --- a/ui/ozone/platform/drm/gpu/screen_manager.cc +++ b/ui/ozone/platform/drm/gpu/screen_manager.cc
@@ -15,12 +15,12 @@ #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/gpu_fence.h" -#include "ui/ozone/common/linux/gbm_buffer.h" #include "ui/ozone/platform/drm/common/drm_util.h" #include "ui/ozone/platform/drm/gpu/crtc_controller.h" #include "ui/ozone/platform/drm/gpu/drm_console_buffer.h" #include "ui/ozone/platform/drm/gpu/drm_device.h" #include "ui/ozone/platform/drm/gpu/drm_framebuffer.h" +#include "ui/ozone/platform/drm/gpu/drm_framebuffer_generator.h" #include "ui/ozone/platform/drm/gpu/drm_window.h" #include "ui/ozone/platform/drm/gpu/hardware_display_controller.h" @@ -96,7 +96,8 @@ } // namespace -ScreenManager::ScreenManager() {} +ScreenManager::ScreenManager(DrmFramebufferGenerator* buffer_generator) + : buffer_generator_(buffer_generator) {} ScreenManager::~ScreenManager() { DCHECK(window_map_.empty()); @@ -386,11 +387,8 @@ } scoped_refptr<DrmDevice> drm = controller->GetDrmDevice(); - std::unique_ptr<GbmBuffer> buffer = - drm->gbm_device()->CreateBufferWithModifiers( - fourcc_format, bounds.size(), GBM_BO_USE_SCANOUT, modifiers); - scoped_refptr<DrmFramebuffer> framebuffer = - DrmFramebuffer::AddFramebuffer(drm, buffer.get()); + scoped_refptr<DrmFramebuffer> buffer = + buffer_generator_->Create(drm, fourcc_format, modifiers, bounds.size()); if (!buffer) { LOG(ERROR) << "Failed to create scanout buffer"; return DrmOverlayPlane(nullptr, 0, gfx::OVERLAY_TRANSFORM_INVALID, @@ -398,8 +396,8 @@ /* gpu_fence */ nullptr); } - FillModesetBuffer(drm, controller, framebuffer.get()); - return DrmOverlayPlane(framebuffer, nullptr); + FillModesetBuffer(drm, controller, buffer.get()); + return DrmOverlayPlane(buffer, nullptr); } bool ScreenManager::EnableController(HardwareDisplayController* controller) {
diff --git a/ui/ozone/platform/drm/gpu/screen_manager.h b/ui/ozone/platform/drm/gpu/screen_manager.h index e5c2760d..c21dbde 100644 --- a/ui/ozone/platform/drm/gpu/screen_manager.h +++ b/ui/ozone/platform/drm/gpu/screen_manager.h
@@ -25,11 +25,12 @@ class DrmDevice; class DrmWindow; +class DrmFramebufferGenerator; // Responsible for keeping track of active displays and configuring them. class ScreenManager { public: - ScreenManager(); + ScreenManager(DrmFramebufferGenerator* surface_generator); virtual ~ScreenManager(); // Register a display controller. This must be called before trying to @@ -130,6 +131,7 @@ DrmWindow* FindWindowAt(const gfx::Rect& bounds) const; + DrmFramebufferGenerator* buffer_generator_; // Not owned. // List of display controllers (active and disabled). HardwareDisplayControllers controllers_;
diff --git a/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc b/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc index 1d05b1d9..d88806e 100644 --- a/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc +++ b/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc
@@ -12,7 +12,6 @@ #include "base/macros.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/gpu_fence.h" -#include "ui/ozone/common/linux/gbm_buffer.h" #include "ui/ozone/platform/drm/gpu/crtc_controller.h" #include "ui/ozone/platform/drm/gpu/drm_device_generator.h" #include "ui/ozone/platform/drm/gpu/drm_device_manager.h" @@ -20,7 +19,7 @@ #include "ui/ozone/platform/drm/gpu/drm_window.h" #include "ui/ozone/platform/drm/gpu/hardware_display_controller.h" #include "ui/ozone/platform/drm/gpu/mock_drm_device.h" -#include "ui/ozone/platform/drm/gpu/mock_gbm_device.h" +#include "ui/ozone/platform/drm/gpu/mock_drm_framebuffer_generator.h" #include "ui/ozone/platform/drm/gpu/screen_manager.h" namespace ui { @@ -57,36 +56,20 @@ } void SetUp() override { - auto gbm = std::make_unique<ui::MockGbmDevice>(); - drm_ = new ui::MockDrmDevice(std::move(gbm)); + drm_ = new ui::MockDrmDevice; device_manager_.reset(new ui::DrmDeviceManager(nullptr)); - screen_manager_.reset(new ui::ScreenManager()); + buffer_generator_.reset(new ui::MockDrmFramebufferGenerator()); + screen_manager_.reset(new ui::ScreenManager(buffer_generator_.get())); } void TearDown() override { screen_manager_.reset(); drm_ = nullptr; } - scoped_refptr<DrmFramebuffer> CreateBuffer(uint32_t format, - const gfx::Size& size) { - return CreateBufferWithModifier(format, DRM_FORMAT_MOD_NONE, size); - } - - scoped_refptr<DrmFramebuffer> CreateBufferWithModifier( - uint32_t format, - uint64_t format_modifier, - const gfx::Size& size) { - std::vector<uint64_t> modifiers; - if (format_modifier != DRM_FORMAT_MOD_NONE) - modifiers.push_back(format_modifier); - auto buffer = drm_->gbm_device()->CreateBufferWithModifiers( - format, size, GBM_BO_USE_SCANOUT, modifiers); - return DrmFramebuffer::AddFramebuffer(drm_, buffer.get()); - } - protected: scoped_refptr<ui::MockDrmDevice> drm_; std::unique_ptr<ui::DrmDeviceManager> device_manager_; + std::unique_ptr<ui::MockDrmFramebufferGenerator> buffer_generator_; std::unique_ptr<ui::ScreenManager> screen_manager_; private: @@ -377,9 +360,7 @@ TEST_F(ScreenManagerTest, CheckProperConfigurationWithDifferentDeviceAndSameCrtc) { - auto gbm_device = std::make_unique<ui::MockGbmDevice>(); - scoped_refptr<ui::MockDrmDevice> drm2 = - new ui::MockDrmDevice(std::move(gbm_device)); + scoped_refptr<ui::MockDrmDevice> drm2 = new ui::MockDrmDevice; screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector); screen_manager_->AddDisplayController(drm2, kPrimaryCrtc, kPrimaryConnector); @@ -404,7 +385,7 @@ TEST_F(ScreenManagerTest, CheckControllerToWindowMappingWithSameBounds) { std::unique_ptr<ui::DrmWindow> window( new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get())); - window->Initialize(); + window->Initialize(buffer_generator_.get()); window->SetBounds(GetPrimaryBounds()); screen_manager_->AddWindow(1, std::move(window)); @@ -422,7 +403,7 @@ TEST_F(ScreenManagerTest, CheckControllerToWindowMappingWithDifferentBounds) { std::unique_ptr<ui::DrmWindow> window( new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get())); - window->Initialize(); + window->Initialize(buffer_generator_.get()); gfx::Rect new_bounds = GetPrimaryBounds(); new_bounds.Inset(0, 0, 1, 1); window->SetBounds(new_bounds); @@ -445,7 +426,7 @@ for (size_t i = 1; i < kWindowCount + 1; ++i) { std::unique_ptr<ui::DrmWindow> window( new ui::DrmWindow(i, device_manager_.get(), screen_manager_.get())); - window->Initialize(); + window->Initialize(buffer_generator_.get()); window->SetBounds(GetPrimaryBounds()); screen_manager_->AddWindow(i, std::move(window)); } @@ -470,7 +451,7 @@ gfx::AcceleratedWidget window_id = 1; std::unique_ptr<ui::DrmWindow> window(new ui::DrmWindow( window_id, device_manager_.get(), screen_manager_.get())); - window->Initialize(); + window->Initialize(buffer_generator_.get()); window->SetBounds(GetPrimaryBounds()); screen_manager_->AddWindow(window_id, std::move(window)); @@ -492,7 +473,7 @@ TEST_F(ScreenManagerTest, EnableControllerWhenWindowHasNoBuffer) { std::unique_ptr<ui::DrmWindow> window( new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get())); - window->Initialize(); + window->Initialize(buffer_generator_.get()); window->SetBounds(GetPrimaryBounds()); screen_manager_->AddWindow(1, std::move(window)); @@ -521,10 +502,11 @@ TEST_F(ScreenManagerTest, EnableControllerWhenWindowHasBuffer) { std::unique_ptr<ui::DrmWindow> window( new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get())); - window->Initialize(); + window->Initialize(buffer_generator_.get()); window->SetBounds(GetPrimaryBounds()); - scoped_refptr<DrmFramebuffer> buffer = - CreateBuffer(DRM_FORMAT_XRGB8888, GetPrimaryBounds().size()); + + scoped_refptr<ui::DrmFramebuffer> buffer = buffer_generator_->Create( + drm_, DRM_FORMAT_XRGB8888, {}, GetPrimaryBounds().size()); ui::DrmOverlayPlaneList planes; planes.push_back(ui::DrmOverlayPlane(buffer, nullptr)); window->SchedulePageFlip(std::move(planes), base::DoNothing(), @@ -546,10 +528,13 @@ TEST_F(ScreenManagerTest, DISABLED_RejectBufferWithIncompatibleModifiers) { std::unique_ptr<ui::DrmWindow> window( new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get())); - window->Initialize(); + window->Initialize(buffer_generator_.get()); window->SetBounds(GetPrimaryBounds()); - auto buffer = CreateBufferWithModifier( - DRM_FORMAT_XRGB8888, I915_FORMAT_MOD_X_TILED, GetPrimaryBounds().size()); + scoped_refptr<ui::DrmFramebuffer> buffer = + buffer_generator_->CreateWithModifier(drm_, DRM_FORMAT_XRGB8888, + I915_FORMAT_MOD_X_TILED, + GetPrimaryBounds().size()); + ui::DrmOverlayPlaneList planes; planes.push_back(ui::DrmOverlayPlane(buffer, nullptr)); window->SchedulePageFlip(std::move(planes), base::DoNothing(), @@ -573,14 +558,11 @@ } TEST(ScreenManagerTest2, ShouldNotHardwareMirrorDifferentDrmDevices) { - auto gbm_device1 = std::make_unique<MockGbmDevice>(); - auto drm_device1 = - base::MakeRefCounted<MockDrmDevice>(std::move(gbm_device1)); - auto gbm_device2 = std::make_unique<MockGbmDevice>(); - auto drm_device2 = - base::MakeRefCounted<MockDrmDevice>(std::move(gbm_device2)); + auto drm_device1 = base::MakeRefCounted<MockDrmDevice>(); + auto drm_device2 = base::MakeRefCounted<MockDrmDevice>(); DrmDeviceManager drm_device_manager(nullptr); - ScreenManager screen_manager; + MockDrmFramebufferGenerator buffer_generator; + ScreenManager screen_manager(&buffer_generator); constexpr uint32_t kCrtc19 = 19; constexpr uint32_t kConnector28 = 28; @@ -599,7 +581,7 @@ { auto window1 = std::make_unique<DrmWindow>(1, &drm_device_manager, &screen_manager); - window1->Initialize(); + window1->Initialize(&buffer_generator); screen_manager.AddWindow(1, std::move(window1)); screen_manager.GetWindow(1)->SetBounds(gfx::Rect(0, 0, 1920, 1080)); screen_manager.AddDisplayController(drm_device1, kCrtc19, kConnector28); @@ -611,7 +593,7 @@ Mode(1920, 1080)); auto window2 = std::make_unique<DrmWindow>(2, &drm_device_manager, &screen_manager); - window2->Initialize(); + window2->Initialize(&buffer_generator); screen_manager.AddWindow(2, std::move(window2)); screen_manager.GetWindow(2)->SetBounds(gfx::Rect(0, 1140, 1920, 1080)); } @@ -657,7 +639,7 @@ Mode(1920, 1080)); auto window3 = std::make_unique<DrmWindow>(3, &drm_device_manager, &screen_manager); - window3->Initialize(); + window3->Initialize(&buffer_generator); screen_manager.AddWindow(3, std::move(window3)); screen_manager.GetWindow(3)->SetBounds(gfx::Rect(0, 0, 1920, 1080)); screen_manager.GetWindow(1)->SetBounds(gfx::Rect(0, 1140, 1920, 1080));
diff --git a/ui/views/controls/button/checkbox.cc b/ui/views/controls/button/checkbox.cc index 1038a13f..91e398e 100644 --- a/ui/views/controls/button/checkbox.cc +++ b/ui/views/controls/button/checkbox.cc
@@ -45,6 +45,10 @@ // Limit the checkbox height to match the legacy appearance. const gfx::Size preferred_size(LabelButton::CalculatePreferredSize()); SetMinSize(gfx::Size(0, preferred_size.height() + 4)); + + // Checkboxes always have a focus ring, even when the platform otherwise + // doesn't generally use them for buttons. + SetInstallFocusRingOnFocus(true); } Checkbox::~Checkbox() {