diff --git a/DEPS b/DEPS index bd785c6..9275223 100644 --- a/DEPS +++ b/DEPS
@@ -129,11 +129,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': 'e62bf561638c60550c35e81b1606843ed74bcfef', + 'skia_revision': '12cf258193dc2b92c19fafefde28265f1201f578', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '8042513e57dbb4da70ff0050af4ad19400108d9f', + 'v8_revision': '81260d20b1cfb15752913acb657113c92c6c0026', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -141,15 +141,15 @@ # 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': '1e064014eb2ba3f8a4aca5dec389ab1c7c58ddd7', + 'angle_revision': '065f8dc35f9dffead39ced85a0ab1ba447ccf843', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': '7d867277f805cedc984b7d4235ee04f35d859487', + 'swiftshader_revision': 'db4f3dfd19601c7c544f2b1eb2e98706a33f7902', # 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': '763affaf6625e4670c172aa19fba8e1a3d23fab5', + 'pdfium_revision': 'd69e0650a1c945933be7766a5b3a9e9c93cadd8a', # 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. @@ -196,7 +196,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': '5b353de6daa95ccf247a9bd26add94edbbdd684b', + 'catapult_revision': 'b614c567e8b363220b00ce5557a3ddfd8d18357c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -805,7 +805,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '7017b6e58088989184bf2581c3862c1b5627f7b9', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'd7ba750e8dd8eb4df11ae6a5bd01e62de590efae', 'condition': 'checkout_linux', }, @@ -978,7 +978,7 @@ Var('chromium_git') + '/chromium/deps/hunspell_dictionaries.git' + '@' + '83f4659730b4de886afa5ea19f71f332a009d2ee', 'src/third_party/icu': - Var('chromium_git') + '/chromium/deps/icu.git' + '@' + '4ae7482a0e9e1f77a793545d803086a5ad4bcfd8', + Var('chromium_git') + '/chromium/deps/icu.git' + '@' + '35f7e139f33f1ddbfdb68b65dda29aff430c3f6f', 'src/third_party/icu4j': { 'packages': [ @@ -1027,7 +1027,7 @@ }, 'src/third_party/leveldatabase/src': - Var('chromium_git') + '/external/leveldb.git' + '@' + '7035af5fc36657447054617759854a726d31dbe0', + Var('chromium_git') + '/external/leveldb.git' + '@' + 'ffabb1ae86cc4eb4516a7c0824c878c3b2d19e5d', 'src/third_party/libFuzzer/src': Var('chromium_git') + '/chromium/llvm-project/compiler-rt/lib/fuzzer.git' + '@' + Var('libfuzzer_revision'), @@ -1354,7 +1354,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '3f6583d3fee4ab71866ade794504a20eb6f63f88', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '3af5c4c3547b7da427b0cc87b0cdc0d56de37bcd', + Var('webrtc_git') + '/src.git' + '@' + '79e9f4b9c128963eef2c7031dd9311f86fca5535', 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d', @@ -1395,7 +1395,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@0d6826ff6cd92888bca24c2423013db9c65c2fc3', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@2221eb4885adfdeb675107859a225d2dd56e3a52', 'condition': 'checkout_src_internal', },
diff --git a/ash/app_list/app_list_controller_impl.cc b/ash/app_list/app_list_controller_impl.cc index f6db694..cba5aad4 100644 --- a/ash/app_list/app_list_controller_impl.cc +++ b/ash/app_list/app_list_controller_impl.cc
@@ -985,9 +985,14 @@ bool AppListControllerImpl::CanProcessEventsOnApplistViews() { // Do not allow processing events during overview or while overview is - // finished but still animating out. + // finished but still animating out. Note in clamshell mode, if overview and + // splitview is both active, we still allow the user to open app list and + // select an app. The app will be opened in snapped window state and overview + // will be ended after the app is opened. OverviewController* overview_controller = Shell::Get()->overview_controller(); - if (overview_controller->IsSelecting() || + auto* split_view_controller = Shell::Get()->split_view_controller(); + if ((overview_controller->IsSelecting() && + !split_view_controller->InClamshellSplitViewMode()) || overview_controller->IsCompletingShutdownAnimations()) { return false; }
diff --git a/ash/app_list/app_list_presenter_delegate_impl.cc b/ash/app_list/app_list_presenter_delegate_impl.cc index 577be62..f8f8f310 100644 --- a/ash/app_list/app_list_presenter_delegate_impl.cc +++ b/ash/app_list/app_list_presenter_delegate_impl.cc
@@ -112,6 +112,7 @@ DCHECK(is_visible_); DCHECK(view_); is_visible_ = false; + Shell::Get()->RemovePreTargetHandler(this); controller_->ViewClosing(); } @@ -230,7 +231,7 @@ } aura::Window* window = view_->GetWidget()->GetNativeView()->parent(); - if (!window->Contains(target) && !presenter_->CloseOpenedPage() && + if (!window->Contains(target) && !presenter_->HandleCloseOpenFolder() && !app_list::switches::ShouldNotDismissOnBlur() && !IsTabletMode()) { const aura::Window* status_window = shelf->shelf_widget()->status_area_widget()->GetNativeWindow(); @@ -242,6 +243,10 @@ if (status_window && status_window->Contains(target)) auto_hide_lock.emplace(shelf); + // Since event happened outside the app list, close the open search box if + // it is open. + presenter_->HandleCloseOpenSearchBox(); + // Keep app list opened if event happened in the shelf area. if (!shelf_window || !shelf_window->Contains(target)) 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 38feec3a..7020b27 100644 --- a/ash/app_list/app_list_presenter_delegate_unittest.cc +++ b/ash/app_list/app_list_presenter_delegate_unittest.cc
@@ -841,8 +841,8 @@ GetPrimaryShelf()->shelf_layout_manager()->GetShelfBackgroundType()); } -// Tests that the half app list transitions to peeking state and then closes -// itself if the user taps outside its bounds. +// Tests that the half app list closes itself if the user taps outside its +// bounds. TEST_P(AppListPresenterDelegateTest, TapAndClickOutsideClosesHalfAppList) { // TODO(newcomer): Investigate mash failures crbug.com/726838 GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId()); @@ -857,16 +857,6 @@ gfx::Point to_point( 0, GetAppListView()->GetWidget()->GetWindowBoundsInScreen().y() - 1); - // Clicking/tapping outside the bounds closes the search results page. - if (TestMouseEventParam()) { - generator->MoveMouseTo(to_point); - generator->ClickLeftButton(); - } else { - generator->GestureTapAt(to_point); - } - GetAppListTestHelper()->WaitUntilIdle(); - GetAppListTestHelper()->CheckState(ash::mojom::AppListViewState::kPeeking); - // Clicking/tapping outside the bounds closes the app list. if (TestMouseEventParam()) { generator->MoveMouseTo(to_point);
diff --git a/ash/app_list/presenter/app_list_presenter_impl.cc b/ash/app_list/presenter/app_list_presenter_impl.cc index 4dfd81d..6f1776bf 100644 --- a/ash/app_list/presenter/app_list_presenter_impl.cc +++ b/ash/app_list/presenter/app_list_presenter_impl.cc
@@ -158,14 +158,12 @@ base::RecordAction(base::UserMetricsAction("Launcher_Dismiss")); } -bool AppListPresenterImpl::CloseOpenedPage() { - if (!is_visible_) - return false; +bool AppListPresenterImpl::HandleCloseOpenFolder() { + return is_visible_ && view_ && view_->HandleCloseOpenFolder(); +} - // If the app list is currently visible, there should be an existing view. - DCHECK(view_); - - return view_->CloseOpenedPage(); +bool AppListPresenterImpl::HandleCloseOpenSearchBox() { + return is_visible_ && view_ && view_->HandleCloseOpenSearchBox(); } ash::ShelfAction AppListPresenterImpl::ToggleAppList(
diff --git a/ash/app_list/presenter/app_list_presenter_impl.h b/ash/app_list/presenter/app_list_presenter_impl.h index e577f591..ad54a25 100644 --- a/ash/app_list/presenter/app_list_presenter_impl.h +++ b/ash/app_list/presenter/app_list_presenter_impl.h
@@ -81,9 +81,13 @@ // one AppListShowSource or focusing out side of the launcher. void Dismiss(base::TimeTicks event_time_stamp); - // Closes opened folder or search result page if they are opened. Returns - // whether the action was handled. - bool CloseOpenedPage(); + // If app list has an opened folder, close it. Returns whether an opened + // folder was closed. + bool HandleCloseOpenFolder(); + + // If app list has an open search box, close it. Returns whether an open + // search box was closed. + bool HandleCloseOpenSearchBox(); // 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 2dc0bad..05d2da1 100644 --- a/ash/app_list/views/app_list_view.cc +++ b/ash/app_list/views/app_list_view.cc
@@ -421,19 +421,31 @@ GetWidget()->Deactivate(); } -bool AppListView::CloseOpenedPage() { - if (!app_list_main_view_) - return false; +void AppListView::CloseOpenedPage() { + if (HandleCloseOpenFolder()) + return; - if (app_list_main_view_->contents_view()->IsShowingSearchResults() || - GetAppsContainerView()->IsInFolderView()) { - return app_list_main_view_->contents_view()->Back(); + HandleCloseOpenSearchBox(); +} + +bool AppListView::HandleCloseOpenFolder() { + if (GetAppsContainerView()->IsInFolderView()) { + GetAppsContainerView()->app_list_folder_view()->CloseFolderPage(); + return true; } return false; } -void AppListView::Back() { - app_list_main_view_->contents_view()->Back(); +bool AppListView::HandleCloseOpenSearchBox() { + if (app_list_main_view_ && + app_list_main_view_->contents_view()->IsShowingSearchResults()) { + return Back(); + } + return false; +} + +bool AppListView::Back() { + return app_list_main_view_->contents_view()->Back(); } void AppListView::OnPaint(gfx::Canvas* canvas) { @@ -461,9 +473,8 @@ case ui::VKEY_BROWSER_BACK: // If the ContentsView does not handle the back action, then this is the // top level, so we close the app list. - if (!app_list_main_view_->contents_view()->Back() && !is_tablet_mode()) { + if (!Back() && !is_tablet_mode()) Dismiss(); - } break; default: NOTREACHED();
diff --git a/ash/app_list/views/app_list_view.h b/ash/app_list/views/app_list_view.h index c94310b..922a947 100644 --- a/ash/app_list/views/app_list_view.h +++ b/ash/app_list/views/app_list_view.h
@@ -147,12 +147,18 @@ // Dismisses the UI, cleans up and sets the state to CLOSED. void Dismiss(); - // Closes opened folder or search result page if they are opened. Returns - // whether the action was handled. - bool CloseOpenedPage(); + // Closes opened folder or search result page if they are opened. + void CloseOpenedPage(); + + // If a folder is open, close it. Returns whether an opened folder was closed. + bool HandleCloseOpenFolder(); + + // If a search box is open, close it. Returns whether an open search box was + // closed. + bool HandleCloseOpenSearchBox(); // Performs the 'back' action for the active page. - void Back(); + bool Back(); // views::View: void OnPaint(gfx::Canvas* canvas) override;
diff --git a/ash/public/cpp/ash_features.cc b/ash/public/cpp/ash_features.cc index cd6f9c84..3a53c68 100644 --- a/ash/public/cpp/ash_features.cc +++ b/ash/public/cpp/ash_features.cc
@@ -13,6 +13,9 @@ const base::Feature kDockedMagnifier{"DockedMagnifier", base::FEATURE_ENABLED_BY_DEFAULT}; +const base::Feature kDragToSnapInClamshellMode{ + "DragToSnapInClamshellMode", base::FEATURE_DISABLED_BY_DEFAULT}; + const base::Feature kEnableOverviewRoundedCorners{ "EnableOverviewRoundedCorners", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/ash/public/cpp/ash_features.h b/ash/public/cpp/ash_features.h index 740cc81d..c0b5b8d 100644 --- a/ash/public/cpp/ash_features.h +++ b/ash/public/cpp/ash_features.h
@@ -16,6 +16,10 @@ // https://crbug.com/709824. ASH_PUBLIC_EXPORT extern const base::Feature kDockedMagnifier; +// Enables dragging and snapping an overview window in clamshell mode. +// TODO(crbug.com/890029): Remove this when the feature is fully launched. +ASH_PUBLIC_EXPORT extern const base::Feature kDragToSnapInClamshellMode; + // Enables rounded corners in overview mode for testing. // TODO(crbug.com/903486): Remove this when new rounded corners implementation // has landed.
diff --git a/ash/wm/overview/overview_controller.cc b/ash/wm/overview/overview_controller.cc index 19348b5..6e72052 100644 --- a/ash/wm/overview/overview_controller.cc +++ b/ash/wm/overview/overview_controller.cc
@@ -326,8 +326,9 @@ if (IsSelecting()) { // Do not allow ending overview if we're in single split mode unless swiping - // up from the shelf. - if (windows.empty() && Shell::Get()->IsSplitViewModeActive() && + // up from the shelf in tablet mode. + if (windows.empty() && + Shell::Get()->split_view_controller()->InTabletSplitViewMode() && type != OverviewSession::EnterExitOverviewType::kSwipeFromShelf) { return true; }
diff --git a/ash/wm/overview/overview_session.cc b/ash/wm/overview/overview_session.cc index 849f793..c8622b9 100644 --- a/ash/wm/overview/overview_session.cc +++ b/ash/wm/overview/overview_session.cc
@@ -9,6 +9,7 @@ #include <utility> #include "ash/accessibility/accessibility_controller.h" +#include "ash/app_list/app_list_controller_impl.h" #include "ash/metrics/user_metrics_recorder.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/screen_util.h" @@ -350,7 +351,7 @@ // not active. Set |index| to -1 so that it does not attempt to select any // items. index = -1; - if (!Shell::Get()->IsSplitViewModeActive()) { + if (!Shell::Get()->split_view_controller()->InTabletSplitViewMode()) { for (const auto& grid : grid_list_) grid->Shutdown(); grid_list_.clear(); @@ -760,6 +761,15 @@ } void OverviewSession::OnKeyEvent(ui::KeyEvent* event) { + // If app list is open when overview is active (it can happen in clamshell + // mode, when we snap an overview window to one side of the screen and then + // open the app list to select an app to snap to the other side), in this case + // we let the app list to handle the key event. + // TODO(crbug.com/952315): Explore better ways to handle this splitview + + // overview + applist case. + if (Shell::Get()->app_list_controller()->IsVisible()) + return; + if (event->type() != ui::ET_KEY_PRESSED) return; @@ -831,6 +841,10 @@ void OverviewSession::OnSplitViewStateChanged( SplitViewController::State previous_state, SplitViewController::State state) { + // Do nothing if overview is being shutdown. + if (!Shell::Get()->overview_controller()->IsSelecting()) + return; + const bool unsnappable_window_activated = state == SplitViewController::NO_SNAP && Shell::Get()->split_view_controller()->end_reason() == @@ -842,9 +856,12 @@ ResetFocusRestoreWindow(false); // If two windows were snapped to both sides of the screen or an unsnappable - // window was just activated, end overview mode and bail out. + // window was just activated, or we're in single split mode in clamshell mode + // and there is no window in overview, end overview mode and bail out. if (state == SplitViewController::BOTH_SNAPPED || - unsnappable_window_activated) { + unsnappable_window_activated || + (Shell::Get()->split_view_controller()->InClamshellSplitViewMode() && + IsEmpty())) { CancelSelection(); return; }
diff --git a/ash/wm/overview/overview_session_unittest.cc b/ash/wm/overview/overview_session_unittest.cc index 42a0c1d..d99dbf3 100644 --- a/ash/wm/overview/overview_session_unittest.cc +++ b/ash/wm/overview/overview_session_unittest.cc
@@ -2840,6 +2840,7 @@ EXPECT_FALSE(IsSelecting()); } +// Test the split view and overview functionalities in tablet mode. class SplitViewOverviewSessionTest : public OverviewSessionTest { public: SplitViewOverviewSessionTest() = default; @@ -4191,4 +4192,292 @@ EXPECT_FALSE(IsSelecting()); } +// Test the split view and overview functionalities in clamshell mode. Split +// view is only active when overview is active in clamshell mode. +class SplitViewOverviewSessionInClamshellTest + : public SplitViewOverviewSessionTest { + public: + SplitViewOverviewSessionInClamshellTest() = default; + ~SplitViewOverviewSessionInClamshellTest() override = default; + + // AshTestBase: + void SetUp() override { + scoped_feature_list_.InitAndEnableFeature( + ash::features::kDragToSnapInClamshellMode); + OverviewSessionTest::SetUp(); + Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager( + false); + DCHECK(ShouldAllowSplitView()); + } + + aura::Window* CreateWindowWithHitTestComponent(int hit_test_component, + const gfx::Rect& bounds) { + return CreateTestWindowInShellWithDelegate( + new TestWindowHitTestDelegate(hit_test_component), 0, bounds); + } + + private: + class TestWindowHitTestDelegate : public aura::test::TestWindowDelegate { + public: + explicit TestWindowHitTestDelegate(int hit_test_component) { + set_window_component(hit_test_component); + } + ~TestWindowHitTestDelegate() override = default; + + private: + // aura::Test::TestWindowDelegate: + void OnWindowDestroyed(aura::Window* window) override { delete this; } + + DISALLOW_COPY_AND_ASSIGN(TestWindowHitTestDelegate); + }; + + base::test::ScopedFeatureList scoped_feature_list_; + DISALLOW_COPY_AND_ASSIGN(SplitViewOverviewSessionInClamshellTest); +}; + +// Test some basic functionalities in clamshell splitview mode. +TEST_F(SplitViewOverviewSessionInClamshellTest, BasicFunctionalitiesTest) { + UpdateDisplay("600x400"); + EXPECT_FALSE(Shell::Get() + ->tablet_mode_controller() + ->IsTabletModeWindowManagerEnabled()); + + // 1. Test the 1 window scenario. + const gfx::Rect bounds(400, 400); + std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); + wm::WindowState* window_state1 = wm::GetWindowState(window1.get()); + EXPECT_FALSE(window_state1->IsSnapped()); + ToggleOverview(); + EXPECT_TRUE(overview_controller()->IsSelecting()); + EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive()); + // Drag |window1| selector item to snap to left. + const int grid_index = 0; + OverviewItem* overview_item1 = + GetWindowItemForWindow(grid_index, window1.get()); + DragWindowTo(overview_item1, gfx::PointF(0, 0)); + // Since the only window is snapped, overview and splitview should be both + // ended. + EXPECT_EQ(window_state1->GetStateType(), + mojom::WindowStateType::LEFT_SNAPPED); + EXPECT_FALSE(overview_controller()->IsSelecting()); + EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive()); + + // 2. Test if one window is snapped, the other windows are showing in + // overview, close all windows in overview will end overview and also + // splitview. + std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); + ToggleOverview(); + EXPECT_TRUE(overview_controller()->IsSelecting()); + EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive()); + overview_item1 = GetWindowItemForWindow(grid_index, window1.get()); + DragWindowTo(overview_item1, gfx::PointF(600, 300)); + // SplitView and overview are both active at the moment. + EXPECT_TRUE(overview_controller()->IsSelecting()); + EXPECT_TRUE(split_view_controller()->IsSplitViewModeActive()); + EXPECT_TRUE(split_view_controller()->IsWindowInSplitView(window1.get())); + EXPECT_TRUE(overview_controller()->overview_session()->IsWindowInOverview( + window2.get())); + EXPECT_EQ(window_state1->GetStateType(), + mojom::WindowStateType::RIGHT_SNAPPED); + // Close |window2| will end overview and splitview. + window2.reset(); + EXPECT_FALSE(overview_controller()->IsSelecting()); + EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive()); + + // 3. Test that snap 2 windows will end overview and splitview. + std::unique_ptr<aura::Window> window3(CreateWindow(bounds)); + ToggleOverview(); + overview_item1 = GetWindowItemForWindow(grid_index, window1.get()); + DragWindowTo(overview_item1, gfx::PointF(0, 0)); + OverviewItem* overview_item3 = + GetWindowItemForWindow(grid_index, window3.get()); + DragWindowTo(overview_item3, gfx::PointF(600, 300)); + EXPECT_EQ(window_state1->GetStateType(), + mojom::WindowStateType::LEFT_SNAPPED); + EXPECT_EQ(wm::GetWindowState(window3.get())->GetStateType(), + mojom::WindowStateType::RIGHT_SNAPPED); + EXPECT_FALSE(overview_controller()->IsSelecting()); + EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive()); + + // 4. Test if one window is snapped, the other windows are showing in + // overview, we can drag another window in overview to snap in splitview, and + // the previous snapped window will not be put back into overview. + std::unique_ptr<aura::Window> window4(CreateWindow(bounds)); + ToggleOverview(); + overview_item1 = GetWindowItemForWindow(grid_index, window1.get()); + DragWindowTo(overview_item1, gfx::PointF(0, 0)); + EXPECT_FALSE(overview_controller()->overview_session()->IsWindowInOverview( + window1.get())); + overview_item3 = GetWindowItemForWindow(grid_index, window3.get()); + DragWindowTo(overview_item3, gfx::PointF(0, 0)); + EXPECT_FALSE(overview_controller()->overview_session()->IsWindowInOverview( + window3.get())); + EXPECT_FALSE(overview_controller()->overview_session()->IsWindowInOverview( + window1.get())); + EXPECT_EQ(window_state1->GetStateType(), + mojom::WindowStateType::LEFT_SNAPPED); + EXPECT_EQ(wm::GetWindowState(window3.get())->GetStateType(), + mojom::WindowStateType::LEFT_SNAPPED); + EXPECT_TRUE(overview_controller()->IsSelecting()); + EXPECT_TRUE(split_view_controller()->IsSplitViewModeActive()); + ToggleOverview(); + EXPECT_EQ(wm::GetWindowState(window4.get())->GetStateType(), + mojom::WindowStateType::RIGHT_SNAPPED); + EXPECT_FALSE(overview_controller()->IsSelecting()); + EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive()); + + // 5. Test if one window is snapped, the other window are showing in overview, + // activating an new window will open in splitview, which ends splitview and + // overview. + ToggleOverview(); + overview_item1 = GetWindowItemForWindow(grid_index, window1.get()); + DragWindowTo(overview_item1, gfx::PointF(0, 0)); + EXPECT_TRUE(overview_controller()->IsSelecting()); + EXPECT_TRUE(split_view_controller()->IsSplitViewModeActive()); + std::unique_ptr<aura::Window> window5(CreateWindow(bounds)); + wm::ActivateWindow(window5.get()); + EXPECT_FALSE(overview_controller()->IsSelecting()); + EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive()); + + // 6. Test if one window is snapped, the other window is showing in overview, + // close the snapped window will end split view, but overview is still active. + ToggleOverview(); + const gfx::Rect overview_bounds = GetGridBounds(); + overview_item1 = GetWindowItemForWindow(grid_index, window1.get()); + DragWindowTo(overview_item1, gfx::PointF(0, 0)); + EXPECT_TRUE(overview_controller()->IsSelecting()); + EXPECT_TRUE(split_view_controller()->IsSplitViewModeActive()); + EXPECT_NE(GetGridBounds(), overview_bounds); + EXPECT_EQ(GetGridBounds(), GetSplitViewRightWindowBounds(window1.get())); + window1.reset(); + EXPECT_TRUE(overview_controller()->IsSelecting()); + EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive()); + // Overview bounds will adjust from snapped bounds to fullscreen bounds. + EXPECT_EQ(GetGridBounds(), overview_bounds); +} + +// Test that if app list is visible when overview is open, overview should +// ignore all key events. +TEST_F(SplitViewOverviewSessionInClamshellTest, IgnoreEventsIfApplistVisible) { + const gfx::Rect bounds(400, 400); + std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); + std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); + + // If splitview is not active, open app list when overview is active will + // just end overview. + ToggleOverview(); + // Open app list. + AppListControllerImpl* app_list_controller = + Shell::Get()->app_list_controller(); + app_list_controller->ToggleAppList( + display::Screen::GetScreen()->GetDisplayNearestWindow(window1.get()).id(), + app_list::AppListShowSource::kSearchKey, base::TimeTicks()); + base::RunLoop().RunUntilIdle(); + // Test that app list is open and overview is ended. + EXPECT_TRUE(app_list_controller->IsVisible()); + EXPECT_FALSE(overview_controller()->IsSelecting()); + + ToggleOverview(); + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(app_list_controller->IsVisible()); + const int grid_index = 0; + OverviewItem* overview_item1 = + GetWindowItemForWindow(grid_index, window1.get()); + DragWindowTo(overview_item1, gfx::PointF(0, 0)); + EXPECT_TRUE(overview_controller()->IsSelecting()); + EXPECT_TRUE(split_view_controller()->IsSplitViewModeActive()); + + // Open app list. + app_list_controller->ToggleAppList( + display::Screen::GetScreen()->GetDisplayNearestWindow(window1.get()).id(), + app_list::AppListShowSource::kSearchKey, base::TimeTicks()); + base::RunLoop().RunUntilIdle(); + // Test that app list is open, splitview and overview are both active. + EXPECT_TRUE(app_list_controller->IsVisible()); + EXPECT_TRUE(overview_controller()->IsSelecting()); + EXPECT_TRUE(split_view_controller()->IsSplitViewModeActive()); + + // Send ui::VKEY_ESCAPE should dismiss app list. But splitview and overview + // should still be active. + SendKey(ui::VKEY_ESCAPE); + EXPECT_FALSE(app_list_controller->IsVisible()); + EXPECT_TRUE(overview_controller()->IsSelecting()); + EXPECT_TRUE(split_view_controller()->IsSplitViewModeActive()); + // Send ui::VKEY_ESCAPE should then end overview. + SendKey(ui::VKEY_ESCAPE); + EXPECT_FALSE(overview_controller()->IsSelecting()); + EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive()); +} + +// Test that when overview and splitview are both active, only resize that +// happens on eligible window components will change snapped window bounds and +// overview bounds at the same time. +TEST_F(SplitViewOverviewSessionInClamshellTest, ResizeWindowTest) { + UpdateDisplay("600x400"); + const gfx::Rect bounds(400, 400); + std::unique_ptr<aura::Window> window1( + CreateWindowWithHitTestComponent(HTRIGHT, bounds)); + std::unique_ptr<aura::Window> window2( + CreateWindowWithHitTestComponent(HTLEFT, bounds)); + std::unique_ptr<aura::Window> window3( + CreateWindowWithHitTestComponent(HTTOP, bounds)); + std::unique_ptr<aura::Window> window4( + CreateWindowWithHitTestComponent(HTBOTTOM, bounds)); + + ToggleOverview(); + const gfx::Rect overview_full_bounds = GetGridBounds(); + const int grid_index = 0; + OverviewItem* overview_item1 = + GetWindowItemForWindow(grid_index, window1.get()); + DragWindowTo(overview_item1, gfx::PointF(0, 0)); + EXPECT_NE(GetGridBounds(), overview_full_bounds); + EXPECT_EQ(GetGridBounds(), GetSplitViewRightWindowBounds(window1.get())); + const gfx::Rect overview_snapped_bounds = GetGridBounds(); + + // Resize that happens on the right edge of the left snapped window will + // resize the window and overview at the same time. + ui::test::EventGenerator generator1(Shell::GetPrimaryRootWindow(), + window1.get()); + generator1.DragMouseBy(50, 50); + EXPECT_TRUE(overview_controller()->IsSelecting()); + EXPECT_TRUE(split_view_controller()->IsSplitViewModeActive()); + EXPECT_NE(GetGridBounds(), overview_full_bounds); + EXPECT_NE(GetGridBounds(), overview_snapped_bounds); + EXPECT_EQ(GetGridBounds(), GetSplitViewRightWindowBounds(window1.get())); + + // Resize that happens on the left edge of the left snapped window will end + // overview. The same for the resize that happens on the top or bottom edge of + // the left snapped window. + OverviewItem* overview_item2 = + GetWindowItemForWindow(grid_index, window2.get()); + DragWindowTo(overview_item2, gfx::PointF(0, 0)); + EXPECT_TRUE(overview_controller()->IsSelecting()); + EXPECT_TRUE(split_view_controller()->IsSplitViewModeActive()); + ui::test::EventGenerator generator2(Shell::GetPrimaryRootWindow(), + window2.get()); + generator2.DragMouseBy(50, 50); + EXPECT_FALSE(overview_controller()->IsSelecting()); + EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive()); + + ToggleOverview(); + OverviewItem* overview_item3 = + GetWindowItemForWindow(grid_index, window3.get()); + DragWindowTo(overview_item3, gfx::PointF(0, 0)); + ui::test::EventGenerator generator3(Shell::GetPrimaryRootWindow(), + window3.get()); + generator3.DragMouseBy(50, 50); + EXPECT_FALSE(overview_controller()->IsSelecting()); + EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive()); + + ToggleOverview(); + OverviewItem* overview_item4 = + GetWindowItemForWindow(grid_index, window4.get()); + DragWindowTo(overview_item4, gfx::PointF(0, 0)); + ui::test::EventGenerator generator4(Shell::GetPrimaryRootWindow(), + window4.get()); + generator4.DragMouseBy(50, 50); + EXPECT_FALSE(overview_controller()->IsSelecting()); + EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive()); +} + } // namespace ash
diff --git a/ash/wm/splitview/split_view_controller.cc b/ash/wm/splitview/split_view_controller.cc index fd252d81..32193e0 100644 --- a/ash/wm/splitview/split_view_controller.cc +++ b/ash/wm/splitview/split_view_controller.cc
@@ -290,6 +290,14 @@ SplitViewController::SplitViewController() { Shell::Get()->accessibility_controller()->AddObserver(this); display::Screen::GetScreen()->AddObserver(this); + Shell::Get()->tablet_mode_controller()->AddObserver(this); + if (IsClamshellSplitViewModeEnabled()) { + split_view_type_ = Shell::Get() + ->tablet_mode_controller() + ->IsTabletModeWindowManagerEnabled() + ? SplitViewType::kTabletType + : SplitViewType::kClamshellType; + } } SplitViewController::~SplitViewController() { @@ -304,7 +312,15 @@ } bool SplitViewController::IsSplitViewModeActive() const { - return state_ != NO_SNAP; + return InClamshellSplitViewMode() || InTabletSplitViewMode(); +} + +bool SplitViewController::InClamshellSplitViewMode() const { + return state_ != NO_SNAP && split_view_type_ == SplitViewType::kClamshellType; +} + +bool SplitViewController::InTabletSplitViewMode() const { + return state_ != NO_SNAP && split_view_type_ == SplitViewType::kTabletType; } void SplitViewController::SnapWindow(aura::Window* window, @@ -328,13 +344,16 @@ Shell::Get()->AddShellObserver(this); Shell::Get()->overview_controller()->AddObserver(this); Shell::Get()->activation_client()->AddObserver(this); - Shell::Get()->tablet_mode_controller()->AddObserver(this); Shell::Get()->NotifySplitViewModeStarting(); divider_position_ = GetDefaultDividerPosition(window); default_snap_position_ = snap_position; - split_view_divider_ = - std::make_unique<SplitViewDivider>(this, window->GetRootWindow()); + + // There is no divider bar in clamshell splitview mode. + if (split_view_type_ == SplitViewType::kTabletType) { + split_view_divider_ = + std::make_unique<SplitViewDivider>(this, window->GetRootWindow()); + } splitview_start_time_ = base::Time::Now(); } @@ -362,20 +381,28 @@ } StartObserving(window); - // Insert the previous snapped window to overview if overview is active. - if (previous_snapped_window) - InsertWindowToOverview(previous_snapped_window); + if (split_view_type_ == SplitViewType::kTabletType) { + // Insert the previous snapped window to overview if overview is active. + if (previous_snapped_window) + InsertWindowToOverview(previous_snapped_window); - // Update the divider position and window bounds before snapping a new window. - // Since the minimum size of |window| maybe larger than currently bounds in - // |snap_position|. - if (state_ != NO_SNAP) { - divider_position_ = GetClosestFixedDividerPosition(); - UpdateSnappedWindowsAndDividerBounds(); + // Update the divider position and window bounds before snapping a new + // window. Since the minimum size of |window| maybe larger than currently + // bounds in |snap_position|. + if (state_ != NO_SNAP) { + divider_position_ = GetClosestFixedDividerPosition(); + UpdateSnappedWindowsAndDividerBounds(); + } } if (wm::GetWindowState(window)->GetStateType() == GetStateTypeFromSnapPosition(snap_position)) { + // Update its snapped bounds as its bounds may not be the expected snapped + // bounds here. + const wm::WMEvent event((snap_position == LEFT) ? wm::WM_EVENT_SNAP_LEFT + : wm::WM_EVENT_SNAP_RIGHT); + wm::GetWindowState(window)->OnWMEvent(&event); + OnWindowSnapped(window); } else { // Otherwise, try to snap it first. It will be activated later after the @@ -483,9 +510,13 @@ const gfx::Rect work_area_bounds_in_screen = screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer( window); - const gfx::Size divider_size = SplitViewDivider::GetDividerSize( - work_area_bounds_in_screen, GetCurrentScreenOrientation(), - false /* is_dragging */); + gfx::Size divider_size; + // In clamshell mode, there is no divider bar, thus divider_size is empty. + if (split_view_type_ == SplitViewType::kTabletType) { + divider_size = SplitViewDivider::GetDividerSize( + work_area_bounds_in_screen, GetCurrentScreenOrientation(), + false /* is_dragging */); + } if (IsCurrentScreenOrientationLandscape()) return (work_area_bounds_in_screen.width() - divider_size.width()) * 0.5f; else @@ -633,7 +664,6 @@ Shell::Get()->RemoveShellObserver(this); Shell::Get()->overview_controller()->RemoveObserver(this); Shell::Get()->activation_client()->RemoveObserver(this); - Shell::Get()->tablet_mode_controller()->RemoveObserver(this); StopObserving(LEFT); StopObserving(RIGHT); @@ -661,7 +691,7 @@ OnSnappedWindowDetached(dragged_window, /*window_drag=*/true); // OnSnappedWindowDetached() may end split view mode. - if (IsSplitViewModeActive()) + if (split_view_divider_) split_view_divider_->OnWindowDragStarted(dragged_window); } @@ -722,6 +752,97 @@ } } +void SplitViewController::OnWindowBoundsChanged( + aura::Window* window, + const gfx::Rect& old_bounds, + const gfx::Rect& new_bounds, + ui::PropertyChangeReason reason) { + if (!IsSplitViewModeActive()) + return; + + if (split_view_type_ == SplitViewType::kClamshellType && + reason == ui::PropertyChangeReason::NOT_FROM_ANIMATION) { + const gfx::Rect work_area = + screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer( + window); + const bool is_left_or_top_window = + IsCurrentScreenOrientationPrimary() + ? (window == left_window_ ? true : false) + : (window == left_window_ ? false : true); + if (IsCurrentScreenOrientationLandscape()) { + divider_position_ = is_left_or_top_window + ? new_bounds.width() + : work_area.width() - new_bounds.width(); + } else { + divider_position_ = is_left_or_top_window + ? new_bounds.height() + : work_area.height() - new_bounds.height(); + } + NotifyDividerPositionChanged(); + } +} + +void SplitViewController::OnResizeLoopStarted(aura::Window* window) { + if (split_view_type_ != SplitViewType::kClamshellType || + !IsSplitViewModeActive()) { + return; + } + + const int resize_component = + wm::GetWindowState(window)->drag_details()->window_component; + const OrientationLockType orientation_type = GetCurrentScreenOrientation(); + + // In clamshell mode, if splitview is active (which means overview is active + // at the same time), only the resize that happens on the window edge that's + // next to the overview grid will resize the window and overview grid at the + // same time. For the resize that happens on the other part of the window, + // we'll just end splitview and overview mode. + bool should_end_splitview = true; + switch (orientation_type) { + case OrientationLockType::kLandscapePrimary: + should_end_splitview = + !(window == left_window_ && resize_component == HTRIGHT) && + !(window == right_window_ && resize_component == HTLEFT); + break; + case OrientationLockType::kLandscapeSecondary: + should_end_splitview = + !(window == left_window_ && resize_component == HTLEFT) && + !(window == right_window_ && resize_component == HTRIGHT); + break; + case OrientationLockType::kPortraitPrimary: + should_end_splitview = + !(window == left_window_ && resize_component == HTBOTTOM) && + !(window == right_window_ && resize_component == HTTOP); + break; + case OrientationLockType::kPortraitSecondary: + should_end_splitview = + !(window == left_window_ && resize_component == HTTOP) && + !(window == right_window_ && resize_component == HTBOTTOM); + break; + default: + break; + } + + if (should_end_splitview) { + EndSplitView(); + EndOverview(); + } +} + +void SplitViewController::OnResizeLoopEnded(aura::Window* window) { + if (split_view_type_ != SplitViewType::kClamshellType || + !IsSplitViewModeActive()) { + return; + } + + if (divider_position_ < GetDividerEndPosition() * kOneThirdPositionRatio || + divider_position_ > GetDividerEndPosition() * kTwoThirdPositionRatio) { + EndSplitView(); + EndOverview(); + wm::GetWindowState(window)->Maximize(); + } +} + void SplitViewController::OnPostWindowStateTypeChange( ash::wm::WindowState* window_state, ash::mojom::WindowStateType old_type) { @@ -844,8 +965,13 @@ OverviewGrid* current_grid = overview_session->GetGridWithRootWindow(root_window); - if (!current_grid) + if (!current_grid || current_grid->empty()) { + // If overview is ended with an empty overview grid, end split view as well + // if we're in clamshell splitview mode. + if (InClamshellSplitViewMode()) + EndSplitView(); return; + } // If split view mode is active but only has one snapped window when overview // mode is ending, retrieve the first snappable window in the overview window @@ -949,10 +1075,20 @@ UpdateSnappedWindowsAndDividerBounds(); } +void SplitViewController::OnTabletModeStarted() { + split_view_type_ = SplitViewType::kTabletType; +} + void SplitViewController::OnTabletModeEnding() { + if (IsClamshellSplitViewModeEnabled()) + split_view_type_ = SplitViewType::kClamshellType; EndSplitView(); } +void SplitViewController::OnTabletControllerDestroyed() { + tablet_mode_observer_.RemoveAll(); +} + void SplitViewController::OnAccessibilityStatusChanged() { // TODO(crubg.com/853588): Exit split screen if ChromeVox is turned on until // they are compatible. @@ -965,7 +1101,8 @@ Shell::Get()->shadow_controller()->UpdateShadowForWindow(window); window->AddObserver(this); wm::GetWindowState(window)->AddObserver(this); - split_view_divider_->AddObservedWindow(window); + if (split_view_divider_) + split_view_divider_->AddObservedWindow(window); } } @@ -979,7 +1116,8 @@ if (window && window->HasObserver(this)) { window->RemoveObserver(this); wm::GetWindowState(window)->RemoveObserver(this); - split_view_divider_->RemoveObservedWindow(window); + if (split_view_divider_) + split_view_divider_->RemoveObservedWindow(window); Shell::Get()->shadow_controller()->UpdateShadowForWindow(window); } } @@ -1076,7 +1214,8 @@ } // Update divider's bounds. - split_view_divider_->UpdateDividerBounds(); + if (split_view_divider_) + split_view_divider_->UpdateDividerBounds(); } SplitViewController::SnapPosition SplitViewController::GetBlackScrimPosition( @@ -1153,9 +1292,17 @@ divider_position_ = (divider_position_ < 0) ? GetDefaultDividerPosition(window) : divider_position_; - const gfx::Rect divider_bounds = SplitViewDivider::GetDividerBoundsInScreen( - work_area_bounds_in_screen, GetCurrentScreenOrientation(), - divider_position_, false /* is_dragging */); + gfx::Rect divider_bounds; + if (split_view_type_ == SplitViewType::kTabletType) { + divider_bounds = SplitViewDivider::GetDividerBoundsInScreen( + work_area_bounds_in_screen, GetCurrentScreenOrientation(), + divider_position_, false /* is_dragging */); + } else { + if (IsCurrentScreenOrientationLandscape()) + divider_bounds.set_x(work_area_bounds_in_screen.x() + divider_position_); + else + divider_bounds.set_y(work_area_bounds_in_screen.y() + divider_position_); + } SplitRect(work_area_bounds_in_screen, divider_bounds, IsCurrentScreenOrientationLandscape(), left_or_top_rect, @@ -1285,6 +1432,12 @@ RestoreTransformIfApplicable(window); UpdateSplitViewStateAndNotifyObservers(); ActivateAndStackSnappedWindow(window); + + // If there are two window snapped in clamshell mode, splitview mode is ended. + if (state_ == BOTH_SNAPPED && + split_view_type_ == SplitViewType::kClamshellType) { + EndSplitView(); + } } void SplitViewController::OnSnappedWindowDetached(aura::Window* window, @@ -1653,7 +1806,7 @@ bool is_being_destroyed, SnapPosition desired_snap_position, const gfx::Point& last_location_in_screen) { - if (IsSplitViewModeActive()) + if (split_view_divider_) split_view_divider_->OnWindowDragEnded(); // If the dragged window is to be destroyed, do not try to snap it.
diff --git a/ash/wm/splitview/split_view_controller.h b/ash/wm/splitview/split_view_controller.h index 258bb0b..9f52e418 100644 --- a/ash/wm/splitview/split_view_controller.h +++ b/ash/wm/splitview/split_view_controller.h
@@ -13,6 +13,7 @@ #include "ash/public/interfaces/split_view.mojom.h" #include "ash/shell_observer.h" #include "ash/wm/overview/overview_observer.h" +#include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "ash/wm/tablet_mode/tablet_mode_observer.h" #include "ash/wm/window_state_observer.h" #include "base/containers/flat_map.h" @@ -76,6 +77,19 @@ kPipExpanded, }; + // The behaviors of split view are very different when in tablet mode and in + // clamshell mode. In tablet mode, split view mode will stay active until the + // user explicitly ends it (e.g., by pressing home launcher, or long pressing + // the overview button, or sliding the divider bar to the edge, etc). However, + // in clamshell mode, there is no divider bar, and split view mode only stays + // active during overview snapping, i.e., it's only possible that split view + // is active when overview is active. Once the user has selected two windows + // to snap to both side of the screen, split view mode is no longer active. + enum class SplitViewType { + kTabletType = 0, + kClamshellType, + }; + class Observer { public: // Called when split view state changed from |previous_state| to |state|. @@ -93,8 +107,12 @@ // Binds the mojom::SplitViewController interface to this object. void BindRequest(mojom::SplitViewControllerRequest request); - // Returns true if split view mode is active. + // Returns true if split view mode is active. Please see SplitViewType above + // to see the difference between tablet mode and clamshell mode splitview + // mode. bool IsSplitViewModeActive() const; + bool InClamshellSplitViewMode() const; + bool InTabletSplitViewMode() const; // Snaps window to left/right. It will try to remove |window| from the // overview window grid first before snapping it if |window| is currently @@ -151,6 +169,12 @@ void OnWindowDragEnded(aura::Window* dragged_window, SnapPosition desired_snap_position, const gfx::Point& last_location_in_screen); + void OnWindowBoundsChanged(aura::Window* window, + const gfx::Rect& old_bounds, + const gfx::Rect& new_bounds, + ui::PropertyChangeReason reason) override; + void OnResizeLoopStarted(aura::Window* window) override; + void OnResizeLoopEnded(aura::Window* window) override; void AddObserver(Observer* observer); void RemoveObserver(Observer* observer); @@ -188,7 +212,9 @@ uint32_t metrics) override; // TabletModeObserver: + void OnTabletModeStarted() override; void OnTabletModeEnding() override; + void OnTabletControllerDestroyed() override; // AccessibilityObserver: void OnAccessibilityStatusChanged() override; @@ -389,10 +415,10 @@ aura::Window* left_window_ = nullptr; aura::Window* right_window_ = nullptr; - // Split view divider widget. It's a black bar stretching from one edge of the - // screen to the other, containing a small white drag bar in the middle. As - // the user presses on it and drag it to left or right, the left and right - // window will be resized accordingly. + // Split view divider widget. Only exist in tablet splitview mode. It's a + // black bar stretching from one edge of the screen to the other, containing a + // small white drag bar in the middle. As the user presses on it and drag it + // to left or right, the left and right window will be resized accordingly. std::unique_ptr<SplitViewDivider> split_view_divider_; // A black scrim layer that fades in over a window when it’s width drops under @@ -400,7 +426,7 @@ // closer to the edge of the screen. std::unique_ptr<ui::Layer> black_scrim_layer_; - // The window observer that obseves the tab-dragged window. + // The window observer that obseves the tab-dragged window in tablet mode. std::unique_ptr<TabDraggedWindowObserver> dragged_window_observer_; // The distance between the origin of the divider and the origin of the @@ -443,6 +469,10 @@ // Stores the reason which cause splitview to end. EndReason end_reason_ = EndReason::kNormal; + // The split view type. See SplitViewType for the differences between tablet + // split view and clamshell split view. + SplitViewType split_view_type_ = SplitViewType::kTabletType; + // The time when splitview starts. Used for metric collection purpose. base::Time splitview_start_time_; @@ -453,6 +483,9 @@ base::ObserverList<Observer>::Unchecked observers_; mojo::InterfacePtrSet<mojom::SplitViewObserver> mojo_observers_; + ScopedObserver<TabletModeController, TabletModeObserver> + tablet_mode_observer_{this}; + // Records the presentation time of resize operation in split view mode. std::unique_ptr<PresentationTimeRecorder> presentation_time_recorder_;
diff --git a/ash/wm/splitview/split_view_utils.cc b/ash/wm/splitview/split_view_utils.cc index 7083610..03afe6b 100644 --- a/ash/wm/splitview/split_view_utils.cc +++ b/ash/wm/splitview/split_view_utils.cc
@@ -5,6 +5,7 @@ #include "ash/wm/splitview/split_view_utils.h" #include "ash/accessibility/accessibility_controller.h" +#include "ash/public/cpp/ash_features.h" #include "ash/public/cpp/ash_switches.h" #include "ash/screen_util.h" #include "ash/shell.h" @@ -217,6 +218,11 @@ layer->SetTransform(target_transform); } +bool IsClamshellSplitViewModeEnabled() { + return base::FeatureList::IsEnabled( + ash::features::kDragToSnapInClamshellMode); +} + bool ShouldAllowSplitView() { if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kAshDisableTabletSplitView)) { @@ -225,7 +231,8 @@ if (!Shell::Get() ->tablet_mode_controller() - ->IsTabletModeWindowManagerEnabled()) { + ->IsTabletModeWindowManagerEnabled() && + !IsClamshellSplitViewModeEnabled()) { return false; }
diff --git a/ash/wm/splitview/split_view_utils.h b/ash/wm/splitview/split_view_utils.h index b64ec1aff..a7e146f 100644 --- a/ash/wm/splitview/split_view_utils.h +++ b/ash/wm/splitview/split_view_utils.h
@@ -79,8 +79,11 @@ SplitviewAnimationType type, const gfx::Transform& target_transform); -// Returns true if split view mode is supported. Currently the split view -// mode is only supported in tablet mode. +// Returns true if we allow dragging an overview window to snap to split view in +// clamshell mode. +ASH_EXPORT bool IsClamshellSplitViewModeEnabled(); + +// Returns true if split view mode is supported. ASH_EXPORT bool ShouldAllowSplitView(); // Returns true if |window| can be activated and snapped in split screen in
diff --git a/ash/wm/window_util.cc b/ash/wm/window_util.cc index a2d18106..5a086f7 100644 --- a/ash/wm/window_util.cc +++ b/ash/wm/window_util.cc
@@ -363,14 +363,15 @@ } bool ShouldExcludeForOverview(const aura::Window* window) { - // Remove the default snapped window from the window list. The default - // snapped window occupies one side of the screen, while the other windows - // occupy the other side of the screen in overview mode. The default snap - // position is the position where the window was first snapped. See - // |default_snap_position_| in SplitViewController for more detail. - if (Shell::Get()->IsSplitViewModeActive() && - window == - Shell::Get()->split_view_controller()->GetDefaultSnappedWindow()) { + // If we're currently in tablet splitview, remove the default snapped window + // from the window list. The default snapped window occupies one side of the + // screen, while the other windows occupy the other side of the screen in + // overview mode. The default snap position is the position where the window + // was first snapped. See |default_snap_position_| in SplitViewController for + // more detail. + auto* split_view_controller = Shell::Get()->split_view_controller(); + if (split_view_controller->InTabletSplitViewMode() && + window == split_view_controller->GetDefaultSnappedWindow()) { return true; }
diff --git a/base/fuchsia/service_directory_client.cc b/base/fuchsia/service_directory_client.cc index 3dc964f..8b5a641a 100644 --- a/base/fuchsia/service_directory_client.cc +++ b/base/fuchsia/service_directory_client.cc
@@ -10,23 +10,12 @@ #include "base/fuchsia/file_utils.h" #include "base/fuchsia/fuchsia_logging.h" #include "base/logging.h" +#include "base/memory/ptr_util.h" #include "base/no_destructor.h" namespace base { namespace fuchsia { -namespace { - -// Singleton container for the process-global ServiceDirectoryClient instance. -std::unique_ptr<ServiceDirectoryClient>* ProcessServiceDirectoryClient() { - static base::NoDestructor<std::unique_ptr<ServiceDirectoryClient>> - service_directory_client_ptr(std::make_unique<ServiceDirectoryClient>( - OpenDirectory(base::FilePath(kServiceDirectoryPath)))); - return service_directory_client_ptr.get(); -} - -} // namespace - ServiceDirectoryClient::ServiceDirectoryClient( fidl::InterfaceHandle<::fuchsia::io::Directory> directory) : directory_(std::move(directory)) { @@ -37,7 +26,7 @@ // static const ServiceDirectoryClient* ServiceDirectoryClient::ForCurrentProcess() { - return ProcessServiceDirectoryClient()->get(); + return ServiceDirectoryClient::ProcessInstance()->get(); } zx_status_t ServiceDirectoryClient::ConnectToServiceUnsafe( @@ -48,19 +37,40 @@ request.release()); } +ServiceDirectoryClient::ServiceDirectoryClient() {} + +// static +std::unique_ptr<ServiceDirectoryClient> +ServiceDirectoryClient::CreateForProcess() { + fidl::InterfaceHandle<::fuchsia::io::Directory> directory = + OpenDirectory(base::FilePath(kServiceDirectoryPath)); + if (directory) + return std::make_unique<ServiceDirectoryClient>(std::move(directory)); + LOG(WARNING) << "/svc is not available."; + return base::WrapUnique(new ServiceDirectoryClient); +} + +// static +std::unique_ptr<ServiceDirectoryClient>* +ServiceDirectoryClient::ProcessInstance() { + static base::NoDestructor<std::unique_ptr<ServiceDirectoryClient>> + service_directory_client_ptr(CreateForProcess()); + return service_directory_client_ptr.get(); +} + ScopedServiceDirectoryClientForCurrentProcessForTest:: ScopedServiceDirectoryClientForCurrentProcessForTest( fidl::InterfaceHandle<::fuchsia::io::Directory> directory) - : old_client_(std::move(*ProcessServiceDirectoryClient())) { - *ProcessServiceDirectoryClient() = + : old_client_(std::move(*ServiceDirectoryClient::ProcessInstance())) { + *ServiceDirectoryClient::ProcessInstance() = std::make_unique<ServiceDirectoryClient>(std::move(directory)); - client_ = ProcessServiceDirectoryClient()->get(); + client_ = ServiceDirectoryClient::ProcessInstance()->get(); } ScopedServiceDirectoryClientForCurrentProcessForTest:: ~ScopedServiceDirectoryClientForCurrentProcessForTest() { - DCHECK_EQ(ProcessServiceDirectoryClient()->get(), client_); - *ProcessServiceDirectoryClient() = std::move(old_client_); + DCHECK_EQ(ServiceDirectoryClient::ProcessInstance()->get(), client_); + *ServiceDirectoryClient::ProcessInstance() = std::move(old_client_); } } // namespace fuchsia
diff --git a/base/fuchsia/service_directory_client.h b/base/fuchsia/service_directory_client.h index c2f9603..8342b772 100644 --- a/base/fuchsia/service_directory_client.h +++ b/base/fuchsia/service_directory_client.h
@@ -25,6 +25,8 @@ namespace base { namespace fuchsia { +class ScopedServiceDirectoryClientForCurrentProcessForTest; + // Helper for connecting to services from a supplied fuchsia.io.Directory. class BASE_EXPORT ServiceDirectoryClient { public: @@ -69,6 +71,18 @@ zx::channel request) const; private: + friend class ScopedServiceDirectoryClientForCurrentProcessForTest; + ServiceDirectoryClient(); + + // Creates a ServiceDirectoryClient connected to the process' "/svc" + // directory, or a dummy instance if the "/svc" directory is not available. + static std::unique_ptr<ServiceDirectoryClient> CreateForProcess(); + + // Returns the container holding the ForCurrentProcess() instance. The + // default ServiceDirectoryClient is created the first time this function is + // called. + static std::unique_ptr<ServiceDirectoryClient>* ProcessInstance(); + const fidl::InterfaceHandle<::fuchsia::io::Directory> directory_; DISALLOW_COPY_AND_ASSIGN(ServiceDirectoryClient);
diff --git a/base/process/launch_posix.cc b/base/process/launch_posix.cc index a81a031b..9b7573f 100644 --- a/base/process/launch_posix.cc +++ b/base/process/launch_posix.cc
@@ -575,16 +575,20 @@ // Adding another element here? Remeber to increase the argument to // reserve(), above. - for (const auto& i : fd_shuffle1) - fd_shuffle2.push_back(i); + // Cannot use STL iterators here, since debug iterators use locks. + // NOLINTNEXTLINE(modernize-loop-convert) + for (size_t i = 0; i < fd_shuffle1.size(); ++i) + fd_shuffle2.push_back(fd_shuffle1[i]); if (!ShuffleFileDescriptors(&fd_shuffle1)) _exit(127); CloseSuperfluousFds(fd_shuffle2); - for (const auto& arg : argv) - argv_cstr.push_back(const_cast<char*>(arg.c_str())); + // Cannot use STL iterators here, since debug iterators use locks. + // NOLINTNEXTLINE(modernize-loop-convert) + for (size_t i = 0; i < argv.size(); ++i) + argv_cstr.push_back(const_cast<char*>(argv[i].c_str())); argv_cstr.push_back(nullptr); if (do_search_path)
diff --git a/build/android/binary_size/apk_downloader.py b/build/android/binary_size/apk_downloader.py index 83f7918c..aa7d12f 100755 --- a/build/android/binary_size/apk_downloader.py +++ b/build/android/binary_size/apk_downloader.py
@@ -15,8 +15,8 @@ sys.path.append(os.path.join(_BUILD_ANDROID, 'gyp')) from util import build_utils -sys.path.append(os.path.join(host_paths.DIR_SOURCE_ROOT, 'build')) -import find_depot_tools # pylint: disable=import-error,unused-import +sys.path.append( + os.path.join(host_paths.DIR_SOURCE_ROOT, 'third_party', 'depot_tools')) import download_from_google_storage import upload_to_google_storage
diff --git a/build/android/gradle/generate_gradle.py b/build/android/gradle/generate_gradle.py index 9ccf5ac..f2bcec5 100755 --- a/build/android/gradle/generate_gradle.py +++ b/build/android/gradle/generate_gradle.py
@@ -29,9 +29,8 @@ import jinja_template from util import build_utils -sys.path.append(os.path.join(host_paths.DIR_SOURCE_ROOT, 'build')) -import find_depot_tools # pylint: disable=import-error - +_DEPOT_TOOLS_PATH = os.path.join(host_paths.DIR_SOURCE_ROOT, 'third_party', + 'depot_tools') _DEFAULT_ANDROID_MANIFEST_PATH = os.path.join( host_paths.DIR_SOURCE_ROOT, 'build', 'android', 'gradle', 'AndroidManifest.xml') @@ -114,9 +113,9 @@ def _RunGnGen(output_dir, args=None): cmd = [ - os.path.join(find_depot_tools.DEPOT_TOOLS_PATH, 'gn'), - 'gen', - output_dir, + os.path.join(_DEPOT_TOOLS_PATH, 'gn'), + 'gen', + output_dir, ] if args: cmd.extend(args) @@ -126,10 +125,10 @@ def _RunNinja(output_dir, args, j): cmd = [ - os.path.join(find_depot_tools.DEPOT_TOOLS_PATH, 'ninja'), - '-C', - output_dir, - '-j{}'.format(j), + os.path.join(_DEPOT_TOOLS_PATH, 'ninja'), + '-C', + output_dir, + '-j{}'.format(j), ] cmd.extend(args) logging.info('Running: %r', cmd) @@ -139,11 +138,11 @@ def _QueryForAllGnTargets(output_dir): # Query ninja rather than GN since it's faster. cmd = [ - os.path.join(find_depot_tools.DEPOT_TOOLS_PATH, 'ninja'), - '-C', - output_dir, - '-t', - 'targets', + os.path.join(_DEPOT_TOOLS_PATH, 'ninja'), + '-C', + output_dir, + '-t', + 'targets', ] logging.info('Running: %r', cmd) ninja_output = build_utils.CheckOutput(cmd)
diff --git a/build/android/resource_sizes.pydeps b/build/android/resource_sizes.pydeps index d071d12..7c075c2 100644 --- a/build/android/resource_sizes.pydeps +++ b/build/android/resource_sizes.pydeps
@@ -44,11 +44,9 @@ ../../third_party/catapult/tracing/tracing/value/__init__.py ../../third_party/catapult/tracing/tracing/value/convert_chart_json.py ../../third_party/catapult/tracing/tracing_project.py -../../third_party/depot_tools/breakpad.py ../../third_party/depot_tools/download_from_google_storage.py ../../third_party/depot_tools/subprocess2.py ../../third_party/depot_tools/upload_to_google_storage.py -../find_depot_tools.py ../gn_helpers.py ../util/lib/common/perf_result_data_type.py ../util/lib/common/perf_tests_results_helper.py
diff --git a/build/android/update_deps/update_third_party_deps.py b/build/android/update_deps/update_third_party_deps.py index 5351d5c..3a869c4 100755 --- a/build/android/update_deps/update_third_party_deps.py +++ b/build/android/update_deps/update_third_party_deps.py
@@ -20,9 +20,9 @@ from pylib import constants from pylib.constants import host_paths -sys.path.append(os.path.abspath( - os.path.join(host_paths.DIR_SOURCE_ROOT, 'build'))) -import find_depot_tools # pylint: disable=import-error,unused-import +sys.path.append( + os.path.abspath( + os.path.join(host_paths.DIR_SOURCE_ROOT, 'third_party', 'depot_tools'))) import download_from_google_storage import upload_to_google_storage
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index 546b0272..0f89ce3 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -8916443031887960288 \ No newline at end of file +8916269455106018432 \ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index cc92c7a8..80b9e33a 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -8916474687955919136 \ No newline at end of file +8916272757229952512 \ No newline at end of file
diff --git a/chrome/VERSION b/chrome/VERSION index 98b5f48..7e1fa72 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=75 MINOR=0 -BUILD=3764 +BUILD=3766 PATCH=0
diff --git a/chrome/android/java/res/color/item_chooser_row_icon_color.xml b/chrome/android/java/res/color/item_chooser_row_icon_color.xml index 4d608a16..fe24d39 100644 --- a/chrome/android/java/res/color/item_chooser_row_icon_color.xml +++ b/chrome/android/java/res/color/item_chooser_row_icon_color.xml
@@ -4,7 +4,7 @@ found in the LICENSE file. --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:color="@android:color/white" android:state_selected="true"/> - <item android:color="@color/primary_text_disabled_material_light" android:state_enabled="false"/> + <item android:color="@color/default_icon_color_inverse" android:state_selected="true"/> + <item android:color="@color/default_icon_color_disabled" android:state_enabled="false"/> <item android:color="@color/default_icon_color"/> </selector>
diff --git a/chrome/android/java/res/color/item_chooser_row_text_color.xml b/chrome/android/java/res/color/item_chooser_row_text_color.xml index bb8c05c..b625ef51 100644 --- a/chrome/android/java/res/color/item_chooser_row_text_color.xml +++ b/chrome/android/java/res/color/item_chooser_row_text_color.xml
@@ -4,7 +4,7 @@ found in the LICENSE file. --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:color="@android:color/white" android:state_selected="true"/> - <item android:color="@color/primary_text_disabled_material_light" android:state_enabled="false"/> + <item android:color="@color/default_text_color_inverse" android:state_selected="true"/> + <item android:color="@color/disabled_text_color" android:state_enabled="false"/> <item android:color="@color/default_text_color"/> </selector>
diff --git a/chrome/android/java/res/layout/item_chooser_dialog.xml b/chrome/android/java/res/layout/item_chooser_dialog.xml index 080b40a..118a82c2 100644 --- a/chrome/android/java/res/layout/item_chooser_dialog.xml +++ b/chrome/android/java/res/layout/item_chooser_dialog.xml
@@ -9,7 +9,8 @@ android:layout_height="fill_parent" android:orientation="vertical" android:paddingBottom="12dp" - android:paddingTop="20dp" > + android:paddingTop="20dp" + android:background="@color/sheet_bg_color"> <!-- The title at the top. --> <org.chromium.ui.widget.TextViewWithClickableSpans
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/BluetoothChooserDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/BluetoothChooserDialog.java index 9a08e1b..913a37a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/BluetoothChooserDialog.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/BluetoothChooserDialog.java
@@ -185,8 +185,14 @@ // Emphasize the origin. Profile profile = Profile.getLastUsedProfile(); SpannableString origin = new SpannableString(mOrigin); - OmniboxUrlEmphasizer.emphasizeUrl( - origin, mActivity.getResources(), profile, mSecurityLevel, false, true, true); + + assert mActivity instanceof ChromeBaseAppCompatActivity; + final boolean useDarkColors = !((ChromeBaseAppCompatActivity) mActivity) + .getNightModeStateProvider() + .isInNightMode(); + + OmniboxUrlEmphasizer.emphasizeUrl(origin, mActivity.getResources(), profile, mSecurityLevel, + false, useDarkColors, true); // Construct a full string and replace the origin text with emphasized version. SpannableString title = new SpannableString(mActivity.getString(R.string.bluetooth_dialog_title, mOrigin));
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index c17c0a12..0bb9306 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -9557,6 +9557,9 @@ <message name="IDS_WEBAUTHN_SELECT_ACCOUNT_DESC" desc="The description on a dialog where the user is expected to select an account from a list. For example, the list may include several identities, e.g. joe@gmail.com, mary@gmail.com, and the user has to select one to login as."> Select an account to sign in: </message> + <message name="IDS_WEBAUTHN_RESIDENT_KEY_PRIVACY" desc="A message included in dialogs when activating a security key (an external physical device for user authentication) may cause information about a site visit to be recorded on that security key. Since this is a privacy concern, a message is shown to the user."> + This will leave a record of your visit to <ph name="WEBSITE"><ex>accounts.google.com</ex>$1</ph> on your security key. + </message> <message name="IDS_WEBAUTHN_ERROR_MISSING_CAPABILITY_TITLE" desc="Title of the dialog informing the user that the security key (an external physical device for user authentication) that they selected does not support some capability that the site requested."> Your security key can't be used with this site </message>
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index b429d77..a745611 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -2126,12 +2126,6 @@ SINGLE_VALUE_TYPE( ::switches::kEnableExperimentalAccessibilityLanguageDetection)}, #if defined(OS_CHROMEOS) - {"disable-system-timezone-automatic-detection", - flag_descriptions::kDisableSystemTimezoneAutomaticDetectionName, - flag_descriptions::kDisableSystemTimezoneAutomaticDetectionDescription, - kOsCrOS, - SINGLE_VALUE_TYPE( - chromeos::switches::kDisableSystemTimezoneAutomaticDetectionPolicy)}, {"enable-bulk-printers", flag_descriptions::kBulkPrintersName, flag_descriptions::kBulkPrintersDescription, kOsCrOS, FEATURE_VALUE_TYPE(features::kBulkPrinters)},
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 3a6ab133..30d0b980 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -5107,9 +5107,10 @@ std::unique_ptr<content::AuthenticatorRequestClientDelegate> ChromeContentBrowserClient::GetWebAuthenticationRequestDelegate( - content::RenderFrameHost* render_frame_host) { - return AuthenticatorRequestScheduler::CreateRequestDelegate( - render_frame_host); + content::RenderFrameHost* render_frame_host, + const std::string& relying_party_id) { + return AuthenticatorRequestScheduler::CreateRequestDelegate(render_frame_host, + relying_party_id); } #if defined(OS_MACOSX)
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h index 319bd17..138a10e 100644 --- a/chrome/browser/chrome_content_browser_client.h +++ b/chrome/browser/chrome_content_browser_client.h
@@ -516,7 +516,8 @@ base::OnceCallback<void(bool, int, int)> callback) override; std::unique_ptr<content::AuthenticatorRequestClientDelegate> GetWebAuthenticationRequestDelegate( - content::RenderFrameHost* render_frame_host) override; + content::RenderFrameHost* render_frame_host, + const std::string& relying_party_id) override; #if defined(OS_MACOSX) bool IsWebAuthenticationTouchIdAuthenticatorSupported() override; #endif
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index b505f19..1eeec1f 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -1827,6 +1827,8 @@ "printing/enterprise_printers_provider.h", "printing/ppd_provider_factory.cc", "printing/ppd_provider_factory.h", + "printing/ppd_resolution_state.cc", + "printing/ppd_resolution_state.h", "printing/printer_configurer.cc", "printing/printer_configurer.h", "printing/printer_detector.h", @@ -2537,6 +2539,7 @@ "preferences_unittest.cc", "printing/bulk_printers_calculator_unittest.cc", "printing/cups_printers_manager_unittest.cc", + "printing/ppd_resolution_state_unittest.cc", "printing/printer_detector_test_util.h", "printing/printer_event_tracker_unittest.cc", "printing/printers_sync_bridge_unittest.cc",
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_regular.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_regular.cc index a5e6d62..ac69064 100644 --- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_regular.cc +++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_regular.cc
@@ -466,6 +466,7 @@ feature_state_ = it->second; LoadRemoteDevices(); + UpdateAppState(); } void EasyUnlockServiceRegular::ShowChromebookAddedNotification() {
diff --git a/chrome/browser/chromeos/login/reset_browsertest.cc b/chrome/browser/chromeos/login/reset_browsertest.cc index abd9b25..c7a387e4 100644 --- a/chrome/browser/chromeos/login/reset_browsertest.cc +++ b/chrome/browser/chromeos/login/reset_browsertest.cc
@@ -272,8 +272,7 @@ RegisterSomeUser(); } -// Disabled due to flakiness (crbug.com/870284) -IN_PROC_BROWSER_TEST_F(ResetFirstAfterBootTest, DISABLED_RollbackUnavailable) { +IN_PROC_BROWSER_TEST_F(ResetFirstAfterBootTest, RollbackUnavailable) { InvokeResetScreen(); EXPECT_EQ(0, FakePowerManagerClient::Get()->num_request_restart_calls()); EXPECT_EQ(0, FakeSessionManagerClient::Get()->start_device_wipe_call_count());
diff --git a/chrome/browser/chromeos/printing/ppd_resolution_state.cc b/chrome/browser/chromeos/printing/ppd_resolution_state.cc new file mode 100644 index 0000000..c1731f7 --- /dev/null +++ b/chrome/browser/chromeos/printing/ppd_resolution_state.cc
@@ -0,0 +1,61 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/printing/ppd_resolution_state.h" + +#include <string> + +#include "base/logging.h" + +namespace chromeos { + +PpdResolutionState::PpdResolutionState() + : is_inflight_(true), is_ppd_resolution_successful_(false) {} + +PpdResolutionState::~PpdResolutionState() = default; + +void PpdResolutionState::MarkResolutionSuccessful( + const Printer::PpdReference& ppd_reference) { + DCHECK(is_inflight_); + + ppd_reference_ = ppd_reference; + is_inflight_ = false; + is_ppd_resolution_successful_ = true; +} + +void PpdResolutionState::MarkResolutionFailed() { + DCHECK(is_inflight_); + + is_inflight_ = false; + is_ppd_resolution_successful_ = false; +} + +void PpdResolutionState::SetUsbManufacturer( + const std::string& usb_manufacturer) { + DCHECK(!is_inflight_); + DCHECK(!is_ppd_resolution_successful_); + + usb_manufacturer_ = usb_manufacturer; +} + +const Printer::PpdReference& PpdResolutionState::GetPpdReference() const { + DCHECK(!is_inflight_); + DCHECK(is_ppd_resolution_successful_); + return ppd_reference_; +} + +const std::string& PpdResolutionState::GetUsbManufacturer() const { + DCHECK(!is_inflight_); + return usb_manufacturer_; +} + +bool PpdResolutionState::IsInflight() const { + return is_inflight_; +} + +bool PpdResolutionState::WasResolutionSuccessful() const { + return is_ppd_resolution_successful_; +} + +} // namespace chromeos
diff --git a/chrome/browser/chromeos/printing/ppd_resolution_state.h b/chrome/browser/chromeos/printing/ppd_resolution_state.h new file mode 100644 index 0000000..675c050 --- /dev/null +++ b/chrome/browser/chromeos/printing/ppd_resolution_state.h
@@ -0,0 +1,51 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_PRINTING_PPD_RESOLUTION_STATE_H_ +#define CHROME_BROWSER_CHROMEOS_PRINTING_PPD_RESOLUTION_STATE_H_ + +#include <string> + +#include "chromeos/printing/printer_configuration.h" + +namespace chromeos { + +class PpdResolutionState { + public: + PpdResolutionState(); + ~PpdResolutionState(); + + // Marks PPD resolution was successful and stores |ppd_reference|. + void MarkResolutionSuccessful(const Printer::PpdReference& ppd_reference); + + // Marks PPD resolution was unsuccessful. + void MarkResolutionFailed(); + + // Store |usb_manufacturer|. + void SetUsbManufacturer(const std::string& usb_manufacturer); + + // Getter function for |ppd_reference_|. + const Printer::PpdReference& GetPpdReference() const; + + // Getter function for |usb_manufacturer_|. + const std::string& GetUsbManufacturer() const; + + // Returns true if the PPD resolution is inflight. + bool IsInflight() const; + + // Returns true if a PpdReference was retrieved. + bool WasResolutionSuccessful() const; + + private: + bool is_inflight_; + bool is_ppd_resolution_successful_; + Printer::PpdReference ppd_reference_; + std::string usb_manufacturer_; + + DISALLOW_COPY_AND_ASSIGN(PpdResolutionState); +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_PRINTING_PPD_RESOLUTION_STATE_H_
diff --git a/chrome/browser/chromeos/printing/ppd_resolution_state_unittest.cc b/chrome/browser/chromeos/printing/ppd_resolution_state_unittest.cc new file mode 100644 index 0000000..394131f9 --- /dev/null +++ b/chrome/browser/chromeos/printing/ppd_resolution_state_unittest.cc
@@ -0,0 +1,65 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/printing/ppd_resolution_state.h" + +#include "base/macros.h" +#include "chromeos/printing/printer_configuration.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace chromeos { +namespace { + +class PpdResolutionStateTest : public testing::Test { + public: + PpdResolutionStateTest() = default; + ~PpdResolutionStateTest() override = default; + + private: + DISALLOW_COPY_AND_ASSIGN(PpdResolutionStateTest); +}; + +TEST_F(PpdResolutionStateTest, TestDefaultState) { + PpdResolutionState ppd_resolution_state_; + + EXPECT_TRUE(ppd_resolution_state_.IsInflight()); + EXPECT_FALSE(ppd_resolution_state_.WasResolutionSuccessful()); +} + +TEST_F(PpdResolutionStateTest, TestMarkPpdResolutionSucessful) { + PpdResolutionState ppd_resolution_state_; + + const std::string expected_make_and_model = "printer_make_model"; + Printer::PpdReference ppd_ref; + ppd_ref.effective_make_and_model = expected_make_and_model; + + ppd_resolution_state_.MarkResolutionSuccessful(ppd_ref); + + EXPECT_FALSE(ppd_resolution_state_.IsInflight()); + EXPECT_TRUE(ppd_resolution_state_.WasResolutionSuccessful()); + + const Printer::PpdReference ref = ppd_resolution_state_.GetPpdReference(); + + EXPECT_EQ(expected_make_and_model, ref.effective_make_and_model); + EXPECT_TRUE(ref.user_supplied_ppd_url.empty()); + EXPECT_FALSE(ref.autoconf); +} + +TEST_F(PpdResolutionStateTest, TestMarkResolutionFailedAndSetUsbManufacturer) { + PpdResolutionState ppd_resolution_state_; + + ppd_resolution_state_.MarkResolutionFailed(); + + EXPECT_FALSE(ppd_resolution_state_.IsInflight()); + EXPECT_FALSE(ppd_resolution_state_.WasResolutionSuccessful()); + + const std::string expected_usb_manufacturer = "Hewlett-Packard"; + ppd_resolution_state_.SetUsbManufacturer(expected_usb_manufacturer); + + EXPECT_EQ(expected_usb_manufacturer, + ppd_resolution_state_.GetUsbManufacturer()); +} + +} // namespace +} // namespace chromeos
diff --git a/chrome/browser/chromeos/system/timezone_resolver_manager.cc b/chrome/browser/chromeos/system/timezone_resolver_manager.cc index 1430c3f..c01ff5e 100644 --- a/chrome/browser/chromeos/system/timezone_resolver_manager.cc +++ b/chrome/browser/chromeos/system/timezone_resolver_manager.cc
@@ -33,11 +33,6 @@ // SystemTimezoneAutomaticDetectionPolicy. // Returns SHOULD_* if timezone resolver status is controlled by this policy. ServiceConfiguration GetServiceConfigurationFromAutomaticDetectionPolicy() { - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - chromeos::switches::kDisableSystemTimezoneAutomaticDetectionPolicy)) { - return UNSPECIFIED; - } - PrefService* local_state = g_browser_process->local_state(); const bool is_managed = local_state->IsManagedPreference( prefs::kSystemTimezoneAutomaticDetectionPolicy);
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 2cbdfb6..577e0bf 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -572,11 +572,6 @@ "expiry_milestone": 76 }, { - "name": "disable-system-timezone-automatic-detection", - // "owners": [ "your-team" ], - "expiry_milestone": 76 - }, - { "name": "disable-tablet-splitview", // "owners": [ "your-team" ], "expiry_milestone": 76
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index d5264ed..7bcbc99 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -3072,11 +3072,6 @@ "Always rely on implicit syncrhonization between GPU and display " "controller instead of using dma-fences explcitily when available."; -const char kDisableSystemTimezoneAutomaticDetectionName[] = - "SystemTimezoneAutomaticDetection policy support"; -const char kDisableSystemTimezoneAutomaticDetectionDescription[] = - "Disable system timezone automatic detection device policy."; - const char kDisableTabletAutohideTitlebarsName[] = "Disable autohide titlebars in tablet mode"; const char kDisableTabletAutohideTitlebarsDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index b9c2c1a..006d4e7 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -1848,9 +1848,6 @@ extern const char kDisableExplicitDmaFencesName[]; extern const char kDisableExplicitDmaFencesDescription[]; -extern const char kDisableSystemTimezoneAutomaticDetectionName[]; -extern const char kDisableSystemTimezoneAutomaticDetectionDescription[]; - extern const char kDisableTabletAutohideTitlebarsName[]; extern const char kDisableTabletAutohideTitlebarsDescription[];
diff --git a/chrome/browser/notifications/notification_permission_context.h b/chrome/browser/notifications/notification_permission_context.h index bdec582..23200bdc 100644 --- a/chrome/browser/notifications/notification_permission_context.h +++ b/chrome/browser/notifications/notification_permission_context.h
@@ -36,6 +36,11 @@ // CONTENT_SETTING_BLOCK will be returned to reflect the fact that permission // cannot be requested. // +// When the user rejects a notification permission request, the WebContents will +// be prevented from requesting the permission again (regardless of origin) +// until a user-initiated navigation occurs. This stops users from being locked +// in to cross-origin request loops that may be hard to escape from. +// // ANDROID O+ // // On Android O and beyond, notification channels will be used for storing
diff --git a/chrome/browser/permissions/permission_request_manager.cc b/chrome/browser/permissions/permission_request_manager.cc index 3345fe7..d08b280 100644 --- a/chrome/browser/permissions/permission_request_manager.cc +++ b/chrome/browser/permissions/permission_request_manager.cc
@@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/command_line.h" #include "base/containers/circular_deque.h" +#include "base/feature_list.h" #include "base/metrics/user_metrics.h" #include "base/metrics/user_metrics_action.h" #include "base/strings/string16.h" @@ -19,6 +20,7 @@ #include "chrome/browser/permissions/permission_uma_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/permission_bubble/permission_prompt.h" +#include "chrome/common/chrome_features.h" #include "chrome/common/chrome_switches.h" #include "components/url_formatter/elide_url.h" #include "content/public/browser/browser_task_traits.h" @@ -95,6 +97,17 @@ return; } + if (is_notification_prompt_cooldown_active_ && + request->GetContentSettingsType() == + CONTENT_SETTINGS_TYPE_NOTIFICATIONS) { + // Short-circuit by canceling rather than denying to avoid creating a large + // number of content setting exceptions on Desktop / disabled notification + // channels on Android. + request->Cancelled(); + request->RequestFinished(); + return; + } + // TODO(tsergeant): change the UMA to no longer mention bubbles. base::RecordAction(base::UserMetricsAction("PermissionBubbleRequest")); @@ -155,6 +168,25 @@ return nullptr; } +void PermissionRequestManager::DidStartNavigation( + content::NavigationHandle* navigation_handle) { + if (!navigation_handle->IsInMainFrame() || + navigation_handle->IsSameDocument()) { + return; + } + + // Cooldown lasts until the next user-initiated navigation, which is defined + // as either a renderer-initiated navigation with a user gesture, or a + // browser-initiated navigation. + // + // TODO(crbug.com/952347): This check has to be done at DidStartNavigation + // time, the HasUserGesture state is lost by the time the navigation commits. + if (!navigation_handle->IsRendererInitiated() || + navigation_handle->HasUserGesture()) { + is_notification_prompt_cooldown_active_ = false; + } +} + void PermissionRequestManager::DidFinishNavigation( content::NavigationHandle* navigation_handle) { if (!navigation_handle->IsInMainFrame() || @@ -262,6 +294,20 @@ void PermissionRequestManager::Deny() { DCHECK(view_); + + // Suppress any further prompts in this WebContents, from any origin, until + // there is a user-initiated navigation. This stops users from getting trapped + // in request loops where the website automatically navigates cross-origin + // (e.g. to another subdomain) to be able to prompt again after a rejection. + if (base::FeatureList::IsEnabled( + features::kBlockRepeatedNotificationPermissionPrompts) && + std::any_of(requests_.begin(), requests_.end(), [](const auto* request) { + return request->GetContentSettingsType() == + CONTENT_SETTINGS_TYPE_NOTIFICATIONS; + })) { + is_notification_prompt_cooldown_active_ = true; + } + std::vector<PermissionRequest*>::iterator requests_iter; for (requests_iter = requests_.begin(); requests_iter != requests_.end();
diff --git a/chrome/browser/permissions/permission_request_manager.h b/chrome/browser/permissions/permission_request_manager.h index 1c5171cc..31a29ba 100644 --- a/chrome/browser/permissions/permission_request_manager.h +++ b/chrome/browser/permissions/permission_request_manager.h
@@ -104,6 +104,8 @@ explicit PermissionRequestManager(content::WebContents* web_contents); // WebContentsObserver: + void DidStartNavigation( + content::NavigationHandle* navigation_handle) override; void DidFinishNavigation( content::NavigationHandle* navigation_handle) override; void DocumentOnLoadCompletedInMainFrame() override; @@ -183,6 +185,10 @@ base::ObserverList<Observer>::Unchecked observer_list_; AutoResponseType auto_response_for_test_; + // Suppress notification permission prompts in this tab, regardless of the + // origin requesting the permission. + bool is_notification_prompt_cooldown_active_ = false; + base::WeakPtrFactory<PermissionRequestManager> weak_factory_; WEB_CONTENTS_USER_DATA_KEY_DECL(); };
diff --git a/chrome/browser/permissions/permission_request_manager_browsertest.cc b/chrome/browser/permissions/permission_request_manager_browsertest.cc index 4ffc322..9abe958 100644 --- a/chrome/browser/permissions/permission_request_manager_browsertest.cc +++ b/chrome/browser/permissions/permission_request_manager_browsertest.cc
@@ -38,6 +38,7 @@ #include "content/public/test/test_navigation_observer.h" #include "content/public/test/test_utils.h" #include "media/base/media_switches.h" +#include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/embedded_test_server.h" namespace { @@ -57,6 +58,10 @@ PermissionRequestManager* manager = GetPermissionRequestManager(); mock_permission_prompt_factory_.reset( new MockPermissionPromptFactory(manager)); + scoped_feature_list_.InitAndEnableFeature( + features::kBlockRepeatedNotificationPermissionPrompts); + + host_resolver()->AddRule("*", "127.0.0.1"); } void TearDownOnMainThread() override { @@ -89,7 +94,73 @@ kPermissionsKillSwitchTestGroup); } + void TriggerAndExpectPromptCooldownToBeStillActiveAfterNavigationAction( + void navigation_action(content::WebContents*, const GURL&), + bool expect_cooldown) { + ASSERT_TRUE(embedded_test_server()->Start()); + + const GURL kInitialURL = embedded_test_server()->GetURL( + "a.localhost", "/permissions/killswitch_tester.html"); + const GURL kSecondURL = embedded_test_server()->GetURL( + "b.localhost", "/permissions/killswitch_tester.html"); + const GURL kThirdURL = embedded_test_server()->GetURL( + "c.localhost", "/permissions/killswitch_tester.html"); + + ui_test_utils::NavigateToURL(browser(), kInitialURL); + bubble_factory()->ResetCounts(); + bubble_factory()->set_response_type( + PermissionRequestManager::AutoResponseType::DENY_ALL); + + // Simulate a notification permission request that is denied by the user. + std::string result; + content::WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + ASSERT_TRUE(content::ExecuteScriptWithoutUserGestureAndExtractString( + web_contents, "requestNotification();", &result)); + ASSERT_EQ(1, bubble_factory()->show_count()); + ASSERT_EQ(1, bubble_factory()->TotalRequestCount()); + ASSERT_EQ("denied", result); + + // In response, simulate the website automatically triggering a + // renderer-initiated cross-origin navigation without user gesture. + content::TestNavigationObserver navigation_observer(web_contents); + ASSERT_TRUE(content::ExecuteScriptWithoutUserGesture( + web_contents, "window.location = \"" + kSecondURL.spec() + "\";")); + navigation_observer.Wait(); + + bubble_factory()->ResetCounts(); + bubble_factory()->set_response_type( + PermissionRequestManager::AutoResponseType::ACCEPT_ALL); + + // Request the notification permission again from a different origin. + // Cross-origin permission prompt cool-down should be in effect. + ASSERT_TRUE(content::ExecuteScriptWithoutUserGestureAndExtractString( + web_contents, "requestNotification();", &result)); + ASSERT_EQ(0, bubble_factory()->show_count()); + ASSERT_EQ(0, bubble_factory()->TotalRequestCount()); + ASSERT_EQ("default", result); + + // Now try one of a number other kinds of navigations, and request the + // notification permission again. + navigation_action(web_contents, kThirdURL); + ASSERT_TRUE(content::ExecuteScriptAndExtractString( + web_contents, "requestNotification();", &result)); + + // Cross-origin prompt cool-down may or may not be in effect anymore + // depending on the type of navigation. + if (expect_cooldown) { + EXPECT_EQ(0, bubble_factory()->show_count()); + EXPECT_EQ(0, bubble_factory()->TotalRequestCount()); + EXPECT_EQ("default", result); + } else { + EXPECT_EQ(1, bubble_factory()->show_count()); + EXPECT_EQ(1, bubble_factory()->TotalRequestCount()); + EXPECT_EQ("granted", result); + } + } + private: + base::test::ScopedFeatureList scoped_feature_list_; std::unique_ptr<MockPermissionPromptFactory> mock_permission_prompt_factory_; DISALLOW_COPY_AND_ASSIGN(PermissionRequestManagerBrowserTest); @@ -451,6 +522,112 @@ EXPECT_EQ(1, bubble_factory()->TotalRequestCount()); } +// Regression test for crbug.com/900997. +IN_PROC_BROWSER_TEST_F(PermissionRequestManagerBrowserTest, + CrossOriginPromptCooldown) { + ASSERT_TRUE(embedded_test_server()->Start()); + + const GURL kInitialURL = embedded_test_server()->GetURL( + "a.localhost", "/permissions/killswitch_tester.html"); + const GURL kSecondURL = embedded_test_server()->GetURL( + "b.localhost", "/permissions/killswitch_tester.html"); + + ui_test_utils::NavigateToURL(browser(), kInitialURL); + bubble_factory()->set_response_type( + PermissionRequestManager::AutoResponseType::DENY_ALL); + + // Simulate a notification permission request that is denied by the user. + std::string result; + content::WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + ASSERT_TRUE(content::ExecuteScriptWithoutUserGestureAndExtractString( + web_contents, "requestNotification();", &result)); + ASSERT_EQ(1, bubble_factory()->show_count()); + ASSERT_EQ(1, bubble_factory()->TotalRequestCount()); + ASSERT_EQ("denied", result); + + // In response, simulate the website automatically triggering a + // renderer-initiated cross-origin navigation without user gesture. + content::TestNavigationObserver navigation_observer(web_contents); + ASSERT_TRUE(content::ExecuteScriptWithoutUserGesture( + web_contents, "window.location = \"" + kSecondURL.spec() + "\";")); + navigation_observer.Wait(); + + // Request the notification permission again from a different origin. + // Cross-origin permission prompt cool-down should be in effect. + bubble_factory()->ResetCounts(); + bubble_factory()->set_response_type( + PermissionRequestManager::AutoResponseType::ACCEPT_ALL); + ASSERT_TRUE(content::ExecuteScriptWithoutUserGestureAndExtractString( + web_contents, "requestNotification();", &result)); + EXPECT_EQ(0, bubble_factory()->show_count()); + EXPECT_EQ(0, bubble_factory()->TotalRequestCount()); + EXPECT_EQ("default", result); +} + +// Regression test for crbug.com/900997. +IN_PROC_BROWSER_TEST_F(PermissionRequestManagerBrowserTest, + CooldownEndsOnUserInitiatedReload) { + TriggerAndExpectPromptCooldownToBeStillActiveAfterNavigationAction( + [](content::WebContents* web_contents, const GURL& unused_url) { + content::NavigationController& controller = + web_contents->GetController(); + controller.Reload(content::ReloadType::NORMAL, false); + EXPECT_TRUE(content::WaitForLoadStop(web_contents)); + }, + false /* expect_cooldown */); +} + +// Regression test for crbug.com/900997. +IN_PROC_BROWSER_TEST_F(PermissionRequestManagerBrowserTest, + CooldownEndsOnBrowserInitiateNavigation) { + TriggerAndExpectPromptCooldownToBeStillActiveAfterNavigationAction( + [](content::WebContents* web_contents, const GURL& url) { + EXPECT_TRUE(content::NavigateToURL(web_contents, url)); + }, + false /* expect_cooldown */); +} + +// Regression test for crbug.com/900997. +IN_PROC_BROWSER_TEST_F(PermissionRequestManagerBrowserTest, + CooldownEndsOnRendererInitiateNavigationWithGesture) { + TriggerAndExpectPromptCooldownToBeStillActiveAfterNavigationAction( + [](content::WebContents* web_contents, const GURL& url) { + content::TestNavigationObserver navigation_observer(web_contents); + EXPECT_TRUE(content::ExecuteScript( + web_contents, "window.location = \"" + url.spec() + "\";")); + navigation_observer.Wait(); + }, + false /* expect_cooldown */); +} + +// Regression test for crbug.com/900997. +IN_PROC_BROWSER_TEST_F(PermissionRequestManagerBrowserTest, + CooldownOutlastsRendererInitiatedReload) { + TriggerAndExpectPromptCooldownToBeStillActiveAfterNavigationAction( + [](content::WebContents* web_contents, const GURL& unused_url) { + content::TestNavigationObserver navigation_observer(web_contents); + EXPECT_TRUE(content::ExecuteScriptWithoutUserGesture( + web_contents, "window.location.reload();")); + navigation_observer.Wait(); + }, + true /* expect_cooldown */); +} + +// Regression test for crbug.com/900997. +IN_PROC_BROWSER_TEST_F( + PermissionRequestManagerBrowserTest, + CooldownOutlastsRendererInitiateNavigationWithoutGesture) { + TriggerAndExpectPromptCooldownToBeStillActiveAfterNavigationAction( + [](content::WebContents* web_contents, const GURL& url) { + content::TestNavigationObserver navigation_observer(web_contents); + EXPECT_TRUE(content::ExecuteScriptWithoutUserGesture( + web_contents, "window.location = \"" + url.spec() + "\";")); + navigation_observer.Wait(); + }, + true /* expect_cooldown */); +} + // Bubble requests should not be shown when the killswitch is on. IN_PROC_BROWSER_TEST_F(PermissionRequestManagerBrowserTest, KillSwitchNotifications) {
diff --git a/chrome/browser/previews/previews_lite_page_browsertest.cc b/chrome/browser/previews/previews_lite_page_browsertest.cc index 0c51bfdb..3daa254 100644 --- a/chrome/browser/previews/previews_lite_page_browsertest.cc +++ b/chrome/browser/previews/previews_lite_page_browsertest.cc
@@ -39,6 +39,8 @@ #include "chrome/test/base/ui_test_utils.h" #include "components/content_settings/core/browser/cookie_settings.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_test_utils.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_pingback_client.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_features.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h" @@ -1413,6 +1415,77 @@ WaitForPingback(); } +class TestDataReductionProxyPingbackClient + : public data_reduction_proxy::DataReductionProxyPingbackClient { + public: + void WaitForPingback() { + base::RunLoop run_loop; + wait_for_pingback_closure_ = run_loop.QuitClosure(); + run_loop.Run(); + } + + data_reduction_proxy::DataReductionProxyData* data() { return data_.get(); } + + private: + void SendPingback( + const data_reduction_proxy::DataReductionProxyData& data, + const data_reduction_proxy::DataReductionProxyPageLoadTiming& timing) + override { + data_ = data.DeepCopy(); + if (wait_for_pingback_closure_) + std::move(wait_for_pingback_closure_).Run(); + } + + void SetPingbackReportingFraction( + float pingback_reporting_fraction) override {} + + base::OnceClosure wait_for_pingback_closure_; + std::unique_ptr<data_reduction_proxy::DataReductionProxyData> data_; +}; + +IN_PROC_BROWSER_TEST_P(PreviewsLitePageServerBrowserTest, + DISABLE_ON_WIN_MAC_CHROMESOS(PingbackContent)) { + TestDataReductionProxyPingbackClient* pingback_client = + new TestDataReductionProxyPingbackClient(); + DataReductionProxyChromeSettingsFactory::GetForBrowserContext( + browser()->profile()) + ->data_reduction_proxy_service() + ->SetPingbackClientForTesting(pingback_client); + + ui_test_utils::NavigateToURL(browser(), HttpsLitePageURL(kSuccess)); + VerifyPreviewLoaded(); + + // Starting a new page load will send a pingback for the previous page load. + GetWebContents()->GetController().Reload(content::ReloadType::NORMAL, false); + pingback_client->WaitForPingback(); + + data_reduction_proxy::DataReductionProxyData* data = pingback_client->data(); + EXPECT_TRUE(data->used_data_reduction_proxy()); + EXPECT_TRUE(data->lite_page_received()); + EXPECT_FALSE(data->lofi_policy_received()); + EXPECT_FALSE(data->lofi_received()); + EXPECT_FALSE(data->was_cached_data_reduction_proxy_response()); + + // TODO(crbug.com/952523): Fix and remove this early return. + if (GetParam()) + return; + + PreviewsUITabHelper* ui_tab_helper = + PreviewsUITabHelper::FromWebContents(GetWebContents()); + previews::PreviewsUserData* previews_data = + ui_tab_helper->previews_user_data(); + + EXPECT_EQ(data->session_key(), + previews_data->server_lite_page_info()->drp_session_key); + + // TODO(crbug.com/952523): The page id is being incremented for every + // restarted navigation. Fix and remove the early return. + return; + + EXPECT_EQ(data->page_id().value(), + previews_data->server_lite_page_info()->page_id); +} + class PreviewsLitePageServerTimeoutBrowserTest : public PreviewsLitePageServerBrowserTest { public:
diff --git a/chrome/browser/ui/views/webauthn/authenticator_dialog_view_browsertest.cc b/chrome/browser/ui/views/webauthn/authenticator_dialog_view_browsertest.cc index c0e90ab..b4990a7 100644 --- a/chrome/browser/ui/views/webauthn/authenticator_dialog_view_browsertest.cc +++ b/chrome/browser/ui/views/webauthn/authenticator_dialog_view_browsertest.cc
@@ -62,6 +62,10 @@ "Line Because Life Would Be Just Too Simple That Way"); } + base::Optional<base::string16> GetAdditionalDescription() const override { + return base::ASCIIToUTF16("More description text."); + } + ui::MenuModel* GetOtherTransportsMenuModel() override { return nullptr; } void OnBack() override {} @@ -105,7 +109,8 @@ content::WebContents* const web_contents = browser()->tab_strip_model()->GetActiveWebContents(); - auto dialog_model = std::make_unique<AuthenticatorRequestDialogModel>(); + auto dialog_model = std::make_unique<AuthenticatorRequestDialogModel>( + /*relying_party_id=*/"example.com"); dialog_model->SetCurrentStep( AuthenticatorRequestDialogModel::Step::kTimedOut); AuthenticatorRequestDialogView* dialog =
diff --git a/chrome/browser/ui/views/webauthn/authenticator_request_sheet_view.cc b/chrome/browser/ui/views/webauthn/authenticator_request_sheet_view.cc index 697959c..1f6fd9a 100644 --- a/chrome/browser/ui/views/webauthn/authenticator_request_sheet_view.cc +++ b/chrome/browser/ui/views/webauthn/authenticator_request_sheet_view.cc
@@ -168,6 +168,18 @@ description_label->SetMultiLine(true); description_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); label_container->AddChildView(description_label.release()); + + base::Optional<base::string16> additional_desciption = + model()->GetAdditionalDescription(); + if (additional_desciption) { + auto label = std::make_unique<views::Label>( + std::move(*additional_desciption), + views::style::CONTEXT_MESSAGE_BOX_BODY_TEXT); + label->SetMultiLine(true); + label->SetHorizontalAlignment(gfx::ALIGN_LEFT); + label_container->AddChildView(label.release()); + } + contents->AddChildView(label_container.release()); std::unique_ptr<views::View> step_specific_content =
diff --git a/chrome/browser/ui/webauthn/authenticator_dialog_browsertest.cc b/chrome/browser/ui/webauthn/authenticator_dialog_browsertest.cc index 2a63174..0bfa486 100644 --- a/chrome/browser/ui/webauthn/authenticator_dialog_browsertest.cc +++ b/chrome/browser/ui/webauthn/authenticator_dialog_browsertest.cc
@@ -28,10 +28,10 @@ // https://crbug.com/893292. set_should_verify_dialog_bounds(false); - auto model = std::make_unique<AuthenticatorRequestDialogModel>(); + auto model = std::make_unique<AuthenticatorRequestDialogModel>( + /*relying_party_id=*/"example.com"); ::device::FidoRequestHandlerBase::TransportAvailabilityInfo transport_availability; - transport_availability.rp_id = "example.com"; transport_availability.available_transports = { AuthenticatorTransport::kBluetoothLowEnergy, AuthenticatorTransport::kUsbHumanInterfaceDevice,
diff --git a/chrome/browser/ui/webauthn/authenticator_request_sheet_model.h b/chrome/browser/ui/webauthn/authenticator_request_sheet_model.h index d7aac0e..a67c81b 100644 --- a/chrome/browser/ui/webauthn/authenticator_request_sheet_model.h +++ b/chrome/browser/ui/webauthn/authenticator_request_sheet_model.h
@@ -7,6 +7,7 @@ #include <memory> +#include "base/optional.h" #include "base/strings/string16.h" namespace gfx { @@ -57,6 +58,7 @@ ImageColorScheme color_scheme) const = 0; virtual base::string16 GetStepTitle() const = 0; virtual base::string16 GetStepDescription() const = 0; + virtual base::Optional<base::string16> GetAdditionalDescription() const = 0; virtual ui::MenuModel* GetOtherTransportsMenuModel() = 0;
diff --git a/chrome/browser/ui/webauthn/sheet_models.cc b/chrome/browser/ui/webauthn/sheet_models.cc index d52834f..a8ccee5 100644 --- a/chrome/browser/ui/webauthn/sheet_models.cc +++ b/chrome/browser/ui/webauthn/sheet_models.cc
@@ -24,13 +24,14 @@ #include "url/gurl.h" namespace { + base::string16 GetRelyingPartyIdString( AuthenticatorRequestDialogModel* dialog_model) { static constexpr char kRpIdUrlPrefix[] = "https://"; // The preferred width of medium snap point modal dialog view is 448 dp, but // we leave some room for padding between the text and the modal views. static constexpr int kDialogWidth = 300; - const auto& rp_id = dialog_model->transport_availability()->rp_id; + const auto& rp_id = dialog_model->relying_party_id(); DCHECK(!rp_id.empty()); GURL rp_id_url(kRpIdUrlPrefix + rp_id); auto max_static_string_length = gfx::GetStringWidthF( @@ -39,6 +40,18 @@ return url_formatter::ElideHost(rp_id_url, gfx::FontList(), kDialogWidth - max_static_string_length); } + +// Possibly returns a resident key warning if the model indicates that it's +// needed. +base::Optional<base::string16> PossibleResidentKeyWarning( + AuthenticatorRequestDialogModel* dialog_model) { + if (dialog_model->might_create_resident_credential()) { + return l10n_util::GetStringFUTF16(IDS_WEBAUTHN_RESIDENT_KEY_PRIVACY, + GetRelyingPartyIdString(dialog_model)); + } + return base::nullopt; +} + } // namespace // AuthenticatorSheetModelBase ------------------------------------------------ @@ -92,6 +105,11 @@ return base::string16(); } +base::Optional<base::string16> +AuthenticatorSheetModelBase::GetAdditionalDescription() const { + return base::nullopt; +} + ui::MenuModel* AuthenticatorSheetModelBase::GetOtherTransportsMenuModel() { return nullptr; } @@ -215,6 +233,11 @@ return l10n_util::GetStringUTF16(IDS_WEBAUTHN_USB_ACTIVATE_DESCRIPTION); } +base::Optional<base::string16> +AuthenticatorInsertAndActivateUsbSheetModel::GetAdditionalDescription() const { + return PossibleResidentKeyWarning(dialog_model()); +} + ui::MenuModel* AuthenticatorInsertAndActivateUsbSheetModel::GetOtherTransportsMenuModel() { return other_transports_menu_model_.get(); @@ -619,6 +642,11 @@ return l10n_util::GetStringUTF16(IDS_WEBAUTHN_BLE_ACTIVATE_DESCRIPTION); } +base::Optional<base::string16> +AuthenticatorBleActivateSheetModel::GetAdditionalDescription() const { + return PossibleResidentKeyWarning(dialog_model()); +} + ui::MenuModel* AuthenticatorBleActivateSheetModel::GetOtherTransportsMenuModel() { return other_transports_menu_model_.get(); @@ -887,6 +915,11 @@ return l10n_util::GetStringUTF16(IDS_WEBAUTHN_PIN_TAP_AGAIN_DESCRIPTION); } +base::Optional<base::string16> +AuthenticatorClientPinTapAgainSheetModel::GetAdditionalDescription() const { + return PossibleResidentKeyWarning(dialog_model()); +} + // AuthenticatorGenericErrorSheetModel ----------------------------------- // static
diff --git a/chrome/browser/ui/webauthn/sheet_models.h b/chrome/browser/ui/webauthn/sheet_models.h index b05c7fe..d69247d 100644 --- a/chrome/browser/ui/webauthn/sheet_models.h +++ b/chrome/browser/ui/webauthn/sheet_models.h
@@ -46,6 +46,7 @@ bool IsAcceptButtonVisible() const override; bool IsAcceptButtonEnabled() const override; base::string16 GetAcceptButtonLabel() const override; + base::Optional<base::string16> GetAdditionalDescription() const override; ui::MenuModel* GetOtherTransportsMenuModel() override; void OnBack() override; void OnAccept() override; @@ -111,6 +112,7 @@ ImageColorScheme color_scheme) const override; base::string16 GetStepTitle() const override; base::string16 GetStepDescription() const override; + base::Optional<base::string16> GetAdditionalDescription() const override; ui::MenuModel* GetOtherTransportsMenuModel() override; std::unique_ptr<OtherTransportsMenuModel> other_transports_menu_model_; @@ -318,6 +320,7 @@ ImageColorScheme color_scheme) const override; base::string16 GetStepTitle() const override; base::string16 GetStepDescription() const override; + base::Optional<base::string16> GetAdditionalDescription() const override; ui::MenuModel* GetOtherTransportsMenuModel() override; std::unique_ptr<OtherTransportsMenuModel> other_transports_menu_model_; @@ -418,6 +421,7 @@ ImageColorScheme color_scheme) const override; base::string16 GetStepTitle() const override; base::string16 GetStepDescription() const override; + base::Optional<base::string16> GetAdditionalDescription() const override; }; // Generic error dialog that can only be dismissed. Backwards navigation is
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc index f2ea054..228d315 100644 --- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc +++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -231,9 +231,7 @@ #endif #if defined(FULL_SAFE_BROWSING) -#include "chrome/browser/safe_browsing/chrome_password_protection_service.h" #include "chrome/browser/ui/webui/reset_password/reset_password_ui.h" -#include "components/safe_browsing/features.h" #endif using content::WebUI; @@ -702,13 +700,7 @@ } #if defined(FULL_SAFE_BROWSING) - bool enable_reset_password = - base::FeatureList::IsEnabled( - safe_browsing::kForceEnableResetPasswordWebUI) || - safe_browsing::ChromePasswordProtectionService:: - IsPasswordReuseProtectionConfigured(profile); - if (url.host_piece() == chrome::kChromeUIResetPasswordHost && - enable_reset_password) { + if (url.host_piece() == chrome::kChromeUIResetPasswordHost) { return &NewWebUI<ResetPasswordUI>; } #endif
diff --git a/chrome/browser/ui/webui/settings/chromeos/date_time_handler.cc b/chrome/browser/ui/webui/settings/chromeos/date_time_handler.cc index 2423ebcd..c3a3202 100644 --- a/chrome/browser/ui/webui/settings/chromeos/date_time_handler.cc +++ b/chrome/browser/ui/webui/settings/chromeos/date_time_handler.cc
@@ -26,19 +26,9 @@ namespace { -// Returns whether the system time zone automatic detection policy is disabled -// by a flag. -bool IsSystemTimezoneAutomaticDetectionPolicyFlagDisabled() { - return base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableSystemTimezoneAutomaticDetectionPolicy); -} - // Returns whether the system's automatic time zone detection setting is // managed, which may override the user's setting. bool IsSystemTimezoneAutomaticDetectionManaged() { - if (IsSystemTimezoneAutomaticDetectionPolicyFlagDisabled()) - return false; - return g_browser_process->local_state()->IsManagedPreference( prefs::kSystemTimezoneAutomaticDetectionPolicy); } @@ -112,9 +102,6 @@ base::Bind(&DateTimeHandler::NotifyTimezoneAutomaticDetectionPolicy, weak_ptr_factory_.GetWeakPtr())); - if (IsSystemTimezoneAutomaticDetectionPolicyFlagDisabled()) - return; - // The auto-detection policy can force auto-detection on or off. local_state_pref_change_registrar_.Init(g_browser_process->local_state()); local_state_pref_change_registrar_.Add( @@ -126,9 +113,7 @@ void DateTimeHandler::OnJavascriptDisallowed() { scoped_observer_.RemoveAll(); system_timezone_policy_subscription_.reset(); - - if (!IsSystemTimezoneAutomaticDetectionPolicyFlagDisabled()) - local_state_pref_change_registrar_.RemoveAll(); + local_state_pref_change_registrar_.RemoveAll(); } void DateTimeHandler::HandleDateTimePageReady(const base::ListValue* args) {
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.cc b/chrome/browser/webauthn/authenticator_request_dialog_model.cc index ae9e468..f9aaedf9a 100644 --- a/chrome/browser/webauthn/authenticator_request_dialog_model.cc +++ b/chrome/browser/webauthn/authenticator_request_dialog_model.cc
@@ -81,8 +81,9 @@ } // namespace -AuthenticatorRequestDialogModel::AuthenticatorRequestDialogModel() - : weak_factory_(this) {} +AuthenticatorRequestDialogModel::AuthenticatorRequestDialogModel( + const std::string& relying_party_id) + : relying_party_id_(relying_party_id), weak_factory_(this) {} AuthenticatorRequestDialogModel::~AuthenticatorRequestDialogModel() { for (auto& observer : observers_)
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.h b/chrome/browser/webauthn/authenticator_request_dialog_model.h index 3915e28..aa45f94 100644 --- a/chrome/browser/webauthn/authenticator_request_dialog_model.h +++ b/chrome/browser/webauthn/authenticator_request_dialog_model.h
@@ -124,7 +124,7 @@ virtual void OnCancelRequest() {} }; - AuthenticatorRequestDialogModel(); + AuthenticatorRequestDialogModel(const std::string& relying_party_id); ~AuthenticatorRequestDialogModel(); void SetCurrentStep(Step step); @@ -384,10 +384,23 @@ incognito_mode_ = incognito_mode; } + bool might_create_resident_credential() const { + return might_create_resident_credential_; + } + + void set_might_create_resident_credential(bool v) { + might_create_resident_credential_ = v; + } + + const std::string& relying_party_id() const { return relying_party_id_; } + private: void DispatchRequestAsync(AuthenticatorReference* authenticator); void DispatchRequestAsyncInternal(const std::string& authenticator_id); + // relying_party_id is the RP ID from Webauthn, essentially a domain name. + const std::string relying_party_id_; + // The current step of the request UX flow that is currently shown. Step current_step_ = Step::kNotStarted; @@ -428,6 +441,12 @@ base::OnceCallback<void(bool)> attestation_callback_; + // might_create_resident_credential_ records whether activating an + // authenticator may cause a resident credential to be created. A resident + // credential may be discovered by someone with physical access to the + // authenticator and thus has privacy implications. + bool might_create_resident_credential_ = false; + // responses_ contains possible accounts to select between. std::vector<device::AuthenticatorGetAssertionResponse> responses_; base::OnceCallback<void(device::AuthenticatorGetAssertionResponse)>
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model_unittest.cc b/chrome/browser/webauthn/authenticator_request_dialog_model_unittest.cc index f10df0b..b348daf 100644 --- a/chrome/browser/webauthn/authenticator_request_dialog_model_unittest.cc +++ b/chrome/browser/webauthn/authenticator_request_dialog_model_unittest.cc
@@ -314,7 +314,7 @@ transports_info.win_native_api_authenticator_id = "some_authenticator_id"; } - AuthenticatorRequestDialogModel model; + AuthenticatorRequestDialogModel model(/*relying_party_id=*/"example.com"); model.StartFlow(std::move(transports_info), test_case.last_used_transport, &test_paired_device_list_); EXPECT_EQ(test_case.expected_first_step, model.current_step()); @@ -331,7 +331,7 @@ TransportAvailabilityInfo transports_info; transports_info.available_transports = kAllTransports; - AuthenticatorRequestDialogModel model; + AuthenticatorRequestDialogModel model(/*relying_party_id=*/"example.com"); model.StartFlow(std::move(transports_info), base::nullopt, &test_paired_device_list_); EXPECT_THAT(model.available_transports(), @@ -345,7 +345,7 @@ TEST_F(AuthenticatorRequestDialogModelTest, NoAvailableTransports) { testing::StrictMock<MockDialogModelObserver> mock_observer; - AuthenticatorRequestDialogModel model; + AuthenticatorRequestDialogModel model(/*relying_party_id=*/"example.com"); model.AddObserver(&mock_observer); EXPECT_CALL(mock_observer, OnStepTransition()); @@ -380,7 +380,7 @@ for (const auto& test_case : kTestCases) { testing::StrictMock<MockDialogModelObserver> mock_observer; - AuthenticatorRequestDialogModel model; + AuthenticatorRequestDialogModel model(/*relying_party_id=*/"example.com"); model.AddObserver(&mock_observer); TransportAvailabilityInfo transports_info; @@ -426,7 +426,7 @@ transports_info.is_ble_powered = true; BluetoothAdapterPowerOnCallbackReceiver power_receiver; - AuthenticatorRequestDialogModel model; + AuthenticatorRequestDialogModel model(/*relying_party_id=*/"example.com"); model.SetBluetoothAdapterPowerOnCallback(power_receiver.GetCallback()); model.StartFlow(std::move(transports_info), base::nullopt, test_case.paired_device_address_list); @@ -453,7 +453,7 @@ transports_info.is_ble_powered = true; BluetoothAdapterPowerOnCallbackReceiver power_receiver; - AuthenticatorRequestDialogModel model; + AuthenticatorRequestDialogModel model(/*relying_party_id=*/"example.com"); model.SetBluetoothAdapterPowerOnCallback(power_receiver.GetCallback()); model.StartFlow(std::move(transports_info), base::nullopt, &test_paired_device_list_); @@ -482,7 +482,7 @@ testing::NiceMock<MockDialogModelObserver> mock_observer; BluetoothAdapterPowerOnCallbackReceiver power_receiver; - AuthenticatorRequestDialogModel model; + AuthenticatorRequestDialogModel model(/*relying_party_id=*/"example.com"); model.AddObserver(&mock_observer); model.SetBluetoothAdapterPowerOnCallback(power_receiver.GetCallback()); model.StartFlow(std::move(transports_info), base::nullopt, @@ -523,7 +523,7 @@ transports_info.is_ble_powered = false; BluetoothAdapterPowerOnCallbackReceiver power_receiver; - AuthenticatorRequestDialogModel model; + AuthenticatorRequestDialogModel model(/*relying_party_id=*/"example.com"); model.SetBluetoothAdapterPowerOnCallback(power_receiver.GetCallback()); model.StartFlow(std::move(transports_info), base::nullopt, &test_paired_device_list_); @@ -553,7 +553,7 @@ AuthenticatorTransport::kUsbHumanInterfaceDevice}; int num_called = 0; - AuthenticatorRequestDialogModel model; + AuthenticatorRequestDialogModel model(/*relying_party_id=*/"example.com"); model.SetRequestCallback(base::BindRepeating( [](int* i, const std::string& authenticator_id) { ++(*i); }, &num_called)); @@ -599,7 +599,7 @@ transports_info.win_native_api_authenticator_id = kWinAuthenticatorId; std::vector<std::string> dispatched_authenticator_ids; - AuthenticatorRequestDialogModel model; + AuthenticatorRequestDialogModel model(/*relying_party_id=*/"example.com"); model.SetRequestCallback(base::BindRepeating( [](std::vector<std::string>* ids, const std::string& authenticator_id) { ids->push_back(authenticator_id);
diff --git a/chrome/browser/webauthn/authenticator_request_scheduler.cc b/chrome/browser/webauthn/authenticator_request_scheduler.cc index fb49996..0bee466 100644 --- a/chrome/browser/webauthn/authenticator_request_scheduler.cc +++ b/chrome/browser/webauthn/authenticator_request_scheduler.cc
@@ -44,7 +44,8 @@ // static std::unique_ptr<ChromeAuthenticatorRequestDelegate> AuthenticatorRequestScheduler::CreateRequestDelegate( - content::RenderFrameHost* render_frame_host) { + content::RenderFrameHost* render_frame_host, + const std::string& relying_party_id) { auto* const web_contents = content::WebContents::FromRenderFrameHost(render_frame_host); auto* const active_request_holder = @@ -53,8 +54,8 @@ if (active_request_holder->request()) return nullptr; - auto request = - std::make_unique<ChromeAuthenticatorRequestDelegate>(render_frame_host); + auto request = std::make_unique<ChromeAuthenticatorRequestDelegate>( + render_frame_host, relying_party_id); active_request_holder->request() = request->AsWeakPtr(); return request; }
diff --git a/chrome/browser/webauthn/authenticator_request_scheduler.h b/chrome/browser/webauthn/authenticator_request_scheduler.h index f70ed3e..8b3d1d9 100644 --- a/chrome/browser/webauthn/authenticator_request_scheduler.h +++ b/chrome/browser/webauthn/authenticator_request_scheduler.h
@@ -6,6 +6,7 @@ #define CHROME_BROWSER_WEBAUTHN_AUTHENTICATOR_REQUEST_SCHEDULER_H_ #include <memory> +#include <string> #include "base/macros.h" @@ -30,7 +31,8 @@ // Returns a nullptr delegate if there is already an ongoing request in the // same WebContents. static std::unique_ptr<ChromeAuthenticatorRequestDelegate> - CreateRequestDelegate(content::RenderFrameHost* render_frame_host); + CreateRequestDelegate(content::RenderFrameHost* render_frame_host, + const std::string& relying_party_id); // Returns the current request delegate associated to the |web_contents| or // nullptr if there is none.
diff --git a/chrome/browser/webauthn/authenticator_request_scheduler_unittest.cc b/chrome/browser/webauthn/authenticator_request_scheduler_unittest.cc index 072ebf98..796a2f1 100644 --- a/chrome/browser/webauthn/authenticator_request_scheduler_unittest.cc +++ b/chrome/browser/webauthn/authenticator_request_scheduler_unittest.cc
@@ -20,26 +20,28 @@ TEST_F(AuthenticatorRequestSchedulerTest, SingleWebContents_AtMostOneSimultaneousRequest) { + const std::string rp_id = "example.com"; auto first_request = AuthenticatorRequestScheduler::CreateRequestDelegate( - web_contents()->GetMainFrame()); + web_contents()->GetMainFrame(), rp_id); ASSERT_TRUE(first_request); ASSERT_FALSE(AuthenticatorRequestScheduler::CreateRequestDelegate( - web_contents()->GetMainFrame())); + web_contents()->GetMainFrame(), rp_id)); first_request.reset(); ASSERT_TRUE(AuthenticatorRequestScheduler::CreateRequestDelegate( - web_contents()->GetMainFrame())); + web_contents()->GetMainFrame(), rp_id)); } TEST_F(AuthenticatorRequestSchedulerTest, TwoWebContents_TwoSimultaneousRequests) { + const std::string rp_id = "example.com"; auto first_request = AuthenticatorRequestScheduler::CreateRequestDelegate( - web_contents()->GetMainFrame()); + web_contents()->GetMainFrame(), rp_id); auto second_web_contents = CreateTestWebContents(); auto second_request = AuthenticatorRequestScheduler::CreateRequestDelegate( - second_web_contents->GetMainFrame()); + second_web_contents->GetMainFrame(), rp_id); ASSERT_TRUE(first_request); ASSERT_TRUE(second_request);
diff --git a/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc b/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc index f35e0f0..54ea6d3e 100644 --- a/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc +++ b/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc
@@ -87,8 +87,11 @@ } ChromeAuthenticatorRequestDelegate::ChromeAuthenticatorRequestDelegate( - content::RenderFrameHost* render_frame_host) - : render_frame_host_(render_frame_host), weak_ptr_factory_(this) {} + content::RenderFrameHost* render_frame_host, + const std::string& relying_party_id) + : render_frame_host_(render_frame_host), + relying_party_id_(relying_party_id), + weak_ptr_factory_(this) {} ChromeAuthenticatorRequestDelegate::~ChromeAuthenticatorRequestDelegate() { // Currently, completion of the request is indicated by //content destroying @@ -165,7 +168,7 @@ cancel_callback_ = std::move(cancel_callback); transient_dialog_model_holder_ = - std::make_unique<AuthenticatorRequestDialogModel>(); + std::make_unique<AuthenticatorRequestDialogModel>(relying_party_id_); transient_dialog_model_holder_->SetRequestCallback(request_callback); transient_dialog_model_holder_->SetBluetoothAdapterPowerOnCallback( bluetooth_adapter_power_on_callback); @@ -441,6 +444,14 @@ AuthenticatorRequestDialogModel::Step::kClientPinTapAgain); } +void ChromeAuthenticatorRequestDelegate::SetMightCreateResidentCredential( + bool v) { + if (!weak_dialog_model_) { + return; + } + weak_dialog_model_->set_might_create_resident_credential(v); +} + void ChromeAuthenticatorRequestDelegate::OnModelDestroyed() { DCHECK(weak_dialog_model_); weak_dialog_model_ = nullptr;
diff --git a/chrome/browser/webauthn/chrome_authenticator_request_delegate.h b/chrome/browser/webauthn/chrome_authenticator_request_delegate.h index 95d7b362..292d8c98 100644 --- a/chrome/browser/webauthn/chrome_authenticator_request_delegate.h +++ b/chrome/browser/webauthn/chrome_authenticator_request_delegate.h
@@ -47,7 +47,8 @@ // The |render_frame_host| must outlive this instance. explicit ChromeAuthenticatorRequestDelegate( - content::RenderFrameHost* render_frame_host); + content::RenderFrameHost* render_frame_host, + const std::string& relying_party_id); ~ChromeAuthenticatorRequestDelegate() override; #if defined(OS_MACOSX) @@ -113,6 +114,7 @@ base::Optional<int> attempts, base::OnceCallback<void(std::string)> provide_pin_cb) override; void FinishCollectPIN() override; + void SetMightCreateResidentCredential(bool v) override; // AuthenticatorRequestDialogModel::Observer: void OnModelDestroyed() override; @@ -123,6 +125,7 @@ const base::ListValue* GetPreviouslyPairedFidoBleDeviceIds() const; content::RenderFrameHost* const render_frame_host_; + const std::string relying_party_id_; AuthenticatorRequestDialogModel* weak_dialog_model_ = nullptr; // Holds ownership of AuthenticatorRequestDialogModel until // OnTransportAvailabilityEnumerated() is invoked, at which point the
diff --git a/chrome/browser/webauthn/chrome_authenticator_request_delegate_unittest.cc b/chrome/browser/webauthn/chrome_authenticator_request_delegate_unittest.cc index c724749..64e8c1b 100644 --- a/chrome/browser/webauthn/chrome_authenticator_request_delegate_unittest.cc +++ b/chrome/browser/webauthn/chrome_authenticator_request_delegate_unittest.cc
@@ -15,8 +15,10 @@ class ChromeAuthenticatorRequestDelegateTest : public ChromeRenderViewHostTestHarness {}; +static constexpr char kRelyingPartyID[] = "example.com"; + TEST_F(ChromeAuthenticatorRequestDelegateTest, TestTransportPrefType) { - ChromeAuthenticatorRequestDelegate delegate(main_rfh()); + ChromeAuthenticatorRequestDelegate delegate(main_rfh(), kRelyingPartyID); EXPECT_FALSE(delegate.GetLastTransportUsed()); delegate.UpdateLastTransportUsed(device::FidoTransportProtocol::kInternal); const auto transport = delegate.GetLastTransportUsed(); @@ -29,7 +31,7 @@ static constexpr char kTestPairedDeviceAddress[] = "paired_device_address"; static constexpr char kTestPairedDeviceAddress2[] = "paired_device_address2"; - ChromeAuthenticatorRequestDelegate delegate(main_rfh()); + ChromeAuthenticatorRequestDelegate delegate(main_rfh(), kRelyingPartyID); auto* const address_list = delegate.GetPreviouslyPairedFidoBleDeviceIds(); ASSERT_TRUE(address_list); @@ -73,7 +75,7 @@ } TEST_F(ChromeAuthenticatorRequestDelegateTest, TouchIdMetadataSecret) { - ChromeAuthenticatorRequestDelegate delegate(main_rfh()); + ChromeAuthenticatorRequestDelegate delegate(main_rfh(), kRelyingPartyID); std::string secret = TouchIdMetadataSecret(delegate); EXPECT_EQ(secret.size(), 32u); EXPECT_EQ(secret, TouchIdMetadataSecret(delegate)); @@ -83,9 +85,10 @@ TouchIdMetadataSecret_EqualForSameProfile) { // Different delegates on the same BrowserContext (Profile) should return the // same secret. - EXPECT_EQ( - TouchIdMetadataSecret(ChromeAuthenticatorRequestDelegate(main_rfh())), - TouchIdMetadataSecret(ChromeAuthenticatorRequestDelegate(main_rfh()))); + EXPECT_EQ(TouchIdMetadataSecret(ChromeAuthenticatorRequestDelegate( + main_rfh(), kRelyingPartyID)), + TouchIdMetadataSecret(ChromeAuthenticatorRequestDelegate( + main_rfh(), kRelyingPartyID))); } TEST_F(ChromeAuthenticatorRequestDelegateTest, @@ -95,13 +98,14 @@ auto browser_context = base::WrapUnique(CreateBrowserContext()); auto web_contents = content::WebContentsTester::CreateTestWebContents( browser_context.get(), nullptr); - EXPECT_NE( - TouchIdMetadataSecret(ChromeAuthenticatorRequestDelegate(main_rfh())), - TouchIdMetadataSecret( - ChromeAuthenticatorRequestDelegate(web_contents->GetMainFrame()))); + EXPECT_NE(TouchIdMetadataSecret(ChromeAuthenticatorRequestDelegate( + main_rfh(), kRelyingPartyID)), + TouchIdMetadataSecret(ChromeAuthenticatorRequestDelegate( + web_contents->GetMainFrame(), kRelyingPartyID))); // Ensure this second secret is actually valid. - EXPECT_EQ(32u, TouchIdMetadataSecret(ChromeAuthenticatorRequestDelegate( - web_contents->GetMainFrame())) + EXPECT_EQ(32u, TouchIdMetadataSecret( + ChromeAuthenticatorRequestDelegate( + web_contents->GetMainFrame(), kRelyingPartyID)) .size()); } #endif
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index 6d4a53ec..b510875 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -110,6 +110,13 @@ const base::Feature kBlockPromptsIfIgnoredOften{ "BlockPromptsIfIgnoredOften", base::FEATURE_DISABLED_BY_DEFAULT}; +// Once the user declines a notification permission prompt in a WebContents, +// automatically dismiss subsequent prompts in the same WebContents, from any +// origin, until the next user-initiated navigation. +const base::Feature kBlockRepeatedNotificationPermissionPrompts{ + "BlockRepeatedNotificationPermissionPrompts", + base::FEATURE_ENABLED_BY_DEFAULT}; + // Fixes for browser hang bugs are deployed in a field trial in order to measure // their impact. See crbug.com/478209. const base::Feature kBrowserHangFixesExperiment{
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h index c9f3776e..cc3ba13 100644 --- a/chrome/common/chrome_features.h +++ b/chrome/common/chrome_features.h
@@ -71,6 +71,9 @@ extern const base::Feature kBlockPromptsIfIgnoredOften; COMPONENT_EXPORT(CHROME_FEATURES) +extern const base::Feature kBlockRepeatedNotificationPermissionPrompts; + +COMPONENT_EXPORT(CHROME_FEATURES) extern const base::Feature kBrowserHangFixesExperiment; COMPONENT_EXPORT(CHROME_FEATURES)
diff --git a/chrome/common/extensions/api/extension_action/action_info.cc b/chrome/common/extensions/api/extension_action/action_info.cc index c4c14f3..a47cccfd 100644 --- a/chrome/common/extensions/api/extension_action/action_info.cc +++ b/chrome/common/extensions/api/extension_action/action_info.cc
@@ -27,15 +27,15 @@ // The manifest data container for the ActionInfos for BrowserActions, // PageActions and SystemIndicators. struct ActionInfoData : public Extension::ManifestData { - explicit ActionInfoData(ActionInfo* action_info); + explicit ActionInfoData(std::unique_ptr<ActionInfo> action_info); ~ActionInfoData() override; // The action associated with the BrowserAction. std::unique_ptr<ActionInfo> action_info; }; -ActionInfoData::ActionInfoData(ActionInfo* info) : action_info(info) { -} +ActionInfoData::ActionInfoData(std::unique_ptr<ActionInfo> info) + : action_info(std::move(info)) {} ActionInfoData::~ActionInfoData() { } @@ -157,28 +157,30 @@ // static void ActionInfo::SetExtensionActionInfo(Extension* extension, - ActionInfo* info) { + std::unique_ptr<ActionInfo> info) { extension->SetManifestData(keys::kAction, - std::make_unique<ActionInfoData>(info)); + std::make_unique<ActionInfoData>(std::move(info))); } // static -void ActionInfo::SetBrowserActionInfo(Extension* extension, ActionInfo* info) { +void ActionInfo::SetBrowserActionInfo(Extension* extension, + std::unique_ptr<ActionInfo> info) { extension->SetManifestData(keys::kBrowserAction, - std::make_unique<ActionInfoData>(info)); + std::make_unique<ActionInfoData>(std::move(info))); } // static -void ActionInfo::SetPageActionInfo(Extension* extension, ActionInfo* info) { +void ActionInfo::SetPageActionInfo(Extension* extension, + std::unique_ptr<ActionInfo> info) { extension->SetManifestData(keys::kPageAction, - std::make_unique<ActionInfoData>(info)); + std::make_unique<ActionInfoData>(std::move(info))); } // static void ActionInfo::SetSystemIndicatorInfo(Extension* extension, - ActionInfo* info) { + std::unique_ptr<ActionInfo> info) { extension->SetManifestData(keys::kSystemIndicator, - std::make_unique<ActionInfoData>(info)); + std::make_unique<ActionInfoData>(std::move(info))); } // static
diff --git a/chrome/common/extensions/api/extension_action/action_info.h b/chrome/common/extensions/api/extension_action/action_info.h index 54d1412..eaa0ed0b 100644 --- a/chrome/common/extensions/api/extension_action/action_info.h +++ b/chrome/common/extensions/api/extension_action/action_info.h
@@ -55,18 +55,21 @@ // Returns the extension's system indicator, if any. static const ActionInfo* GetSystemIndicatorInfo(const Extension* extension); - // Sets the extension's action. |extension| takes ownership of |info|. - static void SetExtensionActionInfo(Extension* extension, ActionInfo* info); + // Sets the extension's action. + static void SetExtensionActionInfo(Extension* extension, + std::unique_ptr<ActionInfo> info); - // Sets the extension's browser action. |extension| takes ownership of |info|. - static void SetBrowserActionInfo(Extension* extension, ActionInfo* info); + // Sets the extension's browser action. + static void SetBrowserActionInfo(Extension* extension, + std::unique_ptr<ActionInfo> info); - // Sets the extension's page action. |extension| takes ownership of |info|. - static void SetPageActionInfo(Extension* extension, ActionInfo* info); + // Sets the extension's page action. + static void SetPageActionInfo(Extension* extension, + std::unique_ptr<ActionInfo> info); - // Sets the extension's system indicator. |extension| takes ownership of - // |info|. - static void SetSystemIndicatorInfo(Extension* extension, ActionInfo* info); + // Sets the extension's system indicator. + static void SetSystemIndicatorInfo(Extension* extension, + std::unique_ptr<ActionInfo> info); // Returns true if the extension needs a verbose install message because // of its page action.
diff --git a/chrome/common/extensions/api/system_indicator/system_indicator_handler.cc b/chrome/common/extensions/api/system_indicator/system_indicator_handler.cc index 761b9dd..e96dcb5 100644 --- a/chrome/common/extensions/api/system_indicator/system_indicator_handler.cc +++ b/chrome/common/extensions/api/system_indicator/system_indicator_handler.cc
@@ -35,7 +35,7 @@ if (!action_info.get()) return false; - ActionInfo::SetSystemIndicatorInfo(extension, action_info.release()); + ActionInfo::SetSystemIndicatorInfo(extension, std::move(action_info)); return true; }
diff --git a/chrome/common/extensions/manifest_handlers/extension_action_handler.cc b/chrome/common/extensions/manifest_handlers/extension_action_handler.cc index b3744ff..7e79d548 100644 --- a/chrome/common/extensions/manifest_handlers/extension_action_handler.cc +++ b/chrome/common/extensions/manifest_handlers/extension_action_handler.cc
@@ -67,7 +67,7 @@ return false; // Failed to parse extension action definition. if (key == manifest_keys::kAction) { - ActionInfo::SetExtensionActionInfo(extension, action_info.release()); + ActionInfo::SetExtensionActionInfo(extension, std::move(action_info)); } else { if (dict->HasKey(manifest_keys::kActionDefaultState)) { *error = @@ -76,9 +76,9 @@ } if (key == manifest_keys::kPageAction) - ActionInfo::SetPageActionInfo(extension, action_info.release()); + ActionInfo::SetPageActionInfo(extension, std::move(action_info)); else - ActionInfo::SetBrowserActionInfo(extension, action_info.release()); + ActionInfo::SetBrowserActionInfo(extension, std::move(action_info)); } } else { // No key, used for synthesizing an action for extensions with none. if (Manifest::IsComponentLocation(extension->location())) @@ -96,7 +96,7 @@ // action) because the action should not be seen as enabled on every page. std::unique_ptr<ActionInfo> action_info(new ActionInfo()); action_info->synthesized = true; - ActionInfo::SetPageActionInfo(extension, action_info.release()); + ActionInfo::SetPageActionInfo(extension, std::move(action_info)); } return true;
diff --git a/chrome/common/media_router/providers/cast/cast_media_source.cc b/chrome/common/media_router/providers/cast/cast_media_source.cc index 7d0fe5b5..af79bff 100644 --- a/chrome/common/media_router/providers/cast/cast_media_source.cc +++ b/chrome/common/media_router/providers/cast/cast_media_source.cc
@@ -4,7 +4,11 @@ #include "chrome/common/media_router/providers/cast/cast_media_source.h" +#include <utility> + +#include "base/containers/flat_map.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/string_piece.h" #include "base/strings/string_split.h" #include "base/strings/utf_string_conversions.h" #include "chrome/common/media_router/media_source_helper.h" @@ -14,38 +18,107 @@ #include "url/url_util.h" using cast_channel::BroadcastRequest; +using cast_channel::CastDeviceCapability; namespace cast_util { + +using media_router::AutoJoinPolicy; +using media_router::DefaultActionPolicy; + template <> -const EnumTable<media_router::AutoJoinPolicy> - EnumTable<media_router::AutoJoinPolicy>::instance({ - {media_router::AutoJoinPolicy::kTabAndOriginScoped, - "tab_and_origin_scoped"}, - {media_router::AutoJoinPolicy::kOriginScoped, "origin_scoped"}, - {media_router::AutoJoinPolicy::kPageScoped, "page_scoped"}, - // kNone deliberately omitted. - }); +const EnumTable<AutoJoinPolicy> EnumTable<AutoJoinPolicy>::instance({ + {AutoJoinPolicy::kPageScoped, "page_scoped"}, + {AutoJoinPolicy::kTabAndOriginScoped, "tab_and_origin_scoped"}, + {AutoJoinPolicy::kOriginScoped, "origin_scoped"}, +}); + +template <> +const EnumTable<DefaultActionPolicy> EnumTable<DefaultActionPolicy>::instance({ + {DefaultActionPolicy::kCreateSession, "create_session"}, + {DefaultActionPolicy::kCastThisTab, "cast_this_tab"}, +}); + +template <> +const EnumTable<CastDeviceCapability> EnumTable<CastDeviceCapability>::instance( + { + {CastDeviceCapability::MULTIZONE_GROUP, "multizone_group"}, + {CastDeviceCapability::DEV_MODE, "dev_mode"}, + {CastDeviceCapability::AUDIO_IN, "audio_in"}, + {CastDeviceCapability::AUDIO_OUT, "audio_out"}, + {CastDeviceCapability::VIDEO_IN, "video_in"}, + {CastDeviceCapability::VIDEO_OUT, "video_out"}, + // NONE deliberately omitted + }, + UnsortedEnumTable); + } // namespace cast_util namespace media_router { namespace { -// Parameter keys used by new Cast URLs. -constexpr char kCapabilitiesKey[] = "capabilities"; -constexpr char kBroadcastNamespaceKey[] = "broadcastNamespace"; -constexpr char kBroadcastMessageKey[] = "broadcastMessage"; -constexpr char kClientIdKey[] = "clientId"; -constexpr char kLaunchTimeoutKey[] = "launchTimeout"; -constexpr char kAutoJoinPolicyKey[] = "autoJoinPolicy"; +// A nonmember version of base::Optional::value_or that works on pointers as +// well as instance of base::Optional. +template <typename T> +inline auto value_or(const T& optional, + const std::decay_t<decltype(*optional)>& default_value) + -> std::decay_t<decltype(*optional)> { + return optional ? *optional : default_value; +} -// Parameter keys used by legacy Cast URLs. -constexpr char kLegacyAppIdKey[] = "__castAppId__"; -constexpr char kLegacyBroadcastNamespaceKey[] = "__castBroadcastNamespace__"; -constexpr char kLegacyBroadcastMessageKey[] = "__castBroadcastMessage__"; -constexpr char kLegacyClientIdKey[] = "__castClientId__"; -constexpr char kLegacyLaunchTimeoutKey[] = "__castLaunchTimeout__"; -constexpr char kLegacyAutoJoinPolicyKey[] = "__castAutoJoinPolicy__"; +// FindValue() looks up the value associated with a key |key| in a map-like +// object |map| and returns a pointer to the value if |key| is found, or nullptr +// otherwise. +// +// The type of |map| can be anything that supports a find() method like +// std::map::find, or any iterable object whose values are key/value pairs. +// +// See also FindValueOr(). + +// Overload for types with a find() method. +template <typename Map, typename = typename Map::key_type> +inline const typename Map::mapped_type* FindValue( + const Map& map, + const typename Map::key_type& key) { + auto it = map.find(key); + if (it == map.end()) + return nullptr; + return &it->second; +} + +// Overload for types without a find() method. +template <typename Map, typename Key> +auto FindValue(const Map& map, const Key& key) -> const + decltype(begin(map)->second)* { + for (const auto& item : map) { + if (item.first == key) + return &item.second; + } + return nullptr; +} + +// Looks up the value associated with a key |key| in a map-like object |map| and +// returns a reference to the value if |key| is found, or |default_value| +// otherwise. +// +// The type of |map| can be anything that supports a find() method like +// std::map::find, or any iterable object whose values are key/value pairs. +template <typename Map, typename Key, typename T> +inline auto FindValueOr(const Map& map, const Key& key, const T& default_value) + -> std::decay_t<decltype(*FindValue(map, key))> { + return value_or(FindValue(map, key), default_value); +} + +// Creates a map from the query parameters of |url|. If |url| contains multiple +// values for the same parameter, the last value is used. +base::flat_map<std::string, std::string> MakeQueryMap(const GURL& url) { + base::flat_map<std::string, std::string> result; + for (net::QueryIterator query_it(url); !query_it.IsAtEnd(); + query_it.Advance()) { + result[query_it.GetKey()] = query_it.GetValue(); + } + return result; +} // TODO(imcheng): Move to common utils? std::string DecodeURLComponent(const std::string& encoded) { @@ -60,20 +133,22 @@ return std::string(); } -cast_channel::CastDeviceCapability CastDeviceCapabilityFromString( +// Converts a string containing a comma-separated list of capabilities into a +// bitwise OR of CastDeviceCapability values. +BitwiseOr<CastDeviceCapability> CastDeviceCapabilitiesFromString( const base::StringPiece& s) { - if (s == "video_out") - return cast_channel::CastDeviceCapability::VIDEO_OUT; - if (s == "video_in") - return cast_channel::CastDeviceCapability::VIDEO_IN; - if (s == "audio_out") - return cast_channel::CastDeviceCapability::AUDIO_OUT; - if (s == "audio_in") - return cast_channel::CastDeviceCapability::AUDIO_IN; - if (s == "multizone_group") - return cast_channel::CastDeviceCapability::MULTIZONE_GROUP; - - return cast_channel::CastDeviceCapability::NONE; + BitwiseOr<CastDeviceCapability> result{}; + for (const auto& capability_str : base::SplitStringPiece( + s, ",", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) { + const auto capability = + cast_util::StringToEnum<CastDeviceCapability>(capability_str); + if (capability) { + result.Add(*capability); + } else { + DLOG(ERROR) << "Unkown capability name: " << capability_str; + } + } + return result; } std::unique_ptr<CastMediaSource> CastMediaSourceForTabMirroring( @@ -92,28 +167,38 @@ source_id, std::vector<CastAppInfo>({CastAppInfo(kCastStreamingAppId)})); } +// The logic shared by ParseCastUrl() and ParseLegacyCastUrl(). std::unique_ptr<CastMediaSource> CreateFromURLParams( const MediaSource::Id& source_id, const std::vector<CastAppInfo>& app_infos, const std::string& auto_join_policy_str, + const std::string& default_action_policy_str, const std::string& client_id, const std::string& broadcast_namespace, - const std::string& broadcast_message, - base::TimeDelta launch_timeout) { + const std::string& encoded_broadcast_message, + const std::string& launch_timeout_str) { if (app_infos.empty()) return nullptr; auto cast_source = std::make_unique<CastMediaSource>( source_id, app_infos, cast_util::StringToEnum<AutoJoinPolicy>(auto_join_policy_str) - .value_or(AutoJoinPolicy::kNone)); + .value_or(AutoJoinPolicy::kPageScoped), + cast_util::StringToEnum<DefaultActionPolicy>(default_action_policy_str) + .value_or(DefaultActionPolicy::kCreateSession)); cast_source->set_client_id(client_id); - if (!broadcast_namespace.empty() && !broadcast_message.empty()) { - cast_source->set_broadcast_request( - BroadcastRequest(broadcast_namespace, broadcast_message)); + if (!broadcast_namespace.empty() && !encoded_broadcast_message.empty()) { + cast_source->set_broadcast_request(BroadcastRequest( + broadcast_namespace, DecodeURLComponent(encoded_broadcast_message))); } - if (launch_timeout > base::TimeDelta()) - cast_source->set_launch_timeout(launch_timeout); + + int launch_timeout_millis; + if (base::StringToInt(launch_timeout_str, &launch_timeout_millis) && + launch_timeout_millis > 0) { + cast_source->set_launch_timeout( + base::TimeDelta::FromMilliseconds(launch_timeout_millis)); + } + return cast_source; } @@ -124,78 +209,30 @@ if (app_id.empty()) return nullptr; - std::string broadcast_namespace, broadcast_message, capabilities; - std::string client_id, auto_join_policy; - int launch_timeout_millis = 0; - for (net::QueryIterator query_it(url); !query_it.IsAtEnd(); - query_it.Advance()) { - std::string key = query_it.GetKey(); - std::string value = query_it.GetValue(); - if (key.empty() || value.empty()) - continue; - if (key == kBroadcastNamespaceKey) { - broadcast_namespace = value; - } else if (key == kBroadcastMessageKey) { - // The broadcast message is URL-encoded. - broadcast_message = DecodeURLComponent(value); - } else if (key == kCapabilitiesKey) { - capabilities = value; - } else if (key == kClientIdKey) { - client_id = value; - } else if (key == kLaunchTimeoutKey) { - if (!base::StringToInt(value, &launch_timeout_millis) || - launch_timeout_millis < 0) - launch_timeout_millis = 0; - } else if (key == kAutoJoinPolicyKey) { - auto_join_policy = value; - } - } - - CastAppInfo app_info(app_id); - if (!capabilities.empty()) { - for (const auto& capability : - base::SplitStringPiece(capabilities, ",", base::KEEP_WHITESPACE, - base::SPLIT_WANT_NONEMPTY)) { - app_info.required_capabilities |= - CastDeviceCapabilityFromString(capability); - } - } - + auto params{MakeQueryMap(url)}; return CreateFromURLParams( - source_id, {app_info}, auto_join_policy, client_id, broadcast_namespace, - broadcast_message, - base::TimeDelta::FromMilliseconds(launch_timeout_millis)); + source_id, + {CastAppInfo(app_id, CastDeviceCapabilitiesFromString( + FindValueOr(params, "capabilities", "")))}, + FindValueOr(params, "autoJoinPolicy", ""), + FindValueOr(params, "defaultActionPolicy", ""), + FindValueOr(params, "clientId", ""), + FindValueOr(params, "broadcastNamespace", ""), + FindValueOr(params, "broadcastMessage", ""), + FindValueOr(params, "launchTimeout", "")); } std::unique_ptr<CastMediaSource> ParseLegacyCastUrl( const MediaSource::Id& source_id, const GURL& url) { - base::StringPairs parameters; - base::SplitStringIntoKeyValuePairs(url.ref(), '=', '/', ¶meters); + base::StringPairs params; + base::SplitStringIntoKeyValuePairs(url.ref(), '=', '/', ¶ms); + // Legacy URLs can specify multiple apps. std::vector<std::string> app_id_params; - std::string broadcast_namespace, broadcast_message; - std::string client_id, auto_join_policy; - int launch_timeout_millis = 0; - for (const auto& key_value : parameters) { - const auto& key = key_value.first; - const auto& value = key_value.second; - if (key == kLegacyAppIdKey) { - app_id_params.push_back(value); - } else if (key == kLegacyBroadcastNamespaceKey) { - broadcast_namespace = value; - } else if (key == kLegacyBroadcastMessageKey) { - // The broadcast message is URL-encoded. - broadcast_message = DecodeURLComponent(value); - } else if (key == kLegacyClientIdKey) { - client_id = value; - } else if (key == kLegacyLaunchTimeoutKey) { - if (!base::StringToInt(value, &launch_timeout_millis) || - launch_timeout_millis < 0) - launch_timeout_millis = 0; - } else if (key == kLegacyAutoJoinPolicyKey) { - auto_join_policy = value; - } + for (const auto& param : params) { + if (param.first == "__castAppId__") + app_id_params.push_back(param.second); } std::vector<CastAppInfo> app_infos; @@ -217,13 +254,8 @@ if (app_id.empty()) continue; - CastAppInfo app_info(app_id); - for (const auto& capability : - base::SplitStringPiece(capabilities, ",", base::KEEP_WHITESPACE, - base::SPLIT_WANT_NONEMPTY)) { - app_info.required_capabilities |= - CastDeviceCapabilityFromString(capability); - } + CastAppInfo app_info(app_id, + CastDeviceCapabilitiesFromString(capabilities)); app_infos.push_back(app_info); } @@ -232,14 +264,20 @@ return nullptr; return CreateFromURLParams( - source_id, app_infos, auto_join_policy, client_id, broadcast_namespace, - broadcast_message, - base::TimeDelta::FromMilliseconds(launch_timeout_millis)); + source_id, app_infos, FindValueOr(params, "__castAutoJoinPolicy__", ""), + FindValueOr(params, "__castDefaultActionPolicy__", ""), + FindValueOr(params, "__castClientId__", ""), + FindValueOr(params, "__castBroadcastNamespace__", ""), + FindValueOr(params, "__castBroadcastMessage__", ""), + FindValueOr(params, "__castLaunchTimeout__", "")); } } // namespace -CastAppInfo::CastAppInfo(const std::string& app_id) : app_id(app_id) {} +CastAppInfo::CastAppInfo( + const std::string& app_id, + BitwiseOr<cast_channel::CastDeviceCapability> required_capabilities) + : app_id(app_id), required_capabilities(required_capabilities) {} CastAppInfo::~CastAppInfo() = default; CastAppInfo::CastAppInfo(const CastAppInfo& other) = default; @@ -279,10 +317,12 @@ CastMediaSource::CastMediaSource(const MediaSource::Id& source_id, const std::vector<CastAppInfo>& app_infos, - AutoJoinPolicy auto_join_policy) + AutoJoinPolicy auto_join_policy, + DefaultActionPolicy default_action_policy) : source_id_(source_id), app_infos_(app_infos), - auto_join_policy_(auto_join_policy) {} + auto_join_policy_(auto_join_policy), + default_action_policy_(default_action_policy) {} CastMediaSource::CastMediaSource(const CastMediaSource& other) = default; CastMediaSource::~CastMediaSource() = default;
diff --git a/chrome/common/media_router/providers/cast/cast_media_source.h b/chrome/common/media_router/providers/cast/cast_media_source.h index bda28af..c5441df 100644 --- a/chrome/common/media_router/providers/cast/cast_media_source.h +++ b/chrome/common/media_router/providers/cast/cast_media_source.h
@@ -5,10 +5,13 @@ #ifndef CHROME_COMMON_MEDIA_ROUTER_PROVIDERS_CAST_CAST_MEDIA_SOURCE_H_ #define CHROME_COMMON_MEDIA_ROUTER_PROVIDERS_CAST_CAST_MEDIA_SOURCE_H_ +#include <initializer_list> #include <memory> #include <string> +#include <type_traits> #include <vector> +#include "base/logging.h" #include "base/optional.h" #include "chrome/common/media_router/media_source.h" #include "components/cast_channel/cast_message_util.h" @@ -26,9 +29,37 @@ static constexpr base::TimeDelta kDefaultLaunchTimeout = base::TimeDelta::FromSeconds(60); +// Class for storing a bitwise OR of enum values. +// +// TODO(jrw): Make values of cast_channel::CastDeviceCapability consecutive and +// store sets of values using a class like v8::base::EnumSet instead of this +// monstrosity. +template <typename E, typename T = std::underlying_type_t<E>> +class BitwiseOr { + public: + constexpr BitwiseOr() : bits_(0) {} + constexpr BitwiseOr(std::initializer_list<E> values) : bits_(0) { + for (E e : values) + Add(e); + } + bool empty() const { return bits_ == 0; } + void Add(E value) { bits_ |= Mask(value); } + bool operator==(const BitwiseOr& other) const { return bits_ == other.bits_; } + bool operator!=(const BitwiseOr& other) const { return *this != other; } + + private: + static T Mask(E value) { + const T result = static_cast<T>(value); + DCHECK(static_cast<E>(result) == value); + return result; + } + T bits_; +}; + // Represents a Cast app and its capabilitity requirements. struct CastAppInfo { - explicit CastAppInfo(const std::string& app_id); + explicit CastAppInfo(const std::string& app_id, + BitwiseOr<cast_channel::CastDeviceCapability> = {}); ~CastAppInfo(); CastAppInfo(const CastAppInfo& other); @@ -36,22 +67,35 @@ std::string app_id; // A bitset of capabilities required by the app. - int required_capabilities = cast_channel::CastDeviceCapability::NONE; + BitwiseOr<cast_channel::CastDeviceCapability> required_capabilities; }; // Auto-join policy determines when the SDK will automatically connect a sender // application to an existing session after API initialization. enum class AutoJoinPolicy { + // No automatic connection. + kPageScoped, // Automatically connects when the session was started with the same app ID, // in the same tab and page origin. kTabAndOriginScoped, // Automatically connects when the session was started with the same app ID // and the same page origin (regardless of tab). kOriginScoped, - // No automatic connection. - kPageScoped, - // No policy was specified. Generally treated the same as kPageScoped. - kNone, +}; + +// Default action policy determines when the SDK will automatically create a +// session after initializing the API. This also controls the default action +// for the tab in the Cast dialog. +enum class DefaultActionPolicy { + // If the tab containing the app is being cast when the API initializes, the + // SDK stops tab casting and automatically launches the app. The Cast dialog + // prompts the user to cast the app. + kCreateSession, + + // No automatic launch is done after initializing the API, even if the tab is + // being cast. The Cast dialog prompts the user to mirror the tab (mirror, + // not cast, despite the name). + kCastThisTab, }; // Represents a MediaSource parsed into structured, Cast specific data. The @@ -69,7 +113,9 @@ CastMediaSource(const MediaSource::Id& source_id, const std::vector<CastAppInfo>& app_infos, - AutoJoinPolicy auto_join_policy = AutoJoinPolicy::kNone); + AutoJoinPolicy auto_join_policy = AutoJoinPolicy::kPageScoped, + DefaultActionPolicy default_action_policy = + DefaultActionPolicy::kCreateSession); CastMediaSource(const CastMediaSource& other); ~CastMediaSource(); @@ -92,17 +138,17 @@ const { return broadcast_request_; } - void set_broadcast_request(const cast_channel::BroadcastRequest& request) { broadcast_request_ = request; } - AutoJoinPolicy auto_join_policy() const { return auto_join_policy_; } + DefaultActionPolicy default_action_policy() { return default_action_policy_; } private: MediaSource::Id source_id_; std::vector<CastAppInfo> app_infos_; AutoJoinPolicy auto_join_policy_; + DefaultActionPolicy default_action_policy_; base::TimeDelta launch_timeout_ = kDefaultLaunchTimeout; // Empty if not set. std::string client_id_;
diff --git a/chrome/common/media_router/providers/cast/cast_media_source_unittest.cc b/chrome/common/media_router/providers/cast/cast_media_source_unittest.cc index a9f9747..7073e8e2 100644 --- a/chrome/common/media_router/providers/cast/cast_media_source_unittest.cc +++ b/chrome/common/media_router/providers/cast/cast_media_source_unittest.cc
@@ -7,16 +7,38 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +using cast_channel::CastDeviceCapability; + namespace media_router { +TEST(CastMediaSourceTest, FromCastURLWithDefaults) { + MediaSource::Id source_id("cast:ABCDEFAB"); + std::unique_ptr<CastMediaSource> source = + CastMediaSource::FromMediaSourceId(source_id); + ASSERT_TRUE(source); + EXPECT_EQ(source_id, source->source_id()); + ASSERT_EQ(1u, source->app_infos().size()); + const CastAppInfo& app_info = source->app_infos()[0]; + EXPECT_EQ("ABCDEFAB", app_info.app_id); + EXPECT_TRUE(app_info.required_capabilities.empty()); + const auto& broadcast_request = source->broadcast_request(); + EXPECT_FALSE(broadcast_request); + EXPECT_EQ("", source->client_id()); + EXPECT_EQ(kDefaultLaunchTimeout, source->launch_timeout()); + EXPECT_EQ(AutoJoinPolicy::kPageScoped, source->auto_join_policy()); + EXPECT_EQ(DefaultActionPolicy::kCreateSession, + source->default_action_policy()); +} + TEST(CastMediaSourceTest, FromCastURL) { MediaSource::Id source_id( "cast:ABCDEFAB?capabilities=video_out,audio_out" "&broadcastNamespace=namespace" - "&broadcastMessage=message" + "&broadcastMessage=message%25" "&clientId=12345" "&launchTimeout=30000" - "&autoJoinPolicy=tab_and_origin_scoped"); + "&autoJoinPolicy=tab_and_origin_scoped" + "&defaultActionPolicy=cast_this_tab"); std::unique_ptr<CastMediaSource> source = CastMediaSource::FromMediaSourceId(source_id); ASSERT_TRUE(source); @@ -24,43 +46,49 @@ ASSERT_EQ(1u, source->app_infos().size()); const CastAppInfo& app_info = source->app_infos()[0]; EXPECT_EQ("ABCDEFAB", app_info.app_id); - EXPECT_EQ(cast_channel::CastDeviceCapability::VIDEO_OUT | - cast_channel::CastDeviceCapability::AUDIO_OUT, + EXPECT_EQ((BitwiseOr<CastDeviceCapability>{CastDeviceCapability::VIDEO_OUT, + CastDeviceCapability::AUDIO_OUT}), app_info.required_capabilities); const auto& broadcast_request = source->broadcast_request(); ASSERT_TRUE(broadcast_request); EXPECT_EQ("namespace", broadcast_request->broadcast_namespace); - EXPECT_EQ("message", broadcast_request->message); + EXPECT_EQ("message%", broadcast_request->message); EXPECT_EQ("12345", source->client_id()); EXPECT_EQ(base::TimeDelta::FromMilliseconds(30000), source->launch_timeout()); EXPECT_EQ(AutoJoinPolicy::kTabAndOriginScoped, source->auto_join_policy()); + EXPECT_EQ(DefaultActionPolicy::kCastThisTab, source->default_action_policy()); } TEST(CastMediaSourceTest, FromLegacyCastURL) { MediaSource::Id source_id( - "https://google.com/cast#__castAppId__=ABCDEFAB(video_out,audio_out)" + "https://google.com/cast" + "#__castAppId__=ABCDEFAB(video_out,audio_out)" + "/__castAppId__=otherAppId" "/__castBroadcastNamespace__=namespace" - "/__castBroadcastMessage__=message" + "/__castBroadcastMessage__=message%25" "/__castClientId__=12345" "/__castLaunchTimeout__=30000" - "/__castAutoJoinPolicy__=origin_scoped"); + "/__castAutoJoinPolicy__=origin_scoped" + "/__castDefaultActionPolicy__=cast_this_tab"); std::unique_ptr<CastMediaSource> source = CastMediaSource::FromMediaSourceId(source_id); ASSERT_TRUE(source); EXPECT_EQ(source_id, source->source_id()); - ASSERT_EQ(1u, source->app_infos().size()); + ASSERT_EQ(2u, source->app_infos().size()); const CastAppInfo& app_info = source->app_infos()[0]; EXPECT_EQ("ABCDEFAB", app_info.app_id); - EXPECT_EQ(cast_channel::CastDeviceCapability::VIDEO_OUT | - cast_channel::CastDeviceCapability::AUDIO_OUT, + EXPECT_EQ((BitwiseOr<CastDeviceCapability>{CastDeviceCapability::VIDEO_OUT, + CastDeviceCapability::AUDIO_OUT}), app_info.required_capabilities); + EXPECT_EQ("otherAppId", source->app_infos()[1].app_id); const auto& broadcast_request = source->broadcast_request(); ASSERT_TRUE(broadcast_request); EXPECT_EQ("namespace", broadcast_request->broadcast_namespace); - EXPECT_EQ("message", broadcast_request->message); + EXPECT_EQ("message%", broadcast_request->message); EXPECT_EQ("12345", source->client_id()); EXPECT_EQ(base::TimeDelta::FromMilliseconds(30000), source->launch_timeout()); EXPECT_EQ(AutoJoinPolicy::kOriginScoped, source->auto_join_policy()); + EXPECT_EQ(DefaultActionPolicy::kCastThisTab, source->default_action_policy()); } TEST(CastMediaSourceTest, FromPresentationURL) { @@ -74,7 +102,9 @@ EXPECT_EQ(kCastStreamingAudioAppId, source->app_infos()[1].app_id); EXPECT_TRUE(source->client_id().empty()); EXPECT_EQ(kDefaultLaunchTimeout, source->launch_timeout()); - EXPECT_EQ(AutoJoinPolicy::kNone, source->auto_join_policy()); + EXPECT_EQ(AutoJoinPolicy::kPageScoped, source->auto_join_policy()); + EXPECT_EQ(DefaultActionPolicy::kCreateSession, + source->default_action_policy()); } TEST(CastMediaSourceTest, FromMirroringURN) { @@ -88,7 +118,9 @@ EXPECT_EQ(kCastStreamingAudioAppId, source->app_infos()[1].app_id); EXPECT_TRUE(source->client_id().empty()); EXPECT_EQ(kDefaultLaunchTimeout, source->launch_timeout()); - EXPECT_EQ(AutoJoinPolicy::kNone, source->auto_join_policy()); + EXPECT_EQ(AutoJoinPolicy::kPageScoped, source->auto_join_policy()); + EXPECT_EQ(DefaultActionPolicy::kCreateSession, + source->default_action_policy()); } TEST(CastMediaSourceTest, FromDesktopUrn) { @@ -101,7 +133,9 @@ EXPECT_EQ(kCastStreamingAppId, source->app_infos()[0].app_id); EXPECT_TRUE(source->client_id().empty()); EXPECT_EQ(kDefaultLaunchTimeout, source->launch_timeout()); - EXPECT_EQ(AutoJoinPolicy::kNone, source->auto_join_policy()); + EXPECT_EQ(AutoJoinPolicy::kPageScoped, source->auto_join_policy()); + EXPECT_EQ(DefaultActionPolicy::kCreateSession, + source->default_action_policy()); } TEST(CastMediaSourceTest, FromInvalidSource) {
diff --git a/chromeos/constants/chromeos_switches.cc b/chromeos/constants/chromeos_switches.cc index 86b94e9..0da8799 100644 --- a/chromeos/constants/chromeos_switches.cc +++ b/chromeos/constants/chromeos_switches.cc
@@ -278,10 +278,6 @@ const char kDisableSigninFrameClientCertUserSelection[] = "disable-signin-frame-client-cert-user-selection"; -// Disables SystemTimezoneAutomaticDetection policy. -const char kDisableSystemTimezoneAutomaticDetectionPolicy[] = - "disable-system-timezone-automatic-detection"; - // Disables volume adjust sound. const char kDisableVolumeAdjustSound[] = "disable-volume-adjust-sound";
diff --git a/chromeos/constants/chromeos_switches.h b/chromeos/constants/chromeos_switches.h index aed69b8..4dc3698 100644 --- a/chromeos/constants/chromeos_switches.h +++ b/chromeos/constants/chromeos_switches.h
@@ -103,8 +103,6 @@ COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kDisableSigninFrameClientCertUserSelection[]; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) -extern const char kDisableSystemTimezoneAutomaticDetectionPolicy[]; -COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kDisableVolumeAdjustSound[]; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kDisableWakeOnWifi[]; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kEnableArc[];
diff --git a/components/content_capture/browser/content_capture_receiver.cc b/components/content_capture/browser/content_capture_receiver.cc index 327b209..b0573e9 100644 --- a/components/content_capture/browser/content_capture_receiver.cc +++ b/components/content_capture/browser/content_capture_receiver.cc
@@ -97,18 +97,22 @@ const ContentCaptureData& ContentCaptureReceiver::GetFrameContentCaptureData() { base::string16 url = base::UTF8ToUTF16(rfh_->GetLastCommittedURL().spec()); - if (url != frame_content_capture_data_.value) { - if (frame_content_capture_data_.id != 0) { - auto* manager = ContentCaptureReceiverManager::FromWebContents( - content::WebContents::FromRenderFrameHost(rfh_)); - manager->DidRemoveSession(this); - } + if (url == frame_content_capture_data_.value) + return frame_content_capture_data_; - frame_content_capture_data_.id = id_; - frame_content_capture_data_.value = url; - const base::Optional<gfx::Size>& size = rfh_->GetFrameSize(); - if (size.has_value()) - frame_content_capture_data_.bounds = gfx::Rect(size.value()); + bool should_remove_session = frame_content_capture_data_.id != 0; + frame_content_capture_data_.id = id_; + frame_content_capture_data_.value = url; + const base::Optional<gfx::Size>& size = rfh_->GetFrameSize(); + if (size.has_value()) + frame_content_capture_data_.bounds = gfx::Rect(size.value()); + + // frame_content_capture_data_ must be set to new value before removing + // sesesion, otherwises, it causes infinite loop. + if (should_remove_session) { + auto* manager = ContentCaptureReceiverManager::FromWebContents( + content::WebContents::FromRenderFrameHost(rfh_)); + manager->DidRemoveSession(this); } return frame_content_capture_data_; }
diff --git a/components/content_capture/browser/content_capture_receiver_test.cc b/components/content_capture/browser/content_capture_receiver_test.cc index 1a0b35f..7c411e0 100644 --- a/components/content_capture/browser/content_capture_receiver_test.cc +++ b/components/content_capture/browser/content_capture_receiver_test.cc
@@ -19,6 +19,7 @@ namespace { static const char kMainFrameUrl[] = "http://foo.com/main.html"; +static const char kMainFrameUrl2[] = "http://foo.com/2.html"; static const char kChildFrameUrl[] = "http://foo.org/child.html"; // Fake ContentCaptureSender to call ContentCaptureReceiver mojom interface. @@ -378,7 +379,34 @@ EXPECT_EQ(GetExpectedTestData2(false /* main_frame */), content_capture_receiver_manager_helper()->captured_data()); - // When main frame navigates to another URL, the parent session will change. + // When main frame navigates to same url, the parent session will not change. + NavigateMainFrame(GURL(kMainFrameUrl)); + SetupChildFrame(); + DidCaptureContentForChildFrame(test_data2(), true /* first_data */); + VerifySession(expected, + content_capture_receiver_manager_helper()->parent_session()); + EXPECT_TRUE( + content_capture_receiver_manager_helper()->removed_session().empty()); + + // When main frame navigates to same domain, the parent session will change. + NavigateMainFrame(GURL(kMainFrameUrl2)); + SetupChildFrame(); + DidCaptureContentForChildFrame(test_data2(), true /* first_data */); + + // Intentionally reuse the data.id from previous result, so we know navigating + // to same domain didn't create new ContentCaptureReceiver when call + // VerifySession(), otherwise, we can't test the code to handle the navigation + // in ContentCaptureReceiver. + data.value = base::ASCIIToUTF16(kMainFrameUrl2); + // Currently, there is no way to fake frame size, set it to 0. + data.bounds = gfx::Rect(); + expected.clear(); + expected.push_back(data); + VerifySession(expected, + content_capture_receiver_manager_helper()->parent_session()); + + // When main frame navigates to different domain, the parent session will + // change. NavigateMainFrame(GURL(kChildFrameUrl)); SetupChildFrame(); DidCaptureContentForChildFrame(test_data2(), true /* first_data */);
diff --git a/components/gwp_asan/client/guarded_page_allocator.cc b/components/gwp_asan/client/guarded_page_allocator.cc index 66146a7..fa627e59 100644 --- a/components/gwp_asan/client/guarded_page_allocator.cc +++ b/components/gwp_asan/client/guarded_page_allocator.cc
@@ -269,8 +269,8 @@ base::debug::CollectStackTrace(trace, AllocatorState::kMaxStackFrames); metadata_[metadata_idx].alloc.trace_len = Pack(reinterpret_cast<uintptr_t*>(trace), len, - metadata_[metadata_idx].alloc.packed_trace, - sizeof(metadata_[metadata_idx].alloc.packed_trace)); + metadata_[metadata_idx].stack_trace_pool, + sizeof(metadata_[metadata_idx].stack_trace_pool) / 2); metadata_[metadata_idx].alloc.tid = ReportTid(); metadata_[metadata_idx].alloc.trace_collected = true; @@ -287,8 +287,10 @@ base::debug::CollectStackTrace(trace, AllocatorState::kMaxStackFrames); metadata_[metadata_idx].dealloc.trace_len = Pack(reinterpret_cast<uintptr_t*>(trace), len, - metadata_[metadata_idx].dealloc.packed_trace, - sizeof(metadata_[metadata_idx].dealloc.packed_trace)); + metadata_[metadata_idx].stack_trace_pool + + metadata_[metadata_idx].alloc.trace_len, + sizeof(metadata_[metadata_idx].stack_trace_pool) - + metadata_[metadata_idx].alloc.trace_len); metadata_[metadata_idx].dealloc.tid = ReportTid(); metadata_[metadata_idx].dealloc.trace_collected = true; }
diff --git a/components/gwp_asan/common/allocator_state.h b/components/gwp_asan/common/allocator_state.h index 4e3d9240..fff558e 100644 --- a/components/gwp_asan/common/allocator_state.h +++ b/components/gwp_asan/common/allocator_state.h
@@ -49,11 +49,12 @@ // Invalid metadata index. static constexpr MetadataIdx kInvalidMetadataIdx = kMaxMetadata; - // Maximum number of stack trace frames to collect. - static constexpr size_t kMaxStackFrames = 60; - // Number of bytes to allocate for packed stack traces. This can hold - // approximately kMaxStackFrames under normal conditions. - static constexpr size_t kMaxPackedTraceLength = 200; + // Maximum number of stack trace frames to collect for an allocation or + // deallocation. + static constexpr size_t kMaxStackFrames = 100; + // Number of bytes to allocate for both allocation and deallocation packed + // stack traces. (Stack trace entries take ~3.5 bytes on average.) + static constexpr size_t kMaxPackedTraceLength = 400; static_assert(std::numeric_limits<SlotIdx>::max() >= kMaxSlots - 1, "SlotIdx can hold all possible slot index values"); @@ -88,12 +89,14 @@ // (De)allocation thread id or base::kInvalidThreadId if no (de)allocation // occurred. uint64_t tid = base::kInvalidThreadId; - // Packed stack trace. - uint8_t packed_trace[kMaxPackedTraceLength]; // Length used to encode the packed stack trace. - size_t trace_len = 0; + uint16_t trace_len = 0; // Whether a stack trace has been collected for this (de)allocation. bool trace_collected = false; + + static_assert(std::numeric_limits<decltype(trace_len)>::max() >= + kMaxPackedTraceLength - 1, + "trace_len can hold all possible length values."); }; // Size of the allocation @@ -103,6 +106,10 @@ // Used to synchronize whether a deallocation has occurred (e.g. whether a // double free has occurred) between threads. std::atomic<bool> deallocation_occurred{false}; + // Holds the combined allocation/deallocation stack traces. The deallocation + // stack trace is stored immediately after the allocation stack trace to + // optimize on space. + uint8_t stack_trace_pool[kMaxPackedTraceLength]; AllocationInfo alloc; AllocationInfo dealloc;
diff --git a/components/gwp_asan/crash_handler/crash_analyzer.cc b/components/gwp_asan/crash_handler/crash_analyzer.cc index 78f3213..a4458753 100644 --- a/components/gwp_asan/crash_handler/crash_analyzer.cc +++ b/components/gwp_asan/crash_handler/crash_analyzer.cc
@@ -169,10 +169,12 @@ proto->set_allocation_size(metadata.alloc_size); if (metadata.alloc.tid != base::kInvalidThreadId || metadata.alloc.trace_len) - ReadAllocationInfo(metadata.alloc, proto->mutable_allocation()); + ReadAllocationInfo(metadata.stack_trace_pool, 0, metadata.alloc, + proto->mutable_allocation()); if (metadata.dealloc.tid != base::kInvalidThreadId || metadata.dealloc.trace_len) - ReadAllocationInfo(metadata.dealloc, proto->mutable_deallocation()); + ReadAllocationInfo(metadata.stack_trace_pool, metadata.alloc.trace_len, + metadata.dealloc, proto->mutable_deallocation()); } proto->set_region_start(valid_state.pages_base_addr); @@ -185,6 +187,8 @@ } void CrashAnalyzer::ReadAllocationInfo( + const uint8_t* stack_trace, + size_t stack_trace_offset, const SlotMetadata::AllocationInfo& slot_info, gwp_asan::Crash_AllocationInfo* proto_info) { if (slot_info.tid != base::kInvalidThreadId) @@ -193,15 +197,17 @@ if (!slot_info.trace_len || !slot_info.trace_collected) return; - if (slot_info.trace_len > AllocatorState::kMaxPackedTraceLength) { + if (slot_info.trace_len > AllocatorState::kMaxPackedTraceLength || + stack_trace_offset + slot_info.trace_len > + AllocatorState::kMaxPackedTraceLength) { DLOG(ERROR) << "Stack trace length is corrupted: " << slot_info.trace_len; return; } uintptr_t unpacked_stack_trace[AllocatorState::kMaxPackedTraceLength]; size_t unpacked_len = - Unpack(slot_info.packed_trace, slot_info.trace_len, unpacked_stack_trace, - AllocatorState::kMaxPackedTraceLength); + Unpack(stack_trace + stack_trace_offset, slot_info.trace_len, + unpacked_stack_trace, AllocatorState::kMaxPackedTraceLength); if (!unpacked_len) { DLOG(ERROR) << "Failed to unpack stack trace."; return;
diff --git a/components/gwp_asan/crash_handler/crash_analyzer.h b/components/gwp_asan/crash_handler/crash_analyzer.h index d38077c..961814d 100644 --- a/components/gwp_asan/crash_handler/crash_analyzer.h +++ b/components/gwp_asan/crash_handler/crash_analyzer.h
@@ -91,9 +91,11 @@ crashpad::VMAddress gpa_addr, gwp_asan::Crash* proto); - // This method fills out an AllocationInfo protobuf from a - // SlotMetadata::AllocationInfo struct. - static void ReadAllocationInfo(const SlotMetadata::AllocationInfo& slot_info, + // This method fills out an AllocationInfo protobuf from a stack trace + // and a SlotMetadata::AllocationInfo struct. + static void ReadAllocationInfo(const uint8_t* stack_trace, + size_t stack_trace_offset, + const SlotMetadata::AllocationInfo& slot_info, gwp_asan::Crash_AllocationInfo* proto_info); FRIEND_TEST_ALL_PREFIXES(CrashAnalyzerTest, StackTraceCollection);
diff --git a/components/safe_browsing/features.cc b/components/safe_browsing/features.cc index 62e7d58..286f3d7b 100644 --- a/components/safe_browsing/features.cc +++ b/components/safe_browsing/features.cc
@@ -35,9 +35,6 @@ const base::Feature kCommittedSBInterstitials{ "SafeBrowsingCommittedInterstitials", base::FEATURE_DISABLED_BY_DEFAULT}; -const base::Feature kForceEnableResetPasswordWebUI{ - "ForceEnableResetPasswordWebUI", base::FEATURE_DISABLED_BY_DEFAULT}; - const base::Feature kPasswordProtectionForSignedInUsers{ "SafeBrowsingPasswordProtectionForSignedInUsers", base::FEATURE_DISABLED_BY_DEFAULT}; @@ -79,7 +76,6 @@ {&kAdSamplerTriggerFeature, false}, {&kCheckByURLLoaderThrottle, true}, {&kCommittedSBInterstitials, true}, - {&kForceEnableResetPasswordWebUI, true}, {&kPasswordProtectionForSignedInUsers, true}, {&kSuspiciousSiteTriggerQuotaFeature, true}, {&kTelemetryForApkDownloads, true},
diff --git a/components/safe_browsing/features.h b/components/safe_browsing/features.h index 87392b4..c0e311e 100644 --- a/components/safe_browsing/features.h +++ b/components/safe_browsing/features.h
@@ -27,10 +27,6 @@ // navigations instead of overlays. extern const base::Feature kCommittedSBInterstitials; -// Forces the chrome://reset-password page to be shown for review or testing -// purpose. -extern const base::Feature kForceEnableResetPasswordWebUI; - // Enable GAIA password protection for signed-in users. extern const base::Feature kPasswordProtectionForSignedInUsers;
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc index 18867d2..abb70db8 100644 --- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc +++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -1970,6 +1970,11 @@ RunHtmlTest(FILE_PATH_LITERAL("nestedlist.html")); } +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, + AccessibilityButtonWithListboxPopup) { + RunHtmlTest(FILE_PATH_LITERAL("button-with-listbox-popup.html")); +} + // // Regression tests. These don't test a specific web platform feature, // they test a specific web page that crashed or had some bad behavior
diff --git a/content/browser/frame_host/navigation_handle_impl_browsertest.cc b/content/browser/frame_host/navigation_handle_impl_browsertest.cc index 7db1917..8817210a 100644 --- a/content/browser/frame_host/navigation_handle_impl_browsertest.cc +++ b/content/browser/frame_host/navigation_handle_impl_browsertest.cc
@@ -1410,6 +1410,71 @@ EXPECT_FALSE(NavigateToURL(shell(), kUrl2)); } +// Verify that a cross-process navigation in a frame for which the current +// renderer process is not live will not result in leaking a +// RenderProcessHost. See https://crbug.com/949977. +IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest, + NoLeakFromStartingSiteInstance) { + GURL url_a = embedded_test_server()->GetURL("a.com", "/title1.html"); + EXPECT_TRUE(NavigateToURL(shell(), url_a)); + + // Kill the a.com process, to test what happens with the next navigation. + scoped_refptr<SiteInstance> site_instance_a = + shell()->web_contents()->GetMainFrame()->GetSiteInstance(); + EXPECT_TRUE(site_instance_a->HasProcess()); + RenderProcessHost* process_1 = site_instance_a->GetProcess(); + RenderProcessHostWatcher process_exit_observer_1( + process_1, content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); + RenderProcessHostWatcher rph_gone_observer_1( + process_1, content::RenderProcessHostWatcher::WATCH_FOR_HOST_DESTRUCTION); + process_1->Shutdown(RESULT_CODE_KILLED); + process_exit_observer_1.Wait(); + + // Start to navigate the sad tab to another site. + GURL url_b = embedded_test_server()->GetURL("b.com", "/title2.html"); + TestNavigationManager navigation_b(shell()->web_contents(), url_b); + shell()->web_contents()->GetController().LoadURL( + url_b, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + EXPECT_TRUE(navigation_b.WaitForRequestStart()); + + // The starting SiteInstance should be the SiteInstance of the current + // RenderFrameHost. + scoped_refptr<SiteInstance> starting_site_instance = + navigation_b.GetNavigationHandle()->GetStartingSiteInstance(); + EXPECT_EQ(shell()->web_contents()->GetMainFrame()->GetSiteInstance(), + starting_site_instance); + // Because of the sad tab, this is actually the b.com SiteInstance, which + // commits immediately after starting the navigation and has a process. + EXPECT_EQ(GURL("http://b.com"), starting_site_instance->GetSiteURL()); + EXPECT_TRUE(starting_site_instance->HasProcess()); + + // In https://crbug.com/949977, we used the a.com SiteInstance here and didn't + // have a process, and an observer called GetProcess, creating a process. This + // process never went away, even after the SiteInstance was gone. + RenderProcessHost* rph_2 = starting_site_instance->GetProcess(); + RenderProcessHostWatcher process_exit_observer_2( + rph_2, content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); + navigation_b.WaitForNavigationFinished(); + + // Ensure RPH 1 is destroyed, which happens at commit time even before the fix + // for the bug. + rph_gone_observer_1.Wait(); + + // Navigate to another process. This isn't necessary to trigger the original + // leak (when the starting SiteInstance was a.com), but it lets the test + // finish in the case that the starting SiteInstance is b.com, since b.com's + // process goes away with this navigation. + // TODO(creis): There's still a slight risk that other buggy code could find + // site_instance_a and call GetProcess() on it, causing a leak. We'll add a + // backup fix and test for that in a followup CL. + GURL url_c = embedded_test_server()->GetURL("c.com", "/title1.html"); + EXPECT_TRUE(NavigateToURL(shell()->web_contents(), url_c)); + + // Wait for rph_2 to exit when it's not used. This wouldn't happen when the + // bug was present. + process_exit_observer_2.Wait(); +} + // Specialized test that verifies the NavigationHandle gets the HTTPS upgraded // URL from the very beginning of the navigation. class NavigationHandleImplHttpsUpgradeBrowserTest
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc index d55cdbd..41b3e41 100644 --- a/content/browser/frame_host/navigation_request.cc +++ b/content/browser/frame_host/navigation_request.cc
@@ -563,17 +563,6 @@ bindings_ = entry->bindings(); } - // This is needed to get site URLs and assign the expected RenderProcessHost. - // This is not always the same as |source_site_instance|, as it only depends - // on the current frame host, and does not depend on |entry|. - starting_site_instance_ = - frame_tree_node->current_frame_host()->GetSiteInstance(); - - // TODO(alexmos): Using |starting_site_instance_|'s IsolationContext may not - // be correct for cross-BrowsingInstance redirects. - site_url_ = SiteInstanceImpl::GetSiteForURL( - starting_site_instance_->GetIsolationContext(), common_params_.url); - // Update the load flags with cache information. UpdateLoadFlagsWithCacheFlags(&begin_params_->load_flags, common_params_.navigation_type, @@ -811,6 +800,21 @@ DCHECK(frame_tree_node_->navigation_request() == this || is_for_commit); FrameTreeNode* frame_tree_node = frame_tree_node_; + // This is needed to get site URLs and assign the expected RenderProcessHost. + // This is not always the same as |source_site_instance_|, as it only depends + // on the current frame host, and does not depend on |entry|. + // The |starting_site_instance_| needs to be set here instead of the + // constructor since a navigation can be started after the constructor and + // before here, which can set a different RenderFrameHost and a different + // starting SiteInstance. + starting_site_instance_ = + frame_tree_node->current_frame_host()->GetSiteInstance(); + + // TODO(alexmos): Using |starting_site_instance_|'s IsolationContext may not + // be correct for cross-BrowsingInstance redirects. + site_url_ = SiteInstanceImpl::GetSiteForURL( + starting_site_instance_->GetIsolationContext(), common_params_.url); + // Compute the redirect chain. // TODO(clamy): Try to simplify this and have the redirects be part of // CommonNavigationParams.
diff --git a/content/browser/tracing/tracing_controller_impl.cc b/content/browser/tracing/tracing_controller_impl.cc index 4eeaaeb3..862bb76 100644 --- a/content/browser/tracing/tracing_controller_impl.cc +++ b/content/browser/tracing/tracing_controller_impl.cc
@@ -455,17 +455,35 @@ // There are two cases: // 1. Startup duration is not reached. // 2. Or if the trace should be saved to file for --trace-config-file flag. + base::Optional<base::FilePath> startup_trace_file; if (startup_trace_timer_.IsRunning()) { startup_trace_timer_.Stop(); if (startup_trace_file_ != base::FilePath().AppendASCII("none")) { - return std::make_unique<BrowserShutdownProfileDumper>( - startup_trace_file_); + startup_trace_file = startup_trace_file_; } } else if (tracing::TraceStartupConfig::GetInstance() ->ShouldTraceToResultFile()) { - return std::make_unique<BrowserShutdownProfileDumper>( - GetStartupTraceFileName()); + startup_trace_file = GetStartupTraceFileName(); } + if (!startup_trace_file) + return nullptr; + if (!tracing::TracingUsesPerfettoBackend()) { + return std::make_unique<BrowserShutdownProfileDumper>( + startup_trace_file.value()); + } + // Perfetto doesn't support shutdown profiling due to complications + // around service shutdown timings. + // TODO(eseckler): Do something about it. + base::RunLoop run_loop; + StopTracing(CreateFileEndpoint( + startup_trace_file.value(), + base::BindRepeating( + [](base::FilePath trace_file, base::OnceClosure quit_closure) { + OnStoppedStartupTracing(trace_file); + std::move(quit_closure).Run(); + }, + startup_trace_file.value(), run_loop.QuitClosure()))); + run_loop.Run(); return nullptr; }
diff --git a/content/browser/webauth/authenticator_common.cc b/content/browser/webauth/authenticator_common.cc index 028b6d5..a2bddd60 100644 --- a/content/browser/webauth/authenticator_common.cc +++ b/content/browser/webauth/authenticator_common.cc
@@ -539,9 +539,10 @@ void AuthenticatorCommon::UpdateRequestDelegate() { DCHECK(!request_delegate_); + DCHECK(!relying_party_id_.empty()); request_delegate_ = GetContentClient()->browser()->GetWebAuthenticationRequestDelegate( - render_frame_host_); + render_frame_host_, relying_party_id_); } bool AuthenticatorCommon::IsFocused() const { @@ -599,6 +600,31 @@ } DCHECK(!request_); + if (!HasValidEffectiveDomain(caller_origin)) { + ReportSecurityCheckFailure( + RelyingPartySecurityCheckFailure::kOpaqueOrNonSecureOrigin); + bad_message::ReceivedBadMessage(render_frame_host_->GetProcess(), + bad_message::AUTH_INVALID_EFFECTIVE_DOMAIN); + InvokeCallbackAndCleanup(std::move(callback), + blink::mojom::AuthenticatorStatus::INVALID_DOMAIN, + nullptr, Focus::kDontCheck); + return; + } + + if (!IsRelyingPartyIdValid(options->relying_party->id, caller_origin)) { + ReportSecurityCheckFailure( + RelyingPartySecurityCheckFailure::kRelyingPartyIdInvalid); + bad_message::ReceivedBadMessage(render_frame_host_->GetProcess(), + bad_message::AUTH_INVALID_RELYING_PARTY); + InvokeCallbackAndCleanup(std::move(callback), + blink::mojom::AuthenticatorStatus::INVALID_DOMAIN, + nullptr, Focus::kDontCheck); + return; + } + + caller_origin_ = caller_origin; + relying_party_id_ = options->relying_party->id; + UpdateRequestDelegate(); if (!request_delegate_) { InvokeCallbackAndCleanup(std::move(callback), @@ -613,31 +639,6 @@ return; } - caller_origin_ = caller_origin; - relying_party_id_ = options->relying_party->id; - - if (!HasValidEffectiveDomain(caller_origin_)) { - ReportSecurityCheckFailure( - RelyingPartySecurityCheckFailure::kOpaqueOrNonSecureOrigin); - bad_message::ReceivedBadMessage(render_frame_host_->GetProcess(), - bad_message::AUTH_INVALID_EFFECTIVE_DOMAIN); - InvokeCallbackAndCleanup(std::move(callback), - blink::mojom::AuthenticatorStatus::INVALID_DOMAIN, - nullptr, Focus::kDontCheck); - return; - } - - if (!IsRelyingPartyIdValid(relying_party_id_, caller_origin_)) { - ReportSecurityCheckFailure( - RelyingPartySecurityCheckFailure::kRelyingPartyIdInvalid); - bad_message::ReceivedBadMessage(render_frame_host_->GetProcess(), - bad_message::AUTH_INVALID_RELYING_PARTY); - InvokeCallbackAndCleanup(std::move(callback), - blink::mojom::AuthenticatorStatus::INVALID_DOMAIN, - nullptr, Focus::kDontCheck); - return; - } - if (options->authenticator_selection && options->authenticator_selection->require_resident_key && (!base::FeatureList::IsEnabled(device::kWebAuthResidentKeys) || @@ -731,6 +732,10 @@ base::BindRepeating( &device::FidoRequestHandlerBase::InitiatePairingWithDevice, request_->GetWeakPtr()) /* ble_pairing_callback */); + if (options->authenticator_selection && + options->authenticator_selection->require_resident_key) { + request_delegate_->SetMightCreateResidentCredential(true); + } request_->set_observer(request_delegate_.get()); request_->SetPlatformAuthenticatorOrMarkUnavailable( @@ -758,6 +763,31 @@ } DCHECK(!request_); + if (!HasValidEffectiveDomain(caller_origin)) { + ReportSecurityCheckFailure( + RelyingPartySecurityCheckFailure::kOpaqueOrNonSecureOrigin); + bad_message::ReceivedBadMessage(render_frame_host_->GetProcess(), + bad_message::AUTH_INVALID_EFFECTIVE_DOMAIN); + InvokeCallbackAndCleanup(std::move(callback), + blink::mojom::AuthenticatorStatus::INVALID_DOMAIN, + nullptr); + return; + } + + if (!IsRelyingPartyIdValid(options->relying_party_id, caller_origin)) { + ReportSecurityCheckFailure( + RelyingPartySecurityCheckFailure::kRelyingPartyIdInvalid); + bad_message::ReceivedBadMessage(render_frame_host_->GetProcess(), + bad_message::AUTH_INVALID_RELYING_PARTY); + InvokeCallbackAndCleanup(std::move(callback), + blink::mojom::AuthenticatorStatus::INVALID_DOMAIN, + nullptr); + return; + } + + caller_origin_ = caller_origin; + relying_party_id_ = options->relying_party_id; + UpdateRequestDelegate(); if (!request_delegate_) { InvokeCallbackAndCleanup(std::move(callback), @@ -766,8 +796,6 @@ return; } - caller_origin_ = caller_origin; - // Save client data to return with the authenticator response. // TODO(kpaulhamus): Fetch and add the Channel ID/Token Binding ID public key // used to communicate with the origin. @@ -785,35 +813,13 @@ std::move(options->challenge)); } - if (!HasValidEffectiveDomain(caller_origin_)) { - ReportSecurityCheckFailure( - RelyingPartySecurityCheckFailure::kOpaqueOrNonSecureOrigin); - bad_message::ReceivedBadMessage(render_frame_host_->GetProcess(), - bad_message::AUTH_INVALID_EFFECTIVE_DOMAIN); - InvokeCallbackAndCleanup(std::move(callback), - blink::mojom::AuthenticatorStatus::INVALID_DOMAIN, - nullptr); - return; - } - - if (!IsRelyingPartyIdValid(options->relying_party_id, caller_origin_)) { - ReportSecurityCheckFailure( - RelyingPartySecurityCheckFailure::kRelyingPartyIdInvalid); - bad_message::ReceivedBadMessage(render_frame_host_->GetProcess(), - bad_message::AUTH_INVALID_RELYING_PARTY); - InvokeCallbackAndCleanup(std::move(callback), - blink::mojom::AuthenticatorStatus::INVALID_DOMAIN, - nullptr); - return; - } - if (options->allow_credentials.empty() && (!base::FeatureList::IsEnabled(device::kWebAuthResidentKeys) || - !request_delegate_->SupportsResidentKeys())) { - InvokeCallbackAndCleanup( - std::move(callback), - blink::mojom::AuthenticatorStatus::RESIDENT_CREDENTIALS_UNSUPPORTED); - return; + !request_delegate_->SupportsResidentKeys())) { + InvokeCallbackAndCleanup( + std::move(callback), + blink::mojom::AuthenticatorStatus::RESIDENT_CREDENTIALS_UNSUPPORTED); + return; } if (options->appid) { @@ -879,6 +885,8 @@ void AuthenticatorCommon::IsUserVerifyingPlatformAuthenticatorAvailable( blink::mojom::Authenticator:: IsUserVerifyingPlatformAuthenticatorAvailableCallback callback) { + const std::string relying_party_id = + render_frame_host_->GetLastCommittedOrigin().host(); // Use |request_delegate_| if a request is currently in progress; or create a // temporary request delegate otherwise. // @@ -888,7 +896,7 @@ request_delegate_ ? nullptr : GetContentClient()->browser()->GetWebAuthenticationRequestDelegate( - render_frame_host_); + render_frame_host_, relying_party_id); AuthenticatorRequestClientDelegate* request_delegate_ptr = request_delegate_ ? request_delegate_.get() : maybe_request_delegate.get(); @@ -1331,6 +1339,8 @@ get_assertion_response_callback_.Reset(); client_data_json_.clear(); app_id_.reset(); + caller_origin_ = url::Origin(); + relying_party_id_.clear(); attestation_requested_ = false; error_awaiting_user_acknowledgement_ = blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR;
diff --git a/content/browser/webauth/authenticator_impl_unittest.cc b/content/browser/webauth/authenticator_impl_unittest.cc index d6337e6..788e95b 100644 --- a/content/browser/webauth/authenticator_impl_unittest.cc +++ b/content/browser/webauth/authenticator_impl_unittest.cc
@@ -1397,7 +1397,8 @@ public: std::unique_ptr<AuthenticatorRequestClientDelegate> GetWebAuthenticationRequestDelegate( - RenderFrameHost* render_frame_host) override { + RenderFrameHost* render_frame_host, + const std::string& relying_party_id) override { if (return_null_delegate) return nullptr; return std::make_unique<TestAuthenticatorRequestDelegate>( @@ -2682,7 +2683,8 @@ public: std::unique_ptr<AuthenticatorRequestClientDelegate> GetWebAuthenticationRequestDelegate( - RenderFrameHost* render_frame_host) override { + RenderFrameHost* render_frame_host, + const std::string& relying_party_id) override { return std::make_unique<PINTestAuthenticatorRequestDelegate>( supports_pin, expected, &failure_reason); } @@ -3216,9 +3218,11 @@ public: ResidentKeyTestAuthenticatorRequestDelegate( std::string expected_accounts, - std::vector<uint8_t> selected_user_id) + std::vector<uint8_t> selected_user_id, + bool* might_create_resident_credential) : expected_accounts_(expected_accounts), - selected_user_id_(selected_user_id) {} + selected_user_id_(selected_user_id), + might_create_resident_credential_(might_create_resident_credential) {} bool SupportsPIN() const override { return true; } @@ -3267,9 +3271,14 @@ FROM_HERE, base::BindOnce(std::move(callback), std::move(*selected))); } + void SetMightCreateResidentCredential(bool v) override { + *might_create_resident_credential_ = v; + } + private: const std::string expected_accounts_; const std::vector<uint8_t> selected_user_id_; + bool* const might_create_resident_credential_; DISALLOW_COPY_AND_ASSIGN(ResidentKeyTestAuthenticatorRequestDelegate); }; @@ -3278,13 +3287,15 @@ public: std::unique_ptr<AuthenticatorRequestClientDelegate> GetWebAuthenticationRequestDelegate( - RenderFrameHost* render_frame_host) override { + RenderFrameHost* render_frame_host, + const std::string& relying_party_id) override { return std::make_unique<ResidentKeyTestAuthenticatorRequestDelegate>( - expected_accounts, selected_user_id); + expected_accounts, selected_user_id, &might_create_resident_credential); } std::string expected_accounts; std::vector<uint8_t> selected_user_id; + bool might_create_resident_credential = false; }; class ResidentKeyAuthenticatorImplTest : public UVAuthenticatorImplTest { @@ -3339,24 +3350,39 @@ TEST_F(ResidentKeyAuthenticatorImplTest, MakeCredential) { TestServiceManagerContext smc; AuthenticatorPtr authenticator = ConnectToAuthenticator(); - TestMakeCredentialCallback callback_receiver; - authenticator->MakeCredential(make_credential_options(), - callback_receiver.callback()); - callback_receiver.WaitForCallback(); - EXPECT_EQ(AuthenticatorStatus::SUCCESS, callback_receiver.status()); - EXPECT_TRUE(HasUV(callback_receiver)); - ASSERT_EQ(1u, virtual_device_.mutable_state()->registrations.size()); - const device::VirtualFidoDevice::RegistrationData& registration = - virtual_device_.mutable_state()->registrations.begin()->second; - EXPECT_TRUE(registration.is_resident); - ASSERT_TRUE(registration.user.has_value()); - const auto options = make_credential_options(); - EXPECT_EQ(options->user->name, registration.user->user_name()); - EXPECT_EQ(options->user->display_name, - registration.user->user_display_name()); - EXPECT_EQ(options->user->id, registration.user->user_id()); - EXPECT_EQ(options->user->icon, registration.user->user_icon_url()); + for (const bool internal_uv : {false, true}) { + SCOPED_TRACE(::testing::Message() << "internal_uv=" << internal_uv); + test_client_.might_create_resident_credential = false; + + if (internal_uv) { + device::VirtualCtap2Device::Config config; + config.resident_key_support = true; + config.internal_uv_support = true; + virtual_device_.SetCtap2Config(config); + virtual_device_.mutable_state()->fingerprints_enrolled = true; + } + + TestMakeCredentialCallback callback_receiver; + authenticator->MakeCredential(make_credential_options(), + callback_receiver.callback()); + callback_receiver.WaitForCallback(); + EXPECT_EQ(AuthenticatorStatus::SUCCESS, callback_receiver.status()); + + EXPECT_TRUE(test_client_.might_create_resident_credential); + EXPECT_TRUE(HasUV(callback_receiver)); + ASSERT_EQ(1u, virtual_device_.mutable_state()->registrations.size()); + const device::VirtualFidoDevice::RegistrationData& registration = + virtual_device_.mutable_state()->registrations.begin()->second; + EXPECT_TRUE(registration.is_resident); + ASSERT_TRUE(registration.user.has_value()); + const auto options = make_credential_options(); + EXPECT_EQ(options->user->name, registration.user->user_name()); + EXPECT_EQ(options->user->display_name, + registration.user->user_display_name()); + EXPECT_EQ(options->user->id, registration.user->user_id()); + EXPECT_EQ(options->user->icon, registration.user->user_icon_url()); + } } TEST_F(ResidentKeyAuthenticatorImplTest, GetAssertionSingle) {
diff --git a/content/browser/webauth/webauth_browsertest.cc b/content/browser/webauth/webauth_browsertest.cc index ac765d0..8c00e09 100644 --- a/content/browser/webauth/webauth_browsertest.cc +++ b/content/browser/webauth/webauth_browsertest.cc
@@ -289,7 +289,8 @@ std::unique_ptr<AuthenticatorRequestClientDelegate> GetWebAuthenticationRequestDelegate( - RenderFrameHost* render_frame_host) override { + RenderFrameHost* render_frame_host, + const std::string& relying_party_id) override { test_state_->delegate_create_count++; return std::make_unique<WebAuthBrowserTestClientDelegate>(test_state_); }
diff --git a/content/public/browser/authenticator_request_client_delegate.cc b/content/public/browser/authenticator_request_client_delegate.cc index dc2a910..c789d428 100644 --- a/content/public/browser/authenticator_request_client_delegate.cc +++ b/content/public/browser/authenticator_request_client_delegate.cc
@@ -42,6 +42,9 @@ return false; } +void AuthenticatorRequestClientDelegate::SetMightCreateResidentCredential( + bool v) {} + void AuthenticatorRequestClientDelegate::SelectAccount( std::vector<device::AuthenticatorGetAssertionResponse> responses, base::OnceCallback<void(device::AuthenticatorGetAssertionResponse)>
diff --git a/content/public/browser/authenticator_request_client_delegate.h b/content/public/browser/authenticator_request_client_delegate.h index d4ef4b9..6d34ff72 100644 --- a/content/public/browser/authenticator_request_client_delegate.h +++ b/content/public/browser/authenticator_request_client_delegate.h
@@ -92,6 +92,12 @@ // |SelectAccount| will never be called. virtual bool SupportsResidentKeys(); + // SetMightCreateResidentCredential indicates whether activating an + // authenticator may cause a resident credential to be created. A resident + // credential may be discovered by someone with physical access to the + // authenticator and thus has privacy implications. + void SetMightCreateResidentCredential(bool v) override; + // SelectAccount is called to allow the embedder to select between one or more // accounts. This is triggered when the web page requests an unspecified // credential (by passing an empty allow-list). In this case, any accounts
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc index d4cc92d3..13cad74 100644 --- a/content/public/browser/content_browser_client.cc +++ b/content/public/browser/content_browser_client.cc
@@ -862,7 +862,8 @@ std::unique_ptr<AuthenticatorRequestClientDelegate> ContentBrowserClient::GetWebAuthenticationRequestDelegate( - RenderFrameHost* render_frame_host) { + RenderFrameHost* render_frame_host, + const std::string& relying_party_id) { return std::make_unique<AuthenticatorRequestClientDelegate>(); }
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h index b7eb0de..fc58b2d 100644 --- a/content/public/browser/content_browser_client.h +++ b/content/public/browser/content_browser_client.h
@@ -1386,9 +1386,11 @@ // being serviced in a given RenderFrame. The instance is guaranteed to be // destroyed before the RenderFrame goes out of scope. The embedder may choose // to return nullptr to indicate that the request cannot be serviced right - // now. + // now. |relying_party_id| is the RP ID from Webauthn, essentially a domain + // name. virtual std::unique_ptr<AuthenticatorRequestClientDelegate> - GetWebAuthenticationRequestDelegate(RenderFrameHost* render_frame_host); + GetWebAuthenticationRequestDelegate(RenderFrameHost* render_frame_host, + const std::string& relying_party_id); #if defined(OS_MACOSX) // Returns whether WebAuthn supports the built-in Touch ID platform
diff --git a/content/test/data/accessibility/html/button-with-listbox-popup-expected-android.txt b/content/test/data/accessibility/html/button-with-listbox-popup-expected-android.txt new file mode 100644 index 0000000..a67ef11e --- /dev/null +++ b/content/test/data/accessibility/html/button-with-listbox-popup-expected-android.txt
@@ -0,0 +1,8 @@ +android.webkit.WebView focusable focused scrollable +++android.view.View +++++android.view.View name='Choose one:' +++++android.widget.Spinner role_description='pop up button' clickable focusable name='Choose one: Foo' +++++android.widget.ListView role_description='list box' clickable collection focusable name='Choose one:' item_count=3 row_count=3 +++++++android.view.View clickable collection_item focusable name='Baz' +++++++android.view.View clickable collection_item focusable name='Bar' item_index=1 row_index=1 +++++++android.view.View clickable collection_item focusable name='Foo' item_index=2 row_index=2
diff --git a/content/test/data/accessibility/html/button-with-listbox-popup-expected-auralinux.txt b/content/test/data/accessibility/html/button-with-listbox-popup-expected-auralinux.txt new file mode 100644 index 0000000..c0387aab --- /dev/null +++ b/content/test/data/accessibility/html/button-with-listbox-popup-expected-auralinux.txt
@@ -0,0 +1,10 @@ +[document web] +++[section] +++++[section] label-for +++++++[text] name='Choose one:' +++++[push button] name='Choose one: Foo' labelled-by +++++++[text] name='Foo' +++++[list box] name='Choose one:' labelled-by +++++++[list item] name='Baz' selectable +++++++[list item] name='Bar' selectable +++++++[list item] name='Foo' selectable
diff --git a/content/test/data/accessibility/html/button-with-listbox-popup-expected-blink.txt b/content/test/data/accessibility/html/button-with-listbox-popup-expected-blink.txt new file mode 100644 index 0000000..6096db6 --- /dev/null +++ b/content/test/data/accessibility/html/button-with-listbox-popup-expected-blink.txt
@@ -0,0 +1,12 @@ +rootWebArea +++genericContainer +++++genericContainer +++++++staticText name='Choose one:' +++++++++inlineTextBox name='Choose one:' +++++popUpButton name='Choose one: Foo' +++++++staticText name='Foo' +++++++++inlineTextBox name='Foo' +++++listBox name='Choose one:' +++++++listBoxOption name='Baz' selected=false +++++++listBoxOption name='Bar' selected=false +++++++listBoxOption name='Foo' selected=false
diff --git a/content/test/data/accessibility/html/button-with-listbox-popup-expected-mac.txt b/content/test/data/accessibility/html/button-with-listbox-popup-expected-mac.txt new file mode 100644 index 0000000..734aa9b --- /dev/null +++ b/content/test/data/accessibility/html/button-with-listbox-popup-expected-mac.txt
@@ -0,0 +1,10 @@ +AXWebArea +++AXGroup +++++AXGroup +++++++AXStaticText AXValue='Choose one:' +++++AXPopUpButton AXTitle='Choose one: Foo' +++++++AXStaticText AXValue='Foo' +++++AXList AXTitle='Choose one:' +++++++AXStaticText AXValue='Baz' +++++++AXStaticText AXValue='Bar' +++++++AXStaticText AXValue='Foo'
diff --git a/content/test/data/accessibility/html/button-with-listbox-popup-expected-uia-win.txt b/content/test/data/accessibility/html/button-with-listbox-popup-expected-uia-win.txt new file mode 100644 index 0000000..96676848 --- /dev/null +++ b/content/test/data/accessibility/html/button-with-listbox-popup-expected-uia-win.txt
@@ -0,0 +1,11 @@ +region +++document +++++group +++++++group +++++++++description Name='Choose one:' +++++++menu Name='Choose one: Foo' ExpandCollapse.ExpandCollapseState='LeafNode' +++++++++description Name='Foo' +++++++listbox Name='Choose one:' Selection.CanSelectMultiple=false Selection.IsSelectionRequired=false +++++++++option Name='Baz' SelectionItem.IsSelected=false SelectionItem.SelectionContainer='Choose one:' +++++++++option Name='Bar' SelectionItem.IsSelected=false SelectionItem.SelectionContainer='Choose one:' +++++++++option Name='Foo' SelectionItem.IsSelected=false SelectionItem.SelectionContainer='Choose one:'
diff --git a/content/test/data/accessibility/html/button-with-listbox-popup-expected-win.txt b/content/test/data/accessibility/html/button-with-listbox-popup-expected-win.txt new file mode 100644 index 0000000..ece56cb --- /dev/null +++ b/content/test/data/accessibility/html/button-with-listbox-popup-expected-win.txt
@@ -0,0 +1,10 @@ +ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE +++IA2_ROLE_SECTION +++++IA2_ROLE_SECTION +++++++ROLE_SYSTEM_STATICTEXT name='Choose one:' +++++ROLE_SYSTEM_BUTTONMENU name='Choose one: Foo' FOCUSABLE HASPOPUP +++++++ROLE_SYSTEM_STATICTEXT name='Foo' +++++ROLE_SYSTEM_LIST name='Choose one:' FOCUSABLE +++++++ROLE_SYSTEM_LISTITEM name='Baz' FOCUSABLE +++++++ROLE_SYSTEM_LISTITEM name='Bar' FOCUSABLE +++++++ROLE_SYSTEM_LISTITEM name='Foo' FOCUSABLE
diff --git a/content/test/data/accessibility/html/button-with-listbox-popup.html b/content/test/data/accessibility/html/button-with-listbox-popup.html new file mode 100644 index 0000000..263529d5 --- /dev/null +++ b/content/test/data/accessibility/html/button-with-listbox-popup.html
@@ -0,0 +1,13 @@ +<html> +<body> +<div id="test1"> + <span id="span">Choose one:</span> + <button aria-haspopup="listbox" aria-labelledby="span test" id="test">Foo</button> + <ul id="options" tabindex="-1" role="listbox" aria-labelledby="span"> + <li id="option1" role="option">Baz</li> + <li id="option2" role="option">Bar</li> + <li id="option3" role="option">Foo</li> + </ul> +</div> +</body> +</html>
diff --git a/device/fido/ble_adapter_manager_unittest.cc b/device/fido/ble_adapter_manager_unittest.cc index 7358421..42980cfb 100644 --- a/device/fido/ble_adapter_manager_unittest.cc +++ b/device/fido/ble_adapter_manager_unittest.cc
@@ -54,6 +54,7 @@ void(base::Optional<int>, base::OnceCallback<void(std::string)>)); MOCK_METHOD0(FinishCollectPIN, void()); + MOCK_METHOD1(SetMightCreateResidentCredential, void(bool)); private: DISALLOW_COPY_AND_ASSIGN(MockObserver);
diff --git a/device/fido/ctap2_device_operation.h b/device/fido/ctap2_device_operation.h index cc194b6..4bda200 100644 --- a/device/fido/ctap2_device_operation.h +++ b/device/fido/ctap2_device_operation.h
@@ -90,6 +90,18 @@ weak_factory_.GetWeakPtr())); } + // Cancel requests that the operation be canceled. This is safe to call at any + // time but may not be effective because the operation may have already + // completed or the device may not support cancelation. Even if canceled, the + // callback will still be invoked, albeit perhaps with a status of + // |kCtap2ErrKeepAliveCancel|. + void Cancel() override { + if (this->token_) { + this->device()->Cancel(*this->token_); + this->token_.reset(); + } + } + void OnResponseReceived( base::Optional<std::vector<uint8_t>> device_response) { this->token_.reset();
diff --git a/device/fido/device_operation.h b/device/fido/device_operation.h index 59793db..debcb4f 100644 --- a/device/fido/device_operation.h +++ b/device/fido/device_operation.h
@@ -50,18 +50,6 @@ virtual ~DeviceOperation() = default; - // Cancel requests that the operation be canceled. This is safe to call at any - // time but may not be effective because the operation may have already - // completed or the device may not support cancelation. Even if canceled, the - // callback will still be invoked, albeit perhaps with a status of - // |kCtap2ErrKeepAliveCancel|. - void Cancel() override { - if (token_) { - device_->Cancel(*token_); - token_.reset(); - } - } - protected: // TODO(hongjunchoi): Refactor so that |command| is never base::nullopt. void DispatchDeviceRequest(base::Optional<std::vector<uint8_t>> command,
diff --git a/device/fido/fido_request_handler_base.h b/device/fido/fido_request_handler_base.h index f76f20cdf..e100d32 100644 --- a/device/fido/fido_request_handler_base.h +++ b/device/fido/fido_request_handler_base.h
@@ -74,10 +74,8 @@ const TransportAvailabilityInfo& other); ~TransportAvailabilityInfo(); - // TODO(hongjunchoi): Factor |rp_id| and |request_type| from - // TransportAvailabilityInfo. + // TODO(hongjunchoi): Factor |request_type| from TransportAvailabilityInfo. // See: https://crbug.com/875011 - std::string rp_id; RequestType request_type = RequestType::kMakeCredential; // The intersection of transports supported by the client and allowed by the @@ -149,6 +147,13 @@ // CollectClientPin is guaranteed to have been called previously. virtual void FinishCollectPIN() = 0; + + // SetMightCreateResidentCredential indicates whether the activation of an + // authenticator may cause a resident credential to be created. A resident + // credential may be discovered by someone with physical access to the + // authenticator and thus has privacy implications. Initially, this is + // assumed to be false. + virtual void SetMightCreateResidentCredential(bool v) = 0; }; // TODO(https://crbug.com/769631): Remove the dependency on Connector once
diff --git a/device/fido/fido_request_handler_unittest.cc b/device/fido/fido_request_handler_unittest.cc index 1d196b5..1cdd155 100644 --- a/device/fido/fido_request_handler_unittest.cc +++ b/device/fido/fido_request_handler_unittest.cc
@@ -135,6 +135,8 @@ NOTREACHED(); } + void SetMightCreateResidentCredential(bool v) override {} + void FinishCollectPIN() override { NOTREACHED(); } private:
diff --git a/device/fido/get_assertion_handler_unittest.cc b/device/fido/get_assertion_handler_unittest.cc index 1a3d33b..c138ed83 100644 --- a/device/fido/get_assertion_handler_unittest.cc +++ b/device/fido/get_assertion_handler_unittest.cc
@@ -49,42 +49,6 @@ } // namespace -class TestObserver : public FidoRequestHandlerBase::Observer { - public: - TestObserver() {} - ~TestObserver() override {} - - void set_controls_dispatch(bool controls_dispatch) { - controls_dispatch_ = controls_dispatch; - } - - private: - // FidoRequestHandlerBase::Observer: - void OnTransportAvailabilityEnumerated( - FidoRequestHandlerBase::TransportAvailabilityInfo data) override {} - bool EmbedderControlsAuthenticatorDispatch( - const FidoAuthenticator&) override { - return controls_dispatch_; - } - void BluetoothAdapterPowerChanged(bool is_powered_on) override {} - void FidoAuthenticatorAdded(const FidoAuthenticator& authenticator) override { - } - void FidoAuthenticatorRemoved(base::StringPiece device_id) override {} - void FidoAuthenticatorIdChanged(base::StringPiece old_authenticator_id, - std::string new_authenticator_id) override {} - void FidoAuthenticatorPairingModeChanged(base::StringPiece authenticator_id, - bool is_in_pairing_mode) override {} - bool SupportsPIN() const override { return false; } - void CollectPIN( - base::Optional<int> attempts, - base::OnceCallback<void(std::string)> provide_pin_cb) override { - NOTREACHED(); - } - void FinishCollectPIN() override { NOTREACHED(); } - - bool controls_dispatch_ = false; -}; - // FidoGetAssertionHandlerTest allows testing GetAssertionRequestHandler against // MockFidoDevices injected via a ScopedFakeFidoDiscoveryFactory. class FidoGetAssertionHandlerTest : public ::testing::Test { @@ -230,8 +194,6 @@ EXPECT_EQ(FidoRequestHandlerBase::RequestType::kGetAssertion, request_handler->transport_availability_info().request_type); - EXPECT_EQ(test_data::kRelyingPartyId, - request_handler->transport_availability_info().rp_id); } TEST_F(FidoGetAssertionHandlerTest, CtapRequestOnSingleDevice) { @@ -740,6 +702,44 @@ } #if defined(OS_WIN) + +class TestObserver : public FidoRequestHandlerBase::Observer { + public: + TestObserver() {} + ~TestObserver() override {} + + void set_controls_dispatch(bool controls_dispatch) { + controls_dispatch_ = controls_dispatch; + } + + private: + // FidoRequestHandlerBase::Observer: + void OnTransportAvailabilityEnumerated( + FidoRequestHandlerBase::TransportAvailabilityInfo data) override {} + bool EmbedderControlsAuthenticatorDispatch( + const FidoAuthenticator&) override { + return controls_dispatch_; + } + void BluetoothAdapterPowerChanged(bool is_powered_on) override {} + void FidoAuthenticatorAdded(const FidoAuthenticator& authenticator) override { + } + void FidoAuthenticatorRemoved(base::StringPiece device_id) override {} + void FidoAuthenticatorIdChanged(base::StringPiece old_authenticator_id, + std::string new_authenticator_id) override {} + void FidoAuthenticatorPairingModeChanged(base::StringPiece authenticator_id, + bool is_in_pairing_mode) override {} + bool SupportsPIN() const override { return false; } + void CollectPIN( + base::Optional<int> attempts, + base::OnceCallback<void(std::string)> provide_pin_cb) override { + NOTREACHED(); + } + void FinishCollectPIN() override { NOTREACHED(); } + void SetMightCreateResidentCredential(bool v) override {} + + bool controls_dispatch_ = false; +}; + // Verify that the request handler instantiates a HID device backed // FidoDeviceAuthenticator or a WinNativeCrossPlatformAuthenticator, depending // on API availability. @@ -779,6 +779,7 @@ handler->AuthenticatorsForTesting().begin()->second->GetId()); } } + #endif // defined(OS_WIN) } // namespace device
diff --git a/device/fido/get_assertion_request_handler.cc b/device/fido/get_assertion_request_handler.cc index 4cb6003..c3e700e 100644 --- a/device/fido/get_assertion_request_handler.cc +++ b/device/fido/get_assertion_request_handler.cc
@@ -189,7 +189,6 @@ std::move(completion_callback)), request_(std::move(request)), weak_factory_(this) { - transport_availability_info().rp_id = request_.rp_id(); transport_availability_info().request_type = FidoRequestHandlerBase::RequestType::kGetAssertion; @@ -318,9 +317,9 @@ authenticator->WillNeedPINToGetAssertion(request_, observer()) == FidoAuthenticator::GetAssertionPINDisposition::kNoPIN); + state_ = State::kFinished; CancelActiveAuthenticators(authenticator->GetId()); - state_ = State::kFinished; if (response_code != CtapDeviceResponseCode::kSuccess) { FIDO_LOG(ERROR) << "Failing assertion request due to status " << static_cast<int>(response_code) << " from " @@ -407,8 +406,8 @@ FidoAuthenticator::GetAssertionPINDisposition::kNoPIN); DCHECK(observer()); - CancelActiveAuthenticators(authenticator->GetId()); state_ = State::kGettingRetries; + CancelActiveAuthenticators(authenticator->GetId()); authenticator_ = authenticator; authenticator_->GetRetries( base::BindOnce(&GetAssertionRequestHandler::OnRetriesResponse, @@ -418,6 +417,7 @@ void GetAssertionRequestHandler::HandleInapplicableAuthenticator( FidoAuthenticator* authenticator) { // User touched an authenticator that cannot handle this request. + state_ = State::kFinished; CancelActiveAuthenticators(authenticator->GetId()); std::move(completion_callback_) .Run(FidoReturnCode::kUserConsentButCredentialNotRecognized,
diff --git a/device/fido/get_assertion_task.cc b/device/fido/get_assertion_task.cc index b531c9b..39e3031b 100644 --- a/device/fido/get_assertion_task.cc +++ b/device/fido/get_assertion_task.cc
@@ -50,6 +50,8 @@ GetAssertionTask::~GetAssertionTask() = default; void GetAssertionTask::Cancel() { + canceled_ = true; + if (sign_operation_) { sign_operation_->Cancel(); } @@ -114,6 +116,10 @@ void GetAssertionTask::HandleResponse( CtapDeviceResponseCode response_code, base::Optional<AuthenticatorGetAssertionResponse> response_data) { + if (canceled_) { + return; + } + // Some authenticators will return this error before waiting for a touch if // they don't recognise a credential. In other cases the result can be // returned immediately. @@ -138,6 +144,10 @@ base::Optional<AuthenticatorGetAssertionResponse> response_data) { DCHECK(request_.allow_list() && request_.allow_list()->size() > 0); + if (canceled_) { + return; + } + // Credential was recognized by the device. As this authentication was a // silent authentication (i.e. user touch was not provided), try again with // only the matching credential, user presence enforced and with the original
diff --git a/device/fido/get_assertion_task.h b/device/fido/get_assertion_task.h index f91d89dc..195d59a 100644 --- a/device/fido/get_assertion_task.h +++ b/device/fido/get_assertion_task.h
@@ -79,6 +79,7 @@ std::unique_ptr<RegisterOperation> dummy_register_operation_; GetAssertionTaskCallback callback_; size_t current_credential_ = 0; + bool canceled_ = false; base::WeakPtrFactory<GetAssertionTask> weak_factory_;
diff --git a/device/fido/hid/fido_hid_device.cc b/device/fido/hid/fido_hid_device.cc index 89e03b8..caafe5f 100644 --- a/device/fido/hid/fido_hid_device.cc +++ b/device/fido/hid/fido_hid_device.cc
@@ -98,8 +98,11 @@ } } -// TODO(agl): maybe Transition should take the next step to move to? -void FidoHidDevice::Transition() { +void FidoHidDevice::Transition(base::Optional<State> next_state) { + if (next_state) { + state_ = *next_state; + } + switch (state_) { case State::kInit: state_ = State::kConnecting; @@ -164,8 +167,7 @@ timeout_callback_.Cancel(); if (!connection) { - state_ = State::kDeviceError; - Transition(); + Transition(State::kDeviceError); return; } @@ -194,8 +196,7 @@ } if (!success) { - state_ = State::kDeviceError; - Transition(); + Transition(State::kDeviceError); } connection_->Read(base::BindOnce(&FidoHidDevice::OnPotentialInitReply, @@ -248,8 +249,7 @@ } if (!success) { - state_ = State::kDeviceError; - Transition(); + Transition(State::kDeviceError); return; } DCHECK(buf); @@ -268,8 +268,7 @@ timeout_callback_.Cancel(); channel_id_ = *maybe_channel_id; - state_ = State::kReady; - Transition(); + Transition(State::kReady); } void FidoHidDevice::WriteMessage(FidoHidMessage message) { @@ -292,8 +291,7 @@ DCHECK_EQ(State::kBusy, state_); if (!success) { - state_ = State::kDeviceError; - Transition(); + Transition(State::kDeviceError); return; } @@ -332,16 +330,14 @@ DCHECK_EQ(State::kBusy, state_); if (!success) { - state_ = State::kDeviceError; - Transition(); + Transition(State::kDeviceError); return; } DCHECK(buf); auto message = FidoHidMessage::CreateFromSerializedData(*buf); if (!message) { - state_ = State::kDeviceError; - Transition(); + Transition(State::kDeviceError); return; } @@ -392,8 +388,7 @@ } if (!success) { - state_ = State::kDeviceError; - Transition(); + Transition(State::kDeviceError); return; } DCHECK(buf); @@ -415,19 +410,47 @@ const auto cmd = message.cmd(); auto response = message.GetMessagePayload(); if (cmd != FidoHidDeviceCommand::kMsg && cmd != FidoHidDeviceCommand::kCbor) { - // TODO(agl): inline |ProcessHidError|, or maybe have it call |Transition|. - ProcessHidError(cmd, response); - Transition(); + if (cmd != FidoHidDeviceCommand::kError || response.size() != 1) { + FIDO_LOG(ERROR) << "Unknown HID message received: " + << static_cast<int>(cmd) << " " + << base::HexEncode(response.data(), response.size()); + Transition(State::kDeviceError); + return; + } + + // HID transport layer error constants that are returned to the client. + // https://fidoalliance.org/specs/fido-v2.0-rd-20170927/fido-client-to-authenticator-protocol-v2.0-rd-20170927.html#ctaphid-commands + enum class HidErrorConstant : uint8_t { + kInvalidCommand = 0x01, + kInvalidParameter = 0x02, + kInvalidLength = 0x03, + // (Other errors omitted.) + }; + + switch (static_cast<HidErrorConstant>(response[0])) { + case HidErrorConstant::kInvalidCommand: + case HidErrorConstant::kInvalidParameter: + case HidErrorConstant::kInvalidLength: + Transition(State::kMsgError); + break; + default: + FIDO_LOG(ERROR) << "HID error received: " + << static_cast<int>(response[0]); + Transition(State::kDeviceError); + } + return; } - state_ = State::kReady; DCHECK(!pending_transactions_.empty()); auto callback = std::move(pending_transactions_.front().callback); pending_transactions_.pop_front(); current_token_ = FidoDevice::kInvalidCancelToken; base::WeakPtr<FidoHidDevice> self = weak_factory_.GetWeakPtr(); + // The callback may call back into this object thus |state_| is set ahead of + // time. + state_ = State::kReady; std::move(callback).Run(std::move(response)); // Executing |callback| may have freed |this|. Check |self| first. @@ -446,44 +469,7 @@ } void FidoHidDevice::OnTimeout() { - state_ = State::kDeviceError; - Transition(); -} - -void FidoHidDevice::ProcessHidError(FidoHidDeviceCommand cmd, - base::span<const uint8_t> payload) { - if (cmd != FidoHidDeviceCommand::kError || payload.size() != 1) { - FIDO_LOG(ERROR) << "Unknown HID message received: " << static_cast<int>(cmd) - << " " << base::HexEncode(payload.data(), payload.size()); - state_ = State::kDeviceError; - return; - } - - // HID transport layer error constants that are returned to the client. - // Carried in the payload section of the Error command. - // https://fidoalliance.org/specs/fido-v2.0-rd-20170927/fido-client-to-authenticator-protocol-v2.0-rd-20170927.html#ctaphid-commands - enum class HidErrorConstant : uint8_t { - kInvalidCommand = 0x01, - kInvalidParameter = 0x02, - kInvalidLength = 0x03, - kInvalidSequence = 0x04, - kTimeout = 0x05, - kBusy = 0x06, - kLockRequired = 0x0a, - kInvalidChannel = 0x0b, - kOther = 0x7f, - }; - - switch (static_cast<HidErrorConstant>(payload[0])) { - case HidErrorConstant::kInvalidCommand: - case HidErrorConstant::kInvalidParameter: - case HidErrorConstant::kInvalidLength: - state_ = State::kMsgError; - break; - default: - FIDO_LOG(ERROR) << "HID error received: " << static_cast<int>(payload[0]); - state_ = State::kDeviceError; - } + Transition(State::kDeviceError); } void FidoHidDevice::WriteCancel() {
diff --git a/device/fido/hid/fido_hid_device.h b/device/fido/hid/fido_hid_device.h index 82cef29..89db992 100644 --- a/device/fido/hid/fido_hid_device.h +++ b/device/fido/hid/fido_hid_device.h
@@ -89,7 +89,7 @@ CancelToken token; }; - void Transition(); + void Transition(base::Optional<State> next_state = base::nullopt); // Open a connection to this device. void Connect(device::mojom::HidManager::ConnectCallback callback); @@ -118,8 +118,6 @@ void ArmTimeout(); void OnTimeout(); void WriteCancel(); - void ProcessHidError(FidoHidDeviceCommand cmd, - base::span<const uint8_t> payload); base::WeakPtr<FidoDevice> GetWeakPtr() override;
diff --git a/device/fido/make_credential_handler_unittest.cc b/device/fido/make_credential_handler_unittest.cc index dd9971b..39f7f5e8 100644 --- a/device/fido/make_credential_handler_unittest.cc +++ b/device/fido/make_credential_handler_unittest.cc
@@ -158,8 +158,6 @@ EXPECT_EQ(FidoRequestHandlerBase::RequestType::kMakeCredential, request_handler->transport_availability_info().request_type); - EXPECT_EQ(test_data::kRelyingPartyId, - request_handler->transport_availability_info().rp_id); } TEST_F(FidoMakeCredentialHandlerTest, TestCtap2MakeCredential) {
diff --git a/device/fido/make_credential_request_handler.cc b/device/fido/make_credential_request_handler.cc index 1e20ec10..4388977 100644 --- a/device/fido/make_credential_request_handler.cc +++ b/device/fido/make_credential_request_handler.cc
@@ -125,7 +125,6 @@ authenticator_selection_criteria_( std::move(authenticator_selection_criteria)), weak_factory_(this) { - transport_availability_info().rp_id = request_.rp().rp_id(); transport_availability_info().request_type = FidoRequestHandlerBase::RequestType::kMakeCredential; @@ -260,9 +259,9 @@ authenticator->WillNeedPINToMakeCredential(request_, observer()) == MakeCredentialPINDisposition::kNoPIN); + state_ = State::kFinished; CancelActiveAuthenticators(authenticator->GetId()); - state_ = State::kFinished; if (response_code != CtapDeviceResponseCode::kSuccess) { OnAuthenticatorResponse(authenticator, response_code, base::nullopt); return; @@ -292,8 +291,8 @@ case MakeCredentialPINDisposition::kUsePIN: // Will need to get PIN to handle this request. DCHECK(observer()); - CancelActiveAuthenticators(authenticator->GetId()); state_ = State::kGettingRetries; + CancelActiveAuthenticators(authenticator->GetId()); authenticator_ = authenticator; authenticator_->GetRetries( base::BindOnce(&MakeCredentialRequestHandler::OnRetriesResponse, @@ -303,8 +302,8 @@ case MakeCredentialPINDisposition::kSetPIN: // Will need to set a PIN to handle this request. DCHECK(observer()); - CancelActiveAuthenticators(authenticator->GetId()); state_ = State::kWaitingForNewPIN; + CancelActiveAuthenticators(authenticator->GetId()); authenticator_ = authenticator; observer()->CollectPIN( base::nullopt, @@ -323,6 +322,7 @@ void MakeCredentialRequestHandler::HandleInapplicableAuthenticator( FidoAuthenticator* authenticator) { // User touched an authenticator that cannot handle this request. + state_ = State::kFinished; CancelActiveAuthenticators(authenticator->GetId()); const FidoReturnCode capability_error = IsCandidateAuthenticatorPostTouch( request_, authenticator, authenticator_selection_criteria_, observer());
diff --git a/device/fido/make_credential_task.cc b/device/fido/make_credential_task.cc index b0c3092..cc9bbe77 100644 --- a/device/fido/make_credential_task.cc +++ b/device/fido/make_credential_task.cc
@@ -96,7 +96,8 @@ } void MakeCredentialTask::Cancel() { - // TODO: should set a flag on this object to stop any more operations. + canceled_ = true; + if (register_operation_) { register_operation_->Cancel(); } @@ -159,6 +160,10 @@ base::Optional<AuthenticatorGetAssertionResponse> response_data) { DCHECK(request_.exclude_list() && request_.exclude_list()->size() > 0); + if (canceled_) { + return; + } + // The authenticator recognized a credential from the exclude list. Send the // actual request with only that credential in the exclude list to collect a // touch and and the CTAP2_ERR_CREDENTIAL_EXCLUDED error code.
diff --git a/device/fido/make_credential_task.h b/device/fido/make_credential_task.h index 4a53cd1a..6c846ab 100644 --- a/device/fido/make_credential_task.h +++ b/device/fido/make_credential_task.h
@@ -73,6 +73,7 @@ std::unique_ptr<SignOperation> silent_sign_operation_; MakeCredentialTaskCallback callback_; size_t current_credential_ = 0; + bool canceled_ = false; base::WeakPtrFactory<MakeCredentialTask> weak_factory_;
diff --git a/device/fido/reset_request_handler.cc b/device/fido/reset_request_handler.cc index aecad53..873b9232 100644 --- a/device/fido/reset_request_handler.cc +++ b/device/fido/reset_request_handler.cc
@@ -27,7 +27,6 @@ ResetRequestHandler::~ResetRequestHandler() { DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_); - CancelActiveAuthenticators(); } void ResetRequestHandler::DispatchRequest(FidoAuthenticator* authenticator) { @@ -46,7 +45,7 @@ } processed_touch_ = true; - CancelActiveAuthenticators(); + CancelActiveAuthenticators(authenticator->GetId()); if (authenticator->SupportedProtocol() != ProtocolVersion::kCtap) { std::move(finished_callback_)
diff --git a/device/fido/set_pin_request_handler.cc b/device/fido/set_pin_request_handler.cc index dfe179f..734e9e7 100644 --- a/device/fido/set_pin_request_handler.cc +++ b/device/fido/set_pin_request_handler.cc
@@ -28,7 +28,6 @@ SetPINRequestHandler::~SetPINRequestHandler() { DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_); - CancelActiveAuthenticators(); } void SetPINRequestHandler::ProvidePIN(const std::string& old_pin, @@ -78,17 +77,18 @@ } authenticator_ = authenticator; - CancelActiveAuthenticators(); switch (authenticator_->Options()->client_pin_availability) { case AuthenticatorSupportedOptions::ClientPinAvailability::kNotSupported: state_ = State::kFinished; + CancelActiveAuthenticators(authenticator->GetId()); finished_callback_.Run(CtapDeviceResponseCode::kCtap1ErrInvalidCommand); return; case AuthenticatorSupportedOptions::ClientPinAvailability:: kSupportedAndPinSet: state_ = State::kGettingRetries; + CancelActiveAuthenticators(authenticator->GetId()); authenticator_->GetRetries( base::BindOnce(&SetPINRequestHandler::OnRetriesResponse, weak_factory_.GetWeakPtr())); @@ -97,6 +97,7 @@ case AuthenticatorSupportedOptions::ClientPinAvailability:: kSupportedButPinNotSet: state_ = State::kWaitingForPIN; + CancelActiveAuthenticators(authenticator->GetId()); std::move(get_pin_callback_).Run(base::nullopt); break; }
diff --git a/device/fido/u2f_register_operation.cc b/device/fido/u2f_register_operation.cc index 056edd07..55d5e7f 100644 --- a/device/fido/u2f_register_operation.cc +++ b/device/fido/u2f_register_operation.cc
@@ -42,6 +42,10 @@ } } +void U2fRegisterOperation::Cancel() { + canceled_ = true; +} + void U2fRegisterOperation::TrySign() { DispatchDeviceRequest( ConvertToU2fSignCommand(request(), excluded_key_handle()), @@ -51,6 +55,10 @@ void U2fRegisterOperation::OnCheckForExcludedKeyHandle( base::Optional<std::vector<uint8_t>> device_response) { + if (canceled_) { + return; + } + auto result = apdu::ApduResponse::Status::SW_WRONG_DATA; if (device_response) { const auto apdu_response = @@ -115,6 +123,10 @@ void U2fRegisterOperation::OnRegisterResponseReceived( base::Optional<std::vector<uint8_t>> device_response) { + if (canceled_) { + return; + } + auto result = apdu::ApduResponse::Status::SW_WRONG_DATA; const auto apdu_response = device_response
diff --git a/device/fido/u2f_register_operation.h b/device/fido/u2f_register_operation.h index cf423f9..e9ee470 100644 --- a/device/fido/u2f_register_operation.h +++ b/device/fido/u2f_register_operation.h
@@ -38,6 +38,7 @@ // DeviceOperation: void Start() override; + void Cancel() override; private: using ExcludeListIterator = @@ -52,6 +53,7 @@ const std::vector<uint8_t>& excluded_key_handle() const; size_t current_key_handle_index_ = 0; + bool canceled_ = false; base::WeakPtrFactory<U2fRegisterOperation> weak_factory_; DISALLOW_COPY_AND_ASSIGN(U2fRegisterOperation);
diff --git a/device/fido/u2f_sign_operation.cc b/device/fido/u2f_sign_operation.cc index 102b361..c0499486 100644 --- a/device/fido/u2f_sign_operation.cc +++ b/device/fido/u2f_sign_operation.cc
@@ -43,6 +43,10 @@ } } +void U2fSignOperation::Cancel() { + canceled_ = true; +} + void U2fSignOperation::TrySign() { DispatchDeviceRequest( ConvertToU2fSignCommand(request(), app_param_type_, key_handle()), @@ -52,6 +56,10 @@ void U2fSignOperation::OnSignResponseReceived( base::Optional<std::vector<uint8_t>> device_response) { + if (canceled_) { + return; + } + auto result = apdu::ApduResponse::Status::SW_WRONG_DATA; const auto apdu_response = device_response @@ -134,6 +142,10 @@ void U2fSignOperation::OnEnrollmentResponseReceived( base::Optional<std::vector<uint8_t>> device_response) { + if (canceled_) { + return; + } + auto result = apdu::ApduResponse::Status::SW_WRONG_DATA; if (device_response) { const auto apdu_response =
diff --git a/device/fido/u2f_sign_operation.h b/device/fido/u2f_sign_operation.h index 99e10b9b..9c6d7a8 100644 --- a/device/fido/u2f_sign_operation.h +++ b/device/fido/u2f_sign_operation.h
@@ -38,6 +38,7 @@ // DeviceOperation: void Start() override; + void Cancel() override; private: void TrySign(); @@ -52,6 +53,7 @@ // app_param_type_ identifies whether we're currently trying the RP ID (the // primary value) or an RP-provided U2F AppID. ApplicationParameterType app_param_type_ = ApplicationParameterType::kPrimary; + bool canceled_ = false; base::WeakPtrFactory<U2fSignOperation> weak_factory_; DISALLOW_COPY_AND_ASSIGN(U2fSignOperation);
diff --git a/device/vr/windows/compositor_base.cc b/device/vr/windows/compositor_base.cc index 992804a..3f1fd64e 100644 --- a/device/vr/windows/compositor_base.cc +++ b/device/vr/windows/compositor_base.cc
@@ -168,6 +168,13 @@ // merge with vr_shell_gl eventually. left_webxr_bounds_ = left_bounds; right_webxr_bounds_ = right_bounds; + + // Swap top/bottom to account for differences between D3D and GL coordinates. + left_webxr_bounds_.set_y( + 1 - (left_webxr_bounds_.y() + left_webxr_bounds_.height())); + right_webxr_bounds_.set_y( + 1 - (right_webxr_bounds_.y() + right_webxr_bounds_.height())); + source_size_ = source_size; OnLayerBoundsChanged();
diff --git a/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.cc b/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.cc index cfbe920..fc7bcb9 100644 --- a/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.cc +++ b/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.cc
@@ -29,6 +29,8 @@ : GuestViewContainer(render_frame), MimeHandlerViewContainerBase(render_frame, info, mime_type, original_url), guest_proxy_routing_id_(-1) { + RecordInteraction( + MimeHandlerViewUMATypes::Type::kDidCreateMimeHandlerViewContainerBase); is_embedded_ = !render_frame->GetWebFrame()->GetDocument().IsPluginDocument(); }
diff --git a/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_base.cc b/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_base.cc index 1ddc5f04..1feafce7 100644 --- a/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_base.cc +++ b/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_base.cc
@@ -200,7 +200,6 @@ DCHECK(!mime_type_.empty()); g_mime_handler_view_container_base_map.Get()[embedder_render_frame].insert( this); - RecordInteraction(UMAType::kDidCreateMimeHandlerViewContainerBase); } MimeHandlerViewContainerBase::~MimeHandlerViewContainerBase() {
diff --git a/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_frame_container.cc b/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_frame_container.cc index b80d88f..466ce206 100644 --- a/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_frame_container.cc +++ b/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_frame_container.cc
@@ -84,6 +84,11 @@ const GURL& resource_url, const std::string& mime_type, const std::string& view_id) { + // TODO(ekaramad): Eventually MHVFC should not request the resource which + // means this mode of MHVFC is no longer necessary. After intercepting the + // response we should just proceed with creating the MimeHandlerViewGuest + // and attaching to the inserted <iframe> on the browser side. The current + // renderer state for it seems unnecessary. new MimeHandlerViewFrameContainer(web_frame, resource_url, mime_type, view_id); } @@ -102,6 +107,8 @@ element_instance_id_(content::RenderThread::Get()->GenerateRoutingID()), render_frame_lifetime_observer_( new RenderFrameLifetimeObserver(this, GetEmbedderRenderFrame())) { + RecordInteraction( + MimeHandlerViewUMATypes::Type::kDidCreateMimeHandlerViewContainerBase); is_embedded_ = true; SendResourceRequest(); }
diff --git a/net/android/network_change_notifier_android.cc b/net/android/network_change_notifier_android.cc index 02cf01e..7094724 100644 --- a/net/android/network_change_notifier_android.cc +++ b/net/android/network_change_notifier_android.cc
@@ -67,9 +67,12 @@ #include "base/macros.h" #include "base/message_loop/message_loop.h" #include "base/metrics/histogram_macros.h" +#include "base/sequenced_task_runner.h" +#include "base/task/post_task.h" +#include "base/task/task_traits.h" #include "base/threading/thread.h" #include "net/base/address_tracker_linux.h" -#include "net/dns/dns_config_service.h" +#include "net/dns/dns_config_service_posix.h" namespace net { @@ -86,41 +89,32 @@ // Thread on which we can run DnsConfigService, which requires a TYPE_IO // message loop to monitor /system/etc/hosts. -class NetworkChangeNotifierAndroid::DnsConfigServiceThread - : public base::Thread { +class NetworkChangeNotifierAndroid::BlockingThreadObjects { public: - DnsConfigServiceThread() - : base::Thread("DnsConfigService"), - address_tracker_(base::DoNothing(), + BlockingThreadObjects() + : address_tracker_(base::DoNothing(), base::DoNothing(), // We're only interested in tunnel interface changes. base::Bind(NotifyNetworkChangeNotifierObservers), std::unordered_set<std::string>()) {} - ~DnsConfigServiceThread() override { - Stop(); - } - - void Init() override { + void Init() { address_tracker_.Init(); - dns_config_service_ = DnsConfigService::CreateSystemService(); - dns_config_service_->WatchConfig( + dns_config_service_.WatchConfig( base::Bind(&NetworkChangeNotifier::SetDnsConfig)); } - void CleanUp() override { dns_config_service_.reset(); } - static void NotifyNetworkChangeNotifierObservers() { NetworkChangeNotifier::NotifyObserversOfIPAddressChange(); NetworkChangeNotifier::NotifyObserversOfConnectionTypeChange(); } private: - std::unique_ptr<DnsConfigService> dns_config_service_; + internal::DnsConfigServicePosix dns_config_service_; // Used to detect tunnel state changes. internal::AddressTrackerLinux address_tracker_; - DISALLOW_COPY_AND_ASSIGN(DnsConfigServiceThread); + DISALLOW_COPY_AND_ASSIGN(BlockingThreadObjects); }; NetworkChangeNotifierAndroid::~NetworkChangeNotifierAndroid() { @@ -175,7 +169,7 @@ } void NetworkChangeNotifierAndroid::OnConnectionTypeChanged() { - DnsConfigServiceThread::NotifyNetworkChangeNotifierObservers(); + BlockingThreadObjects::NotifyNetworkChangeNotifierObservers(); } void NetworkChangeNotifierAndroid::OnMaxBandwidthChanged( @@ -211,13 +205,25 @@ NetworkChangeNotifierDelegateAndroid* delegate) : NetworkChangeNotifier(NetworkChangeCalculatorParamsAndroid()), delegate_(delegate), - dns_config_service_thread_(new DnsConfigServiceThread()), + blocking_thread_runner_( + base::CreateSequencedTaskRunnerWithTraits({base::MayBlock()})), + blocking_thread_objects_( + new BlockingThreadObjects(), + // Ensure |blocking_thread_objects_| lives on + // |blocking_thread_runner_| to prevent races where + // NetworkChangeNotifierAndroid outlives + // ScopedTaskEnvironment. https://crbug.com/938126 + base::OnTaskRunnerDeleter(blocking_thread_runner_)), force_network_handles_supported_for_testing_(false) { CHECK_EQ(NetId::INVALID, NetworkChangeNotifier::kInvalidNetworkHandle) << "kInvalidNetworkHandle doesn't match NetId::INVALID"; delegate_->AddObserver(this); - dns_config_service_thread_->StartWithOptions( - base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); + blocking_thread_runner_->PostTask( + FROM_HERE, + base::BindOnce(&BlockingThreadObjects::Init, + // The Unretained pointer is safe here because it's + // posted before the deleter can post. + base::Unretained(blocking_thread_objects_.get()))); } // static
diff --git a/net/android/network_change_notifier_android.h b/net/android/network_change_notifier_android.h index 003e36b..dab9fd3 100644 --- a/net/android/network_change_notifier_android.h +++ b/net/android/network_change_notifier_android.h
@@ -10,10 +10,16 @@ #include "base/android/jni_android.h" #include "base/compiler_specific.h" #include "base/macros.h" +#include "base/memory/scoped_refptr.h" #include "net/android/network_change_notifier_delegate_android.h" #include "net/base/net_export.h" #include "net/base/network_change_notifier.h" +namespace base { +class SequencedTaskRunner; +struct OnTaskRunnerDeleter; +} // namespace base + namespace net { class NetworkChangeNotifierAndroidTest; @@ -81,7 +87,7 @@ friend class NetworkChangeNotifierAndroidTest; friend class NetworkChangeNotifierFactoryAndroid; - class DnsConfigServiceThread; + class BlockingThreadObjects; // Enable NetworkHandles support for tests. void ForceNetworkHandlesSupportedForTesting(); @@ -90,7 +96,14 @@ NetworkChangeNotifierDelegateAndroid* delegate); NetworkChangeNotifierDelegateAndroid* const delegate_; - std::unique_ptr<DnsConfigServiceThread> dns_config_service_thread_; + // |blocking_thread_objects_| will live on this runner. + scoped_refptr<base::SequencedTaskRunner> blocking_thread_runner_; + // A collection of objects that must live on blocking sequences. These objects + // listen for notifications and relay the notifications to the registered + // observers without posting back to the thread the object was created on. + // Also used for DnsConfigService which also must live on blocking sequences. + std::unique_ptr<BlockingThreadObjects, base::OnTaskRunnerDeleter> + blocking_thread_objects_; bool force_network_handles_supported_for_testing_; DISALLOW_COPY_AND_ASSIGN(NetworkChangeNotifierAndroid);
diff --git a/net/base/address_tracker_linux.cc b/net/base/address_tracker_linux.cc index 7eecd01e..9820b6d0 100644 --- a/net/base/address_tracker_linux.cc +++ b/net/base/address_tracker_linux.cc
@@ -118,7 +118,6 @@ address_callback_(base::DoNothing()), link_callback_(base::DoNothing()), tunnel_callback_(base::DoNothing()), - watcher_(FROM_HERE), ignored_interfaces_(), connection_type_initialized_(false), connection_type_initialized_cv_(&connection_type_lock_), @@ -135,7 +134,6 @@ address_callback_(address_callback), link_callback_(link_callback), tunnel_callback_(tunnel_callback), - watcher_(FROM_HERE), ignored_interfaces_(ignored_interfaces), connection_type_initialized_(false), connection_type_initialized_cv_(&connection_type_lock_), @@ -146,9 +144,7 @@ DCHECK(!link_callback.is_null()); } -AddressTrackerLinux::~AddressTrackerLinux() { - watcher_.StopWatchingFileDescriptor(); -} +AddressTrackerLinux::~AddressTrackerLinux() = default; void AddressTrackerLinux::Init() { netlink_fd_.reset(socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)); @@ -230,19 +226,15 @@ } if (tracking_) { - rv = base::MessageLoopCurrentForIO::Get()->WatchFileDescriptor( - netlink_fd_.get(), true, base::MessagePumpForIO::WATCH_READ, &watcher_, - this); - if (rv < 0) { - PLOG(ERROR) << "Could not watch NETLINK socket"; - AbortAndForceOnline(); - return; - } + watcher_ = base::FileDescriptorWatcher::WatchReadable( + netlink_fd_.get(), + base::BindRepeating(&AddressTrackerLinux::OnFileCanReadWithoutBlocking, + base::Unretained(this))); } } void AddressTrackerLinux::AbortAndForceOnline() { - watcher_.StopWatchingFileDescriptor(); + watcher_.reset(); netlink_fd_.reset(); AddressTrackerAutoLock lock(*this, connection_type_lock_); current_connection_type_ = NetworkChangeNotifier::CONNECTION_UNKNOWN; @@ -424,8 +416,7 @@ } } -void AddressTrackerLinux::OnFileCanReadWithoutBlocking(int fd) { - DCHECK_EQ(netlink_fd_.get(), fd); +void AddressTrackerLinux::OnFileCanReadWithoutBlocking() { bool address_changed; bool link_changed; bool tunnel_changed; @@ -438,8 +429,6 @@ tunnel_callback_.Run(); } -void AddressTrackerLinux::OnFileCanWriteWithoutBlocking(int /* fd */) {} - bool AddressTrackerLinux::IsTunnelInterface(int interface_index) const { char buf[IFNAMSIZ] = {0}; return IsTunnelInterfaceName(get_interface_name_(interface_index, buf));
diff --git a/net/base/address_tracker_linux.h b/net/base/address_tracker_linux.h index 0fd3f09..f937eabf 100644 --- a/net/base/address_tracker_linux.h +++ b/net/base/address_tracker_linux.h
@@ -17,9 +17,9 @@ #include "base/callback.h" #include "base/compiler_specific.h" +#include "base/files/file_descriptor_watcher_posix.h" #include "base/files/scoped_file.h" #include "base/macros.h" -#include "base/message_loop/message_pump_for_io.h" #include "base/synchronization/condition_variable.h" #include "base/synchronization/lock.h" #include "base/threading/thread_checker.h" @@ -32,8 +32,7 @@ // Keeps track of network interface addresses using rtnetlink. Used by // NetworkChangeNotifier to provide signals to registered IPAddressObservers. -class NET_EXPORT_PRIVATE AddressTrackerLinux - : public base::MessagePumpForIO::FdWatcher { +class NET_EXPORT_PRIVATE AddressTrackerLinux { public: typedef std::map<IPAddress, struct ifaddrmsg> AddressMap; @@ -58,7 +57,7 @@ const base::Closure& link_callback, const base::Closure& tunnel_callback, const std::unordered_set<std::string>& ignored_interfaces); - ~AddressTrackerLinux() override; + virtual ~AddressTrackerLinux(); // In tracking mode, it starts watching the system configuration for // changes. The current thread must have a MessageLoopForIO. In @@ -129,9 +128,8 @@ // Call when some part of initialization failed; forces online and unblocks. void AbortAndForceOnline(); - // MessagePumpForIO::FdWatcher: - void OnFileCanReadWithoutBlocking(int fd) override; - void OnFileCanWriteWithoutBlocking(int /* fd */) override; + // Called by |watcher_| when |netlink_fd_| can be read without blocking. + void OnFileCanReadWithoutBlocking(); // Does |interface_index| refer to a tunnel interface? bool IsTunnelInterface(int interface_index) const; @@ -157,7 +155,7 @@ // Note that |watcher_| must be inactive when |netlink_fd_| is closed. base::ScopedFD netlink_fd_; - base::MessagePumpForIO::FdWatchController watcher_; + std::unique_ptr<base::FileDescriptorWatcher::Controller> watcher_; mutable base::Lock address_map_lock_; AddressMap address_map_;
diff --git a/net/base/network_change_notifier_linux.cc b/net/base/network_change_notifier_linux.cc index 9621a74..ff0b277 100644 --- a/net/base/network_change_notifier_linux.cc +++ b/net/base/network_change_notifier_linux.cc
@@ -9,83 +9,73 @@ #include "base/compiler_specific.h" #include "base/macros.h" #include "base/message_loop/message_loop.h" +#include "base/sequenced_task_runner.h" +#include "base/task/post_task.h" +#include "base/task/task_traits.h" #include "base/threading/thread.h" #include "net/base/address_tracker_linux.h" -#include "net/dns/dns_config_service.h" +#include "net/dns/dns_config_service_posix.h" namespace net { -class NetworkChangeNotifierLinux::Thread : public base::Thread { +// A collection of objects that live on blocking threads. +class NetworkChangeNotifierLinux::BlockingThreadObjects { public: - explicit Thread(const std::unordered_set<std::string>& ignored_interfaces); - ~Thread() override; + explicit BlockingThreadObjects( + const std::unordered_set<std::string>& ignored_interfaces); // Plumbing for NetworkChangeNotifier::GetCurrentConnectionType. // Safe to call from any thread. NetworkChangeNotifier::ConnectionType GetCurrentConnectionType() { - return address_tracker_->GetCurrentConnectionType(); + return address_tracker_.GetCurrentConnectionType(); } const internal::AddressTrackerLinux* address_tracker() const { - return address_tracker_.get(); + return &address_tracker_; } - protected: - // base::Thread - void Init() override; - void CleanUp() override; + // Begin watching for DNS and netlink changes. + void Init(); private: void OnIPAddressChanged(); void OnLinkChanged(); - std::unique_ptr<DnsConfigService> dns_config_service_; + internal::DnsConfigServicePosix dns_config_service_; // Used to detect online/offline state and IP address changes. - std::unique_ptr<internal::AddressTrackerLinux> address_tracker_; + internal::AddressTrackerLinux address_tracker_; NetworkChangeNotifier::ConnectionType last_type_; - DISALLOW_COPY_AND_ASSIGN(Thread); + DISALLOW_COPY_AND_ASSIGN(BlockingThreadObjects); }; -NetworkChangeNotifierLinux::Thread::Thread( +NetworkChangeNotifierLinux::BlockingThreadObjects::BlockingThreadObjects( const std::unordered_set<std::string>& ignored_interfaces) - : base::Thread("NetworkChangeNotifier"), - address_tracker_(new internal::AddressTrackerLinux( - base::Bind(&NetworkChangeNotifierLinux::Thread::OnIPAddressChanged, - base::Unretained(this)), - base::Bind(&NetworkChangeNotifierLinux::Thread::OnLinkChanged, - base::Unretained(this)), + : address_tracker_( + base::BindRepeating(&NetworkChangeNotifierLinux:: + BlockingThreadObjects::OnIPAddressChanged, + base::Unretained(this)), + base::BindRepeating( + &NetworkChangeNotifierLinux::BlockingThreadObjects::OnLinkChanged, + base::Unretained(this)), base::DoNothing(), - ignored_interfaces)), + ignored_interfaces), last_type_(NetworkChangeNotifier::CONNECTION_NONE) {} -NetworkChangeNotifierLinux::Thread::~Thread() { - DCHECK(!Thread::IsRunning()); -} - -void NetworkChangeNotifierLinux::Thread::Init() { - address_tracker_->Init(); +void NetworkChangeNotifierLinux::BlockingThreadObjects::Init() { + address_tracker_.Init(); last_type_ = GetCurrentConnectionType(); - dns_config_service_ = DnsConfigService::CreateSystemService(); - dns_config_service_->WatchConfig( + dns_config_service_.WatchConfig( base::Bind(&NetworkChangeNotifier::SetDnsConfig)); } -void NetworkChangeNotifierLinux::Thread::CleanUp() { - // Delete AddressTrackerLinux before MessageLoop gets deleted as - // AddressTrackerLinux's FileDescriptorWatcher holds a pointer to the - // MessageLoop. - address_tracker_.reset(); - dns_config_service_.reset(); -} - -void NetworkChangeNotifierLinux::Thread::OnIPAddressChanged() { +void NetworkChangeNotifierLinux::BlockingThreadObjects::OnIPAddressChanged() { NetworkChangeNotifier::NotifyObserversOfIPAddressChange(); // When the IP address of a network interface is added/deleted, the // connection type may have changed. OnLinkChanged(); } -void NetworkChangeNotifierLinux::Thread::OnLinkChanged() { +void NetworkChangeNotifierLinux::BlockingThreadObjects::OnLinkChanged() { if (last_type_ != GetCurrentConnectionType()) { NetworkChangeNotifier::NotifyObserversOfConnectionTypeChange(); last_type_ = GetCurrentConnectionType(); @@ -100,19 +90,24 @@ NetworkChangeNotifierLinux::NetworkChangeNotifierLinux( const std::unordered_set<std::string>& ignored_interfaces) : NetworkChangeNotifier(NetworkChangeCalculatorParamsLinux()), - notifier_thread_(new Thread(ignored_interfaces)) { - // We create this notifier thread because the notification implementation - // needs a MessageLoopForIO, and there's no guarantee that - // MessageLoopCurrent::Get() meets that criterion. - base::Thread::Options thread_options(base::MessageLoop::TYPE_IO, 0); - notifier_thread_->StartWithOptions(thread_options); + blocking_thread_runner_( + base::CreateSequencedTaskRunnerWithTraits({base::MayBlock()})), + blocking_thread_objects_( + new BlockingThreadObjects(ignored_interfaces), + // Ensure |blocking_thread_objects_| lives on + // |blocking_thread_runner_| to prevent races where + // NetworkChangeNotifierLinux outlives + // ScopedTaskEnvironment. https://crbug.com/938126 + base::OnTaskRunnerDeleter(blocking_thread_runner_)) { + blocking_thread_runner_->PostTask( + FROM_HERE, + base::BindOnce(&NetworkChangeNotifierLinux::BlockingThreadObjects::Init, + // The Unretained pointer is safe here because it's + // posted before the deleter can post. + base::Unretained(blocking_thread_objects_.get()))); } -NetworkChangeNotifierLinux::~NetworkChangeNotifierLinux() { - // Stopping from here allows us to sanity- check that the notifier - // thread shut down properly. - notifier_thread_->Stop(); -} +NetworkChangeNotifierLinux::~NetworkChangeNotifierLinux() = default; // static NetworkChangeNotifier::NetworkChangeCalculatorParams @@ -130,12 +125,12 @@ NetworkChangeNotifier::ConnectionType NetworkChangeNotifierLinux::GetCurrentConnectionType() const { - return notifier_thread_->GetCurrentConnectionType(); + return blocking_thread_objects_->GetCurrentConnectionType(); } const internal::AddressTrackerLinux* NetworkChangeNotifierLinux::GetAddressTrackerInternal() const { - return notifier_thread_->address_tracker(); + return blocking_thread_objects_->address_tracker(); } } // namespace net
diff --git a/net/base/network_change_notifier_linux.h b/net/base/network_change_notifier_linux.h index 3439270b..fa14f30 100644 --- a/net/base/network_change_notifier_linux.h +++ b/net/base/network_change_notifier_linux.h
@@ -10,9 +10,15 @@ #include "base/compiler_specific.h" #include "base/macros.h" +#include "base/memory/scoped_refptr.h" #include "net/base/net_export.h" #include "net/base/network_change_notifier.h" +namespace base { +class SequencedTaskRunner; +struct OnTaskRunnerDeleter; +} // namespace base + namespace net { class NET_EXPORT_PRIVATE NetworkChangeNotifierLinux @@ -28,7 +34,7 @@ const std::unordered_set<std::string>& ignored_interfaces); private: - class Thread; + class BlockingThreadObjects; ~NetworkChangeNotifierLinux() override; static NetworkChangeCalculatorParams NetworkChangeCalculatorParamsLinux(); @@ -39,11 +45,14 @@ const internal::AddressTrackerLinux* GetAddressTrackerInternal() const override; - // The thread used to listen for notifications. This relays the notification - // to the registered observers without posting back to the thread the object - // was created on. - // Also used for DnsConfigService which requires TYPE_IO message loop. - std::unique_ptr<Thread> notifier_thread_; + // |blocking_thread_objects_| will live on this runner. + scoped_refptr<base::SequencedTaskRunner> blocking_thread_runner_; + // A collection of objects that must live on blocking sequences. These objects + // listen for notifications and relay the notifications to the registered + // observers without posting back to the thread the object was created on. + // Also used for DnsConfigService which also must live on blocking sequences. + std::unique_ptr<BlockingThreadObjects, base::OnTaskRunnerDeleter> + blocking_thread_objects_; DISALLOW_COPY_AND_ASSIGN(NetworkChangeNotifierLinux); };
diff --git a/net/dns/dns_config_service_posix.cc b/net/dns/dns_config_service_posix.cc index 3da2eb5..48ee925 100644 --- a/net/dns/dns_config_service_posix.cc +++ b/net/dns/dns_config_service_posix.cc
@@ -18,7 +18,7 @@ #include "base/metrics/histogram_macros.h" #include "base/single_thread_task_runner.h" #include "base/threading/scoped_blocking_call.h" -#include "base/threading/thread_task_runner_handle.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "base/time/time.h" #include "build/build_config.h" #include "net/base/ip_address.h" @@ -273,7 +273,7 @@ void OnConfigChanged(bool succeeded) { // Ignore transient flutter of resolv.conf by delaying the signal a bit. const base::TimeDelta kDelay = base::TimeDelta::FromMilliseconds(50); - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, base::BindOnce(&Watcher::OnConfigChangedDelayed, weak_factory_.GetWeakPtr(), succeeded),
diff --git a/remoting/base/service_urls.cc b/remoting/base/service_urls.cc index 4500599..684db13c6 100644 --- a/remoting/base/service_urls.cc +++ b/remoting/base/service_urls.cc
@@ -10,26 +10,28 @@ #include "remoting/base/remoting_bot.h" // Configurable service data. -const char kDirectoryBaseUrl[] = "https://www.googleapis.com/chromoting/v1"; -const char kGcdBaseUrl[] = "https://www.googleapis.com/clouddevices/v1"; -const char kXmppServerAddress[] = "talk.google.com:443"; -const char kXmppServerAddressForMe2MeHost[] = "talk.google.com:5222"; -const bool kXmppServerUseTls = true; -const char kGcdJid[] = "clouddevices.gserviceaccount.com"; +constexpr char kDirectoryBaseUrl[] = "https://www.googleapis.com/chromoting/v1"; +constexpr char kGcdBaseUrl[] = "https://www.googleapis.com/clouddevices/v1"; +constexpr char kXmppServerAddress[] = "talk.google.com:443"; +constexpr char kXmppServerAddressForMe2MeHost[] = "talk.google.com:5222"; +constexpr bool kXmppServerUseTls = true; +constexpr char kGcdJid[] = "clouddevices.gserviceaccount.com"; +constexpr char kFtlServerEndpoint[] = "instantmessaging-pa.googleapis.com"; // Command line switches. #if !defined(NDEBUG) -const char kDirectoryBaseUrlSwitch[] = "directory-base-url"; -const char kGcdBaseUrlSwitch[] = "gcd-base-url"; -const char kXmppServerAddressSwitch[] = "xmpp-server-address"; -const char kXmppServerDisableTlsSwitch[] = "disable-xmpp-server-tls"; -const char kDirectoryBotJidSwitch[] = "directory-bot-jid"; -const char kGcdJidSwitch[] = "gcd-jid"; +constexpr char kDirectoryBaseUrlSwitch[] = "directory-base-url"; +constexpr char kGcdBaseUrlSwitch[] = "gcd-base-url"; +constexpr char kXmppServerAddressSwitch[] = "xmpp-server-address"; +constexpr char kXmppServerDisableTlsSwitch[] = "disable-xmpp-server-tls"; +constexpr char kDirectoryBotJidSwitch[] = "directory-bot-jid"; +constexpr char kGcdJidSwitch[] = "gcd-jid"; +constexpr char kFtlServerEndpointSwitch[] = "ftl-server-endpoint"; #endif // !defined(NDEBUG) // Non-configurable service paths. -const char kDirectoryHostsSuffix[] = "/@me/hosts/"; -const char kDirectoryIceConfigSuffix[] = "/@me/iceconfig"; +constexpr char kDirectoryHostsSuffix[] = "/@me/hosts/"; +constexpr char kDirectoryIceConfigSuffix[] = "/@me/iceconfig"; namespace remoting { @@ -40,7 +42,8 @@ xmpp_server_address_for_me2me_host_(kXmppServerAddressForMe2MeHost), xmpp_server_use_tls_(kXmppServerUseTls), directory_bot_jid_(kRemotingBotJid), - gcd_jid_(kGcdJid) { + gcd_jid_(kGcdJid), + ftl_server_endpoint_(kFtlServerEndpoint) { #if !defined(NDEBUG) // The command line may not be initialized when running as a PNaCl plugin. if (base::CommandLine::InitializedForCurrentProcess()) { @@ -69,6 +72,10 @@ if (command_line->HasSwitch(kGcdJidSwitch)) { gcd_jid_ = command_line->GetSwitchValueASCII(kGcdJidSwitch); } + if (command_line->HasSwitch(kFtlServerEndpointSwitch)) { + ftl_server_endpoint_ = + command_line->GetSwitchValueASCII(kFtlServerEndpointSwitch); + } } #endif // !defined(NDEBUG)
diff --git a/remoting/base/service_urls.h b/remoting/base/service_urls.h index 12c4d9c0..4f29b7c 100644 --- a/remoting/base/service_urls.h +++ b/remoting/base/service_urls.h
@@ -45,6 +45,10 @@ // ICE config URL. const std::string& ice_config_url() const { return ice_config_url_; } + const std::string& ftl_server_endpoint() const { + return ftl_server_endpoint_; + } + #if !defined(NDEBUG) // Override the directory bot JID for testing. void set_directory_bot_jid(const std::string& bot_jid) { @@ -67,6 +71,7 @@ std::string directory_bot_jid_; std::string gcd_jid_; std::string ice_config_url_; + std::string ftl_server_endpoint_; DISALLOW_COPY_AND_ASSIGN(ServiceUrls); };
diff --git a/remoting/protocol/webrtc_transport.h b/remoting/protocol/webrtc_transport.h index ebd97c7a..b58c668 100644 --- a/remoting/protocol/webrtc_transport.h +++ b/remoting/protocol/webrtc_transport.h
@@ -34,6 +34,8 @@ public: class EventHandler { public: + virtual ~EventHandler() = default; + // Called after |peer_connection| has been created but before handshake. The // handler should create data channels and media streams. Renegotiation will // be required in two cases after this method returns: @@ -58,9 +60,6 @@ scoped_refptr<webrtc::MediaStreamInterface> stream) = 0; virtual void OnWebrtcTransportMediaStreamRemoved( scoped_refptr<webrtc::MediaStreamInterface> stream) = 0; - - protected: - virtual ~EventHandler() {} }; WebrtcTransport(rtc::Thread* worker_thread,
diff --git a/remoting/signaling/ftl_grpc_context.cc b/remoting/signaling/ftl_grpc_context.cc index 0ecbc8f..2c132844 100644 --- a/remoting/signaling/ftl_grpc_context.cc +++ b/remoting/signaling/ftl_grpc_context.cc
@@ -10,6 +10,7 @@ #include "base/no_destructor.h" #include "build/build_config.h" #include "google_apis/google_api_keys.h" +#include "remoting/base/service_urls.h" #include "third_party/grpc/src/include/grpcpp/channel.h" #include "third_party/grpc/src/include/grpcpp/client_context.h" #include "third_party/grpc/src/include/grpcpp/grpcpp.h" @@ -20,9 +21,6 @@ constexpr char kChromotingAppIdentifier[] = "CRD"; -// TODO(yuweih): We should target different service environments. -constexpr char kFtlServerEndpoint[] = "instantmessaging-pa.googleapis.com"; - static base::NoDestructor<GrpcChannelSharedPtr> g_channel_for_testing; const net::BackoffEntry::Policy kBackoffPolicy = { @@ -81,7 +79,8 @@ if (*g_channel_for_testing) { return *g_channel_for_testing; } - return CreateSslChannelForEndpoint(kFtlServerEndpoint); + return CreateSslChannelForEndpoint( + ServiceUrls::GetInstance()->ftl_server_endpoint()); } // static
diff --git a/remoting/test/ftl_signaling_playground.cc b/remoting/test/ftl_signaling_playground.cc index da1bc43..b92d04c 100644 --- a/remoting/test/ftl_signaling_playground.cc +++ b/remoting/test/ftl_signaling_playground.cc
@@ -5,6 +5,7 @@ #include "remoting/test/ftl_signaling_playground.h" #include <inttypes.h> + #include <string> #include <utility> #include <vector> @@ -20,15 +21,21 @@ #include "base/run_loop.h" #include "base/task/post_task.h" #include "jingle/glue/thread_wrapper.h" +#include "remoting/base/chromium_url_request.h" #include "remoting/base/logging.h" #include "remoting/base/oauth_token_getter_impl.h" #include "remoting/base/rsa_key_pair.h" +#include "remoting/base/service_urls.h" +#include "remoting/base/url_request_context_getter.h" #include "remoting/protocol/auth_util.h" +#include "remoting/protocol/chromium_port_allocator_factory.h" #include "remoting/protocol/jingle_session_manager.h" #include "remoting/protocol/me2me_host_authenticator_factory.h" #include "remoting/protocol/negotiating_client_authenticator.h" +#include "remoting/protocol/network_settings.h" #include "remoting/protocol/pairing_registry.h" #include "remoting/protocol/transport.h" +#include "remoting/protocol/transport_context.h" #include "remoting/signaling/ftl_grpc_context.h" #include "remoting/signaling/ftl_services.grpc.pb.h" #include "remoting/signaling/ftl_signal_strategy.h" @@ -37,6 +44,8 @@ #include "remoting/test/test_device_id_provider.h" #include "remoting/test/test_oauth_token_getter.h" #include "remoting/test/test_token_storage.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" +#include "services/network/transitional_url_loader_factory_owner.h" namespace remoting { @@ -62,16 +71,43 @@ return ""; } -class FakeTransport : public protocol::Transport { +class FakeTransportEventHandler final + : public protocol::WebrtcTransport::EventHandler { public: - FakeTransport() = default; - ~FakeTransport() override = default; - - void Start(protocol::Authenticator* authenticator, - SendTransportInfoCallback send_transport_info_callback) override {} - bool ProcessTransportInfo(jingle_xmpp::XmlElement* transport_info) override { - return false; + explicit FakeTransportEventHandler(base::OnceClosure on_closed) { + on_closed_ = std::move(on_closed); } + + ~FakeTransportEventHandler() override = default; + + // protocol::WebrtcTransport::EventHandler interface. + void OnWebrtcTransportConnecting() override { + HOST_LOG << "Webrtc transport is connecting..."; + } + + void OnWebrtcTransportConnected() override { + HOST_LOG << "Webrtc transport is connected!!!"; + std::move(on_closed_).Run(); + } + + void OnWebrtcTransportError(protocol::ErrorCode error) override { + LOG(ERROR) << "Webrtc transport error: " << error; + std::move(on_closed_).Run(); + } + + void OnWebrtcTransportIncomingDataChannel( + const std::string& name, + std::unique_ptr<protocol::MessagePipe> pipe) override {} + + void OnWebrtcTransportMediaStreamAdded( + scoped_refptr<webrtc::MediaStreamInterface> stream) override {} + + void OnWebrtcTransportMediaStreamRemoved( + scoped_refptr<webrtc::MediaStreamInterface> stream) override {} + + private: + base::OnceClosure on_closed_; + DISALLOW_COPY_AND_ASSIGN(FakeTransportEventHandler); }; } // namespace @@ -105,6 +141,13 @@ storage_ = test::TestTokenStorage::OnDisk(username, storage_path); token_getter_ = std::make_unique<test::TestOAuthTokenGetter>(storage_.get()); + auto url_request_context_getter = + base::MakeRefCounted<URLRequestContextGetter>( + base::ThreadTaskRunnerHandle::Get()); + url_loader_factory_owner_ = + std::make_unique<network::TransitionalURLLoaderFactoryOwner>( + url_request_context_getter); + base::RunLoop initialize_token_getter_loop; token_getter_->Initialize(initialize_token_getter_loop.QuitClosure()); initialize_token_getter_loop.Run(); @@ -154,7 +197,8 @@ protocol::Session* owned_session, protocol::SessionManager::IncomingSessionResponse* response) { HOST_LOG << "Received incoming session!\n"; - RegisterSession(base::WrapUnique(owned_session)); + RegisterSession(base::WrapUnique(owned_session), + protocol::TransportRole::CLIENT); *response = protocol::SessionManager::ACCEPT; } @@ -182,7 +226,7 @@ std::make_unique<protocol::NegotiatingClientAuthenticator>( signal_strategy_->GetLocalAddress().id(), host_jid, client_auth_config)); - RegisterSession(std::move(session)); + RegisterSession(std::move(session), protocol::TransportRole::SERVER); } void FtlSignalingPlayground::FetchSecret( @@ -202,26 +246,47 @@ session_manager_ = std::make_unique<protocol::JingleSessionManager>(signal_strategy_.get()); - session_manager_->set_protocol_config( - protocol::CandidateSessionConfig::CreateDefault()); + auto protocol_config = protocol::CandidateSessionConfig::CreateDefault(); + protocol_config->set_webrtc_supported(true); + session_manager_->set_protocol_config(std::move(protocol_config)); signal_strategy_->Connect(); } void FtlSignalingPlayground::TearDownSignaling() { + on_signaling_connected_callback_.Reset(); session_.reset(); - fake_transport_.reset(); + transport_.reset(); + transport_event_handler_.reset(); signal_strategy_->RemoveListener(this); session_manager_.reset(); signal_strategy_.reset(); } void FtlSignalingPlayground::RegisterSession( - std::unique_ptr<protocol::Session> session) { + std::unique_ptr<protocol::Session> session, + protocol::TransportRole transport_role) { session_ = std::move(session); - fake_transport_ = std::make_unique<FakeTransport>(); + protocol::NetworkSettings network_settings( + protocol::NetworkSettings::NAT_TRAVERSAL_FULL); + auto transport_context = base::MakeRefCounted<protocol::TransportContext>( + signal_strategy_.get(), + std::make_unique<protocol::ChromiumPortAllocatorFactory>(), + std::make_unique<ChromiumUrlRequestFactory>( + url_loader_factory_owner_->GetURLLoaderFactory()), + network_settings, transport_role); + transport_context->set_ice_config_url( + ServiceUrls::GetInstance()->ice_config_url(), token_getter_.get()); + std::unique_ptr<protocol::SessionManager> session_manager( + new protocol::JingleSessionManager(signal_strategy_.get())); + transport_event_handler_ = std::make_unique<FakeTransportEventHandler>( + base::BindOnce(&FtlSignalingPlayground::AsyncTearDownAndRunCallback, + base::Unretained(this))); + transport_ = std::make_unique<protocol::WebrtcTransport>( + jingle_glue::JingleThreadWrapper::current(), transport_context, + transport_event_handler_.get()); session_->SetEventHandler(this); - session_->SetTransport(fake_transport_.get()); + session_->SetTransport(transport_.get()); } void FtlSignalingPlayground::OnSignalStrategyStateChange( @@ -281,7 +346,7 @@ return; case protocol::Session::AUTHENTICATED: HOST_LOG << "Session is successfully authenticated!!!"; - break; + return; case protocol::Session::CLOSED: case protocol::Session::FAILED: @@ -289,6 +354,15 @@ break; } + TearDownAndRunCallback(); +} + +void FtlSignalingPlayground::AsyncTearDownAndRunCallback() { + tear_down_timer_.Start(FROM_HERE, base::TimeDelta(), this, + &FtlSignalingPlayground::TearDownAndRunCallback); +} + +void FtlSignalingPlayground::TearDownAndRunCallback() { TearDownSignaling(); if (current_callback_) { std::move(current_callback_).Run();
diff --git a/remoting/test/ftl_signaling_playground.h b/remoting/test/ftl_signaling_playground.h index 21b5932..9256623 100644 --- a/remoting/test/ftl_signaling_playground.h +++ b/remoting/test/ftl_signaling_playground.h
@@ -10,19 +10,21 @@ #include "base/callback_forward.h" #include "base/macros.h" +#include "base/timer/timer.h" #include "remoting/base/oauth_token_getter.h" #include "remoting/protocol/client_authentication_config.h" #include "remoting/protocol/session.h" #include "remoting/protocol/session_manager.h" +#include "remoting/protocol/webrtc_transport.h" #include "remoting/signaling/ftl_messaging_client.h" #include "remoting/signaling/ftl_registration_manager.h" #include "remoting/signaling/signal_strategy.h" -namespace remoting { +namespace network { +class TransitionalURLLoaderFactoryOwner; +} // namespace network -namespace protocol { -class Transport; -} // namespace protocol +namespace remoting { namespace test { class TestOAuthTokenGetter; @@ -53,7 +55,8 @@ void SetUpSignaling(); void TearDownSignaling(); - void RegisterSession(std::unique_ptr<protocol::Session> session); + void RegisterSession(std::unique_ptr<protocol::Session> session, + protocol::TransportRole transport_role); // SignalStrategy::Listener interface. void OnSignalStrategyStateChange(SignalStrategy::State state) override; @@ -63,17 +66,26 @@ // Session::EventHandler interface. void OnSessionStateChange(protocol::Session::State state) override; + void AsyncTearDownAndRunCallback(); + void TearDownAndRunCallback(); + std::unique_ptr<test::TestTokenStorage> storage_; std::unique_ptr<test::TestOAuthTokenGetter> token_getter_; + std::unique_ptr<network::TransitionalURLLoaderFactoryOwner> + url_loader_factory_owner_; std::unique_ptr<SignalStrategy> signal_strategy_; std::unique_ptr<protocol::SessionManager> session_manager_; - std::unique_ptr<protocol::Transport> fake_transport_; + std::unique_ptr<protocol::WebrtcTransport::EventHandler> + transport_event_handler_; + std::unique_ptr<protocol::WebrtcTransport> transport_; std::unique_ptr<protocol::Session> session_; base::OnceClosure current_callback_; base::OnceClosure on_signaling_connected_callback_; + base::OneShotTimer tear_down_timer_; + DISALLOW_COPY_AND_ASSIGN(FtlSignalingPlayground); };
diff --git a/remoting/test/test_oauth_token_getter.cc b/remoting/test/test_oauth_token_getter.cc index 05ce6a3..74fdb24 100644 --- a/remoting/test/test_oauth_token_getter.cc +++ b/remoting/test/test_oauth_token_getter.cc
@@ -87,6 +87,21 @@ void TestOAuthTokenGetter::ResetWithAuthenticationFlow( base::OnceClosure on_done) { + on_authentication_done_.push(std::move(on_done)); + InvalidateCache(); +} + +void TestOAuthTokenGetter::CallWithToken(TokenCallback on_access_token) { + token_getter_->CallWithToken(std::move(on_access_token)); +} + +void TestOAuthTokenGetter::InvalidateCache() { + if (is_authenticating_) { + return; + } + + is_authenticating_ = true; + static const std::string read_auth_code_prompt = base::StringPrintf( "Please authenticate at:\n\n" " %s\n\n" @@ -105,17 +120,8 @@ base::DoNothing::Repeatedly<const std::string&, const std::string&>()); // Get the access token so that we can reuse it for next time. - token_getter_->CallWithToken( - base::BindOnce(&TestOAuthTokenGetter::OnAccessToken, - weak_factory_.GetWeakPtr(), std::move(on_done))); -} - -void TestOAuthTokenGetter::CallWithToken(TokenCallback on_access_token) { - token_getter_->CallWithToken(std::move(on_access_token)); -} - -void TestOAuthTokenGetter::InvalidateCache() { - ResetWithAuthenticationFlow(base::DoNothing()); + token_getter_->CallWithToken(base::BindOnce( + &TestOAuthTokenGetter::OnAccessToken, weak_factory_.GetWeakPtr())); } std::unique_ptr<OAuthTokenGetter> @@ -133,21 +139,24 @@ /* auto_refresh */ true); } -void TestOAuthTokenGetter::OnAccessToken(base::OnceClosure on_done, - OAuthTokenGetter::Status status, +void TestOAuthTokenGetter::OnAccessToken(OAuthTokenGetter::Status status, const std::string& user_email, const std::string& access_token) { + is_authenticating_ = false; if (status != OAuthTokenGetter::Status::SUCCESS) { fprintf(stderr, "Failed to authenticate. Please check if your access token is " "correct.\n"); - ResetWithAuthenticationFlow(std::move(on_done)); + InvalidateCache(); return; } VLOG(0) << "Received access_token: " << access_token; token_storage_->StoreUserEmail(user_email); token_storage_->StoreAccessToken(access_token); - std::move(on_done).Run(); + while (!on_authentication_done_.empty()) { + std::move(on_authentication_done_.front()).Run(); + on_authentication_done_.pop(); + } } } // namespace test
diff --git a/remoting/test/test_oauth_token_getter.h b/remoting/test/test_oauth_token_getter.h index 4bbbfb0..16ca4e1 100644 --- a/remoting/test/test_oauth_token_getter.h +++ b/remoting/test/test_oauth_token_getter.h
@@ -9,6 +9,7 @@ #include <string> #include "base/callback_forward.h" +#include "base/containers/queue.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "remoting/base/oauth_token_getter.h" @@ -49,8 +50,7 @@ const OAuthTokenGetter::CredentialsUpdatedCallback& on_credentials_update); - void OnAccessToken(base::OnceClosure on_done, - OAuthTokenGetter::Status status, + void OnAccessToken(OAuthTokenGetter::Status status, const std::string& user_email, const std::string& access_token); @@ -58,6 +58,8 @@ url_loader_factory_owner_; TestTokenStorage* token_storage_ = nullptr; std::unique_ptr<OAuthTokenGetter> token_getter_; + bool is_authenticating_ = false; + base::queue<base::OnceClosure> on_authentication_done_; base::WeakPtrFactory<TestOAuthTokenGetter> weak_factory_; DISALLOW_COPY_AND_ASSIGN(TestOAuthTokenGetter);
diff --git a/services/network/resource_scheduler.cc b/services/network/resource_scheduler.cc index a44ebe4..bfc7818b 100644 --- a/services/network/resource_scheduler.cc +++ b/services/network/resource_scheduler.cc
@@ -671,9 +671,28 @@ void RecordMetricsOnStartRequest(const ScheduledResourceRequestImpl& request, base::TimeTicks ticks_now) const { + const size_t non_delayable_requests_in_flight_count = + in_flight_requests_.size() - in_flight_delayable_count_; + // Record the number of delayable requests in-flight when a non-delayable // request starts. if (!RequestAttributesAreSet(request.attributes(), kAttributeDelayable)) { + if (non_delayable_requests_in_flight_count > 0) { + if (last_non_delayable_request_start_) { + UMA_HISTOGRAM_MEDIUM_TIMES( + "ResourceScheduler.NonDelayableLastStartToNonDelayableStart." + "NonDelayableInFlight", + ticks_now - last_non_delayable_request_start_.value()); + } + } else { + if (last_non_delayable_request_end_) { + UMA_HISTOGRAM_MEDIUM_TIMES( + "ResourceScheduler.NonDelayableLastEndToNonDelayableStart." + "NonDelayableNotInFlight", + ticks_now - last_non_delayable_request_end_.value()); + } + } + UMA_HISTOGRAM_COUNTS_100( "ResourceScheduler.NumDelayableRequestsInFlightAtStart.NonDelayable", in_flight_delayable_count_);
diff --git a/services/network/resource_scheduler_unittest.cc b/services/network/resource_scheduler_unittest.cc index e3e2e4a..e2a06e6 100644 --- a/services/network/resource_scheduler_unittest.cc +++ b/services/network/resource_scheduler_unittest.cc
@@ -1833,6 +1833,12 @@ ExpectSampleIsAtLeastSpecifiedValue( histogram_tester_1, + "ResourceScheduler.NonDelayableLastStartToNonDelayableStart." + "NonDelayableInFlight", + high1_start_to_high2_start.InMilliseconds()); + + ExpectSampleIsAtLeastSpecifiedValue( + histogram_tester_1, "ResourceScheduler.NonDelayableLastStartOrEndToNonDelayableStart", high1_start_to_high2_start.InMilliseconds()); @@ -1868,6 +1874,12 @@ ExpectSampleIsAtLeastSpecifiedValue( histogram_tester_2, + "ResourceScheduler.NonDelayableLastEndToNonDelayableStart." + "NonDelayableNotInFlight", + high2_end_to_high3_start.InMilliseconds()); + + ExpectSampleIsAtLeastSpecifiedValue( + histogram_tester_2, "ResourceScheduler.NonDelayableLastStartOrEndToNonDelayableStart", high2_end_to_high3_start.InMilliseconds()); }
diff --git a/third_party/blink/renderer/bindings/scripts/utilities.py b/third_party/blink/renderer/bindings/scripts/utilities.py index cbd7579..45df0332 100644 --- a/third_party/blink/renderer/bindings/scripts/utilities.py +++ b/third_party/blink/renderer/bindings/scripts/utilities.py
@@ -445,9 +445,9 @@ 'CSSImageValueOrHTMLImageElementOrSVGImageElementOrHTMLVideoElementOrHTMLCanvasElementOrImageBitmapOrOffscreenCanvas': 'CanvasImageSource', # modules/canvas/htmlcanvas/html_canvas_element_module_support_webgl2_compute.idl # Due to html_canvas_element_module_support_webgl2_compute.idl and html_canvas_element_module.idl are exclusive in modules_idl_files.gni, they have same shorten name. - 'CanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrWebGL2ComputeRenderingContextOrImageBitmapRenderingContextOrXRPresentationContext': 'RenderingContext', + 'CanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrWebGL2ComputeRenderingContextOrImageBitmapRenderingContextOrXRPresentationContextOrGPUCanvasContext': 'RenderingContext', # modules/canvas/htmlcanvas/html_canvas_element_module.idl - 'CanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrImageBitmapRenderingContextOrXRPresentationContext': 'RenderingContext', + 'CanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrImageBitmapRenderingContextOrXRPresentationContextOrGPUCanvasContext': 'RenderingContext', # core/frame/window_or_worker_global_scope.idl 'HTMLImageElementOrSVGImageElementOrHTMLVideoElementOrHTMLCanvasElementOrBlobOrImageDataOrImageBitmapOrOffscreenCanvas': 'ImageBitmapSource', # bindings/tests/idls/core/TestTypedefs.idl
diff --git a/third_party/blink/renderer/core/execution_context/security_context.h b/third_party/blink/renderer/core/execution_context/security_context.h index 02bfd5a5..1c79dfe 100644 --- a/third_party/blink/renderer/core/execution_context/security_context.h +++ b/third_party/blink/renderer/core/execution_context/security_context.h
@@ -129,9 +129,6 @@ bool GetMixedAutoUpgradeOptOut() { return mixed_autoupgrade_opt_out_; } FeaturePolicy* GetFeaturePolicy() const { return feature_policy_.get(); } - FeaturePolicy* GetReportOnlyFeaturePolicy() const { - return report_only_feature_policy_.get(); - } void SetFeaturePolicy(std::unique_ptr<FeaturePolicy> feature_policy); // Constructs the enforcement FeaturePolicy struct for this security context. // The resulted FeaturePolicy is a combination of:
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 cb0a8ae6..71c3d053 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.cc +++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -961,11 +961,11 @@ if (nested_layout_count_) return; - // TODO(crbug.com/946004): Move the following line into a DCHECK_IS_ON() block - // when we no longer see missing layout reports in LayoutNG. +#if DCHECK_IS_ON() // Post-layout assert that nobody was re-marked as needing layout during // layout. GetLayoutView()->AssertSubtreeIsLaidOut(); +#endif if (frame_->IsMainFrame()) { // Scrollbars changing state can cause a visual viewport size change. @@ -2885,9 +2885,9 @@ // These asserts ensure that parent frames are clean, when child frames // finished updating layout and style. CheckDoesNotNeedLayout(); - // TODO(crbug.com/946004): Move the following line into a DCHECK_IS_ON() block - // when we no longer see missing layout reports in LayoutNG. +#if DCHECK_IS_ON() frame_->GetDocument()->GetLayoutView()->AssertLaidOut(); +#endif UpdateGeometriesIfNeeded();
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.cc b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.cc index 9bc6da4..0ab64d5 100644 --- a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.cc +++ b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.cc
@@ -148,6 +148,8 @@ return kContextImageBitmap; if (id == "xrpresent") return kContextXRPresent; + if (id == "gpupresent" && RuntimeEnabledFeatures::WebGPUEnabled()) + return kContextGPUPresent; return kContextTypeUnknown; }
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h index faca212..858c10a 100644 --- a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h +++ b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h
@@ -71,7 +71,8 @@ kContextImageBitmap = 5, kContextXRPresent = 6, kContextWebgl2Compute = 7, - kContextTypeUnknown = 8, + kContextGPUPresent = 8, + kContextTypeUnknown = 9, kMaxValue = kContextTypeUnknown, };
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element.h b/third_party/blink/renderer/core/html/canvas/html_canvas_element.h index 7afd096..eace8c95 100644 --- a/third_party/blink/renderer/core/html/canvas/html_canvas_element.h +++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element.h
@@ -75,13 +75,13 @@ #if defined(SUPPORT_WEBGL2_COMPUTE_CONTEXT) class - CanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrWebGL2ComputeRenderingContextOrImageBitmapRenderingContextOrXRPresentationContext; -typedef CanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrWebGL2ComputeRenderingContextOrImageBitmapRenderingContextOrXRPresentationContext + CanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrWebGL2ComputeRenderingContextOrImageBitmapRenderingContextOrXRPresentationContextOrGPUCanvasContext; +typedef CanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrWebGL2ComputeRenderingContextOrImageBitmapRenderingContextOrXRPresentationContextOrGPUCanvasContext RenderingContext; #else class - CanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrImageBitmapRenderingContextOrXRPresentationContext; -typedef CanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrImageBitmapRenderingContextOrXRPresentationContext + CanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrImageBitmapRenderingContextOrXRPresentationContextOrGPUCanvasContext; +typedef CanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrImageBitmapRenderingContextOrXRPresentationContextOrGPUCanvasContext RenderingContext; #endif
diff --git a/third_party/blink/renderer/core/inspector/inspector_highlight.cc b/third_party/blink/renderer/core/inspector/inspector_highlight.cc index 04a5b56..7844e84 100644 --- a/third_party/blink/renderer/core/inspector/inspector_highlight.cc +++ b/third_party/blink/renderer/core/inspector/inspector_highlight.cc
@@ -359,7 +359,8 @@ // elements like images should use their intristic height and expand the // linebox as needed. To get an appropriate quads we descend // into the children and have them add their boxes. - if (layout_object->IsLayoutInline()) { + if (layout_object->IsLayoutInline() && + LayoutTreeBuilderTraversal::FirstChild(*node)) { for (Node* child = LayoutTreeBuilderTraversal::FirstChild(*node); child; child = LayoutTreeBuilderTraversal::NextSibling(*child)) CollectQuadsRecursive(child, out_quads);
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h index 9d85143..0554a29 100644 --- a/third_party/blink/renderer/core/layout/layout_object.h +++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -392,11 +392,6 @@ LayoutObject& layout_object_; bool preexisting_forbidden_; }; -#endif // DCHECK_IS_ON() - - // TODO(crbug.com/946004): When we no longer see missing layouts in LayoutNG, - // move the following two functions back to the DCHECK_IS_ON() block and - // remove relevant branches and CHECK. void AssertLaidOut() const { #ifndef NDEBUG @@ -404,16 +399,9 @@ ShowLayoutTreeForThis(); #endif SECURITY_DCHECK(!NeedsLayout() || LayoutBlockedByDisplayLock()); - if (!RuntimeEnabledFeatures::LayoutNGEnabled()) - return; - CHECK(!NeedsLayout() || LayoutBlockedByDisplayLock()) << this; } void AssertSubtreeIsLaidOut() const { -#if !DCHECK_IS_ON() - if (!RuntimeEnabledFeatures::LayoutNGEnabled()) - return; -#endif for (const LayoutObject* layout_object = this; layout_object; layout_object = layout_object->LayoutBlockedByDisplayLock() ? layout_object->NextInPreOrderAfterChildren() @@ -422,7 +410,6 @@ } } -#if DCHECK_IS_ON() void AssertClearedPaintInvalidationFlags() const { #ifndef NDEBUG if (PaintInvalidationStateIsDirty() && !PrePaintBlockedByDisplayLock()) { @@ -441,7 +428,7 @@ } } -#endif // DCHECK_IS_ON() +#endif // LayoutObject tree manipulation //////////////////////////////////////////
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 9cd5981..eb0b1bd 100644 --- a/third_party/blink/renderer/core/layout/layout_table_section.cc +++ b/third_party/blink/renderer/core/layout/layout_table_section.cc
@@ -1394,19 +1394,6 @@ for (auto* cell = row->FirstCell(); cell; cell = cell->NextCell()) { if (cell->HasSelfPaintingLayer()) continue; - // Let the section's self visual overflow cover the cell's whole collapsed - // borders. This ensures correct raster invalidation on section border - // style change. - // TODO(wangxianzhu): When implementing row as DisplayItemClient of - // collapsed borders, the following logic should be replaced by - // invalidation of rows on section border style change. crbug.com/663208. - if (const auto* collapsed_borders = cell->GetCollapsedBorderValues()) { - LayoutRect rect = cell->RectForOverflowPropagation( - collapsed_borders->LocalVisualRect()); - rect.MoveBy(cell->Location()); - AddSelfVisualOverflow(rect); - } - if (force_full_paint_ || !cell->HasVisualOverflow()) continue;
diff --git a/third_party/blink/renderer/core/layout/layout_table_section_test.cc b/third_party/blink/renderer/core/layout/layout_table_section_test.cc index 9b40a63..f26085d5 100644 --- a/third_party/blink/renderer/core/layout/layout_table_section_test.cc +++ b/third_party/blink/renderer/core/layout/layout_table_section_test.cc
@@ -301,11 +301,8 @@ auto* section = GetSectionByElementId("section"); - // The section's self visual overflow covers the collapsed borders. - LayoutRect expected_self_visual_overflow = section->BorderBoxRect(); - expected_self_visual_overflow.ExpandEdges(LayoutUnit(1), LayoutUnit(8), - LayoutUnit(0), LayoutUnit(0)); - EXPECT_EQ(expected_self_visual_overflow, section->SelfVisualOverflowRect()); + // The section's self visual overflow doesn't cover the collapsed borders. + EXPECT_EQ(section->BorderBoxRect(), section->SelfVisualOverflowRect()); // The section's visual overflow covers self visual overflow and visual // overflows rows.
diff --git a/third_party/blink/renderer/devtools/front_end/audits2_worker/lighthouse/lighthouse-dt-bundle.js b/third_party/blink/renderer/devtools/front_end/audits2_worker/lighthouse/lighthouse-dt-bundle.js index 5c086c44..f48bc4c 100644 --- a/third_party/blink/renderer/devtools/front_end/audits2_worker/lighthouse/lighthouse-dt-bundle.js +++ b/third_party/blink/renderer/devtools/front_end/audits2_worker/lighthouse/lighthouse-dt-bundle.js
@@ -1,4 +1,4 @@ -// lighthouse, browserified. 4.2.0 (9790337f9873710c3fd38bafdec819337c8367be) +// lighthouse, browserified. 4.3.0 (01b217be64ddff7ca500ad0f787f914fa9900b73) require=function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a;}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r);},p,p.exports,r,e,n,t);}return n[i].exports;}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o;}return r;}()({"../audits/accessibility/accesskeys":[function(require,module,exports){ (function(__filename){ @@ -3138,7 +3138,7 @@ title:str_(UIStrings.title), description:str_(UIStrings.description), scoreDisplayMode:ByteEfficiencyAudit.SCORING_MODES.NUMERIC, -requiredArtifacts:['Scripts','devtoolsLogs','traces']}; +requiredArtifacts:['ScriptElements','devtoolsLogs','traces']}; } @@ -3174,10 +3174,11 @@ const items=[]; const warnings=[]; -for(const{requestId,inline,content}of artifacts.Scripts){ +for(const{requestId,src,content}of artifacts.ScriptElements){ if(!content)continue; + const networkRecord=networkRecords.find(record=>record.requestId===requestId); -const displayUrl=inline||!networkRecord? +const displayUrl=!src||!networkRecord? `inline: ${content.substr(0,40)}...`: networkRecord.url; try{ @@ -6031,7 +6032,7 @@ for(const stylesheet of artifacts.CSSUsage.stylesheets){ -const newlinesStripped=stylesheet.content.replace(/\n/g,' '); +const newlinesStripped=stylesheet.content.replace(/(\r|\n)+/g,' '); const fontFaceDeclarations=newlinesStripped.match(/@font-face\s*{(.*?)}/g)||[]; @@ -6566,10 +6567,10 @@ const tasks=await MainThreadTasksComputed.request(trace,context); const results=tasks. -filter(task=>task.duration>5&&task.parent). + +filter(task=>task.duration>5&&!task.parent). map(task=>{ return{ -type:task.group.id, duration:task.duration, startTime:task.startTime}; @@ -6577,7 +6578,6 @@ const headings=[ -{key:'type',itemType:'text',text:'Task Type'}, {key:'startTime',itemType:'ms',granularity:1,text:'Start Time'}, {key:'duration',itemType:'ms',granularity:1,text:'End Time'}]; @@ -7821,6 +7821,11 @@ undefined:(time-earliestStartTime)*1000; const results=records.map(record=>{ +const endTimeDeltaMs=record.lrStatistics&&record.lrStatistics.endTimeDeltaMs; +const TCPMs=record.lrStatistics&&record.lrStatistics.TCPMs; +const requestMs=record.lrStatistics&&record.lrStatistics.requestMs; +const responseMs=record.lrStatistics&&record.lrStatistics.responseMs; + return{ url:URL.elideDataURI(record.url), startTime:timeToMs(record.startTime), @@ -7829,7 +7834,11 @@ resourceSize:record.resourceSize, statusCode:record.statusCode, mimeType:record.mimeType, -resourceType:record.resourceType}; +resourceType:record.resourceType, +lrEndTimeDeltaMs:endTimeDeltaMs, +lrTCPMs:TCPMs, +lrRequestMs:requestMs, +lrResponseMs:responseMs}; }); @@ -12281,7 +12290,8 @@ const seenUrls=new Set(); return networkRecords.reduce((prev,record)=>{ -if(seenUrls.has(record.url)||!record.finished){ + +if(seenUrls.has(record.url)||!record.finished||record.sessionId){ return prev; } @@ -12493,6 +12503,9 @@ const unoptimizedResponses=[]; networkRecords.forEach(record=>{ + +if(record.sessionId)return; + const mimeType=record.mimeType; const resourceType=record.resourceType||NetworkRequest.TYPES.Other; const resourceSize=record.resourceSize; @@ -13483,7 +13496,7 @@ module.exports=RuntimeExceptions; -},{"./gatherer":48}],"../gather/gatherers/scripts":[function(require,module,exports){ +},{"./gatherer":48}],"../gather/gatherers/script-elements":[function(require,module,exports){ @@ -13491,16 +13504,37 @@ 'use strict'; -const log=require('lighthouse-logger'); -const Gatherer=require('./gatherer'); -const NetworkRequest=require('../../lib/network-request'); +const Gatherer=require('./gatherer.js'); +const NetworkAnalyzer=require('../../lib/dependency-graph/simulator/network-analyzer.js'); +const NetworkRequest=require('../../lib/network-request.js'); const getElementsInDocumentString=require('../../lib/page-functions.js').getElementsInDocumentString; -const URL=require('../../lib/url-shim.js'); -class Scripts extends Gatherer{ + +function collectAllScriptElements(){ + + +const scripts=getElementsInDocument('script'); + +return scripts.map(script=>{ +return{ +type:script.type||null, +src:script.src||null, +async:script.async, +defer:script.defer, +source:script.closest('head')?'head':'body', +content:script.src?null:script.text, +requestId:null}; + +}); +} + + + + +class ScriptElements extends Gatherer{ @@ -13508,52 +13542,42 @@ async afterPass(passContext,loadData){ const driver=passContext.driver; +const mainResource=NetworkAnalyzer.findMainDocument(loadData.networkRecords,passContext.url); -const scripts=[]; - - -const inlineScripts=await driver.evaluateAsync(`(() => { - ${getElementsInDocumentString}; - - return getElementsInDocument('script') - .filter(script => !script.src && script.text.trim()) - .map(script => script.text); +const scripts=await driver.evaluateAsync(`(() => { + ${getElementsInDocumentString} + return (${collectAllScriptElements.toString()})(); })()`,{useIsolation:true}); -if(inlineScripts.length){ - - - -const mainResource=loadData.networkRecords.find(request=> -passContext.url.startsWith(request.url)&& -URL.equalWithExcludedFragments(request.url,passContext.url)); -if(!mainResource){ -log.warn('Scripts','could not locate mainResource'); -} -const requestId=mainResource?mainResource.requestId:undefined; -scripts.push( -...inlineScripts.map(content=>{ -return{ -content, -inline:true, -requestId}; - -})); - +for(const script of scripts){ +if(script.content)script.requestId=mainResource.requestId; } const scriptRecords=loadData.networkRecords. + +filter(record=>!record.sessionId). + filter(record=>record.resourceType===NetworkRequest.TYPES.Script); for(const record of scriptRecords){ try{ const content=await driver.getRequestContent(record.requestId); -if(content){ +if(!content)continue; + +const matchedScriptElement=scripts.find(script=>script.src===record.url); +if(matchedScriptElement){ +matchedScriptElement.requestId=record.requestId; +matchedScriptElement.content=content; +}else{ scripts.push({ -content, -inline:false, -requestId:record.requestId}); +type:null, +src:record.url, +async:false, +defer:false, +source:'network', +requestId:record.requestId, +content}); } }catch(e){} @@ -13563,9 +13587,9 @@ }} -module.exports=Scripts; +module.exports=ScriptElements; -},{"../../lib/network-request":71,"../../lib/page-functions.js":72,"../../lib/url-shim.js":"url","./gatherer":48,"lighthouse-logger":120}],"../gather/gatherers/seo/embedded-content":[function(require,module,exports){ +},{"../../lib/dependency-graph/simulator/network-analyzer.js":57,"../../lib/network-request.js":71,"../../lib/page-functions.js":72,"./gatherer.js":48}],"../gather/gatherers/seo/embedded-content":[function(require,module,exports){ @@ -15801,7 +15825,8 @@ -static _createTasksFromEvents(mainThreadEvents,priorTaskData){ + +static _createTasksFromEvents(mainThreadEvents,priorTaskData,traceEndTs){ const tasks=[]; @@ -15833,7 +15858,7 @@ if(!currentTask){ if(event.ph==='E'){ -throw new Error('Fatal trace logic error'); +throw new Error('Fatal trace logic error - unexpected end event'); } currentTask=MainThreadTasks._createNewTaskNode(event); @@ -15849,7 +15874,8 @@ currentTask=newTask; }else{ if(currentTask.event.ph!=='B'){ -throw new Error('Fatal trace logic error'); +throw new Error( +`Fatal trace logic error - expected start event, got ${currentTask.event.ph}`); } @@ -15858,6 +15884,14 @@ } } + +while(currentTask&&!Number.isFinite(currentTask.endTime)){ + +currentTask.endTime=traceEndTs; +currentTask=currentTask.parent; +} + + return tasks; } @@ -15865,9 +15899,14 @@ -static _computeRecursiveSelfTime(task){ + +static _computeRecursiveSelfTime(task,parent){ +if(parent&&task.endTime>parent.endTime){ +throw new Error('Fatal trace logic error - child cannot end after parent'); +} + const childTime=task.children. -map(MainThreadTasks._computeRecursiveSelfTime). +map(child=>MainThreadTasks._computeRecursiveSelfTime(child,task)). reduce((sum,child)=>sum+child,0); task.duration=task.endTime-task.startTime; task.selfTime=task.duration-childTime; @@ -15942,16 +15981,17 @@ -static getMainThreadTasks(traceEvents){ + +static getMainThreadTasks(traceEvents,traceEndTs){ const timers=new Map(); const priorTaskData={timers}; -const tasks=MainThreadTasks._createTasksFromEvents(traceEvents,priorTaskData); +const tasks=MainThreadTasks._createTasksFromEvents(traceEvents,priorTaskData,traceEndTs); for(const task of tasks){ if(task.parent)continue; -MainThreadTasks._computeRecursiveSelfTime(task); +MainThreadTasks._computeRecursiveSelfTime(task,undefined); MainThreadTasks._computeRecursiveAttributableURLs(task,[],priorTaskData); MainThreadTasks._computeRecursiveTaskGroup(task); } @@ -15979,8 +16019,8 @@ static async compute_(trace,context){ -const{mainThreadEvents}=await TraceOfTab.request(trace,context); -return MainThreadTasks.getMainThreadTasks(mainThreadEvents); +const{mainThreadEvents,timestamps}=await TraceOfTab.request(trace,context); +return MainThreadTasks.getMainThreadTasks(mainThreadEvents,timestamps.traceEnd); }} @@ -17742,7 +17782,7 @@ const records=await NetworkRecords.request(devtoolsLog,context); const throughput=NetworkAnalyzer.estimateThroughput(records); const rttAndServerResponseTime=NetworkAnalysis.computeRTTAndServerResponseTime(records); -return{records,throughput,...rttAndServerResponseTime}; +return{throughput,...rttAndServerResponseTime}; }} @@ -17907,9 +17947,9 @@ rootNode.addDependent(node); } -const redirects=Array.from(node.record.redirects||[]); -redirects.push(node.record); +if(!node.record.redirects)return; +const redirects=[...node.record.redirects,node.record]; for(let i=1;i<redirects.length;i++){ const redirectNode=networkNodeOutput.idToNodeMap.get(redirects[i-1].requestId); const actualNode=networkNodeOutput.idToNodeMap.get(redirects[i].requestId); @@ -19944,7 +19984,6 @@ networkQuietThresholdMs:1000, cpuQuietThresholdMs:1000, gatherers:[ -'scripts', 'css-usage', 'viewport-dimensions', 'runtime-exceptions', @@ -19954,6 +19993,7 @@ 'image-elements', 'link-elements', 'meta-elements', +'script-elements', 'dobetterweb/appcache', 'dobetterweb/doctype', 'dobetterweb/domstats', @@ -20972,7 +21012,7 @@ async _handleReceivedMessageFromTarget(event,parentSessionIds){ -const{sessionId,message}=event; +const{targetId,sessionId,message}=event; const protocolMessage=JSON.parse(message); @@ -20994,7 +21034,7 @@ } if(protocolMessage.method.startsWith('Network')){ -this._handleProtocolEvent(protocolMessage); +this._handleProtocolEvent({...protocolMessage,source:{targetId,sessionId}}); } } @@ -23474,40 +23514,43 @@ const rootNode=this.getRootNode(); -let shouldIncludeNode=()=>true; -if(predicate){ -const idsToInclude=new Set(); +const idsToIncludedClones=new Map(); + + rootNode.traverse(node=>{ +if(idsToIncludedClones.has(node.id))return; + +if(predicate===undefined){ + +idsToIncludedClones.set(node.id,node.cloneWithoutRelationships()); +return; +} + if(predicate(node)){ + node.traverse( -node=>idsToInclude.add(node.id), -node=>node._dependencies.filter(parent=>!idsToInclude.has(parent))); +node=>idsToIncludedClones.set(node.id,node.cloneWithoutRelationships()), + +node=>node._dependencies.filter(parent=>!idsToIncludedClones.has(parent.id))); } }); -shouldIncludeNode=node=>idsToInclude.has(node.id); -} - -const idToNodeMap=new Map(); -rootNode.traverse(originalNode=>{ -if(!shouldIncludeNode(originalNode))return; -const clonedNode=originalNode.cloneWithoutRelationships(); -idToNodeMap.set(clonedNode.id,clonedNode); -}); rootNode.traverse(originalNode=>{ -if(!shouldIncludeNode(originalNode))return; -const clonedNode=idToNodeMap.get(originalNode.id); +const clonedNode=idsToIncludedClones.get(originalNode.id); +if(!clonedNode)return; for(const dependency of originalNode._dependencies){ -const clonedDependency=idToNodeMap.get(dependency.id); +const clonedDependency=idsToIncludedClones.get(dependency.id); +if(!clonedDependency)throw new Error('Dependency somehow not cloned'); clonedNode.addDependency(clonedDependency); } }); -if(!idToNodeMap.has(this.id))throw new Error('Cloned graph missing node'); -return idToNodeMap.get(this.id); +const clonedThisNode=idsToIncludedClones.get(this.id); +if(!clonedThisNode)throw new Error('Cloned graph missing node'); +return clonedThisNode; } @@ -23516,45 +23559,34 @@ -_traversePaths(iterator,getNext){ -const stack=[[this]]; -while(stack.length){ -const path=stack.shift(); -const node=path[0]; -iterator(node,path); -const nodesToAdd=getNext(node); -for(const nextNode of nodesToAdd){ -stack.push([nextNode].concat(path)); -} -} + +traverse(callback,getNextNodes){ +if(!getNextNodes){ +getNextNodes=node=>node.getDependents(); } +const queue=[[this]]; +const visited=new Set([this.id]); + +while(queue.length){ +const traversalPath=queue.shift(); +const node=traversalPath[0]; +callback(node,traversalPath); +for(const nextNode of getNextNodes(node)){ +if(visited.has(nextNode.id))continue; +visited.add(nextNode.id); -traverse(iterator,getNext){ -if(!getNext){ -getNext=node=>node.getDependents(); +queue.push([nextNode,...traversalPath]); } - -const visited=new Set(); -const originalGetNext=getNext; - -getNext=node=>{ -visited.add(node.id); -const allNodesToVisit=originalGetNext(node); -const nodesToVisit=allNodesToVisit.filter(nextNode=>!visited.has(nextNode.id)); -nodesToVisit.forEach(nextNode=>visited.add(nextNode.id)); -return nodesToVisit; -}; - -this._traversePaths(iterator,getNext); +} } @@ -23811,19 +23843,7 @@ constructor(records,options){ -this._options=Object.assign( -{ -rtt:undefined, -throughput:undefined, -additionalRttByOrigin:new Map(), -serverResponseTimeByOrigin:new Map()}, - -options); - - -if(!this._options.rtt||!this._options.throughput){ -throw new Error('Cannot create pool with no rtt or throughput'); -} +this._options=options; this._records=records; @@ -23929,14 +23949,10 @@ acquire(record,options={}){ -if(this._connectionsByRecord.has(record)){ +if(this._connectionsByRecord.has(record))throw new Error('Record already has a connection'); -return this._connectionsByRecord.get(record); -} - -const origin=String(record.parsedURL.securityOrigin); +const origin=record.parsedURL.securityOrigin; const observedConnectionWasReused=!!this._connectionReusedByRequestId.get(record.requestId); - const connections=this._connectionsByOrigin.get(origin)||[]; const connectionToUse=this._findAvailableConnectionWithLargestCongestionWindow(connections,{ ignoreConnectionReused:options.ignoreConnectionReused, @@ -23953,6 +23969,20 @@ + + + + +acquireActiveConnectionFromRecord(record){ +const activeConnection=this._connectionsByRecord.get(record); +if(!activeConnection)throw new Error('Could not find an active connection for record'); + +return activeConnection; +} + + + + release(record){ const connection=this._connectionsByRecord.get(record); this._connectionsByRecord.delete(record); @@ -23979,19 +24009,9 @@ -constructor(options){ -this._options=Object.assign( -{ -rtt:undefined}, +constructor({rtt}){ +this._rtt=rtt; -options); - - -if(!this._options.rtt){ -throw new Error('Cannot create DNS cache with no rtt'); -} - -this._rtt=this._options.rtt; this._resolvedDomainNames=new Map(); } @@ -24312,10 +24332,10 @@ static estimateIfConnectionWasReused(records,options){ -options=Object.assign({forceCoarseEstimates:false},options); +const{forceCoarseEstimates=false}=options||{}; -if(!options.forceCoarseEstimates&&NetworkAnalyzer.canTrustConnectionInformation(records)){ +if(!forceCoarseEstimates&&NetworkAnalyzer.canTrustConnectionInformation(records)){ return new Map(records.map(record=>[record.requestId,!!record.connectionReused])); } @@ -24355,48 +24375,42 @@ static estimateRTTByOrigin(records,options){ -options=Object.assign( -{ +const{ +forceCoarseEstimates=false, -forceCoarseEstimates:false, - - -coarseEstimateMultiplier:0.3, - -useDownloadEstimates:true, -useSendStartEstimates:true, -useHeadersEndEstimates:true}, - -options); - +coarseEstimateMultiplier=0.3, +useDownloadEstimates=true, +useSendStartEstimates=true, +useHeadersEndEstimates=true}= +options||{}; let estimatesByOrigin=NetworkAnalyzer._estimateRTTByOriginViaTCPTiming(records); -if(!estimatesByOrigin.size||options.forceCoarseEstimates){ +if(!estimatesByOrigin.size||forceCoarseEstimates){ estimatesByOrigin=new Map(); const estimatesViaDownload=NetworkAnalyzer._estimateRTTByOriginViaDownloadTiming(records); const estimatesViaSendStart=NetworkAnalyzer._estimateRTTByOriginViaSendStartTiming(records); const estimatesViaTTFB=NetworkAnalyzer._estimateRTTByOriginViaHeadersEndTiming(records); for(const[origin,estimates]of estimatesViaDownload.entries()){ -if(!options.useDownloadEstimates)continue; +if(!useDownloadEstimates)continue; estimatesByOrigin.set(origin,estimates); } for(const[origin,estimates]of estimatesViaSendStart.entries()){ -if(!options.useSendStartEstimates)continue; +if(!useSendStartEstimates)continue; const existing=estimatesByOrigin.get(origin)||[]; estimatesByOrigin.set(origin,existing.concat(estimates)); } for(const[origin,estimates]of estimatesViaTTFB.entries()){ -if(!options.useHeadersEndEstimates)continue; +if(!useHeadersEndEstimates)continue; const existing=estimatesByOrigin.get(origin)||[]; estimatesByOrigin.set(origin,existing.concat(estimates)); } for(const estimates of estimatesByOrigin.values()){ -estimates.forEach((x,i)=>estimates[i]=x*options.coarseEstimateMultiplier); +estimates.forEach((x,i)=>estimates[i]=x*coarseEstimateMultiplier); } } @@ -24413,17 +24427,13 @@ static estimateServerResponseTimeByOrigin(records,options){ -options=Object.assign( -{ -rttByOrigin:null}, - -options); - - -let rttByOrigin=options.rttByOrigin; +let rttByOrigin=(options||{}).rttByOrigin; if(!rttByOrigin){ -rttByOrigin=NetworkAnalyzer.estimateRTTByOrigin(records,options); -for(const[origin,summary]of rttByOrigin.entries()){ + +rttByOrigin=new Map(); + +const rttSummaryByOrigin=NetworkAnalyzer.estimateRTTByOrigin(records,options); +for(const[origin,summary]of rttSummaryByOrigin.entries()){ rttByOrigin.set(origin,summary.min); } } @@ -24523,6 +24533,15 @@ + + + + + + + + + },{"../../network-request.js":71,"../../url-shim.js":"url"}],58:[function(require,module,exports){ @@ -24826,8 +24845,7 @@ const sizeInMb=(record.resourceSize||0)/1024/1024; timeElapsed=8+20*sizeInMb-timingData.timeElapsed; }else{ - -const connection=this._acquireConnection(record); +const connection=this._connectionPool.acquireActiveConnectionFromRecord(record); const dnsResolutionTime=this._dns.getTimeUntilResolution(record,{ requestedAt:timingData.startTime, shouldUpdateCache:true}); @@ -24878,8 +24896,7 @@ if(node.type!==BaseNode.TYPES.NETWORK)throw new Error('Unsupported'); const record=node.record; - -const connection=this._acquireConnection(record); +const connection=this._connectionPool.acquireActiveConnectionFromRecord(record); const dnsResolutionTime=this._dns.getTimeUntilResolution(record,{ requestedAt:timingData.startTime, shouldUpdateCache:true}); @@ -28612,8 +28629,9 @@ -onRequestWillBeSent(data){ -const originalRequest=this._findRealRequest(data.requestId); +onRequestWillBeSent(event){ +const data=event.params; +const originalRequest=this._findRealRequestAndSetSource(data.requestId,event.source); if(!originalRequest){ const request=new NetworkRequest(); @@ -28651,8 +28669,9 @@ -onRequestServedFromCache(data){ -const request=this._findRealRequest(data.requestId); +onRequestServedFromCache(event){ +const data=event.params; +const request=this._findRealRequestAndSetSource(data.requestId,event.source); if(!request)return; request.onRequestServedFromCache(); } @@ -28660,8 +28679,9 @@ -onResponseReceived(data){ -const request=this._findRealRequest(data.requestId); +onResponseReceived(event){ +const data=event.params; +const request=this._findRealRequestAndSetSource(data.requestId,event.source); if(!request)return; request.onResponseReceived(data); } @@ -28669,8 +28689,9 @@ -onDataReceived(data){ -const request=this._findRealRequest(data.requestId); +onDataReceived(event){ +const data=event.params; +const request=this._findRealRequestAndSetSource(data.requestId,event.source); if(!request)return; request.onDataReceived(data); } @@ -28678,8 +28699,9 @@ -onLoadingFinished(data){ -const request=this._findRealRequest(data.requestId); +onLoadingFinished(event){ +const data=event.params; +const request=this._findRealRequestAndSetSource(data.requestId,event.source); if(!request)return; request.onLoadingFinished(data); this.onRequestFinished(request); @@ -28688,8 +28710,9 @@ -onLoadingFailed(data){ -const request=this._findRealRequest(data.requestId); +onLoadingFailed(event){ +const data=event.params; +const request=this._findRealRequestAndSetSource(data.requestId,event.source); if(!request)return; request.onLoadingFailed(data); this.onRequestFinished(request); @@ -28698,8 +28721,9 @@ -onResourceChangedPriority(data){ -const request=this._findRealRequest(data.requestId); +onResourceChangedPriority(event){ +const data=event.params; +const request=this._findRealRequestAndSetSource(data.requestId,event.source); if(!request)return; request.onResourceChangedPriority(data); } @@ -28710,13 +28734,13 @@ dispatch(event){ switch(event.method){ -case'Network.requestWillBeSent':return this.onRequestWillBeSent(event.params); -case'Network.requestServedFromCache':return this.onRequestServedFromCache(event.params); -case'Network.responseReceived':return this.onResponseReceived(event.params); -case'Network.dataReceived':return this.onDataReceived(event.params); -case'Network.loadingFinished':return this.onLoadingFinished(event.params); -case'Network.loadingFailed':return this.onLoadingFailed(event.params); -case'Network.resourceChangedPriority':return this.onResourceChangedPriority(event.params); +case'Network.requestWillBeSent':return this.onRequestWillBeSent(event); +case'Network.requestServedFromCache':return this.onRequestServedFromCache(event); +case'Network.responseReceived':return this.onResponseReceived(event); +case'Network.dataReceived':return this.onDataReceived(event); +case'Network.loadingFinished':return this.onLoadingFinished(event); +case'Network.loadingFailed':return this.onLoadingFailed(event); +case'Network.resourceChangedPriority':return this.onResourceChangedPriority(event); default:return;} } @@ -28730,7 +28754,8 @@ -_findRealRequest(requestId){ + +_findRealRequestAndSetSource(requestId,source){ let request=this._recordsById.get(requestId); if(!request||!request.isValid)return undefined; @@ -28738,6 +28763,7 @@ request=request.redirectDestination; } +request.setSource(source); return request; } @@ -28815,6 +28841,27 @@ +const HEADER_TCP='X-TCPMs'; +const HEADER_SSL='X-SSLMs'; +const HEADER_REQ='X-RequestMs'; +const HEADER_RES='X-ResponseMs'; +const HEADER_TOTAL='X-TotalMs'; +const HEADER_FETCHED_SIZE='X-TotalFetchedSize'; + + + + + + + + + + + + + + + @@ -28846,7 +28893,7 @@ CSPViolationReport:'CSPViolationReport'}; -module.exports=class NetworkRequest{ +class NetworkRequest{ constructor(){ this.requestId=''; this.connectionId='0'; @@ -28871,6 +28918,9 @@ this.fromDiskCache=false; this.fromMemoryCache=false; + +this.lrStatistics=undefined; + this.finished=false; this.requestMethod=''; this.statusCode=-1; @@ -28901,6 +28951,18 @@ this.fetchedViaServiceWorker=false; this.frameId=''; + + + + + +this.targetId=undefined; + + + + + +this.sessionId=undefined; this.isLinkPreload=false; } @@ -28991,6 +29053,7 @@ this._updateResponseReceivedTimeIfNecessary(); this._updateTransferSizeForLightrider(); +this._updateTimingsForLightrider(); } @@ -29009,6 +29072,7 @@ this._updateResponseReceivedTimeIfNecessary(); this._updateTransferSizeForLightrider(); +this._updateTimingsForLightrider(); } @@ -29034,6 +29098,19 @@ +setSource(source){ +if(source){ +this.targetId=source.targetId; +this.sessionId=source.sessionId; +}else{ +this.targetId=undefined; +this.sessionId=undefined; +} +} + + + + _onResponse(response,timestamp,resourceType){ @@ -29082,6 +29159,8 @@ this.responseReceivedTime=Math.min(this.responseReceivedTime,headersReceivedTime); this.responseReceivedTime=Math.max(this.responseReceivedTime,this.startTime); + + this.endTime=Math.max(this.endTime,this.responseReceivedTime); } @@ -29114,10 +29193,71 @@ if(!global.isLightrider)return; -const totalFetchedSize=this.responseHeaders.find(item=>item.name==='X-TotalFetchedSize'); +const totalFetchedSize=this.responseHeaders.find(item=>item.name===HEADER_FETCHED_SIZE); if(!totalFetchedSize)return; -this.transferSize=parseFloat(totalFetchedSize.value); +const floatValue=parseFloat(totalFetchedSize.value); + +if(isNaN(floatValue))return; +this.transferSize=floatValue; +} + + + + + +_updateTimingsForLightrider(){ + +if(!global.isLightrider)return; + + + + + + + + + + + + + + + + + +const totalHeader=this.responseHeaders.find(item=>item.name===HEADER_TOTAL); + +if(!totalHeader)return; + +const totalMs=parseInt(totalHeader.value); +const TCPMsHeader=this.responseHeaders.find(item=>item.name===HEADER_TCP); +const SSLMsHeader=this.responseHeaders.find(item=>item.name===HEADER_SSL); +const requestMsHeader=this.responseHeaders.find(item=>item.name===HEADER_REQ); +const responseMsHeader=this.responseHeaders.find(item=>item.name===HEADER_RES); + + +const TCPMs=TCPMsHeader?Math.max(0,parseInt(TCPMsHeader.value)):0; +const SSLMs=SSLMsHeader?Math.max(0,parseInt(SSLMsHeader.value)):0; +const requestMs=requestMsHeader?Math.max(0,parseInt(requestMsHeader.value)):0; +const responseMs=responseMsHeader?Math.max(0,parseInt(responseMsHeader.value)):0; + + +if(TCPMs+requestMs+responseMs!==totalMs){ +return; +} + + +if(SSLMs>TCPMs){ +return; +} + +this.lrStatistics={ +endTimeDeltaMs:(this.endTime-(this.startTime+totalMs/1000))*1000, +TCPMs:TCPMs, +requestMs:requestMs, +responseMs:responseMs}; + } @@ -29149,9 +29289,18 @@ static get TYPES(){ return RESOURCE_TYPES; -}}; +}} +NetworkRequest.HEADER_TCP=HEADER_TCP; +NetworkRequest.HEADER_SSL=HEADER_SSL; +NetworkRequest.HEADER_REQ=HEADER_REQ; +NetworkRequest.HEADER_RES=HEADER_RES; +NetworkRequest.HEADER_TOTAL=HEADER_TOTAL; +NetworkRequest.HEADER_FETCHED_SIZE=HEADER_FETCHED_SIZE; + +module.exports=NetworkRequest; + }).call(this,typeof global!=="undefined"?global:typeof self!=="undefined"?self:typeof window!=="undefined"?window:{}); },{"./url-shim":"url"}],72:[function(require,module,exports){ @@ -31370,7 +31519,16 @@ ...timingEntriesFromRunner]. map(entry=>[entry.startTime,entry]); -const timingEntries=Array.from(new Map(timingEntriesKeyValues).values()); +const timingEntries=Array.from(new Map(timingEntriesKeyValues).values()). + + +map(entry=>{ +return{ +...entry, +duration:parseFloat(entry.duration.toFixed(2)), +startTime:parseFloat(entry.startTime.toFixed(2))}; + +}); const runnerEntry=timingEntries.find(e=>e.name==='lh:runner:run'); return{entries:timingEntries,total:runnerEntry&&runnerEntry.duration||0}; } @@ -31578,7 +31736,7 @@ static getGathererList(){ const fileList=[ -...["accessibility.js","anchor-elements.js","cache-contents.js","chrome-console-messages.js","css-usage.js","dobetterweb","gatherer.js","html-without-javascript.js","http-redirect.js","image-elements.js","js-usage.js","link-elements.js","meta-elements.js","mixed-content.js","offline.js","runtime-exceptions.js","scripts.js","seo","service-worker.js","start-url.js","viewport-dimensions.js"], +...["accessibility.js","anchor-elements.js","cache-contents.js","chrome-console-messages.js","css-usage.js","dobetterweb","gatherer.js","html-without-javascript.js","http-redirect.js","image-elements.js","js-usage.js","link-elements.js","meta-elements.js","mixed-content.js","offline.js","runtime-exceptions.js","script-elements.js","seo","service-worker.js","start-url.js","viewport-dimensions.js"], ...["embedded-content.js","font-size.js","robots-txt.js","tap-targets.js"].map(f=>`seo/${f}`), ...["appcache.js","doctype.js","domstats.js","js-libraries.js","optimized-images.js","password-inputs-with-prevented-paste.js","response-compression.js","tags-blocking-first-paint.js"]. map(f=>`dobetterweb/${f}`)]; @@ -62174,7 +62332,7 @@ arguments[4][87][0].apply(exports,arguments); },{"./support/isBuffer":165,"_process":137,"dup":87,"inherits":105}],167:[function(require,module,exports){ module.exports={ -"version":"4.2.0"}; +"version":"4.3.0"}; },{}],168:[function(require,module,exports){ module.exports={ @@ -62236,10 +62394,11 @@ {"id":"npm:highcharts:20180225","severity":"high","semver":{"vulnerable":["<6.1.0"]}}], "jquery":[ +{"id":"SNYK-JS-JQUERY-174006","severity":"medium","semver":{"vulnerable":["*"]}}, {"id":"npm:jquery:20160529","severity":"low","semver":{"vulnerable":["=3.0.0-rc1"]}}, {"id":"npm:jquery:20150627","severity":"medium","semver":{"vulnerable":["<1.12.2",">=1.12.3 <2.2.2",">=2.2.3 <3.0.0"]}}, {"id":"npm:jquery:20140902","severity":"medium","semver":{"vulnerable":[">=1.4.2 <1.6.2"]}}, -{"id":"npm:jquery:20120206","severity":"medium","semver":{"vulnerable":["<1.9.0 >=1.7.1"]}}, +{"id":"npm:jquery:20120206","severity":"medium","semver":{"vulnerable":[">=1.7.1 <1.9.0"]}}, {"id":"npm:jquery:20110606","severity":"medium","semver":{"vulnerable":["<1.6.3"]}}], "jquery-mobile":[
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc index 1f8b70a..5603092d 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -42,6 +42,7 @@ #include "third_party/blink/renderer/core/frame/local_frame_view.h" #include "third_party/blink/renderer/core/frame/settings.h" #include "third_party/blink/renderer/core/html/forms/html_input_element.h" +#include "third_party/blink/renderer/core/html/forms/html_select_element.h" #include "third_party/blink/renderer/core/html/html_dialog_element.h" #include "third_party/blink/renderer/core/html/html_frame_owner_element.h" #include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h" @@ -3087,8 +3088,11 @@ case ax::mojom::Role::kComboBoxGrouping: case ax::mojom::Role::kComboBoxMenuButton: case ax::mojom::Role::kListBox: - case ax::mojom::Role::kPopUpButton: return recursive; + // This can be either a button widget with a non-false value of + // aria-haspopup or a select element with size of 1. + case ax::mojom::Role::kPopUpButton: + return ToHTMLSelectElementOrNull(*GetNode()) ? recursive : false; default: return false; }
diff --git a/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module.idl b/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module.idl index 8aa25fc..fa8072f 100644 --- a/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module.idl +++ b/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module.idl
@@ -8,7 +8,8 @@ WebGLRenderingContext or WebGL2RenderingContext or ImageBitmapRenderingContext or - XRPresentationContext) RenderingContext; + XRPresentationContext or + GPUCanvasContext) RenderingContext; [ ImplementedAs=HTMLCanvasElementModule
diff --git a/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module_support_webgl2_compute.idl b/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module_support_webgl2_compute.idl index aee0f57f..6f930b1 100644 --- a/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module_support_webgl2_compute.idl +++ b/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module_support_webgl2_compute.idl
@@ -9,7 +9,8 @@ WebGL2RenderingContext or WebGL2ComputeRenderingContext or ImageBitmapRenderingContext or - XRPresentationContext) RenderingContext; + XRPresentationContext or + GPUCanvasContext) RenderingContext; [ ImplementedAs=HTMLCanvasElementModule
diff --git a/third_party/blink/renderer/modules/gamepad/gamepad.cc b/third_party/blink/renderer/modules/gamepad/gamepad.cc index dc4b9ee..e8c5d87 100644 --- a/third_party/blink/renderer/modules/gamepad/gamepad.cc +++ b/third_party/blink/renderer/modules/gamepad/gamepad.cc
@@ -31,9 +31,9 @@ namespace blink { -Gamepad::Gamepad(NavigatorGamepad* navigator_gamepad) +Gamepad::Gamepad(NavigatorGamepad* navigator_gamepad, unsigned index) : navigator_gamepad_(navigator_gamepad), - index_(0), + index_(index), timestamp_(0.0), has_vibration_actuator_(false), vibration_actuator_type_(device::GamepadHapticActuatorType::kDualRumble),
diff --git a/third_party/blink/renderer/modules/gamepad/gamepad.h b/third_party/blink/renderer/modules/gamepad/gamepad.h index 5a7ee0f6..d98a65a 100644 --- a/third_party/blink/renderer/modules/gamepad/gamepad.h +++ b/third_party/blink/renderer/modules/gamepad/gamepad.h
@@ -45,7 +45,7 @@ DEFINE_WRAPPERTYPEINFO(); public: - explicit Gamepad(NavigatorGamepad* navigator_gamepad); + explicit Gamepad(NavigatorGamepad* navigator_gamepad, unsigned index); ~Gamepad() override; typedef Vector<double> DoubleVector; @@ -54,7 +54,6 @@ void SetId(const String& id) { id_ = id; } unsigned index() const { return index_; } - void SetIndex(unsigned val) { index_ = val; } bool connected() const { return connected_; } void SetConnected(bool val) { connected_ = val; } @@ -99,7 +98,7 @@ String id_; // The index of this gamepad within the GamepadList. - unsigned index_; + const unsigned index_; // True if this gamepad was still connected when gamepad state was captured. bool connected_;
diff --git a/third_party/blink/renderer/modules/gamepad/gamepad_button.cc b/third_party/blink/renderer/modules/gamepad/gamepad_button.cc index 4d9a2b5..0e45883 100644 --- a/third_party/blink/renderer/modules/gamepad/gamepad_button.cc +++ b/third_party/blink/renderer/modules/gamepad/gamepad_button.cc
@@ -4,6 +4,8 @@ #include "third_party/blink/renderer/modules/gamepad/gamepad.h" +#include "device/gamepad/public/cpp/gamepad.h" + namespace blink { GamepadButton::GamepadButton() : value_(0.), pressed_(false), touched_(false) {}
diff --git a/third_party/blink/renderer/modules/gamepad/gamepad_button.h b/third_party/blink/renderer/modules/gamepad/gamepad_button.h index 35099bcb..f53621c 100644 --- a/third_party/blink/renderer/modules/gamepad/gamepad_button.h +++ b/third_party/blink/renderer/modules/gamepad/gamepad_button.h
@@ -5,10 +5,13 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_GAMEPAD_GAMEPAD_BUTTON_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_GAMEPAD_GAMEPAD_BUTTON_H_ -#include "device/gamepad/public/cpp/gamepad.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" -#include "third_party/blink/renderer/platform/heap/handle.h" -#include "third_party/blink/renderer/platform/wtf/vector.h" +#include "third_party/blink/renderer/platform/heap/heap_allocator.h" +#include "third_party/blink/renderer/platform/heap/member.h" + +namespace device { +class GamepadButton; +} namespace blink {
diff --git a/third_party/blink/renderer/modules/gamepad/gamepad_comparisons_test.cc b/third_party/blink/renderer/modules/gamepad/gamepad_comparisons_test.cc index 96877dea..b747f1d 100644 --- a/third_party/blink/renderer/modules/gamepad/gamepad_comparisons_test.cc +++ b/third_party/blink/renderer/modules/gamepad/gamepad_comparisons_test.cc
@@ -53,9 +53,8 @@ device::GamepadButton buttons[1] = {{false, false, 0.0}}; device::GamepadPose null_pose; auto* list = MakeGarbageCollected<GamepadList>(); - auto* gamepad = MakeGarbageCollected<Gamepad>(nullptr); + auto* gamepad = MakeGarbageCollected<Gamepad>(nullptr, 0); gamepad->SetId("gamepad"); - gamepad->SetIndex(0); gamepad->SetAxes(1, axes); gamepad->SetButtons(1, buttons); gamepad->SetConnected(true); @@ -69,9 +68,8 @@ device::GamepadButton buttons[1] = {{false, false, 0.0}}; auto* list = MakeGarbageCollected<GamepadList>(); - auto* gamepad = MakeGarbageCollected<Gamepad>(nullptr); + auto* gamepad = MakeGarbageCollected<Gamepad>(nullptr, 0); gamepad->SetId("gamepad"); - gamepad->SetIndex(0); gamepad->SetAxes(1, axes); gamepad->SetButtons(1, buttons); gamepad->SetConnected(true); @@ -84,9 +82,8 @@ device::GamepadButton buttons[1] = {{true, true, 1.0}}; auto* list = MakeGarbageCollected<GamepadList>(); - auto* gamepad = MakeGarbageCollected<Gamepad>(nullptr); + auto* gamepad = MakeGarbageCollected<Gamepad>(nullptr, 0); gamepad->SetId("gamepad"); - gamepad->SetIndex(0); gamepad->SetAxes(1, axes); gamepad->SetButtons(1, buttons); gamepad->SetConnected(true); @@ -104,9 +101,8 @@ }}; auto* list = MakeGarbageCollected<GamepadList>(); - auto* gamepad = MakeGarbageCollected<Gamepad>(nullptr); + auto* gamepad = MakeGarbageCollected<Gamepad>(nullptr, 0); gamepad->SetId("gamepad"); - gamepad->SetIndex(0); gamepad->SetAxes(1, axes); gamepad->SetButtons(1, buttons); gamepad->SetConnected(true); @@ -124,9 +120,8 @@ }}; auto* list = MakeGarbageCollected<GamepadList>(); - auto* gamepad = MakeGarbageCollected<Gamepad>(nullptr); + auto* gamepad = MakeGarbageCollected<Gamepad>(nullptr, 0); gamepad->SetId("gamepad"); - gamepad->SetIndex(0); gamepad->SetAxes(1, axes); gamepad->SetButtons(1, buttons); gamepad->SetConnected(true); @@ -140,9 +135,8 @@ device::GamepadPose pose; InitGamepadPose(pose); auto* list = MakeGarbageCollected<GamepadList>(); - auto* gamepad = MakeGarbageCollected<Gamepad>(nullptr); + auto* gamepad = MakeGarbageCollected<Gamepad>(nullptr, 0); gamepad->SetId("gamepad"); - gamepad->SetIndex(0); gamepad->SetAxes(1, axes); gamepad->SetButtons(1, buttons); gamepad->SetConnected(true); @@ -159,9 +153,8 @@ // Modify the linear velocity. pose.linear_velocity.x = 100.f; auto* list = MakeGarbageCollected<GamepadList>(); - auto* gamepad = MakeGarbageCollected<Gamepad>(nullptr); + auto* gamepad = MakeGarbageCollected<Gamepad>(nullptr, 0); gamepad->SetId("gamepad"); - gamepad->SetIndex(0); gamepad->SetAxes(1, axes); gamepad->SetButtons(1, buttons); gamepad->SetConnected(true);
diff --git a/third_party/blink/renderer/modules/gamepad/gamepad_dispatcher.cc b/third_party/blink/renderer/modules/gamepad/gamepad_dispatcher.cc index b8f5c6e..b02f10ae 100644 --- a/third_party/blink/renderer/modules/gamepad/gamepad_dispatcher.cc +++ b/third_party/blink/renderer/modules/gamepad/gamepad_dispatcher.cc
@@ -4,6 +4,7 @@ #include "third_party/blink/renderer/modules/gamepad/gamepad_dispatcher.h" +#include "device/gamepad/public/cpp/gamepads.h" #include "third_party/blink/public/platform/interface_provider.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/renderer/modules/gamepad/gamepad_shared_memory_reader.h"
diff --git a/third_party/blink/renderer/modules/gamepad/gamepad_dispatcher.h b/third_party/blink/renderer/modules/gamepad/gamepad_dispatcher.h index 2fe8e15..6cdbd1e 100644 --- a/third_party/blink/renderer/modules/gamepad/gamepad_dispatcher.h +++ b/third_party/blink/renderer/modules/gamepad/gamepad_dispatcher.h
@@ -5,11 +5,17 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_GAMEPAD_GAMEPAD_DISPATCHER_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_GAMEPAD_GAMEPAD_DISPATCHER_H_ -#include "device/gamepad/public/cpp/gamepads.h" +#include <memory> + +#include "base/memory/scoped_refptr.h" #include "device/gamepad/public/mojom/gamepad.mojom-blink.h" #include "third_party/blink/public/platform/web_gamepad_listener.h" #include "third_party/blink/renderer/core/frame/platform_event_dispatcher.h" -#include "third_party/blink/renderer/platform/heap/handle.h" + +namespace device { +class Gamepad; +class Gamepads; +} // namespace device namespace blink {
diff --git a/third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.cc b/third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.cc index d7a955a..aaac240 100644 --- a/third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.cc +++ b/third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.cc
@@ -5,9 +5,13 @@ #include "third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.h" #include "base/bind_helpers.h" +#include "device/gamepad/public/cpp/gamepad.h" +#include "third_party/blink/renderer/bindings/core/v8/script_promise.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" #include "third_party/blink/renderer/modules/gamepad/gamepad_dispatcher.h" +#include "third_party/blink/renderer/modules/gamepad/gamepad_effect_parameters.h" #include "third_party/blink/renderer/platform/wtf/functional.h" +#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" namespace {
diff --git a/third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.h b/third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.h index 32d5b42..0a15ef4 100644 --- a/third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.h +++ b/third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.h
@@ -5,19 +5,20 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_GAMEPAD_GAMEPAD_HAPTIC_ACTUATOR_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_GAMEPAD_GAMEPAD_HAPTIC_ACTUATOR_H_ -#include "device/gamepad/public/cpp/gamepad.h" #include "device/gamepad/public/mojom/gamepad.mojom-blink.h" -#include "third_party/blink/renderer/bindings/core/v8/script_promise.h" -#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" -#include "third_party/blink/renderer/modules/gamepad/gamepad_effect_parameters.h" +#include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" -#include "third_party/blink/renderer/platform/heap/handle.h" +#include "third_party/blink/renderer/platform/heap/member.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" -#include "third_party/blink/renderer/platform/wtf/vector.h" namespace blink { class GamepadDispatcher; +class GamepadEffectParameters; +enum class GamepadHapticActuatorType; +class ScriptState; +class ScriptPromise; +class ScriptPromiseResolver; class GamepadHapticActuator final : public ScriptWrappable, public ContextClient {
diff --git a/third_party/blink/renderer/modules/gamepad/gamepad_pose.cc b/third_party/blink/renderer/modules/gamepad/gamepad_pose.cc index b44ffe9..6fce407 100644 --- a/third_party/blink/renderer/modules/gamepad/gamepad_pose.cc +++ b/third_party/blink/renderer/modules/gamepad/gamepad_pose.cc
@@ -4,6 +4,8 @@ #include "third_party/blink/renderer/modules/gamepad/gamepad_pose.h" +#include "device/gamepad/public/cpp/gamepad.h" + namespace blink { namespace {
diff --git a/third_party/blink/renderer/modules/gamepad/gamepad_pose.h b/third_party/blink/renderer/modules/gamepad/gamepad_pose.h index 0b4b2ef22..d7580717 100644 --- a/third_party/blink/renderer/modules/gamepad/gamepad_pose.h +++ b/third_party/blink/renderer/modules/gamepad/gamepad_pose.h
@@ -5,11 +5,13 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_GAMEPAD_GAMEPAD_POSE_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_GAMEPAD_GAMEPAD_POSE_H_ -#include "device/gamepad/public/cpp/gamepad.h" #include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" -#include "third_party/blink/renderer/platform/heap/handle.h" -#include "third_party/blink/renderer/platform/wtf/forward.h" +#include "third_party/blink/renderer/platform/heap/member.h" + +namespace device { +class GamepadPose; +} namespace blink {
diff --git a/third_party/blink/renderer/modules/gamepad/gamepad_shared_memory_reader.cc b/third_party/blink/renderer/modules/gamepad/gamepad_shared_memory_reader.cc index b659128c9..2a595cd1 100644 --- a/third_party/blink/renderer/modules/gamepad/gamepad_shared_memory_reader.cc +++ b/third_party/blink/renderer/modules/gamepad/gamepad_shared_memory_reader.cc
@@ -3,9 +3,13 @@ // found in the LICENSE file. #include "third_party/blink/renderer/modules/gamepad/gamepad_shared_memory_reader.h" + #include "base/metrics/histogram_macros.h" +#include "device/gamepad/public/cpp/gamepads.h" +#include "device/gamepad/public/mojom/gamepad_hardware_buffer.h" #include "services/service_manager/public/cpp/interface_provider.h" #include "third_party/blink/public/platform/interface_provider.h" +#include "third_party/blink/public/platform/web_gamepad_listener.h" #include "third_party/blink/renderer/core/frame/local_frame.h" namespace blink {
diff --git a/third_party/blink/renderer/modules/gamepad/gamepad_shared_memory_reader.h b/third_party/blink/renderer/modules/gamepad/gamepad_shared_memory_reader.h index 091f5ff..abfb0d7 100644 --- a/third_party/blink/renderer/modules/gamepad/gamepad_shared_memory_reader.h +++ b/third_party/blink/renderer/modules/gamepad/gamepad_shared_memory_reader.h
@@ -8,17 +8,24 @@ #include <memory> #include "base/macros.h" -#include "device/base/synchronization/shared_memory_seqlock_buffer.h" -#include "device/gamepad/public/cpp/gamepads.h" #include "device/gamepad/public/mojom/gamepad.mojom-blink.h" #include "device/gamepad/public/mojom/gamepad_hardware_buffer.h" #include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/system/buffer.h" -#include "third_party/blink/public/platform/web_gamepad_listener.h" + +namespace base { +class ReadOnlySharedMemoryRegion; +} + +namespace device { +class Gamepad; +class Gamepads; +} // namespace device namespace blink { class LocalFrame; +class WebGamepadListener; class GamepadSharedMemoryReader : public device::mojom::blink::GamepadObserver { public:
diff --git a/third_party/blink/renderer/modules/gamepad/navigator_gamepad.cc b/third_party/blink/renderer/modules/gamepad/navigator_gamepad.cc index 16db3e3..2b825836 100644 --- a/third_party/blink/renderer/modules/gamepad/navigator_gamepad.cc +++ b/third_party/blink/renderer/modules/gamepad/navigator_gamepad.cc
@@ -36,11 +36,13 @@ #include "third_party/blink/renderer/core/origin_trials/origin_trials.h" #include "third_party/blink/renderer/core/page/page.h" #include "third_party/blink/renderer/core/timing/performance.h" +#include "third_party/blink/renderer/modules/gamepad/gamepad.h" #include "third_party/blink/renderer/modules/gamepad/gamepad_comparisons.h" #include "third_party/blink/renderer/modules/gamepad/gamepad_dispatcher.h" #include "third_party/blink/renderer/modules/gamepad/gamepad_event.h" #include "third_party/blink/renderer/modules/gamepad/gamepad_list.h" #include "third_party/blink/renderer/modules/vr/navigator_vr.h" +#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h" #include "third_party/blink/renderer/platform/wtf/text/string_view.h" namespace blink { @@ -132,8 +134,8 @@ } else if (device_gamepad.connected) { Gamepad* gamepad = gamepads_back_->item(i); if (!gamepad) - gamepad = MakeGarbageCollected<Gamepad>(this); - SampleGamepad(i, *gamepad, device_gamepad); + gamepad = MakeGarbageCollected<Gamepad>(this, i); + SampleGamepad(device_gamepad, *gamepad); gamepads_back_->Set(i, gamepad); } else { gamepads_back_->Set(i, nullptr); @@ -141,9 +143,8 @@ } } -void NavigatorGamepad::SampleGamepad(uint32_t index, - Gamepad& gamepad, - const device::Gamepad& device_gamepad) { +void NavigatorGamepad::SampleGamepad(const device::Gamepad& device_gamepad, + Gamepad& gamepad) { bool newly_connected; GamepadComparisons::HasGamepadConnectionChanged( gamepad.connected(), // Old connected. @@ -182,7 +183,6 @@ // gamepad is newly connected. if (newly_connected) { gamepad.SetId(device_gamepad.id); - gamepad.SetIndex(index); gamepad.SetMapping(device_gamepad.mapping); if (device_gamepad.is_xr && device_gamepad.display_id) {
diff --git a/third_party/blink/renderer/modules/gamepad/navigator_gamepad.h b/third_party/blink/renderer/modules/gamepad/navigator_gamepad.h index 385dcde..6422223 100644 --- a/third_party/blink/renderer/modules/gamepad/navigator_gamepad.h +++ b/third_party/blink/renderer/modules/gamepad/navigator_gamepad.h
@@ -31,14 +31,19 @@ #include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/navigator.h" #include "third_party/blink/renderer/core/frame/platform_event_controller.h" -#include "third_party/blink/renderer/modules/gamepad/gamepad.h" #include "third_party/blink/renderer/modules/modules_export.h" -#include "third_party/blink/renderer/platform/heap/handle.h" +#include "third_party/blink/renderer/platform/heap/member.h" #include "third_party/blink/renderer/platform/supplementable.h" +#include "third_party/blink/renderer/platform/wtf/forward.h" + +namespace device { +class Gamepad; +} namespace blink { class Document; +class Gamepad; class GamepadDispatcher; class GamepadHapticActuator; class GamepadList; @@ -70,9 +75,7 @@ private: void SampleGamepads(); - void SampleGamepad(uint32_t index, - Gamepad& gamepad, - const device::Gamepad& device_gamepad); + void SampleGamepad(const device::Gamepad& device_gamepad, Gamepad& gamepad); void DidRemoveGamepadEventListeners(); bool StartUpdatingIfAttached();
diff --git a/third_party/blink/renderer/modules/modules_initializer.cc b/third_party/blink/renderer/modules/modules_initializer.cc index 362c72f..6df2d5ceb 100644 --- a/third_party/blink/renderer/modules/modules_initializer.cc +++ b/third_party/blink/renderer/modules/modules_initializer.cc
@@ -87,6 +87,7 @@ #include "third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.h" #include "third_party/blink/renderer/modules/webgl/webgl2_rendering_context.h" #include "third_party/blink/renderer/modules/webgl/webgl_rendering_context.h" +#include "third_party/blink/renderer/modules/webgpu/gpu_canvas_context.h" #include "third_party/blink/renderer/modules/xr/xr_presentation_context.h" #include "third_party/blink/renderer/platform/cross_thread_functional.h" #include "third_party/blink/renderer/platform/mojo/mojo_helper.h" @@ -140,6 +141,8 @@ std::make_unique<ImageBitmapRenderingContext::Factory>()); HTMLCanvasElement::RegisterRenderingContextFactory( std::make_unique<XRPresentationContext::Factory>()); + HTMLCanvasElement::RegisterRenderingContextFactory( + std::make_unique<GPUCanvasContext::Factory>()); // OffscreenCanvas context types must be registered with the OffscreenCanvas. OffscreenCanvas::RegisterRenderingContextFactory(
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.cc b/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.cc index f1c82d15b..c9fa73f4 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.cc +++ b/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.cc
@@ -4,4 +4,37 @@ #include "third_party/blink/renderer/modules/webgpu/gpu_canvas_context.h" -namespace blink {} // namespace blink +#include "third_party/blink/renderer/bindings/modules/v8/rendering_context.h" + +namespace blink { + +GPUCanvasContext::Factory::Factory() {} +GPUCanvasContext::Factory::~Factory() {} + +CanvasRenderingContext* GPUCanvasContext::Factory::Create( + CanvasRenderingContextHost* host, + const CanvasContextCreationAttributesCore& attrs) { + return MakeGarbageCollected<GPUCanvasContext>(host, attrs); +} + +CanvasRenderingContext::ContextType GPUCanvasContext::Factory::GetContextType() + const { + return CanvasRenderingContext::kContextGPUPresent; +} + +GPUCanvasContext::GPUCanvasContext( + CanvasRenderingContextHost* host, + const CanvasContextCreationAttributesCore& attrs) + : CanvasRenderingContext(host, attrs) {} + +GPUCanvasContext::~GPUCanvasContext() {} + +CanvasRenderingContext::ContextType GPUCanvasContext::GetContextType() const { + return CanvasRenderingContext::kContextGPUPresent; +} + +void GPUCanvasContext::SetCanvasGetContextResult(RenderingContext& result) { + result.SetGPUCanvasContext(this); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.h b/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.h index 3f1a42e9..aa4b69d 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.h +++ b/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.h
@@ -5,14 +5,55 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_CANVAS_CONTEXT_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_CANVAS_CONTEXT_H_ +#include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h" +#include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context_factory.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" +#include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h" namespace blink { -class GPUCanvasContext : public ScriptWrappable { +// A GPUCanvasContext does little by itself and basically just binds a canvas +// and a GPUSwapChain together and forwards calls from one to the other. The +// logic that are in other CanvasRenderingContext is in GPUSwapChain instead. +class GPUCanvasContext : public CanvasRenderingContext { DEFINE_WRAPPERTYPEINFO(); public: + class Factory : public CanvasRenderingContextFactory { + DISALLOW_COPY_AND_ASSIGN(Factory); + + public: + Factory(); + ~Factory() override; + + CanvasRenderingContext* Create( + CanvasRenderingContextHost*, + const CanvasContextCreationAttributesCore&) override; + CanvasRenderingContext::ContextType GetContextType() const override; + }; + + GPUCanvasContext(CanvasRenderingContextHost*, + const CanvasContextCreationAttributesCore&); + ~GPUCanvasContext() override; + + // CanvasRenderingContext implementation + ContextType GetContextType() const override; + void SetCanvasGetContextResult(RenderingContext&) final; + scoped_refptr<StaticBitmapImage> GetImage(AccelerationHint) const final { + return nullptr; + } + void SetIsHidden(bool) override {} + bool isContextLost() const override { return false; } + bool IsComposited() const final { return true; } + bool IsAccelerated() const final { return true; } + bool IsOriginTopLeft() const final { return true; } + bool Is3d() const final { return true; } + void SetFilterQuality(SkFilterQuality) final {} + bool IsPaintable() const final { return true; } + int ExternallyAllocatedBufferCountPerPixel() final { return 1; } + void Stop() override {} + cc::Layer* CcLayer() const final { return nullptr; } + // gpu_canvas_context.idl // TODO(crbug.com/877147): implement GPUCanvasContext. @@ -20,6 +61,14 @@ DISALLOW_COPY_AND_ASSIGN(GPUCanvasContext); }; +DEFINE_TYPE_CASTS(GPUCanvasContext, + CanvasRenderingContext, + context, + context->GetContextType() == + CanvasRenderingContext::kContextGPUPresent, + context.GetContextType() == + CanvasRenderingContext::kContextGPUPresent); + } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_CANVAS_CONTEXT_H_
diff --git a/third_party/blink/renderer/modules/xr/xr_webgl_layer.cc b/third_party/blink/renderer/modules/xr/xr_webgl_layer.cc index 8bfcba0..4cde7cd6 100644 --- a/third_party/blink/renderer/modules/xr/xr_webgl_layer.cc +++ b/third_party/blink/renderer/modules/xr/xr_webgl_layer.cc
@@ -227,12 +227,10 @@ // When mirroring make sure to also update the mirrored canvas UVs so it // only shows a single eye's data, cropped to display proportionally. if (session()->outputContext()) { - float left = 0; - float top = 0; - float right = static_cast<float>(left_viewport_->width()) / - static_cast<float>(framebuffer_width); - float bottom = static_cast<float>(left_viewport_->height()) / - static_cast<float>(framebuffer_height); + float source_pixels_left = left_viewport_->x(); + float source_pixels_right = left_viewport_->x() + left_viewport_->width(); + float source_pixels_bottom = left_viewport_->y(); + float source_pixels_top = left_viewport_->y() + left_viewport_->height(); // Adjust the UVs so that the mirrored content always fills the canvas // and is centered while staying proportional. @@ -242,23 +240,32 @@ static_cast<float>(left_viewport_->height()); if (output_aspect > viewport_aspect) { - float viewport_scale = bottom; - output_aspect = viewport_aspect / output_aspect; - top = 0.5 - (output_aspect * 0.5); - bottom = top + output_aspect; - top *= viewport_scale; - bottom *= viewport_scale; + // Output is wider than rendered image, scale to height and chop off top + // and bottom. + float cropped_image_height = left_viewport_->width() / output_aspect; + float crop_amount = (left_viewport_->height() - cropped_image_height); + source_pixels_top -= crop_amount / 2; + source_pixels_bottom += crop_amount / 2; + } else { - float viewport_scale = right; - output_aspect = output_aspect / viewport_aspect; - left = 0.5 - (output_aspect * 0.5); - right = left + output_aspect; - left *= viewport_scale; - right *= viewport_scale; + // Output is taller relatively than rendered image, scale to width and + // chop of left and right. + float cropped_image_width = left_viewport_->height() * output_aspect; + float crop_amount = (left_viewport_->width() - cropped_image_width); + source_pixels_left += crop_amount / 2; + source_pixels_right -= crop_amount / 2; } - session()->outputContext()->SetUV(FloatPoint(left, top), - FloatPoint(right, bottom)); + float uv_left = source_pixels_left / framebuffer_width; + float uv_right = source_pixels_right / framebuffer_width; + float uv_top = source_pixels_top / framebuffer_height; + float uv_bottom = source_pixels_bottom / framebuffer_height; + + // Finally, in UV space (0, 0) is top-left corner, so we need to flip. + uv_top = 1 - uv_top; + uv_bottom = 1 - uv_bottom; + session()->outputContext()->SetUV(FloatPoint(uv_left, uv_top), + FloatPoint(uv_right, uv_bottom)); } } else { left_viewport_ = MakeGarbageCollected<XRViewport>(
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc index bd96d88..2805c25 100644 --- a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc +++ b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
@@ -1036,6 +1036,8 @@ blink_effects[effect.id] && blink_effects[effect.id]->HasActiveOpacityAnimation()) return true; + if (effect.is_fast_rounded_corner) + return true; return false; }
diff --git a/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc b/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc index 8d9a9f5..818c388 100644 --- a/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc +++ b/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc
@@ -504,6 +504,9 @@ } void PropertyTreeManager::EmitClipMaskLayer() { + if (RuntimeEnabledFeatures::FastBorderRadiusEnabled()) + return; + cc::EffectNode& mask_isolation = *GetEffectTree().Node(current_.effect_id); if (pending_synthetic_mask_layers_.Contains(mask_isolation.id)) return; @@ -755,8 +758,15 @@ const auto& transform = pending_clip.clip->LocalTransformSpace(); synthetic_effect.transform_id = EnsureCompositorTransformNode(transform); synthetic_effect.double_sided = !transform.IsBackfaceHidden(); - synthetic_effect.has_render_surface = true; - pending_synthetic_mask_layers_.insert(synthetic_effect.id); + + if (RuntimeEnabledFeatures::FastBorderRadiusEnabled()) { + synthetic_effect.rounded_corner_bounds = + gfx::RRectF(pending_clip.clip->ClipRect()); + synthetic_effect.is_fast_rounded_corner = true; + } else { + synthetic_effect.has_render_surface = true; + pending_synthetic_mask_layers_.insert(synthetic_effect.id); + } // Clip and kDstIn do not commute. This shall never be reached because // kDstIn is only used internally to implement CSS clip-path and mask,
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 1880fa5..b8a2018 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -525,6 +525,9 @@ name: "FallbackCursorMode", }, { + name: "FastBorderRadius", + }, + { name: "FastFlatTreeTraversal", status: "stable", },
diff --git a/third_party/blink/renderer/platform/transforms/transformation_matrix.cc b/third_party/blink/renderer/platform/transforms/transformation_matrix.cc index 1bea01b..ea51d53 100644 --- a/third_party/blink/renderer/platform/transforms/transformation_matrix.cc +++ b/third_party/blink/renderer/platform/transforms/transformation_matrix.cc
@@ -2080,26 +2080,11 @@ SkMatrix44 TransformationMatrix::ToSkMatrix44( const TransformationMatrix& matrix) { - // TODO(masonfreed): Replace this with an explicit 16-element constructor - // on SkMatrix44, once that's available. This code does a *lot* of extra - // work, because each call to setDouble re-calculates the matrix type. - SkMatrix44 ret(SkMatrix44::kIdentity_Constructor); - ret.setDouble(0, 0, matrix.M11()); - ret.setDouble(0, 1, matrix.M21()); - ret.setDouble(0, 2, matrix.M31()); - ret.setDouble(0, 3, matrix.M41()); - ret.setDouble(1, 0, matrix.M12()); - ret.setDouble(1, 1, matrix.M22()); - ret.setDouble(1, 2, matrix.M32()); - ret.setDouble(1, 3, matrix.M42()); - ret.setDouble(2, 0, matrix.M13()); - ret.setDouble(2, 1, matrix.M23()); - ret.setDouble(2, 2, matrix.M33()); - ret.setDouble(2, 3, matrix.M43()); - ret.setDouble(3, 0, matrix.M14()); - ret.setDouble(3, 1, matrix.M24()); - ret.setDouble(3, 2, matrix.M34()); - ret.setDouble(3, 3, matrix.M44()); + SkMatrix44 ret(SkMatrix44::kUninitialized_Constructor); + ret.set4x4(matrix.M11(), matrix.M12(), matrix.M13(), matrix.M14(), + matrix.M21(), matrix.M22(), matrix.M23(), matrix.M24(), + matrix.M31(), matrix.M32(), matrix.M33(), matrix.M34(), + matrix.M41(), matrix.M42(), matrix.M43(), matrix.M44()); return ret; }
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-unsafe-webgpu b/third_party/blink/web_tests/FlagExpectations/enable-unsafe-webgpu index 85b70dd..55a55dd0 100644 --- a/third_party/blink/web_tests/FlagExpectations/enable-unsafe-webgpu +++ b/third_party/blink/web_tests/FlagExpectations/enable-unsafe-webgpu
@@ -1,2 +1,3 @@ # WebGPU tests are only run with --enable-unsafe-webgpu +Bug(none) webgpu/canvas_context.html [ Pass ] Bug(none) webgpu/fence.html [ Pass ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 09b6e08..888a01d 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -12,6 +12,7 @@ Bug(intentional) external/wpt/infrastructure/expected-fail/timeout.html [ Timeout ] # WebGPU tests are only run with --enable-unsafe-webgpu +Bug(none) webgpu/canvas_context.html [ Skip ] Bug(none) webgpu/fence.html [ Skip ] crbug.com/807686 crbug.com/24182 jquery/manipulation.html [ Timeout Pass ] @@ -92,6 +93,7 @@ crbug.com/678482 virtual/nobinary-for-devtools/http/tests/devtools/debugger/fetch-breakpoints.js [ Timeout Pass ] crbug.com/678491 http/tests/misc/webtiming-no-origin.html [ Crash Pass ] crbug.com/765779 http/tests/loading/bad-server-subframe.html [ Failure ] +crbug.com/793127 external/wpt/content-security-policy/securitypolicyviolation/upgrade-insecure-requests-reporting.https.html [ Crash ] crbug.com/793127 http/tests/security/upgrade-insecure-requests/iframe-upgrade.https.html [ Crash ] crbug.com/793127 virtual/outofblink-cors/http/tests/security/upgrade-insecure-requests/iframe-upgrade.https.html [ Crash ] crbug.com/801992 http/tests/misc/iframe-script-modify-attr.html [ Pass Crash ]
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/table/invisible-col-visible-td-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/table/invisible-col-visible-td-expected.txt index f7877fc..4bd25cb 100644 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/table/invisible-col-visible-td-expected.txt +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/table/invisible-col-visible-td-expected.txt
@@ -8,7 +8,7 @@ "paintInvalidations": [ { "object": "LayoutTableSection TBODY", - "rect": [8, 8, 200, 200], + "rect": [9, 9, 198, 198], "reason": "style change" } ]
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/table/invisible-tbody-visible-td-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/table/invisible-tbody-visible-td-expected.txt index 4ee94a75..1db1e66 100644 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/table/invisible-tbody-visible-td-expected.txt +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/table/invisible-tbody-visible-td-expected.txt
@@ -8,7 +8,7 @@ "paintInvalidations": [ { "object": "LayoutTableSection TBODY id='tbody'", - "rect": [8, 8, 200, 200], + "rect": [9, 9, 198, 198], "reason": "background" } ]
diff --git a/third_party/blink/web_tests/http/tests/devtools/audits2/audits2-successful-run-expected.txt b/third_party/blink/web_tests/http/tests/devtools/audits2/audits2-successful-run-expected.txt index f293516..184a3e8 100644 --- a/third_party/blink/web_tests/http/tests/devtools/audits2/audits2-successful-run-expected.txt +++ b/third_party/blink/web_tests/http/tests/devtools/audits2/audits2-successful-run-expected.txt
@@ -22,7 +22,6 @@ Benchmarking machine Initializing… Running beforePass methods -Retrieving setup: Scripts Retrieving setup: CSSUsage Retrieving setup: ViewportDimensions Retrieving setup: RuntimeExceptions @@ -32,6 +31,7 @@ Retrieving setup: ImageElements Retrieving setup: LinkElements Retrieving setup: MetaElements +Retrieving setup: ScriptElements Retrieving setup: AppCacheManifest Retrieving setup: Doctype Retrieving setup: DOMStats @@ -41,15 +41,12 @@ Retrieving setup: ResponseCompression Retrieving setup: TagsBlockingFirstPaint Retrieving setup: FontSize -Retrieving setup: Hreflang Retrieving setup: EmbeddedContent -Retrieving setup: Canonical Retrieving setup: RobotsTxt Retrieving setup: TapTargets Loading page & waiting for onload Getting browser version Running pass methods -Retrieving in-page: Scripts Retrieving in-page: CSSUsage Retrieving in-page: ViewportDimensions Retrieving in-page: RuntimeExceptions @@ -59,6 +56,7 @@ Retrieving in-page: ImageElements Retrieving in-page: LinkElements Retrieving in-page: MetaElements +Retrieving in-page: ScriptElements Retrieving in-page: AppCacheManifest Retrieving in-page: Doctype Retrieving in-page: DOMStats @@ -68,15 +66,12 @@ Retrieving in-page: ResponseCompression Retrieving in-page: TagsBlockingFirstPaint Retrieving in-page: FontSize -Retrieving in-page: Hreflang Retrieving in-page: EmbeddedContent -Retrieving in-page: Canonical Retrieving in-page: RobotsTxt Retrieving in-page: TapTargets Retrieving trace Retrieving devtoolsLog & network records Running afterPass methods -Retrieving: Scripts Retrieving: CSSUsage Retrieving: ViewportDimensions Retrieving: RuntimeExceptions @@ -86,6 +81,7 @@ Retrieving: ImageElements Retrieving: LinkElements Retrieving: MetaElements +Retrieving: ScriptElements Retrieving: AppCacheManifest Retrieving: Doctype Retrieving: DOMStats @@ -95,9 +91,7 @@ Retrieving: ResponseCompression Retrieving: TagsBlockingFirstPaint Retrieving: FontSize -Retrieving: Hreflang Retrieving: EmbeddedContent -Retrieving: Canonical Retrieving: RobotsTxt Retrieving: TapTargets Resetting state with about:blank @@ -277,7 +271,7 @@ =============== Lighthouse Results =============== URL: http://127.0.0.1:8000/devtools/resources/inspected-page.html -Version: 4.2.0 +Version: 4.3.0 accesskeys: notApplicable
diff --git a/third_party/blink/web_tests/inspector-protocol/dom/dom-getContentQuads-before-element-expected.txt b/third_party/blink/web_tests/inspector-protocol/dom/dom-getContentQuads-before-element-expected.txt new file mode 100644 index 0000000..e8b0a05 --- /dev/null +++ b/third_party/blink/web_tests/inspector-protocol/dom/dom-getContentQuads-before-element-expected.txt
@@ -0,0 +1,4 @@ +Tests DOM.getContentQuads method with single before element. +Returned quads amount: 1 +window.CLICKED = 42 +
diff --git a/third_party/blink/web_tests/inspector-protocol/dom/dom-getContentQuads-before-element.js b/third_party/blink/web_tests/inspector-protocol/dom/dom-getContentQuads-before-element.js new file mode 100644 index 0000000..ca1fc46a --- /dev/null +++ b/third_party/blink/web_tests/inspector-protocol/dom/dom-getContentQuads-before-element.js
@@ -0,0 +1,48 @@ +(async function(testRunner) { + const {page, session, dp} = await testRunner.startHTML(` + <style> + span::before { + content: '\e003'; + } + </style> + <span onclick='javascript:window.CLICKED = 42;'></span> + `, 'Tests DOM.getContentQuads method with single before element.'); + + const document = (await dp.DOM.getDocument()).result.root; + const node = (await dp.DOM.querySelector({nodeId: document.nodeId, selector: 'span'})).result; + const quads = (await dp.DOM.getContentQuads({nodeId: node.nodeId})).result.quads; + testRunner.log('Returned quads amount: ' + quads.length); + const center = middlePoint(quads[0]); + await dp.Input.dispatchMouseEvent({ + type: 'mousePressed', + button: 'left', + buttons: 1, + clickCount: 1, + x: center.x, + y: center.y, + }); + await dp.Input.dispatchMouseEvent({ + type: 'mouseReleased', + button: 'left', + buttons: 1, + clickCount: 1, + x: center.x, + y: center.y, + }); + testRunner.log('window.CLICKED = ' + (await session.evaluate(`window.CLICKED`))); + + testRunner.completeTest(); + + function middlePoint(quad) { + let x = 0, y = 0; + for (let i = 0; i < 8; i += 2) { + x += quad[i]; + y += quad[i + 1]; + } + return { + x: Math.round(x / 4), + y: Math.round(y / 4) + }; + } +}) +
diff --git a/third_party/blink/web_tests/paint/invalidation/table/invisible-col-visible-td-expected.txt b/third_party/blink/web_tests/paint/invalidation/table/invisible-col-visible-td-expected.txt index cd3d1ca..0f96792 100644 --- a/third_party/blink/web_tests/paint/invalidation/table/invisible-col-visible-td-expected.txt +++ b/third_party/blink/web_tests/paint/invalidation/table/invisible-col-visible-td-expected.txt
@@ -19,7 +19,7 @@ "paintInvalidations": [ { "object": "LayoutTableSection TBODY", - "rect": [8, 8, 200, 200], + "rect": [9, 9, 198, 198], "reason": "style change" } ]
diff --git a/third_party/blink/web_tests/paint/invalidation/table/invisible-tbody-visible-td-expected.txt b/third_party/blink/web_tests/paint/invalidation/table/invisible-tbody-visible-td-expected.txt index ebdbe091..537612d 100644 --- a/third_party/blink/web_tests/paint/invalidation/table/invisible-tbody-visible-td-expected.txt +++ b/third_party/blink/web_tests/paint/invalidation/table/invisible-tbody-visible-td-expected.txt
@@ -19,7 +19,7 @@ "paintInvalidations": [ { "object": "LayoutTableSection TBODY id='tbody'", - "rect": [8, 8, 200, 200], + "rect": [9, 9, 198, 198], "reason": "background" } ]
diff --git a/third_party/blink/web_tests/webgpu/canvas_context.html b/third_party/blink/web_tests/webgpu/canvas_context.html new file mode 100644 index 0000000..7075ea1 --- /dev/null +++ b/third_party/blink/web_tests/webgpu/canvas_context.html
@@ -0,0 +1,17 @@ +<!DOCTYPE html> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<script> +let width = 10; +let height = 10; + +test(function() { + let canvas = document.createElement("canvas"); + canvas.width = width; + canvas.height = height; + + let ctx = canvas.getContext('gpupresent'); + assert_true(ctx instanceof GPUCanvasContext); +}, "Test that canvas.getContext('gpupresent') returns an instance of GPUCanvasContext"); + +</script>
diff --git a/third_party/leveldatabase/README.chromium b/third_party/leveldatabase/README.chromium index c948db4..4355952 100644 --- a/third_party/leveldatabase/README.chromium +++ b/third_party/leveldatabase/README.chromium
@@ -1,7 +1,7 @@ Name: LevelDB: A Fast Persistent Key-Value Store Short Name: leveldb URL: https://github.com/google/leveldb.git -Version: 1.20.git.7035af5fc36657447054617759854a726d31dbe0 +Version: 1.21.git.ffabb1ae86cc4eb4516a7c0824c878c3b2d19e5d License: New BSD License File: src/LICENSE Security Critical: yes
diff --git a/third_party/sqlite/amalgamation/sqlite3.c b/third_party/sqlite/amalgamation/sqlite3.c index a1529a6f..a33c21a 100644 --- a/third_party/sqlite/amalgamation/sqlite3.c +++ b/third_party/sqlite/amalgamation/sqlite3.c
@@ -69202,7 +69202,7 @@ MemPage *pPage1 = pBt->pPage1; /* Local reference to page 1 */ MemPage *pPage; /* Page being freed. May be NULL. */ int rc; /* Return Code */ - int nFree; /* Initial number of pages on free-list */ + u32 nFree; /* Initial number of pages on free-list */ assert( sqlite3_mutex_held(pBt->mutex) ); assert( CORRUPT_DB || iPage>1 ); @@ -118449,6 +118449,9 @@ if( pSrcIdx==0 ){ return 0; /* pDestIdx has no corresponding index in pSrc */ } + if( pSrcIdx->tnum==pDestIdx->tnum && pSrc->pSchema==pDest->pSchema ){ + return 0; /* Corrupt schema - two indexes on the same btree */ + } } #ifndef SQLITE_OMIT_CHECK if( pDest->pCheck && sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1) ){ @@ -221431,7 +221434,7 @@ #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */ /************** End of stmt.c ************************************************/ -#if __LINE__!=221434 +#if __LINE__!=221437 #undef SQLITE_SOURCE_ID #define SQLITE_SOURCE_ID "2019-02-25 16:06:06 bd49a8271d650fa89e446b42e513b595a717b9212c91dd384aab871fc1d0alt2" #endif
diff --git a/third_party/sqlite/patched/src/btree.c b/third_party/sqlite/patched/src/btree.c index c528bb1..269cd419 100644 --- a/third_party/sqlite/patched/src/btree.c +++ b/third_party/sqlite/patched/src/btree.c
@@ -6142,7 +6142,7 @@ MemPage *pPage1 = pBt->pPage1; /* Local reference to page 1 */ MemPage *pPage; /* Page being freed. May be NULL. */ int rc; /* Return Code */ - int nFree; /* Initial number of pages on free-list */ + u32 nFree; /* Initial number of pages on free-list */ assert( sqlite3_mutex_held(pBt->mutex) ); assert( CORRUPT_DB || iPage>1 );
diff --git a/third_party/sqlite/patched/src/insert.c b/third_party/sqlite/patched/src/insert.c index 624ce298..e0007af 100644 --- a/third_party/sqlite/patched/src/insert.c +++ b/third_party/sqlite/patched/src/insert.c
@@ -2273,6 +2273,9 @@ if( pSrcIdx==0 ){ return 0; /* pDestIdx has no corresponding index in pSrc */ } + if( pSrcIdx->tnum==pDestIdx->tnum && pSrc->pSchema==pDest->pSchema ){ + return 0; /* Corrupt schema - two indexes on the same btree */ + } } #ifndef SQLITE_OMIT_CHECK if( pDest->pCheck && sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1) ){
diff --git a/third_party/sqlite/patches/0001-Virtual-table-supporting-recovery-of-corrupted-datab.patch b/third_party/sqlite/patches/0001-Virtual-table-supporting-recovery-of-corrupted-datab.patch index c5c57d4..087fc90 100644 --- a/third_party/sqlite/patches/0001-Virtual-table-supporting-recovery-of-corrupted-datab.patch +++ b/third_party/sqlite/patches/0001-Virtual-table-supporting-recovery-of-corrupted-datab.patch
@@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Scott Hess <shess@chromium.org> Date: Sat, 20 Jul 2013 11:42:21 -0700 -Subject: [PATCH 01/11] Virtual table supporting recovery of corrupted +Subject: [PATCH 01/13] Virtual table supporting recovery of corrupted databases. "recover" implements a virtual table which uses the SQLite pager layer @@ -3901,5 +3901,5 @@ + +finish_test -- -2.20.1 +2.21.0.392.gf8f6787159e-goog
diff --git a/third_party/sqlite/patches/0002-Custom-shell.c-helpers-to-load-Chromium-s-ICU-data.patch b/third_party/sqlite/patches/0002-Custom-shell.c-helpers-to-load-Chromium-s-ICU-data.patch index 38b19e1..f62a60c 100644 --- a/third_party/sqlite/patches/0002-Custom-shell.c-helpers-to-load-Chromium-s-ICU-data.patch +++ b/third_party/sqlite/patches/0002-Custom-shell.c-helpers-to-load-Chromium-s-ICU-data.patch
@@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: "tc@google.com" <tc@google.com> Date: Tue, 6 Jan 2009 22:39:41 +0000 -Subject: [PATCH 02/11] Custom shell.c helpers to load Chromium's ICU data. +Subject: [PATCH 02/13] Custom shell.c helpers to load Chromium's ICU data. History uses fts3 with an icu-based segmenter. These changes allow building a sqlite3 binary for Linux or Windows which can read those files. @@ -141,5 +141,5 @@ + return 1; +} -- -2.20.1 +2.21.0.392.gf8f6787159e-goog
diff --git a/third_party/sqlite/patches/0003-Fix-compilation-with-SQLITE_OMIT_WINDOWFUNC.patch b/third_party/sqlite/patches/0003-Fix-compilation-with-SQLITE_OMIT_WINDOWFUNC.patch index 6cd9acc..8253553 100644 --- a/third_party/sqlite/patches/0003-Fix-compilation-with-SQLITE_OMIT_WINDOWFUNC.patch +++ b/third_party/sqlite/patches/0003-Fix-compilation-with-SQLITE_OMIT_WINDOWFUNC.patch
@@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Victor Costan <pwnall@chromium.org> Date: Sun, 10 Feb 2019 13:12:57 -0800 -Subject: [PATCH 03/11] Fix compilation with SQLITE_OMIT_WINDOWFUNC. +Subject: [PATCH 03/13] Fix compilation with SQLITE_OMIT_WINDOWFUNC. --- third_party/sqlite/patched/src/resolve.c | 2 ++ @@ -28,5 +28,5 @@ /* If this is part of a compound SELECT, check that it has the right ** number of expressions in the select list. */ -- -2.20.1 +2.21.0.392.gf8f6787159e-goog
diff --git a/third_party/sqlite/patches/0004-Fix-dbfuzz2.c-compilation-errors-on-Windows.patch b/third_party/sqlite/patches/0004-Fix-dbfuzz2.c-compilation-errors-on-Windows.patch index d2ee401..274d62e 100644 --- a/third_party/sqlite/patches/0004-Fix-dbfuzz2.c-compilation-errors-on-Windows.patch +++ b/third_party/sqlite/patches/0004-Fix-dbfuzz2.c-compilation-errors-on-Windows.patch
@@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Victor Costan <pwnall@chromium.org> Date: Sun, 10 Feb 2019 15:18:43 -0800 -Subject: [PATCH 04/11] Fix dbfuzz2.c compilation errors on Windows. +Subject: [PATCH 04/13] Fix dbfuzz2.c compilation errors on Windows. --- third_party/sqlite/patched/test/dbfuzz2.c | 4 ++++ @@ -39,5 +39,5 @@ argv[j++] = argv[i]; } -- -2.20.1 +2.21.0.392.gf8f6787159e-goog
diff --git a/third_party/sqlite/patches/0005-Fix-Heap-buffer-overflow-in-vdbeRecordCompareInt.patch b/third_party/sqlite/patches/0005-Fix-Heap-buffer-overflow-in-vdbeRecordCompareInt.patch index f10b0df..4de7809 100644 --- a/third_party/sqlite/patches/0005-Fix-Heap-buffer-overflow-in-vdbeRecordCompareInt.patch +++ b/third_party/sqlite/patches/0005-Fix-Heap-buffer-overflow-in-vdbeRecordCompareInt.patch
@@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Darwin Huang <huangdarwin@chromium.org> Date: Tue, 5 Mar 2019 13:49:51 -0800 -Subject: [PATCH 05/11] Fix Heap-buffer-overflow in vdbeRecordCompareInt +Subject: [PATCH 05/13] Fix Heap-buffer-overflow in vdbeRecordCompareInt This backports https://www.sqlite.org/src/info/c1ac00706bae45fe @@ -24,5 +24,5 @@ } assert( -- -2.20.1 +2.21.0.392.gf8f6787159e-goog
diff --git a/third_party/sqlite/patches/0006-fix-heap-buffer-overflow-in-cellsizeptr.patch b/third_party/sqlite/patches/0006-fix-heap-buffer-overflow-in-cellsizeptr.patch index b265b86..bf065ee 100644 --- a/third_party/sqlite/patches/0006-fix-heap-buffer-overflow-in-cellsizeptr.patch +++ b/third_party/sqlite/patches/0006-fix-heap-buffer-overflow-in-cellsizeptr.patch
@@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Darwin Huang <huangdarwin@chromium.org> Date: Tue, 5 Mar 2019 14:13:19 -0800 -Subject: [PATCH 06/11] fix heap-buffer-overflow in cellsizeptr +Subject: [PATCH 06/13] fix heap-buffer-overflow in cellsizeptr This backports https://www.sqlite.org/src/info/e7aca0714bc475e0 @@ -32,5 +32,5 @@ if( rc==SQLITE_OK ){ -- -2.20.1 +2.21.0.392.gf8f6787159e-goog
diff --git a/third_party/sqlite/patches/0007-fix-integer-overflow-in-checkList.patch b/third_party/sqlite/patches/0007-fix-integer-overflow-in-checkList.patch index 2c67373..bf12915 100644 --- a/third_party/sqlite/patches/0007-fix-integer-overflow-in-checkList.patch +++ b/third_party/sqlite/patches/0007-fix-integer-overflow-in-checkList.patch
@@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Darwin Huang <huangdarwin@chromium.org> Date: Tue, 5 Mar 2019 14:17:05 -0800 -Subject: [PATCH 07/11] fix integer overflow in checkList +Subject: [PATCH 07/13] fix integer overflow in checkList This backports https://www.sqlite.org/src/info/05b87e0755638d31 @@ -37,5 +37,5 @@ assert( pc + info.nSize - 4 <= usableSize ); nPage = (info.nPayload - info.nLocal + usableSize - 5)/(usableSize - 4); -- -2.20.1 +2.21.0.392.gf8f6787159e-goog
diff --git a/third_party/sqlite/patches/0008-Fix-Heap-use-after-free-in-releasePageNotNull.patch b/third_party/sqlite/patches/0008-Fix-Heap-use-after-free-in-releasePageNotNull.patch index cce0e58..f06de28 100644 --- a/third_party/sqlite/patches/0008-Fix-Heap-use-after-free-in-releasePageNotNull.patch +++ b/third_party/sqlite/patches/0008-Fix-Heap-use-after-free-in-releasePageNotNull.patch
@@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Darwin Huang <huangdarwin@chromium.org> Date: Tue, 12 Mar 2019 17:30:33 -0700 -Subject: [PATCH 08/11] Fix Heap-use-after-free in releasePageNotNull +Subject: [PATCH 08/13] Fix Heap-use-after-free in releasePageNotNull This backports https://www.sqlite.org/src/info/b0d5cf40bba34e45 @@ -29,5 +29,5 @@ if( pPager->tempFile ){ /* Do not discard pages from an in-memory database since we might -- -2.20.1 +2.21.0.392.gf8f6787159e-goog
diff --git a/third_party/sqlite/patches/0009-Fix-dangling-pointer-dereference.patch b/third_party/sqlite/patches/0009-Fix-dangling-pointer-dereference.patch index d9b34b8..cc5d07a 100644 --- a/third_party/sqlite/patches/0009-Fix-dangling-pointer-dereference.patch +++ b/third_party/sqlite/patches/0009-Fix-dangling-pointer-dereference.patch
@@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Darwin Huang <huangdarwin@chromium.org> Date: Thu, 21 Mar 2019 13:19:11 -0700 -Subject: [PATCH 09/11] Fix dangling pointer dereference +Subject: [PATCH 09/13] Fix dangling pointer dereference This backports https://www.sqlite.org/src/info/b9e2393cf201e3fc @@ -62,5 +62,5 @@ finish_test -- -2.20.1 +2.21.0.392.gf8f6787159e-goog
diff --git a/third_party/sqlite/patches/0010-Fix-faulty-assert-statement.patch b/third_party/sqlite/patches/0010-Fix-faulty-assert-statement.patch index a0c2235..bbfe184 100644 --- a/third_party/sqlite/patches/0010-Fix-faulty-assert-statement.patch +++ b/third_party/sqlite/patches/0010-Fix-faulty-assert-statement.patch
@@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Darwin Huang <huangdarwin@chromium.org> Date: Wed, 27 Mar 2019 12:05:31 -0700 -Subject: [PATCH 10/11] Fix faulty assert statement +Subject: [PATCH 10/13] Fix faulty assert statement This backports https://www.sqlite.org/src/info/bcbe7d96df3c9515 @@ -25,5 +25,5 @@ ); copyNodeContent(apNew[0], pParent, &rc); -- -2.20.1 +2.21.0.392.gf8f6787159e-goog
diff --git a/third_party/sqlite/patches/0011-Add-dbfuzz2-progress-handler-patch.patch b/third_party/sqlite/patches/0011-Add-dbfuzz2-progress-handler-patch.patch index 32fb274..02f8b620 100644 --- a/third_party/sqlite/patches/0011-Add-dbfuzz2-progress-handler-patch.patch +++ b/third_party/sqlite/patches/0011-Add-dbfuzz2-progress-handler-patch.patch
@@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Darwin Huang <huangdarwin@chromium.org> Date: Wed, 27 Mar 2019 12:10:17 -0700 -Subject: [PATCH 11/11] Add dbfuzz2 progress handler patch +Subject: [PATCH 11/13] Add dbfuzz2 progress handler patch This backports https://www.sqlite.org/src/info/b99f8512c06b9d47 @@ -80,5 +80,5 @@ sqlite3MemTraceActivate(stdout); continue; -- -2.20.1 +2.21.0.392.gf8f6787159e-goog
diff --git a/third_party/sqlite/patches/0012-Use-fixed-width-integer-type.patch b/third_party/sqlite/patches/0012-Use-fixed-width-integer-type.patch new file mode 100644 index 0000000..9b6c97e0 --- /dev/null +++ b/third_party/sqlite/patches/0012-Use-fixed-width-integer-type.patch
@@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Darwin Huang <huangdarwin@chromium.org> +Date: Fri, 12 Apr 2019 18:07:16 -0700 +Subject: [PATCH 12/13] Use fixed-width integer type + +This backports https://www.sqlite.org/src/info/8820408597341344 + +Bug: 950296 +--- + third_party/sqlite/patched/src/btree.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/third_party/sqlite/patched/src/btree.c b/third_party/sqlite/patched/src/btree.c +index c528bb1815fd..269cd4198d36 100644 +--- a/third_party/sqlite/patched/src/btree.c ++++ b/third_party/sqlite/patched/src/btree.c +@@ -6142,7 +6142,7 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){ + MemPage *pPage1 = pBt->pPage1; /* Local reference to page 1 */ + MemPage *pPage; /* Page being freed. May be NULL. */ + int rc; /* Return Code */ +- int nFree; /* Initial number of pages on free-list */ ++ u32 nFree; /* Initial number of pages on free-list */ + + assert( sqlite3_mutex_held(pBt->mutex) ); + assert( CORRUPT_DB || iPage>1 ); +-- +2.21.0.392.gf8f6787159e-goog +
diff --git a/third_party/sqlite/patches/0013-Do-early-detection-for-corrupt-schema.patch b/third_party/sqlite/patches/0013-Do-early-detection-for-corrupt-schema.patch new file mode 100644 index 0000000..dc03fc4 --- /dev/null +++ b/third_party/sqlite/patches/0013-Do-early-detection-for-corrupt-schema.patch
@@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Darwin Huang <huangdarwin@chromium.org> +Date: Fri, 12 Apr 2019 18:09:06 -0700 +Subject: [PATCH 13/13] Do early detection for corrupt schema + +This backports https://www.sqlite.org/src/info/af1e5873d44d3146 + +Bug: 949453 +--- + third_party/sqlite/patched/src/insert.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/third_party/sqlite/patched/src/insert.c b/third_party/sqlite/patched/src/insert.c +index 624ce29870f3..e0007afa15d7 100644 +--- a/third_party/sqlite/patched/src/insert.c ++++ b/third_party/sqlite/patched/src/insert.c +@@ -2273,6 +2273,9 @@ static int xferOptimization( + if( pSrcIdx==0 ){ + return 0; /* pDestIdx has no corresponding index in pSrc */ + } ++ if( pSrcIdx->tnum==pDestIdx->tnum && pSrc->pSchema==pDest->pSchema ){ ++ return 0; /* Corrupt schema - two indexes on the same btree */ ++ } + } + #ifndef SQLITE_OMIT_CHECK + if( pDest->pCheck && sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1) ){ +-- +2.21.0.392.gf8f6787159e-goog +
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 2df779b..fd78724 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -11879,7 +11879,7 @@ </histogram> <histogram name="Blink.Fonts.WindowsUniqueLocalFontInstantiationResult" - enum="WindowsUniqueLocalFontInstantiationResult" expires_after="M75"> + enum="WindowsUniqueLocalFontInstantiationResult" expires_after="M78"> <owner>drott@chromium.org</owner> <summary> Tracks whether a locally uniquely matched font can be instantiated inside @@ -102681,6 +102681,20 @@ </histogram> <histogram + name="ResourceScheduler.NonDelayableLastEndToNonDelayableStart.NonDelayableNotInFlight" + units="ms" expires_after="M77"> + <owner>tbansal@chromium.org</owner> + <owner>dougarnett@chromium.org</owner> + <summary> + The duration of time between the end of a non-delayable resource request to + the start of the next non-delayable resource request. Recorded at the start + of all non-delayable requests that are preceeded by at least one completed + non-delayable request in the same resource scheduler client. Recorded only + when a non-delayable request is NOT in-flight. + </summary> +</histogram> + +<histogram name="ResourceScheduler.NonDelayableLastStartOrEndToNonDelayableStart" units="ms" expires_after="M77"> <owner>tbansal@chromium.org</owner> @@ -102707,6 +102721,20 @@ </histogram> <histogram + name="ResourceScheduler.NonDelayableLastStartToNonDelayableStart.NonDelayableInFlight" + units="ms" expires_after="M77"> + <owner>tbansal@chromium.org</owner> + <owner>dougarnett@chromium.org</owner> + <summary> + The duration of time between the start of a non-delayable resource request + to the start of the next non-delayable resource request. Recorded at the + start of all non-delayable requests that are preceeded by at least one + started non-delayable request in the same resource scheduler client. + Recorded only when a delayable request is in-flight. + </summary> +</histogram> + +<histogram name="ResourceScheduler.NumDelayableRequestsInFlightAtStart.NonDelayable" units="requests"> <owner>tbansal@chromium.org</owner>
diff --git a/ui/accessibility/platform/atk_util_auralinux.cc b/ui/accessibility/platform/atk_util_auralinux.cc index 945bc2c..bc83396 100644 --- a/ui/accessibility/platform/atk_util_auralinux.cc +++ b/ui/accessibility/platform/atk_util_auralinux.cc
@@ -4,6 +4,8 @@ #include <atk/atk.h> #include <map> +#include <memory> +#include <string> #include <utility> #include "base/environment.h" @@ -45,13 +47,11 @@ typedef struct _AtkUtilAuraLinux AtkUtilAuraLinux; typedef struct _AtkUtilAuraLinuxClass AtkUtilAuraLinuxClass; -struct _AtkUtilAuraLinux -{ +struct _AtkUtilAuraLinux { AtkUtil parent; }; -struct _AtkUtilAuraLinuxClass -{ +struct _AtkUtilAuraLinuxClass { AtkUtilClass parent_class; }; @@ -99,7 +99,7 @@ } static void atk_util_auralinux_class_init(AtkUtilAuraLinuxClass *klass) { - AtkUtilClass *atk_class; + AtkUtilClass* atk_class; gpointer data; data = g_type_class_peek(ATK_TYPE_UTIL);
diff --git a/ui/accessibility/platform/atk_util_auralinux.h b/ui/accessibility/platform/atk_util_auralinux.h index b846d5f..9f6ad91 100644 --- a/ui/accessibility/platform/atk_util_auralinux.h +++ b/ui/accessibility/platform/atk_util_auralinux.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 UI_ACCESSIBILITY_AX_UTIL_AURALINUX_H_ -#define UI_ACCESSIBILITY_AX_UTIL_AURALINUX_H_ +#ifndef UI_ACCESSIBILITY_PLATFORM_ATK_UTIL_AURALINUX_H_ +#define UI_ACCESSIBILITY_PLATFORM_ATK_UTIL_AURALINUX_H_ #include <atk/atk.h> @@ -65,4 +65,4 @@ } // namespace ui -#endif // UI_ACCESSIBILITY_AX_UTIL_AURALINUX_H_ +#endif // UI_ACCESSIBILITY_PLATFORM_ATK_UTIL_AURALINUX_H_
diff --git a/ui/accessibility/platform/ax_fragment_root_win.cc b/ui/accessibility/platform/ax_fragment_root_win.cc index adcffb4e..a029658 100644 --- a/ui/accessibility/platform/ax_fragment_root_win.cc +++ b/ui/accessibility/platform/ax_fragment_root_win.cc
@@ -4,6 +4,8 @@ #include "ui/accessibility/platform/ax_fragment_root_win.h" +#include <unordered_map> + #include "base/no_destructor.h" #include "ui/accessibility/platform/ax_platform_node_win.h" #include "ui/base/win/atl_module.h"
diff --git a/ui/accessibility/platform/ax_platform_node.h b/ui/accessibility/platform/ax_platform_node.h index 1e9b8be6..aeab1f7 100644 --- a/ui/accessibility/platform/ax_platform_node.h +++ b/ui/accessibility/platform/ax_platform_node.h
@@ -96,7 +96,7 @@ #if defined(OS_MACOSX) // Fire a platform-specific notification to announce |text|. - virtual void AnnounceText(base::string16& text) = 0; + virtual void AnnounceText(const base::string16& text) = 0; #endif // Return this object's delegate.
diff --git a/ui/accessibility/platform/ax_platform_node_auralinux.cc b/ui/accessibility/platform/ax_platform_node_auralinux.cc index 9796e55..d6291a8 100644 --- a/ui/accessibility/platform/ax_platform_node_auralinux.cc +++ b/ui/accessibility/platform/ax_platform_node_auralinux.cc
@@ -235,7 +235,7 @@ } void IdsToGPtrArray(AXPlatformNodeDelegate* delegate, - std::vector<int32_t>& ids, + const std::vector<int32_t>& ids, GPtrArray* array) { for (const auto& node_id : ids) { if (AXPlatformNode* header = delegate->GetFromNodeID(node_id)) {
diff --git a/ui/accessibility/platform/ax_platform_node_base.cc b/ui/accessibility/platform/ax_platform_node_base.cc index 9019c920..5195d07 100644 --- a/ui/accessibility/platform/ax_platform_node_base.cc +++ b/ui/accessibility/platform/ax_platform_node_base.cc
@@ -123,7 +123,7 @@ } #if defined(OS_MACOSX) -void AXPlatformNodeBase::AnnounceText(base::string16& text) {} +void AXPlatformNodeBase::AnnounceText(const base::string16& text) {} #endif AXPlatformNodeDelegate* AXPlatformNodeBase::GetDelegate() const {
diff --git a/ui/accessibility/platform/ax_platform_node_base.h b/ui/accessibility/platform/ax_platform_node_base.h index 0ef8d74..3cbca68 100644 --- a/ui/accessibility/platform/ax_platform_node_base.h +++ b/ui/accessibility/platform/ax_platform_node_base.h
@@ -68,7 +68,7 @@ void NotifyAccessibilityEvent(ax::mojom::Event event_type) override; #if defined(OS_MACOSX) - void AnnounceText(base::string16& text) override; + void AnnounceText(const base::string16& text) override; #endif AXPlatformNodeDelegate* GetDelegate() const override;
diff --git a/ui/accessibility/platform/ax_platform_node_delegate_base.h b/ui/accessibility/platform/ax_platform_node_delegate_base.h index f5b243b..1db5ffb 100644 --- a/ui/accessibility/platform/ax_platform_node_delegate_base.h +++ b/ui/accessibility/platform/ax_platform_node_delegate_base.h
@@ -8,6 +8,7 @@ #include "ui/accessibility/platform/ax_platform_node_delegate.h" #include <set> +#include <vector> namespace ui {
diff --git a/ui/accessibility/platform/ax_platform_node_mac.h b/ui/accessibility/platform/ax_platform_node_mac.h index a58408b..a5624cb7 100644 --- a/ui/accessibility/platform/ax_platform_node_mac.h +++ b/ui/accessibility/platform/ax_platform_node_mac.h
@@ -23,7 +23,7 @@ // AXPlatformNode. gfx::NativeViewAccessible GetNativeViewAccessible() override; void NotifyAccessibilityEvent(ax::mojom::Event event_type) override; - void AnnounceText(base::string16& text) override; + void AnnounceText(const base::string16& text) override; // AXPlatformNodeBase. void Destroy() override;
diff --git a/ui/accessibility/platform/ax_platform_node_mac.mm b/ui/accessibility/platform/ax_platform_node_mac.mm index f7f0f3e..3e767ce 100644 --- a/ui/accessibility/platform/ax_platform_node_mac.mm +++ b/ui/accessibility/platform/ax_platform_node_mac.mm
@@ -992,7 +992,7 @@ NotifyMacEvent(native_node_, event_type); } -void AXPlatformNodeMac::AnnounceText(base::string16& text) { +void AXPlatformNodeMac::AnnounceText(const base::string16& text) { PostAnnouncementNotification(base::SysUTF16ToNSString(text)); }
diff --git a/ui/accessibility/platform/ax_platform_node_test_helper.h b/ui/accessibility/platform/ax_platform_node_test_helper.h index 14994ea..dd5ffb2e 100644 --- a/ui/accessibility/platform/ax_platform_node_test_helper.h +++ b/ui/accessibility/platform/ax_platform_node_test_helper.h
@@ -5,6 +5,8 @@ #ifndef UI_ACCESSIBILITY_PLATFORM_AX_PLATFORM_NODE_TEST_HELPER_H_ #define UI_ACCESSIBILITY_PLATFORM_AX_PLATFORM_NODE_TEST_HELPER_H_ +#include <string> + #include "ui/accessibility/platform/ax_platform_node.h" #include "ui/accessibility/platform/ax_platform_node_delegate.h"
diff --git a/ui/accessibility/platform/ax_platform_node_textprovider_win.cc b/ui/accessibility/platform/ax_platform_node_textprovider_win.cc index 959f2e6..5e068d0 100644 --- a/ui/accessibility/platform/ax_platform_node_textprovider_win.cc +++ b/ui/accessibility/platform/ax_platform_node_textprovider_win.cc
@@ -109,7 +109,7 @@ if (!selections_to_return.Get()) return E_OUTOFMEMORY; - long index = 0; + LONG index = 0; hr = SafeArrayPutElement(selections_to_return.Get(), &index, text_range_provider); DCHECK(SUCCEEDED(hr));
diff --git a/ui/accessibility/platform/ax_platform_node_textprovider_win.h b/ui/accessibility/platform/ax_platform_node_textprovider_win.h index 65c5713..4a7567d 100644 --- a/ui/accessibility/platform/ax_platform_node_textprovider_win.h +++ b/ui/accessibility/platform/ax_platform_node_textprovider_win.h
@@ -5,6 +5,8 @@ #ifndef UI_ACCESSIBILITY_PLATFORM_AX_PLATFORM_NODE_TEXTPROVIDER_WIN_H_ #define UI_ACCESSIBILITY_PLATFORM_AX_PLATFORM_NODE_TEXTPROVIDER_WIN_H_ +#include <string> + #include "ui/accessibility/platform/ax_platform_node_win.h" namespace ui {
diff --git a/ui/accessibility/platform/ax_platform_node_textprovider_win_unittest.cc b/ui/accessibility/platform/ax_platform_node_textprovider_win_unittest.cc index 8bfc52a4..239bc450 100644 --- a/ui/accessibility/platform/ax_platform_node_textprovider_win_unittest.cc +++ b/ui/accessibility/platform/ax_platform_node_textprovider_win_unittest.cc
@@ -316,14 +316,14 @@ root_text_provider->GetSelection(selections.Receive()); ASSERT_NE(nullptr, selections.Get()); - long ubound; + LONG ubound; EXPECT_HRESULT_SUCCEEDED(SafeArrayGetUBound(selections.Get(), 1, &ubound)); EXPECT_EQ(0, ubound); - long lbound; + LONG lbound; EXPECT_HRESULT_SUCCEEDED(SafeArrayGetLBound(selections.Get(), 1, &lbound)); EXPECT_EQ(0, lbound); - long index = 0; + LONG index = 0; CComPtr<ITextRangeProvider> text_range_provider; EXPECT_HRESULT_SUCCEEDED( SafeArrayGetElement(selections.Get(), &index, &text_range_provider));
diff --git a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.h b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.h index 8456cc7..5e03a81 100644 --- a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.h +++ b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.h
@@ -5,6 +5,7 @@ #ifndef UI_ACCESSIBILITY_PLATFORM_AX_PLATFORM_NODE_TEXTRANGEPROVIDER_WIN_H_ #define UI_ACCESSIBILITY_PLATFORM_AX_PLATFORM_NODE_TEXTRANGEPROVIDER_WIN_H_ +#include <string> #include <tuple> #include <vector>
diff --git a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc index 3d98c46..b79fac73 100644 --- a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc +++ b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc
@@ -1501,9 +1501,9 @@ CComPtr<ITextRangeProvider> selected_text_range_provider; base::win::ScopedSafearray selection; - long index = 0; - long ubound; - long lbound; + LONG index = 0; + LONG ubound; + LONG lbound; // Text range "some text" performs select. {
diff --git a/ui/accessibility/platform/ax_platform_node_unittest.h b/ui/accessibility/platform/ax_platform_node_unittest.h index c9218a4..9bd6ea1 100644 --- a/ui/accessibility/platform/ax_platform_node_unittest.h +++ b/ui/accessibility/platform/ax_platform_node_unittest.h
@@ -2,8 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_ACCESSIBILITY_AX_PLATFORM_NODE_UNITTEST_H_ -#define UI_ACCESSIBILITY_AX_PLATFORM_NODE_UNITTEST_H_ +#ifndef UI_ACCESSIBILITY_PLATFORM_AX_PLATFORM_NODE_UNITTEST_H_ +#define UI_ACCESSIBILITY_PLATFORM_AX_PLATFORM_NODE_UNITTEST_H_ + +#include <memory> #include "testing/gtest/include/gtest/gtest.h" #include "ui/accessibility/ax_node.h" @@ -63,4 +65,4 @@ } // namespace ui -#endif // UI_ACCESSIBILITY_AX_PLATFORM_NODE_UNITTEST_H_ +#endif // UI_ACCESSIBILITY_PLATFORM_AX_PLATFORM_NODE_UNITTEST_H_
diff --git a/ui/accessibility/platform/ax_platform_node_win.cc b/ui/accessibility/platform/ax_platform_node_win.cc index de4e39c..cdf0a9058 100644 --- a/ui/accessibility/platform/ax_platform_node_win.cc +++ b/ui/accessibility/platform/ax_platform_node_win.cc
@@ -3575,8 +3575,8 @@ VARIANT* result) { WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_PROPERTY_VALUE); - constexpr long kFirstKnownUiaPropertyId = UIA_RuntimeIdPropertyId; - constexpr long kLastKnownUiaPropertyId = UIA_HeadingLevelPropertyId; + constexpr LONG kFirstKnownUiaPropertyId = UIA_RuntimeIdPropertyId; + constexpr LONG kLastKnownUiaPropertyId = UIA_HeadingLevelPropertyId; if (property_id >= kFirstKnownUiaPropertyId && property_id <= kLastKnownUiaPropertyId) { base::UmaHistogramSparse("Accessibility.WinAPIs.GetPropertyValue",
diff --git a/ui/accessibility/platform/ax_platform_node_win.h b/ui/accessibility/platform/ax_platform_node_win.h index caed8f9..ee9e2a9 100644 --- a/ui/accessibility/platform/ax_platform_node_win.h +++ b/ui/accessibility/platform/ax_platform_node_win.h
@@ -1,3 +1,4 @@ +// // 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.
diff --git a/ui/accessibility/platform/ax_platform_node_win_unittest.cc b/ui/accessibility/platform/ax_platform_node_win_unittest.cc index aa2f127..d803a82 100644 --- a/ui/accessibility/platform/ax_platform_node_win_unittest.cc +++ b/ui/accessibility/platform/ax_platform_node_win_unittest.cc
@@ -1,3 +1,4 @@ +// // 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. @@ -308,7 +309,7 @@ return result; } -void AXPlatformNodeWinTest::CheckVariantHasName(ScopedVariant& variant, +void AXPlatformNodeWinTest::CheckVariantHasName(const ScopedVariant& variant, const wchar_t* expected_name) { ASSERT_NE(nullptr, variant.ptr()); ComPtr<IAccessible> accessible;
diff --git a/ui/accessibility/platform/ax_platform_node_win_unittest.h b/ui/accessibility/platform/ax_platform_node_win_unittest.h index 4ed3cef..88a871a 100644 --- a/ui/accessibility/platform/ax_platform_node_win_unittest.h +++ b/ui/accessibility/platform/ax_platform_node_win_unittest.h
@@ -7,6 +7,7 @@ #include "ui/accessibility/platform/ax_platform_node_unittest.h" +#include <memory> #include <unordered_set> #include "ui/base/win/accessibility_misc_utils.h" @@ -58,7 +59,7 @@ Microsoft::WRL::ComPtr<IAccessible> accessible); Microsoft::WRL::ComPtr<IAccessible2_2> ToIAccessible2_2( Microsoft::WRL::ComPtr<IAccessible> accessible); - void CheckVariantHasName(base::win::ScopedVariant& variant, + void CheckVariantHasName(const base::win::ScopedVariant& variant, const wchar_t* expected_name); void CheckIUnknownHasName(Microsoft::WRL::ComPtr<IUnknown> unknown, const wchar_t* expected_name); @@ -67,7 +68,7 @@ void InitFragmentRoot(); Microsoft::WRL::ComPtr<IRawElementProviderFragmentRoot> GetFragmentRoot(); - using PatternSet = std::unordered_set<long>; + using PatternSet = std::unordered_set<LONG>; PatternSet GetSupportedPatternsFromNodeId(int32_t id); std::unique_ptr<AXFragmentRootWin> ax_fragment_root_; };
diff --git a/ui/accessibility/platform/ax_platform_relation_win.h b/ui/accessibility/platform/ax_platform_relation_win.h index 2abfe23..dd8426f 100644 --- a/ui/accessibility/platform/ax_platform_relation_win.h +++ b/ui/accessibility/platform/ax_platform_relation_win.h
@@ -79,4 +79,4 @@ } // namespace ui -#endif // UI_ACCESSIBILITY_PLATFORM_AX_PLATFORM_NODE_WIN_H_ +#endif // UI_ACCESSIBILITY_PLATFORM_AX_PLATFORM_RELATION_WIN_H_
diff --git a/ui/accessibility/platform/ax_system_caret_win.h b/ui/accessibility/platform/ax_system_caret_win.h index a18ed98..0d017c6 100644 --- a/ui/accessibility/platform/ax_system_caret_win.h +++ b/ui/accessibility/platform/ax_system_caret_win.h
@@ -47,12 +47,11 @@ AXPlatformNodeWin* caret_; gfx::AcceleratedWidget event_target_; AXNodeData data_; + ui::AXUniqueId unique_id_; friend class AXPlatformNodeWin; - DISALLOW_COPY_AND_ASSIGN(AXSystemCaretWin); - private: - ui::AXUniqueId unique_id_; + DISALLOW_COPY_AND_ASSIGN(AXSystemCaretWin); }; } // namespace ui
diff --git a/ui/accessibility/platform/test_ax_node_wrapper.cc b/ui/accessibility/platform/test_ax_node_wrapper.cc index 2fcb1ba8..551395dd 100644 --- a/ui/accessibility/platform/test_ax_node_wrapper.cc +++ b/ui/accessibility/platform/test_ax_node_wrapper.cc
@@ -5,6 +5,7 @@ #include "ui/accessibility/platform/test_ax_node_wrapper.h" #include <unordered_map> +#include <utility> #include "base/stl_util.h" #include "base/strings/utf_string_conversions.h" @@ -600,13 +601,13 @@ // descendants for a given node within the descendants vector. void TestAXNodeWrapper::Descendants( const AXNode* node, - std::vector<gfx::NativeViewAccessible>& descendants) const { + std::vector<gfx::NativeViewAccessible>* descendants) const { std::vector<AXNode*> child_nodes = node->children(); for (AXNode* child : child_nodes) { - descendants.emplace_back(ax_platform_node() - ->GetDelegate() - ->GetFromNodeID(child->id()) - ->GetNativeViewAccessible()); + descendants->emplace_back(ax_platform_node() + ->GetDelegate() + ->GetFromNodeID(child->id()) + ->GetNativeViewAccessible()); Descendants(child, descendants); } } @@ -614,7 +615,7 @@ const std::vector<gfx::NativeViewAccessible> TestAXNodeWrapper::GetDescendants() const { std::vector<gfx::NativeViewAccessible> descendants; - Descendants(node_, descendants); + Descendants(node_, &descendants); return descendants; }
diff --git a/ui/accessibility/platform/test_ax_node_wrapper.h b/ui/accessibility/platform/test_ax_node_wrapper.h index e3cfad2..3136e0d 100644 --- a/ui/accessibility/platform/test_ax_node_wrapper.h +++ b/ui/accessibility/platform/test_ax_node_wrapper.h
@@ -6,6 +6,7 @@ #define UI_ACCESSIBILITY_PLATFORM_TEST_AX_NODE_WRAPPER_H_ #include <set> +#include <string> #include <vector> #include "build/build_config.h" @@ -113,7 +114,7 @@ int32_t GetSetSize() const override; const std::vector<gfx::NativeViewAccessible> GetDescendants() const override; void Descendants(const AXNode* node, - std::vector<gfx::NativeViewAccessible>& descendants) const; + std::vector<gfx::NativeViewAccessible>* descendants) const; private: TestAXNodeWrapper(AXTree* tree, AXNode* node);
diff --git a/ui/base/mpris/mpris_service_impl.cc b/ui/base/mpris/mpris_service_impl.cc index 64a2fabbd..240b7c6 100644 --- a/ui/base/mpris/mpris_service_impl.cc +++ b/ui/base/mpris/mpris_service_impl.cc
@@ -227,8 +227,12 @@ void MprisServiceImpl::OnExported(const std::string& interface_name, const std::string& method_name, bool success) { - if (success) - num_methods_exported_++; + if (!success) { + service_failed_to_start_ = true; + return; + } + + num_methods_exported_++; // Still waiting for more methods to finish exporting. if (num_methods_exported_ < kNumMethodsToExport) @@ -242,8 +246,10 @@ void MprisServiceImpl::OnOwnership(const std::string& service_name, bool success) { - if (!success) + if (!success) { + service_failed_to_start_ = true; return; + } service_ready_ = true; @@ -441,6 +447,12 @@ } void MprisServiceImpl::EmitPropertiesChangedSignal() { + // If we're still trying to start the service, delay emitting. + if (!service_ready_ && !service_failed_to_start_) { + EmitPropertiesChangedSignalDebounced(); + return; + } + if (!bus_ || !exported_object_ || !service_ready_) return;
diff --git a/ui/base/mpris/mpris_service_impl.h b/ui/base/mpris/mpris_service_impl.h index 0fc9e640f..801ac56 100644 --- a/ui/base/mpris/mpris_service_impl.h +++ b/ui/base/mpris/mpris_service_impl.h
@@ -132,6 +132,9 @@ // True if we have finished creating the DBus service and received ownership. bool service_ready_ = false; + // True if we failed to start the MPRIS DBus service. + bool service_failed_to_start_ = false; + // Used to only send 1 PropertiesChanged signal when many properties are // changed at once. base::OneShotTimer properties_changed_debounce_timer_;
diff --git a/ui/file_manager/image_loader/piex/tests.html b/ui/file_manager/image_loader/piex/tests.html index 6394b97c..f9cd1c35 100644 --- a/ui/file_manager/image_loader/piex/tests.html +++ b/ui/file_manager/image_loader/piex/tests.html
@@ -86,6 +86,53 @@ } } + function createFileSystem(images) { + return new Promise((resolve, reject) => { + document.title = 'createFileSystem'; + + function failed(error) { + reject(new Error('Creating file system: ' + error.name)); + } + + function createdFileSystem(fileSystem) { + console.log('test: created file system', fileSystem.name); + window.fileSystem = fileSystem; + resolve(); + } + + const bytes = images * 30 * 1024 * 1024; // 30M per image. + window.webkitRequestFileSystem( + window.TEMPORARY, bytes, createdFileSystem, failed); + }); + } + + function writeToFileSystem(image) { + return new Promise(async (resolve, reject) => { + document.title = image; + + const buffer = await fetch(image).then((response) => { + if (!response.ok) + throw new Error('Failed to fetch image: ' + image); + return response.arrayBuffer(); + }).catch(reject); + + function failure(error) { + reject(new Error('Writing file system: ' + error.name)); + } + + function writeEntry(fileEntry) { + fileEntry.createWriter((writer) => { + writer.onerror = failure; + writer.onwrite = resolve; + writer.write(new Blob([buffer])); + }, failure); + } + + window.fileSystem.root.getFile( + image.replace('images/', ''), {create: true}, writeEntry, failure); + }); + } + function hashUint8Array(data, hash = ~0) { for (let i = 0; i < data.byteLength; ++i) hash = (hash << 5) - hash + data[i];
diff --git a/ui/gfx/transform.cc b/ui/gfx/transform.cc index 0d5e04b..b42890ec3 100644 --- a/ui/gfx/transform.cc +++ b/ui/gfx/transform.cc
@@ -53,29 +53,10 @@ SkMScalar col2row4, SkMScalar col3row4, SkMScalar col4row4) - : matrix_(SkMatrix44::kIdentity_Constructor) { - // TODO(masonfreed): Replace this with an explicit 16-element constructor - // on SkMatrix44, once that's available. This code does a *lot* of extra - // work, because each call to setDouble re-calculates the matrix type. - matrix_.set(0, 0, col1row1); - matrix_.set(1, 0, col1row2); - matrix_.set(2, 0, col1row3); - matrix_.set(3, 0, col1row4); - - matrix_.set(0, 1, col2row1); - matrix_.set(1, 1, col2row2); - matrix_.set(2, 1, col2row3); - matrix_.set(3, 1, col2row4); - - matrix_.set(0, 2, col3row1); - matrix_.set(1, 2, col3row2); - matrix_.set(2, 2, col3row3); - matrix_.set(3, 2, col3row4); - - matrix_.set(0, 3, col4row1); - matrix_.set(1, 3, col4row2); - matrix_.set(2, 3, col4row3); - matrix_.set(3, 3, col4row4); + : matrix_(SkMatrix44::kUninitialized_Constructor) { + matrix_.set4x4(col1row1, col1row2, col1row3, col1row4, col2row1, col2row2, + col2row3, col2row4, col3row1, col3row2, col3row3, col3row4, + col4row1, col4row2, col4row3, col4row4); } Transform::Transform(SkMScalar col1row1,
diff --git a/ui/login/screen.js b/ui/login/screen.js index 8fcddc9..6d54840 100644 --- a/ui/login/screen.js +++ b/ui/login/screen.js
@@ -60,56 +60,6 @@ }, /** - * Creates and returns new button element with given identifier - * and on-click event listener, which sends notification about - * user action to the C++ side. - * - * @param {string} id Identifier of a button. - * @param {string} opt_action_id Identifier of user action. - * @final - */ - declareButton: function(id, opt_action_id) { - var button = this.ownerDocument.createElement('button'); - button.id = id; - this.declareUserAction(button, - { action_id: opt_action_id, - event: 'click' - }); - return button; - }, - - /** - * Adds event listener to an element which sends notification - * about event to the C++ side. - * - * @param {Element} element An DOM element - * @param {Object} options A dictionary of optional arguments: - * {string} event: name of event that will be listened, - * default: 'click'. - * {string} action_id: name of an action which will be sent to - * the C++ side. - * {function} condition: a one-argument function which takes - * event as an argument, notification is sent to the - * C++ side iff condition is true, default: constant - * true function. - * @final - */ - declareUserAction: function(element, options) { - var self = this; - options = options || {}; - - var event = options.event || 'click'; - var action_id = options.action_id || element.id; - var condition = options.condition || alwaysTruePredicate; - - element.addEventListener(event, function(e) { - if (condition(e)) - self.sendImpl_(CALLBACK_USER_ACTED, action_id); - e.stopPropagation(); - }); - }, - - /** * @override * @final */ @@ -118,34 +68,10 @@ }, /** - * Does the following things: - * * Looks for elements having "alias" property and adds them as the - * proprties of the screen with name equal to value of "alias", i.e. HTML - * element <div alias="myDiv"></div> will be stored in this.myDiv. - * * Looks for buttons having "action" properties and adds click handlers - * to them. These handlers send |CALLBACK_USER_ACTED| messages to - * C++ with "action" property's value as payload. * @private */ initializeImpl_: function() { this.decorate(); - - this.querySelectorAllImpl_('[alias]').forEach(function(element) { - var alias = element.getAttribute('alias'); - if (alias in this) - throw Error('Alias "' + alias + '" of "' + this.name() + '" screen ' + - 'shadows or redefines property that is already defined.'); - this[alias] = element; - this[element.getAttribute('alias')] = element; - }, this); - var self = this; - this.querySelectorAllImpl_('button[action]').forEach(function(button) { - button.addEventListener('click', function(e) { - var action = this.getAttribute('action'); - self.send(CALLBACK_USER_ACTED, action); - e.stopPropagation(); - }); - }); }, /**