diff --git a/DEPS b/DEPS index 85ce8fb0..4988f70 100644 --- a/DEPS +++ b/DEPS
@@ -116,11 +116,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': 'e7b1a13a1e2ae07cd53144bc979184118f1a852e', + 'skia_revision': 'a1211832046de9730dac317afaa8491e1f9019d8', # 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': '558ce607b922e7ac06ac3147a90a38b5266f5241', + 'v8_revision': '655a9bc2d20b6879e1a644613899ca05aa6121ad', # 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. @@ -128,7 +128,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': 'fde74c078f77f434963f763a4715136b4ed6baaf', + 'angle_revision': '8a0fb48a56d668d9473dfead811e1e0d1bbc5f0c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling build tools # and whatever else without interference from each other. @@ -176,7 +176,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': '352a0e0997b945a08a0c0b25e600fec59ed9ce22', + 'catapult_revision': '5913160a7d40a5d0edb2578f3bb769e8667d41a9', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -224,7 +224,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'spv_tools_revision': 'cd22b3155708d7922524e7f52551e0794b3c1d62', + 'spv_tools_revision': 'd652ed3029eb89a4ba0b51e6604dbf3472299647', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -655,7 +655,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'a58355c49753c0a79b39c1a9891e1a0d3e0f2908', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'dac70cc74650f16c7a57b6059df0ae83ae326d72', 'condition': 'checkout_linux', }, @@ -680,7 +680,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'af3328fc7a75c5462e2d0078b9d59b0a5e5e90c1', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'ae6836ecee576f30a16050b84e5e97f69d584851', 'src/third_party/devtools-node-modules': Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'), @@ -1014,7 +1014,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + 'e867072a2353e9609710c7ee0af14a954d21e397', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '96e14159c92b4b47817ae224193553e6771ead0b', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78', @@ -1166,7 +1166,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '5b6cbd789b9b91b4e46dde883c9f2ecb31eddade', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '72bba625d5f79f26ca75984d7acbc7ece0468a84', + Var('webrtc_git') + '/src.git' + '@' + '85340ce5166c880be8c863be6949874b675238f1', 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d', @@ -1197,7 +1197,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@e86231b9da1a598d910364855eb070457bebf606', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@baafd0234bc7db77b39ac9d55926cde57fa86e80', 'condition': 'checkout_src_internal', },
diff --git a/WATCHLISTS b/WATCHLISTS index 6ab7089..b5c428a 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -130,6 +130,10 @@ 'arc_fileapi': { 'filepath': 'chrome/browser/chromeos/arc/fileapi' }, + 'arc_ime': { + 'filepath': 'chrome/browser/chromeos/arc/input_method_manager/'\ + '|components/arc/ime/' + }, 'arc_kiosk': { 'filepath': 'chrome/browser/chromeos/app_mode/arc/'\ '|components/arc/kiosk/'\ @@ -1813,6 +1817,7 @@ 'arc_auth': ['khmel+watch@chromium.org'], 'arc_common': ['hashimoto+watch@chromium.org'], 'arc_fileapi': ['nya+watch@chromium.org'], + 'arc_ime': ['yhanada+watch@chromium.org'], 'arc_kiosk': ['poromov+watch@chromium.org'], 'arc_net': ['abhishekbh@chromium.org', 'cernekee@chromium.org',
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index ec018be..dde21b4d 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -1264,6 +1264,8 @@ "ws/ash_gpu_interface_provider.h", "ws/ash_window_manager.cc", "ws/ash_window_manager.h", + "ws/multi_user_window_manager_bridge.cc", + "ws/multi_user_window_manager_bridge.h", "ws/window_lookup.cc", "ws/window_service_delegate_impl.cc", "ws/window_service_delegate_impl.h",
diff --git a/ash/app_list/app_list_presenter_delegate_unittest.cc b/ash/app_list/app_list_presenter_delegate_unittest.cc index 3617781..8487488 100644 --- a/ash/app_list/app_list_presenter_delegate_unittest.cc +++ b/ash/app_list/app_list_presenter_delegate_unittest.cc
@@ -1088,6 +1088,13 @@ EXPECT_LE(0, view->GetWidget()->GetNativeView()->bounds().y()); } +// Tests that no crash occurs after an attempt to show app list in an invalid +// display. +TEST_F(AppListPresenterDelegateTest, ShowInInvalidDisplay) { + GetAppListTestHelper()->ShowAndRunLoop(display::kInvalidDisplayId); + GetAppListTestHelper()->CheckState(app_list::AppListViewState::CLOSED); +} + // Test a variety of behaviors for home launcher (app list in tablet mode). class AppListPresenterDelegateHomeLauncherTest : public AppListPresenterDelegateTest {
diff --git a/ash/app_list/presenter/app_list_presenter_impl.cc b/ash/app_list/presenter/app_list_presenter_impl.cc index e012041..eb06530 100644 --- a/ash/app_list/presenter/app_list_presenter_impl.cc +++ b/ash/app_list/presenter/app_list_presenter_impl.cc
@@ -126,6 +126,11 @@ return; } + if (!delegate_->GetRootWindowForDisplayId(display_id)) { + LOG(ERROR) << "Root window does not exist for display: " << display_id; + return; + } + is_visible_ = true; RequestPresentationTime(display_id, event_time_stamp);
diff --git a/ash/app_list/presenter/app_list_presenter_impl_unittest.cc b/ash/app_list/presenter/app_list_presenter_impl_unittest.cc index fba8e6a8..2e181ab 100644 --- a/ash/app_list/presenter/app_list_presenter_impl_unittest.cc +++ b/ash/app_list/presenter/app_list_presenter_impl_unittest.cc
@@ -70,7 +70,7 @@ bool IsHomeLauncherEnabledInTabletMode() override { return false; } bool GetOnScreenKeyboardShown() override { return false; } aura::Window* GetRootWindowForDisplayId(int64_t display_id) override { - return nullptr; + return container_->GetRootWindow(); } void OnVisibilityChanged(bool visible, aura::Window* root_window) override {} void OnTargetVisibilityChanged(bool visible) override {}
diff --git a/ash/app_list/views/app_list_item_view.cc b/ash/app_list/views/app_list_item_view.cc index 3fad61f1..26037c9d 100644 --- a/ash/app_list/views/app_list_item_view.cc +++ b/ash/app_list/views/app_list_item_view.cc
@@ -20,7 +20,6 @@ #include "build/build_config.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" -#include "ui/base/ui_base_features.h" #include "ui/compositor/layer.h" #include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/gfx/animation/throb_animation.h" @@ -462,24 +461,19 @@ if (!apps_grid_view_->IsSelectedView(this)) apps_grid_view_->ClearAnySelectedView(); - int run_types = views::MenuRunner::HAS_MNEMONICS; + + int run_types = views::MenuRunner::HAS_MNEMONICS | + views::MenuRunner::USE_TOUCHABLE_LAYOUT | + views::MenuRunner::FIXED_ANCHOR | + views::MenuRunner::CONTEXT_MENU; if (source_type == ui::MENU_SOURCE_TOUCH) run_types |= views::MenuRunner::SEND_GESTURE_EVENTS_TO_OWNER; - views::MenuAnchorPosition anchor_position = views::MENU_ANCHOR_TOPLEFT; - gfx::Rect anchor_rect = gfx::Rect(point, gfx::Size()); - - if (::features::IsTouchableAppContextMenuEnabled()) { - run_types |= views::MenuRunner::USE_TOUCHABLE_LAYOUT | - views::MenuRunner::FIXED_ANCHOR | - views::MenuRunner::CONTEXT_MENU; - anchor_position = views::MENU_ANCHOR_BUBBLE_TOUCHABLE_RIGHT; - anchor_rect = apps_grid_view_->GetIdealBounds(this); - // Anchor the menu to the same rect that is used for selection highlight. - AdaptBoundsForSelectionHighlight(&anchor_rect); - views::View::ConvertRectToScreen(apps_grid_view_, &anchor_rect); - } + gfx::Rect anchor_rect = apps_grid_view_->GetIdealBounds(this); + // Anchor the menu to the same rect that is used for selection highlight. + AdaptBoundsForSelectionHighlight(&anchor_rect); + views::View::ConvertRectToScreen(apps_grid_view_, &anchor_rect); context_menu_ = std::make_unique<AppListMenuModelAdapter>( item_weak_->GetMetadata()->id, this, source_type, this, @@ -487,7 +481,8 @@ base::BindOnce(&AppListItemView::OnMenuClosed, weak_ptr_factory_.GetWeakPtr())); context_menu_->Build(std::move(menu)); - context_menu_->Run(anchor_rect, anchor_position, run_types); + context_menu_->Run(anchor_rect, views::MENU_ANCHOR_BUBBLE_TOUCHABLE_RIGHT, + run_types); apps_grid_view_->SetSelectedView(this); }
diff --git a/ash/app_list/views/search_result_tile_item_view.cc b/ash/app_list/views/search_result_tile_item_view.cc index c6ee795b..4fb773c 100644 --- a/ash/app_list/views/search_result_tile_item_view.cc +++ b/ash/app_list/views/search_result_tile_item_view.cc
@@ -24,7 +24,6 @@ #include "base/strings/utf_string_conversions.h" #include "ui/accessibility/ax_node_data.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/base/ui_base_features.h" #include "ui/gfx/canvas.h" #include "ui/gfx/color_palette.h" #include "ui/gfx/image/image_skia_operations.h" @@ -367,27 +366,20 @@ if (menu.empty() || (context_menu_ && context_menu_->IsShowingMenu())) return; - int run_types = views::MenuRunner::HAS_MNEMONICS; - views::MenuAnchorPosition anchor_position = views::MENU_ANCHOR_TOPLEFT; - gfx::Rect anchor_rect = gfx::Rect(point, gfx::Size()); - - if (::features::IsTouchableAppContextMenuEnabled()) { - anchor_position = views::MENU_ANCHOR_BUBBLE_TOUCHABLE_RIGHT; - run_types |= views::MenuRunner::USE_TOUCHABLE_LAYOUT | - views::MenuRunner::CONTEXT_MENU | - views::MenuRunner::FIXED_ANCHOR; - anchor_rect = source->GetBoundsInScreen(); - // Anchor the menu to the same rect that is used for selection highlight. - anchor_rect.ClampToCenteredSize( - AppListConfig::instance().grid_focus_size()); - } + gfx::Rect anchor_rect = source->GetBoundsInScreen(); + // Anchor the menu to the same rect that is used for selection highlight. + anchor_rect.ClampToCenteredSize(AppListConfig::instance().grid_focus_size()); context_menu_ = std::make_unique<AppListMenuModelAdapter>( item_->id(), this, source_type, this, GetAppType(), base::BindOnce(&SearchResultTileItemView::OnMenuClosed, weak_ptr_factory_.GetWeakPtr())); context_menu_->Build(std::move(menu)); - context_menu_->Run(anchor_rect, anchor_position, run_types); + context_menu_->Run(anchor_rect, views::MENU_ANCHOR_BUBBLE_TOUCHABLE_RIGHT, + views::MenuRunner::HAS_MNEMONICS | + views::MenuRunner::USE_TOUCHABLE_LAYOUT | + views::MenuRunner::CONTEXT_MENU | + views::MenuRunner::FIXED_ANCHOR); source->RequestFocus(); }
diff --git a/ash/login/ui/lock_contents_view.cc b/ash/login/ui/lock_contents_view.cc index 16c33721..63304f4 100644 --- a/ash/login/ui/lock_contents_view.cc +++ b/ash/login/ui/lock_contents_view.cc
@@ -697,7 +697,7 @@ auth_error_bubble_->ShowErrorBubble( container, big_view->auth_user()->password_view() /*anchor_view*/, - LoginBubble::kFlagPersistent); + true /*show_persistently*/); } } @@ -816,7 +816,7 @@ label->SetEnabledColor(SK_ColorWHITE); warning_banner_bubble_->ShowErrorBubble( label, CurrentBigUserView()->auth_user()->password_view() /*anchor_view*/, - LoginBubble::kFlagPersistent); + true /*show_persistently*/); } void LockContentsView::OnHideWarningBanner() { @@ -975,7 +975,7 @@ detachable_base_error_bubble_->ShowErrorBubble( label, CurrentBigUserView()->auth_user()->password_view() /*anchor_view*/, - LoginBubble::kFlagPersistent); + true /*show_persistently*/); // Remove the focus from the password field, to make user less likely to enter // the password without seeing the warning about detachable base change. @@ -1489,7 +1489,7 @@ supervised_user_deprecation_bubble_->ShowErrorBubble( label, CurrentBigUserView()->auth_user()->password_view() /*anchor_view*/, - LoginBubble::kFlagPersistent); + true /*show_persistently*/); } // The new auth user might have different last used detachable base - make @@ -1595,7 +1595,7 @@ auth_error_bubble_->ShowErrorBubble( container, big_view->auth_user()->password_view() /*anchor_view*/, - LoginBubble::kFlagsNone); + false /*show_persistently*/); } void LockContentsView::OnEasyUnlockIconHovered() {
diff --git a/ash/login/ui/lock_contents_view_unittest.cc b/ash/login/ui/lock_contents_view_unittest.cc index d35d155a..3914642 100644 --- a/ash/login/ui/lock_contents_view_unittest.cc +++ b/ash/login/ui/lock_contents_view_unittest.cc
@@ -377,7 +377,7 @@ LockContentsView* contents = LockScreen::TestApi(LockScreen::Get()).contents_view(); ASSERT_NE(nullptr, contents); - LoadUsers(9); + SetUserCount(9); // Users list in extra small layout should adjust its height to parent. ScrollableUsersListView* users_list = @@ -399,7 +399,7 @@ LockContentsView* contents = LockScreen::TestApi(LockScreen::Get()).contents_view(); ASSERT_NE(nullptr, contents); - LoadUsers(4); + SetUserCount(4); ScrollableUsersListView* users_list = LockContentsView::TestApi(contents).users_list(); @@ -1231,7 +1231,7 @@ // Add user who can use pin authentication. const std::string email = "user@domain.com"; - LoadUser(email); + AddUserByEmail(email); contents->OnPinEnabledForUserChanged(AccountId::FromUserEmail(email), true); LoginBigUserView* big_view = LockContentsView::TestApi(contents).primary_big_view(); @@ -1259,7 +1259,7 @@ LockScreen::TestApi(LockScreen::Get()).contents_view(); ASSERT_NE(nullptr, contents); - LoadUsers(2); + SetUserCount(2); LoginAuthUserView::TestApi primary_user( LockContentsView::TestApi(contents).primary_big_view()->auth_user()); @@ -1305,7 +1305,7 @@ // Add user who can use pin authentication. const std::string email = "user@domain.com"; - LoadUser(email); + AddUserByEmail(email); contents->OnPinEnabledForUserChanged(AccountId::FromUserEmail(email), true); LoginBigUserView* big_view = LockContentsView::TestApi(contents).primary_big_view(); @@ -1799,14 +1799,13 @@ EXPECT_TRUE(HasFocusInAnyChildView(status_area)); } -class LockContentsViewPowerManagerUnitTest - : public LockContentsViewKeyboardUnitTest { +class LockContentsViewPowerManagerUnitTest : public LockContentsViewUnitTest { public: void SetUp() override { chromeos::DBusThreadManager::GetSetterForTesting()->SetPowerManagerClient( std::make_unique<chromeos::FakePowerManagerClient>()); - LockContentsViewKeyboardUnitTest::SetUp(); + LockContentsViewUnitTest::SetUp(); } }; @@ -1831,9 +1830,9 @@ // Verifies that the password box for the active user is cleared if a suspend // event is received. -TEST_F(LockContentsViewKeyboardUnitTest, PasswordClearedOnSuspend) { +TEST_F(LockContentsViewUnitTest, PasswordClearedOnSuspend) { ASSERT_NO_FATAL_FAILURE(ShowLoginScreen()); - LoadUsers(1); + AddUsers(1); LockScreen::TestApi lock_screen = LockScreen::TestApi(LockScreen::Get()); LockContentsView* contents = lock_screen.contents_view(); @@ -1851,9 +1850,9 @@ EXPECT_TRUE(textfield->text().empty()); } -TEST_F(LockContentsViewKeyboardUnitTest, ArrowNavSingleUser) { +TEST_F(LockContentsViewUnitTest, ArrowNavSingleUser) { ASSERT_NO_FATAL_FAILURE(ShowLoginScreen()); - LoadUsers(1); + SetUserCount(1); LockContentsView* lock_contents = LockScreen::TestApi(LockScreen::Get()).contents_view(); @@ -1869,10 +1868,10 @@ EXPECT_TRUE(login_views_utils::HasFocusInAnyChildView(primary_big_view)); } -TEST_F(LockContentsViewKeyboardUnitTest, ArrowNavTwoUsers) { +TEST_F(LockContentsViewUnitTest, ArrowNavTwoUsers) { ASSERT_NO_FATAL_FAILURE(ShowLoginScreen()); - LoadUsers(1); - LoadPublicAccountUsers(1); + AddUsers(1); + AddPublicAccountUsers(1); LockContentsView::TestApi lock_contents = LockContentsView::TestApi( LockScreen::TestApi(LockScreen::Get()).contents_view()); @@ -1899,9 +1898,9 @@ EXPECT_TRUE(login_views_utils::HasFocusInAnyChildView(primary_password_view)); } -TEST_F(LockContentsViewKeyboardUnitTest, ArrowNavThreeUsers) { +TEST_F(LockContentsViewUnitTest, ArrowNavThreeUsers) { ASSERT_NO_FATAL_FAILURE(ShowLoginScreen()); - LoadUsers(3); + SetUserCount(3); LockContentsView::TestApi lock_contents = LockContentsView::TestApi( LockScreen::TestApi(LockScreen::Get()).contents_view()); @@ -1932,9 +1931,9 @@ EXPECT_TRUE(login_views_utils::HasFocusInAnyChildView(primary_password_view)); } -TEST_F(LockContentsViewKeyboardUnitTest, UserSwapFocusesBigView) { +TEST_F(LockContentsViewUnitTest, UserSwapFocusesBigView) { ASSERT_NO_FATAL_FAILURE(ShowLoginScreen()); - LoadUsers(3); + SetUserCount(3); LockContentsView::TestApi lock_contents = LockContentsView::TestApi( LockScreen::TestApi(LockScreen::Get()).contents_view());
diff --git a/ash/login/ui/lock_window_unittest.cc b/ash/login/ui/lock_window_unittest.cc index 5296834..667d4e8 100644 --- a/ash/login/ui/lock_window_unittest.cc +++ b/ash/login/ui/lock_window_unittest.cc
@@ -21,7 +21,7 @@ LockScreen::TestApi(LockScreen::Get()).contents_view(); ASSERT_NE(nullptr, lock_contents); - LoadUsers(1); + SetUserCount(1); LoginBigUserView* auth_view = MakeLockContentsViewTestApi(lock_contents).primary_big_view();
diff --git a/ash/login/ui/login_base_bubble_view.cc b/ash/login/ui/login_base_bubble_view.cc index efe6305..69813f7 100644 --- a/ash/login/ui/login_base_bubble_view.cc +++ b/ash/login/ui/login_base_bubble_view.cc
@@ -50,6 +50,10 @@ return nullptr; } +bool LoginBaseBubbleView::IsPersistent() const { + return false; +} + void LoginBaseBubbleView::OnBeforeBubbleWidgetInit( views::Widget::InitParams* params, views::Widget* widget) const {
diff --git a/ash/login/ui/login_base_bubble_view.h b/ash/login/ui/login_base_bubble_view.h index 4f89b1d..f8aa76e4 100644 --- a/ash/login/ui/login_base_bubble_view.h +++ b/ash/login/ui/login_base_bubble_view.h
@@ -25,6 +25,9 @@ // Returns the button responsible for opening this bubble. virtual LoginButton* GetBubbleOpener() const; + // Returns whether or not this bubble should show persistently. + virtual bool IsPersistent() const; + // views::BubbleDialogDelegateView: void OnBeforeBubbleWidgetInit(views::Widget::InitParams* params, views::Widget* widget) const override;
diff --git a/ash/login/ui/login_bubble.cc b/ash/login/ui/login_bubble.cc index aae18d70..8d2a7346 100644 --- a/ash/login/ui/login_bubble.cc +++ b/ash/login/ui/login_bubble.cc
@@ -96,8 +96,10 @@ public: LoginErrorBubbleView(views::View* content, views::View* anchor_view, - aura::Window* container) - : LoginBaseBubbleView(anchor_view, container) { + aura::Window* container, + bool show_persistently) + : LoginBaseBubbleView(anchor_view, container), + show_persistently_(show_persistently) { set_anchor_view_insets( gfx::Insets(kAnchorViewErrorBubbleVerticalSpacingDp, 0)); @@ -125,6 +127,9 @@ ~LoginErrorBubbleView() override = default; + // LoginBaseBubbleView: + bool IsPersistent() const override { return show_persistently_; } + // views::View: const char* GetClassName() const override { return "LoginErrorBubbleView"; } void GetAccessibleNodeData(ui::AXNodeData* node_data) override { @@ -132,6 +137,8 @@ } private: + bool show_persistently_; + DISALLOW_COPY_AND_ASSIGN(LoginErrorBubbleView); }; @@ -453,14 +460,14 @@ void LoginBubble::ShowErrorBubble(views::View* content, views::View* anchor_view, - uint32_t flags) { + bool show_persistently) { if (bubble_view_) CloseImmediately(); - flags_ = flags; aura::Window* menu_container = Shell::GetContainer( Shell::GetPrimaryRootWindow(), kShellWindowId_MenuContainer); - bubble_view_ = new LoginErrorBubbleView(content, anchor_view, menu_container); + bubble_view_ = new LoginErrorBubbleView(content, anchor_view, menu_container, + show_persistently); Show(); } @@ -477,7 +484,6 @@ if (bubble_view_) CloseImmediately(); - flags_ = kFlagsNone; bubble_view_ = new LoginUserMenuView( this, username, email, type, is_owner, anchor_view, bubble_opener, show_remove_user, std::move(on_remove_user_warning_shown), @@ -496,7 +502,6 @@ if (bubble_view_) CloseImmediately(); - flags_ = kFlagsNone; bubble_view_ = new LoginTooltipView(message, anchor_view); Show(); } @@ -505,7 +510,6 @@ if (bubble_view_) CloseImmediately(); - flags_ = kFlagsNone; const bool had_focus = menu->GetBubbleOpener() && menu->GetBubbleOpener()->HasFocus(); @@ -579,7 +583,7 @@ if (bubble_view_->GetWidget()->IsActive()) return; - if (!(flags_ & kFlagPersistent)) { + if (!bubble_view_->IsPersistent()) { Close(); } } @@ -603,7 +607,7 @@ if (gained_focus && bubble_window->Contains(gained_focus)) return; - if (!(flags_ & kFlagPersistent)) + if (!bubble_view_->IsPersistent()) Close(); } @@ -645,7 +649,7 @@ return; } - if (!(flags_ & kFlagPersistent)) + if (!bubble_view_->IsPersistent()) Close(); } @@ -694,7 +698,6 @@ bubble_view_->GetWidget()->Close(); is_visible_ = false; bubble_view_ = nullptr; - flags_ = kFlagsNone; } void LoginBubble::EnsureBubbleInScreen() {
diff --git a/ash/login/ui/login_bubble.h b/ash/login/ui/login_bubble.h index 56b6b9c..db3619c 100644 --- a/ash/login/ui/login_bubble.h +++ b/ash/login/ui/login_bubble.h
@@ -40,12 +40,6 @@ static const int kUserMenuRemoveUserButtonIdForTest; - // Flags passed to ShowErrorBubble(). - static constexpr uint32_t kFlagsNone = 0; - // If set, the shown error bubble will not be closed due to an unrelated user - // action - e.g. the bubble will not be closed if the user starts typing. - static constexpr uint32_t kFlagPersistent = 1 << 0; - LoginBubble(); ~LoginBubble() override; @@ -53,7 +47,7 @@ // |anchor_view| is the anchor for placing the bubble view. void ShowErrorBubble(views::View* content, views::View* anchor_view, - uint32_t flags); + bool show_persistently); // Shows a user menu bubble. // |anchor_view| is the anchor for placing the bubble view. @@ -128,9 +122,6 @@ // Repositions the bubble view if it extends too far right or down. void EnsureBubbleInScreen(); - // Flags passed to ShowErrorBubble(). - uint32_t flags_ = kFlagsNone; - LoginBaseBubbleView* bubble_view_ = nullptr; // The status of bubble after animation ends.
diff --git a/ash/login/ui/login_bubble_unittest.cc b/ash/login/ui/login_bubble_unittest.cc index 07fee4bd..0e51846 100644 --- a/ash/login/ui/login_bubble_unittest.cc +++ b/ash/login/ui/login_bubble_unittest.cc
@@ -288,7 +288,7 @@ EXPECT_FALSE(bubble_->IsVisible()); views::Label* error_text = new views::Label(base::ASCIIToUTF16("Error text")); - bubble_->ShowErrorBubble(error_text, container_, LoginBubble::kFlagsNone); + bubble_->ShowErrorBubble(error_text, container_, false /*show_persistently*/); EXPECT_TRUE(bubble_->IsVisible()); // Verifies that key event on a view other than error closes the error bubble. @@ -302,7 +302,7 @@ EXPECT_FALSE(bubble_->IsVisible()); views::Label* error_text = new views::Label(base::ASCIIToUTF16("Error text")); - bubble_->ShowErrorBubble(error_text, container_, LoginBubble::kFlagsNone); + bubble_->ShowErrorBubble(error_text, container_, false /*show_persistently*/); EXPECT_TRUE(bubble_->IsVisible()); // Verifies that mouse event on the bubble itself won't close the bubble. @@ -322,7 +322,7 @@ EXPECT_FALSE(bubble_->IsVisible()); views::Label* error_text = new views::Label(base::ASCIIToUTF16("Error text")); - bubble_->ShowErrorBubble(error_text, container_, LoginBubble::kFlagsNone); + bubble_->ShowErrorBubble(error_text, container_, false /*show_persistently*/); EXPECT_TRUE(bubble_->IsVisible()); // Verifies that gesture event on the bubble itself won't close the bubble. @@ -340,8 +340,7 @@ EXPECT_FALSE(bubble_->IsVisible()); views::Label* error_text = new views::Label(base::ASCIIToUTF16("Error text")); - bubble_->ShowErrorBubble(error_text, container_, - LoginBubble::kFlagPersistent); + bubble_->ShowErrorBubble(error_text, container_, true /*show_persistently*/); EXPECT_TRUE(bubble_->IsVisible()); // Verifies that mouse event on the bubble itself won't close the bubble.
diff --git a/ash/login/ui/login_keyboard_test_base.cc b/ash/login/ui/login_keyboard_test_base.cc index a2ef470..fed9442 100644 --- a/ash/login/ui/login_keyboard_test_base.cc +++ b/ash/login/ui/login_keyboard_test_base.cc
@@ -5,7 +5,6 @@ #include "ash/login/ui/login_keyboard_test_base.h" #include "ash/keyboard/ash_keyboard_controller.h" -#include "ash/login/login_screen_controller.h" #include "ash/login/mock_login_screen_client.h" #include "ash/login/ui/lock_screen.h" #include "ash/login/ui/login_test_utils.h" @@ -29,19 +28,15 @@ void LoginKeyboardTestBase::SetUp() { base::CommandLine::ForCurrentProcess()->AppendSwitch( keyboard::switches::kEnableVirtualKeyboard); - AshTestBase::SetUp(); - - login_controller_ = Shell::Get()->login_screen_controller(); - ASSERT_NE(nullptr, login_controller_); + LoginTestBase::SetUp(); Shell::Get()->ash_keyboard_controller()->ActivateKeyboard(); } void LoginKeyboardTestBase::TearDown() { Shell::Get()->ash_keyboard_controller()->DeactivateKeyboard(); - if (ash::LockScreen::HasInstance()) - ash::LockScreen::Get()->Destroy(); - AshTestBase::TearDown(); + + LoginTestBase::TearDown(); } void LoginKeyboardTestBase::ShowKeyboard() { @@ -68,57 +63,4 @@ ->GetBoundsInScreen(); } -void LoginKeyboardTestBase::ShowLockScreen() { - GetSessionControllerClient()->SetSessionState( - session_manager::SessionState::LOCKED); - // The lock screen can't be shown without a wallpaper. - Shell::Get()->wallpaper_controller()->ShowDefaultWallpaperForTesting(); - - base::Optional<bool> result; - login_controller_->ShowLockScreen(base::BindOnce( - [](base::Optional<bool>* result, bool did_show) { *result = did_show; }, - &result)); - base::RunLoop().RunUntilIdle(); - ASSERT_TRUE(result.has_value()); - ASSERT_EQ(*result, true); -} - -void LoginKeyboardTestBase::ShowLoginScreen() { - GetSessionControllerClient()->SetSessionState( - session_manager::SessionState::LOGIN_PRIMARY); - // The login screen can't be shown without a wallpaper. - Shell::Get()->wallpaper_controller()->ShowDefaultWallpaperForTesting(); - - base::Optional<bool> result; - login_controller_->ShowLoginScreen(base::BindOnce( - [](base::Optional<bool>* result, bool did_show) { *result = did_show; }, - &result)); - base::RunLoop().RunUntilIdle(); - ASSERT_TRUE(result.has_value()); - ASSERT_EQ(*result, true); -} - -void LoginKeyboardTestBase::LoadUsers(int count) { - for (int i = 0; i < count; ++i) { - std::string email = - base::StrCat({"user", std::to_string(i), "@domain.com "}); - users_.push_back(CreateUser(email)); - } - ash::LockScreen::Get()->data_dispatcher()->NotifyUsers(users_); -} - -void LoginKeyboardTestBase::LoadPublicAccountUsers(int count) { - for (int i = 0; i < count; ++i) { - std::string email = - base::StrCat({"publicuser", std::to_string(i), "@domain.com"}); - users_.push_back(CreatePublicAccountUser(email)); - } - ash::LockScreen::Get()->data_dispatcher()->NotifyUsers(users_); -} - -void LoginKeyboardTestBase::LoadUser(const std::string& email) { - users_.push_back(CreateUser(email)); - ash::LockScreen::Get()->data_dispatcher()->NotifyUsers(users_); -} - } // namespace ash
diff --git a/ash/login/ui/login_keyboard_test_base.h b/ash/login/ui/login_keyboard_test_base.h index 36801a9..75a31e1 100644 --- a/ash/login/ui/login_keyboard_test_base.h +++ b/ash/login/ui/login_keyboard_test_base.h
@@ -7,16 +7,15 @@ #include <memory> +#include "ash/login/ui/login_test_base.h" #include "ash/public/interfaces/login_user_info.mojom.h" #include "ash/test/ash_test_base.h" namespace ash { -class LoginScreenController; - // Base test fixture for testing the views-based login and lock screens with // virtual keyboard. -class LoginKeyboardTestBase : public AshTestBase { +class LoginKeyboardTestBase : public LoginTestBase { public: LoginKeyboardTestBase(); ~LoginKeyboardTestBase() override; @@ -33,29 +32,11 @@ // Returns bounds of the keyboard in screen coordinate space. gfx::Rect GetKeyboardBoundsInScreen() const; - // Shows lock screen. Asserts that lock screen is shown. To stop execution of - // the test on failed assertion use ASSERT_NO_FATAL_FAILURE macro. - void ShowLockScreen(); - - // Shows login screen. Asserts that login screen is shown. To stop execution - // of the test on failed assertion use ASSERT_NO_FATAL_FAILURE macro. - void ShowLoginScreen(); - - // Loads the number of test users specified by |count|. - void LoadUsers(int count); - - // Loads the number of test public account users specified by |count|. - void LoadPublicAccountUsers(int count); - - // Loads user with the specified |email|. - void LoadUser(const std::string& email); - // AshTestBase: void SetUp() override; void TearDown() override; private: - LoginScreenController* login_controller_ = nullptr; std::vector<mojom::LoginUserInfoPtr> users_; DISALLOW_COPY_AND_ASSIGN(LoginKeyboardTestBase);
diff --git a/ash/login/ui/login_test_base.cc b/ash/login/ui/login_test_base.cc index e246616d..bfba837 100644 --- a/ash/login/ui/login_test_base.cc +++ b/ash/login/ui/login_test_base.cc
@@ -6,10 +6,14 @@ #include <string> +#include "ash/login/login_screen_controller.h" +#include "ash/login/ui/lock_screen.h" #include "ash/login/ui/login_test_utils.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/public/interfaces/tray_action.mojom.h" +#include "ash/session/test_session_controller_client.h" #include "ash/shell.h" +#include "ash/wallpaper/wallpaper_controller.h" #include "base/strings/strcat.h" #include "services/ws/public/cpp/property_type_converters.h" #include "services/ws/public/mojom/window_manager.mojom.h" @@ -42,6 +46,36 @@ LoginTestBase::~LoginTestBase() = default; +void LoginTestBase::ShowLockScreen() { + GetSessionControllerClient()->SetSessionState( + session_manager::SessionState::LOCKED); + // The lock screen can't be shown without a wallpaper. + Shell::Get()->wallpaper_controller()->ShowDefaultWallpaperForTesting(); + + base::Optional<bool> result; + Shell::Get()->login_screen_controller()->ShowLockScreen(base::BindOnce( + [](base::Optional<bool>* result, bool did_show) { *result = did_show; }, + &result)); + base::RunLoop().RunUntilIdle(); + ASSERT_TRUE(result.has_value()); + ASSERT_EQ(*result, true); +} + +void LoginTestBase::ShowLoginScreen() { + GetSessionControllerClient()->SetSessionState( + session_manager::SessionState::LOGIN_PRIMARY); + // The login screen can't be shown without a wallpaper. + Shell::Get()->wallpaper_controller()->ShowDefaultWallpaperForTesting(); + + base::Optional<bool> result; + Shell::Get()->login_screen_controller()->ShowLoginScreen(base::BindOnce( + [](base::Optional<bool>* result, bool did_show) { *result = did_show; }, + &result)); + base::RunLoop().RunUntilIdle(); + ASSERT_TRUE(result.has_value()); + ASSERT_EQ(*result, true); +} + void LoginTestBase::SetWidget(std::unique_ptr<views::Widget> widget) { EXPECT_FALSE(widget_) << "SetWidget can only be called once."; widget_ = std::move(widget); @@ -76,7 +110,7 @@ users_.erase(users_.begin() + count, users_.end()); // Notify any listeners that the user count has changed. - data_dispatcher_.NotifyUsers(users_); + data_dispatcher()->NotifyUsers(users_); } void LoginTestBase::AddUsers(size_t num_users) { @@ -87,7 +121,12 @@ } // Notify any listeners that the user count has changed. - data_dispatcher_.NotifyUsers(users_); + data_dispatcher()->NotifyUsers(users_); +} + +void LoginTestBase::AddUserByEmail(const std::string& email) { + users_.push_back(CreateUser(email)); + data_dispatcher()->NotifyUsers(users_); } void LoginTestBase::AddPublicAccountUsers(size_t num_public_accounts) { @@ -98,12 +137,20 @@ } // Notify any listeners that the user count has changed. - data_dispatcher_.NotifyUsers(users_); + data_dispatcher()->NotifyUsers(users_); +} + +LoginDataDispatcher* LoginTestBase::data_dispatcher() { + return LockScreen::HasInstance() ? LockScreen::Get()->data_dispatcher() + : &data_dispatcher_; } void LoginTestBase::TearDown() { widget_.reset(); + if (LockScreen::HasInstance()) + LockScreen::Get()->Destroy(); + AshTestBase::TearDown(); }
diff --git a/ash/login/ui/login_test_base.h b/ash/login/ui/login_test_base.h index 298d32a..b914ae97 100644 --- a/ash/login/ui/login_test_base.h +++ b/ash/login/ui/login_test_base.h
@@ -26,6 +26,13 @@ LoginTestBase(); ~LoginTestBase() override; + // Shows a full Lock/Login screen. These methods are useful for when we want + // to test interactions between multiple lock screen components, or when some + // component needs to be able to talk directly to the lockscreen (e.g. getting + // the ScreenType). + void ShowLockScreen(); + void ShowLoginScreen(); + // Sets the primary test widget. The widget can be retrieved using |widget()|. // This can be used to make a widget scoped to the whole test, e.g. if the // widget is created in a SetUp override. @@ -45,6 +52,9 @@ // |data_dispatcher()|. void AddUsers(size_t num_users); + // Add a single user with the specified |email|. + void AddUserByEmail(const std::string& email); + // Append number of |num_public_accounts| public account users. // Changes the active number of users. Fires an event on // |data_dispatcher()|. @@ -54,7 +64,10 @@ const std::vector<mojom::LoginUserInfoPtr>& users() const { return users_; } - LoginDataDispatcher* data_dispatcher() { return &data_dispatcher_; } + // If the LockScreen is instantiated, returns its data dispatcher. Otherwise, + // returns a standalone instance. + // TODO(crbug/906676): rename this method to DataDispatcher. + LoginDataDispatcher* data_dispatcher(); // AshTestBase: void TearDown() override;
diff --git a/ash/multi_user/multi_user_window_manager.cc b/ash/multi_user/multi_user_window_manager.cc index 214b028..bafe7ee 100644 --- a/ash/multi_user/multi_user_window_manager.cc +++ b/ash/multi_user/multi_user_window_manager.cc
@@ -15,12 +15,13 @@ #include "ash/session/session_controller.h" #include "ash/shell.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" +#include "ash/ws/window_service_owner.h" #include "base/auto_reset.h" #include "base/macros.h" -#include "ui/aura/client/aura_constants.h" +#include "services/ws/window_service.h" +#include "ui/aura/mus/window_mus.h" +#include "ui/aura/mus/window_tree_client.h" #include "ui/aura/window.h" -#include "ui/aura/window_event_dispatcher.h" -#include "ui/aura/window_tree_host.h" #include "ui/base/ui_base_types.h" #include "ui/events/event.h" #include "ui/views/mus/mus_client.h" @@ -82,6 +83,35 @@ return wallpaper_user_info; } +// If |window| has a remote client, this converts it to the remote window used +// by the delegate. This effectively undoes the mapping that +// MultiUserWindowManagerBridge does. +// TODO: remove this and instead notify about changes to these windows over a +// mojom. https://crbug.com/875111. +aura::Window* MapWindowIfNecessary(aura::Window* window) { + if (!ws::WindowService::HasRemoteClient(window) || + !views::MusClient::Exists()) { + return window; + } + + const ws::Id window_id = Shell::Get() + ->window_service_owner() + ->window_service() + ->GetTopLevelWindowId(window); + if (window_id == ws::kInvalidTransportId) + return window; + + // children[0] is used to deal with DesktopNativeWidgetAura. In particular, + // client code generally expects to see the first child, which corresponds to + // Widget::GetNativeWindow(), when using DesktopNativeWidgetAura. + aura::WindowMus* window_mus = + views::MusClient::Get()->window_tree_client()->GetWindowByServerId( + window_id); + return window_mus && !window_mus->GetWindow()->children().empty() + ? window_mus->GetWindow()->children()[0] + : window; +} + } // namespace // A class to temporarily change the animation properties for a window. @@ -134,13 +164,12 @@ animation_->CancelAnimation(); // Remove all window observers. - WindowToEntryMap::iterator window = window_to_entry_.begin(); - while (window != window_to_entry_.end()) { + while (!window_to_entry_.empty()) { // Explicitly remove this from window observer list since OnWindowDestroyed // no longer does that. - window->first->RemoveObserver(this); - OnWindowDestroyed(window->first); - window = window_to_entry_.begin(); + aura::Window* window = window_to_entry_.begin()->first; + window->RemoveObserver(this); + OnWindowDestroyed(window); } Shell::Get()->session_controller()->RemoveObserver(this); @@ -154,7 +183,8 @@ } void MultiUserWindowManager::SetWindowOwner(aura::Window* window, - const AccountId& account_id) { + const AccountId& account_id, + bool show_for_current_user) { // Make sure the window is valid and there was no owner yet. DCHECK(window); DCHECK(account_id.is_valid()); @@ -162,10 +192,13 @@ if (GetWindowOwner(window) == account_id) return; DCHECK(GetWindowOwner(window).empty()); - window_to_entry_[window] = new WindowEntry(account_id); + std::unique_ptr<WindowEntry> window_entry_ptr = + std::make_unique<WindowEntry>(account_id); + WindowEntry* window_entry = window_entry_ptr.get(); + window_to_entry_[window] = std::move(window_entry_ptr); // Remember the initial visibility of the window. - window_to_entry_[window]->set_show(window->IsVisible()); + window_entry->set_show(window->IsVisible()); // Add observers to track state changes. window->AddObserver(this); @@ -173,8 +206,8 @@ // Check if this window was created due to a user interaction. If it was, // transfer it to the current user. - if (window->GetProperty(aura::client::kCreatedByUserGesture)) - window_to_entry_[window]->set_show_for_user(current_account_id_); + if (show_for_current_user) + window_entry->set_show_for_user(current_account_id_); // Add all transient children to our set of windows. Note that the function // will add the children but not the owner to the transient children map. @@ -206,9 +239,8 @@ } bool MultiUserWindowManager::AreWindowsSharedAmongUsers() const { - WindowToEntryMap::const_iterator it = window_to_entry_.begin(); - for (; it != window_to_entry_.end(); ++it) { - if (it->second->owner() != it->second->show_for_user()) + for (auto& window_pair : window_to_entry_) { + if (window_pair.second->owner() != window_pair.second->show_for_user()) return true; } return false; @@ -269,8 +301,6 @@ return; } ::wm::TransientWindowManager::GetOrCreate(window)->RemoveObserver(this); - // Remove the window from the owners list. - delete window_to_entry_[window]; window_to_entry_.erase(window); } @@ -340,7 +370,7 @@ } void MultiUserWindowManager::OnTabletModeStarted() { - for (auto entry : window_to_entry_) + for (auto& entry : window_to_entry_) Shell::Get()->tablet_mode_controller()->AddWindow(entry.first); } @@ -372,23 +402,25 @@ if (account_id != owner && minimized) return false; - WindowToEntryMap::iterator it = window_to_entry_.find(window); - it->second->set_show_for_user(account_id); + WindowEntry* window_entry = window_to_entry_[window].get(); + window_entry->set_show_for_user(account_id); const bool teleported = !IsWindowOnDesktopOfUser(window, owner); // Show the window if the added user is the current one. if (account_id == current_account_id_) { // Only show the window if it should be shown according to its state. - if (it->second->show()) + if (window_entry->show()) SetWindowVisibility(window, true, kTeleportAnimationTime); } else { SetWindowVisibility(window, false, kTeleportAnimationTime); } // Notify entry change. - if (delegate_) - delegate_->OnOwnerEntryChanged(window, account_id, minimized, teleported); + if (delegate_) { + delegate_->OnOwnerEntryChanged(MapWindowIfNecessary(window), account_id, + minimized, teleported); + } return true; }
diff --git a/ash/multi_user/multi_user_window_manager.h b/ash/multi_user/multi_user_window_manager.h index e336b5d..8420d59 100644 --- a/ash/multi_user/multi_user_window_manager.h +++ b/ash/multi_user/multi_user_window_manager.h
@@ -7,8 +7,6 @@ #include <map> #include <memory> -#include <set> -#include <string> #include "ash/ash_export.h" #include "ash/session/session_observer.h" @@ -64,8 +62,11 @@ // Associates a window with a particular account. This may result in hiding // |window|. This should *not* be called more than once with a different - // account. - void SetWindowOwner(aura::Window* window, const AccountId& account_id); + // account. If |show_for_current_user| is true, this sets the 'shown' + // account to the current account. + void SetWindowOwner(aura::Window* window, + const AccountId& account_id, + bool show_for_current_user); // Sets the 'shown' account for a window. See class description for details on // what the 'shown' account is. This function may trigger changing the active @@ -137,8 +138,8 @@ DISALLOW_COPY_AND_ASSIGN(WindowEntry); }; - // TODO: make map to std::unique_ptr<WindowEntry>. - using WindowToEntryMap = std::map<aura::Window*, WindowEntry*>; + using WindowToEntryMap = + std::map<aura::Window*, std::unique_ptr<WindowEntry>>; const AccountId& GetWindowOwner(aura::Window* window) const;
diff --git a/ash/public/interfaces/BUILD.gn b/ash/public/interfaces/BUILD.gn index d9c4b81..d44aa88 100644 --- a/ash/public/interfaces/BUILD.gn +++ b/ash/public/interfaces/BUILD.gn
@@ -42,6 +42,7 @@ "login_user_info.mojom", "media.mojom", "menu.mojom", + "multi_user_window_manager.mojom", "new_window.mojom", "night_light_controller.mojom", "note_taking_controller.mojom",
diff --git a/ash/public/interfaces/multi_user_window_manager.mojom b/ash/public/interfaces/multi_user_window_manager.mojom new file mode 100644 index 0000000..43060e2 --- /dev/null +++ b/ash/public/interfaces/multi_user_window_manager.mojom
@@ -0,0 +1,22 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module ash.mojom; + +import "components/account_id/interfaces/account_id.mojom"; + +// Used to assign windows to user accounts so that ash shows the appropriate set +// of windows based on the active user. +interface MultiUserWindowManager { + // Associates a window with an account. If |show_for_current_user| is true, + // the window is associated with |account_id|, but is shown for the currently + // active user. + SetWindowOwner(uint64 window_id, + signin.mojom.AccountId account_id, + bool show_for_current_user); + + // Shows a previously registered window for the specified account. + ShowWindowForUser(uint64 window_id, + signin.mojom.AccountId account_id); +};
diff --git a/ash/wm/overview/window_selector.h b/ash/wm/overview/window_selector.h index d1cb05526..d20aece2 100644 --- a/ash/wm/overview/window_selector.h +++ b/ash/wm/overview/window_selector.h
@@ -236,6 +236,8 @@ return split_view_drag_indicators_.get(); } + views::Widget* text_filter_widget() { return text_filter_widget_.get(); } + int text_filter_bottom() const { return text_filter_bottom_; } EnterExitOverviewType enter_exit_overview_type() const {
diff --git a/ash/wm/splitview/split_view_controller.cc b/ash/wm/splitview/split_view_controller.cc index 4a0bc25..c5254a27 100644 --- a/ash/wm/splitview/split_view_controller.cc +++ b/ash/wm/splitview/split_view_controller.cc
@@ -697,7 +697,15 @@ void SplitViewController::OnWindowActivated(ActivationReason reason, aura::Window* gained_active, aura::Window* lost_active) { - DCHECK(IsSplitViewModeActive()); + // This may be called while SnapWindow is still underway because SnapWindow + // will end the overview start animations which will cause the overview text + // filter to be activated. + aura::Window* text_filter_widget = + GetWindowSelector() + ? GetWindowSelector()->text_filter_widget()->GetNativeWindow() + : nullptr; + DCHECK(IsSplitViewModeActive() || + (text_filter_widget && text_filter_widget == gained_active)); // If |gained_active| was activated as a side effect of a window disposition // change, do nothing. For example, when a snapped window is closed, another
diff --git a/ash/ws/multi_user_window_manager_bridge.cc b/ash/ws/multi_user_window_manager_bridge.cc new file mode 100644 index 0000000..fb295855 --- /dev/null +++ b/ash/ws/multi_user_window_manager_bridge.cc
@@ -0,0 +1,53 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/ws/multi_user_window_manager_bridge.h" + +#include "ash/multi_user/multi_user_window_manager.h" +#include "services/ws/window_tree.h" +#include "ui/aura/window.h" + +namespace ash { + +MultiUserWindowManagerBridge::MultiUserWindowManagerBridge( + ws::WindowTree* window_tree, + mojo::ScopedInterfaceEndpointHandle handle) + : window_tree_(window_tree), + binding_(this, + mojo::AssociatedInterfaceRequest<mojom::MultiUserWindowManager>( + std::move(handle))) {} + +MultiUserWindowManagerBridge::~MultiUserWindowManagerBridge() = default; + +void MultiUserWindowManagerBridge::SetWindowOwner(ws::Id window_id, + const AccountId& account_id, + bool show_for_current_user) { + // At this time this is only called once MultiUserWindowManager has been + // created. This needs to be fixed for the multi-process case. + // http://crbug.com/875111. + DCHECK(ash::MultiUserWindowManager::Get()); + aura::Window* window = window_tree_->GetWindowByTransportId(window_id); + if (window && window_tree_->IsTopLevel(window)) { + ash::MultiUserWindowManager::Get()->SetWindowOwner(window, account_id, + show_for_current_user); + } else { + DVLOG(1) << "SetWindowOwner passed invalid window, id=" << window_id; + } +} + +void MultiUserWindowManagerBridge::ShowWindowForUser( + ws::Id window_id, + const AccountId& account_id) { + // At this time this is only called once MultiUserWindowManager has been + // created. This needs to be fixed for the multi-process case. + // http://crbug.com/875111. + DCHECK(ash::MultiUserWindowManager::Get()); + aura::Window* window = window_tree_->GetWindowByTransportId(window_id); + if (window && window_tree_->IsTopLevel(window)) + ash::MultiUserWindowManager::Get()->ShowWindowForUser(window, account_id); + else + DVLOG(1) << "ShowWindowForUser passed invalid window, id=" << window_id; +} + +} // namespace ash
diff --git a/ash/ws/multi_user_window_manager_bridge.h b/ash/ws/multi_user_window_manager_bridge.h new file mode 100644 index 0000000..d74ece57 --- /dev/null +++ b/ash/ws/multi_user_window_manager_bridge.h
@@ -0,0 +1,47 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_WS_MULTI_USER_WINDOW_MANAGER_BRIDGE_H_ +#define ASH_WS_MULTI_USER_WINDOW_MANAGER_BRIDGE_H_ + +#include "ash/public/interfaces/multi_user_window_manager.mojom.h" +#include "mojo/public/cpp/bindings/associated_binding.h" +#include "services/ws/common/types.h" +#include "services/ws/window_manager_interface.h" + +namespace mojo { +class ScopedInterfaceEndpointHandle; +} + +namespace ws { +class WindowTree; +} + +namespace ash { + +// Trivially forwards calls to MultiUserWindowManager. +class MultiUserWindowManagerBridge : public mojom::MultiUserWindowManager, + public ws::WindowManagerInterface { + public: + MultiUserWindowManagerBridge(ws::WindowTree* window_tree, + mojo::ScopedInterfaceEndpointHandle handle); + ~MultiUserWindowManagerBridge() override; + + // mojom::MultiUserWindowManager overrides: + void SetWindowOwner(ws::Id window_id, + const AccountId& account_id, + bool show_for_current_user) override; + void ShowWindowForUser(ws::Id window_id, + const AccountId& account_id) override; + + private: + ws::WindowTree* window_tree_; + mojo::AssociatedBinding<mojom::MultiUserWindowManager> binding_; + + DISALLOW_COPY_AND_ASSIGN(MultiUserWindowManagerBridge); +}; + +} // namespace ash + +#endif // ASH_WS_MULTI_USER_WINDOW_MANAGER_BRIDGE_H_
diff --git a/ash/ws/window_lookup.cc b/ash/ws/window_lookup.cc index 4b3444e..9387bbd5c 100644 --- a/ash/ws/window_lookup.cc +++ b/ash/ws/window_lookup.cc
@@ -18,12 +18,5 @@ ->GetWindowByClientId(transport_id); } -ws::ClientSpecificId GetFirstWindowTreeClientId() { - return Shell::Get() - ->window_service_owner() - ->window_service() - ->GetFirstWindowTreeClientId(); -} - } // namespace window_lookup } // namespace ash
diff --git a/ash/ws/window_lookup.h b/ash/ws/window_lookup.h index 2523a1a..0c1c2c187 100644 --- a/ash/ws/window_lookup.h +++ b/ash/ws/window_lookup.h
@@ -20,10 +20,6 @@ // Returns the aura::Window by transport id. ASH_EXPORT aura::Window* GetWindowByClientId(ws::Id transport_id); -// Returns the id of the first WindowTreeClient. That is, the id assigned to -// the first client that connects to the WindowService. -ASH_EXPORT ws::ClientSpecificId GetFirstWindowTreeClientId(); - } // namespace window_lookup } // namespace ash
diff --git a/ash/ws/window_service_delegate_impl.cc b/ash/ws/window_service_delegate_impl.cc index 3231993a..072c3bf 100644 --- a/ash/ws/window_service_delegate_impl.cc +++ b/ash/ws/window_service_delegate_impl.cc
@@ -16,6 +16,7 @@ #include "ash/wm/window_finder.h" #include "ash/wm/window_util.h" #include "ash/ws/ash_window_manager.h" +#include "ash/ws/multi_user_window_manager_bridge.h" #include "base/bind.h" #include "mojo/public/cpp/bindings/map.h" #include "services/ws/public/mojom/window_manager.mojom.h" @@ -230,10 +231,14 @@ ws::WindowTree* tree, const std::string& name, mojo::ScopedInterfaceEndpointHandle handle) { - if (name != mojom::AshWindowManager::Name_) - return nullptr; + if (name == mojom::AshWindowManager::Name_) + return std::make_unique<AshWindowManager>(tree, std::move(handle)); - return std::make_unique<AshWindowManager>(tree, std::move(handle)); + if (name == mojom::MultiUserWindowManager::Name_) { + return std::make_unique<MultiUserWindowManagerBridge>(tree, + std::move(handle)); + } + return nullptr; } } // namespace ash
diff --git a/base/android/jni_generator/BUILD.gn b/base/android/jni_generator/BUILD.gn index a37726b..6d92eed 100644 --- a/base/android/jni_generator/BUILD.gn +++ b/base/android/jni_generator/BUILD.gn
@@ -80,6 +80,14 @@ ] } +java_cpp_template("processor_args_java") { + package_path = "org/chromium/jni_generator" + sources = [ + "ProcessorArgs.template", + ] + defines = [ "IS_JAVA_DEBUG_VALUE=$is_java_debug" ] +} + java_annotation_processor("jni_processor") { java_files = [ "java/src/org/chromium/jni_generator/JniProcessor.java" ] @@ -93,4 +101,6 @@ "//third_party/auto:auto_service_java", "//third_party/guava:guava_java", ] + + srcjar_deps = [ ":processor_args_java" ] }
diff --git a/base/android/jni_generator/ProcessorArgs.template b/base/android/jni_generator/ProcessorArgs.template new file mode 100644 index 0000000..bbd4c4b --- /dev/null +++ b/base/android/jni_generator/ProcessorArgs.template
@@ -0,0 +1,9 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.jni_generator; + +class ProcessorArgs { + public static final boolean IS_JAVA_DEBUG = IS_JAVA_DEBUG_VALUE; +}
diff --git a/base/android/jni_generator/java/src/org/chromium/jni_generator/JniProcessor.java b/base/android/jni_generator/java/src/org/chromium/jni_generator/JniProcessor.java index 48edf19..4956c65 100644 --- a/base/android/jni_generator/java/src/org/chromium/jni_generator/JniProcessor.java +++ b/base/android/jni_generator/java/src/org/chromium/jni_generator/JniProcessor.java
@@ -75,7 +75,7 @@ private static MessageDigest sNativeMethodHashFunction; // If true, native methods in GEN_JNI will be named as a hash of their descriptor. - private static final boolean USE_HASH_FOR_METHODS = false; + private static final boolean USE_HASH_FOR_METHODS = !ProcessorArgs.IS_JAVA_DEBUG; // Limits the number characters of the Base64 encoded hash // of the method descriptor used as name of the generated
diff --git a/base/android/jni_generator/jni_registration_generator.py b/base/android/jni_generator/jni_registration_generator.py index 45abb511..19e85e4 100755 --- a/base/android/jni_generator/jni_registration_generator.py +++ b/base/android/jni_generator/jni_registration_generator.py
@@ -10,6 +10,7 @@ to register all native methods that exist within an application.""" import argparse +import functools import multiprocessing import os import string @@ -34,7 +35,11 @@ ] -def _Generate(java_file_paths, srcjar_path, header_path=None, namespace=''): +def _Generate(java_file_paths, + srcjar_path, + use_proxy_hash=False, + header_path=None, + namespace=''): """Generates files required to perform JNI registration. Generates a srcjar containing a single class, GEN_JNI, that contains all @@ -53,34 +58,39 @@ # Without multiprocessing, script takes ~13 seconds for chrome_public_apk # on a z620. With multiprocessing, takes ~2 seconds. pool = multiprocessing.Pool() - results = [d for d in pool.imap_unordered(_DictForPath, java_file_paths) if d] + + results = [] + for d in pool.imap_unordered( + functools.partial(_DictForPath, use_proxy_hash=use_proxy_hash), + java_file_paths): + if d: + results.append(d) pool.close() # Sort to make output deterministic. results.sort(key=lambda d: d['FULL_CLASS_NAME']) - if header_path: - combined_dict = {} - for key in MERGEABLE_KEYS: - combined_dict[key] = ''.join(d.get(key, '') for d in results) + combined_dict = {} + for key in MERGEABLE_KEYS: + combined_dict[key] = ''.join(d.get(key, '') for d in results) + if header_path: combined_dict['HEADER_GUARD'] = \ os.path.splitext(header_path)[0].replace('/', '_').upper() + '_' combined_dict['NAMESPACE'] = namespace - header_content = CreateFromDict(combined_dict) with build_utils.AtomicOutput(header_path) as f: f.write(header_content) with build_utils.AtomicOutput(srcjar_path) as f: with zipfile.ZipFile(f, 'w') as srcjar: - # TODO(abenner): Write GEN_JNI.java here. - # build_utils.AddToZipHermetic(srcjar, 'org/chromium/base/GEN_JNI.java', - # data='$CONTENT') - pass + build_utils.AddToZipHermetic( + srcjar, + 'org/chromium/base/natives/GEN_JNI.java', + data=CreateProxyJavaFromDict(combined_dict)) -def _DictForPath(path): +def _DictForPath(path, use_proxy_hash=False): with open(path) as f: contents = jni_generator.RemoveComments(f.read()) if '@JniIgnoreNatives' in contents: @@ -93,7 +103,8 @@ natives += jni_generator.NativeProxyHelpers.ExtractStaticProxyNatives( fully_qualified_class=fully_qualified_class, contents=contents, - ptr_type='long') + ptr_type='long', + use_hash=use_proxy_hash) if len(natives) == 0: return None namespace = jni_generator.ExtractJNINamespace(contents) @@ -516,6 +527,11 @@ default='', help='Namespace to wrap the registration functions ' 'into.') + arg_parser.add_argument( + '--use_proxy_hash', + action='store_true', + help='Enables hashing of the native declaration ' + 'for methods in an @JniNatives interface') args = arg_parser.parse_args(build_utils.ExpandFileArgs(argv[1:])) args.sources_files = build_utils.ParseGnList(args.sources_files) @@ -529,6 +545,7 @@ _Generate( java_file_paths, args.srcjar_path, + use_proxy_hash=args.use_proxy_hash, header_path=args.header_path, namespace=args.namespace)
diff --git a/base/profiler/native_stack_sampler_win.cc b/base/profiler/native_stack_sampler_win.cc index d7d6c31..4fbf4027f 100644 --- a/base/profiler/native_stack_sampler_win.cc +++ b/base/profiler/native_stack_sampler_win.cc
@@ -355,7 +355,8 @@ uintptr_t bottom = 0u; { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cpu_profiler"), "SuspendThread"); + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cpu_profiler.debug"), + "SuspendThread"); { ScopedSuspendThread suspend_thread(thread_handle); @@ -393,7 +394,8 @@ test_delegate->OnPreStackWalk(); { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cpu_profiler"), "RecordStack"); + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cpu_profiler.debug"), + "RecordStack"); RewritePointersToStackMemory(top, bottom, &thread_context, stack_copy_buffer); @@ -452,7 +454,7 @@ std::vector<Frame> NativeStackSamplerWin::RecordStackFrames( StackBuffer* stack_buffer, ProfileBuilder* profile_builder) { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cpu_profiler"), + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cpu_profiler.debug"), "NativeStackSamplerWin::RecordStackFrames"); DCHECK(stack_buffer); @@ -476,7 +478,7 @@ std::vector<Frame> NativeStackSamplerWin::CreateFrames( const std::vector<RecordedFrame>& stack) { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cpu_profiler"), + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cpu_profiler.debug"), "NativeStackSamplerWin::CreateFrames"); std::vector<Frame> frames;
diff --git a/base/trace_event/builtin_categories.h b/base/trace_event/builtin_categories.h index 4cb1748..5572409 100644 --- a/base/trace_event/builtin_categories.h +++ b/base/trace_event/builtin_categories.h
@@ -161,6 +161,7 @@ X(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames")) \ X(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.now")) \ X(TRACE_DISABLED_BY_DEFAULT("cpu_profiler")) \ + X(TRACE_DISABLED_BY_DEFAULT("cpu_profiler.debug")) \ X(TRACE_DISABLED_BY_DEFAULT("devtools.screenshot")) \ X(TRACE_DISABLED_BY_DEFAULT("devtools.timeline")) \ X(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.frame")) \
diff --git a/base/trace_event/category_registry.cc b/base/trace_event/category_registry.cc index 2e4ef47..3002f49f 100644 --- a/base/trace_event/category_registry.cc +++ b/base/trace_event/category_registry.cc
@@ -122,9 +122,9 @@ } // static -bool CategoryRegistry::IsBuiltinCategory(const TraceCategory* category) { +bool CategoryRegistry::IsMetaCategory(const TraceCategory* category) { DCHECK(IsValidCategoryPtr(category)); - return category < &categories_[BuiltinCategories::Size()]; + return category <= kCategoryMetadata; } // static
diff --git a/base/trace_event/category_registry.h b/base/trace_event/category_registry.h index ddf346c98..b820303 100644 --- a/base/trace_event/category_registry.h +++ b/base/trace_event/category_registry.h
@@ -83,7 +83,9 @@ #endif } - static bool IsBuiltinCategory(const TraceCategory*); + // Returns whether |category| points at one of the meta categories that + // shouldn't be displayed in the tracing UI. + static bool IsMetaCategory(const TraceCategory* category); private: friend class TraceCategoryTest;
diff --git a/base/trace_event/trace_category_unittest.cc b/base/trace_event/trace_category_unittest.cc index ed6fda9..eff06f7 100644 --- a/base/trace_event/trace_category_unittest.cc +++ b/base/trace_event/trace_category_unittest.cc
@@ -112,10 +112,10 @@ int num_test_categories_seen = 0; for (const TraceCategory& cat : GetAllCategories()) { if (strcmp(cat.name(), kMetadataName) == 0) - ASSERT_TRUE(CategoryRegistry::IsBuiltinCategory(&cat)); + ASSERT_TRUE(CategoryRegistry::IsMetaCategory(&cat)); if (strncmp(cat.name(), "__test_basic_", 13) == 0) { - ASSERT_FALSE(CategoryRegistry::IsBuiltinCategory(&cat)); + ASSERT_FALSE(CategoryRegistry::IsMetaCategory(&cat)); num_test_categories_seen++; } }
diff --git a/base/trace_event/trace_event_argument.h b/base/trace_event/trace_event_argument.h deleted file mode 100644 index 2d2eb54..0000000 --- a/base/trace_event/trace_event_argument.h +++ /dev/null
@@ -1,11 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_TRACE_EVENT_ARGUMENT_H_ -#define BASE_TRACE_EVENT_TRACE_EVENT_ARGUMENT_H_ - -// TODO(crbug/898787): Update callers to use traced_value.h instead. -#include "base/trace_event/traced_value.h" - -#endif // BASE_TRACE_EVENT_TRACE_EVENT_ARGUMENT_H_
diff --git a/base/trace_event/trace_log.cc b/base/trace_event/trace_log.cc index 998d78e..210b5e6 100644 --- a/base/trace_event/trace_log.cc +++ b/base/trace_event/trace_log.cc
@@ -562,7 +562,7 @@ void TraceLog::GetKnownCategoryGroups( std::vector<std::string>* category_groups) { for (const auto& category : CategoryRegistry::GetAllCategories()) { - if (!CategoryRegistry::IsBuiltinCategory(&category)) + if (!CategoryRegistry::IsMetaCategory(&category)) category_groups->push_back(category.name()); } }
diff --git a/build/android/gyp/create_app_bundle.py b/build/android/gyp/create_app_bundle.py index f3224ba..c787bbd 100755 --- a/build/android/gyp/create_app_bundle.py +++ b/build/android/gyp/create_app_bundle.py
@@ -172,8 +172,7 @@ locales#<language>/<locale>.pak, where <language> is the language code from the locale. - Returns a list of paths. The language split should be duplicated at all the - returned paths. + Returns new path. """ if not src_path.startswith(_LOCALES_SUBDIR) or not src_path.endswith('.pak'): return [src_path] @@ -189,11 +188,16 @@ else: android_language = android_locale - result_paths = ['assets/locales#lang_%s/%s.pak' % (android_language, locale)] if android_language == _FALLBACK_LANGUAGE: - result_paths.append('assets/locales/%s.pak' % locale) + # Fallback language .pak files must be placed in a different directory + # to ensure they are always stored in the base module. + result_path = 'assets/fallback-locales/%s.pak' % locale + else: + # Other language .pak files go into a language-specific asset directory + # that bundletool will store in separate split APKs. + result_path = 'assets/locales#lang_%s/%s.pak' % (android_language, locale) - return result_paths + return result_path def _SplitModuleForAssetTargeting(src_module_zip, tmp_dir, split_dimensions): @@ -230,16 +234,15 @@ src_path = info.filename is_compressed = info.compress_type != zipfile.ZIP_STORED - dst_paths = [src_path] + dst_path = src_path if src_path in language_files: - dst_paths = _RewriteLanguageAssetPath(src_path) + dst_path = _RewriteLanguageAssetPath(src_path) - for dst_path in dst_paths: - build_utils.AddToZipHermetic( - dst_zip, - dst_path, - data=src_zip.read(src_path), - compress=is_compressed) + build_utils.AddToZipHermetic( + dst_zip, + dst_path, + data=src_zip.read(src_path), + compress=is_compressed) return tmp_zip
diff --git a/build/android/lint/suppressions.xml b/build/android/lint/suppressions.xml index 38c2c50..701e77e 100644 --- a/build/android/lint/suppressions.xml +++ b/build/android/lint/suppressions.xml
@@ -271,10 +271,6 @@ <issue id="ResourceType" severity="Error"> <ignore regexp="/javatests/"/> </issue> - <issue id="RedundantNamespace"> - <!-- Please do not add any additional suppressions here with the exception of the 1 file below --> - <ignore regexp="chrome/android/java/res_autofill_assistant/layout/init_screen.xml"/> - </issue> <!-- TODO(crbug.com/831774): Play Services starts complaining about RestrictedApi. Needs investigation --> <issue id="RestrictedApi" severity="ignore"/> <issue id="RtlCompat" severity="ignore"/>
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index 8417916..ea79cb1 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni
@@ -249,6 +249,10 @@ rebase_path(_jni_generator_include, _jni_output_dir), ] + if (!is_java_debug) { + args += [ "--use_proxy_hash" ] + } + if (enable_profiling) { args += [ "--enable_profiling" ] } @@ -435,6 +439,17 @@ "--depfile", rebase_path(depfile, root_build_dir), ] + + if (!is_java_debug) { + args += [ "--use_proxy_hash" ] + } + + if (defined(invoker.exception_files)) { + _rebase_exception_java_files = + rebase_path(invoker.exception_files, root_build_dir) + args += [ "--no_register_java=$_rebase_exception_java_files" ] + } + if (defined(invoker.header_output)) { outputs += [ invoker.header_output ] args += [ @@ -442,11 +457,13 @@ rebase_path(invoker.header_output, root_build_dir), ] } + if (defined(invoker.sources_blacklist)) { _rebase_sources_blacklist = rebase_path(invoker.sources_blacklist, root_build_dir) args += [ "--sources-blacklist=$_rebase_sources_blacklist" ] } + if (defined(invoker.namespace)) { args += [ "--namespace=${invoker.namespace}" ] }
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index 3abf2ce8..b7373bd 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -1cea35ffc58495fc5a3f9913bf8f18109965f873 \ No newline at end of file +426769662771726c2926af9b909376fdd91f79b4 \ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 31c871c..34ff0e6 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -20ae813ac8b9d9aedc7e41502db2c83701be633f \ No newline at end of file +af68fe84f0c46a943568c3ac9045c33e53bf5fba \ No newline at end of file
diff --git a/cc/layers/heads_up_display_layer_impl.cc b/cc/layers/heads_up_display_layer_impl.cc index 0d349e6..1227c14f 100644 --- a/cc/layers/heads_up_display_layer_impl.cc +++ b/cc/layers/heads_up_display_layer_impl.cc
@@ -11,19 +11,13 @@ #include <vector> #include "base/numerics/safe_conversions.h" -#include "base/optional.h" #include "base/single_thread_task_runner.h" +#include "base/stl_util.h" #include "base/strings/stringprintf.h" #include "base/trace_event/process_memory_dump.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/traced_value.h" #include "cc/debug/debug_colors.h" -#include "cc/paint/display_item_list.h" -#include "cc/paint/paint_canvas.h" -#include "cc/paint/paint_flags.h" -#include "cc/paint/paint_shader.h" -#include "cc/paint/record_paint_canvas.h" -#include "cc/paint/skia_paint_canvas.h" #include "cc/raster/scoped_gpu_raster.h" #include "cc/resources/memory_history.h" #include "cc/trees/frame_rate_counter.h" @@ -39,30 +33,28 @@ #include "components/viz/common/resources/platform_color.h" #include "gpu/command_buffer/client/context_support.h" #include "gpu/command_buffer/client/gles2_interface.h" -#include "gpu/command_buffer/client/raster_interface.h" #include "gpu/command_buffer/client/shared_image_interface.h" #include "gpu/command_buffer/common/shared_image_trace_utils.h" #include "gpu/command_buffer/common/shared_image_usage.h" -#include "gpu/config/gpu_feature_info.h" -#include "third_party/skia/include/core/SkFont.h" +#include "skia/ext/platform_canvas.h" +#include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkPaint.h" #include "third_party/skia/include/core/SkPath.h" #include "third_party/skia/include/core/SkTypeface.h" +#include "third_party/skia/include/effects/SkColorMatrixFilter.h" +#include "third_party/skia/include/effects/SkGradientShader.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size_conversions.h" -#include "ui/gfx/skia_util.h" #include "ui/gl/trace_util.h" namespace cc { -namespace { - -PaintFlags CreatePaintFlags() { - PaintFlags flags; +static inline SkPaint CreatePaint() { + SkPaint paint; #if (SK_R32_SHIFT || SK_B32_SHIFT != 16) - // The PaintCanvas is in RGBA but the shader is expecting BGRA, so we need to - // swizzle our colors when drawing to the PaintCanvas. + // The SkCanvas is in RGBA but the shader is expecting BGRA, so we need to + // swizzle our colors when drawing to the SkCanvas. SkScalar color_matrix[20]; for (int i = 0; i < 20; ++i) color_matrix[i] = 0; @@ -71,39 +63,12 @@ color_matrix[2 + 5 * 0] = 1; color_matrix[3 + 5 * 3] = 1; - flags.setColorFilter( + paint.setColorFilter( SkColorFilter::MakeMatrixFilterRowMajor255(color_matrix)); #endif - return flags; + return paint; } -void DrawArc(PaintCanvas* canvas, - const SkRect& oval, - SkScalar start_angle, - SkScalar sweep_angle, - const PaintFlags& flags) { - DCHECK_GT(sweep_angle, 0.f); - DCHECK_LT(sweep_angle, 360.f); - SkPath path; - path.moveTo(oval.centerX(), oval.centerY()); - path.arcTo(oval, start_angle, sweep_angle, false /* forceMoveTo */); - path.close(); - canvas->drawPath(path, flags); -} - -class DummyImageProvider : public ImageProvider { - public: - DummyImageProvider() = default; - ~DummyImageProvider() override = default; - ScopedDecodedDrawImage GetDecodedDrawImage( - const DrawImage& draw_image) override { - NOTREACHED(); - return ScopedDecodedDrawImage(); - } -}; - -} // namespace - HeadsUpDisplayLayerImpl::Graph::Graph(double indicator_value, double start_upper_bound) : value(0.0), @@ -125,9 +90,7 @@ internal_contents_scale_(1.f), fps_graph_(60.0, 80.0), paint_time_graph_(16.0, 48.0), - fade_step_(0), - raster_color_space_(gfx::ColorSpace::CreateSRGB(), - gfx::ColorSpace::GetNextId()) {} + fade_step_(0) {} HeadsUpDisplayLayerImpl::~HeadsUpDisplayLayerImpl() { ReleaseResources(); @@ -143,10 +106,11 @@ ~HudGpuBacking() override { if (mailbox.IsZero()) return; + auto* sii = compositor_context_provider->SharedImageInterface(); if (returned_sync_token.HasData()) - shared_image_interface->DestroySharedImage(returned_sync_token, mailbox); + sii->DestroySharedImage(returned_sync_token, mailbox); else if (mailbox_sync_token.HasData()) - shared_image_interface->DestroySharedImage(mailbox_sync_token, mailbox); + sii->DestroySharedImage(mailbox_sync_token, mailbox); } void OnMemoryDump( @@ -162,7 +126,7 @@ pmd->AddOwnershipEdge(buffer_dump_guid, tracing_guid, importance); } - gpu::SharedImageInterface* shared_image_interface = nullptr; + viz::ContextProvider* compositor_context_provider; }; class HudSoftwareBacking : public ResourcePool::SoftwareBacking { @@ -234,33 +198,14 @@ // Update state that will be drawn. UpdateHudContents(); - // TODO(penghuang): Do not use worker_context_provider() when context_provider - // is changed to RasterContextProvider. - // https://crbug.com/c/1286950 - auto* raster_context_provider = - gpu_raster ? layer_tree_frame_sink->worker_context_provider() : nullptr; - base::Optional<viz::RasterContextProvider::ScopedRasterContextLock> lock; - bool use_oopr = false; - if (raster_context_provider) { - lock.emplace(raster_context_provider); - use_oopr = raster_context_provider->GetGpuFeatureInfo() - .status_values[gpu::GPU_FEATURE_TYPE_GPU_RASTERIZATION] == - gpu::kGpuFeatureStatusEnabled; - if (!use_oopr) { - raster_context_provider = nullptr; - lock.reset(); - } - } - - auto* context_provider = layer_tree_frame_sink->context_provider(); if (!pool_) { scoped_refptr<base::SingleThreadTaskRunner> task_runner = layer_tree_impl()->task_runner_provider()->HasImplThread() ? layer_tree_impl()->task_runner_provider()->ImplThreadTaskRunner() : layer_tree_impl()->task_runner_provider()->MainThreadTaskRunner(); pool_ = std::make_unique<ResourcePool>( - resource_provider, context_provider, std::move(task_runner), - ResourcePool::kDefaultExpirationDelay, + resource_provider, layer_tree_frame_sink->context_provider(), + std::move(task_runner), ResourcePool::kDefaultExpirationDelay, layer_tree_impl()->settings().disallow_non_exact_resource_reuse); } @@ -275,58 +220,39 @@ // compositing. ResourcePool::InUsePoolResource pool_resource; if (draw_mode == DRAW_MODE_HARDWARE) { - DCHECK(raster_context_provider || context_provider); - const auto& caps = raster_context_provider - ? raster_context_provider->ContextCapabilities() - : context_provider->ContextCapabilities(); + viz::ContextProvider* context_provider = + layer_tree_impl()->context_provider(); + DCHECK(context_provider); + viz::ResourceFormat format = - viz::PlatformColor::BestSupportedRenderBufferFormat(caps); + viz::PlatformColor::BestSupportedRenderBufferFormat( + context_provider->ContextCapabilities()); pool_resource = pool_->AcquireResource(internal_content_bounds_, format, gfx::ColorSpace()); if (!pool_resource.gpu_backing()) { auto backing = std::make_unique<HudGpuBacking>(); - auto* sii = raster_context_provider - ? raster_context_provider->SharedImageInterface() - : context_provider->SharedImageInterface(); - backing->shared_image_interface = sii; + backing->compositor_context_provider = context_provider; backing->InitOverlayCandidateAndTextureTarget( - pool_resource.format(), caps, + pool_resource.format(), context_provider->ContextCapabilities(), layer_tree_impl() ->settings() .resource_settings.use_gpu_memory_buffer_resources); - - uint32_t flags = 0; - if (use_oopr) { - flags = gpu::SHARED_IMAGE_USAGE_RASTER | - gpu::SHARED_IMAGE_USAGE_OOP_RASTERIZATION; - } else if (gpu_raster) { - flags = gpu::SHARED_IMAGE_USAGE_GLES2 | - gpu::SHARED_IMAGE_USAGE_GLES2_FRAMEBUFFER_HINT; - } + auto* sii = context_provider->SharedImageInterface(); + uint32_t flags = gpu::SHARED_IMAGE_USAGE_GLES2; + if (gpu_raster) + flags |= gpu::SHARED_IMAGE_USAGE_GLES2_FRAMEBUFFER_HINT; if (backing->overlay_candidate) flags |= gpu::SHARED_IMAGE_USAGE_SCANOUT; backing->mailbox = sii->CreateSharedImage(pool_resource.format(), pool_resource.size(), pool_resource.color_space(), flags); - if (raster_context_provider) { - auto* ri = raster_context_provider->RasterInterface(); - ri->WaitSyncTokenCHROMIUM(sii->GenUnverifiedSyncToken().GetConstData()); - } else { - auto* gl = context_provider->ContextGL(); - gl->WaitSyncTokenCHROMIUM(sii->GenUnverifiedSyncToken().GetConstData()); - } + gpu::gles2::GLES2Interface* gl = context_provider->ContextGL(); + gl->WaitSyncTokenCHROMIUM(sii->GenUnverifiedSyncToken().GetConstData()); pool_resource.set_gpu_backing(std::move(backing)); } else if (pool_resource.gpu_backing()->returned_sync_token.HasData()) { - if (raster_context_provider) { - auto* ri = raster_context_provider->RasterInterface(); - ri->WaitSyncTokenCHROMIUM( - pool_resource.gpu_backing()->returned_sync_token.GetConstData()); - } else { - auto* gl = context_provider->ContextGL(); - gl->WaitSyncTokenCHROMIUM( - pool_resource.gpu_backing()->returned_sync_token.GetConstData()); - } + context_provider->ContextGL()->WaitSyncTokenCHROMIUM( + pool_resource.gpu_backing()->returned_sync_token.GetConstData()); pool_resource.gpu_backing()->returned_sync_token = gpu::SyncToken(); } } else { @@ -359,60 +285,29 @@ DCHECK_EQ(draw_mode, DRAW_MODE_HARDWARE); DCHECK(pool_resource.gpu_backing()); auto* backing = static_cast<HudGpuBacking*>(pool_resource.gpu_backing()); + viz::ContextProvider* context_provider = + layer_tree_impl()->context_provider(); + gpu::gles2::GLES2Interface* gl = context_provider->ContextGL(); + GLuint mailbox_texture_id = + gl->CreateAndConsumeTextureCHROMIUM(backing->mailbox.name); - if (use_oopr) { - const auto& size = pool_resource.size(); - auto display_item_list = base::MakeRefCounted<DisplayItemList>( - DisplayItemList::kTopLevelDisplayItemList); - RecordPaintCanvas canvas(display_item_list.get(), - SkRect::MakeIWH(size.width(), size.height())); - display_item_list->StartPaint(); - DrawHudContents(&canvas); - display_item_list->EndPaintOfUnpaired(gfx::Rect(size)); - display_item_list->Finalize(); - - auto* ri = raster_context_provider->RasterInterface(); - constexpr GLuint background_color = SkColorSetARGB(0, 0, 0, 0); - constexpr GLuint msaa_sample_count = -1; - constexpr bool can_use_lcd_text = true; - const auto pixel_config = viz::ResourceFormatToClosestSkColorType( - true /* gpu_compositing */, pool_resource.format()); - ri->BeginRasterCHROMIUM(background_color, msaa_sample_count, - can_use_lcd_text, pixel_config, - raster_color_space_, backing->mailbox.name); - gfx::Vector2dF post_translate(0.f, 0.f); - DummyImageProvider image_provider; - ri->RasterCHROMIUM(display_item_list.get(), &image_provider, size, - gfx::Rect(size), gfx::Rect(size), post_translate, - 1.f /* post_scale */, false /* requires_clear */); - ri->EndRasterCHROMIUM(); - backing->mailbox_sync_token = - viz::ClientResourceProvider::GenerateSyncTokenHelper(ri); - } else { - auto* gl = context_provider->ContextGL(); - GLuint mailbox_texture_id = - gl->CreateAndConsumeTextureCHROMIUM(backing->mailbox.name); - - { - ScopedGpuRaster gpu_raster(context_provider); - viz::ClientResourceProvider::ScopedSkSurface scoped_surface( - context_provider->GrContext(), mailbox_texture_id, - backing->texture_target, pool_resource.size(), - pool_resource.format(), false /* can_use_lcd_text */, - 0 /* msaa_sample_count */); - SkSurface* surface = scoped_surface.surface(); - if (!surface) { - pool_->ReleaseResource(std::move(pool_resource)); - return; - } - SkiaPaintCanvas canvas(surface->getCanvas()); - DrawHudContents(&canvas); + { + ScopedGpuRaster gpu_raster(context_provider); + viz::ClientResourceProvider::ScopedSkSurface scoped_surface( + context_provider->GrContext(), mailbox_texture_id, + backing->texture_target, pool_resource.size(), pool_resource.format(), + false /* can_use_lcd_text */, 0 /* msaa_sample_count */); + SkSurface* surface = scoped_surface.surface(); + if (!surface) { + pool_->ReleaseResource(std::move(pool_resource)); + return; } - - gl->DeleteTextures(1, &mailbox_texture_id); - backing->mailbox_sync_token = - viz::ClientResourceProvider::GenerateSyncTokenHelper(gl); + DrawHudContents(surface->getCanvas()); } + + gl->DeleteTextures(1, &mailbox_texture_id); + backing->mailbox_sync_token = + viz::ClientResourceProvider::GenerateSyncTokenHelper(gl); } else if (draw_mode == DRAW_MODE_HARDWARE) { // If not using |gpu_raster| but using gpu compositing, we DrawHudContents() // into a software bitmap and upload it to a texture for compositing. @@ -429,8 +324,7 @@ pool_resource.size().width(), pool_resource.size().height()); } - SkiaPaintCanvas canvas(staging_surface_->getCanvas()); - DrawHudContents(&canvas); + DrawHudContents(staging_surface_->getCanvas()); TRACE_EVENT0("cc", "UploadHudTexture"); SkPixmap pixmap; @@ -460,8 +354,7 @@ sk_sp<SkSurface> surface = SkSurface::MakeRasterDirect( info, backing->shared_memory->memory(), info.minRowBytes()); - SkiaPaintCanvas canvas(surface->getCanvas()); - DrawHudContents(&canvas); + DrawHudContents(surface->getCanvas()); } // Exports the backing to the ResourceProvider, giving it a ResourceId that @@ -564,7 +457,7 @@ paint_time_graph_.UpdateUpperBound(); } -void HeadsUpDisplayLayerImpl::DrawHudContents(PaintCanvas* canvas) { +void HeadsUpDisplayLayerImpl::DrawHudContents(SkCanvas* canvas) { const LayerTreeDebugState& debug_state = layer_tree_impl()->debug_state(); TRACE_EVENT0("cc", "DrawHudContents"); @@ -594,74 +487,94 @@ canvas->restore(); } +int HeadsUpDisplayLayerImpl::MeasureText(SkPaint* paint, + const std::string& text, + int size) const { + DCHECK(typeface_.get()); + const bool anti_alias = paint->isAntiAlias(); + paint->setAntiAlias(true); + paint->setTextSize(size); + paint->setTypeface(typeface_); + SkScalar text_width = paint->measureText(text.c_str(), text.length()); -void HeadsUpDisplayLayerImpl::DrawText(PaintCanvas* canvas, - PaintFlags* flags, + paint->setAntiAlias(anti_alias); + return SkScalarCeilToInt(text_width); +} +void HeadsUpDisplayLayerImpl::DrawText(SkCanvas* canvas, + SkPaint* paint, const std::string& text, TextAlign align, int size, int x, int y) const { DCHECK(typeface_.get()); - flags->setAntiAlias(true); - flags->setTextSize(size); - flags->setTypeface(typeface_); - if (align == TextAlign::kCenter) { - auto width = flags->ToSkPaint().measureText(text.c_str(), text.length()); - x -= width * 0.5f; - } else if (align == TextAlign::kRight) { - auto width = flags->ToSkPaint().measureText(text.c_str(), text.length()); - x -= width; - } - auto sk_paint = flags->ToSkPaint(); + const bool anti_alias = paint->isAntiAlias(); + paint->setAntiAlias(true); - auto text_blob = SkTextBlob::MakeFromText( - text.c_str(), text.length(), - SkFont(sk_paint.refTypeface(), sk_paint.getTextSize())); - canvas->drawTextBlob(std::move(text_blob), x, y, *flags); + paint->setTextSize(size); + paint->setTypeface(typeface_); + + if (align != TextAlign::kLeft) { + SkScalar width = paint->measureText(text.c_str(), text.length(), nullptr); + if (align == TextAlign::kCenter) { + x -= width * 0.5f; + } else { + DCHECK_EQ(align, TextAlign::kRight); + x -= width; + } + } + canvas->drawText(text.c_str(), text.length(), x, y, *paint); + + paint->setAntiAlias(anti_alias); } -void HeadsUpDisplayLayerImpl::DrawText(PaintCanvas* canvas, - PaintFlags* flags, +void HeadsUpDisplayLayerImpl::DrawText(SkCanvas* canvas, + SkPaint* paint, const std::string& text, TextAlign align, int size, const SkPoint& pos) const { - DrawText(canvas, flags, text, align, size, pos.x(), pos.y()); + DrawText(canvas, paint, text, align, size, pos.x(), pos.y()); } -void HeadsUpDisplayLayerImpl::DrawGraphBackground(PaintCanvas* canvas, - PaintFlags* flags, +void HeadsUpDisplayLayerImpl::DrawGraphBackground(SkCanvas* canvas, + SkPaint* paint, const SkRect& bounds) const { - flags->setColor(DebugColors::HUDBackgroundColor()); - canvas->drawRect(bounds, *flags); + paint->setColor(DebugColors::HUDBackgroundColor()); + canvas->drawRect(bounds, *paint); } -void HeadsUpDisplayLayerImpl::DrawGraphLines(PaintCanvas* canvas, - PaintFlags* flags, +void HeadsUpDisplayLayerImpl::DrawGraphLines(SkCanvas* canvas, + SkPaint* paint, const SkRect& bounds, const Graph& graph) const { // Draw top and bottom line. - flags->setColor(DebugColors::HUDSeparatorLineColor()); - canvas->drawLine(bounds.left(), bounds.top() - 1, bounds.right(), - bounds.top() - 1, *flags); - canvas->drawLine(bounds.left(), bounds.bottom(), bounds.right(), - bounds.bottom(), *flags); + paint->setColor(DebugColors::HUDSeparatorLineColor()); + canvas->drawLine(bounds.left(), + bounds.top() - 1, + bounds.right(), + bounds.top() - 1, + *paint); + canvas->drawLine( + bounds.left(), bounds.bottom(), bounds.right(), bounds.bottom(), *paint); // Draw indicator line (additive blend mode to increase contrast when drawn on // top of graph). - flags->setColor(DebugColors::HUDIndicatorLineColor()); - flags->setBlendMode(SkBlendMode::kPlus); + paint->setColor(DebugColors::HUDIndicatorLineColor()); + paint->setBlendMode(SkBlendMode::kPlus); const double indicator_top = bounds.height() * (1.0 - graph.indicator / graph.current_upper_bound) - 1.0; - canvas->drawLine(bounds.left(), bounds.top() + indicator_top, bounds.right(), - bounds.top() + indicator_top, *flags); - flags->setBlendMode(SkBlendMode::kSrcOver); + canvas->drawLine(bounds.left(), + bounds.top() + indicator_top, + bounds.right(), + bounds.top() + indicator_top, + *paint); + paint->setBlendMode(SkBlendMode::kSrcOver); } SkRect HeadsUpDisplayLayerImpl::DrawFPSDisplay( - PaintCanvas* canvas, + SkCanvas* canvas, const FrameRateCounter* fps_counter, int right, int top) const { @@ -682,8 +595,8 @@ int left = bounds().width() - width - right; SkRect area = SkRect::MakeXYWH(left, top, width, height); - PaintFlags flags = CreatePaintFlags(); - DrawGraphBackground(canvas, &flags, area); + SkPaint paint = CreatePaint(); + DrawGraphBackground(canvas, &paint, area); SkRect title_bounds = SkRect::MakeXYWH( left + kPadding, top + kPadding, kGraphWidth + kHistogramWidth + kGap + 2, @@ -708,17 +621,17 @@ VLOG(1) << value_text; - flags.setColor(DebugColors::HUDTitleColor()); - DrawText(canvas, &flags, title, TextAlign::kLeft, kTitleFontHeight, + paint.setColor(DebugColors::HUDTitleColor()); + DrawText(canvas, &paint, title, TextAlign::kLeft, kTitleFontHeight, title_bounds.left(), title_bounds.bottom()); - flags.setColor(DebugColors::FPSDisplayTextAndGraphColor()); - DrawText(canvas, &flags, value_text, TextAlign::kLeft, kFontHeight, + paint.setColor(DebugColors::FPSDisplayTextAndGraphColor()); + DrawText(canvas, &paint, value_text, TextAlign::kLeft, kFontHeight, text_bounds.left(), text_bounds.bottom()); - DrawText(canvas, &flags, min_max_text, TextAlign::kRight, kFontHeight, + DrawText(canvas, &paint, min_max_text, TextAlign::kRight, kFontHeight, text_bounds.right(), text_bounds.bottom()); - DrawGraphLines(canvas, &flags, graph_bounds, fps_graph_); + DrawGraphLines(canvas, &paint, graph_bounds, fps_graph_); // Collect graph and histogram data. SkPath path; @@ -761,15 +674,19 @@ } // Draw FPS histogram. - flags.setColor(DebugColors::HUDSeparatorLineColor()); - canvas->drawLine(histogram_bounds.left() - 1, histogram_bounds.top() - 1, - histogram_bounds.left() - 1, histogram_bounds.bottom() + 1, - flags); - canvas->drawLine(histogram_bounds.right() + 1, histogram_bounds.top() - 1, - histogram_bounds.right() + 1, histogram_bounds.bottom() + 1, - flags); + paint.setColor(DebugColors::HUDSeparatorLineColor()); + canvas->drawLine(histogram_bounds.left() - 1, + histogram_bounds.top() - 1, + histogram_bounds.left() - 1, + histogram_bounds.bottom() + 1, + paint); + canvas->drawLine(histogram_bounds.right() + 1, + histogram_bounds.top() - 1, + histogram_bounds.right() + 1, + histogram_bounds.bottom() + 1, + paint); - flags.setColor(DebugColors::FPSDisplayTextAndGraphColor()); + paint.setColor(DebugColors::FPSDisplayTextAndGraphColor()); const double bar_height = histogram_bounds.height() / kHistogramSize; for (int i = kHistogramSize - 1; i >= 0; --i) { @@ -779,21 +696,22 @@ canvas->drawRect( SkRect::MakeXYWH(histogram_bounds.left(), histogram_bounds.bottom() - (i + 1) * bar_height, - bar_width, 1), - flags); + bar_width, + 1), + paint); } } // Draw FPS graph. - flags.setAntiAlias(true); - flags.setStyle(PaintFlags::kStroke_Style); - flags.setStrokeWidth(1); - canvas->drawPath(path, flags); + paint.setAntiAlias(true); + paint.setStyle(SkPaint::kStroke_Style); + paint.setStrokeWidth(1); + canvas->drawPath(path, paint); return area; } -SkRect HeadsUpDisplayLayerImpl::DrawMemoryDisplay(PaintCanvas* canvas, +SkRect HeadsUpDisplayLayerImpl::DrawMemoryDisplay(SkCanvas* canvas, int right, int top, int width) const { @@ -807,8 +725,8 @@ const double kMegabyte = 1024.0 * 1024.0; - PaintFlags flags = CreatePaintFlags(); - DrawGraphBackground(canvas, &flags, area); + SkPaint paint = CreatePaint(); + DrawGraphBackground(canvas, &paint, area); SkPoint title_pos = SkPoint::Make(left + kPadding, top + kFontHeight + kPadding); @@ -817,32 +735,31 @@ SkPoint stat2_pos = SkPoint::Make(left + width - kPadding - 1, top + 2 * kPadding + 3 * kFontHeight); - flags.setColor(DebugColors::HUDTitleColor()); - DrawText(canvas, &flags, "GPU Memory", TextAlign::kLeft, kTitleFontHeight, + paint.setColor(DebugColors::HUDTitleColor()); + DrawText(canvas, &paint, "GPU Memory", TextAlign::kLeft, kTitleFontHeight, title_pos); - flags.setColor(DebugColors::MemoryDisplayTextColor()); + paint.setColor(DebugColors::MemoryDisplayTextColor()); std::string text = base::StringPrintf( "%6.1f MB used", memory_entry_.total_bytes_used / kMegabyte); - DrawText(canvas, &flags, text, TextAlign::kRight, kFontHeight, stat1_pos); + DrawText(canvas, &paint, text, TextAlign::kRight, kFontHeight, stat1_pos); if (!memory_entry_.had_enough_memory) - flags.setColor(SK_ColorRED); + paint.setColor(SK_ColorRED); text = base::StringPrintf("%6.1f MB max ", memory_entry_.total_budget_in_bytes / kMegabyte); - - DrawText(canvas, &flags, text, TextAlign::kRight, kFontHeight, stat2_pos); + DrawText(canvas, &paint, text, TextAlign::kRight, kFontHeight, stat2_pos); // Draw memory graph. int length = 2 * kFontHeight + kPadding + 12; SkRect oval = SkRect::MakeXYWH(left + kPadding * 6, top + kTitleFontHeight + kPadding * 3, length, length); - flags.setAntiAlias(true); - flags.setStyle(PaintFlags::kFill_Style); + paint.setAntiAlias(true); + paint.setStyle(SkPaint::kFill_Style); - flags.setColor(SkColorSetARGB(64, 255, 255, 0)); - DrawArc(canvas, oval, 180, 180, flags); + paint.setColor(SkColorSetARGB(64, 255, 255, 0)); + canvas->drawArc(oval, 180, 180, true, paint); int radius = length / 2; int cx = oval.left() + radius; @@ -856,25 +773,24 @@ const SkScalar pos[] = {SkFloatToScalar(0.2f), SkFloatToScalar(0.4f), SkFloatToScalar(0.6f), SkFloatToScalar(0.8f), SkFloatToScalar(1.0f)}; - flags.setShader(PaintShader::MakeSweepGradient( - cx, cy, colors, pos, 5, SkShader::kClamp_TileMode, 0, 360)); - flags.setAntiAlias(true); + paint.setShader(SkGradientShader::MakeSweep(cx, cy, colors, pos, 5)); + paint.setFlags(SkPaint::kAntiAlias_Flag); // Draw current status. - flags.setStyle(PaintFlags::kStroke_Style); - flags.setAlpha(32); - flags.setStrokeWidth(4); - DrawArc(canvas, oval, 180, angle, flags); + paint.setStyle(SkPaint::kStroke_Style); + paint.setAlpha(32); + paint.setStrokeWidth(4); + canvas->drawArc(oval, 180, angle, true, paint); - flags.setStyle(PaintFlags::kFill_Style); - flags.setColor(SkColorSetARGB(255, 0, 255, 0)); - DrawArc(canvas, oval, 180, angle, flags); - flags.setShader(nullptr); + paint.setStyle(SkPaint::kFill_Style); + paint.setColor(SkColorSetARGB(255, 0, 255, 0)); + canvas->drawArc(oval, 180, angle, true, paint); + paint.setShader(nullptr); return area; } -SkRect HeadsUpDisplayLayerImpl::DrawGpuRasterizationStatus(PaintCanvas* canvas, +SkRect HeadsUpDisplayLayerImpl::DrawGpuRasterizationStatus(SkCanvas* canvas, int right, int top, int width) const { @@ -914,24 +830,24 @@ const int left = bounds().width() - width - right; const SkRect area = SkRect::MakeXYWH(left, top, width, height); - PaintFlags flags = CreatePaintFlags(); - DrawGraphBackground(canvas, &flags, area); + SkPaint paint = CreatePaint(); + DrawGraphBackground(canvas, &paint, area); SkPoint gpu_status_pos = SkPoint::Make(left + width - kPadding, top + 2 * kFontHeight + 2 * kPadding); - flags.setColor(DebugColors::HUDTitleColor()); - DrawText(canvas, &flags, "GPU Raster", TextAlign::kLeft, kTitleFontHeight, + paint.setColor(DebugColors::HUDTitleColor()); + DrawText(canvas, &paint, "GPU Raster", TextAlign::kLeft, kTitleFontHeight, left + kPadding, top + kFontHeight + kPadding); - flags.setColor(color); - DrawText(canvas, &flags, status, TextAlign::kRight, kFontHeight, + paint.setColor(color); + DrawText(canvas, &paint, status, TextAlign::kRight, kFontHeight, gpu_status_pos); return area; } void HeadsUpDisplayLayerImpl::DrawDebugRect( - PaintCanvas* canvas, - PaintFlags* flags, + SkCanvas* canvas, + SkPaint* paint, const DebugRect& rect, SkColor stroke_color, SkColor fill_color, @@ -942,14 +858,14 @@ gfx::ScaleToEnclosingRect(rect.rect, 1.0 / internal_contents_scale_, 1.0 / internal_contents_scale_); SkIRect sk_rect = RectToSkIRect(debug_layer_rect); - flags->setColor(fill_color); - flags->setStyle(PaintFlags::kFill_Style); - canvas->drawIRect(sk_rect, *flags); + paint->setColor(fill_color); + paint->setStyle(SkPaint::kFill_Style); + canvas->drawIRect(sk_rect, *paint); - flags->setColor(stroke_color); - flags->setStyle(PaintFlags::kStroke_Style); - flags->setStrokeWidth(SkFloatToScalar(stroke_width)); - canvas->drawIRect(sk_rect, *flags); + paint->setColor(stroke_color); + paint->setStyle(SkPaint::kStroke_Style); + paint->setStrokeWidth(SkFloatToScalar(stroke_width)); + canvas->drawIRect(sk_rect, *paint); if (label_text.length()) { const int kFontHeight = 12; @@ -965,29 +881,33 @@ canvas->clipRect(sk_clip_rect); canvas->translate(sk_clip_rect.x(), sk_clip_rect.y()); - PaintFlags label_flags = CreatePaintFlags(); - label_flags.setTextSize(kFontHeight); - label_flags.setTypeface(typeface_); - label_flags.setColor(stroke_color); + SkPaint label_paint = CreatePaint(); + label_paint.setTextSize(kFontHeight); + label_paint.setTypeface(typeface_); + label_paint.setColor(stroke_color); - const SkScalar label_text_width = label_flags.ToSkPaint().measureText( - label_text.c_str(), label_text.length()); + const SkScalar label_text_width = + label_paint.measureText(label_text.c_str(), label_text.length()); canvas->drawRect(SkRect::MakeWH(label_text_width + 2 * kPadding, kFontHeight + 2 * kPadding), - label_flags); + label_paint); - label_flags.setAntiAlias(true); - label_flags.setColor(SkColorSetARGB(255, 50, 50, 50)); - DrawText(canvas, &label_flags, label_text, TextAlign::kLeft, kFontHeight, - kPadding, kFontHeight * 0.8f + kPadding); + label_paint.setAntiAlias(true); + label_paint.setColor(SkColorSetARGB(255, 50, 50, 50)); + canvas->drawText(label_text.c_str(), + label_text.length(), + kPadding, + kFontHeight * 0.8f + kPadding, + label_paint); + canvas->restore(); } } void HeadsUpDisplayLayerImpl::DrawDebugRects( - PaintCanvas* canvas, + SkCanvas* canvas, DebugRectHistory* debug_rect_history) { - PaintFlags flags = CreatePaintFlags(); + SkPaint paint = CreatePaint(); const std::vector<DebugRect>& debug_rects = debug_rect_history->debug_rects(); std::vector<DebugRect> new_paint_rects; @@ -1050,8 +970,13 @@ break; } - DrawDebugRect(canvas, &flags, debug_rects[i], stroke_color, fill_color, - stroke_width, label_text); + DrawDebugRect(canvas, + &paint, + debug_rects[i], + stroke_color, + fill_color, + stroke_width, + label_text); } if (new_paint_rects.size()) { @@ -1061,10 +986,13 @@ if (fade_step_ > 0) { fade_step_--; for (size_t i = 0; i < paint_rects_.size(); ++i) { - DrawDebugRect(canvas, &flags, paint_rects_[i], + DrawDebugRect(canvas, + &paint, + paint_rects_[i], DebugColors::PaintRectBorderColor(fade_step_), DebugColors::PaintRectFillColor(fade_step_), - DebugColors::PaintRectBorderWidth(), ""); + DebugColors::PaintRectBorderWidth(), + ""); } } }
diff --git a/cc/layers/heads_up_display_layer_impl.h b/cc/layers/heads_up_display_layer_impl.h index 9a97dae..a7e3c1a9 100644 --- a/cc/layers/heads_up_display_layer_impl.h +++ b/cc/layers/heads_up_display_layer_impl.h
@@ -14,12 +14,13 @@ #include "base/time/time.h" #include "cc/cc_export.h" #include "cc/layers/layer_impl.h" -#include "cc/paint/color_space_transfer_cache_entry.h" #include "cc/resources/memory_history.h" #include "cc/resources/resource_pool.h" #include "cc/trees/debug_rect_history.h" #include "third_party/skia/include/core/SkRefCnt.h" +class SkCanvas; +class SkPaint; class SkTypeface; struct SkRect; @@ -30,8 +31,6 @@ namespace cc { class FrameRateCounter; class LayerTreeFrameSink; -class PaintCanvas; -class PaintFlags; enum class TextAlign { kLeft, kCenter, kRight }; @@ -96,49 +95,50 @@ void AsValueInto(base::trace_event::TracedValue* dict) const override; void UpdateHudContents(); - void DrawHudContents(PaintCanvas* canvas); - void DrawText(PaintCanvas* canvas, - PaintFlags* flags, + void DrawHudContents(SkCanvas* canvas); + + int MeasureText(SkPaint* paint, const std::string& text, int size) const; + void DrawText(SkCanvas* canvas, + SkPaint* paint, const std::string& text, TextAlign align, int size, int x, int y) const; - void DrawText(PaintCanvas* canvas, - PaintFlags* flags, + void DrawText(SkCanvas* canvas, + SkPaint* paint, const std::string& text, TextAlign align, int size, const SkPoint& pos) const; - void DrawGraphBackground(PaintCanvas* canvas, - PaintFlags* flags, + void DrawGraphBackground(SkCanvas* canvas, + SkPaint* paint, const SkRect& bounds) const; - void DrawGraphLines(PaintCanvas* canvas, - PaintFlags* flags, + void DrawGraphLines(SkCanvas* canvas, + SkPaint* paint, const SkRect& bounds, const Graph& graph) const; - SkRect DrawFPSDisplay(PaintCanvas* canvas, + SkRect DrawFPSDisplay(SkCanvas* canvas, const FrameRateCounter* fps_counter, int right, int top) const; - SkRect DrawMemoryDisplay(PaintCanvas* canvas, + SkRect DrawMemoryDisplay(SkCanvas* canvas, int top, int right, int width) const; - SkRect DrawGpuRasterizationStatus(PaintCanvas* canvas, + SkRect DrawGpuRasterizationStatus(SkCanvas* canvas, int right, int top, int width) const; - void DrawDebugRect(PaintCanvas* canvas, - PaintFlags* flags, + void DrawDebugRect(SkCanvas* canvas, + SkPaint* paint, const DebugRect& rect, SkColor stroke_color, SkColor fill_color, float stroke_width, const std::string& label_text) const; - void DrawDebugRects(PaintCanvas* canvas, - DebugRectHistory* debug_rect_history); + void DrawDebugRects(SkCanvas* canvas, DebugRectHistory* debug_rect_history); ResourcePool::InUsePoolResource in_flight_resource_; std::unique_ptr<ResourcePool> pool_; @@ -159,9 +159,6 @@ base::TimeTicks time_of_last_graph_update_; - // color space for OOPR - const RasterColorSpace raster_color_space_; - DISALLOW_COPY_AND_ASSIGN(HeadsUpDisplayLayerImpl); };
diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml index 18b4a171..01c213bc 100644 --- a/chrome/android/java/AndroidManifest.xml +++ b/chrome/android/java/AndroidManifest.xml
@@ -1107,6 +1107,9 @@ </intent-filter> </receiver> + <receiver android:name="org.chromium.chrome.browser.notifications.NotificationIntentInterceptor$Receiver" + android:exported="false"/> + <receiver android:name="org.chromium.chrome.browser.ntp.ContentSuggestionsNotifier$OpenUrlReceiver" android:exported="false"/> <receiver android:name="org.chromium.chrome.browser.ntp.ContentSuggestionsNotifier$DeleteReceiver"
diff --git a/chrome/android/java/res/drawable-sw600dp/bg_white_dialog.xml b/chrome/android/java/res/drawable-sw600dp/bg_white_dialog.xml index f384c95..112698f 100644 --- a/chrome/android/java/res/drawable-sw600dp/bg_white_dialog.xml +++ b/chrome/android/java/res/drawable-sw600dp/bg_white_dialog.xml
@@ -3,10 +3,5 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> -<shape xmlns:android="http://schemas.android.com/apk/res/android" - android:shape="rectangle"> - <corners - android:radius="2dp" /> - <solid - android:color="@android:color/white" /> -</shape> \ No newline at end of file +<nine-patch xmlns:android="http://schemas.android.com/apk/res/android" + android:src="@drawable/popup_bg" />
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiDelegate.java index 1821242..0c6fe13 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiDelegate.java
@@ -456,12 +456,12 @@ /** Called to show overlay. */ public void showOverlay() { - mTouchEventFilter.setEnableFiltering(true); + mTouchEventFilter.setFullOverlay(true); } /** Called to hide overlay. */ public void hideOverlay() { - mTouchEventFilter.setEnableFiltering(false); + mTouchEventFilter.setFullOverlay(false); } public void hideDetails() { @@ -657,7 +657,7 @@ } public void updateTouchableArea(boolean enabled, List<RectF> boxes) { - mTouchEventFilter.updateTouchableArea(enabled, boxes); + mTouchEventFilter.setPartialOverlay(enabled, boxes); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/ui/TouchEventFilter.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/ui/TouchEventFilter.java index 0ac6981..21301cd 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/ui/TouchEventFilter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/ui/TouchEventFilter.java
@@ -70,8 +70,13 @@ private final Paint mGrayOut; private final Paint mClear; - /** Whether filtering is enabled. */ - private boolean mEnabled; + /** Whether a partial-screen overlay is enabled or not. Has precedence over {@link + * @mFullOverlayEnabled}. */ + private boolean mPartialOverlayEnabled; + + /** Whether a full-screen overlay is enabled or not. Is overridden by {@link + * @mPartialOverlayEnabled}.*/ + private boolean mFullOverlayEnabled; /** Padding added between the element area and the grayed-out area. */ private final float mPaddingPx; @@ -153,12 +158,14 @@ @Override public boolean onScroll(MotionEvent downEvent, MotionEvent moveEvent, float distanceX, float distanceY) { - mClient.scrollBy(distanceX / getWidth(), distanceY / getVisualViewportHeight()); + if (mPartialOverlayEnabled) + mClient.scrollBy(distanceX / getWidth(), distanceY / getVisualViewportHeight()); return true; } }); - updateTouchableArea(false, Collections.emptyList()); + setFullOverlay(false); + setPartialOverlay(false, Collections.emptyList()); } /** Initializes dependencies. */ @@ -175,49 +182,71 @@ mGrayOut.setColor(color); } - /** Enables/disables the filter. Clears all currently set touchable areas. */ - public void setEnableFiltering(boolean enabled) { - if (mEnabled != enabled) { - clearTouchableArea(); - mEnabled = enabled; - setAlpha(mEnabled ? 1.0f : 0.0f); + /** + * Enables/disables a full screen overlay. + * + * If both a full and a partial screen overlay are set, the partial overlay has precedence. + * + * @param enabled if {@code false}, the full screen overlay is disabled + */ + public void setFullOverlay(boolean enabled) { + if (mFullOverlayEnabled != enabled) { + mFullOverlayEnabled = enabled; - // reset tap counter each time the filter is disabled. - if (!mEnabled) mUnexpectedTapTimes.clear(); - + // reset tap counter each time the full screen overlay is disabled. + if (!mFullOverlayEnabled) mUnexpectedTapTimes.clear(); + updateVisibility(); invalidate(); } } /** - * Defines the area of the visible viewport that can be used. + * Enables/disables a partial screen overlay. * - * @param enabled if {@code false}, the filter is fully disabled and invisible + * If both a full and a partial screen overlay are set, the partial overlay has precedence. + * + * @param enabled if {@code false}, the partial overlay is disabled * @param rectangles rectangles defining the area that can be used, may be empty */ - public void updateTouchableArea(boolean enabled, List<RectF> rectangles) { - setEnableFiltering(enabled); - if (!mTouchableArea.equals(rectangles)) { + public void setPartialOverlay(boolean enabled, List<RectF> rectangles) { + if (mPartialOverlayEnabled != enabled || (enabled && !mTouchableArea.equals(rectangles))) { + mPartialOverlayEnabled = enabled; + clearTouchableArea(); mTouchableArea.addAll(rectangles); + updateVisibility(); + invalidate(); } } + private boolean isOverlayShown() { + return mFullOverlayEnabled || mPartialOverlayEnabled; + } + + private void updateVisibility() { + setAlpha(isOverlayShown() ? 1.0f : 0.0f); + } + private void clearTouchableArea() { mTouchableArea.clear(); mOffsetY = 0; mInitialBrowserScrollOffsetY += mBrowserScrollOffsetY; mBrowserScrollOffsetY = 0; - invalidate(); } @Override public boolean dispatchTouchEvent(MotionEvent event) { + // Note that partial overlays have precedence over full overlays + if (mPartialOverlayEnabled) return dispatchTouchEventWithPartialOverlay(event); + if (mFullOverlayEnabled) return dispatchTouchEventWithFullOverlay(event); + return false; + } + + private boolean dispatchTouchEventWithPartialOverlay(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_SCROLL: // Scrolling is always safe. Let it through. return false; - case MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: @@ -236,8 +265,6 @@ // fallthrough case MotionEvent.ACTION_DOWN: - if (!mEnabled) return false; // let everything through - // Only let through events if they're meant for the touchable area of the screen. int yTop = getVisualViewportTop(); int yBottom = getVisualViewportBottom(); @@ -259,12 +286,17 @@ } } + private boolean dispatchTouchEventWithFullOverlay(MotionEvent event) { + mNonBrowserGesture.onTouchEvent(event); + return true; + } + /** Returns the origin of the visual viewport in this view. */ @Override @SuppressLint("CanvasSize") protected void onDraw(Canvas canvas) { super.onDraw(canvas); - if (!mEnabled) { + if (!isOverlayShown()) { return; } canvas.drawPaint(mGrayOut);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java index e0cff14..ac39128 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
@@ -110,7 +110,9 @@ import org.chromium.chrome.browser.webapps.WebappCustomTabTimeSpentLogger; import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils; import org.chromium.content_public.browser.LoadUrlParams; +import org.chromium.content_public.browser.NavigationController; import org.chromium.content_public.browser.NavigationEntry; +import org.chromium.content_public.browser.NavigationHistory; import org.chromium.content_public.browser.WebContents; import org.chromium.ui.base.PageTransition; @@ -370,6 +372,32 @@ } } + /** + * @return The index of the previous navigation history entry managed by a dynamic module + * or -1 if there is no such entry. + */ + private boolean goToModuleManagedNavigationIndex() { + if (mModuleActivityDelegate == null && mModuleCallback == null) return false; + NavigationController navigationController = getNavigationController(); + if (navigationController == null) return false; + + NavigationHistory history = navigationController.getNavigationHistory(); + for (int i = history.getCurrentEntryIndex() - 1; i >= 0; i--) { + if (isModuleManagedUrl(history.getEntryAtIndex(i).getUrl())) { + navigationController.goToNavigationIndex(i); + return true; + } + } + + return false; + } + + @Nullable + private NavigationController getNavigationController() { + WebContents webContents = getActivityTab().getWebContents(); + return webContents == null ? null : webContents.getNavigationController(); + } + @VisibleForTesting void maybeInitialiseDynamicModulePostMessageHandler(PostMessageBackend backend) { // Only initialise the handler if the feature is enabled. @@ -592,6 +620,11 @@ if (mIntentDataProvider.shouldEnableEmbeddedMediaExperience()) { RecordUserAction.record("CustomTabs.CloseButtonClicked.DownloadsUI"); } + if (goToModuleManagedNavigationIndex()) { + RecordUserAction.record( + "CustomTabs.CloseButtonClicked.GoToModuleManagedUrl"); + return; + } recordClientConnectionStatus(); finishAndClose(false); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java index 29a9db42..97d4b0d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
@@ -134,10 +134,12 @@ "org.chromium.chrome.browser.customtabs.EXTRA_MODULE_MANAGED_URLS_REGEX"; /** The APK package to load the module from. */ + @VisibleForTesting /* package */ static final String EXTRA_MODULE_PACKAGE_NAME = "org.chromium.chrome.browser.customtabs.EXTRA_MODULE_PACKAGE_NAME"; /** The class name of the module entry point. */ + @VisibleForTesting /* package */ static final String EXTRA_MODULE_CLASS_NAME = "org.chromium.chrome.browser.customtabs.EXTRA_MODULE_CLASS_NAME";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationIntentInterceptor.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationIntentInterceptor.java new file mode 100644 index 0000000..6af94f2 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationIntentInterceptor.java
@@ -0,0 +1,107 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.notifications; + +import android.app.Notification; +import android.app.PendingIntent; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.os.Build; +import android.support.annotation.IntDef; + +import org.chromium.base.ContextUtils; +import org.chromium.base.Log; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Random; + +/** + * Class to intercept {@link PendingIntent}s from notifications, including + * {@link Notification#contentIntent}, {@link Notification.Action#actionIntent} and + * {@link Notification#deleteIntent} with broadcast receivers. + */ +public class NotificationIntentInterceptor { + private static final String TAG = "IntentInterceptor"; + private static final String EXTRA_PENDING_INTENT = + "notifications.NotificationIntentInterceptor.EXTRA_PENDING_INTENT"; + private static final String EXTRA_INTENT_TYPE = + "notifications.NotificationIntentInterceptor.EXTRA_INTENT_TYPE"; + + /** + * Enum that defines type of notification intent. + */ + @IntDef({IntentType.CONTENT_INTENT, IntentType.ACTION_INTENT, IntentType.DELETE_INTENT}) + @Retention(RetentionPolicy.SOURCE) + public @interface IntentType { + int CONTENT_INTENT = 0; + int ACTION_INTENT = 1; + int DELETE_INTENT = 2; + } + + /** + * Receives the event when the user taps on the notification body, notification action, or + * dismiss notification. + * {@link Notification#contentIntent}, {@link Notification#deleteIntent} + * {@link Notification.Action#actionIntent} will be delivered to this broadcast receiver. + */ + public static final class Receiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + // TODO(xingliu): Record notification CTR UMA. + forwardPendingIntent(intent); + } + } + + private NotificationIntentInterceptor() {} + + /** + * Wraps the notification {@link PendingIntent }into another PendingIntent, to intercept clicks + * and dismiss events for metrics purpose. + * @param intentType The type of the pending intent to intercept. + * @param pendingIntent The {@link PendingIntent} of the notification that performs actual task. + */ + public static PendingIntent createInterceptPendingIntent( + @IntentType int intentType, PendingIntent pendingIntent) { + Context applicationContext = ContextUtils.getApplicationContext(); + Intent intent = new Intent(applicationContext, Receiver.class); + intent.putExtra(EXTRA_PENDING_INTENT, pendingIntent); + intent.putExtra(EXTRA_INTENT_TYPE, intentType); + // TODO(xingliu): Add more extras to track notification type and action type. Use the + // combination of notification type and id as the request code. + int requestCode = new Random().nextInt(Integer.MAX_VALUE); + + // This flag ensures the broadcast is delivered with foreground priority to speed up the + // broadcast delivery. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); + } + return PendingIntent.getBroadcast( + applicationContext, requestCode, intent, PendingIntent.FLAG_CANCEL_CURRENT); + } + + // Launches the notification's pending intent, which will perform Chrome feature related tasks. + private static void forwardPendingIntent(Intent intent) { + if (intent == null) { + Log.e(TAG, "Intent to forward is null."); + return; + } + + PendingIntent pendingIntent = + (PendingIntent) (intent.getParcelableExtra(EXTRA_PENDING_INTENT)); + if (pendingIntent == null) { + Log.d(TAG, "The notification's PendingIntent is null."); + return; + } + + try { + pendingIntent.send(); + } catch (PendingIntent.CanceledException e) { + Log.e(TAG, "The PendingIntent to fire is canceled."); + e.printStackTrace(); + } + } +}
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index c41b9f9a..6b3bced1 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -967,6 +967,7 @@ "java/src/org/chromium/chrome/browser/notifications/NotificationBuilderFactory.java", "java/src/org/chromium/chrome/browser/notifications/NotificationCompatBuilder.java", "java/src/org/chromium/chrome/browser/notifications/NotificationConstants.java", + "java/src/org/chromium/chrome/browser/notifications/NotificationIntentInterceptor.java", "java/src/org/chromium/chrome/browser/notifications/NotificationManagerProxy.java", "java/src/org/chromium/chrome/browser/notifications/NotificationManagerProxyImpl.java", "java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java", @@ -2011,6 +2012,7 @@ "javatests/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtilsTest.java", "javatests/src/org/chromium/chrome/browser/notifications/ChromeNotificationBuilderTest.java", "javatests/src/org/chromium/chrome/browser/notifications/CustomNotificationBuilderTest.java", + "javatests/src/org/chromium/chrome/browser/notifications/NotificationIntentInterceptorTest.java", "javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeIntentTest.java", "javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeTest.java", "javatests/src/org/chromium/chrome/browser/notifications/NotificationTestRule.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java index cbd6bd50e..5ce67cd 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
@@ -42,6 +42,7 @@ import android.support.test.InstrumentationRegistry; import android.support.test.filters.MediumTest; import android.support.test.filters.SmallTest; +import android.support.test.uiautomator.UiDevice; import android.support.v7.content.res.AppCompatResources; import android.text.TextUtils; import android.view.Menu; @@ -77,6 +78,7 @@ import org.chromium.base.test.util.Restriction; import org.chromium.base.test.util.RetryOnFailure; import org.chromium.chrome.R; +import org.chromium.chrome.browser.AppHooksModule; import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.ChromeSwitches; @@ -88,6 +90,7 @@ import org.chromium.chrome.browser.browserservices.BrowserSessionContentUtils; import org.chromium.chrome.browser.browserservices.Origin; import org.chromium.chrome.browser.browserservices.OriginVerifier; +import org.chromium.chrome.browser.dependency_injection.ModuleFactoryOverrides; import org.chromium.chrome.browser.document.ChromeLauncherActivity; import org.chromium.chrome.browser.firstrun.FirstRunStatus; import org.chromium.chrome.browser.history.BrowsingHistoryBridge; @@ -117,6 +120,7 @@ import org.chromium.chrome.test.util.browser.contextmenu.ContextMenuUtils; import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.browser.WebContentsObserver; +import org.chromium.content_public.browser.test.util.ClickUtils; import org.chromium.content_public.browser.test.util.Criteria; import org.chromium.content_public.browser.test.util.CriteriaHelper; import org.chromium.content_public.browser.test.util.DOMUtils; @@ -124,12 +128,14 @@ import org.chromium.content_public.browser.test.util.WebContentsUtils; import org.chromium.net.test.EmbeddedTestServer; import org.chromium.net.test.util.TestWebServer; +import org.chromium.ui.base.PageTransition; import org.chromium.ui.mojom.WindowOpenDisposition; import org.chromium.ui.test.util.UiRestriction; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.concurrent.ExecutionException; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -220,6 +226,9 @@ PathUtils.setPrivateDataDirectorySuffix(PRIVATE_DATA_DIRECTORY_SUFFIX); LibraryLoader.getInstance().ensureInitialized(LibraryProcessType.PROCESS_BROWSER); mWebServer = TestWebServer.start(); + + ModuleFactoryOverrides.setOverride(AppHooksModule.Factory.class, + CustomTabsDynamicModuleTestUtils.AppHooksModuleForTest::new); } @After @@ -236,6 +245,8 @@ if (handler != null) handler.hideAppMenu(); }); mWebServer.shutdown(); + + ModuleFactoryOverrides.clearOverrides(); } private CustomTabActivity getActivity() { @@ -1110,6 +1121,119 @@ } } + private void runAndWaitForActivityStopped(Runnable runnable) + throws TimeoutException, InterruptedException { + CallbackHelper cctHiddenCallback = new CallbackHelper(); + ActivityStateListener listener = (activity, newState) -> { + if (activity == mCustomTabActivityTestRule.getActivity() + && (newState == ActivityState.STOPPED || newState == ActivityState.DESTROYED)) { + cctHiddenCallback.notifyCalled(); + } + }; + ApplicationStatus.registerStateListenerForAllActivities(listener); + + runnable.run(); + cctHiddenCallback.waitForCallback("Hide cct", 0); + ApplicationStatus.unregisterActivityStateListener(listener); + } + + /** + This test executes the following workflow assuming dynamic module has been loaded succesfully: + - moduleManagedUrl1 -> nav1.1 -> nav1.2 -> modulemanagedUrl2 -> nav2.1 -> nav2.2 + - User hits the "close button", therefore goes back to modulemanagedUrl2 + - User hits the Android back button, going returning to nav1.2 + - User hits the "close button" again, going return to moduleManagedUrl1 + - User hits the Android back button thereby closes CCT. + */ + @Test + @SmallTest + @EnableFeatures(ChromeFeatureList.CCT_MODULE) + public void testCloseButtonBehaviourWithDynamicModule() + throws InterruptedException, ExecutionException, TimeoutException { + String moduleManagedUrl1 = "https://www.google.com/search?q=cat"; + String moduleManagedUrl2 = "https://www.google.com/search?q=dog"; + + Intent intent = CustomTabsDynamicModuleTestUtils.makeDynamicModuleIntent( + moduleManagedUrl1, "^https://www.google.com/search.*"); + + // Open CCT with moduleManagedUrl1 and navigate + // moduleManagedUrl1 -> nav1.1 - nav1.2 -> modulemanagedUrl2 -> nav2.1 -> nav2.2 + mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent); + CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity(); + + mCustomTabActivityTestRule.loadUrlInTab(mTestPage, PageTransition.LINK, + cctActivity.getActivityTab()); + mCustomTabActivityTestRule.loadUrlInTab(mTestPage2, PageTransition.LINK, + cctActivity.getActivityTab()); + mCustomTabActivityTestRule.loadUrlInTab(moduleManagedUrl2, PageTransition.TYPED, + cctActivity.getActivityTab()); + mCustomTabActivityTestRule.loadUrlInTab(mTestPage, PageTransition.LINK, + cctActivity.getActivityTab()); + mCustomTabActivityTestRule.loadUrlInTab(mTestPage2, PageTransition.LINK, + cctActivity.getActivityTab()); + + // click the close button and wait while tab page loaded + ClickUtils.clickButton(cctActivity.findViewById(R.id.close_button)); + ChromeTabUtils.waitForTabPageLoaded(cctActivity.getActivityTab(), (String) null); + + // close button returns back to moduleManagedUrl2 + Assert.assertEquals(moduleManagedUrl2, cctActivity.getActivityTab().getUrl()); + + // press the back button and wait while tab page loaded + UiDevice mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); + mDevice.pressBack(); + ChromeTabUtils.waitForTabPageLoaded(cctActivity.getActivityTab(), (String) null); + + // the back button returns to nav1.2 + Assert.assertEquals(mTestPage2, cctActivity.getActivityTab().getUrl()); + + // click the close button and wait while tab page loaded + ClickUtils.clickButton(cctActivity.findViewById(R.id.close_button)); + ChromeTabUtils.waitForTabPageLoaded(cctActivity.getActivityTab(), (String) null); + + // close button returns back to moduleManagedUrl1 + Assert.assertEquals(moduleManagedUrl1, cctActivity.getActivityTab().getUrl()); + + // press back button and while cct is hidden + runAndWaitForActivityStopped(mDevice::pressBack); + } + + /** + This test executes the following workflow assuming dynamic module has not been loaded: + - moduleManagedUrl1 -> nav1.1 - nav1.2 -> modulemanagedUrl2 -> nav2.1 -> nav2.2 + - User hits the close button, thereby closes CCT + */ + @Test + @SmallTest + public void testCloseButtonBehaviourWithoutDynamicModule() + throws InterruptedException, ExecutionException, TimeoutException { + String moduleManagedUrl1 = "https://www.google.com/search?q=cat"; + String moduleManagedUrl2 = "https://www.google.com/search?q=dog"; + + // Open CCT with moduleManagedUrl1 and navigate + // moduleManagedUrl1 -> nav1.1 - nav1.2 -> modulemanagedUrl2 -> nav2.1 -> nav2.2 + + Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent( + InstrumentationRegistry.getTargetContext(), moduleManagedUrl1); + mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent); + CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity(); + + mCustomTabActivityTestRule.loadUrlInTab(mTestPage, PageTransition.LINK, + cctActivity.getActivityTab()); + mCustomTabActivityTestRule.loadUrlInTab(mTestPage2, PageTransition.LINK, + cctActivity.getActivityTab()); + mCustomTabActivityTestRule.loadUrlInTab(moduleManagedUrl2, PageTransition.LINK, + cctActivity.getActivityTab()); + mCustomTabActivityTestRule.loadUrlInTab(mTestPage, PageTransition.LINK, + cctActivity.getActivityTab()); + mCustomTabActivityTestRule.loadUrlInTab(mTestPage2, PageTransition.LINK, + cctActivity.getActivityTab()); + + // click close button and wait while cct is hidden + runAndWaitForActivityStopped(() -> + ClickUtils.clickButton(cctActivity.findViewById(R.id.close_button))); + } + @Test @SmallTest @RetryOnFailure
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationIntentInterceptorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationIntentInterceptorTest.java new file mode 100644 index 0000000..0de0c5b --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationIntentInterceptorTest.java
@@ -0,0 +1,120 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.notifications; + +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.MediumTest; +import android.support.test.uiautomator.By; +import android.support.test.uiautomator.UiDevice; +import android.support.test.uiautomator.UiObject2; +import android.support.test.uiautomator.Until; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.ContextUtils; +import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.chrome.R; +import org.chromium.chrome.browser.ChromeSwitches; +import org.chromium.chrome.browser.ChromeTabbedActivity; +import org.chromium.chrome.browser.notifications.channels.ChannelDefinitions; +import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.ChromeTabbedActivityTestRule; +import org.chromium.content_public.browser.test.util.Criteria; +import org.chromium.content_public.browser.test.util.CriteriaHelper; + +/** + * Test to verify intercepting notification pending intents with broadcast receiver. + */ +@RunWith(ChromeJUnit4ClassRunner.class) +@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) +public class NotificationIntentInterceptorTest { + @Rule + public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); + + private static final String TEST_NOTIFICATION_TITLE = "Test notification title."; + private static final long WAIT_FOR_NOTIFICATION_SHOWN_TIMEOUT_MILLISECONDS = 3000; + + @Before + public void setUp() throws Exception { + mActivityTestRule.startMainActivityOnBlankPage(); + } + + // Builds a simple notification used in tests. + private Notification buildSimpleNotification(String title) { + ChromeNotificationBuilder builder = + NotificationBuilderFactory.createChromeNotificationBuilder( + true /* preferCompat */, ChannelDefinitions.ChannelId.DOWNLOADS); + + // Set content intent. UI automator may tap the notification and expand the action buttons, + // in order to reduce flakiness, don't add action button. + Context context = ContextUtils.getApplicationContext(); + Intent contentIntent = new Intent(context, ChromeTabbedActivity.class); + Uri uri = Uri.parse("www.example.com"); + contentIntent.setData(uri); + contentIntent.setAction(Intent.ACTION_VIEW); + int flags = PendingIntent.FLAG_ONE_SHOT; + PendingIntent contentPendingIntent = + PendingIntent.getActivity(context, 0, contentIntent, flags); + assert contentPendingIntent != null; + builder.setContentIntent(NotificationIntentInterceptor.createInterceptPendingIntent( + NotificationIntentInterceptor.IntentType.CONTENT_INTENT, contentPendingIntent)); + builder.setContentTitle(title); + builder.setSmallIcon(R.drawable.offline_pin); + return builder.build(); + } + + /** + * Clicks the notification with UI automator. Notice the notification bar is not part of the + * app, so we have to use UI automator. + * @param text The text of notification UI. + */ + private void clickNotification(String text) { + UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); + device.openNotification(); + device.wait( + Until.hasObject(By.text(text)), WAIT_FOR_NOTIFICATION_SHOWN_TIMEOUT_MILLISECONDS); + UiObject2 textObject = device.findObject(By.text(text)); + Assert.assertEquals(text, textObject.getText()); + textObject.click(); + } + + /** + * Verifies {@link Notification#contentIntent} can be intercepted by broadcast receiver. + * Action button and dismiss have no test coverage due to difficulty in simulation with UI + * automator. On different Android version, the way to dismiss or find the action button can be + * different. + */ + @Test + @MediumTest + public void testContentIntentInterception() { + // Send notification. + NotificationManager notificationManager = + (NotificationManager) ContextUtils.getApplicationContext().getSystemService( + Context.NOTIFICATION_SERVICE); + notificationManager.notify(0, buildSimpleNotification(TEST_NOTIFICATION_TITLE)); + + // Click notification body. + clickNotification(TEST_NOTIFICATION_TITLE); + + // Wait for another tab to load. + CriteriaHelper.pollUiThread(new Criteria() { + @Override + public boolean isSatisfied() { + return mActivityTestRule.tabsCount(false) > 1; + } + }); + notificationManager.cancelAll(); + } +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/partnercustomizations/PartnerDisableIncognitoModeIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/partnercustomizations/PartnerDisableIncognitoModeIntegrationTest.java index 82872e3..53ae1ba 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/partnercustomizations/PartnerDisableIncognitoModeIntegrationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/partnercustomizations/PartnerDisableIncognitoModeIntegrationTest.java
@@ -155,7 +155,7 @@ waitForParentalControlsEnabledState(true); CriteriaHelper.pollInstrumentationThread( - Criteria.equals(0, () -> mActivityTestRule.incognitoTabsCount())); + Criteria.equals(0, () -> mActivityTestRule.tabsCount(true /* incognito */))); } finally { testServer.stopAndDestroyServer(); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/UndoTabModelTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/UndoTabModelTest.java index d55f8e58..0421051 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/UndoTabModelTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/UndoTabModelTest.java
@@ -462,12 +462,12 @@ * @throws InterruptedException */ @Test - @MediumTest - // TODO(jbudorick): Replace with DisableIf when it supports filtering by device type. - // Flaky on tablets, crbug.com/620014. - @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) - @RetryOnFailure - public void testTwoTabs() throws InterruptedException, TimeoutException { + // @MediumTest + // @RetryOnFailure + @DisabledTest( + message = "Flaky on all Android configurations except Swarming. See crbug.com/620014.") + public void + testTwoTabs() throws InterruptedException, TimeoutException { TabModel model = mActivityTestRule.getActivity().getTabModelSelector().getModel(false); ChromeTabCreator tabCreator = mActivityTestRule.getActivity().getTabCreator(false); createTabOnUiThread(tabCreator);
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 6d72834d..d484067 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -5080,6 +5080,9 @@ <message name="IDS_NEWTAB_PROMO_2" desc="Variations option 3. Text shown on promotional UI appearing next to the New Tab button, which encourages users to use it."> Open a new tab to browse two sites at once </message> + <message name="IDS_REOPEN_TAB_PROMO" desc="Text shown on promotional UI appearing next to the app menu button"> + Reopen a tab if you accidentally closed it + </message> <!-- Browser Hung Plugin Detector --> <if expr="is_win">
diff --git a/chrome/app/generated_resources_grd/IDS_REOPEN_TAB_PROMO.png.sha1 b/chrome/app/generated_resources_grd/IDS_REOPEN_TAB_PROMO.png.sha1 new file mode 100644 index 0000000..03fb3fa --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_REOPEN_TAB_PROMO.png.sha1
@@ -0,0 +1 @@ +6e3827c2634ca8ef00f34a4df80367296252542b \ No newline at end of file
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 9dc3120..ee72a15 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -461,20 +461,6 @@ {flag_descriptions::kNumRasterThreadsFour, switches::kNumRasterThreads, "4"}}; -const FeatureEntry::Choice kGpuRasterizationMSAASampleCountChoices[] = { - {flags_ui::kGenericExperimentChoiceDefault, "", ""}, - {flag_descriptions::kGpuRasterizationMsaaSampleCountZero, - switches::kGpuRasterizationMSAASampleCount, "0"}, - {flag_descriptions::kGpuRasterizationMsaaSampleCountTwo, - switches::kGpuRasterizationMSAASampleCount, "2"}, - {flag_descriptions::kGpuRasterizationMsaaSampleCountFour, - switches::kGpuRasterizationMSAASampleCount, "4"}, - {flag_descriptions::kGpuRasterizationMsaaSampleCountEight, - switches::kGpuRasterizationMSAASampleCount, "8"}, - {flag_descriptions::kGpuRasterizationMsaaSampleCountSixteen, - switches::kGpuRasterizationMSAASampleCount, "16"}, -}; - const FeatureEntry::Choice kMHTMLGeneratorOptionChoices[] = { {flags_ui::kGenericExperimentChoiceDefault, "", ""}, {flag_descriptions::kMhtmlSkipNostoreMain, switches::kMHTMLGeneratorOption, @@ -1571,10 +1557,6 @@ {"enable-oop-rasterization", flag_descriptions::kOopRasterizationName, flag_descriptions::kOopRasterizationDescription, kOsAll, MULTI_VALUE_TYPE(kEnableOopRasterizationChoices)}, - {"gpu-rasterization-msaa-sample-count", - flag_descriptions::kGpuRasterizationMsaaSampleCountName, - flag_descriptions::kGpuRasterizationMsaaSampleCountDescription, kOsAll, - MULTI_VALUE_TYPE(kGpuRasterizationMSAASampleCountChoices)}, {"enable-experimental-web-platform-features", flag_descriptions::kExperimentalWebPlatformFeaturesName, flag_descriptions::kExperimentalWebPlatformFeaturesDescription, kOsAll,
diff --git a/chrome/browser/autofill/autofill_interactive_uitest.cc b/chrome/browser/autofill/autofill_interactive_uitest.cc index 946b85d2..16d6dda 100644 --- a/chrome/browser/autofill/autofill_interactive_uitest.cc +++ b/chrome/browser/autofill/autofill_interactive_uitest.cc
@@ -2961,6 +2961,70 @@ } // Test that we can autofill forms that dynamically change the element that +// has been clicked on, even though there are multiple forms with identical +// names. +IN_PROC_BROWSER_TEST_P( + AutofillDynamicFormInteractiveTest, + DynamicFormFill_FirstElementDisappearsMultipleBadNameForms) { + CreateTestProfile(); + + GURL url = embedded_test_server()->GetURL( + "a.com", + "/autofill/dynamic_form_element_invalid_multiple_badname_forms.html"); + + ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(), url)); + + TriggerFormFill("firstname_5"); + + // Wait for the re-fill to happen. + bool has_refilled = false; + ASSERT_TRUE(content::ExecuteScriptAndExtractBool( + GetWebContents(), "hasRefilled()", &has_refilled)); + + ASSERT_TRUE(has_refilled); + // Make sure the second form was filled correctly, and the first form was left + // unfilled. + ExpectFieldValue("firstname_1", ""); + ExpectFieldValue("firstname_2", ""); + ExpectFieldValue("address1_3", ""); + ExpectFieldValue("country_4", "CA"); // default + ExpectFieldValue("firstname_6", "Milton"); + ExpectFieldValue("address1_7", "4120 Freidrich Lane"); + ExpectFieldValue("country_8", "US"); +} + +// Test that we can autofill forms that dynamically change the element that +// has been clicked on, even though there are multiple forms with identical +// names. +IN_PROC_BROWSER_TEST_P(AutofillDynamicFormInteractiveTest, + DynamicFormFill_FirstElementDisappearsBadnameUnowned) { + CreateTestProfile(); + + GURL url = embedded_test_server()->GetURL( + "a.com", "/autofill/dynamic_form_element_invalid_unowned_badnames.html"); + + ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(), url)); + + TriggerFormFill("firstname_5"); + + // Wait for the re-fill to happen. + bool has_refilled = false; + ASSERT_TRUE(content::ExecuteScriptAndExtractBool( + GetWebContents(), "hasRefilled()", &has_refilled)); + + ASSERT_TRUE(has_refilled); + // Make sure the second form was filled correctly, and the first form was left + // unfilled. + ExpectFieldValue("firstname_1", ""); + ExpectFieldValue("firstname_2", ""); + ExpectFieldValue("address1_3", ""); + ExpectFieldValue("country_4", "CA"); // default + ExpectFieldValue("firstname_6", "Milton"); + ExpectFieldValue("address1_7", "4120 Freidrich Lane"); + ExpectFieldValue("country_8", "US"); +} + +// Test that we can autofill forms that dynamically change the element that // has been clicked on, even though the elements are unowned. IN_PROC_BROWSER_TEST_P(AutofillDynamicFormInteractiveTest, DynamicFormFill_FirstElementDisappearsUnowned) {
diff --git a/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc b/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc index b16c80a..c2d663c 100644 --- a/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc +++ b/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc
@@ -45,7 +45,6 @@ #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "components/browsing_data/core/browsing_data_utils.h" -#include "components/browsing_data/core/features.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/prefs/pref_service.h" #include "components/signin/core/browser/account_reconcilor.h" @@ -284,8 +283,7 @@ public: BrowsingDataRemoverBrowserTest() { feature_list_.InitWithFeatures( - {browsing_data::features::kRemoveNavigationHistory, - leveldb::kLevelDBRewriteFeature, + {leveldb::kLevelDBRewriteFeature, // Ensure that kOnionSoupDOMStorage is enabled because the old // SessionStorage implementation causes flaky tests. blink::features::kOnionSoupDOMStorage},
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc index 7f77886..61fcb1c 100644 --- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc +++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
@@ -53,7 +53,6 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" #include "chrome/browser/search_engines/template_url_service_factory.h" -#include "chrome/browser/sessions/tab_restore_service_factory.h" #include "chrome/browser/translate/chrome_translate_client.h" #include "chrome/browser/web_data_service_factory.h" #include "chrome/browser/webauthn/chrome_authenticator_request_delegate.h" @@ -64,7 +63,6 @@ #include "components/autofill/core/browser/personal_data_manager.h" #include "components/autofill/core/browser/webdata/autofill_webdata_service.h" #include "components/bookmarks/browser/bookmark_model.h" -#include "components/browsing_data/core/features.h" #include "components/content_settings/core/browser/content_settings_registry.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/content_settings/core/common/content_settings.h" @@ -87,13 +85,13 @@ #include "components/prefs/pref_service.h" #include "components/previews/content/previews_ui_service.h" #include "components/search_engines/template_url_service.h" -#include "components/sessions/core/tab_restore_service.h" #include "components/web_cache/browser/web_cache_manager.h" #include "components/webrtc_logging/browser/log_cleanup.h" #include "components/webrtc_logging/browser/text_log_list.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/browsing_data_filter_builder.h" +#include "content/public/browser/host_zoom_map.h" #include "content/public/browser/plugin_data_remover.h" #include "content/public/browser/ssl_host_state_delegate.h" #include "content/public/browser/storage_partition.h" @@ -122,11 +120,6 @@ #include "extensions/common/constants.h" #endif // BUILDFLAG(ENABLE_EXTENSIONS) -#if BUILDFLAG(ENABLE_SESSION_SERVICE) -#include "chrome/browser/sessions/session_service.h" -#include "chrome/browser/sessions/session_service_factory.h" -#endif // BUILDFLAG(ENABLE_SESSION_SERVICE) - #if defined(OS_CHROMEOS) #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chromeos/cryptohome/cryptohome_parameters.h" @@ -500,33 +493,6 @@ prerender::PrerenderManager::CLEAR_PRERENDER_HISTORY); } - // When this feature is enabled, recent tabs and sessions will be deleted - // by NavigationEntryRemover and not here. - bool is_navigation_entry_remover_enabled = base::FeatureList::IsEnabled( - browsing_data::features::kRemoveNavigationHistory); - - // If the caller is removing history for all hosts, then clear ancillary - // historical information. - if (!is_navigation_entry_remover_enabled && - filter_builder.GetMode() == BrowsingDataFilterBuilder::BLACKLIST) { - // We also delete the list of recently closed tabs. Since these expire, - // they can't be more than a day old, so we can simply clear them all. - sessions::TabRestoreService* tab_service = - TabRestoreServiceFactory::GetForProfile(profile_); - if (tab_service) { - tab_service->ClearEntries(); - tab_service->DeleteLastSession(); - } - -#if BUILDFLAG(ENABLE_SESSION_SERVICE) - // We also delete the last session when we delete the history. - SessionService* session_service = - SessionServiceFactory::GetForProfile(profile_); - if (session_service) - session_service->DeleteLastSession(); -#endif - } - // The saved Autofill profiles and credit cards can include the origin from // which these profiles and credit cards were learned. These are a form of // history, so clear them as well.
diff --git a/chrome/browser/browsing_data/navigation_entry_remover.cc b/chrome/browser/browsing_data/navigation_entry_remover.cc index 0896c266..41bedc1 100644 --- a/chrome/browser/browsing_data/navigation_entry_remover.cc +++ b/chrome/browser/browsing_data/navigation_entry_remover.cc
@@ -8,7 +8,6 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sessions/tab_restore_service_factory.h" #include "chrome/common/buildflags.h" -#include "components/browsing_data/core/features.h" #include "components/sessions/core/serialized_navigation_entry.h" #include "components/sessions/core/tab_restore_service.h" #include "components/sessions/core/tab_restore_service_observer.h" @@ -216,10 +215,6 @@ const history::DeletionInfo& deletion_info) { DCHECK(profile->GetProfileType() == Profile::ProfileType::REGULAR_PROFILE); DCHECK(!deletion_info.is_from_expiration()); - if (!base::FeatureList::IsEnabled( - browsing_data::features::kRemoveNavigationHistory)) { - return; - } base::flat_set<GURL> url_set; if (!deletion_info.time_range().IsValid())
diff --git a/chrome/browser/browsing_data/navigation_entry_remover_browsertest.cc b/chrome/browser/browsing_data/navigation_entry_remover_browsertest.cc index a11c7d7..6a201c23 100644 --- a/chrome/browser/browsing_data/navigation_entry_remover_browsertest.cc +++ b/chrome/browser/browsing_data/navigation_entry_remover_browsertest.cc
@@ -3,7 +3,6 @@ // found in the LICENSE file. #include "base/files/file_path.h" -#include "base/test/scoped_feature_list.h" #include "build/build_config.h" #include "chrome/browser/browsing_data/navigation_entry_remover.h" #include "chrome/browser/sessions/tab_restore_service_factory.h" @@ -13,7 +12,6 @@ #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" -#include "components/browsing_data/core/features.h" #include "components/sessions/core/tab_restore_service.h" #include "content/public/browser/navigation_controller.h" #include "content/public/browser/navigation_entry.h" @@ -28,8 +26,6 @@ class NavigationEntryRemoverTest : public InProcessBrowserTest { protected: void SetUpOnMainThread() override { - feature_list_.InitWithFeatures( - {browsing_data::features::kRemoveNavigationHistory}, {}); auto path = base::FilePath(FILE_PATH_LITERAL("browsing_data")); url_a_ = ui_test_utils::GetTestUrl( path, base::FilePath(FILE_PATH_LITERAL("a.html"))); @@ -107,8 +103,6 @@ GURL url_d_; GURL about_blank_; - private: - base::test::ScopedFeatureList feature_list_; }; // === Tests for helper functions ===
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc index eaa2f776..d9a9d11 100644 --- a/chrome/browser/chrome_browser_main.cc +++ b/chrome/browser/chrome_browser_main.cc
@@ -610,33 +610,6 @@ #endif } -bool WaitUntilMachineLevelUserCloudPolicyEnrollmentFinished( - policy::ChromeBrowserPolicyConnector* connector) { -#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID) - using RegisterResult = - policy::MachineLevelUserCloudPolicyController::RegisterResult; - switch (connector->machine_level_user_cloud_policy_controller() - ->WaitUntilPolicyEnrollmentFinished()) { - case RegisterResult::kNoEnrollmentNeeded: - case RegisterResult::kEnrollmentSuccessBeforeDialogDisplayed: - return true; - case RegisterResult::kEnrollmentSuccess: -#if defined(OS_MACOSX) - app_controller_mac::EnterpriseStartupDialogClosed(); -#endif - return true; - case RegisterResult::kRestartDueToFailure: - chrome::AttemptRestart(); - return false; - case RegisterResult::kQuitDueToFailure: - chrome::AttemptExit(); - return false; - } -#else - return true; -#endif -} - // Sets up the ThreadProfiler for the browser process, runs it, and returns the // profiler. std::unique_ptr<ThreadProfiler> CreateAndStartBrowserMainThreadProfiler() { @@ -1373,13 +1346,16 @@ // running. browser_process_->PreMainMessageLoopRun(); +#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID) // Wait for the result of machine level user cloud policy enrollment after // we start the enrollment process in browser_porcess_->PreMainMessageLoopRun. // Abort the launch process if the enrollment is failed. - if (!WaitUntilMachineLevelUserCloudPolicyEnrollmentFinished( - browser_process_->browser_policy_connector())) { + if (!browser_process_->browser_policy_connector() + ->machine_level_user_cloud_policy_controller() + ->WaitUntilPolicyEnrollmentFinished()) { return chrome::RESULT_CODE_CLOUD_POLICY_ENROLLMENT_FAILED; } +#endif // Record last shutdown time into a histogram. browser_shutdown::ReadLastShutdownInfo();
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index 772da05..4996d130 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -1573,8 +1573,6 @@ "policy/status_uploader.h", "policy/system_log_uploader.cc", "policy/system_log_uploader.h", - "policy/temp_certs_cache_nss.cc", - "policy/temp_certs_cache_nss.h", "policy/ticl_device_settings_provider.cc", "policy/ticl_device_settings_provider.h", "policy/upload_job.h", @@ -2303,7 +2301,6 @@ "policy/single_app_install_event_log_unittest.cc", "policy/status_uploader_unittest.cc", "policy/system_log_uploader_unittest.cc", - "policy/temp_certs_cache_nss_unittest.cc", "policy/upload_job_unittest.cc", "policy/user_cloud_policy_manager_chromeos_unittest.cc", "policy/user_cloud_policy_store_chromeos_unittest.cc",
diff --git a/chrome/browser/chromeos/DEPS b/chrome/browser/chromeos/DEPS index 2345595e7e..b9346a7 100644 --- a/chrome/browser/chromeos/DEPS +++ b/chrome/browser/chromeos/DEPS
@@ -15,6 +15,7 @@ "+remoting/host/it2me", # For CRD host in remote command "+services/device/public", "+services/metrics/public", + "+services/network", "+services/tracing/public", "+services/viz/public/interfaces", # Chromeos should not use ozone directly, it must go through mojo as ozone
diff --git a/chrome/browser/chromeos/arc/accessibility/accessibility_node_info_data_wrapper.cc b/chrome/browser/chromeos/arc/accessibility/accessibility_node_info_data_wrapper.cc index c4d934da..9058bc0 100644 --- a/chrome/browser/chromeos/arc/accessibility/accessibility_node_info_data_wrapper.cc +++ b/chrome/browser/chromeos/arc/accessibility/accessibility_node_info_data_wrapper.cc
@@ -139,19 +139,18 @@ // need additional information contained only in the CollectionInfo. The // CollectionInfo should be an ancestor of this node. AXCollectionInfoData* collection_info = nullptr; - for (AXNodeInfoData* container = node_ptr_; container;) { - if (!container) + for (const ArcAccessibilityInfoData* container = + static_cast<const ArcAccessibilityInfoData*>(this); + container;) { + if (!container || !container->IsNode()) break; - if (container->collection_info.get()) { - collection_info = container->collection_info.get(); + if (container->IsNode() && container->GetNode()->collection_info.get()) { + collection_info = container->GetNode()->collection_info.get(); break; } - ArcAccessibilityInfoData* container_data = - tree_source_->GetParent(tree_source_->GetFromId(container->id)); - if (!container_data->IsNode()) - break; - container = container_data->GetNode(); + container = + tree_source_->GetParent(tree_source_->GetFromId(container->GetId())); } if (collection_info) { @@ -387,6 +386,10 @@ local_bounds.width(), local_bounds.height()); } + // TODO(katie): Try using offset_container_id to make bounds calculations + // more efficient. If this is the child of the root, set the + // offset_container_id to be the root. Otherwise, set it to the first node + // child of the root. // Integer properties. int32_t val;
diff --git a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge_unittest.cc b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge_unittest.cc index ab1d070..d6bf312 100644 --- a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge_unittest.cc +++ b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge_unittest.cc
@@ -239,6 +239,7 @@ // Same task id, different package name. event2->node_data.clear(); event2->node_data.push_back(arc::mojom::AccessibilityNodeInfoData::New()); + event2->source_id = 3; event2->node_data[0]->id = 3; event2->node_data[0]->string_properties = base::flat_map<arc::mojom::AccessibilityStringProperty, std::string>();
diff --git a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc index e01e61a..3859243 100644 --- a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc +++ b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc
@@ -31,7 +31,7 @@ : current_tree_serializer_(new AXTreeArcSerializer(this)), root_id_(-1), window_id_(-1), - focused_node_id_(-1), + focused_id_(-1), is_notification_(false), delegate_(delegate) {} @@ -61,10 +61,30 @@ continue; auto it = event_data->node_data[i]->int_list_properties->find( AXIntListProperty::CHILD_NODE_IDS); - if (it != event_data->node_data[i]->int_list_properties->end()) { - all_children_map[event_data->node_data[i]->id] = it->second; + if (it == event_data->node_data[i]->int_list_properties->end()) + continue; + all_children_map[event_data->node_data[i]->id] = it->second; + for (size_t j = 0; j < it->second.size(); ++j) + all_parent_map[it->second[j]] = event_data->node_data[i]->id; + } + if (event_data->window_data) { + for (size_t i = 0; i < event_data->window_data->size(); ++i) { + int32_t window_id = event_data->window_data->at(i)->window_id; + int32_t root_node_id = event_data->window_data->at(i)->root_node_id; + if (root_node_id) { + all_parent_map[root_node_id] = window_id; + all_children_map[window_id] = {root_node_id}; + } + if (!event_data->window_data->at(i)->int_list_properties) + continue; + auto it = event_data->window_data->at(i)->int_list_properties->find( + mojom::AccessibilityWindowIntListProperty::CHILD_WINDOW_IDS); + if (it == event_data->window_data->at(i)->int_list_properties->end()) + continue; + all_children_map[window_id].insert(all_children_map[window_id].begin(), + it->second.begin(), it->second.end()); for (size_t j = 0; j < it->second.size(); ++j) - all_parent_map[it->second[j]] = event_data->node_data[i]->id; + all_parent_map[it->second[j]] = window_id; } } @@ -103,8 +123,19 @@ tree_map_[id] = std::make_unique<AccessibilityNodeInfoDataWrapper>(this, node); - if (tree_map_[id]->IsFocused()) { - focused_node_id_ = id; + if (tree_map_[id]->IsFocused()) + focused_id_ = id; + } + if (event_data->window_data) { + for (size_t i = 0; i < event_data->window_data->size(); ++i) { + int32_t id = event_data->window_data->at(i)->window_id; + // Only map nodes in the parent_map and the root. + // This avoids adding other subtrees that are not interesting. + if (parent_map_.find(id) == parent_map_.end() && id != root_id_) + continue; + AXWindowInfoData* window = event_data->window_data->at(i).get(); + tree_map_[id] = + std::make_unique<AccessibilityWindowInfoDataWrapper>(this, window); } } @@ -117,6 +148,14 @@ continue; cached_computed_bounds_[id] = ComputeEnclosingBounds(tree_map_[id].get()); } + if (event_data->window_data) { + for (int i = event_data->window_data->size() - 1; i >= 0; --i) { + int32_t id = event_data->window_data->at(i)->window_id; + if (parent_map_.find(id) == parent_map_.end() && id != root_id_) + continue; + cached_computed_bounds_[id] = ComputeEnclosingBounds(tree_map_[id].get()); + } + } ExtensionMsg_AccessibilityEventBundleParams event_bundle; event_bundle.tree_id = tree_id(); @@ -147,10 +186,25 @@ bool AXTreeSourceArc::GetTreeData(ui::AXTreeData* data) const { data->tree_id = tree_id(); - if (focused_node_id_ >= 0) - data->focus_id = focused_node_id_; - else if (root_id_ >= 0) - data->focus_id = root_id_; + if (focused_id_ >= 0) { + data->focus_id = focused_id_; + } else if (root_id_ >= 0) { + ArcAccessibilityInfoData* root = GetRoot(); + if (root->IsNode()) { + data->focus_id = root_id_; + } else { + std::vector<ArcAccessibilityInfoData*> children; + root->GetChildren(&children); + if (!children.empty()) { + for (size_t i = 0; i < children.size(); ++i) { + if (children[i]->IsNode()) { + data->focus_id = children[i]->GetId(); + break; + } + } + } + } + } return true; } @@ -261,9 +315,11 @@ int32_t id = info_data->GetId(); out_data->id = id; - // TODO(katie): this may not hold true with Windows. it's probably the root - // window's root node which is a kRootWebArea. - if (id == root_id_) + // If the node is the root, or if the node's parent is the root window, + // the role should be rootWebArea. + if (info_data->IsNode() && id == root_id_) + out_data->role = ax::mojom::Role::kRootWebArea; + else if (info_data->IsNode() && parent_map_.at(id) == root_id_) out_data->role = ax::mojom::Role::kRootWebArea; else info_data->PopulateAXRole(out_data); @@ -275,46 +331,44 @@ aura::Window* active_window) const { DCHECK_NE(root_id_, -1); - gfx::Rect node_bounds = info_data->GetBounds(); + gfx::Rect info_data_bounds = info_data->GetBounds(); - if (active_window && info_data->GetId() == root_id_) { - // Top level window returns its bounds in dip. - aura::Window* toplevel_window = active_window->GetToplevelWindow(); - float scale = toplevel_window->layer()->device_scale_factor(); - - views::Widget* widget = - views::Widget::GetWidgetForNativeView(active_window); - DCHECK(widget); - DCHECK(widget->widget_delegate()); - DCHECK(widget->widget_delegate()->GetContentsView()); - const gfx::Rect bounds = - widget->widget_delegate()->GetContentsView()->GetBoundsInScreen(); - - // Bounds of root node is relative to its container, i.e. contents view - // (ShellSurfaceBase). - node_bounds.Offset( - static_cast<int>(-1.0f * scale * static_cast<float>(bounds.x())), - static_cast<int>(-1.0f * scale * static_cast<float>(bounds.y()))); - - // On Android side, content is rendered without considering height of - // caption bar, e.g. content is rendered at y:0 instead of y:32 where 32 is - // height of caption bar. Add back height of caption bar here. - if (widget->IsMaximized()) { - node_bounds.Offset( - 0, static_cast<int>(scale * - static_cast<float>(widget->non_client_view() - ->frame_view() - ->GetBoundsForClientView() - .y()))); - } - - return node_bounds; + if (!active_window) { + gfx::Rect root_bounds = GetRoot()->GetBounds(); + info_data_bounds.Offset(-1 * root_bounds.x(), -1 * root_bounds.y()); + return info_data_bounds; } - // Bounds of non-root node is relative to its tree's root. - gfx::Rect root_bounds = GetFromId(root_id_)->GetBounds(); - node_bounds.Offset(-1 * root_bounds.x(), -1 * root_bounds.y()); - return node_bounds; + // TODO(katie): offset_container_id should work and we shouldn't have to + // go into this code path for each node. + aura::Window* toplevel_window = active_window->GetToplevelWindow(); + float scale = toplevel_window->layer()->device_scale_factor(); + + views::Widget* widget = views::Widget::GetWidgetForNativeView(active_window); + DCHECK(widget); + DCHECK(widget->widget_delegate()); + DCHECK(widget->widget_delegate()->GetContentsView()); + const gfx::Rect bounds = + widget->widget_delegate()->GetContentsView()->GetBoundsInScreen(); + + // Bounds of root node is relative to its container, i.e. contents view + // (ShellSurfaceBase). + info_data_bounds.Offset( + static_cast<int>(-1.0f * scale * static_cast<float>(bounds.x())), + static_cast<int>(-1.0f * scale * static_cast<float>(bounds.y()))); + + // On Android side, content is rendered without considering height of + // caption bar, e.g. content is rendered at y:0 instead of y:32 where 32 is + // height of caption bar. Add back height of caption bar here. + if (widget->IsMaximized()) { + info_data_bounds.Offset( + 0, static_cast<int>(scale * + static_cast<float>(widget->non_client_view() + ->frame_view() + ->GetBoundsForClientView() + .y()))); + } + return info_data_bounds; } gfx::Rect AXTreeSourceArc::ComputeEnclosingBounds( @@ -363,7 +417,7 @@ cached_computed_bounds_.clear(); current_tree_serializer_.reset(new AXTreeArcSerializer(this)); root_id_ = -1; - focused_node_id_ = -1; + focused_id_ = -1; extensions::AutomationEventRouter* router = extensions::AutomationEventRouter::GetInstance(); if (!router)
diff --git a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.h b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.h index c1aeaba..c3a96558 100644 --- a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.h +++ b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.h
@@ -62,10 +62,10 @@ // TODO(katie): should these be "friended" or "protected" instead? ArcAccessibilityInfoData* GetRoot() const override; ArcAccessibilityInfoData* GetFromId(int32_t id) const override; - void SerializeNode(ArcAccessibilityInfoData* node, + void SerializeNode(ArcAccessibilityInfoData* info_data, ui::AXNodeData* out_data) const override; ArcAccessibilityInfoData* GetParent( - ArcAccessibilityInfoData* node) const override; + ArcAccessibilityInfoData* info_data) const override; // Returns bounds of a node which can be passed to AXNodeData.location. Bounds // are returned in the following coordinates depending on whether it's root or @@ -74,7 +74,7 @@ // - Non-root node is relative to the root node of this tree. // // focused_window is nullptr for notification. - const gfx::Rect GetBounds(ArcAccessibilityInfoData* node, + const gfx::Rect GetBounds(ArcAccessibilityInfoData* info_data, aura::Window* focused_window) const; bool is_notification() { return is_notification_; } @@ -84,21 +84,22 @@ class FocusStealer; // AXTreeSource overrides. - int32_t GetId(ArcAccessibilityInfoData* node) const override; + int32_t GetId(ArcAccessibilityInfoData* info_data) const override; void GetChildren( - ArcAccessibilityInfoData* node, + ArcAccessibilityInfoData* info_data, std::vector<ArcAccessibilityInfoData*>* out_children) const override; - bool IsValid(ArcAccessibilityInfoData* node) const override; - bool IsEqual(ArcAccessibilityInfoData* node1, - ArcAccessibilityInfoData* node2) const override; + bool IsValid(ArcAccessibilityInfoData* info_data) const override; + bool IsEqual(ArcAccessibilityInfoData* info_data1, + ArcAccessibilityInfoData* info_data2) const override; ArcAccessibilityInfoData* GetNull() const override; - // Computes the smallest rect that encloses all of the descendants of |node|. - gfx::Rect ComputeEnclosingBounds(ArcAccessibilityInfoData* node) const; + // Computes the smallest rect that encloses all of the descendants of + // |info_data|. + gfx::Rect ComputeEnclosingBounds(ArcAccessibilityInfoData* info_data) const; - // Helper to recursively compute bounds for |node|. Returns true if non-empty - // bounds were encountered. - void ComputeEnclosingBoundsInternal(ArcAccessibilityInfoData* node, + // Helper to recursively compute bounds for |info_data|. Returns true if + // non-empty bounds were encountered. + void ComputeEnclosingBoundsInternal(ArcAccessibilityInfoData* info_data, gfx::Rect& computed_bounds) const; // AXHostDelegate overrides. @@ -115,7 +116,7 @@ std::unique_ptr<AXTreeArcSerializer> current_tree_serializer_; int32_t root_id_; int32_t window_id_; - int32_t focused_node_id_; + int32_t focused_id_; bool is_notification_; // A delegate that handles accessibility actions on behalf of this tree. The
diff --git a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc_unittest.cc b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc_unittest.cc index a5372dd..53f3ccd 100644 --- a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc_unittest.cc +++ b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc_unittest.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.h" #include "chrome/browser/chromeos/arc/accessibility/accessibility_node_info_data_wrapper.h" +#include "chrome/browser/chromeos/arc/accessibility/accessibility_window_info_data_wrapper.h" #include "components/arc/common/accessibility_helper.mojom.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/accessibility/platform/ax_android_constants.h" @@ -22,6 +23,9 @@ using AXRangeInfoData = mojom::AccessibilityRangeInfoData; using AXStringListProperty = mojom::AccessibilityStringListProperty; using AXStringProperty = mojom::AccessibilityStringProperty; +using AXWindowInfoData = mojom::AccessibilityWindowInfoData; +using AXWindowIntListProperty = mojom::AccessibilityWindowIntListProperty; +using AXWindowStringProperty = mojom::AccessibilityWindowStringProperty; void SetProperty(AXNodeInfoData* node, AXBooleanProperty prop, bool value) { if (!node->boolean_properties) { @@ -46,6 +50,16 @@ node->int_properties.value().insert(std::make_pair(prop, value)); } +void SetProperty(AXWindowInfoData* window, + AXWindowStringProperty prop, + const std::string& value) { + if (!window->string_properties) { + window->string_properties = + base::flat_map<AXWindowStringProperty, std::string>(); + } + window->string_properties.value().insert(std::make_pair(prop, value)); +} + void SetProperty(AXNodeInfoData* node, AXIntListProperty prop, const std::vector<int>& value) { @@ -56,6 +70,16 @@ node->int_list_properties.value().insert(std::make_pair(prop, value)); } +void SetProperty(AXWindowInfoData* window, + AXWindowIntListProperty prop, + const std::vector<int>& value) { + if (!window->int_list_properties) { + window->int_list_properties = + base::flat_map<AXWindowIntListProperty, std::vector<int>>(); + } + window->int_list_properties.value().insert(std::make_pair(prop, value)); +} + class AXTreeSourceArcTest : public testing::Test, public AXTreeSourceArc::Delegate { public: @@ -67,13 +91,13 @@ } void CallGetChildren( - mojom::AccessibilityNodeInfoData* node, + AXNodeInfoData* node, std::vector<ArcAccessibilityInfoData*>* out_children) const { AccessibilityNodeInfoDataWrapper node_data(tree_.get(), node); tree_->GetChildren(&node_data, out_children); } - void CallSerializeNode(mojom::AccessibilityNodeInfoData* node, + void CallSerializeNode(AXNodeInfoData* node, std::unique_ptr<ui::AXNodeData>* out_data) const { ASSERT_TRUE(out_data); AccessibilityNodeInfoDataWrapper node_data(tree_.get(), node); @@ -81,10 +105,22 @@ tree_->SerializeNode(&node_data, out_data->get()); } + void CallSerializeWindow(AXWindowInfoData* window, + std::unique_ptr<ui::AXNodeData>* out_data) const { + ASSERT_TRUE(out_data); + AccessibilityWindowInfoDataWrapper window_data(tree_.get(), window); + *out_data = std::make_unique<ui::AXNodeData>(); + tree_->SerializeNode(&window_data, out_data->get()); + } + ArcAccessibilityInfoData* CallGetFromId(int32_t id) const { return tree_->GetFromId(id); } + bool CallGetTreeData(ui::AXTreeData* data) { + return tree_->GetTreeData(data); + } + private: void OnAction(const ui::AXActionData& data) const override {} @@ -99,6 +135,12 @@ event->task_id = 1; event->event_type = AXEventType::VIEW_FOCUSED; + event->window_data = std::vector<mojom::AccessibilityWindowInfoDataPtr>(); + event->window_data->push_back(AXWindowInfoData::New()); + AXWindowInfoData* root_window = event->window_data->back().get(); + root_window->window_id = 100; + root_window->root_node_id = 0; + event->node_data.push_back(AXNodeInfoData::New()); AXNodeInfoData* root = event->node_data.back().get(); root->id = 0; @@ -247,8 +289,6 @@ // Populate the tree source with the data. CallNotifyAccessibilityEvent(event.get()); - // Live edit name related attributes. - // No attributes. std::unique_ptr<ui::AXNodeData> data; CallSerializeNode(root, &data); @@ -262,7 +302,7 @@ CallSerializeNode(root, &data); ASSERT_TRUE( data->GetStringAttribute(ax::mojom::StringAttribute::kName, &name)); - ASSERT_EQ("", name); + EXPECT_EQ("", name); // Text (non-empty). root->string_properties->clear(); @@ -271,7 +311,7 @@ CallSerializeNode(root, &data); ASSERT_TRUE( data->GetStringAttribute(ax::mojom::StringAttribute::kName, &name)); - ASSERT_EQ("label text", name); + EXPECT_EQ("label text", name); // Content description (empty), text (non-empty). SetProperty(root, AXStringProperty::CONTENT_DESCRIPTION, ""); @@ -279,7 +319,7 @@ CallSerializeNode(root, &data); ASSERT_TRUE( data->GetStringAttribute(ax::mojom::StringAttribute::kName, &name)); - ASSERT_EQ("label text", name); + EXPECT_EQ("label text", name); // Content description (non-empty), text (non-empty). root->string_properties.value()[AXStringProperty::CONTENT_DESCRIPTION] = @@ -288,7 +328,7 @@ CallSerializeNode(root, &data); ASSERT_TRUE( data->GetStringAttribute(ax::mojom::StringAttribute::kName, &name)); - ASSERT_EQ("label content description", name); + EXPECT_EQ("label content description", name); // Name from contents. @@ -321,8 +361,111 @@ data->GetStringAttribute(ax::mojom::StringAttribute::kName, &name)); } +TEST_F(AXTreeSourceArcTest, AccessibleNameComputationWindow) { + auto event = AXEventData::New(); + event->source_id = 0; + event->task_id = 1; + event->event_type = AXEventType::VIEW_FOCUSED; + event->window_data = std::vector<mojom::AccessibilityWindowInfoDataPtr>(); + event->window_data->push_back(AXWindowInfoData::New()); + AXWindowInfoData* root = event->window_data->back().get(); + root->window_id = 0; + + CallNotifyAccessibilityEvent(event.get()); + + // Live edit name related attributes. + + // No attributes. + std::unique_ptr<ui::AXNodeData> data; + CallSerializeWindow(root, &data); + std::string name; + ASSERT_FALSE( + data->GetStringAttribute(ax::mojom::StringAttribute::kName, &name)); + + // Title attribute + SetProperty(root, AXWindowStringProperty::TITLE, "window title"); + CallSerializeWindow(root, &data); + ASSERT_TRUE( + data->GetStringAttribute(ax::mojom::StringAttribute::kName, &name)); + EXPECT_EQ("window title", name); +} + +TEST_F(AXTreeSourceArcTest, AccessibleNameComputationWindowWithChildren) { + auto event = AXEventData::New(); + event->source_id = 3; + event->task_id = 1; + event->event_type = AXEventType::VIEW_FOCUSED; + event->window_data = std::vector<mojom::AccessibilityWindowInfoDataPtr>(); + event->window_data->push_back(AXWindowInfoData::New()); + AXWindowInfoData* root = event->window_data->back().get(); + root->window_id = 0; + root->root_node_id = 3; + SetProperty(root, AXWindowIntListProperty::CHILD_WINDOW_IDS, {2, 5}); + SetProperty(root, AXWindowStringProperty::TITLE, "window title"); + + // Add a child window. + event->window_data->push_back(AXWindowInfoData::New()); + AXWindowInfoData* child = event->window_data->back().get(); + child->window_id = 2; + child->root_node_id = 4; + SetProperty(child, AXWindowStringProperty::TITLE, "child window title"); + + // Add a child node. + event->node_data.push_back(AXNodeInfoData::New()); + AXNodeInfoData* node = event->node_data.back().get(); + node->id = 3; + SetProperty(node, AXStringProperty::TEXT, "node text"); + + // Add a child node to the child window as well. + event->node_data.push_back(AXNodeInfoData::New()); + AXNodeInfoData* child_node = event->node_data.back().get(); + child_node->id = 4; + SetProperty(child_node, AXStringProperty::TEXT, "child node text"); + + // Add a child window with no children as well. + event->window_data->push_back(AXWindowInfoData::New()); + AXWindowInfoData* child2 = event->window_data->back().get(); + child2->window_id = 5; + SetProperty(child2, AXWindowStringProperty::TITLE, "child2 window title"); + + CallNotifyAccessibilityEvent(event.get()); + std::unique_ptr<ui::AXNodeData> data; + std::string name; + + CallSerializeWindow(root, &data); + ASSERT_TRUE( + data->GetStringAttribute(ax::mojom::StringAttribute::kName, &name)); + EXPECT_EQ("window title", name); + EXPECT_NE(ax::mojom::Role::kRootWebArea, data->role); + + CallSerializeWindow(child, &data); + ASSERT_TRUE( + data->GetStringAttribute(ax::mojom::StringAttribute::kName, &name)); + EXPECT_EQ("child window title", name); + EXPECT_NE(ax::mojom::Role::kRootWebArea, data->role); + + CallSerializeNode(node, &data); + ASSERT_TRUE( + data->GetStringAttribute(ax::mojom::StringAttribute::kName, &name)); + EXPECT_EQ("node text", name); + EXPECT_EQ(ax::mojom::Role::kRootWebArea, data->role); + + CallSerializeNode(child_node, &data); + ASSERT_TRUE( + data->GetStringAttribute(ax::mojom::StringAttribute::kName, &name)); + EXPECT_EQ("child node text", name); + EXPECT_NE(ax::mojom::Role::kRootWebArea, data->role); + + CallSerializeWindow(child2, &data); + ASSERT_TRUE( + data->GetStringAttribute(ax::mojom::StringAttribute::kName, &name)); + EXPECT_EQ("child2 window title", name); + EXPECT_NE(ax::mojom::Role::kRootWebArea, data->role); +} + // TODO(katie): Maybe remove this test when adding AccessibilityWindowInfoData -// support per go/a11y-arc++-window-mapping if it is no longer needed. +// support per go/a11y-arc++-window-mapping if it is no longer needed. This +// depends on if we can assume that each tree has exactly one root. TEST_F(AXTreeSourceArcTest, MultipleNodeSubtrees) { // Run several times to try source_id from root, middle, or leaf of the tree. int tree_size = 4; @@ -383,4 +526,103 @@ } } +TEST_F(AXTreeSourceArcTest, ComplexTreeStructure) { + int tree_size = 4; + int num_trees = 3; + + auto event = AXEventData::New(); + event->source_id = 4; + event->task_id = 1; + event->event_type = AXEventType::VIEW_FOCUSED; + event->window_data = std::vector<mojom::AccessibilityWindowInfoDataPtr>(); + event->window_data->push_back(AXWindowInfoData::New()); + AXWindowInfoData* root_window = event->window_data->back().get(); + // Pick large numbers for the IDs so as not to overlap. + root_window->window_id = 1000; + SetProperty(root_window, AXWindowIntListProperty::CHILD_WINDOW_IDS, + {100, 200, 300}); + + // Make three non-overlapping trees rooted at the same window. One tree has + // the source_id of interest. Each subtree has a root window, which has a + // root node with one child, and that child has two leaf children. + for (int i = 0; i < num_trees; i++) { + event->window_data->push_back(AXWindowInfoData::New()); + AXWindowInfoData* child_window = event->window_data->back().get(); + child_window->window_id = (i + 1) * 100; + child_window->root_node_id = i * tree_size + 1; + + event->node_data.push_back(AXNodeInfoData::New()); + AXNodeInfoData* root = event->node_data.back().get(); + root->id = i * tree_size + 1; + root->window_id = (i + 1) * 100; + SetProperty(root, AXIntListProperty::CHILD_NODE_IDS, + std::vector<int>({i * tree_size + 2})); + + event->node_data.push_back(AXNodeInfoData::New()); + AXNodeInfoData* child1 = event->node_data.back().get(); + child1->id = i * tree_size + 2; + SetProperty(child1, AXIntListProperty::CHILD_NODE_IDS, + std::vector<int>({i * tree_size + 3, i * tree_size + 4})); + + event->node_data.push_back(AXNodeInfoData::New()); + AXNodeInfoData* child2 = event->node_data.back().get(); + child2->id = i * tree_size + 3; + + event->node_data.push_back(AXNodeInfoData::New()); + AXNodeInfoData* child3 = event->node_data.back().get(); + child3->id = i * tree_size + 4; + } + + CallNotifyAccessibilityEvent(event.get()); + + // Check that each node subtree tree was added, and that it is correct. + std::vector<ArcAccessibilityInfoData*> children; + for (int i = 0; i < num_trees; i++) { + CallGetChildren(event->node_data.at(i * tree_size).get(), &children); + ASSERT_EQ(1U, children.size()); + EXPECT_EQ(i * tree_size + 2, children[0]->GetId()); + children.clear(); + CallGetChildren(event->node_data.at(i * tree_size + 1).get(), &children); + ASSERT_EQ(2U, children.size()); + EXPECT_EQ(i * tree_size + 3, children[0]->GetId()); + EXPECT_EQ(i * tree_size + 4, children[1]->GetId()); + children.clear(); + } +} + +TEST_F(AXTreeSourceArcTest, GetTreeDataAppliesFocus) { + auto event = AXEventData::New(); + event->source_id = 5; + event->task_id = 1; + event->event_type = AXEventType::VIEW_FOCUSED; + event->window_data = std::vector<mojom::AccessibilityWindowInfoDataPtr>(); + event->window_data->push_back(AXWindowInfoData::New()); + AXWindowInfoData* root = event->window_data->back().get(); + root->window_id = 5; + SetProperty(root, AXWindowIntListProperty::CHILD_WINDOW_IDS, {1}); + + // Add a child window. + event->window_data->push_back(AXWindowInfoData::New()); + AXWindowInfoData* child = event->window_data->back().get(); + child->window_id = 1; + + CallNotifyAccessibilityEvent(event.get()); + ui::AXTreeData data; + + // Nothing should be focused when there are no nodes. + EXPECT_TRUE(CallGetTreeData(&data)); + EXPECT_EQ(-1, data.focus_id); + + // Add a child node. + root->root_node_id = 2; + event->node_data.push_back(AXNodeInfoData::New()); + AXNodeInfoData* node = event->node_data.back().get(); + node->id = 2; + + CallNotifyAccessibilityEvent(event.get()); + + EXPECT_TRUE(CallGetTreeData(&data)); + EXPECT_EQ(2, data.focus_id); +} + } // namespace arc
diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl.cc b/chrome/browser/chromeos/input_method/input_method_manager_impl.cc index 0e46ef39..44a16b2 100644 --- a/chrome/browser/chromeos/input_method/input_method_manager_impl.cc +++ b/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
@@ -1393,13 +1393,17 @@ ui::InputMethodKeyboardController* InputMethodManagerImpl::GetInputMethodKeyboardController() { + // TODO(stevenjb/shuchen): Fix this for Mash. https://crbug.com/756059 + if (features::IsMultiProcessMash()) + return nullptr; // Callers expect a nullptr when the keyboard is disabled. See - // https://crbug.com/850020. TODO(stevenjb/shuchen): Fix this for Mash. - // https://crbug.com/756059 - return keyboard::KeyboardController::HasInstance() && - keyboard::KeyboardController::Get()->IsEnabled() - ? keyboard::KeyboardController::Get() - : nullptr; + // https://crbug.com/850020. + if (!keyboard::KeyboardController::HasInstance() || + !keyboard::KeyboardController::Get()->IsEnabled()) { + return nullptr; + } + return keyboard::KeyboardController::Get() + ->input_method_keyboard_controller(); } void InputMethodManagerImpl::ReloadKeyboard() {
diff --git a/chrome/browser/chromeos/policy/policy_cert_service.cc b/chrome/browser/chromeos/policy/policy_cert_service.cc index e7468ac..08a1669 100644 --- a/chrome/browser/chromeos/policy/policy_cert_service.cc +++ b/chrome/browser/chromeos/policy/policy_cert_service.cc
@@ -10,7 +10,6 @@ #include "base/memory/ptr_util.h" #include "base/task/post_task.h" #include "chrome/browser/chromeos/policy/policy_cert_service_factory.h" -#include "chrome/browser/chromeos/policy/temp_certs_cache_nss.h" #include "chrome/browser/net/profile_network_context_service.h" #include "chrome/browser/net/profile_network_context_service_factory.h" #include "chrome/browser/profiles/profile.h" @@ -19,6 +18,7 @@ #include "content/public/browser/browser_thread.h" #include "net/cert/x509_certificate.h" #include "services/network/cert_verifier_with_trust_anchors.h" +#include "services/network/nss_temp_certs_cache_chromeos.h" #include "services/network/public/cpp/features.h" namespace policy { @@ -110,7 +110,9 @@ // expecting that the operation of creating in-memory NSS certs is cheap in // that case. temp_policy_provided_certs_ = - std::make_unique<TempCertsCacheNSS>(all_server_and_authority_certs); + std::make_unique<network::NSSTempCertsCacheChromeOS>( + all_server_and_authority_certs); + all_server_and_authority_certs_ = all_server_and_authority_certs; // Do not use certificates installed via ONC policy if the current session has // multiple profiles. This is important to make sure that any possibly tainted @@ -119,17 +121,18 @@ if (!trust_anchors.empty() && user_manager_->GetLoggedInUsers().size() > 1u) { LOG(ERROR) << "Ignoring ONC-pushed certificates update because multiple " << "users are logged in."; - return; + trust_anchors_.clear(); + } else { + trust_anchors_ = trust_anchors; } - trust_anchors_ = trust_anchors; - if (!notify) return; if (base::FeatureList::IsEnabled(network::features::kNetworkService)) { ProfileNetworkContextServiceFactory::GetForContext(profile_) - ->UpdateTrustAnchors(trust_anchors_); + ->UpdateAdditionalCertificates(all_server_and_authority_certs_, + trust_anchors_); return; }
diff --git a/chrome/browser/chromeos/policy/policy_cert_service.h b/chrome/browser/chromeos/policy/policy_cert_service.h index 22b9d595..0fdae41 100644 --- a/chrome/browser/chromeos/policy/policy_cert_service.h +++ b/chrome/browser/chromeos/policy/policy_cert_service.h
@@ -30,10 +30,10 @@ namespace network { class CertVerifierWithTrustAnchors; +class NSSTempCertsCacheChromeOS; } namespace policy { -class TempCertsCacheNSS; // This service is the counterpart of PolicyCertVerifier on the UI thread. It's // responsible for pushing the current list of trust anchors to the CertVerifier @@ -66,6 +66,9 @@ bool has_policy_certificates() const { return !trust_anchors_.empty(); } + const net::CertificateList& all_server_and_authority_certs() const { + return all_server_and_authority_certs_; + } const net::CertificateList& trust_anchors() const { return trust_anchors_; } // UserNetworkConfigurationUpdater::PolicyProvidedCertsObserver: @@ -97,12 +100,14 @@ std::string user_id_; UserNetworkConfigurationUpdater* net_conf_updater_; user_manager::UserManager* user_manager_; + net::CertificateList all_server_and_authority_certs_; net::CertificateList trust_anchors_; // Holds all policy-provided server and authority certificates and makes them // available to NSS as temp certificates. This is needed so they can be used // as intermediates when NSS verifies a certificate. - std::unique_ptr<TempCertsCacheNSS> temp_policy_provided_certs_; + std::unique_ptr<network::NSSTempCertsCacheChromeOS> + temp_policy_provided_certs_; // Weak pointers to handle callbacks from PolicyCertVerifier on the IO thread. // The factory and the created WeakPtrs must only be used on the UI thread.
diff --git a/chrome/browser/chromeos/policy/temp_certs_cache_nss.cc b/chrome/browser/chromeos/policy/temp_certs_cache_nss.cc deleted file mode 100644 index efafe06..0000000 --- a/chrome/browser/chromeos/policy/temp_certs_cache_nss.cc +++ /dev/null
@@ -1,31 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/chromeos/policy/temp_certs_cache_nss.h" - -#include "chrome/browser/browser_process.h" -#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" -#include "chrome/browser/chromeos/policy/device_network_configuration_updater.h" -#include "chromeos/network/onc/onc_utils.h" -#include "net/cert/x509_util_nss.h" - -namespace policy { - -TempCertsCacheNSS::TempCertsCacheNSS(const net::CertificateList& certificates) { - for (const auto& certificate : certificates) { - net::ScopedCERTCertificate x509_cert = - net::x509_util::CreateCERTCertificateFromX509Certificate( - certificate.get()); - if (!x509_cert) { - LOG(ERROR) << "Unable to create CERTCertificate"; - continue; - } - - temp_certs_.push_back(std::move(x509_cert)); - } -} - -TempCertsCacheNSS::~TempCertsCacheNSS() {} - -} // namespace policy
diff --git a/chrome/browser/chromeos/policy/user_network_configuration_updater_factory_browsertest.cc b/chrome/browser/chromeos/policy/user_network_configuration_updater_factory_browsertest.cc index 7c6ae90..c70e2ce 100644 --- a/chrome/browser/chromeos/policy/user_network_configuration_updater_factory_browsertest.cc +++ b/chrome/browser/chromeos/policy/user_network_configuration_updater_factory_browsertest.cc
@@ -68,15 +68,20 @@ namespace { // Test data file storing an ONC blob with an Authority certificate. -constexpr char kRootCertOnc[] = "root-ca-cert.onc"; +constexpr char kRootCaCertOnc[] = "root-ca-cert.onc"; constexpr char kClientCertOnc[] = "certificate-client.onc"; +constexpr char kRootAndIntermediateCaCertsOnc[] = + "root-and-intermediate-ca-certs.onc"; constexpr char kClientCertSubjectCommonName[] = "lmao"; constexpr char kNetworkComponentDirectory[] = "network"; // A PEM-encoded certificate which was signed by the Authority specified in -// |kRootCertOnc|. -constexpr char kGoodCert[] = "ok_cert.pem"; -// The PEM-encoded Authority certificate specified by |kRootCertOnc|. -constexpr char kRootCert[] = "root_ca_cert.pem"; +// |kRootCaCertOnc|. +constexpr char kServerCert[] = "ok_cert.pem"; +// A PEM-encoded certificate which was signed by the intermediate Authority +// specified in |kRootAndIntermediateCaCertsOnc|. +constexpr char kServerCertByIntermediate[] = "ok_cert_by_intermediate.pem"; +// The PEM-encoded Authority certificate specified by |kRootCaCertOnc|. +constexpr char kRootCaCert[] = "root_ca_cert.pem"; constexpr char kDeviceLocalAccountId[] = "dla1@example.com"; // Allows waiting until the list of policy-pushed web-trusted certificates @@ -147,23 +152,29 @@ }; // Allows setting user policy to assign trust to the CA certificate specified by -// |kRootCert|. +// |kRootCaCert|. class UserPolicyCertsHelper { public: UserPolicyCertsHelper() { - base::FilePath server_cert_pem_file_path; - chromeos::test_utils::GetTestDataPath(kNetworkComponentDirectory, kGoodCert, - &server_cert_pem_file_path); - test_server_cert_ = - net::ImportCertFromFile(server_cert_pem_file_path.DirName(), - server_cert_pem_file_path.BaseName().value()); + base::FilePath server_cert_path; + chromeos::test_utils::GetTestDataPath(kNetworkComponentDirectory, + kServerCert, &server_cert_path); + server_cert_ = net::ImportCertFromFile(server_cert_path.DirName(), + server_cert_path.BaseName().value()); - base::FilePath root_cert_pem_file_path; - chromeos::test_utils::GetTestDataPath(kNetworkComponentDirectory, kRootCert, - &root_cert_pem_file_path); - test_root_cert_ = - net::ImportCertFromFile(root_cert_pem_file_path.DirName(), - root_cert_pem_file_path.BaseName().value()); + base::FilePath root_cert_path; + chromeos::test_utils::GetTestDataPath(kNetworkComponentDirectory, + kRootCaCert, &root_cert_path); + root_cert_ = net::ImportCertFromFile(root_cert_path.DirName(), + root_cert_path.BaseName().value()); + + base::FilePath server_cert_by_intermediate_path; + chromeos::test_utils::GetTestDataPath(kNetworkComponentDirectory, + kServerCertByIntermediate, + &server_cert_by_intermediate_path); + server_cert_by_intermediate_ = net::ImportCertFromFile( + server_cert_path.DirName(), + server_cert_by_intermediate_path.BaseName().value()); } // Installs the BrowserPolicyConnector to set user policy. @@ -176,10 +187,36 @@ BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_); } - // Sets the ONC-policy to the blob defined by |kRootCertOnc| and waits until + // Sets the ONC-policy to the blob defined by |kRootCaCertOnc| and waits until // the notification that policy-provided trust roots have changed is sent from // |profile|'s UserNetworkConfigurationUpdater. void SetRootCertONCUserPolicy(Profile* profile) { + std::string onc_policy_data = + chromeos::onc::test_utils::ReadTestData(kRootCaCertOnc); + SetONCUserPolicy(profile, onc_policy_data); + } + + // Sets the ONC-policy to the blob defined by |kRootCaCertOnc| and waits until + // the notification that policy-provided trust roots have changed is sent from + // |profile|'s UserNetworkConfigurationUpdater. + void SetRootAndIntermediateCertsONCUserPolicy(Profile* profile) { + std::string onc_policy_data = + chromeos::onc::test_utils::ReadTestData(kRootAndIntermediateCaCertsOnc); + SetONCUserPolicy(profile, onc_policy_data); + } + + const scoped_refptr<net::X509Certificate>& server_cert() { + return server_cert_; + } + + const scoped_refptr<net::X509Certificate>& root_cert() { return root_cert_; } + + const scoped_refptr<net::X509Certificate>& server_cert_by_intermediate() { + return server_cert_by_intermediate_; + } + + private: + void SetONCUserPolicy(Profile* profile, const std::string& onc_policy_data) { ASSERT_TRUE(is_set_up_); UserNetworkConfigurationUpdater* user_network_configuration_updater = UserNetworkConfigurationUpdaterFactory::GetForBrowserContext(profile); @@ -188,12 +225,10 @@ user_network_configuration_updater->AddPolicyProvidedCertsObserver( &trust_roots_changed_observer); - const std::string& user_policy_blob = - chromeos::onc::test_utils::ReadTestData(kRootCertOnc); policy::PolicyMap policy; policy.Set(key::kOpenNetworkConfiguration, policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD, - std::make_unique<base::Value>(user_policy_blob), nullptr); + std::make_unique<base::Value>(onc_policy_data), nullptr); provider_.UpdateChromePolicy(policy); // Note that this relies on the implementation detail that the notification // is sent even if the trust roots effectively remain the same. @@ -202,25 +237,23 @@ &trust_roots_changed_observer); } - const scoped_refptr<net::X509Certificate>& test_server_cert() { - return test_server_cert_; - } - - const scoped_refptr<net::X509Certificate>& test_root_cert() { - return test_root_cert_; - } - - private: // This is set to true when |SetUpInProcessBrowserTestFixture| has been // called. bool is_set_up_ = false; MockConfigurationPolicyProvider provider_; - // Server Certificate which is signed by authority specified in |kRootCert|. - scoped_refptr<net::X509Certificate> test_server_cert_; - // Authority Certificate specified in |kRootCert|. - scoped_refptr<net::X509Certificate> test_root_cert_; + // Server Certificate which is signed by authority specified in |kRootCaCert|. + scoped_refptr<net::X509Certificate> server_cert_; + // Authority Certificate specified in |kRootCaCert|. + scoped_refptr<net::X509Certificate> root_cert_; + // Server Certificate which is signed by an intermediate authority, which + // itself is signed by the authority specified in |kRootCaCert|. + // |kRootCaCertOnc| does not know this intermediate authority. + // |kRootCaAndIntermediateCertsOnc| does know this intermediate authority, but + // does not request web trust for it. Instead, trust should be delegate from + // the root authrotiy. + scoped_refptr<net::X509Certificate> server_cert_by_intermediate_; }; // Verifies |certificate| with |profile|'s CertVerifier and returns the result. @@ -338,11 +371,31 @@ }; IN_PROC_BROWSER_TEST_F(PolicyProvidedTrustAnchorsRegularUserTest, - AllowedForRegularUser) { + TrustAnchorApplied) { user_policy_certs_helper_.SetRootCertONCUserPolicy(browser()->profile()); EXPECT_EQ(net::OK, VerifyTestServerCert(browser()->profile(), - user_policy_certs_helper_.test_server_cert())); + user_policy_certs_helper_.server_cert())); +} + +IN_PROC_BROWSER_TEST_F(PolicyProvidedTrustAnchorsRegularUserTest, + UntrustedIntermediateAuthorityApplied) { + // Sanity check: Apply ONC policy which does not mention the intermediate + // authority. + user_policy_certs_helper_.SetRootCertONCUserPolicy(browser()->profile()); + EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID, + VerifyTestServerCert( + browser()->profile(), + user_policy_certs_helper_.server_cert_by_intermediate())); + + // Now apply ONC policy which mentions the intermediate authority (but does + // not assign trust to it). + user_policy_certs_helper_.SetRootAndIntermediateCertsONCUserPolicy( + browser()->profile()); + EXPECT_EQ(net::OK, + VerifyTestServerCert( + browser()->profile(), + user_policy_certs_helper_.server_cert_by_intermediate())); } IN_PROC_BROWSER_TEST_F(PolicyProvidedTrustAnchorsRegularUserTest, @@ -355,7 +408,7 @@ chromeos::NetworkCertLoader::Get()->SetUserNSSDB(test_nss_cert_db_.get()); EXPECT_FALSE( - IsCertInCertificateList(user_policy_certs_helper_.test_root_cert().get(), + IsCertInCertificateList(user_policy_certs_helper_.root_cert().get(), chromeos::NetworkCertLoader::Get()->all_certs())); NetworkCertLoaderTestObserver network_cert_loader_observer( chromeos::NetworkCertLoader::Get()); @@ -366,7 +419,7 @@ // (Web Trust does not matter for the NetworkCertLoader, but we currently only // set a policy with a certificate requesting Web Trust here). EXPECT_TRUE( - IsCertInCertificateList(user_policy_certs_helper_.test_root_cert().get(), + IsCertInCertificateList(user_policy_certs_helper_.root_cert().get(), chromeos::NetworkCertLoader::Get()->all_certs())); } @@ -503,7 +556,7 @@ user_policy_certs_helper_.SetRootCertONCUserPolicy(browser->profile()); EXPECT_EQ(net::OK, VerifyTestServerCert(browser->profile(), - user_policy_certs_helper_.test_server_cert())); + user_policy_certs_helper_.server_cert())); } class PolicyProvidedTrustAnchorsOnUserSessionInitTest @@ -530,7 +583,7 @@ void GetMandatoryPoliciesValue(base::DictionaryValue* policy) const override { const std::string& user_policy_blob = - chromeos::onc::test_utils::ReadTestData(kRootCertOnc); + chromeos::onc::test_utils::ReadTestData(kRootCaCertOnc); policy->SetKey(key::kOpenNetworkConfiguration, base::Value(user_policy_blob)); } @@ -584,12 +637,11 @@ TrustAnchorsAvailableImmediatelyAfterSessionStart) { // Load the certificate which is only OK if the policy-provided authority is // actually trusted. - base::FilePath cert_pem_file_path; - chromeos::test_utils::GetTestDataPath(kNetworkComponentDirectory, kGoodCert, - &cert_pem_file_path); - scoped_refptr<net::X509Certificate> test_server_cert = - net::ImportCertFromFile(cert_pem_file_path.DirName(), - cert_pem_file_path.BaseName().value()); + base::FilePath cert_path; + chromeos::test_utils::GetTestDataPath(kNetworkComponentDirectory, kServerCert, + &cert_path); + scoped_refptr<net::X509Certificate> server_cert = net::ImportCertFromFile( + cert_path.DirName(), cert_path.BaseName().value()); SkipToLoginScreen(); TriggerLogIn(); @@ -597,8 +649,7 @@ EXPECT_FALSE(user_session_started()); WaitSessionStart(); - EXPECT_EQ(net::OK, - VerifyTestServerCert(active_user_profile(), test_server_cert)); + EXPECT_EQ(net::OK, VerifyTestServerCert(active_user_profile(), server_cert)); } // Testing policy-provided client cert import.
diff --git a/chrome/browser/chromeos/power/extension_event_observer_unittest.cc b/chrome/browser/chromeos/power/extension_event_observer_unittest.cc index e47ae2d7..08e2b133 100644 --- a/chrome/browser/chromeos/power/extension_event_observer_unittest.cc +++ b/chrome/browser/chromeos/power/extension_event_observer_unittest.cc
@@ -15,6 +15,7 @@ #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h" #include "chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h" #include "chrome/common/extensions/api/gcm.h" +#include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile_manager.h" @@ -32,39 +33,28 @@ #include "extensions/common/manifest_handlers/background_info.h" #include "extensions/common/value_builder.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/aura/test/test_screen.h" -#include "ui/display/screen.h" namespace chromeos { -class ExtensionEventObserverTest : public ::testing::Test { +class ExtensionEventObserverTest : public ChromeRenderViewHostTestHarness { public: ExtensionEventObserverTest() : power_manager_client_(new FakePowerManagerClient()), - test_screen_(aura::TestScreen::Create(gfx::Size())), fake_user_manager_(new FakeChromeUserManager()), - scoped_user_manager_enabler_(base::WrapUnique(fake_user_manager_)) { + scoped_user_manager_enabler_(base::WrapUnique(fake_user_manager_)) {} + + ~ExtensionEventObserverTest() override = default; + + // ChromeRenerViewHostTestHarness overrides: + void SetUp() override { + ChromeRenderViewHostTestHarness::SetUp(); + DBusThreadManager::GetSetterForTesting()->SetPowerManagerClient( base::WrapUnique(power_manager_client_)); - - profile_manager_.reset( - new TestingProfileManager(TestingBrowserProcess::GetGlobal())); - - extension_event_observer_.reset(new ExtensionEventObserver()); + profile_manager_ = std::make_unique<TestingProfileManager>( + TestingBrowserProcess::GetGlobal()); + extension_event_observer_ = std::make_unique<ExtensionEventObserver>(); test_api_ = extension_event_observer_->CreateTestApi(); - } - - ~ExtensionEventObserverTest() override { - extension_event_observer_.reset(); - profile_manager_.reset(); - DBusThreadManager::Shutdown(); - } - - // ::testing::Test overrides. - void SetUp() override { - ::testing::Test::SetUp(); - - display::Screen::SetScreenInstance(test_screen_.get()); // Must be called from ::testing::Test::SetUp. ASSERT_TRUE(profile_manager_->SetUp()); @@ -79,10 +69,12 @@ profile_manager_->SetLoggedIn(true); } void TearDown() override { + extension_event_observer_.reset(); profile_ = NULL; profile_manager_->DeleteAllTestingProfiles(); - display::Screen::SetScreenInstance(nullptr); - ::testing::Test::TearDown(); + profile_manager_.reset(); + DBusThreadManager::Shutdown(); + ChromeRenderViewHostTestHarness::TearDown(); } protected: @@ -137,13 +129,6 @@ std::unique_ptr<TestingProfileManager> profile_manager_; private: - std::unique_ptr<aura::TestScreen> test_screen_; - content::TestBrowserThreadBundle browser_thread_bundle_; - - // Needed to ensure we don't end up creating actual RenderViewHosts - // and RenderProcessHosts. - content::RenderViewHostTestEnabler render_view_host_test_enabler_; - // Chrome OS needs the CrosSettings test helper. ScopedCrosSettingsTestHelper cros_settings_test_helper_;
diff --git a/chrome/browser/conflicts/module_blacklist_cache_updater_win.cc b/chrome/browser/conflicts/module_blacklist_cache_updater_win.cc index 8b5a795..30a7ce2e 100644 --- a/chrome/browser/conflicts/module_blacklist_cache_updater_win.cc +++ b/chrome/browser/conflicts/module_blacklist_cache_updater_win.cc
@@ -135,13 +135,13 @@ base::i18n::ToLower(module_key.module_path.BaseName().value())); base::SHA1HashBytes(reinterpret_cast<const uint8_t*>(module_basename.data()), module_basename.length(), - packed_list_module->basename_hash); + &packed_list_module->basename_hash[0]); // Hash the code id. const std::string module_code_id = GenerateCodeId(module_key); base::SHA1HashBytes(reinterpret_cast<const uint8_t*>(module_code_id.data()), module_code_id.length(), - packed_list_module->code_id_hash); + &packed_list_module->code_id_hash[0]); packed_list_module->time_date_stamp = CalculateTimeDateStamp(base::Time::Now());
diff --git a/chrome/browser/conflicts/module_blacklist_cache_updater_win_unittest.cc b/chrome/browser/conflicts/module_blacklist_cache_updater_win_unittest.cc index c3dfab2..d4d7fc03 100644 --- a/chrome/browser/conflicts/module_blacklist_cache_updater_win_unittest.cc +++ b/chrome/browser/conflicts/module_blacklist_cache_updater_win_unittest.cc
@@ -349,10 +349,10 @@ const std::string module_basename = base::UTF16ToUTF8( base::i18n::ToLower(module_key2.module_path.BaseName().value())); base::SHA1HashBytes(reinterpret_cast<const uint8_t*>(module_basename.data()), - module_basename.length(), expected.basename_hash); + module_basename.length(), &expected.basename_hash[0]); const std::string module_code_id = GenerateCodeId(module_key2); base::SHA1HashBytes(reinterpret_cast<const uint8_t*>(module_code_id.data()), - module_code_id.length(), expected.code_id_hash); + module_code_id.length(), &expected.code_id_hash[0]); EXPECT_TRUE(internal::ModuleEqual()(expected, blacklisted_modules[0])); }
diff --git a/chrome/browser/conflicts/module_blacklist_cache_util_win.cc b/chrome/browser/conflicts/module_blacklist_cache_util_win.cc index 2f567901..7b3d908 100644 --- a/chrome/browser/conflicts/module_blacklist_cache_util_win.cc +++ b/chrome/browser/conflicts/module_blacklist_cache_util_win.cc
@@ -8,6 +8,7 @@ #include <functional> #include <iterator> #include <string> +#include <tuple> #include <utility> #include "base/files/file.h" @@ -237,30 +238,15 @@ bool ModuleLess::operator()( const third_party_dlls::PackedListModule& lhs, const third_party_dlls::PackedListModule& rhs) const { - auto is_less = [](const auto& lhs, const auto& rhs) { - return std::lexicographical_compare(std::begin(lhs), std::end(lhs), - std::begin(rhs), std::end(rhs)); - }; - - if (is_less(lhs.basename_hash, rhs.basename_hash)) - return true; - - if (is_less(rhs.basename_hash, lhs.basename_hash)) - return false; - - return is_less(lhs.code_id_hash, rhs.code_id_hash); + return std::tie(lhs.basename_hash, lhs.code_id_hash) < + std::tie(rhs.basename_hash, rhs.code_id_hash); } bool ModuleEqual::operator()( const third_party_dlls::PackedListModule& lhs, const third_party_dlls::PackedListModule& rhs) const { - auto are_equal = [](const auto& lhs, const auto& rhs) { - return std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs), - std::end(rhs)); - }; - - return are_equal(lhs.basename_hash, rhs.basename_hash) && - are_equal(lhs.code_id_hash, rhs.code_id_hash); + return lhs.basename_hash == rhs.basename_hash && + lhs.code_id_hash == rhs.code_id_hash; } bool ModuleTimeDateStampGreater::operator()(
diff --git a/chrome/browser/conflicts/module_blacklist_cache_util_win_unittest.cc b/chrome/browser/conflicts/module_blacklist_cache_util_win_unittest.cc index e29df43..dd53d2e 100644 --- a/chrome/browser/conflicts/module_blacklist_cache_util_win_unittest.cc +++ b/chrome/browser/conflicts/module_blacklist_cache_util_win_unittest.cc
@@ -18,6 +18,7 @@ #include "base/stl_util.h" #include "base/time/time.h" #include "chrome/browser/conflicts/module_list_filter_win.h" +#include "chrome_elf/sha1/sha1.h" #include "chrome_elf/third_party_dlls/packed_list_format.h" #include "testing/gtest/include/gtest/gtest.h" @@ -42,9 +43,7 @@ for (auto& entry : entries) { // Fill up each bytes for both SHA1 hashes. - for (size_t i = 0; - i < arraysize(third_party_dlls::PackedListModule::basename_hash); - ++i) { + for (size_t i = 0; i < elf_sha1::kSHA1Length; ++i) { entry.basename_hash[i] = byte_distribution(random_engine); entry.code_id_hash[i] = byte_distribution(random_engine); } @@ -186,10 +185,12 @@ void AddWhitelistedModule(const third_party_dlls::PackedListModule& module) { whitelisted_modules_.emplace( - base::StringPiece(reinterpret_cast<const char*>(module.basename_hash), - base::size(module.basename_hash)), - base::StringPiece(reinterpret_cast<const char*>(module.code_id_hash), - base::size(module.basename_hash))); + base::StringPiece( + reinterpret_cast<const char*>(&module.basename_hash[0]), + base::size(module.basename_hash)), + base::StringPiece( + reinterpret_cast<const char*>(&module.code_id_hash[0]), + base::size(module.basename_hash))); } // ModuleListFilter:
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 71d09b0..d587a72 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -309,7 +309,7 @@ }, { "name": "background-task-component-update", - // "owners": [ "your-team" ], + "owners": [ "sorin", "waffles", "tiborg" ], "expiry_milestone": 76 }, { @@ -2036,7 +2036,7 @@ }, { "name": "enable-webrtc-remote-event-log", - // "owners": [ "your-team" ], + "owners": [ "eladalon" ], "expiry_milestone": 76 }, { @@ -2230,11 +2230,6 @@ "expiry_milestone": 76 }, { - "name": "gpu-rasterization-msaa-sample-count", - // "owners": [ "your-team" ], - "expiry_milestone": 76 - }, - { "name": "grant-notifications-to-dse", // "owners": [ "your-team" ], "expiry_milestone": 76
diff --git a/chrome/browser/google/google_brand_code_map_chromeos.cc b/chrome/browser/google/google_brand_code_map_chromeos.cc index def1e155..a5b7e0b1 100644 --- a/chrome/browser/google/google_brand_code_map_chromeos.cc +++ b/chrome/browser/google/google_brand_code_map_chromeos.cc
@@ -34,7 +34,67 @@ {"GJZV", {"BUSA", "GIOS", "UYOM"}}, {"FSGY", {"PJQC", "RHZW", "POVI"}}, {"IHZG", {"MLLN", "EZTK", "GJEJ"}}, - {"PXDO", {"ZXCF", "TQWC", "HOAL"}}}); + {"PXDO", {"ZXCF", "TQWC", "HOAL"}}, + {"ACAC", {"CFZM", "BEUH", "GUTN"}}, + {"ACAG", {"KSOU", "MUHR", "YYJR"}}, + {"ACAH", {"KEFG", "RYNH", "HHAZ"}}, + {"ACAJ", {"KVPC", "UHAI", "CPNG"}}, + {"ACAM", {"HBCZ", "ZGSZ", "MFUO"}}, + {"ACAO", {"MWDF", "BNNY", "SYIY"}}, + {"ACAP", {"LKNW", "SVFL", "FGKR"}}, + {"ACAR", {"EAQE", "UHHJ", "ZYFW"}}, + {"ACAT", {"RJNJ", "CKCB", "VHGI"}}, + {"ACAV", {"TTSD", "XTQQ", "TIQC"}}, + {"ACAY", {"HKDC", "RYKK", "KSIY"}}, + {"ACBA", {"TVZD", "HLQR", "DOWV"}}, + {"MNZG", {"PPTP", "OFXE", "ROJJ"}}, + {"CYQR", {"XGJJ", "DRMC", "RUQD"}}, + {"ASUA", {"IEIT", "JAIV", "MURN"}}, + {"ASUD", {"QLMM", "CRUA", "JSID"}}, + {"ASUE", {"XLEN", "KECH", "HBGX"}}, + {"ASUF", {"IVGE", "VNTM", "XELD"}}, + {"ASUJ", {"HJUL", "XWWL", "WSCY"}}, + {"ASUK", {"RGUX", "OXBQ", "LDTL"}}, + {"DEAA", {"HXUG", "BJUN", "IYTV"}}, + {"DEAC", {"DSMM", "IXET", "KQDV"}}, + {"DEAF", {"TATK", "RWXF", "DQDT"}}, + {"DEAG", {"JFEX", "CVLN", "UFWN"}}, + {"DRYI", {"LWTQ", "OLEY", "NWUA"}}, + {"ZZAB", {"WVIK", "IUXK", "ZCIK"}}, + {"ZZAD", {"KSTH", "CBJY", "TSID"}}, + {"ZZAF", {"OTWH", "RRNB", "VNXA"}}, + {"XWJE", {"KDZI", "IYPJ", "ERIM"}}, + {"NBQS", {"KMJF", "MFWA", "UWRX"}}, + {"HPZY", {"RAWP", "CNRC", "TPIA"}}, + {"HPZV", {"WAFN", "PQVW", "MJVM"}}, + {"HPZT", {"IUCU", "WDAV", "LOLH"}}, + {"HPZS", {"QRFK", "SQGI", "VESI"}}, + {"HPZQ", {"XGER", "OLTF", "DVQA"}}, + {"HPZP", {"NQDY", "QIMT", "QKAK"}}, + {"JBPA", {"VUZL", "XYPI", "XOWE"}}, + {"LEAC", {"DMEA", "EXWD", "PBTU"}}, + {"LEAE", {"QFVM", "GACH", "BMXB"}}, + {"LEAG", {"XTLW", "WLQO", "QVKP"}}, + {"LEAH", {"QIDR", "XBTQ", "QYUO"}}, + {"LEAI", {"KCSV", "PRBF", "FVDO"}}, + {"LEAK", {"CGWM", "ZLOS", "JGTD"}}, + {"LEAL", {"EYPX", "SOCH", "PFPW"}}, + {"LEAO", {"MKOE", "YJSI", "QQMN"}}, + {"LEAP", {"AEZG", "JOYE", "JHWK"}}, + {"ZFCZ", {"JQUA", "SEEH", "RJVV"}}, + {"VEUT", {"JDFA", "ALIR", "DDJM"}}, + {"SMAE", {"SUUV", "QXWL", "LYKX"}}, + {"SMAF", {"HKPA", "NFCE", "UBOP"}}, + {"SMAH", {"EXLB", "YYYY", "LLLA"}}, + {"SMAI", {"PPDO", "ISMM", "BKNT"}}, + {"SMAJ", {"PVCB", "UCIK", "XVBK"}}, + {"SMAK", {"WOMZ", "OHAX", "JSTF"}}, + {"ZSKM", {"JPEZ", "FTUS", "ZFUF"}}, + {"SMAL", {"OWLX", "YXSA", "TXJR"}}, + {"TAAB", {"ZBMY", "NYDT", "CXYZ"}}, + {"YMMU", {"ZVIA", "CFKN", "ERLO"}}, + {"FSFR", {"ZDAR", "BERM", "COKX"}}, + {"ASCT", {"CTRF", "LBBD", "YBND"}}}); const auto it = kBrandCodeMap->find(static_brand_code); if (it == kBrandCodeMap->end())
diff --git a/chrome/browser/mac/install.sh b/chrome/browser/mac/install.sh index e39e729b..a7c2a3d7 100755 --- a/chrome/browser/mac/install.sh +++ b/chrome/browser/mac/install.sh
@@ -98,12 +98,6 @@ # permissions on any symbolic links. find "${DEST}" -type l -exec chmod -h "${CHMOD_MODE}" {} + >& /dev/null -# Host OS version check, to be able to take advantage of features on newer -# systems and fall back to slow ways of doing things on older systems. -OS_VERSION=$(sw_vers -productVersion) -OS_MAJOR=$(sed -Ene 's/^([0-9]+).*/\1/p' <<< ${OS_VERSION}) -OS_MINOR=$(sed -Ene 's/^([0-9]+)\.([0-9]+).*/\2/p' <<< ${OS_VERSION}) - # Because this script is launched by the application itself, the installation # process inherits the quarantine bit (LSFileQuarantineEnabled). Any files or # directories created during the update will be quarantined in that case, @@ -113,14 +107,7 @@ # it can be assumed that the installed copy should not be quarantined. Use # xattr to drop the quarantine attribute. QUARANTINE_ATTR=com.apple.quarantine -if [ ${OS_MAJOR} -gt 10 ] || - ([ ${OS_MAJOR} -eq 10 ] && [ ${OS_MINOR} -ge 6 ]) ; then - # On 10.6, xattr supports -r for recursive operation. - xattr -d -r "${QUARANTINE_ATTR}" "${DEST}" >& /dev/null -else - # On earlier systems, xattr doesn't support -r, so run xattr via find. - find "${DEST}" -exec xattr -d "${QUARANTINE_ATTR}" {} + >& /dev/null -fi +xattr -d -r "${QUARANTINE_ATTR}" "${DEST}" >& /dev/null # Great success! exit 0
diff --git a/chrome/browser/net/profile_network_context_service.cc b/chrome/browser/net/profile_network_context_service.cc index cf5c361..1c982f9 100644 --- a/chrome/browser/net/profile_network_context_service.cc +++ b/chrome/browser/net/profile_network_context_service.cc
@@ -200,17 +200,24 @@ } #if defined(OS_CHROMEOS) -void ProfileNetworkContextService::UpdateTrustAnchors( +void ProfileNetworkContextService::UpdateAdditionalCertificates( + const net::CertificateList& all_additional_certificates, const net::CertificateList& trust_anchors) { content::BrowserContext::ForEachStoragePartition( - profile_, - base::BindRepeating( - [](const net::CertificateList& trust_anchors, - content::StoragePartition* storage_partition) { - storage_partition->GetNetworkContext()->UpdateTrustAnchors( - trust_anchors); - }, - trust_anchors)); + profile_, base::BindRepeating( + [](const net::CertificateList& all_additional_certificates, + const net::CertificateList& trust_anchors, + content::StoragePartition* storage_partition) { + auto additional_certificates = + network::mojom::AdditionalCertificates::New(); + additional_certificates->all_certificates = + all_additional_certificates; + additional_certificates->trust_anchors = trust_anchors; + storage_partition->GetNetworkContext() + ->UpdateAdditionalCertificates( + std::move(additional_certificates)); + }, + all_additional_certificates, trust_anchors)); } #endif @@ -469,7 +476,12 @@ policy::PolicyCertService* service = policy::PolicyCertServiceFactory::GetForProfile(profile_); - network_context_params->initial_trust_anchors = service->trust_anchors(); + network_context_params->initial_additional_certificates = + network::mojom::AdditionalCertificates::New(); + network_context_params->initial_additional_certificates + ->all_certificates = service->all_server_and_authority_certs(); + network_context_params->initial_additional_certificates->trust_anchors = + service->trust_anchors(); } } #endif
diff --git a/chrome/browser/net/profile_network_context_service.h b/chrome/browser/net/profile_network_context_service.h index faec69e..abdae110 100644 --- a/chrome/browser/net/profile_network_context_service.h +++ b/chrome/browser/net/profile_network_context_service.h
@@ -67,7 +67,9 @@ network::mojom::NetworkContextParamsPtr* network_context_params); #if defined(OS_CHROMEOS) - void UpdateTrustAnchors(const net::CertificateList& trust_anchors); + void UpdateAdditionalCertificates( + const net::CertificateList& all_additional_certificates, + const net::CertificateList& trust_anchors); #endif static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
diff --git a/chrome/browser/notifications/notification_platform_bridge_win.cc b/chrome/browser/notifications/notification_platform_bridge_win.cc index 103090ed..715f66d4 100644 --- a/chrome/browser/notifications/notification_platform_bridge_win.cc +++ b/chrome/browser/notifications/notification_platform_bridge_win.cc
@@ -868,9 +868,11 @@ // static bool NotificationPlatformBridgeWin::NativeNotificationEnabled() { - // Windows 10 native notification seems to have memory leak issues on OS - // builds older than 17134 (i.e., VERSION_WIN10_RS4). This seems to be a - // Windows issue which has been fixed in 17134. + // There was a Microsoft bug in Windows 10 prior to build 17134 (i.e., + // VERSION_WIN10_RS4), causing endless loops in displaying notifications. It + // significantly amplified the memory and CPU usage. Therefore, we enable + // Windows 10 native notification only for build 17134 and later. See + // crbug.com/882622 and crbug.com/878823 for more details. return base::win::GetVersion() >= base::win::VERSION_WIN10_RS4 && base::FeatureList::IsEnabled(features::kNativeNotifications); }
diff --git a/chrome/browser/policy/cloud/machine_level_user_cloud_policy_browsertest.cc b/chrome/browser/policy/cloud/machine_level_user_cloud_policy_browsertest.cc index 9deea9a0..930a808 100644 --- a/chrome/browser/policy/cloud/machine_level_user_cloud_policy_browsertest.cc +++ b/chrome/browser/policy/cloud/machine_level_user_cloud_policy_browsertest.cc
@@ -73,7 +73,7 @@ : public MachineLevelUserCloudPolicyController::Observer { public: void OnPolicyRegisterFinished(bool succeeded) override { - if (!succeeded) { + if (!succeeded && should_display_error_message_) { EXPECT_EQ(0u, chrome::GetTotalBrowserCount()); #if defined(OS_MACOSX) PostAppControllerNSNotifications(); @@ -93,11 +93,16 @@ should_succeed_ = should_succeed; } + void SetShouldDisplayErrorMessage(bool should_display) { + should_display_error_message_ = should_display; + } + bool IsFinished() { return is_finished_; } private: bool is_finished_ = false; bool should_succeed_ = false; + bool should_display_error_message_ = false; }; class FakeBrowserDMTokenStorage : public BrowserDMTokenStorage { @@ -116,11 +121,16 @@ std::move(callback).Run(storage_enabled_); } std::string RetrieveDMToken() override { return dm_token_; } - bool ShouldDisplayErrorMessageOnFailure() override { return true; } + bool ShouldDisplayErrorMessageOnFailure() override { + return should_display_error_message_on_failure_; + } void SetEnrollmentToken(const std::string& enrollment_token) { enrollment_token_ = enrollment_token; } + void SetErrorMessageOption(bool should_displayed) { + should_display_error_message_on_failure_ = should_displayed; + } void SetClientId(std::string client_id) { client_id_ = client_id; } @@ -152,6 +162,7 @@ std::string client_id_; std::string dm_token_; bool storage_enabled_ = true; + bool should_display_error_message_on_failure_ = true; DISALLOW_COPY_AND_ASSIGN(FakeBrowserDMTokenStorage); }; @@ -383,7 +394,7 @@ class MachineLevelUserCloudPolicyEnrollmentTest : public InProcessBrowserTest, - public ::testing::WithParamInterface<std::tuple<bool, bool>> { + public ::testing::WithParamInterface<std::tuple<bool, bool, bool>> { public: MachineLevelUserCloudPolicyEnrollmentTest() { BrowserDMTokenStorage::SetForTesting(&storage_); @@ -392,8 +403,12 @@ : kInvalidEnrollmentToken); storage_.SetClientId("client_id"); storage_.EnableStorage(storage_enabled()); + storage_.SetErrorMessageOption(should_display_error_message()); + observer_.SetShouldSucceed(is_enrollment_token_valid()); - if (!is_enrollment_token_valid()) { + observer_.SetShouldDisplayErrorMessage(should_display_error_message()); + + if (!is_enrollment_token_valid() && should_display_error_message()) { set_expected_exit_code( chrome::RESULT_CODE_CLOUD_POLICY_ENROLLMENT_FAILED); } @@ -455,6 +470,7 @@ protected: bool is_enrollment_token_valid() const { return std::get<0>(GetParam()); } bool storage_enabled() const { return std::get<1>(GetParam()); } + bool should_display_error_message() const { return std::get<2>(GetParam()); } base::HistogramTester histogram_tester_; @@ -467,8 +483,9 @@ }; IN_PROC_BROWSER_TEST_P(MachineLevelUserCloudPolicyEnrollmentTest, Test) { - // Test body is ran only if enrollment is succeeded. - EXPECT_TRUE(is_enrollment_token_valid()); + // Test body is run only if enrollment is succeeded or failed without error + // message. + EXPECT_TRUE(is_enrollment_token_valid() || !should_display_error_message()); EXPECT_EQ(1u, chrome::GetTotalBrowserCount()); @@ -485,6 +502,7 @@ INSTANTIATE_TEST_CASE_P(, MachineLevelUserCloudPolicyEnrollmentTest, ::testing::Combine(::testing::Bool(), + ::testing::Bool(), ::testing::Bool())); } // namespace policy
diff --git a/chrome/browser/policy/machine_level_user_cloud_policy_controller.cc b/chrome/browser/policy/machine_level_user_cloud_policy_controller.cc index 183792ec..f1a0c65 100644 --- a/chrome/browser/policy/machine_level_user_cloud_policy_controller.cc +++ b/chrome/browser/policy/machine_level_user_cloud_policy_controller.cc
@@ -16,6 +16,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/lifetime/application_lifetime.h" #include "chrome/browser/policy/browser_dm_token_storage.h" #include "chrome/browser/policy/chrome_browser_policy_connector.h" #include "chrome/browser/policy/cloud/machine_level_user_cloud_policy_helper.h" @@ -38,6 +39,10 @@ #include "chrome/common/chrome_switches.h" #endif +#if defined(OS_MACOSX) +#include "chrome/browser/app_controller_mac.h" +#endif + namespace policy { namespace { @@ -194,12 +199,30 @@ } } -MachineLevelUserCloudPolicyController::RegisterResult -MachineLevelUserCloudPolicyController::WaitUntilPolicyEnrollmentFinished() { +bool MachineLevelUserCloudPolicyController:: + WaitUntilPolicyEnrollmentFinished() { if (policy_register_watcher_) { - return policy_register_watcher_->WaitUntilCloudPolicyEnrollmentFinished(); + switch ( + policy_register_watcher_->WaitUntilCloudPolicyEnrollmentFinished()) { + case RegisterResult::kNoEnrollmentNeeded: + case RegisterResult::kEnrollmentSuccessBeforeDialogDisplayed: + case RegisterResult::kEnrollmentFailedSilentlyBeforeDialogDisplayed: + return true; + case RegisterResult::kEnrollmentSuccess: + case RegisterResult::kEnrollmentFailedSilently: +#if defined(OS_MACOSX) + app_controller_mac::EnterpriseStartupDialogClosed(); +#endif + return true; + case RegisterResult::kRestartDueToFailure: + chrome::AttemptRestart(); + return false; + case RegisterResult::kQuitDueToFailure: + chrome::AttemptExit(); + return false; + } } - return RegisterResult::kNoEnrollmentNeeded; + return true; } void MachineLevelUserCloudPolicyController::AddObserver(Observer* observer) {
diff --git a/chrome/browser/policy/machine_level_user_cloud_policy_controller.h b/chrome/browser/policy/machine_level_user_cloud_policy_controller.h index d5ab692..7c1adb03 100644 --- a/chrome/browser/policy/machine_level_user_cloud_policy_controller.h +++ b/chrome/browser/policy/machine_level_user_cloud_policy_controller.h
@@ -40,6 +40,13 @@ kQuitDueToFailure, // The enrollment has failed or aborted, user choose to // quit Chrome. kRestartDueToFailure, // The enrollment has failed, user choose to restart + kEnrollmentFailedSilently, // The enrollment has failed, admin choose to + // ignore the error message. + kEnrollmentFailedSilentlyBeforeDialogDisplayed, // The enrollment has + // failed before dialog + // displayed, admin choose + // to ignore the error + // message. }; class Observer { @@ -63,7 +70,7 @@ void Init(PrefService* local_state, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory); - RegisterResult WaitUntilPolicyEnrollmentFinished(); + bool WaitUntilPolicyEnrollmentFinished(); void AddObserver(Observer* observer); void RemoveObserver(Observer* observer);
diff --git a/chrome/browser/policy/machine_level_user_cloud_policy_register_watcher.cc b/chrome/browser/policy/machine_level_user_cloud_policy_register_watcher.cc index 96908ec..08e1e84 100644 --- a/chrome/browser/policy/machine_level_user_cloud_policy_register_watcher.cc +++ b/chrome/browser/policy/machine_level_user_cloud_policy_register_watcher.cc
@@ -38,14 +38,12 @@ WaitUntilCloudPolicyEnrollmentFinished() { BrowserDMTokenStorage* token_storage = BrowserDMTokenStorage::Get(); - if (token_storage->RetrieveEnrollmentToken().empty()) { + if (token_storage->RetrieveEnrollmentToken().empty()) return RegisterResult::kNoEnrollmentNeeded; - } // We are already enrolled successfully. - if (!token_storage->RetrieveDMToken().empty()) { + if (!token_storage->RetrieveDMToken().empty()) return RegisterResult::kEnrollmentSuccessBeforeDialogDisplayed; - } EnterpriseStartupDialog::DialogResultCallback callback = base::BindOnce( &MachineLevelUserCloudPolicyRegisterWatcher::OnDialogClosed, @@ -56,27 +54,38 @@ dialog_ = EnterpriseStartupDialog::CreateAndShowDialog(std::move(callback)); visible_start_time_ = base::Time::Now(); - RecordEnrollmentStartDialog(EnrollmentStartupDialog::kShown); if (register_result_) { - // |register_result_| has been set only if the enrollment has finihsed. + // |register_result_| has been set only if the enrollment has finished. // And it must be failed if it's finished without a DM token which is // checked above. Show the error message directly. DCHECK(!register_result_.value()); + + if (!token_storage->ShouldDisplayErrorMessageOnFailure()) + return RegisterResult::kEnrollmentFailedSilentlyBeforeDialogDisplayed; + DisplayErrorMessage(); } else { // Display the loading dialog and wait for the enrollment process. dialog_->DisplayLaunchingInformationWithThrobber(l10n_util::GetStringUTF16( IDS_ENTERPRISE_STARTUP_CLOUD_POLICY_ENROLLMENT_TOOLTIP)); } + RecordEnrollmentStartDialog(EnrollmentStartupDialog::kShown); run_loop_.Run(); if (register_result_.value_or(false)) return RegisterResult::kEnrollmentSuccess; + if (!token_storage->ShouldDisplayErrorMessageOnFailure() && + register_result_) { + SYSLOG(ERROR) << "Machine level user cloud policy enrollment has failed."; + return RegisterResult::kEnrollmentFailedSilently; + } + SYSLOG(ERROR) << "Can not start Chrome as machine level user cloud policy " "enrollment has failed. Please double check network " "connection and the status of enrollment token then open " "Chrome again."; + if (is_restart_needed_) return RegisterResult::kRestartDueToFailure; return RegisterResult::kQuitDueToFailure; @@ -105,7 +114,8 @@ // show the error message. If dialog has been closed before enrollment // finished, Chrome should already be in the shutdown process. if (dialog_ && dialog_->IsShowing()) { - if (register_result_.value()) { + if (register_result_.value() || + !BrowserDMTokenStorage::Get()->ShouldDisplayErrorMessageOnFailure()) { dialog_.reset(); } else { DisplayErrorMessage(); @@ -118,7 +128,12 @@ bool can_show_browser_window) { if (can_show_browser_window) { // Chrome startup can continue normally. - RecordEnrollmentStartDialog(EnrollmentStartupDialog::kClosedSuccess); + if (register_result_.value()) { + RecordEnrollmentStartDialog(EnrollmentStartupDialog::kClosedSuccess); + } else { + RecordEnrollmentStartDialog( + EnrollmentStartupDialog::kClosedFailAndIgnore); + } } else if (is_accepted) { // User chose to restart chrome and try re-enrolling. RecordEnrollmentStartDialog(EnrollmentStartupDialog::kClosedRelaunch);
diff --git a/chrome/browser/policy/machine_level_user_cloud_policy_register_watcher.h b/chrome/browser/policy/machine_level_user_cloud_policy_register_watcher.h index 2e30c04..fa31df6c 100644 --- a/chrome/browser/policy/machine_level_user_cloud_policy_register_watcher.h +++ b/chrome/browser/policy/machine_level_user_cloud_policy_register_watcher.h
@@ -48,13 +48,23 @@ FRIEND_TEST_ALL_PREFIXES(MachineLevelUserCloudPolicyRegisterWatcherTest, EnrollmentSucceed); FRIEND_TEST_ALL_PREFIXES(MachineLevelUserCloudPolicyRegisterWatcherTest, + EnrollmentSucceedWithNoErrorMessageSetup); + FRIEND_TEST_ALL_PREFIXES(MachineLevelUserCloudPolicyRegisterWatcherTest, EnrollmentFailedAndQuit); FRIEND_TEST_ALL_PREFIXES(MachineLevelUserCloudPolicyRegisterWatcherTest, EnrollmentFailedAndRestart); FRIEND_TEST_ALL_PREFIXES(MachineLevelUserCloudPolicyRegisterWatcherTest, EnrollmentCanceledBeforeFinish); + FRIEND_TEST_ALL_PREFIXES( + MachineLevelUserCloudPolicyRegisterWatcherTest, + EnrollmentCanceledBeforeFinishWithNoErrorMessageSetup); FRIEND_TEST_ALL_PREFIXES(MachineLevelUserCloudPolicyRegisterWatcherTest, EnrollmentFailedBeforeDialogDisplay); + FRIEND_TEST_ALL_PREFIXES(MachineLevelUserCloudPolicyRegisterWatcherTest, + EnrollmentFailedWithoutErrorMessage); + FRIEND_TEST_ALL_PREFIXES( + MachineLevelUserCloudPolicyRegisterWatcherTest, + EnrollmentFailedBeforeDialogDisplayWithoutErrorMessage); // Enum used with kStartupDialogHistogramName. enum class EnrollmentStartupDialog { @@ -77,7 +87,11 @@ // before the user gave up and closed the dialog. kClosedAbort = 4, - kMaxValue = kClosedAbort, + // The dialog was closed automatically because enrollment failed but admin + // choose to ignore the error and show the browser window. + kClosedFailAndIgnore = 5, + + kMaxValue = kClosedFailAndIgnore, }; static const char kStartupDialogHistogramName[];
diff --git a/chrome/browser/policy/machine_level_user_cloud_policy_register_watcher_unittest.cc b/chrome/browser/policy/machine_level_user_cloud_policy_register_watcher_unittest.cc index 52af0ae8..20ec082e 100644 --- a/chrome/browser/policy/machine_level_user_cloud_policy_register_watcher_unittest.cc +++ b/chrome/browser/policy/machine_level_user_cloud_policy_register_watcher_unittest.cc
@@ -38,7 +38,9 @@ std::string RetrieveDMToken() override { return dm_token_; } std::string RetrieveEnrollmentToken() override { return enrollment_token_; } std::string RetrieveClientId() override { return kClientId; } - bool ShouldDisplayErrorMessageOnFailure() override { return true; } + bool ShouldDisplayErrorMessageOnFailure() override { + return should_display_error_message_on_failure_; + } std::string InitClientId() override { NOTREACHED(); @@ -63,10 +65,14 @@ void set_enrollment_token(const std::string& enrollment_token) { enrollment_token_ = enrollment_token; } + void set_should_display_error_message_on_failure(bool should_display) { + should_display_error_message_on_failure_ = should_display; + } private: std::string enrollment_token_; std::string dm_token_; + bool should_display_error_message_on_failure_ = true; DISALLOW_COPY_AND_ASSIGN(FakeDMTokenStorage); }; @@ -204,6 +210,32 @@ } TEST_F(MachineLevelUserCloudPolicyRegisterWatcherTest, + EnrollmentSucceedWithNoErrorMessageSetup) { + base::HistogramTester histogram_tester; + + EXPECT_CALL(*dialog(), DisplayLaunchingInformationWithThrobber(_)); + EXPECT_CALL(*dialog(), IsShowing()).WillOnce(Return(true)); + storage()->set_should_display_error_message_on_failure(false); + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce( + &FakeMachineLevelUserCloudPolicyController::FireNotification, + base::Unretained(controller()), true)); + EXPECT_EQ(RegisterResult::kEnrollmentSuccess, + watcher()->WaitUntilCloudPolicyEnrollmentFinished()); + histogram_tester.ExpectBucketCount( + MachineLevelUserCloudPolicyRegisterWatcher::kStartupDialogHistogramName, + MachineLevelUserCloudPolicyRegisterWatcher::EnrollmentStartupDialog:: + kShown, + 1); + histogram_tester.ExpectBucketCount( + MachineLevelUserCloudPolicyRegisterWatcher::kStartupDialogHistogramName, + MachineLevelUserCloudPolicyRegisterWatcher::EnrollmentStartupDialog:: + kClosedSuccess, + 1); +} + +TEST_F(MachineLevelUserCloudPolicyRegisterWatcherTest, EnrollmentFailedAndQuit) { base::HistogramTester histogram_tester; @@ -283,6 +315,31 @@ } TEST_F(MachineLevelUserCloudPolicyRegisterWatcherTest, + EnrollmentCanceledBeforeFinishWithNoErrorMessageSetup) { + base::HistogramTester histogram_tester; + + EXPECT_CALL(*dialog(), DisplayLaunchingInformationWithThrobber(_)); + storage()->set_should_display_error_message_on_failure(false); + + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(&MockEnterpriseStartupDialog::UserClickedTheButton, + base::Unretained(dialog()), false)); + EXPECT_EQ(RegisterResult::kQuitDueToFailure, + watcher()->WaitUntilCloudPolicyEnrollmentFinished()); + histogram_tester.ExpectBucketCount( + MachineLevelUserCloudPolicyRegisterWatcher::kStartupDialogHistogramName, + MachineLevelUserCloudPolicyRegisterWatcher::EnrollmentStartupDialog:: + kShown, + 1); + histogram_tester.ExpectBucketCount( + MachineLevelUserCloudPolicyRegisterWatcher::kStartupDialogHistogramName, + MachineLevelUserCloudPolicyRegisterWatcher::EnrollmentStartupDialog:: + kClosedAbort, + 1); +} + +TEST_F(MachineLevelUserCloudPolicyRegisterWatcherTest, EnrollmentFailedBeforeDialogDisplay) { base::HistogramTester histogram_tester; @@ -304,4 +361,43 @@ 1); } +TEST_F(MachineLevelUserCloudPolicyRegisterWatcherTest, + EnrollmentFailedWithoutErrorMessage) { + base::HistogramTester histogram_tester; + + EXPECT_CALL(*dialog(), DisplayLaunchingInformationWithThrobber(_)); + EXPECT_CALL(*dialog(), IsShowing()).WillOnce(Return(true)); + storage()->set_should_display_error_message_on_failure(false); + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce( + &FakeMachineLevelUserCloudPolicyController::FireNotification, + base::Unretained(controller()), false)); + EXPECT_EQ(RegisterResult::kEnrollmentFailedSilently, + watcher()->WaitUntilCloudPolicyEnrollmentFinished()); + histogram_tester.ExpectBucketCount( + MachineLevelUserCloudPolicyRegisterWatcher::kStartupDialogHistogramName, + MachineLevelUserCloudPolicyRegisterWatcher::EnrollmentStartupDialog:: + kShown, + 1); + histogram_tester.ExpectBucketCount( + MachineLevelUserCloudPolicyRegisterWatcher::kStartupDialogHistogramName, + MachineLevelUserCloudPolicyRegisterWatcher::EnrollmentStartupDialog:: + kClosedFailAndIgnore, + 1); +} + +TEST_F(MachineLevelUserCloudPolicyRegisterWatcherTest, + EnrollmentFailedBeforeDialogDisplayWithoutErrorMessage) { + base::HistogramTester histogram_tester; + + storage()->set_should_display_error_message_on_failure(false); + controller()->FireNotification(false); + EXPECT_EQ(RegisterResult::kEnrollmentFailedSilentlyBeforeDialogDisplayed, + watcher()->WaitUntilCloudPolicyEnrollmentFinished()); + histogram_tester.ExpectTotalCount( + MachineLevelUserCloudPolicyRegisterWatcher::kStartupDialogHistogramName, + 0); +} + } // namespace policy
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index c9986a1..edd85e91 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc
@@ -381,6 +381,7 @@ // Deprecated 11/2018. const char kNetworkQualities[] = "net.network_qualities"; const char kForceSessionSync[] = "settings.history_recorded"; +const char kOnboardDuringNUX[] = "browser.onboard_during_nux"; // Register prefs used only for migration (clearing or moving to a new key). void RegisterProfilePrefsForMigration( @@ -410,6 +411,7 @@ registry->RegisterDictionaryPref(kNetworkQualities, PrefRegistry::LOSSY_PREF); registry->RegisterBooleanPref(kForceSessionSync, false); + registry->RegisterBooleanPref(kOnboardDuringNUX, false); } } // namespace @@ -873,4 +875,5 @@ // Added 11/2018. profile_prefs->ClearPref(kNetworkQualities); profile_prefs->ClearPref(kForceSessionSync); + profile_prefs->ClearPref(kOnboardDuringNUX); }
diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc index cc62bbe..608e518 100644 --- a/chrome/browser/profiles/profile_manager.cc +++ b/chrome/browser/profiles/profile_manager.cc
@@ -63,6 +63,7 @@ #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/startup/startup_browser_creator.h" #include "chrome/browser/ui/sync/sync_promo_ui.h" +#include "chrome/browser/ui/webui/welcome/nux_helper.h" #include "chrome/browser/unified_consent/unified_consent_service_factory.h" #include "chrome/common/buildflags.h" #include "chrome/common/chrome_constants.h" @@ -1078,9 +1079,10 @@ if (profile->IsNewProfile() || first_run::IsChromeFirstRun()) { profile->GetPrefs()->SetBoolean(prefs::kHasSeenWelcomePage, false); #if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD) - // Enterprise users should not be included in any NUX flow. + // Enterprise users should not be included in any NUX/Navi flow. if (!base::win::IsEnterpriseManaged()) { - profile->GetPrefs()->SetBoolean(prefs::kOnboardDuringNUX, true); + int group = nux::GetOnboardingGroup(); + profile->GetPrefs()->SetInteger(prefs::kNuxOnboardGroup, group); } #endif // defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD) }
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/next_earcons.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/next_earcons.js index 50e61154..2e861aa 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/next_earcons.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/next_earcons.js
@@ -36,11 +36,15 @@ /** @private {boolean} */ this.shouldPan_ = true; - chrome.audio.getDevices( - {isActive: true, streamTypes: [chrome.audio.StreamType.OUTPUT]}, - this.updateShouldPanForDevices_.bind(this)); - chrome.audio.onDeviceListChanged.addListener( - this.updateShouldPanForDevices_.bind(this)); + if (chrome.audio) { + chrome.audio.getDevices( + {isActive: true, streamTypes: [chrome.audio.StreamType.OUTPUT]}, + this.updateShouldPanForDevices_.bind(this)); + chrome.audio.onDeviceListChanged.addListener( + this.updateShouldPanForDevices_.bind(this)); + } else { + this.shouldPan_ = false; + } }; NextEarcons.prototype = {
diff --git a/chrome/browser/sessions/tab_loader.cc b/chrome/browser/sessions/tab_loader.cc index f07309b..a55f56cc 100644 --- a/chrome/browser/sessions/tab_loader.cc +++ b/chrome/browser/sessions/tab_loader.cc
@@ -18,6 +18,7 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_finder.h" #include "components/favicon/content/content_favicon_driver.h" +#include "content/public/browser/background_tracing_manager.h" #include "content/public/browser/navigation_controller.h" #include "content/public/browser/web_contents.h" #include "content/public/common/content_features.h" @@ -27,6 +28,18 @@ namespace { +void BackgroundTracingTrigger() { + static content::BackgroundTracingManager::TriggerHandle trigger_handle_ = -1; + if (trigger_handle_ == -1) { + trigger_handle_ = + content::BackgroundTracingManager::GetInstance()->RegisterTriggerType( + "session-restore-config"); + } + content::BackgroundTracingManager::GetInstance()->TriggerNamedEvent( + trigger_handle_, + content::BackgroundTracingManager::StartedFinalizingCallback()); +} + const base::TickClock* GetDefaultTickClock() { static base::NoDestructor<base::DefaultTickClock> default_tick_clock; return default_tick_clock.get(); @@ -80,6 +93,10 @@ if (tabs.empty()) return; + // Trigger a slow-reports and collect a session restore trace if needed. + BackgroundTracingTrigger(); + TRACE_EVENT0("browser", "TabLoader::RestoreTabs"); + if (!shared_tab_loader_) shared_tab_loader_ = new TabLoader(restore_started); @@ -172,6 +189,7 @@ void TabLoader::StartLoading(const std::vector<RestoredTab>& tabs) { DCHECK(!tabs.empty()); ReentrancyHelper lifetime_helper(this); + TRACE_EVENT1("browser", "TabLoader::StartLoading", "tabs_count", tabs.size()); // Create a TabLoaderDelegate which will allow OS specific behavior for tab // loading. This needs to be done before any calls to AddTab, as the delegate @@ -221,6 +239,7 @@ LoadingState old_loading_state, LoadingState new_loading_state) { ReentrancyHelper lifetime_helper(this); + TRACE_EVENT0("browser", "TabLoader::OnLoadingStateChange"); // Calls into this can come from observers that are still running even if // |is_loading_enabled_| is false. @@ -263,6 +282,8 @@ void TabLoader::OnMemoryPressure( base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) { ReentrancyHelper lifetime_helper(this); + TRACE_EVENT0("browser", "TabLoader::OnMemoryPressure"); + switch (memory_pressure_level) { case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE: break; @@ -362,6 +383,7 @@ void TabLoader::MarkTabAsLoadInitiated(WebContents* contents) { DCHECK(reentry_depth_ > 0); // This can only be called internally. + TRACE_EVENT0("browser", "TabLoader::MarkTabAsLoadInitiated"); // This can only be called for a tab that is waiting to be loaded so this // should never fail. @@ -379,6 +401,7 @@ void TabLoader::MarkTabAsLoading(WebContents* contents) { DCHECK(reentry_depth_ > 0); // This can only be called internally. + TRACE_EVENT0("browser", "TabLoader::MarkTabAsLoading"); // Calls into this can come from observers that are still running even if // |is_loading_enabled_| is false. @@ -413,6 +436,7 @@ void TabLoader::MarkTabAsDeferred(content::WebContents* contents) { DCHECK(reentry_depth_ > 0); // This can only be called internally. + TRACE_EVENT0("browser", "TabLoader::MarkTabAsDeferred"); // This can only be called for a tab that is waiting to be loaded so this // should never fail. @@ -424,6 +448,7 @@ void TabLoader::MaybeLoadSomeTabs() { DCHECK(reentry_depth_ > 0); // This can only be called internally. + TRACE_EVENT0("browser", "TabLoader::MaybeLoadSomeTabs"); if (!is_loading_enabled_ || tabs_to_load_.empty()) return; @@ -437,6 +462,7 @@ void TabLoader::ForceLoadTimerFired() { ReentrancyHelper lifetime_helper(this); + TRACE_EVENT0("browser", "TabLoader::ForceLoadTimerFired"); // CheckInvariants can't be called directly as the timer is no longer // running at this point. However, the conditions under which the timer @@ -468,6 +494,7 @@ void TabLoader::StopLoadingTabs() { DCHECK(reentry_depth_ > 0); // This can only be called internally. + TRACE_EVENT0("browser", "TabLoader::StopLoadingTabs"); // Calls into this can come from observers that are still running even if // |is_loading_enabled_| is false. @@ -508,6 +535,7 @@ void TabLoader::LoadNextTab(bool due_to_timeout) { DCHECK(reentry_depth_ > 0); // This can only be called internally. DCHECK(!tabs_to_load_.empty()); + TRACE_EVENT0("browser", "TabLoader::LoadNextTab"); // This is checked before loading every single tab to ensure that responses // to memory pressure are immediate.
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index a8d9d649..e830eb6 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -3298,6 +3298,8 @@ "in_product_help/reopen_tab_in_product_help_factory.h", "in_product_help/reopen_tab_in_product_help_trigger.cc", "in_product_help/reopen_tab_in_product_help_trigger.h", + "views/feature_promos/reopen_tab_promo_controller.cc", + "views/feature_promos/reopen_tab_promo_controller.h", ] }
diff --git a/chrome/browser/ui/ash/multi_user/DEPS b/chrome/browser/ui/ash/multi_user/DEPS index 1a1ad789..e8f4899e 100644 --- a/chrome/browser/ui/ash/multi_user/DEPS +++ b/chrome/browser/ui/ash/multi_user/DEPS
@@ -8,5 +8,6 @@ "multi_user_window_manager_chromeos_unittest\.cc": [ "+ash/multi_user/user_switch_animator.h", "+ash/session/session_controller.h", + "+ash/ws/window_lookup.h", ], }
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.cc b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.cc index 7184725..ee49dd71 100644 --- a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.cc +++ b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.cc
@@ -26,8 +26,14 @@ #include "extensions/browser/app_window/app_window.h" #include "extensions/browser/app_window/app_window_registry.h" #include "ui/aura/client/aura_constants.h" +#include "ui/aura/env.h" +#include "ui/aura/mus/window_mus.h" +#include "ui/aura/mus/window_tree_client.h" #include "ui/aura/window.h" +#include "ui/base/ui_base_features.h" #include "ui/base/ui_base_types.h" +#include "ui/views/mus/mus_client.h" +#include "ui/views/widget/widget.h" namespace { @@ -80,6 +86,26 @@ NUM_TELEPORT_WINDOW_TYPES); } +// Returns the WindowMus to use when sending messages to the server. +aura::WindowMus* GetWindowMus(aura::Window* window) { + if (!aura::WindowMus::Get(window)) + return nullptr; + + aura::Window* root_window = window->GetRootWindow(); + if (!root_window) + return nullptr; + + // DesktopNativeWidgetAura creates two aura Windows. GetNativeWindow() returns + // the child window. Get the widget for |window| and its root. If the Widgets + // are the same, it means |window| is the native window of a + // DesktopNativeWidgetAura. Use the root window to notify the server as that + // corresponds to the top-level window that ash knows about. + views::Widget* widget = views::Widget::GetWidgetForNativeView(window); + views::Widget* root_widget = + views::Widget::GetWidgetForNativeView(root_window); + return widget == root_widget ? aura::WindowMus::Get(root_window) : nullptr; +} + } // namespace // This class keeps track of all applications which were started for a user. @@ -110,20 +136,26 @@ : current_account_id_(current_account_id), ash_multi_user_window_manager_( std::make_unique<ash::MultiUserWindowManager>(this, - current_account_id)) {} + current_account_id)) { + if (features::IsUsingWindowService()) { + multi_user_window_manager_mojom_ = + views::MusClient::Get() + ->window_tree_client() + ->BindWindowManagerInterface<ash::mojom::MultiUserWindowManager>(); + } +} MultiUserWindowManagerChromeOS::~MultiUserWindowManagerChromeOS() { // This may trigger callbacks to us, delete it early on. ash_multi_user_window_manager_.reset(); // Remove all window observers. - WindowToEntryMap::iterator window = window_to_entry_.begin(); - while (window != window_to_entry_.end()) { + while (!window_to_entry_.empty()) { // Explicitly remove this from window observer list since OnWindowDestroyed // no longer does that. - window->first->RemoveObserver(this); - OnWindowDestroyed(window->first); - window = window_to_entry_.begin(); + aura::Window* window = window_to_entry_.begin()->first; + window->RemoveObserver(this); + OnWindowDestroyed(window); } // Remove all app observers. @@ -174,17 +206,31 @@ return; DCHECK(GetWindowOwner(window).empty()); - window_to_entry_[window] = new WindowEntry(account_id); + std::unique_ptr<WindowEntry> window_entry_ptr = + std::make_unique<WindowEntry>(account_id); + WindowEntry* window_entry = window_entry_ptr.get(); + window_to_entry_[window] = std::move(window_entry_ptr); - ash_multi_user_window_manager_->SetWindowOwner(window, account_id); + // Check if this window was created due to a user interaction. If it was, + // transfer it to the current user. + const bool show_for_current_user = + window->GetProperty(aura::client::kCreatedByUserGesture); + if (window->env()->mode() == aura::Env::Mode::MUS) { + aura::WindowMus* window_mus = GetWindowMus(window); + if (window_mus) { + multi_user_window_manager_mojom_->SetWindowOwner( + window_mus->server_id(), account_id, show_for_current_user); + } // else case can happen during shutdown, or for child windows. + } else { + ash_multi_user_window_manager_->SetWindowOwner(window, account_id, + show_for_current_user); + } // Add observers to track state changes. window->AddObserver(this); - // Check if this window was created due to a user interaction. If it was, - // transfer it to the current user. - if (window->GetProperty(aura::client::kCreatedByUserGesture)) - window_to_entry_[window]->set_show_for_user(current_account_id_); + if (show_for_current_user) + window_entry->set_show_for_user(current_account_id_); // Notify entry adding. for (Observer& observer : observers_) @@ -200,13 +246,23 @@ void MultiUserWindowManagerChromeOS::ShowWindowForUser( aura::Window* window, const AccountId& account_id) { - ash_multi_user_window_manager_->ShowWindowForUser(window, account_id); + if (!window) + return; + + if (window->env()->mode() == aura::Env::Mode::MUS) { + aura::WindowMus* window_mus = GetWindowMus(window); + if (window_mus) { + multi_user_window_manager_mojom_->ShowWindowForUser( + window_mus->server_id(), account_id); + } + } else { + ash_multi_user_window_manager_->ShowWindowForUser(window, account_id); + } } bool MultiUserWindowManagerChromeOS::AreWindowsSharedAmongUsers() const { - WindowToEntryMap::const_iterator it = window_to_entry_.begin(); - for (; it != window_to_entry_.end(); ++it) { - if (it->second->owner() != it->second->show_for_user()) + for (auto& window_pair : window_to_entry_) { + if (window_pair.second->owner() != window_pair.second->show_for_user()) return true; } return false; @@ -214,10 +270,9 @@ void MultiUserWindowManagerChromeOS::GetOwnersOfVisibleWindows( std::set<AccountId>* account_ids) const { - for (WindowToEntryMap::const_iterator it = window_to_entry_.begin(); - it != window_to_entry_.end(); ++it) { - if (it->first->IsVisible()) - account_ids->insert(it->second->owner()); + for (auto& window_pair : window_to_entry_) { + if (window_pair.first->IsVisible()) + account_ids->insert(window_pair.second->owner()); } } @@ -278,8 +333,6 @@ } void MultiUserWindowManagerChromeOS::OnWindowDestroyed(aura::Window* window) { - // Remove the window from the owners list. - delete window_to_entry_[window]; window_to_entry_.erase(window); }
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h index 1db57996..ed9bd5f 100644 --- a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h +++ b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h
@@ -7,9 +7,9 @@ #include <map> #include <memory> -#include <string> #include "ash/multi_user/multi_user_window_manager_delegate.h" +#include "ash/public/interfaces/multi_user_window_manager.mojom.h" #include "base/macros.h" #include "base/observer_list.h" #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h" @@ -91,8 +91,8 @@ // Returns the current user for unit tests. const AccountId& GetCurrentUserForTest() const; - protected: - friend class UserSwitchAnimatorChromeOS; + private: + friend class ash::MultiUserWindowManagerChromeOSTest; class WindowEntry { public: @@ -122,15 +122,10 @@ DISALLOW_COPY_AND_ASSIGN(WindowEntry); }; - // TODO(sky): make this map to unique_ptr<WindowEntry>. - using WindowToEntryMap = std::map<aura::Window*, WindowEntry*>; + using AccountIdToAppWindowObserver = std::map<AccountId, AppObserver*>; - const WindowToEntryMap& window_to_entry() { return window_to_entry_; } - - private: - friend class ash::MultiUserWindowManagerChromeOSTest; - - typedef std::map<AccountId, AppObserver*> AccountIdToAppWindowObserver; + using WindowToEntryMap = + std::map<aura::Window*, std::unique_ptr<WindowEntry>>; // Add a browser window to the system so that the owner can be remembered. void AddBrowserWindow(Browser* browser); @@ -153,8 +148,17 @@ // The notification registrar to track the creation of browser windows. content::NotificationRegistrar registrar_; + // TODO: this won't work in the multi-process mash case. What needs to happen + // for the multi-process case is MultiUserWindowManagerDelegate needs to be + // converted to a mojom that ash uses to call this code. + // https://crbug.com/875111. std::unique_ptr<ash::MultiUserWindowManager> ash_multi_user_window_manager_; + // Only used for windows created for the window-service. For example, + // Browser windows when running in mash. + ash::mojom::MultiUserWindowManagerAssociatedPtr + multi_user_window_manager_mojom_; + DISALLOW_COPY_AND_ASSIGN(MultiUserWindowManagerChromeOS); };
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos_unittest.cc b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos_unittest.cc index 1ff34c2..1400885 100644 --- a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos_unittest.cc +++ b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos_unittest.cc
@@ -25,6 +25,7 @@ #include "ash/wm/tablet_mode/tablet_mode_window_manager.h" #include "ash/wm/window_state.h" #include "ash/wm/wm_event.h" +#include "ash/ws/window_lookup.h" #include "base/compiler_specific.h" #include "base/logging.h" #include "base/macros.h" @@ -58,13 +59,22 @@ #include "components/user_manager/scoped_user_manager.h" #include "components/user_manager/user_info.h" #include "components/user_manager/user_manager.h" +#include "services/ws/common/util.h" #include "ui/aura/client/aura_constants.h" +#include "ui/aura/env.h" +#include "ui/aura/mus/window_port_mus.h" +#include "ui/aura/mus/window_tree_client.h" #include "ui/aura/test/env_test_helper.h" +#include "ui/aura/test/mus/change_completion_waiter.h" +#include "ui/aura/test/mus/window_tree_client_test_api.h" #include "ui/aura/window.h" #include "ui/aura/window_event_dispatcher.h" +#include "ui/base/ui_base_features.h" #include "ui/base/ui_base_types.h" #include "ui/display/manager/display_manager.h" #include "ui/display/test/display_manager_test_api.h" +#include "ui/views/mus/mus_client.h" +#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h" #include "ui/wm/core/window_modality_controller.h" #include "ui/wm/core/window_util.h" #include "ui/wm/public/activation_client.h" @@ -78,6 +88,43 @@ const char kArrowBAccountIdString[] = "->{\"account_type\":\"unknown\",\"email\":\"B\"}"; +aura::Window* FindWindowInAshForClientWindow(aura::Window* window) { + if (!aura::WindowMus::Get(window)) + return nullptr; + + // Flush all messages from the WindowTreeClient to ensure the client id has + // been received. + aura::test::WaitForAllChangesToComplete(); + + DCHECK_EQ(window->env()->mode(), aura::Env::Mode::MUS); + DCHECK(views::MusClient::Exists()); + aura::WindowTreeClient* window_tree_client = + views::MusClient::Get()->window_tree_client(); + DCHECK(window_tree_client); + + aura::WindowPortMus* window_port_mus = aura::WindowPortMus::Get(window); + if (!window_port_mus) + return nullptr; // Should only happen if we're in shutdown. + + // By the time we get here the id should have been determined. + DCHECK(window_tree_client->id().has_value()); + ws::ClientSpecificId client_id = *(window_tree_client->id()); + + // Use the top-most remote window. This should correspond to the Window of + // the Widget (DesktopNativeWidgetAura creates two windows). + const ws::Id transport_id = ws::BuildTransportId( + client_id, + static_cast<ws::ClientSpecificId>(window_port_mus->server_id())); + return ash::window_lookup::GetWindowByClientId(transport_id); +} + +void FlushWindowTreeClientMessages() { + if (!views::MusClient::Exists()) + return; + aura::WindowTreeClientTestApi(views::MusClient::Get()->window_tree_client()) + .FlushForTesting(); +} + const content::BrowserContext* GetActiveContext() { const user_manager::UserManager* user_manager = user_manager::UserManager::Get(); @@ -130,8 +177,14 @@ protected: void SwitchActiveUser(const AccountId& id) { + // WaitForAllChangesToComplete() does nothing in classic mode. + // WaitForAllChangesToComplete() is called before and after to ensure all + // changes have been pushed to ash before a switch, and similarly after a + // switch. + FlushWindowTreeClientMessages(); fake_user_manager_->SwitchActiveUser(id); ash::MultiUserWindowManager::Get()->OnActiveUserSessionChanged(id); + FlushWindowTreeClientMessages(); } // Set up the test environment for this many windows. @@ -282,7 +335,6 @@ TestingBrowserProcess::GetGlobal()->local_state()); ash_test_helper()->set_test_shell_delegate(new TestShellDelegateChromeOS); AshTestBase::SetUp(); - // This test has mixed case user ids. ash_test_helper() ->test_session_controller_client() ->set_use_lower_case_user_id(false); @@ -1533,4 +1585,159 @@ EXPECT_EQ(bounds, window(1)->bounds()); } +class MultiUserWindowManagerChromeOSMashTest + : public MultiUserWindowManagerChromeOSTest { + public: + MultiUserWindowManagerChromeOSMashTest() = default; + ~MultiUserWindowManagerChromeOSMashTest() override = default; + + // MultiUserWindowManagerChromeOSTest: + void SetUp() override { + original_aura_env_mode_ = + aura::test::EnvTestHelper().SetMode(aura::Env::Mode::MUS); + feature_list_.InitWithFeatures({::features::kSingleProcessMash}, {}); + MultiUserWindowManagerChromeOSTest::SetUp(); + // TabletModeController calls to PowerManagerClient with a callback that is + // run via a posted task. Run the loop now so that we know the task is + // processed. Without this, the task gets processed later on, interfering + // with this test. + base::RunLoop().RunUntilIdle(); + + // This test configures views with mus, which means it triggers some of the + // DCHECKs ensuring Shell's Env is used. + SetRunningOutsideAsh(); + + // Configure views backed by mus. + views::MusClient::InitParams mus_client_init_params; + mus_client_init_params.connector = + ash_test_helper()->GetWindowServiceConnector(); + mus_client_init_params.create_wm_state = false; + mus_client_init_params.running_in_ws_process = true; + mus_client_ = std::make_unique<views::MusClient>(mus_client_init_params); + } + void TearDown() override { + mus_client_.reset(); + MultiUserWindowManagerChromeOSTest::TearDown(); + aura::test::EnvTestHelper().SetMode(original_aura_env_mode_); + } + + protected: + std::unique_ptr<views::Widget> CreateMusWidget() { + std::unique_ptr<views::Widget> widget = std::make_unique<views::Widget>(); + views::Widget::InitParams params; + params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + params.bounds = gfx::Rect(0, 0, 200, 200); + params.native_widget = + mus_client_->CreateNativeWidget(params, widget.get()); + widget->Init(params); + widget->Show(); + EXPECT_EQ(aura::Env::Mode::MUS, widget->GetNativeWindow()->env()->mode()); + // Flush all messages from the WindowTreeClient to ensure ash has finished + // Widget creation. + aura::test::WaitForAllChangesToComplete(); + return widget; + } + + private: + aura::Env::Mode original_aura_env_mode_ = aura::Env::Mode::LOCAL; + base::test::ScopedFeatureList feature_list_; + std::unique_ptr<views::MusClient> mus_client_; + + DISALLOW_COPY_AND_ASSIGN(MultiUserWindowManagerChromeOSMashTest); +}; + +TEST_F(MultiUserWindowManagerChromeOSMashTest, + SingleProcessMashWindowOrdering) { + SetUpForThisManyWindows(1); + + std::unique_ptr<views::Widget> widget = CreateMusWidget(); + aura::Window* widget_window_in_ash = + FindWindowInAshForClientWindow(widget->GetNativeWindow()->parent()); + ASSERT_TRUE(widget_window_in_ash); + EXPECT_EQ(widget_window_in_ash->parent(), window(0)->parent()); + + const AccountId account_id_A(AccountId::FromUserEmail("A")); + const AccountId account_id_B(AccountId::FromUserEmail("B")); + AddTestUser(account_id_A); + AddTestUser(account_id_B); + SwitchActiveUser(account_id_A); + + // Set the windows owner. + ::wm::ActivationClient* activation_client = + ::wm::GetActivationClient(window(0)->GetRootWindow()); + multi_user_window_manager()->SetWindowOwner(window(0), account_id_A); + multi_user_window_manager()->SetWindowOwner(widget->GetNativeWindow(), + account_id_A); + aura::test::WaitForAllChangesToComplete(); + + // Activate the windows one by one. + activation_client->ActivateWindow(widget_window_in_ash); + EXPECT_EQ(activation_client->GetActiveWindow(), widget_window_in_ash); + activation_client->ActivateWindow(window(0)); + EXPECT_EQ(activation_client->GetActiveWindow(), window(0)); + + aura::Window::Windows mru_list = + Shell::Get()->mru_window_tracker()->BuildMruWindowList(); + EXPECT_EQ(mru_list[0], window(0)); + EXPECT_EQ(mru_list[1], widget_window_in_ash); + + SwitchActiveUser(account_id_B); + EXPECT_EQ(activation_client->GetActiveWindow(), nullptr); + + SwitchActiveUser(account_id_A); + EXPECT_EQ(activation_client->GetActiveWindow(), window(0)); + + mru_list = Shell::Get()->mru_window_tracker()->BuildMruWindowList(); + ASSERT_EQ(2u, mru_list.size()); + EXPECT_EQ(mru_list[0], window(0)); + EXPECT_TRUE(widget_window_in_ash->Contains(mru_list[1])); + + // Swap the activation order, and retry. + activation_client->ActivateWindow(window(0)); + EXPECT_EQ(activation_client->GetActiveWindow(), window(0)); + activation_client->ActivateWindow(widget_window_in_ash); + EXPECT_EQ(activation_client->GetActiveWindow(), widget_window_in_ash); + + mru_list = Shell::Get()->mru_window_tracker()->BuildMruWindowList(); + EXPECT_EQ(mru_list[0], widget_window_in_ash); + EXPECT_EQ(mru_list[1], window(0)); + + SwitchActiveUser(account_id_B); + EXPECT_EQ(activation_client->GetActiveWindow(), nullptr); + + SwitchActiveUser(account_id_A); + EXPECT_EQ(activation_client->GetActiveWindow(), widget_window_in_ash); + + mru_list = Shell::Get()->mru_window_tracker()->BuildMruWindowList(); + EXPECT_EQ(mru_list[0], widget_window_in_ash); + EXPECT_EQ(mru_list[1], window(0)); +} + +TEST_F(MultiUserWindowManagerChromeOSMashTest, SetWindowOwner) { + SetUpForThisManyWindows(1); + + std::unique_ptr<views::Widget> widget = CreateMusWidget(); + const AccountId account1(AccountId::FromUserEmail("A")); + const AccountId account2(AccountId::FromUserEmail("B")); + AddTestUser(account1); + AddTestUser(account2); + SwitchActiveUser(account1); + + // Make both windows be own by |account1|. + multi_user_window_manager()->SetWindowOwner(window(0), account1); + multi_user_window_manager()->SetWindowOwner(widget->GetNativeWindow(), + account1); + aura::test::WaitForAllChangesToComplete(); + + // Switch to account2, which should hide the widget. + SwitchActiveUser(account2); + EXPECT_FALSE(widget->IsVisible()); + + // Show the widget for the current user, which should trigger showing it. + multi_user_window_manager()->ShowWindowForUser(widget->GetNativeWindow(), + account2); + aura::test::WaitForAllChangesToComplete(); + EXPECT_TRUE(widget->IsVisible()); +} + } // namespace ash
diff --git a/chrome/browser/ui/startup/startup_browser_creator.cc b/chrome/browser/ui/startup/startup_browser_creator.cc index 2ac28dc..9ca0cf74 100644 --- a/chrome/browser/ui/startup/startup_browser_creator.cc +++ b/chrome/browser/ui/startup/startup_browser_creator.cc
@@ -470,9 +470,9 @@ // creation. registry->RegisterBooleanPref(prefs::kHasSeenWelcomePage, true); #if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD) - // This will be set to true for newly created profiles, and is used to - // indicate which users went through FRE after NUX is enabled. - registry->RegisterBooleanPref(prefs::kOnboardDuringNUX, false); + // This will be set to a group number for newly created profiles, and is used + // to indicate which users went through onboarding with the current group. + registry->RegisterIntegerPref(prefs::kNuxOnboardGroup, 0); #endif // defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD) }
diff --git a/chrome/browser/ui/views/feature_promos/reopen_tab_promo_controller.cc b/chrome/browser/ui/views/feature_promos/reopen_tab_promo_controller.cc new file mode 100644 index 0000000..e2549cd --- /dev/null +++ b/chrome/browser/ui/views/feature_promos/reopen_tab_promo_controller.cc
@@ -0,0 +1,95 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/views/feature_promos/reopen_tab_promo_controller.h" + +#include "chrome/app/chrome_command_ids.h" +#include "chrome/browser/ui/in_product_help/reopen_tab_in_product_help.h" +#include "chrome/browser/ui/in_product_help/reopen_tab_in_product_help_factory.h" +#include "chrome/browser/ui/toolbar/app_menu_model.h" +#include "chrome/browser/ui/views/feature_promos/feature_promo_bubble_view.h" +#include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/browser/ui/views/toolbar/app_menu.h" +#include "chrome/browser/ui/views/toolbar/browser_app_menu_button.h" +#include "chrome/browser/ui/views/toolbar/toolbar_view.h" +#include "chrome/grit/generated_resources.h" +#include "ui/views/controls/menu/menu_item_view.h" + +ReopenTabPromoController::ReopenTabPromoController(BrowserView* browser_view) + : iph_service_(ReopenTabInProductHelpFactory::GetForProfile( + browser_view->browser()->profile())), + browser_view_(browser_view) { + // Check that the app menu button exists. It should only not exist when there + // is no tab strip, in which case this shouldn't trigger in the first place. + BrowserAppMenuButton* app_menu_button = + browser_view_->toolbar()->app_menu_button(); + DCHECK(app_menu_button); +} + +void ReopenTabPromoController::ShowPromo() { + // Here, we start the promo display. We highlight the app menu button and open + // the promo bubble. + BrowserAppMenuButton* app_menu_button = + browser_view_->toolbar()->app_menu_button(); + app_menu_button->AddMenuListener(this); + app_menu_button->SetHighlighted(true); + + promo_bubble_ = FeaturePromoBubbleView::CreateOwned( + app_menu_button, views::BubbleBorder::Arrow::TOP_RIGHT, + IDS_REOPEN_TAB_PROMO, FeaturePromoBubbleView::ActivationAction::ACTIVATE); + promo_bubble_->GetWidget()->AddObserver(this); +} + +void ReopenTabPromoController::OnMenuOpened() { + // The user followed the promo and opened the menu. Now, we highlight the + // history item and observe for the history submenu opening. + BrowserAppMenuButton* app_menu_button = + browser_view_->toolbar()->app_menu_button(); + app_menu_button->RemoveMenuListener(this); + + AppMenu* app_menu = app_menu_button->app_menu(); + app_menu->AddObserver(this); + + views::MenuItemView* recent_tabs_menu_item = + app_menu->root_menu_item()->GetMenuItemByID(IDC_RECENT_TABS_MENU); + recent_tabs_menu_item->SetForcedVisualSelection(true); +} + +void ReopenTabPromoController::OnWidgetDestroying(views::Widget* widget) { + DCHECK(promo_bubble_); + + // If the menu isn't showing, that means the promo bubble timed out. We should + // notify our IPH service that help was dismissed. + if (!browser_view_->toolbar()->app_menu_button()->IsMenuShowing()) { + BrowserAppMenuButton* app_menu_button = + browser_view_->toolbar()->app_menu_button(); + app_menu_button->RemoveMenuListener(this); + app_menu_button->SetHighlighted(false); + + iph_service_->HelpDismissed(); + } +} + +void ReopenTabPromoController::AppMenuClosed() { + // The menu was opened then closed, whether by clicking away or by clicking a + // menu item. We notify the service regardless of whether IPH succeeded. + // Success is determined by whether the reopen tab event was sent. + iph_service_->HelpDismissed(); + + AppMenu* app_menu = browser_view_->toolbar()->app_menu_button()->app_menu(); + app_menu->RemoveObserver(this); +} + +void ReopenTabPromoController::OnShowSubmenu() { + // Check if the last opened tab menu item exists (it will if the history + // submenu was opened). If so, highlight it. + views::MenuItemView* root_menu_item = + browser_view_->toolbar()->app_menu_button()->app_menu()->root_menu_item(); + views::MenuItemView* last_tab_menu_item = + root_menu_item->GetMenuItemByID(AppMenuModel::kMinRecentTabsCommandId); + if (last_tab_menu_item) { + // The history submenu was shown. Highlight the last-closed tab item. + last_tab_menu_item->SetForcedVisualSelection(true); + } +}
diff --git a/chrome/browser/ui/views/feature_promos/reopen_tab_promo_controller.h b/chrome/browser/ui/views/feature_promos/reopen_tab_promo_controller.h new file mode 100644 index 0000000..1b51c2da --- /dev/null +++ b/chrome/browser/ui/views/feature_promos/reopen_tab_promo_controller.h
@@ -0,0 +1,44 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_VIEWS_FEATURE_PROMOS_REOPEN_TAB_PROMO_CONTROLLER_H_ +#define CHROME_BROWSER_UI_VIEWS_FEATURE_PROMOS_REOPEN_TAB_PROMO_CONTROLLER_H_ + +#include "chrome/browser/ui/views/toolbar/app_menu_observer.h" +#include "ui/views/controls/menu/menu_listener.h" +#include "ui/views/widget/widget_observer.h" + +class BrowserView; +class FeaturePromoBubbleView; +class ReopenTabInProductHelp; + +// Handles display of the reopen tab in-product help promo, including showing +// the promo bubble and highlighting the appropriate app menu items. Notifies +// the |ReopenTabInProductHelp| service when the promo is finished. +class ReopenTabPromoController : public AppMenuObserver, + public views::MenuListener, + public views::WidgetObserver { + public: + explicit ReopenTabPromoController(BrowserView* browser_view); + ~ReopenTabPromoController() override = default; + + void ShowPromo(); + + private: + // views::MenuListener: + void OnMenuOpened() override; + + // views::WidgetObserver: + void OnWidgetDestroying(views::Widget* widget) override; + + // AppMenuObserver: + void AppMenuClosed() override; + void OnShowSubmenu() override; + + ReopenTabInProductHelp* const iph_service_; + BrowserView* const browser_view_; + FeaturePromoBubbleView* promo_bubble_ = nullptr; +}; + +#endif // CHROME_BROWSER_UI_VIEWS_FEATURE_PROMOS_REOPEN_TAB_PROMO_CONTROLLER_H_
diff --git a/chrome/browser/ui/views/frame/app_menu_button.h b/chrome/browser/ui/views/frame/app_menu_button.h index e9036c6..409ce46d 100644 --- a/chrome/browser/ui/views/frame/app_menu_button.h +++ b/chrome/browser/ui/views/frame/app_menu_button.h
@@ -43,7 +43,7 @@ // Removes a menu listener. void RemoveMenuListener(views::MenuListener* listener); - AppMenu* app_menu_for_testing() { return menu_.get(); } + AppMenu* app_menu() { return menu_.get(); } protected: // Create (but don't show) the menu. |menu_model| should be a newly created
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc index e4f7a82..cac0c11 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
@@ -778,8 +778,7 @@ } AppMenu* GetAppMenu() { - return hosted_app_button_container_->app_menu_button_ - ->app_menu_for_testing(); + return hosted_app_button_container_->app_menu_button_->app_menu(); } SkColor GetActiveColor() {
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index 67ef208..b29e298 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -100,6 +100,7 @@ #include "chrome/browser/ui/views/tabs/tab.h" #include "chrome/browser/ui/views/tabs/tab_strip.h" #include "chrome/browser/ui/views/toolbar/browser_actions_container.h" +#include "chrome/browser/ui/views/toolbar/browser_app_menu_button.h" #include "chrome/browser/ui/views/toolbar/reload_button.h" #include "chrome/browser/ui/views/toolbar/toolbar_view.h" #include "chrome/browser/ui/views/translate/translate_bubble_view.h" @@ -194,6 +195,7 @@ #if BUILDFLAG(ENABLE_DESKTOP_IN_PRODUCT_HELP) #include "chrome/browser/ui/in_product_help/reopen_tab_in_product_help.h" #include "chrome/browser/ui/in_product_help/reopen_tab_in_product_help_factory.h" +#include "chrome/browser/ui/views/feature_promos/reopen_tab_promo_controller.h" #endif // BUILDFLAG(ENABLE_DESKTOP_IN_PRODUCT_HELP) #if BUILDFLAG(ENABLE_ONE_CLICK_SIGNIN) @@ -2958,9 +2960,11 @@ void BrowserView::ShowInProductHelpPromo(InProductHelpFeature iph_feature) { switch (iph_feature) { case InProductHelpFeature::kReopenTab: - // TODO(collinbaker): start in-product help flow here. - ReopenTabInProductHelpFactory::GetForProfile(browser()->profile()) - ->HelpDismissed(); + if (!reopen_tab_promo_controller_) { + reopen_tab_promo_controller_ = + std::make_unique<ReopenTabPromoController>(this); + } + reopen_tab_promo_controller_->ShowPromo(); break; } }
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h index a80f870..f5aa356 100644 --- a/chrome/browser/ui/views/frame/browser_view.h +++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -61,6 +61,7 @@ class FullscreenControlHost; class InfoBarContainerView; class LocationBarView; +class ReopenTabPromoController; class StatusBubbleViews; class TabStrip; class ToolbarButtonProvider; @@ -806,6 +807,10 @@ std::unique_ptr<FullscreenControlHost> fullscreen_control_host_; +#if BUILDFLAG(ENABLE_DESKTOP_IN_PRODUCT_HELP) + std::unique_ptr<ReopenTabPromoController> reopen_tab_promo_controller_; +#endif + struct ResizeSession { // The time when user started resizing the window. base::TimeTicks begin_timestamp;
diff --git a/chrome/browser/ui/views/media_router/app_menu_test_api_views.cc b/chrome/browser/ui/views/media_router/app_menu_test_api_views.cc index 80e5679..04018e5 100644 --- a/chrome/browser/ui/views/media_router/app_menu_test_api_views.cc +++ b/chrome/browser/ui/views/media_router/app_menu_test_api_views.cc
@@ -57,7 +57,7 @@ } AppMenu* AppMenuTestApiViews::GetAppMenu() { - return GetAppMenuButton()->app_menu_for_testing(); + return GetAppMenuButton()->app_menu(); } } // namespace
diff --git a/chrome/browser/ui/views/toolbar/app_menu.cc b/chrome/browser/ui/views/toolbar/app_menu.cc index ef4d8ea..e83c5a5 100644 --- a/chrome/browser/ui/views/toolbar/app_menu.cc +++ b/chrome/browser/ui/views/toolbar/app_menu.cc
@@ -1025,6 +1025,11 @@ } void AppMenu::WillShowMenu(MenuItemView* menu) { + if (menu != root_) { + for (AppMenuObserver& observer : observer_list_) + observer.OnShowSubmenu(); + } + if (menu == bookmark_menu_) CreateBookmarkMenu(); else if (bookmark_menu_delegate_) @@ -1051,6 +1056,9 @@ } void AppMenu::OnMenuClosed(views::MenuItemView* menu) { + for (AppMenuObserver& observer : observer_list_) + observer.AppMenuClosed(); + if (bookmark_menu_delegate_.get()) { BookmarkModel* model = BookmarkModelFactory::GetForBrowserContext(browser_->profile());
diff --git a/chrome/browser/ui/views/toolbar/app_menu.h b/chrome/browser/ui/views/toolbar/app_menu.h index 21538b8437..1e917da2 100644 --- a/chrome/browser/ui/views/toolbar/app_menu.h +++ b/chrome/browser/ui/views/toolbar/app_menu.h
@@ -57,6 +57,8 @@ bool for_drop() const { return (run_flags_ & FOR_DROP) != 0; } + views::MenuItemView* root_menu_item() { return root_; } + void AddObserver(AppMenuObserver* observer); void RemoveObserver(AppMenuObserver* observer);
diff --git a/chrome/browser/ui/views/toolbar/app_menu_observer.h b/chrome/browser/ui/views/toolbar/app_menu_observer.h index 1809379b..40982e0 100644 --- a/chrome/browser/ui/views/toolbar/app_menu_observer.h +++ b/chrome/browser/ui/views/toolbar/app_menu_observer.h
@@ -8,7 +8,11 @@ class AppMenuObserver { public: // Invoked when the AppMenu is about to be destroyed (from its destructor). - virtual void AppMenuDestroyed() = 0; + virtual void AppMenuDestroyed() {} + + virtual void AppMenuClosed() {} + + virtual void OnShowSubmenu() {} protected: virtual ~AppMenuObserver() {}
diff --git a/chrome/browser/ui/views/toolbar/toolbar_action_view_interactive_uitest.cc b/chrome/browser/ui/views/toolbar/toolbar_action_view_interactive_uitest.cc index 3497911..5c4d6c7 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_action_view_interactive_uitest.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_action_view_interactive_uitest.cc
@@ -51,7 +51,7 @@ // A bunch of plumbing to safely get at the overflowed toolbar action. BrowserAppMenuButton* app_menu_button = GetAppButtonFromBrowser(browser); EXPECT_TRUE(app_menu_button->IsMenuShowing()); - AppMenu* app_menu = app_menu_button->app_menu_for_testing(); + AppMenu* app_menu = app_menu_button->app_menu(); ASSERT_TRUE(app_menu); ExtensionToolbarMenuView* menu_view = app_menu->extension_toolbar_for_testing(); @@ -92,7 +92,7 @@ // Get the overflow container. BrowserAppMenuButton* app_menu_button = GetAppButtonFromBrowser(browser); - AppMenu* app_menu = app_menu_button->app_menu_for_testing(); + AppMenu* app_menu = app_menu_button->app_menu(); ASSERT_TRUE(app_menu); ExtensionToolbarMenuView* menu_view = app_menu->extension_toolbar_for_testing();
diff --git a/chrome/browser/ui/webui/chromeos/DEPS b/chrome/browser/ui/webui/chromeos/DEPS index ef0d6e1..c1fd05f9 100644 --- a/chrome/browser/ui/webui/chromeos/DEPS +++ b/chrome/browser/ui/webui/chromeos/DEPS
@@ -1,6 +1,7 @@ include_rules = [ "+media/audio/sounds", "+services/device/public/mojom", + "+services/network", ] specific_include_rules = {
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc index 9911c73f5..8301dcc 100644 --- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
@@ -35,7 +35,6 @@ #include "chrome/browser/chromeos/net/network_portal_detector_impl.h" #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" #include "chrome/browser/chromeos/policy/device_network_configuration_updater.h" -#include "chrome/browser/chromeos/policy/temp_certs_cache_nss.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/chromeos/settings/cros_settings.h" #include "chrome/browser/lifetime/browser_shutdown.h" @@ -71,6 +70,7 @@ #include "google_apis/gaia/gaia_auth_util.h" #include "google_apis/gaia/gaia_urls.h" #include "mojo/public/cpp/bindings/callback_helpers.h" +#include "services/network/nss_temp_certs_cache_chromeos.h" #include "services/network/public/mojom/network_context.mojom.h" #include "ui/base/ime/chromeos/input_method_manager.h" #include "ui/base/ime/chromeos/input_method_util.h" @@ -1195,7 +1195,7 @@ // When the WebUI is destroyed, |untrusted_authority_certs_cache_| will go // out of scope and the certificates will not be held in memory anymore. untrusted_authority_certs_cache_ = - std::make_unique<policy::TempCertsCacheNSS>( + std::make_unique<network::NSSTempCertsCacheChromeOS>( g_browser_process->platform_part() ->browser_policy_connector_chromeos() ->GetDeviceNetworkConfigurationUpdater()
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h index e2bbb7c..75fced3 100644 --- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h
@@ -24,8 +24,8 @@ class CanonicalCookie; } -namespace policy { -class TempCertsCacheNSS; +namespace network { +class NSSTempCertsCacheChromeOS; } namespace chromeos { @@ -302,7 +302,8 @@ // Makes untrusted authority certificates from device policy available for // client certificate discovery. - std::unique_ptr<policy::TempCertsCacheNSS> untrusted_authority_certs_cache_; + std::unique_ptr<network::NSSTempCertsCacheChromeOS> + untrusted_authority_certs_cache_; base::WeakPtrFactory<GaiaScreenHandler> weak_factory_;
diff --git a/chrome/browser/ui/webui/welcome/nux_helper.cc b/chrome/browser/ui/webui/welcome/nux_helper.cc index d2434c4f..0c24ce3e 100644 --- a/chrome/browser/ui/webui/welcome/nux_helper.cc +++ b/chrome/browser/ui/webui/welcome/nux_helper.cc
@@ -3,7 +3,11 @@ // found in the LICENSE file. #include "chrome/browser/ui/webui/welcome/nux_helper.h" + +#include <string> + #include "base/feature_list.h" +#include "base/metrics/field_trial_params.h" #include "base/values.h" #include "build/build_config.h" #include "chrome/browser/profiles/profile.h" @@ -30,20 +34,38 @@ const base::FeatureParam<bool> kNuxOnboardingForceEnabledShowEmailInterstitial = {&kNuxOnboardingForceEnabled, "show-email-interstitial", true}; +int GetOnboardingGroup() { + // Preppend a 0 to avoid issues with empty string. + return std::stoi("0" + base::GetFieldTrialParamValue( + /* Must match finch study name */ "NaviOnboarding", + "onboarding-group")); +} + bool IsNuxOnboardingEnabled(Profile* profile) { if (base::FeatureList::IsEnabled(nux::kNuxOnboardingForceEnabled)) { return true; } else { #if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD) // To avoid diluting data collection, existing users should not be assigned - // an NUX group. So, the kOnboardDuringNUX flag is used to short-circuit the - // feature checks below. + // an NUX group. So, the kNuxOnboardGroup integer is used to short-circuit + // the feature checks below. PrefService* prefs = profile->GetPrefs(); - bool onboard_during_nux = - prefs && prefs->GetBoolean(prefs::kOnboardDuringNUX); + if (!prefs) + return false; - return onboard_during_nux && - base::FeatureList::IsEnabled(nux::kNuxOnboardingFeature); + int onboard_group = prefs->GetInteger(prefs::kNuxOnboardGroup); + + if (onboard_group == 0) + return false; + + int current_group = GetOnboardingGroup(); + if (onboard_group != current_group) { + // Remove user from group if they're not part of the current experiment. + prefs->SetInteger(prefs::kNuxOnboardGroup, 0); + return false; + } + + return base::FeatureList::IsEnabled(nux::kNuxOnboardingFeature); #else return false; #endif // defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
diff --git a/chrome/browser/ui/webui/welcome/nux_helper.h b/chrome/browser/ui/webui/welcome/nux_helper.h index afd9493..dc60891 100644 --- a/chrome/browser/ui/webui/welcome/nux_helper.h +++ b/chrome/browser/ui/webui/welcome/nux_helper.h
@@ -25,6 +25,15 @@ extern const base::FeatureParam<bool> kNuxOnboardingForceEnabledShowEmailInterstitial; +// Get the group number for users who onboard in this experiment. +// Groups are: +// - Specified by finch +// - The same for all experiments in finch +// - Incremented with each new version +// - Not reused +// - Cleared out when experiment ends +int GetOnboardingGroup(); + bool IsNuxOnboardingEnabled(Profile* profile); base::DictionaryValue GetNuxOnboardingModules(Profile* profile);
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index ca5b4af..db906c0a 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc
@@ -1283,10 +1283,10 @@ const char kHasSeenWin10PromoPage[] = "browser.has_seen_win10_promo_page"; #if defined(GOOGLE_CHROME_BUILD) -// Whether or not this user went through the first-run experience after NUX -// launched. This is necessary for determining which users to keep "tagging" -// with the NUX finch experiment group, and allows a more accurate analysis. -const char kOnboardDuringNUX[] = "browser.onboard_during_nux"; +// Put the user into an onboarding group that's decided when they go through +// the first run onboarding experience. Only users in a group will have their +// finch group pinged to keep track of them for the experiment. +const char kNuxOnboardGroup[] = "browser.onboard_group"; #endif // defined(GOOGLE_CHROME_BUILD) #endif // defined(OS_WIN)
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index fe67794..fc18910 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h
@@ -440,7 +440,7 @@ #if defined(OS_WIN) extern const char kHasSeenWin10PromoPage[]; #if defined(GOOGLE_CHROME_BUILD) -extern const char kOnboardDuringNUX[]; +extern const char kNuxOnboardGroup[]; #endif // defined(GOOGLE_CHROME_BUILD) #endif // defined(OS_WIN)
diff --git a/chrome/common/thread_profiler.cc b/chrome/common/thread_profiler.cc index b520412..3dc957a7 100644 --- a/chrome/common/thread_profiler.cc +++ b/chrome/common/thread_profiler.cc
@@ -66,6 +66,20 @@ return CallStackProfileParams::UNKNOWN_PROCESS; } +std::unique_ptr<base::StackSamplingProfiler::ProfileBuilder> +CreateProfileBuilder( + const CallStackProfileParams& params, + base::OnceClosure completed_callback = base::OnceClosure()) { + // Enable the new profile builder half the time. + if (base::RandInt(0, 99) < 50) { + return std::make_unique<CallStackProfileBuilder>( + params, std::move(completed_callback)); + } + + return std::make_unique<LegacyCallStackProfileBuilder>( + params, std::move(completed_callback)); +} + } // namespace // The scheduler works by splitting execution time into repeated periods such @@ -193,29 +207,16 @@ ThreadProfiler::ThreadProfiler( CallStackProfileParams::Thread thread, scoped_refptr<base::SingleThreadTaskRunner> owning_thread_task_runner) - : owning_thread_task_runner_(owning_thread_task_runner), - periodic_profile_params_(GetProcess(), - thread, - CallStackProfileParams::PERIODIC_COLLECTION), + : thread_(thread), + owning_thread_task_runner_(owning_thread_task_runner), weak_factory_(this) { if (!StackSamplingConfiguration::Get()->IsProfilerEnabledForCurrentProcess()) return; - std::unique_ptr<base::StackSamplingProfiler::ProfileBuilder> profile_builder; - // Enable the new profile builder 1% of the time. - if (base::RandInt(0, 99) == 0) { - profile_builder = - std::make_unique<CallStackProfileBuilder>(CallStackProfileParams( - GetProcess(), thread, CallStackProfileParams::PROCESS_STARTUP)); - } else { - profile_builder = - std::make_unique<LegacyCallStackProfileBuilder>(CallStackProfileParams( - GetProcess(), thread, CallStackProfileParams::PROCESS_STARTUP)); - } - startup_profiler_ = std::make_unique<StackSamplingProfiler>( base::PlatformThread::CurrentId(), kSamplingParams, - std::move(profile_builder)); + CreateProfileBuilder(CallStackProfileParams( + GetProcess(), thread, CallStackProfileParams::PROCESS_STARTUP))); startup_profiler_->Start(); @@ -256,14 +257,14 @@ void ThreadProfiler::StartPeriodicSamplingCollection() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); // NB: Destroys the previous profiler as side effect. - auto profile_builder = std::make_unique<LegacyCallStackProfileBuilder>( - periodic_profile_params_, - base::BindOnce(&ThreadProfiler::OnPeriodicCollectionCompleted, - owning_thread_task_runner_, weak_factory_.GetWeakPtr())); - periodic_profiler_ = std::make_unique<StackSamplingProfiler>( base::PlatformThread::CurrentId(), kSamplingParams, - std::move(profile_builder)); + CreateProfileBuilder( + CallStackProfileParams(GetProcess(), thread_, + CallStackProfileParams::PERIODIC_COLLECTION), + base::BindOnce(&ThreadProfiler::OnPeriodicCollectionCompleted, + owning_thread_task_runner_, + weak_factory_.GetWeakPtr()))); periodic_profiler_->Start(); }
diff --git a/chrome/common/thread_profiler.h b/chrome/common/thread_profiler.h index f1cb7e7..76a687f 100644 --- a/chrome/common/thread_profiler.h +++ b/chrome/common/thread_profiler.h
@@ -110,9 +110,9 @@ // Creates a new periodic profiler and initiates a collection with it. void StartPeriodicSamplingCollection(); - scoped_refptr<base::SingleThreadTaskRunner> owning_thread_task_runner_; + metrics::CallStackProfileParams::Thread thread_; - const metrics::CallStackProfileParams periodic_profile_params_; + scoped_refptr<base::SingleThreadTaskRunner> owning_thread_task_runner_; std::unique_ptr<base::StackSamplingProfiler> startup_profiler_;
diff --git a/chrome/renderer/net/net_error_helper.cc b/chrome/renderer/net/net_error_helper.cc index c3475d20..cd3a4f1 100644 --- a/chrome/renderer/net/net_error_helper.cc +++ b/chrome/renderer/net/net_error_helper.cc
@@ -118,7 +118,11 @@ #if defined(OS_ANDROID) bool IsAutoFetchFeatureEnabled() { - return base::FeatureList::IsEnabled(features::kAutoFetchOnNetErrorPage); + // This feature is incompatible with OfflineContentOnNetError, so don't allow + // both. + return GetOfflineContentOnNetErrorFeatureState() == + OfflineContentOnNetErrorFeatureState::kDisabled && + base::FeatureList::IsEnabled(features::kAutoFetchOnNetErrorPage); } #else // OS_ANDROID bool IsAutoFetchFeatureEnabled() { @@ -205,6 +209,14 @@ core_->LaunchDownloadsPage(); } +void NetErrorHelper::SavePageForLater() { + core_->SavePageForLater(); +} + +void NetErrorHelper::CancelSavePage() { + core_->CancelSavePage(); +} + content::RenderFrame* NetErrorHelper::GetRenderFrame() { return render_frame(); }
diff --git a/chrome/renderer/net/net_error_helper.h b/chrome/renderer/net/net_error_helper.h index 23177864..186c8cc 100644 --- a/chrome/renderer/net/net_error_helper.h +++ b/chrome/renderer/net/net_error_helper.h
@@ -68,6 +68,8 @@ void LaunchOfflineItem(const std::string& id, const std::string& name_space) override; void LaunchDownloadsPage() override; + void SavePageForLater() override; + void CancelSavePage() override; // SSLCertificateErrorPageController::Delegate implementation void SendCommand(
diff --git a/chrome/renderer/net/net_error_helper_core.cc b/chrome/renderer/net/net_error_helper_core.cc index 750dcd1..49c5ad92 100644 --- a/chrome/renderer/net/net_error_helper_core.cc +++ b/chrome/renderer/net/net_error_helper_core.cc
@@ -1128,3 +1128,17 @@ available_content_helper_.LaunchDownloadsPage(); #endif } + +void NetErrorHelperCore::SavePageForLater() { +#if defined(OS_ANDROID) + page_auto_fetcher_helper_->TrySchedule( + /*user_requested=*/true, base::BindOnce(&Delegate::SetAutoFetchState, + base::Unretained(delegate_))); +#endif +} + +void NetErrorHelperCore::CancelSavePage() { +#if defined(OS_ANDROID) + page_auto_fetcher_helper_->CancelSchedule(); +#endif +}
diff --git a/chrome/renderer/net/net_error_helper_core.h b/chrome/renderer/net/net_error_helper_core.h index 896a8f4..2f86f16 100644 --- a/chrome/renderer/net/net_error_helper_core.h +++ b/chrome/renderer/net/net_error_helper_core.h
@@ -248,6 +248,9 @@ // Shows all available offline content. void LaunchDownloadsPage(); + void CancelSavePage(); + void SavePageForLater(); + private: struct ErrorPageInfo;
diff --git a/chrome/renderer/net/net_error_page_controller.cc b/chrome/renderer/net/net_error_page_controller.cc index e8bfd97..936809d 100644 --- a/chrome/renderer/net/net_error_page_controller.cc +++ b/chrome/renderer/net/net_error_page_controller.cc
@@ -102,6 +102,16 @@ delegate_->LaunchDownloadsPage(); } +void NetErrorPageController::SavePageForLater() { + if (delegate_) + delegate_->SavePageForLater(); +} + +void NetErrorPageController::CancelSavePage() { + if (delegate_) + delegate_->CancelSavePage(); +} + NetErrorPageController::NetErrorPageController(base::WeakPtr<Delegate> delegate) : delegate_(delegate) { } @@ -129,5 +139,7 @@ .SetMethod("launchOfflineItem", &NetErrorPageController::LaunchOfflineItem) .SetMethod("launchDownloadsPage", - &NetErrorPageController::LaunchDownloadsPage); + &NetErrorPageController::LaunchDownloadsPage) + .SetMethod("savePageForLater", &NetErrorPageController::SavePageForLater) + .SetMethod("cancelSavePage", &NetErrorPageController::CancelSavePage); }
diff --git a/chrome/renderer/net/net_error_page_controller.h b/chrome/renderer/net/net_error_page_controller.h index 6c024b1..c11af32 100644 --- a/chrome/renderer/net/net_error_page_controller.h +++ b/chrome/renderer/net/net_error_page_controller.h
@@ -38,6 +38,17 @@ // Called to show all available offline content. virtual void LaunchDownloadsPage() = 0; + // Schedules a request to save the page later. This is different from the + // download button in that the page is only saved temporarily. This is used + // only for the auto-fetch-on-net-error-page feature. + virtual void SavePageForLater() = 0; + + // Cancels the request to save the page later. This cancels a previous call + // to |SavePageForLater|, or the automatic request made when loading the + // error page. This is used only for the auto-fetch-on-net-error-page + // feature. + virtual void CancelSavePage() = 0; + protected: Delegate(); virtual ~Delegate(); @@ -86,6 +97,8 @@ void LaunchOfflineItem(gin::Arguments* args); void LaunchDownloadsPage(); + void SavePageForLater(); + void CancelSavePage(); // gin::WrappableBase gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
diff --git a/chrome/renderer/safe_browsing/phishing_classifier_delegate.cc b/chrome/renderer/safe_browsing/phishing_classifier_delegate.cc index 62ec6602..4ef5ac5 100644 --- a/chrome/renderer/safe_browsing/phishing_classifier_delegate.cc +++ b/chrome/renderer/safe_browsing/phishing_classifier_delegate.cc
@@ -39,7 +39,7 @@ return url.ReplaceComponents(replacements); } -std::set<PhishingClassifierDelegate*> PhishingClassifierDelegates() { +std::set<PhishingClassifierDelegate*>& PhishingClassifierDelegates() { static base::NoDestructor<std::set<PhishingClassifierDelegate*>> s; return *s; }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java index 37f354b..6ee8160 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java
@@ -536,13 +536,13 @@ } /** - * @return The number of incognito tabs currently open. + * @return The number of tabs currently open. */ - public int incognitoTabsCount() { + public int tabsCount(boolean incognito) { return ThreadUtils.runOnUiThreadBlockingNoException(new Callable<Integer>() { @Override public Integer call() { - return getActivity().getTabModelSelector().getModel(true).getCount(); + return getActivity().getTabModelSelector().getModel(incognito).getCount(); } }); }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeTabUtils.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeTabUtils.java index cc688bc..51f7303a 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeTabUtils.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeTabUtils.java
@@ -5,6 +5,7 @@ package org.chromium.chrome.test.util; import android.app.Instrumentation; +import android.support.annotation.Nullable; import android.support.test.InstrumentationRegistry; import android.text.TextUtils; import android.view.View; @@ -45,8 +46,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import javax.annotation.Nullable; - /** * A utility class that contains methods generic to all Tabs tests. */
diff --git a/chrome/test/data/autofill/dynamic_form_element_invalid_multiple_badname_forms.html b/chrome/test/data/autofill/dynamic_form_element_invalid_multiple_badname_forms.html new file mode 100644 index 0000000..745a5a1 --- /dev/null +++ b/chrome/test/data/autofill/dynamic_form_element_invalid_multiple_badname_forms.html
@@ -0,0 +1,66 @@ +<!-- A page that is used to test that a dynamic form fill feature works properly. --> +<body> + <form name="one" action="https://example.com/" method="post"> + Name: <input type="text" name="firstname" id="firstname_1" autocomplete="given-name"><br> + <input type="text" name="firstname" id="firstname_2" autocomplete="given-name" style="display: none"><br> + Address: <input type="text" name="address1" id="address1_3"><br> + Country: <select name="country" id="country_4" onchange="CountryChanged()"> + <option value="CA">Canada</option> + <option value="US">United States</option> + </select> + <input type="reset" value="Reset"> + <input type="submit" value="Submit" id="profile_submit"> +</form> +<br><br> + <form name="one" action="https://example.com/" method="post"> + Name: <input type="text" name="firstname" id="firstname_5" autocomplete="given-name"><br> + <input type="text" name="firstname" id="firstname_6" autocomplete="given-name" style="display: none"><br> + Address: <input type="text" name="address1" id="address1_7"><br> + Country: <select name="country" id="country_8" onchange="CountryChanged()"> + <option value="CA">Canada</option> + <option value="US">United States</option> + </select> + <input type="reset" value="Reset"> + <input type="submit" value="Submit" id="profile_submit"> + </form> +</body> + +<script> + + +var notify_on_address_input_change = false; +var address_input_changed = false; + +function CountryChanged() { + // Reset the value of the address field. + var address1 = document.getElementById('address1_7'); + address1.value = ''; + address1.onchange = function() { + if (notify_on_address_input_change) + window.domAutomationController.send(address1.value != ''); + else + address_input_changed = true; + } + + // Change the element that triggered the autofill. Remove it, and make another + // field visible. This is to test if the autofill can handle the case where + // the clicked on element is no longer valid. + var first_name_input = document.getElementById("firstname_5"); + first_name_input.setAttribute("style", "display: none"); + + var name_later = document.getElementById("firstname_6"); + name_later.removeAttribute('style'); +} + + +function hasRefilled() { + var address1 = document.getElementById('address1_7'); + if (address1 && address_input_changed) { + window.domAutomationController.send(address1.value != ''); + } else { + notify_on_address_input_change = true; + } +} + +</script> +
diff --git a/chrome/test/data/autofill/dynamic_form_element_invalid_unowned_badnames.html b/chrome/test/data/autofill/dynamic_form_element_invalid_unowned_badnames.html new file mode 100644 index 0000000..1344ded --- /dev/null +++ b/chrome/test/data/autofill/dynamic_form_element_invalid_unowned_badnames.html
@@ -0,0 +1,61 @@ +<!-- A page that is used to test that a dynamic form fill feature works properly. --> +<body> + Name: <input type="text" name="firstname" id="firstname_1" autocomplete="given-name"><br> + <input type="text" name="firstname" id="firstname_2" autocomplete="given-name" style="display: none"><br> + Address: <input type="text" name="address1" id="address1_3"><br> + Country: <select name="country" id="country_4" onchange="CountryChanged()"> + <option value="CA">Canada</option> + <option value="US">United States</option> + </select> + <input type="reset" value="Reset"> + <input type="submit" value="Submit" id="profile_submit"> + Name: <input type="text" name="firstname" id="firstname_5" autocomplete="given-name"><br> + <input type="text" name="firstname" id="firstname_6" autocomplete="given-name" style="display: none"><br> + Address: <input type="text" name="address1" id="address1_7"><br> + Country: <select name="country" id="country_8" onchange="CountryChanged()"> + <option value="CA">Canada</option> + <option value="US">United States</option> + </select> + <input type="reset" value="Reset"> + <input type="submit" value="Submit" id="profile_submit"> +</body> + +<script> + + +var notify_on_address_input_change = false; +var address_input_changed = false; + +function CountryChanged() { + // Reset the value of the address field. + var address1 = document.getElementById('address1_7'); + address1.value = ''; + address1.onchange = function() { + if (notify_on_address_input_change) + window.domAutomationController.send(address1.value != ''); + else + address_input_changed = true; + } + + // Change the element that triggered the autofill. Remove it, and make another + // field visible. This is to test if the autofill can handle the case where + // the clicked on element is no longer valid. + var first_name_input = document.getElementById("firstname_5"); + first_name_input.parentNode.removeChild(first_name_input); + + var name_later = document.getElementById("firstname_6"); + name_later.removeAttribute('style'); +} + + +function hasRefilled() { + var address1 = document.getElementById('address1_7'); + if (address1 && address_input_changed) { + window.domAutomationController.send(address1.value != ''); + } else { + notify_on_address_input_change = true; + } +} + +</script> +
diff --git a/chrome_elf/OWNERS b/chrome_elf/OWNERS index 62497b2..75fbb43 100644 --- a/chrome_elf/OWNERS +++ b/chrome_elf/OWNERS
@@ -1,5 +1,6 @@ caitkp@chromium.org pennymac@chromium.org +pmonette@chromium.org robertshield@chromium.org # TEAM: security-dev@chromium.org
diff --git a/chrome_elf/sha1/sha1.cc b/chrome_elf/sha1/sha1.cc index 63e5f102..3139b86 100644 --- a/chrome_elf/sha1/sha1.cc +++ b/chrome_elf/sha1/sha1.cc
@@ -205,26 +205,11 @@ //------------------------------------------------------------------------------ // Public functions //------------------------------------------------------------------------------ - -int CompareHashes(const uint8_t* first, const uint8_t* second) { - // Compare bytes, high-order to low-order. - for (size_t i = 0; i < kSHA1Length; ++i) { - if (first[i] < second[i]) - return -1; - if (first[i] > second[i]) - return 1; - // else they are equal, continue; - } - - return 0; -} - -std::string SHA1HashString(const std::string& str) { - char hash[kSHA1Length] = {}; +Digest SHA1HashString(const std::string& str) { + Digest digest; SHA1HashBytes(reinterpret_cast<const unsigned char*>(str.c_str()), - str.length(), reinterpret_cast<unsigned char*>(hash)); - - return std::string(hash, kSHA1Length); + str.length(), reinterpret_cast<unsigned char*>(&digest[0])); + return digest; } } // namespace elf_sha1
diff --git a/chrome_elf/sha1/sha1.h b/chrome_elf/sha1/sha1.h index 5d57e470c..fdb2d57 100644 --- a/chrome_elf/sha1/sha1.h +++ b/chrome_elf/sha1/sha1.h
@@ -11,6 +11,7 @@ #include <stddef.h> +#include <array> #include <string> namespace elf_sha1 { @@ -18,16 +19,10 @@ // Length in bytes of a SHA-1 hash. constexpr size_t kSHA1Length = 20; -// Compare two hashes. -// - Returns -1 if |first| < |second| -// - Returns 0 if |first| == |second| -// - Returns 1 if |first| > |second| -// Note: Arguments should be kSHA1Length long. -int CompareHashes(const uint8_t* first, const uint8_t* second); +using Digest = std::array<uint8_t, kSHA1Length>; -// Computes the SHA1 hash of the input string |str| and returns the full -// hash. The returned SHA1 will be 20 bytes in length. -std::string SHA1HashString(const std::string& str); +// Returns the computed SHA1 of the input string |str|. +Digest SHA1HashString(const std::string& str); } // namespace elf_sha1
diff --git a/chrome_elf/sha1/sha1_unittest.cc b/chrome_elf/sha1/sha1_unittest.cc index 1f07ad8..8d45c99 100644 --- a/chrome_elf/sha1/sha1_unittest.cc +++ b/chrome_elf/sha1/sha1_unittest.cc
@@ -20,12 +20,11 @@ // Example A.1 from FIPS 180-2: one-block message. std::string input = "abc"; - int expected[] = {0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, 0xba, 0x3e, - 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c, 0x9c, 0xd0, 0xd8, 0x9d}; + elf_sha1::Digest expected = {0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, + 0x6a, 0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, + 0xc2, 0x6c, 0x9c, 0xd0, 0xd8, 0x9d}; - std::string output = elf_sha1::SHA1HashString(input); - for (size_t i = 0; i < elf_sha1::kSHA1Length; i++) - EXPECT_EQ(expected[i], output[i] & 0xFF); + EXPECT_EQ(elf_sha1::SHA1HashString(input), expected); } TEST(SHA1Test, Test2) { @@ -33,24 +32,22 @@ std::string input = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; - int expected[] = {0x84, 0x98, 0x3e, 0x44, 0x1c, 0x3b, 0xd2, 0x6e, 0xba, 0xae, - 0x4a, 0xa1, 0xf9, 0x51, 0x29, 0xe5, 0xe5, 0x46, 0x70, 0xf1}; + elf_sha1::Digest expected = {0x84, 0x98, 0x3e, 0x44, 0x1c, 0x3b, 0xd2, + 0x6e, 0xba, 0xae, 0x4a, 0xa1, 0xf9, 0x51, + 0x29, 0xe5, 0xe5, 0x46, 0x70, 0xf1}; - std::string output = elf_sha1::SHA1HashString(input); - for (size_t i = 0; i < elf_sha1::kSHA1Length; i++) - EXPECT_EQ(expected[i], output[i] & 0xFF); + EXPECT_EQ(elf_sha1::SHA1HashString(input), expected); } TEST(SHA1Test, Test3) { // Example A.3 from FIPS 180-2: long message. std::string input(1000000, 'a'); - int expected[] = {0x34, 0xaa, 0x97, 0x3c, 0xd4, 0xc4, 0xda, 0xa4, 0xf6, 0x1e, - 0xeb, 0x2b, 0xdb, 0xad, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6f}; + elf_sha1::Digest expected = {0x34, 0xaa, 0x97, 0x3c, 0xd4, 0xc4, 0xda, + 0xa4, 0xf6, 0x1e, 0xeb, 0x2b, 0xdb, 0xad, + 0x27, 0x31, 0x65, 0x34, 0x01, 0x6f}; - std::string output = elf_sha1::SHA1HashString(input); - for (size_t i = 0; i < elf_sha1::kSHA1Length; i++) - EXPECT_EQ(expected[i], output[i] & 0xFF); + EXPECT_EQ(elf_sha1::SHA1HashString(input), expected); } } // namespace
diff --git a/chrome_elf/third_party_dlls/hook.cc b/chrome_elf/third_party_dlls/hook.cc index a0f25247..68db6ab2 100644 --- a/chrome_elf/third_party_dlls/hook.cc +++ b/chrome_elf/third_party_dlls/hook.cc
@@ -294,25 +294,24 @@ } // Note that one of either image_name or section_basename can be empty. - std::string image_name_hash; + elf_sha1::Digest image_name_hash; if (!image_name.empty()) image_name_hash = elf_sha1::SHA1HashString(image_name); - std::string section_basename_hash; + elf_sha1::Digest section_basename_hash; if (!section_basename.empty()) section_basename_hash = elf_sha1::SHA1HashString(section_basename); - std::string fingerprint_hash = - GetFingerprintString(time_date_stamp, image_size); - fingerprint_hash = elf_sha1::SHA1HashString(fingerprint_hash); + elf_sha1::Digest fingerprint_hash = elf_sha1::SHA1HashString( + GetFingerprintString(time_date_stamp, image_size)); // Check sources for blacklist decision. bool block = false; - if (!image_name_hash.empty() && + if (!image_name.empty() && IsModuleListed(image_name_hash, fingerprint_hash)) { // 1) Third-party DLL blacklist, check for image name from PE header. block = true; - } else if (!section_basename_hash.empty() && - section_basename_hash.compare(image_name_hash) != 0 && + } else if (!section_basename.empty() && + section_basename_hash != image_name_hash && IsModuleListed(section_basename_hash, fingerprint_hash)) { // 2) Third-party DLL blacklist, check for image name from the section. block = true;
diff --git a/chrome_elf/third_party_dlls/main_unittest.cc b/chrome_elf/third_party_dlls/main_unittest.cc index cfca6450..dcc9406 100644 --- a/chrome_elf/third_party_dlls/main_unittest.cc +++ b/chrome_elf/third_party_dlls/main_unittest.cc
@@ -6,6 +6,8 @@ #include <windows.h> +#include <string> + #include "base/command_line.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" @@ -98,15 +100,11 @@ // Internally, an empty string should not be passed in here. assert(!image_name.empty()); - // SHA1 hash the two strings, and copy them into the new struct. - std::string code_id = GetFingerprintString(timedatestamp, imagesize); - code_id = elf_sha1::SHA1HashString(code_id); - std::string name_hash = elf_sha1::SHA1HashString(image_name); - + // SHA1 hash the two strings into the new struct. PackedListModule packed_module; - ::memcpy(packed_module.code_id_hash, code_id.data(), elf_sha1::kSHA1Length); - ::memcpy(packed_module.basename_hash, name_hash.data(), - elf_sha1::kSHA1Length); + packed_module.code_id_hash = + elf_sha1::SHA1HashString(GetFingerprintString(timedatestamp, imagesize)); + packed_module.basename_hash = elf_sha1::SHA1HashString(image_name); return packed_module; } @@ -480,15 +478,14 @@ // Get hashes from base_sha1. const std::string module_basename_hash = base::SHA1HashString(base::UTF16ToUTF8(kChineseUnicode)); - const std::string module_code_id_hash = - base::SHA1HashString(base::StringPrintf( - "%08lX%lx", module_data.timedatestamp, module_data.imagesize)); + const std::string module_code_id_hash = base::SHA1HashString( + GetFingerprintString(module_data.timedatestamp, module_data.imagesize)); // Compare the hashes. - EXPECT_EQ(::memcmp(elf_sha1_generated.basename_hash, + EXPECT_EQ(::memcmp(&elf_sha1_generated.basename_hash[0], module_basename_hash.data(), elf_sha1::kSHA1Length), 0); - EXPECT_EQ(::memcmp(elf_sha1_generated.code_id_hash, + EXPECT_EQ(::memcmp(&elf_sha1_generated.code_id_hash[0], module_code_id_hash.data(), elf_sha1::kSHA1Length), 0); }
diff --git a/chrome_elf/third_party_dlls/packed_list_file.cc b/chrome_elf/third_party_dlls/packed_list_file.cc index 8d8d355..55743f1c 100644 --- a/chrome_elf/third_party_dlls/packed_list_file.cc +++ b/chrome_elf/third_party_dlls/packed_list_file.cc
@@ -42,7 +42,7 @@ // std::equal_range/std::is_sorted. Must return TRUE if lhs < rhs. bool HashBinaryPredicate(const PackedListModule& lhs, const PackedListModule& rhs) { - return elf_sha1::CompareHashes(lhs.basename_hash, rhs.basename_hash) < 0; + return lhs.basename_hash < rhs.basename_hash; } // Given a file opened for read, pull in the packed list. @@ -172,19 +172,16 @@ // Public defines & functions //------------------------------------------------------------------------------ -bool IsModuleListed(const std::string& basename_hash, - const std::string& fingerprint_hash) { +bool IsModuleListed(const elf_sha1::Digest& basename_hash, + const elf_sha1::Digest& fingerprint_hash) { assert(g_initialized); - assert(!basename_hash.empty() && !fingerprint_hash.empty()); - assert(basename_hash.length() == elf_sha1::kSHA1Length && - fingerprint_hash.length() == elf_sha1::kSHA1Length); if (!g_bl_module_array_size) return false; PackedListModule target = {}; - ::memcpy(target.basename_hash, basename_hash.data(), elf_sha1::kSHA1Length); - ::memcpy(target.code_id_hash, fingerprint_hash.data(), elf_sha1::kSHA1Length); + target.basename_hash = basename_hash; + target.code_id_hash = fingerprint_hash; // Binary search for primary hash (basename). There can be more than one // match. @@ -194,7 +191,7 @@ // Search for secondary hash. for (PackedListModule* i = pair.first; i != pair.second; ++i) { - if (!elf_sha1::CompareHashes(target.code_id_hash, i->code_id_hash)) + if (target.code_id_hash == i->code_id_hash) return true; }
diff --git a/chrome_elf/third_party_dlls/packed_list_file.h b/chrome_elf/third_party_dlls/packed_list_file.h index 72a6e9e..53393d4 100644 --- a/chrome_elf/third_party_dlls/packed_list_file.h +++ b/chrome_elf/third_party_dlls/packed_list_file.h
@@ -7,14 +7,15 @@ #include <string> +#include "chrome_elf/sha1/sha1.h" #include "chrome_elf/third_party_dlls/status_codes.h" namespace third_party_dlls { // Look up a binary based on the required data points. // - Returns true if match found in the list. -bool IsModuleListed(const std::string& basename_hash, - const std::string& fingerprint_hash); +bool IsModuleListed(const elf_sha1::Digest& basename_hash, + const elf_sha1::Digest& fingerprint_hash); // Get the full path of the blacklist file used. std::wstring GetBlFilePathUsed();
diff --git a/chrome_elf/third_party_dlls/packed_list_file_unittest.cc b/chrome_elf/third_party_dlls/packed_list_file_unittest.cc index 06fc110..3c6219a0 100644 --- a/chrome_elf/third_party_dlls/packed_list_file_unittest.cc +++ b/chrome_elf/third_party_dlls/packed_list_file_unittest.cc
@@ -79,8 +79,6 @@ base::FilePath path; char buffer[kPageSize]; PIMAGE_NT_HEADERS nt_headers = nullptr; - std::string code_id; - std::string basename_hash; test_modules->clear(); packed_modules->clear(); @@ -106,15 +104,11 @@ test_modules->push_back(test_module); // SHA1 hash the two strings, and copy them into the module array. - code_id = base::StringPrintf("%08lX%lx", test_module.timedatestamp, - test_module.imagesize); - code_id = elf_sha1::SHA1HashString(code_id); - basename_hash = elf_sha1::SHA1HashString(test_module.basename); - PackedListModule packed_module; - ::memcpy(packed_module.code_id_hash, code_id.data(), elf_sha1::kSHA1Length); - ::memcpy(packed_module.basename_hash, basename_hash.data(), - elf_sha1::kSHA1Length); + packed_module.code_id_hash = elf_sha1::SHA1HashString( + GetFingerprintString(test_module.timedatestamp, test_module.imagesize)); + packed_module.basename_hash = + elf_sha1::SHA1HashString(test_module.basename); packed_modules->push_back(packed_module); } @@ -198,22 +192,18 @@ // Init. ASSERT_EQ(InitFromFile(), ThirdPartyStatus::kSuccess); - std::string fingerprint_hash; - std::string name_hash; - // Test matching. for (const auto& test_module : GetTestArray()) { - fingerprint_hash = - GetFingerprintString(test_module.timedatestamp, test_module.imagesize); - fingerprint_hash = elf_sha1::SHA1HashString(fingerprint_hash); - name_hash = elf_sha1::SHA1HashString(test_module.basename); + elf_sha1::Digest name_hash = elf_sha1::SHA1HashString(test_module.basename); + elf_sha1::Digest fingerprint_hash = elf_sha1::SHA1HashString( + GetFingerprintString(test_module.timedatestamp, test_module.imagesize)); EXPECT_TRUE(IsModuleListed(name_hash, fingerprint_hash)); } // Test a failure to match. - fingerprint_hash = GetFingerprintString(0x12345678, 1337); - fingerprint_hash = elf_sha1::SHA1HashString(fingerprint_hash); - name_hash = elf_sha1::SHA1HashString("booya.dll"); + elf_sha1::Digest name_hash = elf_sha1::SHA1HashString("booya.dll"); + elf_sha1::Digest fingerprint_hash = + elf_sha1::SHA1HashString(GetFingerprintString(0x12345678, 1337)); EXPECT_FALSE(IsModuleListed(name_hash, fingerprint_hash)); } @@ -222,9 +212,9 @@ // kFileNotFound is a non-fatal status code. ASSERT_EQ(InitFromFile(), ThirdPartyStatus::kFileNotFound); - std::string fingerprint_hash = GetFingerprintString(0x12345678, 1337); - fingerprint_hash = elf_sha1::SHA1HashString(fingerprint_hash); - std::string name_hash = elf_sha1::SHA1HashString("booya.dll"); + elf_sha1::Digest name_hash = elf_sha1::SHA1HashString("booya.dll"); + elf_sha1::Digest fingerprint_hash = + elf_sha1::SHA1HashString(GetFingerprintString(0x12345678, 1337)); EXPECT_FALSE(IsModuleListed(name_hash, fingerprint_hash)); }
diff --git a/chrome_elf/third_party_dlls/packed_list_format.h b/chrome_elf/third_party_dlls/packed_list_format.h index 470de64..e6e4de1 100644 --- a/chrome_elf/third_party_dlls/packed_list_format.h +++ b/chrome_elf/third_party_dlls/packed_list_format.h
@@ -10,6 +10,7 @@ #ifndef CHROME_ELF_THIRD_PARTY_DLLS_PACKED_LIST_FORMAT_H_ #define CHROME_ELF_THIRD_PARTY_DLLS_PACKED_LIST_FORMAT_H_ +#include <array> #include <string> #include <stdint.h> @@ -53,9 +54,9 @@ struct PackedListModule { // SHA1 of lowercase, UTF-8 basename (no path). - uint8_t basename_hash[elf_sha1::kSHA1Length]; + elf_sha1::Digest basename_hash; // Code ID. Get the formatted string via GetFingerprintString(), then SHA1. - uint8_t code_id_hash[elf_sha1::kSHA1Length]; + elf_sha1::Digest code_id_hash; // A timestamp used for tracking "last attempted load". Used to manage // lifetime of entries in the local caches. uint32_t time_date_stamp;
diff --git a/chromeos/test/data/network/README b/chromeos/test/data/network/README new file mode 100644 index 0000000..c8f5d4a --- /dev/null +++ b/chromeos/test/data/network/README
@@ -0,0 +1,23 @@ +This directory contains test data for ChromeOS-specific network configuration +tests. + +==== Certificates ==== +The certificates in here are extracted from /net/data/ssl/certificates using the +script setup-certificates.sh. +The script produces: +(*) root_ca_cert.pem: An Authority certificate that is the root of the hierarchy. +(*) root-ca-cert.onc: ONC policy for specifying root_ca_cert.pem as an + additional trust anchor for Web navigations. +(*) ok_cert.pem: A Server certificate that is signed by root_ca_cert.pem. +(*) intermediate_ca_cert.pem: An Authority certificate that is signed by + root_ca_cert.pem +(*) root-and-intermediate-ca-certs.onc: ONC policy for specifying + root_ca_cert.pem as an additional trust anchor for Web navigations, and + intermediate_ca_cert.pem as an untrusted Authority. +(*) ok_cert_by_intermediate.pem: A Server certificate that is signed by + intermediate_ca_cert.pem. + +Run +The script takes two arguments: Input directory, output directory. +./setup-certificates.sh ${chromium_dir}/src/net/data/ssl/certificates . +in this directory to sync the certificates.
diff --git a/chromeos/test/data/network/intermediate_ca_cert.pem b/chromeos/test/data/network/intermediate_ca_cert.pem new file mode 100644 index 0000000..0a9dae5 --- /dev/null +++ b/chromeos/test/data/network/intermediate_ca_cert.pem
@@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDizCCAnOgAwIBAgIBATANBgkqhkiG9w0BAQsFADBjMQswCQYDVQQGEwJVUzET +MBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4G +A1UECgwHVGVzdCBDQTEVMBMGA1UEAwwMVGVzdCBSb290IENBMB4XDTE3MDYwNTE3 +MTA0NVoXDTI3MDYwMzE3MTA0NVowazELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNh +bGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxEDAOBgNVBAoMB1Rlc3Qg +Q0ExHTAbBgNVBAMMFFRlc3QgSW50ZXJtZWRpYXRlIENBMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAnem95D1KL/vC+eYiKkIVRhyMj0dM6cVXlR9mcJMi +8JTDu7Vb76RvyMeJlXW6DDa/TmupNUcIQ54pauLD+wO3H7bhUWvtexnH+c473GXp +ZseDlMTRTu7tZEuB8RrqWmQYG2pOk9ATbJBgytJOtyQW+LIIWJ2NpzNFFTSBrS0t +nGDv+SuY/nnTjSxI2xKR9C76v/UmwYIFgN1MqHC/p7wQNHc520cED+1EsmVGIiCI +WSgPxwyitJGloqrKBZ+Km26jy9Sk6CR1nSCBIltfdz7J8R6u64ozjCdbHr5tIRtC +cpXjnhMDdadY1L5oEv5jjksRejTno2vdc64+GZrskYtzrwIDAQABo0IwQDAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBQXXEXz0KwcEEyLQ0QgxN2TxcUZOzAOBgNV +HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggEBAD711/2COx40jGai814Y4fGp +dZ+1k+cKjs8KM+1Jzc7Oyl+jHWR204QW/p2IrPTR+DYrIIBSCu/gD2QnVTWje8aK +fKXEKRex+tKJXRNruAPL1xLWziTwr0gXA1SZr+nL/UREGCNhkPa9VWUGwzaYjep9 +D3nvtrsiKAOm7NnUG0esLCXe7xoCaUwYuylI9J3hUkJkbIhGaIaD/ST1fQXXGn4i +vEl1nIpN6POi65uDcKfW3S8FLaq+1+57jnVEO9rfhWG/6TsTQE6LUgjZ5IxU2kHb +eywFXpkGDQKMjhmOVbA6MxgwA6ftSuT4WMwSuK/WZlUp7AEfku09TcNxO+AvcJA= +-----END CERTIFICATE-----
diff --git a/chromeos/test/data/network/ok_cert.pem b/chromeos/test/data/network/ok_cert.pem index 18f94ca..5384510 100644 --- a/chromeos/test/data/network/ok_cert.pem +++ b/chromeos/test/data/network/ok_cert.pem
@@ -1,21 +1,23 @@ -----BEGIN CERTIFICATE----- -MIIDczCCAlugAwIBAgIBAjANBgkqhkiG9w0BAQsFADAXMRUwEwYDVQQDDAxUZXN0 -IFJvb3QgQ0EwHhcNMTQwODE0MDMwNTI5WhcNMjQwODExMDMwNTI5WjBgMQswCQYD -VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4g -VmlldzEQMA4GA1UECgwHVGVzdCBDQTESMBAGA1UEAwwJMTI3LjAuMC4xMIIBIjAN -BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtfj0Mtj19GXK6dDL3emXoW6Q4vSy -shbQm+KZV+17xltvScGUAKkNXbU19Dp7PBgGo3haaP+mBR99EAiuCWzc7924l55s -zsug3DMrHpXvHfvT2vg+V+2Ljp6GTRKmDDAj7whFTyESQoiHAdilMp+3OO9grbdH -aztLplwrVnJc0bU4h5nsO//GAu+GOO7iBcbwZuIYkVDlVyMnmbvbSSSIZqgUln4a -bSrh/xj1ajfSiKh5yblQ9ZpoCwSeaAIdoXHgiRW6KkgGenjT0Qx3g5iD+LniYCCS -B5vUyMD6WlqdJkDCNWUA86Di0yFNpcSRiJAUp173E7fqK6K914QYGrd7XQIDAQAB -o4GAMH4wDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUggQdvQVxg2/2mBlNTxFGiE2b -v6gwHwYDVR0jBBgwFoAUvPcw0TzA8nn675/JbFyT84poq4MwHQYDVR0lBBYwFAYI -KwYBBQUHAwEGCCsGAQUFBwMCMA8GA1UdEQQIMAaHBH8AAAEwDQYJKoZIhvcNAQEL -BQADggEBAITcEASNvT/BPvtoSz815F0C63PmDnQW5MUwawWUTpxpEF56r6R2xiin -GsFcfh1eHF6Hl/5cWyhHMbF5Svg29rFSuNWra4bv7D3tUAtAN2ULIjq3r9QENvDw -0poWaV2LJQP2BYdeSL0lFcQ7au1j2IdVjj4cRN7rG93Ec8emahJtSNXlEmqoVSYm -DX68zXGFsYp25FoaxZwmv9deVxT6tlLPhZAK6H9p4bCUG6xkWuk4zFOe/cbU4V6c -NyIuS9mBX1nhQ6d77acjIP0EkfAdTmzA3quaGStPAKMdWHTJMm7uNbYzTGSNbuyo -jtczxzPGkorOtfZdjhJS7J0Kz0s73fM= +MIIDvzCCAqegAwIBAgIBAzANBgkqhkiG9w0BAQsFADBjMQswCQYDVQQGEwJVUzET +MBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4G +A1UECgwHVGVzdCBDQTEVMBMGA1UEAwwMVGVzdCBSb290IENBMB4XDTE3MDYwNTE3 +MTA0NloXDTI3MDYwMzE3MTA0NlowYDELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNh +bGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxEDAOBgNVBAoMB1Rlc3Qg +Q0ExEjAQBgNVBAMMCTEyNy4wLjAuMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBALS/0pcz5RNbd2W9cxp1KJtHWea3MOhGM21YW9ofCv/k5C3yHfiJ6GQu +9sPN16OO1/fN59gOEMPnVtL85ebTTuL/gk0YY4ewo97a7wo3e6y1t0PO8gc53xTp +w6RBPn5oRzSbe2HEGOYTzrO0puC6A+7k6+eq9G2+l1uqBpdQAdB4uNaSsOTiuUOI +ta4UZH1ScNQFHAkl1eJPyaiC20Exw75EbwvU/b/B7tlivzuPtQDI0d9dShOtceRL +X9HZckyD2JNAv2zNL2YOBNa5QygkySX9WXD+PfKpCk7Cm8TenldeXRYl5ni2REkp +nfa/dPuF1g3xZVjyK9aPEEnIAC2I4i0CAwEAAaOBgDB+MAwGA1UdEwEB/wQCMAAw +HQYDVR0OBBYEFODc4C8HiHQ6n9Mwo3GK+dal5aZTMB8GA1UdIwQYMBaAFJsmC4qY +qbsduR8c4xpAM+2OF4irMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAP +BgNVHREECDAGhwR/AAABMA0GCSqGSIb3DQEBCwUAA4IBAQB6FEQuUDRcC5jkX3aZ +uuTeZEqMVL7JXgvgFqzXsPb8zIdmxr/tEDfwXx2qDf2Dpxts7Fq4vqUwimK4qV3K +7heLnWV2+FBvV1eeSfZ7AQj+SURkdlyo42r41+t13QUf+Z0ftR9266LSWLKrukeI +Mxk73hOkm/u8enhTd00dy/FN9dOFBFHseVMspWNxIkdRILgOmiyfQNRgxNYdOf0e +EfELR8Hn6WjZ8wAbvO4p7RTrzu1c/RZ0M+NLkID56Brbl70GC2h5681LPwAOaZ7/ +mWQ5kekSyJjmLfF12b+h9RVAt5MrXZgk2vNujssgGf4nbWh4KZyQ6qrs778ZdDLm +yfUn -----END CERTIFICATE-----
diff --git a/chromeos/test/data/network/ok_cert_by_intermediate.pem b/chromeos/test/data/network/ok_cert_by_intermediate.pem new file mode 100644 index 0000000..3b00699 --- /dev/null +++ b/chromeos/test/data/network/ok_cert_by_intermediate.pem
@@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIIDxzCCAq+gAwIBAgIBATANBgkqhkiG9w0BAQsFADBrMQswCQYDVQQGEwJVUzET +MBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4G +A1UECgwHVGVzdCBDQTEdMBsGA1UEAwwUVGVzdCBJbnRlcm1lZGlhdGUgQ0EwHhcN +MTcwNjA1MTcxMDQ2WhcNMjcwNjAzMTcxMDQ2WjBgMQswCQYDVQQGEwJVUzETMBEG +A1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4GA1UE +CgwHVGVzdCBDQTESMBAGA1UEAwwJMTI3LjAuMC4xMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAtL/SlzPlE1t3Zb1zGnUom0dZ5rcw6EYzbVhb2h8K/+Tk +LfId+InoZC72w83Xo47X983n2A4Qw+dW0vzl5tNO4v+CTRhjh7Cj3trvCjd7rLW3 +Q87yBznfFOnDpEE+fmhHNJt7YcQY5hPOs7Sm4LoD7uTr56r0bb6XW6oGl1AB0Hi4 +1pKw5OK5Q4i1rhRkfVJw1AUcCSXV4k/JqILbQTHDvkRvC9T9v8Hu2WK/O4+1AMjR +311KE61x5Etf0dlyTIPYk0C/bM0vZg4E1rlDKCTJJf1ZcP498qkKTsKbxN6eV15d +FiXmeLZESSmd9r90+4XWDfFlWPIr1o8QScgALYjiLQIDAQABo4GAMH4wDAYDVR0T +AQH/BAIwADAdBgNVHQ4EFgQU4NzgLweIdDqf0zCjcYr51qXlplMwHwYDVR0jBBgw +FoAUF1xF89CsHBBMi0NEIMTdk8XFGTswHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG +AQUFBwMCMA8GA1UdEQQIMAaHBH8AAAEwDQYJKoZIhvcNAQELBQADggEBAEP3Yzij +MD+r5mxCod3/jfatsuu2nku9kPzY9PBaQvy+W8zHJC+RSKahu6K3GWEhrNOB7m67 +BC0WtX7L5qMXjz5lTR2Nwdo9O62hs+j14xYTFwqjReDPhLI96DhpMUbojBBjD15r +9BAlI5i4XNkGeIMYcAmm74/p9f+zRIU19mlhCyqN3occ7NxQx2fviCwo3sDbbiEg +AMVbXe82xgrpBqMlPk0T+vA/vP6caEj/7BvnLDmsiCugiJYRPvAg4in8vdPTyiRj +WBcVw6wZIcshKfxT5zvPwgpe9M7xnnc41MaQTpT+LpfLGpQqHow72zZlxhm61wsD +IuWS4vY+35nOa0k= +-----END CERTIFICATE-----
diff --git a/chromeos/test/data/network/root-and-intermediate-ca-certs.onc b/chromeos/test/data/network/root-and-intermediate-ca-certs.onc new file mode 100644 index 0000000..ebc5093 --- /dev/null +++ b/chromeos/test/data/network/root-and-intermediate-ca-certs.onc
@@ -0,0 +1,19 @@ +{ + "Certificates": [ + { + "GUID": "{b3aae353-cfa9-4093-9aff-9f8ee2bf8c29}", + "TrustBits": [ + "Web" + ], + "Type": "Authority", + "X509": "-----BEGIN CERTIFICATE-----\nMIIDizCCAnOgAwIBAgIJAJRTRMx4iMvZMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNV\nBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBW\naWV3MRAwDgYDVQQKDAdUZXN0IENBMRUwEwYDVQQDDAxUZXN0IFJvb3QgQ0EwHhcN\nMTcwNjA1MTcxMDQ0WhcNMjcwNjAzMTcxMDQ0WjBjMQswCQYDVQQGEwJVUzETMBEG\nA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4GA1UE\nCgwHVGVzdCBDQTEVMBMGA1UEAwwMVGVzdCBSb290IENBMIIBIjANBgkqhkiG9w0B\nAQEFAAOCAQ8AMIIBCgKCAQEAxoEfknO2WIXZjay3IP3Hv0Cy6vrlC1IBj5rB63qA\nwfOJpD7VG2HMtc+AsRrbuyXgGL+SaSZQzec//w08tB8UEqtnN94HA2wSdII2rMPU\n02Sfke1b9ql6pJyY6GVslOHLVXOu+B1QsHjldP+xNyzLGT2kjOd2ToZcP9+z7UUj\nT1SbM8aJXhMd3X1ZpQc0KIYnH/qeU08qtkKtNxJi9XI2tgISQET+x56ViUNRXrRu\nx2eAWEO+zAcovVn/HEyNkEL0z/1UAE9IcivhZzyEF2iVv8oHe9+GnVbjMuNwh7f4\nOvfjbmUUfLt2txfxQoxvKjRkEDUUjIX2V7/zXFWdrQMQ8wIDAQABo0IwQDAPBgNV\nHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSbJguKmKm7HbkfHOMaQDPtjheIqzAOBgNV\nHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggEBAFtT/23VCkOlD9R9xl2I45id\nZ+sygrMP9cF4+AVKv7whBe4hCCyyFaG4svajFWHkwa2EpKdADIcJXysb+U1skn3L\nfiuwAQrtQOVOrxrxDewdnpbH1GFkOSP6XynEKjq47YpyUGqsRQR2Cag9V9fwS65G\ntIPBFFAqGVlTsk2u/C9AScitTZ3IIo2MAdsxM1r0vEyb7dfjQ9noHVOLMNiBnnKr\nns649YOT8nLb3s2wUppFTc/nIdjOFmSPQq/Bh6j51eID3bprG3x9oDgzYTm03Vxp\nF3kCOuwdb167E/umgl0HIPyG/m6LrOHCGKL+P5Vm02mKAAYsVjc0ubYx3g/2RDk=\n-----END CERTIFICATE-----\n" + }, + { + "GUID": "{ac861420-3342-4537-a20e-3c2ec0809b7a}", + "TrustBits": [ ], + "Type": "Authority", + "X509": "-----BEGIN CERTIFICATE-----\nMIIDizCCAnOgAwIBAgIBATANBgkqhkiG9w0BAQsFADBjMQswCQYDVQQGEwJVUzET\nMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4G\nA1UECgwHVGVzdCBDQTEVMBMGA1UEAwwMVGVzdCBSb290IENBMB4XDTE3MDYwNTE3\nMTA0NVoXDTI3MDYwMzE3MTA0NVowazELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNh\nbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxEDAOBgNVBAoMB1Rlc3Qg\nQ0ExHTAbBgNVBAMMFFRlc3QgSW50ZXJtZWRpYXRlIENBMIIBIjANBgkqhkiG9w0B\nAQEFAAOCAQ8AMIIBCgKCAQEAnem95D1KL/vC+eYiKkIVRhyMj0dM6cVXlR9mcJMi\n8JTDu7Vb76RvyMeJlXW6DDa/TmupNUcIQ54pauLD+wO3H7bhUWvtexnH+c473GXp\nZseDlMTRTu7tZEuB8RrqWmQYG2pOk9ATbJBgytJOtyQW+LIIWJ2NpzNFFTSBrS0t\nnGDv+SuY/nnTjSxI2xKR9C76v/UmwYIFgN1MqHC/p7wQNHc520cED+1EsmVGIiCI\nWSgPxwyitJGloqrKBZ+Km26jy9Sk6CR1nSCBIltfdz7J8R6u64ozjCdbHr5tIRtC\ncpXjnhMDdadY1L5oEv5jjksRejTno2vdc64+GZrskYtzrwIDAQABo0IwQDAPBgNV\nHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQXXEXz0KwcEEyLQ0QgxN2TxcUZOzAOBgNV\nHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggEBAD711/2COx40jGai814Y4fGp\ndZ+1k+cKjs8KM+1Jzc7Oyl+jHWR204QW/p2IrPTR+DYrIIBSCu/gD2QnVTWje8aK\nfKXEKRex+tKJXRNruAPL1xLWziTwr0gXA1SZr+nL/UREGCNhkPa9VWUGwzaYjep9\nD3nvtrsiKAOm7NnUG0esLCXe7xoCaUwYuylI9J3hUkJkbIhGaIaD/ST1fQXXGn4i\nvEl1nIpN6POi65uDcKfW3S8FLaq+1+57jnVEO9rfhWG/6TsTQE6LUgjZ5IxU2kHb\neywFXpkGDQKMjhmOVbA6MxgwA6ftSuT4WMwSuK/WZlUp7AEfku09TcNxO+AvcJA=\n-----END CERTIFICATE-----\n" + } + ], + "Type": "UnencryptedConfiguration" +}
diff --git a/chromeos/test/data/network/root-ca-cert.onc b/chromeos/test/data/network/root-ca-cert.onc index 9a364ba..7217453 100644 --- a/chromeos/test/data/network/root-ca-cert.onc +++ b/chromeos/test/data/network/root-ca-cert.onc
@@ -6,7 +6,7 @@ "Web" ], "Type": "Authority", - "X509": "-----BEGIN CERTIFICATE-----\nMIIC8zCCAdugAwIBAgIJALF9qhLor0+aMA0GCSqGSIb3DQEBBQUAMBcxFTATBgNV\nBAMMDFRlc3QgUm9vdCBDQTAeFw0xNDA4MTQwMzA1MjlaFw0yNDA4MTEwMzA1Mjla\nMBcxFTATBgNVBAMMDFRlc3QgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP\nADCCAQoCggEBALZJQeNCAVGofzx6cdP7zZE1F4QajvY2x9FwHfqG8267dm/oMi43\n/TiSPWjkin1CMxRGG9wE9pFuVEDECgn97C1i4l7huiycwbFgTNrH+CJcgiBlQh5W\nd3VP65AsSupXDiKNbJWsEerM1+72cA0J3aY1YV3Jdm2w8h6/MIbYd1I2lZcO0UbF\n7YE9G7DyYZU8wUA4719dumGf7yucn4WJdHBj1XboNX7OAeHzERGQHA31/Y3OEGyt\nfFUaIW/XLfR4FeovOL2RnjwdB0b1Q8GCi68SU2UZimlpZgay2gv6KgChKhWESfEB\nv5swBtAVoB+dUZFH4VNf717swmF5whSfxOMCAwEAAaNCMEAwDwYDVR0TAQH/BAUw\nAwEB/zAdBgNVHQ4EFgQUvPcw0TzA8nn675/JbFyT84poq4MwDgYDVR0PAQH/BAQD\nAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBXByn7f+j/sObYWGrDkKE4HLTzaLHs6Ikj\nJNeo8iHDYOSkSVwAv9/HgniAKxj3rd3QYl6nsMzwqrTOcBJZZWd2BQAYmv/EKhfj\n8VXYvlxe68rLU4cQ1QkyNqdeQfRT2n5WYNJ+TpqlCF9ddennMMsi6e8ZSYOlI6H4\nYEzlNtU5eBjxXr/OqgtTgSx4qQpr2xMQIRR/G3A9iRpAigYsXVAZYvnHRYnyPWYF\nPX11W1UegEJyoZp8bQp09u6mIWw6mPt3gl/ya1bm3ZuOUPDGrv3qpgUHqSYGVrOy\n2bI3oCE+eQYfuVG+9LFJTZC1M+UOx15bQMVqBNFDepRqpE9h/ILg\n-----END CERTIFICATE-----" + "X509": "-----BEGIN CERTIFICATE-----\nMIIDizCCAnOgAwIBAgIJAJRTRMx4iMvZMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNV\nBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBW\naWV3MRAwDgYDVQQKDAdUZXN0IENBMRUwEwYDVQQDDAxUZXN0IFJvb3QgQ0EwHhcN\nMTcwNjA1MTcxMDQ0WhcNMjcwNjAzMTcxMDQ0WjBjMQswCQYDVQQGEwJVUzETMBEG\nA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4GA1UE\nCgwHVGVzdCBDQTEVMBMGA1UEAwwMVGVzdCBSb290IENBMIIBIjANBgkqhkiG9w0B\nAQEFAAOCAQ8AMIIBCgKCAQEAxoEfknO2WIXZjay3IP3Hv0Cy6vrlC1IBj5rB63qA\nwfOJpD7VG2HMtc+AsRrbuyXgGL+SaSZQzec//w08tB8UEqtnN94HA2wSdII2rMPU\n02Sfke1b9ql6pJyY6GVslOHLVXOu+B1QsHjldP+xNyzLGT2kjOd2ToZcP9+z7UUj\nT1SbM8aJXhMd3X1ZpQc0KIYnH/qeU08qtkKtNxJi9XI2tgISQET+x56ViUNRXrRu\nx2eAWEO+zAcovVn/HEyNkEL0z/1UAE9IcivhZzyEF2iVv8oHe9+GnVbjMuNwh7f4\nOvfjbmUUfLt2txfxQoxvKjRkEDUUjIX2V7/zXFWdrQMQ8wIDAQABo0IwQDAPBgNV\nHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSbJguKmKm7HbkfHOMaQDPtjheIqzAOBgNV\nHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggEBAFtT/23VCkOlD9R9xl2I45id\nZ+sygrMP9cF4+AVKv7whBe4hCCyyFaG4svajFWHkwa2EpKdADIcJXysb+U1skn3L\nfiuwAQrtQOVOrxrxDewdnpbH1GFkOSP6XynEKjq47YpyUGqsRQR2Cag9V9fwS65G\ntIPBFFAqGVlTsk2u/C9AScitTZ3IIo2MAdsxM1r0vEyb7dfjQ9noHVOLMNiBnnKr\nns649YOT8nLb3s2wUppFTc/nIdjOFmSPQq/Bh6j51eID3bprG3x9oDgzYTm03Vxp\nF3kCOuwdb167E/umgl0HIPyG/m6LrOHCGKL+P5Vm02mKAAYsVjc0ubYx3g/2RDk=\n-----END CERTIFICATE-----\n" } ], "Type": "UnencryptedConfiguration"
diff --git a/chromeos/test/data/network/root_ca_cert.pem b/chromeos/test/data/network/root_ca_cert.pem index 6957b749..dac64712 100644 --- a/chromeos/test/data/network/root_ca_cert.pem +++ b/chromeos/test/data/network/root_ca_cert.pem
@@ -1,19 +1,21 @@ -----BEGIN CERTIFICATE----- -MIIC8zCCAdugAwIBAgIJALF9qhLor0+aMA0GCSqGSIb3DQEBBQUAMBcxFTATBgNV -BAMMDFRlc3QgUm9vdCBDQTAeFw0xNDA4MTQwMzA1MjlaFw0yNDA4MTEwMzA1Mjla -MBcxFTATBgNVBAMMDFRlc3QgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP -ADCCAQoCggEBALZJQeNCAVGofzx6cdP7zZE1F4QajvY2x9FwHfqG8267dm/oMi43 -/TiSPWjkin1CMxRGG9wE9pFuVEDECgn97C1i4l7huiycwbFgTNrH+CJcgiBlQh5W -d3VP65AsSupXDiKNbJWsEerM1+72cA0J3aY1YV3Jdm2w8h6/MIbYd1I2lZcO0UbF -7YE9G7DyYZU8wUA4719dumGf7yucn4WJdHBj1XboNX7OAeHzERGQHA31/Y3OEGyt -fFUaIW/XLfR4FeovOL2RnjwdB0b1Q8GCi68SU2UZimlpZgay2gv6KgChKhWESfEB -v5swBtAVoB+dUZFH4VNf717swmF5whSfxOMCAwEAAaNCMEAwDwYDVR0TAQH/BAUw -AwEB/zAdBgNVHQ4EFgQUvPcw0TzA8nn675/JbFyT84poq4MwDgYDVR0PAQH/BAQD -AgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBXByn7f+j/sObYWGrDkKE4HLTzaLHs6Ikj -JNeo8iHDYOSkSVwAv9/HgniAKxj3rd3QYl6nsMzwqrTOcBJZZWd2BQAYmv/EKhfj -8VXYvlxe68rLU4cQ1QkyNqdeQfRT2n5WYNJ+TpqlCF9ddennMMsi6e8ZSYOlI6H4 -YEzlNtU5eBjxXr/OqgtTgSx4qQpr2xMQIRR/G3A9iRpAigYsXVAZYvnHRYnyPWYF -PX11W1UegEJyoZp8bQp09u6mIWw6mPt3gl/ya1bm3ZuOUPDGrv3qpgUHqSYGVrOy -2bI3oCE+eQYfuVG+9LFJTZC1M+UOx15bQMVqBNFDepRqpE9h/ILg +MIIDizCCAnOgAwIBAgIJAJRTRMx4iMvZMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNV +BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBW +aWV3MRAwDgYDVQQKDAdUZXN0IENBMRUwEwYDVQQDDAxUZXN0IFJvb3QgQ0EwHhcN +MTcwNjA1MTcxMDQ0WhcNMjcwNjAzMTcxMDQ0WjBjMQswCQYDVQQGEwJVUzETMBEG +A1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4GA1UE +CgwHVGVzdCBDQTEVMBMGA1UEAwwMVGVzdCBSb290IENBMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAxoEfknO2WIXZjay3IP3Hv0Cy6vrlC1IBj5rB63qA +wfOJpD7VG2HMtc+AsRrbuyXgGL+SaSZQzec//w08tB8UEqtnN94HA2wSdII2rMPU +02Sfke1b9ql6pJyY6GVslOHLVXOu+B1QsHjldP+xNyzLGT2kjOd2ToZcP9+z7UUj +T1SbM8aJXhMd3X1ZpQc0KIYnH/qeU08qtkKtNxJi9XI2tgISQET+x56ViUNRXrRu +x2eAWEO+zAcovVn/HEyNkEL0z/1UAE9IcivhZzyEF2iVv8oHe9+GnVbjMuNwh7f4 +OvfjbmUUfLt2txfxQoxvKjRkEDUUjIX2V7/zXFWdrQMQ8wIDAQABo0IwQDAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBSbJguKmKm7HbkfHOMaQDPtjheIqzAOBgNV +HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggEBAFtT/23VCkOlD9R9xl2I45id +Z+sygrMP9cF4+AVKv7whBe4hCCyyFaG4svajFWHkwa2EpKdADIcJXysb+U1skn3L +fiuwAQrtQOVOrxrxDewdnpbH1GFkOSP6XynEKjq47YpyUGqsRQR2Cag9V9fwS65G +tIPBFFAqGVlTsk2u/C9AScitTZ3IIo2MAdsxM1r0vEyb7dfjQ9noHVOLMNiBnnKr +ns649YOT8nLb3s2wUppFTc/nIdjOFmSPQq/Bh6j51eID3bprG3x9oDgzYTm03Vxp +F3kCOuwdb167E/umgl0HIPyG/m6LrOHCGKL+P5Vm02mKAAYsVjc0ubYx3g/2RDk= -----END CERTIFICATE----- -
diff --git a/chromeos/test/data/network/setup-certificates.sh b/chromeos/test/data/network/setup-certificates.sh new file mode 100755 index 0000000..f849732a --- /dev/null +++ b/chromeos/test/data/network/setup-certificates.sh
@@ -0,0 +1,70 @@ +#!/bin/bash + +# Copyright 2018 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +INPUT_DIR=${1?first param missing - input directory} +OUTPUT_DIR=${2?second param missing - output directory} + +# This script grabs certain certificates from ${INPUT_DIR} and places them under +# ${OUTPUT_DIR}. It uses openssl's x509 command to only take the certificate +# sections (and not e.g. private keys). +# Additionally, this script creates ONC files which contain some of the +# certificates to be used by tests. + +openssl x509 -in "${INPUT_DIR}/root_ca_cert.pem" -inform PEM \ + > "${OUTPUT_DIR}/root_ca_cert.pem" +openssl x509 -in "${INPUT_DIR}/ok_cert.pem" -inform PEM \ + > "${OUTPUT_DIR}/ok_cert.pem" +openssl x509 -in "${INPUT_DIR}/intermediate_ca_cert.pem" -inform PEM \ + > "${OUTPUT_DIR}/intermediate_ca_cert.pem" +openssl x509 -in "${INPUT_DIR}/ok_cert_by_intermediate.pem" -inform PEM \ + > "${OUTPUT_DIR}/ok_cert_by_intermediate.pem" + +# Read the root CA cert and interemdiate CA cert PEM files and replace newlines +# with \n literals. This is needed because the ONC JSON does not support +# multi-line strings. Note that replacement is done in two steps, using ',' as +# intermediate character. PEM files will not contain commas. +ROOT_CA_CERT_CONTENTS=$(cat root_ca_cert.pem \ + | tr '\n' ',' | sed 's/,/\\n/g') +INTERMEDIATE_CA_CERT_CONTENTS=$(cat intermediate_ca_cert.pem \ + | tr '\n' ',' | sed 's/,/\\n/g') + +cat > "${OUTPUT_DIR}/root-ca-cert.onc" << EOL +{ + "Certificates": [ + { + "GUID": "{b3aae353-cfa9-4093-9aff-9f8ee2bf8c29}", + "TrustBits": [ + "Web" + ], + "Type": "Authority", + "X509": "${ROOT_CA_CERT_CONTENTS}" + } + ], + "Type": "UnencryptedConfiguration" +} +EOL + +cat > "${OUTPUT_DIR}/root-and-intermediate-ca-certs.onc" << EOL +{ + "Certificates": [ + { + "GUID": "{b3aae353-cfa9-4093-9aff-9f8ee2bf8c29}", + "TrustBits": [ + "Web" + ], + "Type": "Authority", + "X509": "${ROOT_CA_CERT_CONTENTS}" + }, + { + "GUID": "{ac861420-3342-4537-a20e-3c2ec0809b7a}", + "TrustBits": [ ], + "Type": "Authority", + "X509": "${INTERMEDIATE_CA_CERT_CONTENTS}" + } + ], + "Type": "UnencryptedConfiguration" +} +EOL
diff --git a/components/browsing_data/core/BUILD.gn b/components/browsing_data/core/BUILD.gn index 0d22030..35db894c 100644 --- a/components/browsing_data/core/BUILD.gn +++ b/components/browsing_data/core/BUILD.gn
@@ -23,8 +23,6 @@ "counters/passwords_counter.h", "counters/sync_tracker.cc", "counters/sync_tracker.h", - "features.cc", - "features.h", "history_notice_utils.cc", "history_notice_utils.h", "pref_names.cc",
diff --git a/components/browsing_data/core/features.cc b/components/browsing_data/core/features.cc deleted file mode 100644 index 054b27e..0000000 --- a/components/browsing_data/core/features.cc +++ /dev/null
@@ -1,14 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/browsing_data/core/features.h" - -namespace browsing_data { -namespace features { - -const base::Feature kRemoveNavigationHistory{"RemoveNavigationHistory", - base::FEATURE_ENABLED_BY_DEFAULT}; - -} // namespace features -} // namespace browsing_data
diff --git a/components/browsing_data/core/features.h b/components/browsing_data/core/features.h deleted file mode 100644 index 5ec27f3..0000000 --- a/components/browsing_data/core/features.h +++ /dev/null
@@ -1,19 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_BROWSING_DATA_FEATURES_H_ -#define COMPONENTS_BROWSING_DATA_FEATURES_H_ - -#include "base/feature_list.h" - -namespace browsing_data { -namespace features { - -// Enable propagation of history deletions to navigation history. -extern const base::Feature kRemoveNavigationHistory; - -} // namespace features -} // namespace browsing_data - -#endif // COMPONENTS_BROWSING_DATA_FEATURES_H_
diff --git a/components/error_page/common/localized_error.cc b/components/error_page/common/localized_error.cc index 8253826..8c60334 100644 --- a/components/error_page/common/localized_error.cc +++ b/components/error_page/common/localized_error.cc
@@ -1071,23 +1071,28 @@ !is_incognito && failed_url.is_valid() && failed_url.SchemeIsHTTPOrHTTPS() && IsOfflineError(error_domain, error_code)) { - error_strings->SetPath( - {"downloadButton", "msg"}, - base::Value(l10n_util::GetStringUTF16(IDS_ERRORPAGES_BUTTON_DOWNLOAD))); - error_strings->SetPath({"downloadButton", "disabledMsg"}, - base::Value(l10n_util::GetStringUTF16( - IDS_ERRORPAGES_BUTTON_DOWNLOADING))); + if (!auto_fetch_feature_enabled) { + error_strings->SetPath({"downloadButton", "msg"}, + base::Value(l10n_util::GetStringUTF16( + IDS_ERRORPAGES_BUTTON_DOWNLOAD))); + error_strings->SetPath({"downloadButton", "disabledMsg"}, + base::Value(l10n_util::GetStringUTF16( + IDS_ERRORPAGES_BUTTON_DOWNLOADING))); + } else { + error_strings->SetString("attemptAutoFetch", "true"); + error_strings->SetPath({"savePageLater", "savePageMsg"}, + base::Value(l10n_util::GetStringUTF16( + IDS_ERRORPAGES_SAVE_PAGE_BUTTON))); + error_strings->SetPath({"savePageLater", "cancelMsg"}, + base::Value(l10n_util::GetStringUTF16( + IDS_ERRORPAGES_CANCEL_SAVE_PAGE_BUTTON))); + } } error_strings->SetString( "closeDescriptionPopup", l10n_util::GetStringUTF16(IDS_ERRORPAGES_SUGGESTION_CLOSE_POPUP_BUTTON)); - if (auto_fetch_feature_enabled && IsOfflineError(error_domain, error_code) && - !is_incognito) { - error_strings->SetString("attemptAutoFetch", "true"); - } - if (IsOfflineError(error_domain, error_code) && !is_incognito) { switch (offline_content_feature_state) { case OfflineContentOnNetErrorFeatureState::kDisabled:
diff --git a/components/error_page_strings.grdp b/components/error_page_strings.grdp index e83eb86..4e347059 100644 --- a/components/error_page_strings.grdp +++ b/components/error_page_strings.grdp
@@ -48,6 +48,12 @@ <message name="IDS_ERRORPAGES_OFFLINE_CONTENT_SUMMARY_BUTTON" desc="Label for the button that will take the user to the downloads home, attached to the offline content summary card shown in an error page"> Take me there now </message> + <message name="IDS_ERRORPAGES_SAVE_PAGE_BUTTON" desc="Label for the button that will save the page for later. The saved page is not retained in Downloads, unlike with the DOWNLOAD button."> + Save page for later + </message> + <message name="IDS_ERRORPAGES_CANCEL_SAVE_PAGE_BUTTON" desc="Label for the button that will cancel the request to save the page for later. 'Cancel' is colored blue with the 'a' tag."> + Chrome will let you know when this page is ready. <a>Cancel</a> + </message> </if> <message name="IDS_ERRORPAGES_SUGGESTION_VISIT_GOOGLE_CACHE" desc="When a page fails to load, sometimes we viewing a version of the page cached on Google's servers.">
diff --git a/components/exo/fullscreen_shell_surface.cc b/components/exo/fullscreen_shell_surface.cc index 5859522..31ee9a6 100644 --- a/components/exo/fullscreen_shell_surface.cc +++ b/components/exo/fullscreen_shell_surface.cc
@@ -5,7 +5,7 @@ #include "components/exo/fullscreen_shell_surface.h" #include "base/trace_event/trace_event.h" -#include "base/trace_event/trace_event_argument.h" +#include "base/trace_event/traced_value.h" #include "components/exo/surface.h" #include "components/exo/wm_helper.h" #include "ui/aura/window.h"
diff --git a/components/exo/wayland/BUILD.gn b/components/exo/wayland/BUILD.gn index 2629757c..d31d603 100644 --- a/components/exo/wayland/BUILD.gn +++ b/components/exo/wayland/BUILD.gn
@@ -63,6 +63,8 @@ "zcr_stylus_tools.h", "zwp_input_timestamps_manager.cc", "zwp_input_timestamps_manager.h", + "zwp_pointer_gestures.cc", + "zwp_pointer_gestures.h", "zwp_text_input_manager.cc", "zwp_text_input_manager.h", "zxdg_shell.cc",
diff --git a/components/exo/wayland/server.cc b/components/exo/wayland/server.cc index 93ee212..9f2988e4 100644 --- a/components/exo/wayland/server.cc +++ b/components/exo/wayland/server.cc
@@ -109,6 +109,7 @@ #include "components/exo/wayland/zcr_remote_shell.h" #include "components/exo/wayland/zcr_stylus_tools.h" #include "components/exo/wayland/zwp_input_timestamps_manager.h" +#include "components/exo/wayland/zwp_pointer_gestures.h" #include "components/exo/wayland/zwp_text_input_manager.h" #include "components/exo/wayland/zxdg_shell.h" #include "components/exo/wm_helper.h" @@ -2207,95 +2208,6 @@ nullptr); } -//////////////////////////////////////////////////////////////////////////////// -// pointer_gesture_swipe_v1 interface: - -void pointer_gestures_get_swipe_gesture(wl_client* client, - wl_resource* resource, - uint32_t id, - wl_resource* pointer_resource) { - NOTIMPLEMENTED(); -} - -//////////////////////////////////////////////////////////////////////////////// -// pointer_gesture_pinch_v1 interface: - -class WaylandPointerGesturePinchDelegate : public PointerGesturePinchDelegate { - public: - WaylandPointerGesturePinchDelegate(wl_resource* resource, Pointer* pointer) - : resource_(resource), pointer_(pointer) { - pointer_->SetGesturePinchDelegate(this); - } - - ~WaylandPointerGesturePinchDelegate() override { - if (pointer_) - pointer_->SetGesturePinchDelegate(nullptr); - } - void OnPointerDestroying(Pointer* pointer) override { pointer_ = nullptr; } - void OnPointerPinchBegin(uint32_t unique_touch_event_id, - base::TimeTicks time_stamp, - Surface* surface) override { - wl_resource* surface_resource = GetSurfaceResource(surface); - DCHECK(surface_resource); - zwp_pointer_gesture_pinch_v1_send_begin(resource_, unique_touch_event_id, - TimeTicksToMilliseconds(time_stamp), - surface_resource, 2); - } - void OnPointerPinchUpdate(base::TimeTicks time_stamp, float scale) override { - zwp_pointer_gesture_pinch_v1_send_update( - resource_, TimeTicksToMilliseconds(time_stamp), 0, 0, - wl_fixed_from_double(scale), 0); - } - void OnPointerPinchEnd(uint32_t unique_touch_event_id, - base::TimeTicks time_stamp) override { - zwp_pointer_gesture_pinch_v1_send_end(resource_, unique_touch_event_id, - TimeTicksToMilliseconds(time_stamp), - 0); - } - - private: - wl_resource* const resource_; - Pointer* pointer_; - - DISALLOW_COPY_AND_ASSIGN(WaylandPointerGesturePinchDelegate); -}; - -void pointer_gesture_pinch_destroy(wl_client* client, wl_resource* resource) { - wl_resource_destroy(resource); -} - -const struct zwp_pointer_gesture_pinch_v1_interface - pointer_gesture_pinch_implementation = {pointer_gesture_pinch_destroy}; - -void pointer_gestures_get_pinch_gesture(wl_client* client, - wl_resource* resource, - uint32_t id, - wl_resource* pointer_resource) { - Pointer* pointer = GetUserDataAs<Pointer>(pointer_resource); - wl_resource* pointer_gesture_pinch_resource = wl_resource_create( - client, &zwp_pointer_gesture_pinch_v1_interface, 1, id); - SetImplementation(pointer_gesture_pinch_resource, - &pointer_gesture_pinch_implementation, - std::make_unique<WaylandPointerGesturePinchDelegate>( - pointer_gesture_pinch_resource, pointer)); -} - -//////////////////////////////////////////////////////////////////////////////// -// pointer_gestures_v1 interface: - -const struct zwp_pointer_gestures_v1_interface pointer_gestures_implementation = - {pointer_gestures_get_swipe_gesture, pointer_gestures_get_pinch_gesture}; - -void bind_pointer_gestures(wl_client* client, - void* data, - uint32_t version, - uint32_t id) { - wl_resource* resource = wl_resource_create( - client, &zwp_pointer_gestures_v1_interface, version, id); - wl_resource_set_implementation(resource, &pointer_gestures_implementation, - data, nullptr); -} - } // namespace ////////////////////////////////////////////////////////////////////////////////
diff --git a/components/exo/wayland/zcr_remote_shell.cc b/components/exo/wayland/zcr_remote_shell.cc index bd7076e..2b33ca0 100644 --- a/components/exo/wayland/zcr_remote_shell.cc +++ b/components/exo/wayland/zcr_remote_shell.cc
@@ -664,7 +664,7 @@ for (const auto& display : screen->GetAllDisplays()) { const gfx::Rect& bounds = display.bounds(); - const gfx::Insets& insets = display.GetWorkAreaInsets(); + const gfx::Insets& insets = GetAdjustedInsets(display); double device_scale_factor = display.device_scale_factor();
diff --git a/components/exo/wayland/zwp_pointer_gestures.cc b/components/exo/wayland/zwp_pointer_gestures.cc new file mode 100644 index 0000000..4548a13 --- /dev/null +++ b/components/exo/wayland/zwp_pointer_gestures.cc
@@ -0,0 +1,113 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/exo/wayland/zwp_pointer_gestures.h" + +#include <pointer-gestures-unstable-v1-server-protocol.h> +#include <wayland-server-core.h> +#include <wayland-server-protocol-core.h> + +#include "components/exo/pointer.h" +#include "components/exo/pointer_gesture_pinch_delegate.h" +#include "components/exo/surface.h" +#include "components/exo/wayland/server_util.h" + +namespace exo { +namespace wayland { + +namespace { + +//////////////////////////////////////////////////////////////////////////////// +// pointer_gesture_swipe_v1 interface: + +void pointer_gestures_get_swipe_gesture(wl_client* client, + wl_resource* resource, + uint32_t id, + wl_resource* pointer_resource) { + NOTIMPLEMENTED(); +} + +//////////////////////////////////////////////////////////////////////////////// +// pointer_gesture_pinch_v1 interface: + +class WaylandPointerGesturePinchDelegate : public PointerGesturePinchDelegate { + public: + WaylandPointerGesturePinchDelegate(wl_resource* resource, Pointer* pointer) + : resource_(resource), pointer_(pointer) { + pointer_->SetGesturePinchDelegate(this); + } + + ~WaylandPointerGesturePinchDelegate() override { + if (pointer_) + pointer_->SetGesturePinchDelegate(nullptr); + } + void OnPointerDestroying(Pointer* pointer) override { pointer_ = nullptr; } + void OnPointerPinchBegin(uint32_t unique_touch_event_id, + base::TimeTicks time_stamp, + Surface* surface) override { + wl_resource* surface_resource = GetSurfaceResource(surface); + DCHECK(surface_resource); + zwp_pointer_gesture_pinch_v1_send_begin(resource_, unique_touch_event_id, + TimeTicksToMilliseconds(time_stamp), + surface_resource, 2); + } + void OnPointerPinchUpdate(base::TimeTicks time_stamp, float scale) override { + zwp_pointer_gesture_pinch_v1_send_update( + resource_, TimeTicksToMilliseconds(time_stamp), 0, 0, + wl_fixed_from_double(scale), 0); + } + void OnPointerPinchEnd(uint32_t unique_touch_event_id, + base::TimeTicks time_stamp) override { + zwp_pointer_gesture_pinch_v1_send_end(resource_, unique_touch_event_id, + TimeTicksToMilliseconds(time_stamp), + 0); + } + + private: + wl_resource* const resource_; + Pointer* pointer_; + + DISALLOW_COPY_AND_ASSIGN(WaylandPointerGesturePinchDelegate); +}; + +void pointer_gesture_pinch_destroy(wl_client* client, wl_resource* resource) { + wl_resource_destroy(resource); +} + +const struct zwp_pointer_gesture_pinch_v1_interface + pointer_gesture_pinch_implementation = {pointer_gesture_pinch_destroy}; + +void pointer_gestures_get_pinch_gesture(wl_client* client, + wl_resource* resource, + uint32_t id, + wl_resource* pointer_resource) { + Pointer* pointer = GetUserDataAs<Pointer>(pointer_resource); + wl_resource* pointer_gesture_pinch_resource = wl_resource_create( + client, &zwp_pointer_gesture_pinch_v1_interface, 1, id); + SetImplementation(pointer_gesture_pinch_resource, + &pointer_gesture_pinch_implementation, + std::make_unique<WaylandPointerGesturePinchDelegate>( + pointer_gesture_pinch_resource, pointer)); +} + +//////////////////////////////////////////////////////////////////////////////// +// pointer_gestures_v1 interface: + +const struct zwp_pointer_gestures_v1_interface pointer_gestures_implementation = + {pointer_gestures_get_swipe_gesture, pointer_gestures_get_pinch_gesture}; + +} // namespace + +void bind_pointer_gestures(wl_client* client, + void* data, + uint32_t version, + uint32_t id) { + wl_resource* resource = wl_resource_create( + client, &zwp_pointer_gestures_v1_interface, version, id); + wl_resource_set_implementation(resource, &pointer_gestures_implementation, + data, nullptr); +} + +} // namespace wayland +} // namespace exo
diff --git a/components/exo/wayland/zwp_pointer_gestures.h b/components/exo/wayland/zwp_pointer_gestures.h new file mode 100644 index 0000000..f593fc1 --- /dev/null +++ b/components/exo/wayland/zwp_pointer_gestures.h
@@ -0,0 +1,23 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_EXO_WAYLAND_ZWP_POINTER_GESTURES_H_ +#define COMPONENTS_EXO_WAYLAND_ZWP_POINTER_GESTURES_H_ + +#include <stdint.h> + +struct wl_client; + +namespace exo { +namespace wayland { + +void bind_pointer_gestures(wl_client* client, + void* data, + uint32_t version, + uint32_t id); + +} // namespace wayland +} // namespace exo + +#endif // COMPONENTS_EXO_WAYLAND_ZWP_POINTER_GESTURES_H_
diff --git a/components/gwp_asan/common/guarded_page_allocator.cc b/components/gwp_asan/common/guarded_page_allocator.cc index 379ea59..030142b3 100644 --- a/components/gwp_asan/common/guarded_page_allocator.cc +++ b/components/gwp_asan/common/guarded_page_allocator.cc
@@ -39,16 +39,13 @@ (num_pages_ == kGpaMaxPages) ? ~0ULL : (1ULL << num_pages_) - 1; } - for (size_t i = 0; i < num_pages_; i++) - data_[i].Init(); + AllocateStackTraces(); } GuardedPageAllocator::~GuardedPageAllocator() { if (num_pages_) { UnmapPages(); - - for (size_t i = 0; i < num_pages_; i++) - data_[i].Destroy(); + DeallocateStackTraces(); } } @@ -83,7 +80,7 @@ void* alloc = reinterpret_cast<void*>(free_page + offset); // Initialize slot metadata. - data_[free_slot].RecordAllocation(size, alloc); + RecordAllocationInSlot(free_slot, size, alloc); return alloc; } @@ -104,7 +101,7 @@ } // Record deallocation stack trace/thread id. - data_[slot].RecordDeallocation(); + RecordDeallocationInSlot(slot); FreeSlot(slot); } @@ -218,56 +215,60 @@ return slot; } -void GuardedPageAllocator::SlotMetadata::Init() { +void GuardedPageAllocator::AllocateStackTraces() { // new is not used so that we can explicitly call the constructor when we // want to collect a stack trace. - alloc.stacktrace = - static_cast<StackTrace*>(malloc(sizeof(*alloc.stacktrace))); - CHECK(alloc.stacktrace); - dealloc.stacktrace = - static_cast<StackTrace*>(malloc(sizeof(*dealloc.stacktrace))); - CHECK(dealloc.stacktrace); + for (size_t i = 0; i < num_pages_; i++) { + alloc_traces[i] = + static_cast<StackTrace*>(malloc(sizeof(*alloc_traces[i]))); + CHECK(alloc_traces[i]); + dealloc_traces[i] = + static_cast<StackTrace*>(malloc(sizeof(*dealloc_traces[i]))); + CHECK(dealloc_traces[i]); + } } -void GuardedPageAllocator::SlotMetadata::Destroy() { - CHECK(alloc.stacktrace); - CHECK(dealloc.stacktrace); +void GuardedPageAllocator::DeallocateStackTraces() { + for (size_t i = 0; i < num_pages_; i++) { + DestructStackTrace(i); - Reset(); - - free(alloc.stacktrace); - free(dealloc.stacktrace); + free(alloc_traces[i]); + alloc_traces[i] = nullptr; + free(dealloc_traces[i]); + dealloc_traces[i] = nullptr; + } } -void GuardedPageAllocator::SlotMetadata::Reset() { +void GuardedPageAllocator::DestructStackTrace(size_t slot) { // Destruct previous allocation/deallocation traces. The constructor was only // called if trace_addr is non-null. - if (alloc.trace_addr) - alloc.stacktrace->~StackTrace(); - if (dealloc.trace_addr) - dealloc.stacktrace->~StackTrace(); + if (data_[slot].alloc.trace_addr) + alloc_traces[slot]->~StackTrace(); + if (data_[slot].dealloc.trace_addr) + dealloc_traces[slot]->~StackTrace(); } -void GuardedPageAllocator::SlotMetadata::RecordAllocation(size_t size, - void* ptr) { - Reset(); +void GuardedPageAllocator::RecordAllocationInSlot(size_t slot, + size_t size, + void* ptr) { + data_[slot].alloc_size = size; + data_[slot].alloc_ptr = reinterpret_cast<uintptr_t>(ptr); - alloc_size = size; - alloc_ptr = reinterpret_cast<uintptr_t>(ptr); + data_[slot].alloc.tid = base::PlatformThread::CurrentId(); + new (alloc_traces[slot]) StackTrace(); + data_[slot].alloc.trace_addr = reinterpret_cast<uintptr_t>( + alloc_traces[slot]->Addresses(&data_[slot].alloc.trace_len)); - alloc.tid = base::PlatformThread::CurrentId(); - new (alloc.stacktrace) StackTrace(); - alloc.trace_addr = alloc.stacktrace->Addresses(&alloc.trace_len); - - dealloc.tid = base::kInvalidThreadId; - dealloc.trace_addr = nullptr; - dealloc.trace_len = 0; + data_[slot].dealloc.tid = base::kInvalidThreadId; + data_[slot].dealloc.trace_addr = 0; + data_[slot].dealloc.trace_len = 0; } -void GuardedPageAllocator::SlotMetadata::RecordDeallocation() { - dealloc.tid = base::PlatformThread::CurrentId(); - new (dealloc.stacktrace) StackTrace(); - dealloc.trace_addr = dealloc.stacktrace->Addresses(&dealloc.trace_len); +void GuardedPageAllocator::RecordDeallocationInSlot(size_t slot) { + data_[slot].dealloc.tid = base::PlatformThread::CurrentId(); + new (dealloc_traces[slot]) StackTrace(); + data_[slot].dealloc.trace_addr = reinterpret_cast<uintptr_t>( + dealloc_traces[slot]->Addresses(&data_[slot].dealloc.trace_len)); } } // namespace internal
diff --git a/components/gwp_asan/common/guarded_page_allocator.h b/components/gwp_asan/common/guarded_page_allocator.h index acb9699..155f892 100644 --- a/components/gwp_asan/common/guarded_page_allocator.h +++ b/components/gwp_asan/common/guarded_page_allocator.h
@@ -82,36 +82,12 @@ // (De)allocation thread id or base::kInvalidThreadId if no (de)allocation // occurred. base::PlatformThreadId tid = base::kInvalidThreadId; - - // Pointer to stack trace addresses or null if no (de)allocation occurred. - const void* const* trace_addr = nullptr; - + // Address of stack trace addresses or null if no (de)allocation occurred. + uintptr_t trace_addr = 0; // Stack trace length or 0 if no (de)allocation occurred. size_t trace_len = 0; - - private: - // StackTrace object for this slot, it's allocated in - // SlotMetadata()::Init() and only used internally, trace_addr/len should - // be used by external consumers of the stack trace data. - base::debug::StackTrace* stacktrace = nullptr; - - friend struct SlotMetadata; }; - // Allocate internal data (StackTraces) for this slot. StackTrace objects - // are large so we only allocate them if they're required (instead of - // having them be statically allocated in the SlotMetadata itself.) - void Init(); - - // Frees internal data. May only be called after Init(). - void Destroy(); - - // Update slot metadata on an allocation with the given size and pointer. - void RecordAllocation(size_t size, void* ptr); - - // Update slot metadata on a deallocation. - void RecordDeallocation(); - // Size of the allocation size_t alloc_size = 0; // The allocation address. @@ -119,11 +95,6 @@ AllocationInfo alloc; AllocationInfo dealloc; - - private: - // Call destructors on (de)alloc.stacktrace if constructors for them have - // previously been called. - void Reset(); }; // Does not allocate any memory for the allocator, to finish initializing call @@ -169,6 +140,23 @@ uintptr_t SlotToAddr(size_t slot) const; size_t AddrToSlot(uintptr_t addr) const; + // Allocate num_pages_ stack traces. + void AllocateStackTraces(); + + // Deallocate stack traces. May only be called after AllocateStackTraces(). + void DeallocateStackTraces(); + + // Call the destructor on the allocation and deallocation stack traces for + // a given slot index if the constructors for those stack traces have been + // called. + void DestructStackTrace(size_t slot); + + // Record an allocation or deallocation for a given slot index. This + // encapsulates the logic for updating the stack traces and metadata for a + // given slot. + void RecordAllocationInSlot(size_t slot, size_t size, void* ptr); + void RecordDeallocationInSlot(size_t slot); + // Allocator lock that protects free_pages_. base::Lock lock_; @@ -189,6 +177,12 @@ // Set to true if a double free has occurred. std::atomic<bool> double_free_detected_{false}; + // StackTrace objects for every slot in AllocateStateBase::data_. We avoid + // statically allocating the StackTrace objects because they are large and + // the allocator may be initialized with num_pages_ < kGpaMaxPages. + base::debug::StackTrace* alloc_traces[kGpaMaxPages]; + base::debug::StackTrace* dealloc_traces[kGpaMaxPages]; + // Required for a singleton to access the constructor. friend base::NoDestructor<GuardedPageAllocator>;
diff --git a/components/metrics/BUILD.gn b/components/metrics/BUILD.gn index 53317fc6..2f64965 100644 --- a/components/metrics/BUILD.gn +++ b/components/metrics/BUILD.gn
@@ -431,6 +431,10 @@ sources -= [ "child_call_stack_profile_collector_unittest.cc" ] } + if (is_ios) { + deps += [ "//ios/web/public/test" ] + } + if (!is_ios) { deps += [ "//content/test:test_support" ] }
diff --git a/components/metrics/net/DEPS b/components/metrics/net/DEPS index 58106e5..79a65616 100644 --- a/components/metrics/net/DEPS +++ b/components/metrics/net/DEPS
@@ -5,6 +5,7 @@ "+components/encrypted_messages", "+components/variations", "+content/public/test/test_browser_thread_bundle.h", + "+ios/web/public/test/test_web_thread_bundle.h", "+net", "+services/network/public/cpp", "+services/network/test",
diff --git a/components/metrics/net/network_metrics_provider_unittest.cc b/components/metrics/net/network_metrics_provider_unittest.cc index 835dfa61..ef2e586 100644 --- a/components/metrics/net/network_metrics_provider_unittest.cc +++ b/components/metrics/net/network_metrics_provider_unittest.cc
@@ -22,9 +22,11 @@ #endif // OS_CHROMEOS #if defined(OS_IOS) -#include "base/test/scoped_task_environment.h" +#include "ios/web/public/test/test_web_thread_bundle.h" +using TestThreadBundle = web::TestWebThreadBundle; #else // !defined(OS_IOS) #include "content/public/test/test_browser_thread_bundle.h" +using TestThreadBundle = content::TestBrowserThreadBundle; #endif // defined(OS_IOS) namespace metrics { @@ -33,14 +35,7 @@ public: protected: NetworkMetricsProviderTest() -#if defined(OS_IOS) - : scoped_task_environment_( - base::test::ScopedTaskEnvironment::MainThreadType::IO) -#else // !defined(OS_IOS) - : test_browser_thread_bundle_( - content::TestBrowserThreadBundle::IO_MAINLOOP) -#endif // defined(OS_IOS) - { + : test_thread_bundle_(TestThreadBundle::IO_MAINLOOP) { #if defined(OS_CHROMEOS) chromeos::DBusThreadManager::Initialize(); chromeos::NetworkHandler::Initialize(); @@ -48,11 +43,7 @@ } private: -#if defined(OS_IOS) - base::test::ScopedTaskEnvironment scoped_task_environment_; -#else // !defined(OS_IOS) - content::TestBrowserThreadBundle test_browser_thread_bundle_; -#endif // defined(OS_IOS) + TestThreadBundle test_thread_bundle_; }; // Verifies that the effective connection type is correctly set.
diff --git a/components/neterror/resources/neterror.css b/components/neterror/resources/neterror.css index b0cfdda..c325a21 100644 --- a/components/neterror/resources/neterror.css +++ b/components/neterror/resources/neterror.css
@@ -584,6 +584,23 @@ padding-top: 12px; } +#cancel-save-page-button { + border: 1px solid var(--google-gray-300); + border-radius: 5px; + color: var(--google-gray-700); + padding: 16px; + text-align: center; +} + +#save-page-for-later-button { + display: flex; + justify-content: center; +} + +.hidden#save-page-for-later-button { + display: none; +} + /* Don't allow overflow when in a subframe. */ html[subframe] body { overflow: hidden;
diff --git a/components/neterror/resources/neterror.html b/components/neterror/resources/neterror.html index 25c98f9..019a2892 100644 --- a/components/neterror/resources/neterror.html +++ b/components/neterror/resources/neterror.html
@@ -117,6 +117,17 @@ jsselect="downloadButton" jscontent="msg" jsvalues=".disabledText:disabledMsg"> </button> + <div id="save-page-for-later-button" class="hidden"> + <a class="link-button" onclick="savePageLaterClick()" + jsselect="savePageLater" + jscontent="savePageMsg"> + </a> + </div> + <div id="cancel-save-page-button" class="hidden" + onclick="cancelSavePageClick()" + jsselect="savePageLater" + jsvalues=".innerHTML:cancelMsg"> + </div> </div> <button id="details-button" class="secondary-button text-button small-link" onclick="detailsButtonClick(); toggleHelpBox()" jscontent="details"
diff --git a/components/neterror/resources/neterror.js b/components/neterror/resources/neterror.js index df76f57..e495d10 100644 --- a/components/neterror/resources/neterror.js +++ b/components/neterror/resources/neterror.js
@@ -159,8 +159,24 @@ primaryControlOnLeft = false; // </if> -// TODO(crbug.com/883486): UI not yet implemented. function setAutoFetchState(scheduled, can_schedule) { + document.getElementById('cancel-save-page-button') + .classList.toggle(HIDDEN_CLASS, !scheduled); + document.getElementById('save-page-for-later-button') + .classList.toggle(HIDDEN_CLASS, scheduled || !can_schedule); +} + +function savePageLaterClick() { + errorPageController.savePageForLater(); + // savePageForLater will eventually trigger a call to setAutoFetchState() when + // it completes. +} + +function cancelSavePageClick() { + errorPageController.cancelSavePage(); + // setAutoFetchState is not called in response to cancelSavePage(), so do it + // now. + setAutoFetchState(false, true); } function toggleErrorInformationPopup() { @@ -347,9 +363,12 @@ detailsButton.classList.add('singular'); } + var attemptAutoFetch = loadTimeData.valueExists('attemptAutoFetch') && + loadTimeData.getValue('attemptAutoFetch'); + // Show control buttons. if (reloadButtonVisible || showSavedCopyButtonVisible || - downloadButtonVisible) { + downloadButtonVisible || attemptAutoFetch) { controlButtonDiv.hidden = false; // Set the secondary button state in the cases of two call to actions.
diff --git a/components/password_manager/core/browser/new_password_form_manager.cc b/components/password_manager/core/browser/new_password_form_manager.cc index 49afff9..73bf1f4 100644 --- a/components/password_manager/core/browser/new_password_form_manager.cc +++ b/components/password_manager/core/browser/new_password_form_manager.cc
@@ -280,7 +280,7 @@ metrics_util::PASSWORD_USED); } - // TODO(https://crbug.com/831123): Implement updating Password Form Managers. + client_->UpdateFormManagers(); } void NewPasswordFormManager::Update(const PasswordForm& credentials_to_update) { @@ -308,6 +308,8 @@ FindOtherCredentialsToUpdate(); form_saver_->Update(pending_credentials_, best_matches_, &more_credentials_to_update, nullptr); + + client_->UpdateFormManagers(); } void NewPasswordFormManager::UpdateUsername(
diff --git a/components/password_manager/core/browser/new_password_form_manager_unittest.cc b/components/password_manager/core/browser/new_password_form_manager_unittest.cc index d767bf94..82bb64d6 100644 --- a/components/password_manager/core/browser/new_password_form_manager_unittest.cc +++ b/components/password_manager/core/browser/new_password_form_manager_unittest.cc
@@ -56,6 +56,14 @@ MOCK_METHOD1(AllowPasswordGenerationForForm, void(const PasswordForm&)); }; +class MockPasswordManagerClient : public StubPasswordManagerClient { + public: + MockPasswordManagerClient() = default; + ~MockPasswordManagerClient() override = default; + + MOCK_METHOD0(UpdateFormManagers, void()); +}; + void CheckPendingCredentials(const PasswordForm& expected, const PasswordForm& actual) { EXPECT_EQ(expected.signon_realm, actual.signon_realm); @@ -279,7 +287,7 @@ PasswordForm blacklisted_match_; PasswordForm parsed_observed_form_; PasswordForm parsed_submitted_form_; - StubPasswordManagerClient client_; + MockPasswordManagerClient client_; MockPasswordManagerDriver driver_; scoped_refptr<TestMockTimeTaskRunner> task_runner_; // Define |fetcher_| before |form_manager_|, because the former needs to @@ -715,6 +723,7 @@ std::map<base::string16, const PasswordForm*> best_matches; EXPECT_CALL(form_saver, Save(_, _)) .WillOnce(DoAll(SaveArg<0>(&saved_form), SaveArg<1>(&best_matches))); + EXPECT_CALL(client_, UpdateFormManagers()); form_manager_->Save(); @@ -1364,6 +1373,7 @@ EXPECT_CALL(form_saver, Update(_, _, _, nullptr)) .WillOnce(DoAll(SaveArg<0>(&updated_form), SaveArg<1>(&best_matches), SaveArgPointee<2>(&credentials_to_update))); + EXPECT_CALL(client_, UpdateFormManagers()); form_manager_->Update(saved_match_);
diff --git a/components/password_manager/core/browser/password_manager.cc b/components/password_manager/core/browser/password_manager.cc index 208087a..6f838eb 100644 --- a/components/password_manager/core/browser/password_manager.cc +++ b/components/password_manager/core/browser/password_manager.cc
@@ -563,13 +563,11 @@ void PasswordManager::UpdateFormManagers() { std::vector<PasswordFormManagerInterface*> form_managers; - if (base::FeatureList::IsEnabled(features::kNewPasswordFormParsing)) { - for (const auto& form_manager : form_managers_) - form_managers.push_back(form_manager.get()); - } else { - for (const auto& form_manager : pending_login_managers_) - form_managers.push_back(form_manager.get()); - } + for (const auto& form_manager : form_managers_) + form_managers.push_back(form_manager.get()); + + for (const auto& form_manager : pending_login_managers_) + form_managers.push_back(form_manager.get()); // Get the fetchers and all the drivers. std::vector<FormFetcher*> fetchers;
diff --git a/components/password_manager/core/browser/password_manager_unittest.cc b/components/password_manager/core/browser/password_manager_unittest.cc index dcdbec8..1e1f8133 100644 --- a/components/password_manager/core/browser/password_manager_unittest.cc +++ b/components/password_manager/core/browser/password_manager_unittest.cc
@@ -1979,25 +1979,30 @@ } TEST_F(PasswordManagerTest, UpdateFormManagers) { - // Seeing some forms should result in creating PasswordFormManagers and - // querying PasswordStore. Calling UpdateFormManagers should result in - // querying the store again. - EXPECT_CALL(*store_, GetLogins(_, _)); + for (bool new_parsing_for_saving : {false, true}) { + SCOPED_TRACE(testing::Message() + << "new_parsing_for_saving = " << new_parsing_for_saving); + base::test::ScopedFeatureList scoped_feature_list; + if (new_parsing_for_saving) + TurnOnNewParsingForSaving(&scoped_feature_list); - PasswordForm form; - std::vector<PasswordForm> observed; - observed.push_back(form); - manager()->OnPasswordFormsParsed(&driver_, observed); - ASSERT_EQ(1u, manager()->pending_login_managers().size()); - PasswordFormManager* form_manager = - manager()->pending_login_managers().front().get(); + // Seeing a form should result in creating PasswordFormManager and + // NewPasswordFormManager and querying PasswordStore. Calling + // UpdateFormManagers should result in querying the store again. + EXPECT_CALL(*store_, GetLogins(_, _)) + .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms())); - // The first GetLogins should have fired, but to unblock the second, we need - // to first send a response from the store (to be ignored). - static_cast<FormFetcherImpl*>(form_manager->GetFormFetcher()) - ->OnGetPasswordStoreResults(std::vector<std::unique_ptr<PasswordForm>>()); - EXPECT_CALL(*store_, GetLogins(_, _)); - manager()->UpdateFormManagers(); + manager()->OnPasswordFormsParsed(&driver_, {PasswordForm()}); + + // When new parsing is on, both PasswordFormManager and + // NewPasswordFormManager query the password store. + size_t expected_calls_to_store = new_parsing_for_saving ? 2 : 1; + + EXPECT_CALL(*store_, GetLogins(_, _)).Times(expected_calls_to_store); + manager()->UpdateFormManagers(); + + testing::Mock::VerifyAndClearExpectations(&store_); + } } TEST_F(PasswordManagerTest, DropFormManagers) {
diff --git a/components/rlz/rlz_tracker.cc b/components/rlz/rlz_tracker.cc index 2b35d730..948a7798 100644 --- a/components/rlz/rlz_tracker.cc +++ b/components/rlz/rlz_tracker.cc
@@ -303,7 +303,12 @@ delegate_->IsBrandOrganic(reactivation_brand_)) { SYSLOG(INFO) << "RLZ is disabled"; } else { - rlz_lib::UpdateExistingAccessPointRlz(brand_); + background_task_runner_->PostTask( + FROM_HERE, base::BindOnce( + [](const std::string& brand) { + rlz_lib::UpdateExistingAccessPointRlz(brand); + }, + brand_)); } #endif
diff --git a/components/security_interstitials/core/common/resources/interstitial_core.css b/components/security_interstitials/core/common/resources/interstitial_core.css index 7137e0b3ad..8aa42e09a 100644 --- a/components/security_interstitials/core/common/resources/interstitial_core.css +++ b/components/security_interstitials/core/common/resources/interstitial_core.css
@@ -10,6 +10,7 @@ --google-blue-600: rgb(26, 115, 232); --google-blue-700: rgb(25, 103, 210); --google-gray-50: rgb(248, 249, 250); + --google-gray-300: rgb(218, 220, 224); --google-gray-500: rgb(154, 160, 166); --google-gray-600: rgb(128, 134, 139); --google-gray-700: rgb(95, 99, 105); @@ -39,4 +40,4 @@ .icon { background-repeat: no-repeat; background-size: 100%; -} \ No newline at end of file +}
diff --git a/components/sync/engine_impl/model_type_worker_unittest.cc b/components/sync/engine_impl/model_type_worker_unittest.cc index 8d4a582..a5fd1ee 100644 --- a/components/sync/engine_impl/model_type_worker_unittest.cc +++ b/components/sync/engine_impl/model_type_worker_unittest.cc
@@ -1180,6 +1180,34 @@ EXPECT_FALSE(update2.encryption_key_name.empty()); } +// Test the receipt of decryptable entities, and that the worker will keep the +// entities until the decryption key arrives. +TEST_F(ModelTypeWorkerTest, + ReceiveDecryptableEntitiesShouldWaitTillKeyArrives) { + NormalInitialize(); + + // This next update will be encrypted using the second key. + SetUpdateEncryptionFilter(2); + TriggerUpdateFromServer(10, kTag1, kValue1); + + // Worker cannot decrypt it. + EXPECT_FALSE(processor()->HasUpdateResponse(kHash1)); + + // Allow the cryptographer to decrypt using the first key. + AddPendingKey(); + DecryptPendingKey(); + + // Worker still cannot decrypt it. + EXPECT_FALSE(processor()->HasUpdateResponse(kHash1)); + + // Allow the cryptographer to decrypt using the second key. + AddPendingKey(); + DecryptPendingKey(); + + // The worker can now decrypt the update and forward it to the processor. + EXPECT_TRUE(processor()->HasUpdateResponse(kHash1)); +} + // Test initializing a CommitQueue with a cryptographer at startup. TEST_F(ModelTypeWorkerTest, InitializeWithCryptographer) { // Set up some encryption state. @@ -1717,6 +1745,43 @@ update.entity->specifics.password().has_client_only_encrypted_data()); } +// Similar to ReceiveDecryptableEntities but for PASSWORDS, which have a custom +// encryption mechanism. +TEST_F(ModelTypeWorkerPasswordsTest, + ReceiveDecryptablePasswordShouldWaitTillKeyArrives) { + NormalInitialize(); + + // Receive an encrypted password, encrypted with the second ecnryption key. + sync_pb::PasswordSpecificsData unencrypted_password; + unencrypted_password.set_password_value(kPassword); + sync_pb::EntitySpecifics encrypted_specifics = + EncryptPasswordSpecifics(GetNthKeyParams(2), unencrypted_password); + + SyncEntity entity = server()->UpdateFromServer( + /*version_offset=*/10, kHash1, encrypted_specifics); + worker()->ProcessGetUpdatesResponse(server()->GetProgress(), + server()->GetContext(), {&entity}, + status_controller()); + worker()->ApplyUpdates(status_controller()); + + // Worker cannot decrypt it. + EXPECT_FALSE(processor()->HasUpdateResponse(kHash1)); + + // Allow the cryptographer to decrypt using the first key. + AddPendingKey(); + DecryptPendingKey(); + + // Worker still cannot decrypt it. + EXPECT_FALSE(processor()->HasUpdateResponse(kHash1)); + + // Allow the cryptographer to decrypt using the second key. + AddPendingKey(); + DecryptPendingKey(); + + // The worker can now decrypt the update and forward it to the processor. + EXPECT_TRUE(processor()->HasUpdateResponse(kHash1)); +} + // Analogous to ReceiveUndecryptableEntries but for PASSWORDS, which have a // custom encryption mechanism. TEST_F(ModelTypeWorkerPasswordsTest, ReceiveUndecryptablePasswordEntries) {
diff --git a/components/sync/model_impl/client_tag_based_model_type_processor.cc b/components/sync/model_impl/client_tag_based_model_type_processor.cc index 2270616..8867847 100644 --- a/components/sync/model_impl/client_tag_based_model_type_processor.cc +++ b/components/sync/model_impl/client_tag_based_model_type_processor.cc
@@ -1406,22 +1406,29 @@ std::string type_string = ModelTypeToString(type_); while (batch->HasNext()) { - KeyAndData data = batch->Next(); - std::unique_ptr<base::DictionaryValue> node = - data.second->ToDictionaryValue(); - ProcessorEntityTracker* entity = GetEntityForStorageKey(data.first); - // Entity could be null if there are some unapplied changes. + KeyAndData key_and_data = batch->Next(); + std::unique_ptr<EntityData> data = std::move(key_and_data.second); + + // There is an overlap between EntityData fields from the bridge and + // EntityMetadata fields from the processor's entity tracker, metadata is + // the authoritative source of truth. + ProcessorEntityTracker* entity = GetEntityForStorageKey(key_and_data.first); + // Tracker could be null if there are some unapplied changes. if (entity != nullptr) { - std::unique_ptr<base::DictionaryValue> metadata = - EntityMetadataToValue(entity->metadata()); - base::Value* server_id = metadata->FindKey("server_id"); - if (server_id) { - // Set ID value as directory, "s" means server. - node->SetString("ID", "s" + server_id->GetString()); - } - node->Set("metadata", std::move(metadata)); + const sync_pb::EntityMetadata& metadata = entity->metadata(); + // Set id value as directory, "s" means server. + data->id = "s" + metadata.server_id(); + data->creation_time = ProtoTimeToTime(metadata.creation_time()); + data->modification_time = ProtoTimeToTime(metadata.modification_time()); + data->client_tag_hash = metadata.client_tag_hash(); } + + std::unique_ptr<base::DictionaryValue> node = data->ToDictionaryValue(); node->SetString("modelType", type_string); + // Copy the whole metadata message into the dictionary (if existing). + if (entity != nullptr) { + node->Set("metadata", EntityMetadataToValue(entity->metadata())); + } all_nodes->Append(std::move(node)); }
diff --git a/components/viz/common/surfaces/parent_local_surface_id_allocator.cc b/components/viz/common/surfaces/parent_local_surface_id_allocator.cc index 02deaf492..f9bf6e38 100644 --- a/components/viz/common/surfaces/parent_local_surface_id_allocator.cc +++ b/components/viz/common/surfaces/parent_local_surface_id_allocator.cc
@@ -124,7 +124,7 @@ } bool ParentLocalSurfaceIdAllocator::HasValidLocalSurfaceIdAllocation() const { - return current_local_surface_id_allocation_.IsValid(); + return !is_invalid_ && current_local_surface_id_allocation_.IsValid(); } // static
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc index cb384e2..a5bee4e 100644 --- a/components/viz/service/display/skia_renderer.cc +++ b/components/viz/service/display/skia_renderer.cc
@@ -541,7 +541,7 @@ PrepareCanvasForDrawQuads(quad->shared_quad_state, draw_region, scissor_rect, &auto_canvas_restore); - current_paint_.reset(); + SkPaint paint; if (settings_->force_antialiasing || !IsScaleAndIntegerTranslate(current_canvas_->getTotalMatrix())) { // TODO(danakj): Until we can enable AA only on exterior edges of the @@ -551,30 +551,29 @@ quad->IsRightEdge(); if (settings_->allow_antialiasing && (settings_->force_antialiasing || all_four_edges_are_exterior)) - current_paint_.setAntiAlias(true); - current_paint_.setFilterQuality(kLow_SkFilterQuality); + paint.setAntiAlias(true); + paint.setFilterQuality(kLow_SkFilterQuality); } - current_paint_.setAlpha(quad->shared_quad_state->opacity * 255); - current_paint_.setBlendMode( + paint.setAlpha(quad->shared_quad_state->opacity * 255); + paint.setBlendMode( static_cast<SkBlendMode>(quad->shared_quad_state->blend_mode)); - switch (quad->material) { case DrawQuad::DEBUG_BORDER: - DrawDebugBorderQuad(DebugBorderDrawQuad::MaterialCast(quad)); + DrawDebugBorderQuad(DebugBorderDrawQuad::MaterialCast(quad), &paint); break; case DrawQuad::PICTURE_CONTENT: - DrawPictureQuad(PictureDrawQuad::MaterialCast(quad)); + DrawPictureQuad(PictureDrawQuad::MaterialCast(quad), &paint); break; case DrawQuad::RENDER_PASS: - DrawRenderPassQuad(RenderPassDrawQuad::MaterialCast(quad)); + DrawRenderPassQuad(RenderPassDrawQuad::MaterialCast(quad), &paint); break; case DrawQuad::SOLID_COLOR: - DrawSolidColorQuad(SolidColorDrawQuad::MaterialCast(quad)); + DrawSolidColorQuad(SolidColorDrawQuad::MaterialCast(quad), &paint); break; case DrawQuad::TEXTURE_CONTENT: - DrawTextureQuad(TextureDrawQuad::MaterialCast(quad)); + DrawTextureQuad(TextureDrawQuad::MaterialCast(quad), &paint); break; case DrawQuad::TILED_CONTENT: NOTREACHED(); @@ -585,11 +584,11 @@ NOTREACHED(); break; case DrawQuad::YUV_VIDEO_CONTENT: - DrawYUVVideoQuad(YUVVideoDrawQuad::MaterialCast(quad)); + DrawYUVVideoQuad(YUVVideoDrawQuad::MaterialCast(quad), &paint); break; case DrawQuad::INVALID: case DrawQuad::STREAM_VIDEO_CONTENT: - DrawUnsupportedQuad(quad); + DrawUnsupportedQuad(quad, &paint); NOTREACHED(); break; } @@ -655,7 +654,9 @@ } } -void SkiaRenderer::DrawDebugBorderQuad(const DebugBorderDrawQuad* quad) { +void SkiaRenderer::DrawDebugBorderQuad(const DebugBorderDrawQuad* quad, + SkPaint* paint) { + DCHECK(paint); // We need to apply the matrix manually to have pixel-sized stroke width. SkPoint vertices[4]; gfx::RectToSkRect(quad->rect).toQuad(vertices); @@ -664,16 +665,17 @@ 4); current_canvas_->resetMatrix(); - current_paint_.setColor(quad->color); - current_paint_.setAlpha(quad->shared_quad_state->opacity * - SkColorGetA(quad->color)); - current_paint_.setStyle(SkPaint::kStroke_Style); - current_paint_.setStrokeWidth(quad->width); + paint->setColor(quad->color); + paint->setAlpha(quad->shared_quad_state->opacity * SkColorGetA(quad->color)); + paint->setStyle(SkPaint::kStroke_Style); + paint->setStrokeWidth(quad->width); current_canvas_->drawPoints(SkCanvas::kPolygon_PointMode, 4, - transformed_vertices, current_paint_); + transformed_vertices, *paint); } -void SkiaRenderer::DrawPictureQuad(const PictureDrawQuad* quad) { +void SkiaRenderer::DrawPictureQuad(const PictureDrawQuad* quad, + SkPaint* paint) { + DCHECK(paint); SkMatrix content_matrix; content_matrix.setRectToRect(gfx::RectFToSkRect(quad->tex_coord_rect), gfx::RectToSkRect(quad->rect), @@ -718,15 +720,17 @@ quad->display_item_list->Raster(raster_canvas); } -void SkiaRenderer::DrawSolidColorQuad(const SolidColorDrawQuad* quad) { - current_paint_.setColor(quad->color); - current_paint_.setAlpha(quad->shared_quad_state->opacity * - SkColorGetA(quad->color)); - current_canvas_->drawRect(gfx::RectToSkRect(quad->visible_rect), - current_paint_); +void SkiaRenderer::DrawSolidColorQuad(const SolidColorDrawQuad* quad, + SkPaint* paint) { + DCHECK(paint); + paint->setColor(quad->color); + paint->setAlpha(quad->shared_quad_state->opacity * SkColorGetA(quad->color)); + current_canvas_->drawRect(gfx::RectToSkRect(quad->visible_rect), *paint); } -void SkiaRenderer::DrawTextureQuad(const TextureDrawQuad* quad) { +void SkiaRenderer::DrawTextureQuad(const TextureDrawQuad* quad, + SkPaint* paint) { + DCHECK(paint); ScopedSkImageBuilder builder(this, quad->resource_id()); const SkImage* image = builder.sk_image(); if (!image) @@ -746,21 +750,21 @@ bool blend_background = quad->background_color != SK_ColorTRANSPARENT && !image->isOpaque(); - bool needs_layer = blend_background && (current_paint_.getAlpha() != 0xFF); + bool needs_layer = blend_background && (paint->getAlpha() != 0xFF); base::Optional<SkAutoCanvasRestore> auto_canvas_restore; if (needs_layer) { auto_canvas_restore.emplace(current_canvas_, false /* do_save */); - current_canvas_->saveLayerAlpha(&quad_rect, current_paint_.getAlpha()); - current_paint_.setAlpha(0xFF); + current_canvas_->saveLayerAlpha(&quad_rect, paint->getAlpha()); + paint->setAlpha(0xFF); } if (blend_background) { SkPaint background_paint; background_paint.setColor(quad->background_color); current_canvas_->drawRect(quad_rect, background_paint); } - current_paint_.setFilterQuality( - quad->nearest_neighbor ? kNone_SkFilterQuality : kLow_SkFilterQuality); - current_canvas_->drawImageRect(image, sk_uv_rect, quad_rect, ¤t_paint_); + paint->setFilterQuality(quad->nearest_neighbor ? kNone_SkFilterQuality + : kLow_SkFilterQuality); + current_canvas_->drawImageRect(image, sk_uv_rect, quad_rect, paint); } void SkiaRenderer::AddTileQuadToBatch(const TileDrawQuad* quad, @@ -827,7 +831,9 @@ batched_tiles_.clear(); } -void SkiaRenderer::DrawYUVVideoQuad(const YUVVideoDrawQuad* quad) { +void SkiaRenderer::DrawYUVVideoQuad(const YUVVideoDrawQuad* quad, + SkPaint* paint) { + DCHECK(paint); if (draw_mode_ != DrawMode::DDL) { NOTIMPLEMENTED(); return; @@ -844,9 +850,9 @@ SkRect uv_rect = gfx::RectFToSkRect(visible_tex_coord_rect); // TODO(penghuang): figure out how to set correct filter quality. - current_paint_.setFilterQuality(kLow_SkFilterQuality); - current_canvas_->drawImageRect( - image, uv_rect, gfx::RectToSkRect(quad->visible_rect), ¤t_paint_); + paint->setFilterQuality(kLow_SkFilterQuality); + current_canvas_->drawImageRect(image, uv_rect, + gfx::RectToSkRect(quad->visible_rect), paint); } bool SkiaRenderer::CalculateRPDQParams(sk_sp<SkImage> content, @@ -920,14 +926,16 @@ resource_provider_); } -void SkiaRenderer::DrawRenderPassQuad(const RenderPassDrawQuad* quad) { +void SkiaRenderer::DrawRenderPassQuad(const RenderPassDrawQuad* quad, + SkPaint* paint) { + DCHECK(paint); auto bypass = render_pass_bypass_quads_.find(quad->render_pass_id); // When Render Pass has a single quad inside we would draw that directly. if (bypass != render_pass_bypass_quads_.end()) { TileDrawQuad* tile_quad = &bypass->second; ScopedSkImageBuilder builder(this, tile_quad->resource_id()); sk_sp<SkImage> content_image = sk_ref_sp(builder.sk_image()); - DrawRenderPassQuadInternal(quad, content_image); + DrawRenderPassQuadInternal(quad, content_image, paint); } else { auto iter = render_pass_backings_.find(quad->render_pass_id); DCHECK(render_pass_backings_.end() != iter); @@ -957,12 +965,14 @@ } } - DrawRenderPassQuadInternal(quad, content_image); + DrawRenderPassQuadInternal(quad, content_image, paint); } } void SkiaRenderer::DrawRenderPassQuadInternal(const RenderPassDrawQuad* quad, - sk_sp<SkImage> content_image) { + sk_sp<SkImage> content_image, + SkPaint* paint) { + DCHECK(paint); DrawRenderPassDrawQuadParams params; params.filters = FiltersForPass(quad->render_pass_id); bool can_draw = CalculateRPDQParams(content_image, quad, ¶ms); @@ -1006,13 +1016,13 @@ if (!mask_filter) { // Not mask, so we just draw the context_image directly. current_canvas_->drawImageRect(content_image, content_rect, - dest_visible_rect, ¤t_paint_); + dest_visible_rect, paint); return; } // With mask, we need convert the content_image to a shader, and use // drawRect() with the shader and the mask. - current_paint_.setMaskFilter(mask_filter); + paint->setMaskFilter(mask_filter); // Convert the content_image to a shader, and use drawRect() with the // shader. SkMatrix content_to_dest_matrix; @@ -1020,8 +1030,8 @@ gfx::RectToSkRect(quad->rect), SkMatrix::kFill_ScaleToFit); auto shader = content_image->makeShader(&content_to_dest_matrix); - current_paint_.setShader(std::move(shader)); - current_canvas_->drawRect(dest_visible_rect, current_paint_); + paint->setShader(std::move(shader)); + current_canvas_->drawRect(dest_visible_rect, *paint); return; } @@ -1046,9 +1056,9 @@ SkAutoCanvasRestore auto_canvas_restore(current_canvas_, true /* do_save */); current_canvas_->clipRect(gfx::RectToSkRect(quad->rect)); - SkPaint paint; - paint.setMaskFilter(mask_filter); - SkCanvas::SaveLayerRec rec(&dest_visible_rect, &paint, + SkPaint tmp_paint; + tmp_paint.setMaskFilter(mask_filter); + SkCanvas::SaveLayerRec rec(&dest_visible_rect, &tmp_paint, background_image_filter.get(), SkCanvas::kInitWithPrevious_SaveLayerFlag); // Lift content in the current_canvas_ into a new layer with @@ -1059,19 +1069,20 @@ false /* do_save */); current_canvas_->saveLayer(rec); current_canvas_->drawImageRect(content_image, content_rect, dest_visible_rect, - ¤t_paint_); + paint); } -void SkiaRenderer::DrawUnsupportedQuad(const DrawQuad* quad) { +void SkiaRenderer::DrawUnsupportedQuad(const DrawQuad* quad, SkPaint* paint) { + DCHECK(paint); // TODO(weiliangc): Make sure unsupported quads work. (crbug.com/644851) NOTIMPLEMENTED(); #ifdef NDEBUG - current_paint_.setColor(SK_ColorWHITE); + paint->setColor(SK_ColorWHITE); #else - current_paint_.setColor(SK_ColorMAGENTA); + paint->setColor(SK_ColorMAGENTA); #endif - current_paint_.setAlpha(quad->shared_quad_state->opacity * 255); - current_canvas_->drawRect(gfx::RectToSkRect(quad->rect), current_paint_); + paint->setAlpha(quad->shared_quad_state->opacity * 255); + current_canvas_->drawRect(gfx::RectToSkRect(quad->rect), *paint); } void SkiaRenderer::CopyDrawnRenderPass(
diff --git a/components/viz/service/display/skia_renderer.h b/components/viz/service/display/skia_renderer.h index d5da31a..4e9d693 100644 --- a/components/viz/service/display/skia_renderer.h +++ b/components/viz/service/display/skia_renderer.h
@@ -96,21 +96,22 @@ const gfx::QuadF* draw_region, const gfx::Rect* scissor_rect, base::Optional<SkAutoCanvasRestore>* auto_canvas_restore); - void DrawDebugBorderQuad(const DebugBorderDrawQuad* quad); - void DrawPictureQuad(const PictureDrawQuad* quad); - void DrawRenderPassQuad(const RenderPassDrawQuad* quad); + void DrawDebugBorderQuad(const DebugBorderDrawQuad* quad, SkPaint* paint); + void DrawPictureQuad(const PictureDrawQuad* quad, SkPaint* paint); + void DrawRenderPassQuad(const RenderPassDrawQuad* quad, SkPaint* paint); void DrawRenderPassQuadInternal(const RenderPassDrawQuad* quad, - sk_sp<SkImage> content_image); + sk_sp<SkImage> content_image, + SkPaint* paint); - void DrawSolidColorQuad(const SolidColorDrawQuad* quad); - void DrawTextureQuad(const TextureDrawQuad* quad); + void DrawSolidColorQuad(const SolidColorDrawQuad* quad, SkPaint* paint); + void DrawTextureQuad(const TextureDrawQuad* quad, SkPaint* paint); bool MustDrawBatchedTileQuadsBeforeQuad(const DrawQuad* new_quad, const gfx::QuadF* draw_region); void AddTileQuadToBatch(const TileDrawQuad* quad, const gfx::QuadF* draw_region); void DrawBatchedTileQuads(); - void DrawYUVVideoQuad(const YUVVideoDrawQuad* quad); - void DrawUnsupportedQuad(const DrawQuad* quad); + void DrawYUVVideoQuad(const YUVVideoDrawQuad* quad, SkPaint* paint); + void DrawUnsupportedQuad(const DrawQuad* quad, SkPaint* paint); bool CalculateRPDQParams(sk_sp<SkImage> src_image, const RenderPassDrawQuad* quad, DrawRenderPassDrawQuadParams* params); @@ -164,7 +165,6 @@ bool disable_picture_quad_image_filtering_ = false; bool is_scissor_enabled_ = false; gfx::Rect scissor_rect_; - SkPaint current_paint_; // Specific for overdraw. sk_sp<SkSurface> overdraw_surface_;
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 8cc48f5..2987224 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -991,6 +991,7 @@ "indexed_db/indexed_db_quota_client.h", "indexed_db/indexed_db_reporting.cc", "indexed_db/indexed_db_reporting.h", + "indexed_db/indexed_db_return_value.cc", "indexed_db/indexed_db_return_value.h", "indexed_db/indexed_db_tombstone_sweeper.cc", "indexed_db/indexed_db_tombstone_sweeper.h",
diff --git a/content/browser/indexed_db/indexed_db_blob_info.cc b/content/browser/indexed_db/indexed_db_blob_info.cc index 0e40f9c..9b9690e1 100644 --- a/content/browser/indexed_db/indexed_db_blob_info.cc +++ b/content/browser/indexed_db/indexed_db_blob_info.cc
@@ -7,9 +7,32 @@ #include "base/bind.h" #include "base/logging.h" #include "content/browser/indexed_db/indexed_db_leveldb_coding.h" +#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h" namespace content { +// static +void IndexedDBBlobInfo::ConvertBlobInfo( + const std::vector<IndexedDBBlobInfo>& blob_info, + std::vector<blink::mojom::IDBBlobInfoPtr>* blob_or_file_info) { + blob_or_file_info->reserve(blob_info.size()); + for (const auto& iter : blob_info) { + if (!iter.mark_used_callback().is_null()) + iter.mark_used_callback().Run(); + + auto info = blink::mojom::IDBBlobInfo::New(); + info->mime_type = iter.type(); + info->size = iter.size(); + if (iter.is_file()) { + info->file = blink::mojom::IDBFileInfo::New(); + info->file->name = iter.file_name(); + info->file->path = iter.file_path(); + info->file->last_modified = iter.last_modified(); + } + blob_or_file_info->push_back(std::move(info)); + } +} + IndexedDBBlobInfo::IndexedDBBlobInfo() : is_file_(false), size_(-1), key_(DatabaseMetaDataKey::kInvalidBlobKey) { }
diff --git a/content/browser/indexed_db/indexed_db_blob_info.h b/content/browser/indexed_db/indexed_db_blob_info.h index 2e36c081..6826ee9 100644 --- a/content/browser/indexed_db/indexed_db_blob_info.h +++ b/content/browser/indexed_db/indexed_db_blob_info.h
@@ -15,6 +15,7 @@ #include "base/time/time.h" #include "content/common/content_export.h" #include "storage/browser/blob/blob_data_handle.h" +#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h" namespace content { @@ -22,6 +23,11 @@ public: // TODO(mek): Use ShareableFileReference::FinalReleaseCallback somehow. typedef base::RepeatingCallback<void(const base::FilePath&)> ReleaseCallback; + + static void ConvertBlobInfo( + const std::vector<IndexedDBBlobInfo>& blob_info, + std::vector<blink::mojom::IDBBlobInfoPtr>* blob_or_file_info); + IndexedDBBlobInfo(); // These two are used for Blobs. IndexedDBBlobInfo(std::unique_ptr<storage::BlobDataHandle> blob_handle,
diff --git a/content/browser/indexed_db/indexed_db_callbacks.cc b/content/browser/indexed_db/indexed_db_callbacks.cc index be43dc3..81b168e 100644 --- a/content/browser/indexed_db/indexed_db_callbacks.cc +++ b/content/browser/indexed_db/indexed_db_callbacks.cc
@@ -92,49 +92,6 @@ DISALLOW_COPY_AND_ASSIGN(SafeIOThreadCursorWrapper); }; -void ConvertBlobInfo( - const std::vector<IndexedDBBlobInfo>& blob_info, - std::vector<blink::mojom::IDBBlobInfoPtr>* blob_or_file_info) { - blob_or_file_info->reserve(blob_info.size()); - for (const auto& iter : blob_info) { - if (!iter.mark_used_callback().is_null()) - iter.mark_used_callback().Run(); - - auto info = blink::mojom::IDBBlobInfo::New(); - info->mime_type = iter.type(); - info->size = iter.size(); - if (iter.is_file()) { - info->file = blink::mojom::IDBFileInfo::New(); - info->file->name = iter.file_name(); - info->file->path = iter.file_path(); - info->file->last_modified = iter.last_modified(); - } - blob_or_file_info->push_back(std::move(info)); - } -} - -// Destructively converts an IndexedDBReturnValue to a Mojo ReturnValue. -blink::mojom::IDBReturnValuePtr ConvertReturnValue( - IndexedDBReturnValue* value) { - auto mojo_value = blink::mojom::IDBReturnValue::New(); - mojo_value->value = blink::mojom::IDBValue::New(); - if (value->primary_key.IsValid()) { - mojo_value->primary_key = value->primary_key; - mojo_value->key_path = value->key_path; - } - if (!value->empty()) { - // TODO(crbug.com/902498): Use mojom traits to map directly from - // std::string. - const char* value_data = value->bits.data(); - mojo_value->value->bits = - std::vector<uint8_t>(value_data, value_data + value->bits.length()); - // Release value->bits std::string. - value->bits.clear(); - } - ConvertBlobInfo(value->blob_info, &mojo_value->value->blob_or_file_info); - return mojo_value; -} - } // namespace // Expected to be created and called from IO thread. @@ -198,23 +155,6 @@ DISALLOW_COPY_AND_ASSIGN(IOThreadHelper); }; -// static -blink::mojom::IDBValuePtr IndexedDBCallbacks::ConvertAndEraseValue( - IndexedDBValue* value) { - auto mojo_value = blink::mojom::IDBValue::New(); - if (!value->empty()) { - // TODO(crbug.com/902498): Use mojom traits to map directly from - // std::string. - const char* value_data = value->bits.data(); - mojo_value->bits = - std::vector<uint8_t>(value_data, value_data + value->bits.length()); - // Release value->bits std::string. - value->bits.clear(); - } - ConvertBlobInfo(value->blob_info, &mojo_value->blob_or_file_info); - return mojo_value; -} - IndexedDBCallbacks::IndexedDBCallbacks( base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host, const url::Origin& origin, @@ -347,7 +287,7 @@ blink::mojom::IDBValuePtr mojo_value; std::vector<IndexedDBBlobInfo> blob_info; if (value) { - mojo_value = ConvertAndEraseValue(value); + mojo_value = IndexedDBValue::ConvertAndEraseValue(value); blob_info.swap(value->blob_info); } @@ -374,7 +314,7 @@ blink::mojom::IDBValuePtr mojo_value; std::vector<IndexedDBBlobInfo> blob_info; if (value) { - mojo_value = ConvertAndEraseValue(value); + mojo_value = IndexedDBValue::ConvertAndEraseValue(value); blob_info.swap(value->blob_info); } @@ -401,7 +341,7 @@ std::vector<blink::mojom::IDBValuePtr> mojo_values; mojo_values.reserve(values->size()); for (size_t i = 0; i < values->size(); ++i) - mojo_values.push_back(ConvertAndEraseValue(&(*values)[i])); + mojo_values.push_back(IndexedDBValue::ConvertAndEraseValue(&(*values)[i])); base::PostTaskWithTraits( FROM_HERE, {BrowserThread::IO}, @@ -420,7 +360,7 @@ blink::mojom::IDBReturnValuePtr mojo_value; std::vector<IndexedDBBlobInfo> blob_info; if (value) { - mojo_value = ConvertReturnValue(value); + mojo_value = IndexedDBReturnValue::ConvertReturnValue(value); blob_info = value->blob_info; } @@ -442,8 +382,10 @@ std::vector<blink::mojom::IDBReturnValuePtr> mojo_values; mojo_values.reserve(values->size()); - for (size_t i = 0; i < values->size(); ++i) - mojo_values.push_back(ConvertReturnValue(&(*values)[i])); + for (size_t i = 0; i < values->size(); ++i) { + mojo_values.push_back( + IndexedDBReturnValue::ConvertReturnValue(&(*values)[i])); + } base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO}, base::BindOnce(&IOThreadHelper::SendSuccessArray,
diff --git a/content/browser/indexed_db/indexed_db_callbacks.h b/content/browser/indexed_db/indexed_db_callbacks.h index 4ec6798..d9ddd61 100644 --- a/content/browser/indexed_db/indexed_db_callbacks.h +++ b/content/browser/indexed_db/indexed_db_callbacks.h
@@ -43,9 +43,6 @@ class CONTENT_EXPORT IndexedDBCallbacks : public base::RefCounted<IndexedDBCallbacks> { public: - // Destructively converts an IndexedDBValue to a Mojo Value. - static blink::mojom::IDBValuePtr ConvertAndEraseValue(IndexedDBValue* value); - IndexedDBCallbacks(base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host, const url::Origin& origin, blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks_info,
diff --git a/content/browser/indexed_db/indexed_db_database.cc b/content/browser/indexed_db/indexed_db_database.cc index 418c1a2..8a7b204 100644 --- a/content/browser/indexed_db/indexed_db_database.cc +++ b/content/browser/indexed_db/indexed_db_database.cc
@@ -870,7 +870,7 @@ // indexeddb value. crbug.com/682363 IndexedDBValue copy = *value; changes->observations.back()->value = - IndexedDBCallbacks::ConvertAndEraseValue(©); + IndexedDBValue::ConvertAndEraseValue(©); } } }
diff --git a/content/browser/indexed_db/indexed_db_return_value.cc b/content/browser/indexed_db/indexed_db_return_value.cc new file mode 100644 index 0000000..d0b68ae --- /dev/null +++ b/content/browser/indexed_db/indexed_db_return_value.cc
@@ -0,0 +1,34 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/indexed_db/indexed_db_return_value.h" + +#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h" + +namespace content { + +// static +blink::mojom::IDBReturnValuePtr IndexedDBReturnValue::ConvertReturnValue( + IndexedDBReturnValue* value) { + auto mojo_value = blink::mojom::IDBReturnValue::New(); + mojo_value->value = blink::mojom::IDBValue::New(); + if (value->primary_key.IsValid()) { + mojo_value->primary_key = value->primary_key; + mojo_value->key_path = value->key_path; + } + if (!value->empty()) { + // TODO(crbug.com/902498): Use mojom traits to map directly from + // std::string. + const char* value_data = value->bits.data(); + mojo_value->value->bits = + std::vector<uint8_t>(value_data, value_data + value->bits.length()); + // Release value->bits std::string. + value->bits.clear(); + } + IndexedDBBlobInfo::ConvertBlobInfo(value->blob_info, + &mojo_value->value->blob_or_file_info); + return mojo_value; +} + +} // namespace content
diff --git a/content/browser/indexed_db/indexed_db_return_value.h b/content/browser/indexed_db/indexed_db_return_value.h index a528519..ca8436b 100644 --- a/content/browser/indexed_db/indexed_db_return_value.h +++ b/content/browser/indexed_db/indexed_db_return_value.h
@@ -18,6 +18,10 @@ // database, so they are kept separately, and sent back with the original data // so that the render process can amend the returned object. struct CONTENT_EXPORT IndexedDBReturnValue : public IndexedDBValue { + // Destructively converts an IndexedDBReturnValue to a Mojo ReturnValue. + static blink::mojom::IDBReturnValuePtr ConvertReturnValue( + IndexedDBReturnValue* value); + blink::IndexedDBKey primary_key; // primary key (only when using key generator) blink::IndexedDBKeyPath key_path;
diff --git a/content/browser/indexed_db/indexed_db_value.cc b/content/browser/indexed_db/indexed_db_value.cc index 6feed69..2566540 100644 --- a/content/browser/indexed_db/indexed_db_value.cc +++ b/content/browser/indexed_db/indexed_db_value.cc
@@ -5,9 +5,28 @@ #include "content/browser/indexed_db/indexed_db_value.h" #include "base/logging.h" +#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h" namespace content { +// static +blink::mojom::IDBValuePtr IndexedDBValue::ConvertAndEraseValue( + IndexedDBValue* value) { + auto mojo_value = blink::mojom::IDBValue::New(); + if (!value->empty()) { + // TODO(crbug.com/902498): Use mojom traits to map directly from + // std::string. + const char* value_data = value->bits.data(); + mojo_value->bits = + std::vector<uint8_t>(value_data, value_data + value->bits.length()); + // Release value->bits std::string. + value->bits.clear(); + } + IndexedDBBlobInfo::ConvertBlobInfo(value->blob_info, + &mojo_value->blob_or_file_info); + return mojo_value; +} + IndexedDBValue::IndexedDBValue() = default; IndexedDBValue::IndexedDBValue( const std::string& input_bits,
diff --git a/content/browser/indexed_db/indexed_db_value.h b/content/browser/indexed_db/indexed_db_value.h index 33bb45a..9314b5b64 100644 --- a/content/browser/indexed_db/indexed_db_value.h +++ b/content/browser/indexed_db/indexed_db_value.h
@@ -17,6 +17,9 @@ namespace content { struct CONTENT_EXPORT IndexedDBValue { + // Destructively converts an IndexedDBValue to a Mojo Value. + static blink::mojom::IDBValuePtr ConvertAndEraseValue(IndexedDBValue* value); + IndexedDBValue(); IndexedDBValue(const std::string& input_bits, const std::vector<IndexedDBBlobInfo>& input_blob_info);
diff --git a/content/browser/navigation_browsertest.cc b/content/browser/navigation_browsertest.cc index 91f3a642..46ea2b1 100644 --- a/content/browser/navigation_browsertest.cc +++ b/content/browser/navigation_browsertest.cc
@@ -1435,12 +1435,13 @@ DownloadTestObserverInProgress observer( BrowserContext::GetDownloadManager(opener->GetBrowserContext()), 1 /* wait_count */); - EXPECT_TRUE(ExecuteScript( + EXPECT_TRUE(ExecuteScriptWithoutUserGesture( popup, "window.opener.location ='data:html/text;base64,'+btoa('payload');")); observer.WaitForFinished(); histograms.ExpectUniqueSample("Navigation.DownloadPolicy", - NavigationDownloadPolicy::kAllowOpener, 1); + NavigationDownloadPolicy::kAllowOpenerNoGesture, + 1); } } // namespace content
diff --git a/content/browser/renderer_host/browser_compositor_view_mac.h b/content/browser/renderer_host/browser_compositor_view_mac.h index e271d4bc..da7e339 100644 --- a/content/browser/renderer_host/browser_compositor_view_mac.h +++ b/content/browser/renderer_host/browser_compositor_view_mac.h
@@ -127,7 +127,7 @@ void OnBeginFrame(base::TimeTicks frame_time) override; void OnFrameTokenChanged(uint32_t frame_token) override; float GetDeviceScaleFactor() const override; - void AllocateNewSurfaceIdOnEviction() override; + void InvalidateLocalSurfaceIdOnEviction() override; std::vector<viz::SurfaceId> CollectSurfaceIdsForEviction() override; base::WeakPtr<BrowserCompositorMac> GetWeakPtr() {
diff --git a/content/browser/renderer_host/browser_compositor_view_mac.mm b/content/browser/renderer_host/browser_compositor_view_mac.mm index 0240d73..20b88ff4 100644 --- a/content/browser/renderer_host/browser_compositor_view_mac.mm +++ b/content/browser/renderer_host/browser_compositor_view_mac.mm
@@ -346,8 +346,8 @@ return dfh_display_.device_scale_factor(); } -void BrowserCompositorMac::AllocateNewSurfaceIdOnEviction() { - dfh_local_surface_id_allocator_.GenerateId(); +void BrowserCompositorMac::InvalidateLocalSurfaceIdOnEviction() { + dfh_local_surface_id_allocator_.Invalidate(); } std::vector<viz::SurfaceId>
diff --git a/content/browser/renderer_host/delegated_frame_host.cc b/content/browser/renderer_host/delegated_frame_host.cc index 2ff513d..3fa783b 100644 --- a/content/browser/renderer_host/delegated_frame_host.cc +++ b/content/browser/renderer_host/delegated_frame_host.cc
@@ -360,7 +360,7 @@ host_frame_sink_manager_->EvictSurfaces(surface_ids); } frame_evictor_->OnSurfaceDiscarded(); - client_->AllocateNewSurfaceIdOnEviction(); + client_->InvalidateLocalSurfaceIdOnEviction(); } ////////////////////////////////////////////////////////////////////////////////
diff --git a/content/browser/renderer_host/delegated_frame_host.h b/content/browser/renderer_host/delegated_frame_host.h index 9689e8e..3a855f7 100644 --- a/content/browser/renderer_host/delegated_frame_host.h +++ b/content/browser/renderer_host/delegated_frame_host.h
@@ -50,7 +50,7 @@ virtual void OnBeginFrame(base::TimeTicks frame_time) = 0; virtual void OnFrameTokenChanged(uint32_t frame_token) = 0; virtual float GetDeviceScaleFactor() const = 0; - virtual void AllocateNewSurfaceIdOnEviction() = 0; + virtual void InvalidateLocalSurfaceIdOnEviction() = 0; virtual std::vector<viz::SurfaceId> CollectSurfaceIdsForEviction() = 0; };
diff --git a/content/browser/renderer_host/delegated_frame_host_client_aura.cc b/content/browser/renderer_host/delegated_frame_host_client_aura.cc index 973a35f..75a43f1 100644 --- a/content/browser/renderer_host/delegated_frame_host_client_aura.cc +++ b/content/browser/renderer_host/delegated_frame_host_client_aura.cc
@@ -55,8 +55,8 @@ return render_widget_host_view_->device_scale_factor_; } -void DelegatedFrameHostClientAura::AllocateNewSurfaceIdOnEviction() { - render_widget_host_view_->AllocateNewSurfaceIdOnEviction(); +void DelegatedFrameHostClientAura::InvalidateLocalSurfaceIdOnEviction() { + render_widget_host_view_->InvalidateLocalSurfaceIdOnEviction(); } std::vector<viz::SurfaceId>
diff --git a/content/browser/renderer_host/delegated_frame_host_client_aura.h b/content/browser/renderer_host/delegated_frame_host_client_aura.h index 8f93648..40e1f52e 100644 --- a/content/browser/renderer_host/delegated_frame_host_client_aura.h +++ b/content/browser/renderer_host/delegated_frame_host_client_aura.h
@@ -33,7 +33,7 @@ void OnBeginFrame(base::TimeTicks frame_time) override; void OnFrameTokenChanged(uint32_t frame_token) override; float GetDeviceScaleFactor() const override; - void AllocateNewSurfaceIdOnEviction() override; + void InvalidateLocalSurfaceIdOnEviction() override; std::vector<viz::SurfaceId> CollectSurfaceIdsForEviction() override; private:
diff --git a/content/browser/renderer_host/input/input_router_impl.cc b/content/browser/renderer_host/input/input_router_impl.cc index 77d4db9e5..4603cff 100644 --- a/content/browser/renderer_host/input/input_router_impl.cc +++ b/content/browser/renderer_host/input/input_router_impl.cc
@@ -276,6 +276,12 @@ void InputRouterImpl::SetWhiteListedTouchAction(cc::TouchAction touch_action, uint32_t unique_touch_event_id, InputEventAckState state) { + DCHECK(!compositor_touch_action_enabled_); + OnSetWhiteListedTouchAction(touch_action); +} + +void InputRouterImpl::OnSetWhiteListedTouchAction( + cc::TouchAction touch_action) { touch_action_filter_.OnSetWhiteListedTouchAction(touch_action); client_->OnSetWhiteListedTouchAction(touch_action); if (compositor_touch_action_enabled_) { @@ -574,8 +580,18 @@ // The SetTouchAction IPC occurs on a different channel so always // send it in the input event ack to ensure it is available at the // time the ACK is handled. - if (touch_action.has_value()) - OnSetTouchAction(touch_action.value()); + if (touch_action.has_value()) { + if (!compositor_touch_action_enabled_) { + OnSetTouchAction(touch_action.value()); + } else { + if (source == InputEventAckSource::COMPOSITOR_THREAD) + OnSetWhiteListedTouchAction(touch_action.value()); + else if (source == InputEventAckSource::MAIN_THREAD) + OnSetTouchAction(touch_action.value()); + else + NOTREACHED(); + } + } bool should_stop_timeout_monitor = !compositor_touch_action_enabled_ ||
diff --git a/content/browser/renderer_host/input/input_router_impl.h b/content/browser/renderer_host/input/input_router_impl.h index 05bb0d01..dd4e239 100644 --- a/content/browser/renderer_host/input/input_router_impl.h +++ b/content/browser/renderer_host/input/input_router_impl.h
@@ -111,6 +111,7 @@ void ForceResetTouchActionForTest(); private: + friend class InputRouterImplTest; friend class InputRouterImplTestBase; friend class MockRenderWidgetHost; friend class RenderWidgetHostSitePerProcessTest; @@ -216,6 +217,7 @@ GestureEventWithLatencyInfo& gesture_event, const FilterGestureEventResult& existing_result); void ProcessDeferredGestureEventQueue(); + void OnSetWhiteListedTouchAction(cc::TouchAction touch_action); InputRouterImplClient* client_; InputDispositionHandler* disposition_handler_;
diff --git a/content/browser/renderer_host/input/input_router_impl_unittest.cc b/content/browser/renderer_host/input/input_router_impl_unittest.cc index 49327ed..45cff45 100644 --- a/content/browser/renderer_host/input/input_router_impl_unittest.cc +++ b/content/browser/renderer_host/input/input_router_impl_unittest.cc
@@ -425,13 +425,14 @@ PressTouchPoint(1, 1); base::Optional<ui::DidOverscrollParams> overscroll; input_router_->SendTouchEvent(TouchEventWithLatencyInfo(touch_event_)); - input_router_->TouchEventHandled( - TouchEventWithLatencyInfo(touch_event_), InputEventAckSource::BROWSER, - ui::LatencyInfo(), state, overscroll, touch_action); + input_router_->TouchEventHandled(TouchEventWithLatencyInfo(touch_event_), + InputEventAckSource::MAIN_THREAD, + ui::LatencyInfo(), state, overscroll, + touch_action); EXPECT_EQ(input_router_->touch_action_filter_.num_of_active_touches_, 1); ReleaseTouchPoint(0); input_router_->OnTouchEventAck(TouchEventWithLatencyInfo(touch_event_), - InputEventAckSource::BROWSER, state); + InputEventAckSource::MAIN_THREAD, state); EXPECT_EQ(input_router_->touch_action_filter_.num_of_active_touches_, 0); } @@ -470,6 +471,14 @@ } } + base::Optional<cc::TouchAction> AllowedTouchAction() { + return input_router_->touch_action_filter_.allowed_touch_action_; + } + + base::Optional<cc::TouchAction> WhiteListedTouchAction() { + return input_router_->touch_action_filter_.white_listed_touch_action_; + } + protected: const bool compositor_touch_action_enabled_; @@ -1272,7 +1281,7 @@ // kTouchActionNone should disable the timeout. CancelTouchTimeout(); dispatched_messages[0]->ToEvent()->CallCallback( - InputEventAckSource::COMPOSITOR_THREAD, ui::LatencyInfo(), + InputEventAckSource::MAIN_THREAD, ui::LatencyInfo(), INPUT_EVENT_ACK_STATE_CONSUMED, base::nullopt, cc::kTouchActionNone); EXPECT_EQ(1U, disposition_handler_->GetAndResetAckCount()); EXPECT_FALSE(TouchEventTimeoutEnabled()); @@ -1356,7 +1365,7 @@ ASSERT_TRUE(touch_release_event2[0]->ToEvent()); touch_press_event1[0]->ToEvent()->CallCallback( - InputEventAckSource::COMPOSITOR_THREAD, ui::LatencyInfo(), + InputEventAckSource::MAIN_THREAD, ui::LatencyInfo(), INPUT_EVENT_ACK_STATE_CONSUMED, base::nullopt, cc::kTouchActionNone); touch_move_event1[0]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED); @@ -1416,7 +1425,7 @@ ASSERT_TRUE(touch_move_event1[0]->ToEvent()); CancelTouchTimeout(); touch_press_event1[0]->ToEvent()->CallCallback( - InputEventAckSource::COMPOSITOR_THREAD, ui::LatencyInfo(), + InputEventAckSource::MAIN_THREAD, ui::LatencyInfo(), INPUT_EVENT_ACK_STATE_CONSUMED, base::nullopt, cc::kTouchActionNone); touch_move_event1[0]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED); @@ -1490,7 +1499,7 @@ // Ensure we have touch-action:none, suppressing scroll events. dispatched_messages[0]->ToEvent()->CallCallback( - InputEventAckSource::COMPOSITOR_THREAD, ui::LatencyInfo(), + InputEventAckSource::MAIN_THREAD, ui::LatencyInfo(), INPUT_EVENT_ACK_STATE_CONSUMED, base::nullopt, cc::kTouchActionNone); EXPECT_EQ(0U, GetAndResetDispatchedMessages().size()); dispatched_messages[1]->ToEvent()->CallCallback( @@ -1577,7 +1586,7 @@ ASSERT_EQ(1U, dispatched_messages.size()); ASSERT_TRUE(dispatched_messages[0]->ToEvent()); dispatched_messages[0]->ToEvent()->CallCallback( - InputEventAckSource::COMPOSITOR_THREAD, ui::LatencyInfo(), + InputEventAckSource::MAIN_THREAD, ui::LatencyInfo(), INPUT_EVENT_ACK_STATE_CONSUMED, base::nullopt, cc::kTouchActionNone); ReleaseTouchPoint(0); SendTouchEvent(); @@ -1966,6 +1975,9 @@ // Test proper routing of whitelisted touch action notifications received from // |SetWhiteListedTouchAction| IPC messages. TEST_P(InputRouterImplTest, OnSetWhiteListedTouchAction) { + // The white listed touch action is bundled in the ack. + if (compositor_touch_action_enabled_) + return; cc::TouchAction touch_action = cc::kTouchActionPanY; OnSetWhiteListedTouchAction(touch_action, 0, INPUT_EVENT_ACK_STATE_NOT_CONSUMED); @@ -2021,14 +2033,24 @@ DispatchedMessages dispatched_messages = GetAndResetDispatchedMessages(); ASSERT_EQ(1U, dispatched_messages.size()); ASSERT_TRUE(dispatched_messages[0]->ToEvent()); + InputEventAckSource source = InputEventAckSource::MAIN_THREAD; + base::Optional<cc::TouchAction> expected_touch_action = cc::kTouchActionPan; + if (compositor_touch_action_enabled_) + source = InputEventAckSource::COMPOSITOR_THREAD; dispatched_messages[0]->ToEvent()->CallCallback( - InputEventAckSource::COMPOSITOR_THREAD, ui::LatencyInfo(), - INPUT_EVENT_ACK_STATE_CONSUMED, base::nullopt, cc::kTouchActionNone); + source, ui::LatencyInfo(), INPUT_EVENT_ACK_STATE_CONSUMED, base::nullopt, + expected_touch_action); ASSERT_EQ(1U, disposition_handler_->GetAndResetAckCount()); - base::Optional<cc::TouchAction> allowed_touch_action = - input_router_->AllowedTouchAction(); - DCHECK(allowed_touch_action.has_value()); - EXPECT_EQ(cc::TouchAction::kTouchActionNone, allowed_touch_action.value()); + base::Optional<cc::TouchAction> allowed_touch_action = AllowedTouchAction(); + base::Optional<cc::TouchAction> white_listed_touch_action = + WhiteListedTouchAction(); + if (compositor_touch_action_enabled_) { + EXPECT_FALSE(allowed_touch_action.has_value()); + EXPECT_EQ(expected_touch_action, white_listed_touch_action); + } else { + EXPECT_FALSE(white_listed_touch_action.has_value()); + EXPECT_EQ(expected_touch_action, allowed_touch_action); + } } namespace {
diff --git a/content/browser/renderer_host/input/touch_action_filter.h b/content/browser/renderer_host/input/touch_action_filter.h index 4ee9a50..d5d6efd 100644 --- a/content/browser/renderer_host/input/touch_action_filter.h +++ b/content/browser/renderer_host/input/touch_action_filter.h
@@ -76,6 +76,7 @@ void AppendToGestureSequenceForDebugging(const char* str); private: + friend class InputRouterImplTest; friend class InputRouterImplTestBase; friend class MockRenderWidgetHost; friend class TouchActionFilterTest;
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc index cb745652..98fea8b 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.cc +++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -2400,7 +2400,7 @@ } void RenderWidgetHostViewAndroid::WasEvicted() { - local_surface_id_allocator_.GenerateId(); + local_surface_id_allocator_.Invalidate(); } } // namespace content
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc index 2f878e4..4572744 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -501,6 +501,15 @@ if (is_mus_browser_plugin_guest_) return; + // If the viz::LocalSurfaceIdAllocation is invalid, we may have been evicted, + // and no other visual properties have since been changed. Allocate a new id + // and start synchronizing. + if (!window_->GetLocalSurfaceIdAllocation().IsValid()) { + window_->AllocateLocalSurfaceId(); + SynchronizeVisualProperties(cc::DeadlinePolicy::UseDefaultDeadline(), + window_->GetLocalSurfaceIdAllocation()); + } + window_->Show(); WasUnOccluded(); } @@ -2096,6 +2105,10 @@ DCHECK(window_); window_->UpdateLocalSurfaceIdFromEmbeddedClient( child_local_surface_id_allocation); + // If the viz::LocalSurfaceIdAllocation is invalid, we may have been evicted, + // allocate a new one to establish bounds. + if (!GetLocalSurfaceIdAllocation().IsValid()) + window_->AllocateLocalSurfaceId(); if (delegated_frame_host_) { delegated_frame_host_->EmbedSurface( @@ -2589,8 +2602,8 @@ host()->GetContentRenderingTimeoutFrom(view_aura->host()); } -void RenderWidgetHostViewAura::AllocateNewSurfaceIdOnEviction() { - window_->UpdateLocalSurfaceIdFromEmbeddedClient(base::nullopt); +void RenderWidgetHostViewAura::InvalidateLocalSurfaceIdOnEviction() { + window_->InvalidateLocalSurfaceId(); } } // namespace content
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h index f567a62..df797fe 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.h +++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -558,7 +558,7 @@ // Called when the window title is changed. void WindowTitleChanged(); - void AllocateNewSurfaceIdOnEviction(); + void InvalidateLocalSurfaceIdOnEviction(); const bool is_mus_browser_plugin_guest_;
diff --git a/content/browser/tracing/background_tracing_manager_browsertest.cc b/content/browser/tracing/background_tracing_manager_browsertest.cc index 9dd2cb9..d846263e 100644 --- a/content/browser/tracing/background_tracing_manager_browsertest.cc +++ b/content/browser/tracing/background_tracing_manager_browsertest.cc
@@ -394,8 +394,10 @@ wait_for_tracing.Run(); } - TRACE_EVENT1("benchmark", "whitelisted", "find_this", 1); - TRACE_EVENT1("benchmark", "not_whitelisted", "this_not_found", 1); + { + TRACE_EVENT1("benchmark", "whitelisted", "find_this", 1); + TRACE_EVENT1("benchmark", "not_whitelisted", "this_not_found", 1); + } BackgroundTracingManager::GetInstance()->WhenIdle( base::Bind(&DisableScenarioWhenIdle));
diff --git a/content/browser/tracing/background_tracing_manager_impl.cc b/content/browser/tracing/background_tracing_manager_impl.cc index 03ff4ea..df69487 100644 --- a/content/browser/tracing/background_tracing_manager_impl.cc +++ b/content/browser/tracing/background_tracing_manager_impl.cc
@@ -513,6 +513,18 @@ is_tracing_ = TracingControllerImpl::GetInstance()->StartTracing( config, base::BindOnce(&BackgroundTracingManagerImpl::OnStartTracingDone, base::Unretained(this), preset)); + + // Activate the categories immediately. StartTracing eventually does this + // itself, but asynchronously via PostTask, and in the meantime events will be + // dropped. This ensures that we start recording events for those categories + // immediately. + if (is_tracing_) { + uint8_t modes = base::trace_event::TraceLog::RECORDING_MODE; + if (!config.event_filters().empty()) + modes |= base::trace_event::TraceLog::FILTERING_MODE; + base::trace_event::TraceLog::GetInstance()->SetEnabled(config, modes); + } + RecordBackgroundTracingMetric(RECORDING_ENABLED); }
diff --git a/content/browser/web_contents/web_contents_view_mac.mm b/content/browser/web_contents/web_contents_view_mac.mm index ed6586cf..18f8533 100644 --- a/content/browser/web_contents/web_contents_view_mac.mm +++ b/content/browser/web_contents/web_contents_view_mac.mm
@@ -172,7 +172,8 @@ // The drag invokes a nested event loop, arrange to continue // processing events. base::MessageLoopCurrent::ScopedNestableTaskAllower allow; - NSDragOperation mask = static_cast<NSDragOperation>(allowed_operations); + NSDragOperation mask = static_cast<NSDragOperation>(allowed_operations) & + ~NSDragOperationGeneric; NSPoint offset = NSPointFromCGPoint( gfx::PointAtOffsetFromOrigin(image_offset).ToCGPoint()); [cocoa_view_ startDragWithDropData:drop_data
diff --git a/content/renderer/input/widget_input_handler_manager.cc b/content/renderer/input/widget_input_handler_manager.cc index 202f08a..67a2a5e 100644 --- a/content/renderer/input/widget_input_handler_manager.cc +++ b/content/renderer/input/widget_input_handler_manager.cc
@@ -276,6 +276,10 @@ cc::TouchAction touch_action, uint32_t unique_touch_event_id, ui::InputHandlerProxy::EventDisposition event_disposition) { + if (base::FeatureList::IsEnabled(features::kCompositorTouchAction)) { + white_listed_touch_action_ = touch_action; + return; + } mojom::WidgetInputHandlerHost* host = GetWidgetInputHandlerHost(); if (!host) return; @@ -478,6 +482,10 @@ if (!callback) return; + if (!touch_action.has_value()) { + touch_action = white_listed_touch_action_; + white_listed_touch_action_.reset(); + } // This method is called from either the main thread or the compositor thread. bool is_compositor_thread = compositor_task_runner_ && compositor_task_runner_->BelongsToCurrentThread();
diff --git a/content/renderer/input/widget_input_handler_manager.h b/content/renderer/input/widget_input_handler_manager.h index 0682118..6ebdf02 100644 --- a/content/renderer/input/widget_input_handler_manager.h +++ b/content/renderer/input/widget_input_handler_manager.h
@@ -146,6 +146,8 @@ scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_; + base::Optional<cc::TouchAction> white_listed_touch_action_; + #if defined(OS_ANDROID) std::unique_ptr<SynchronousCompositorProxyRegistry> synchronous_compositor_registry_;
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index b99f6ef9..3adeac7 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -662,7 +662,8 @@ DCHECK(content::RenderThread::Get()); if (closing_) return; - NotifyOnClose(); + for (auto& observer : render_frames_) + observer.WidgetWillClose(); closing_ = true; // Browser correspondence is no longer needed at this point. @@ -806,9 +807,10 @@ void RenderWidget::OnWasShown(base::TimeTicks show_request_timestamp, bool was_evicted) { TRACE_EVENT0("renderer", "RenderWidget::OnWasShown"); - // TODO(crbug.com/896836): CHECK to try track down why we make a frame sink - // for a RenderWidget without a main frame. - CHECK(!is_frozen_); + // TODO(danakj): Nothing should happen ideally if the RenderWidget is frozen! + // It's not visible! However.. the RenderView needs to see it as visible in + // order to make the Page visible /o\ so this is hard. We need to detangle + // page visibility from the main widget. https://crbug.com/419087 was_shown_time_ = base::TimeTicks::Now(); // See OnWasHidden @@ -1603,17 +1605,9 @@ } void RenderWidget::DoDeferredClose() { - // Prevent compositor from setting up new IPC channels, since we know a - // WidgetMsg_Close is coming. - host_will_close_this_ = true; Send(new WidgetHostMsg_Close(routing_id_)); } -void RenderWidget::NotifyOnClose() { - for (auto& observer : render_frames_) - observer.WidgetWillClose(); -} - void RenderWidget::CloseWidgetSoon() { DCHECK(content::RenderThread::Get()); if (is_frozen_) { @@ -1624,9 +1618,17 @@ return; } + // Prevent compositor from setting up new IPC channels, since we know a + // WidgetMsg_Close is coming. We do this immediately, not in DoDeferredClose, + // as the caller (eg WebPagePopupImpl) may start tearing down things after + // calling this method, including detaching the frame from this RenderWidget. + // Then trying to make a LayerTreeFrameSink would crash. + // https://crbug.com/906340 + host_will_close_this_ = true; + // If a page calls window.close() twice, we'll end up here twice, but that's // OK. It is safe to send multiple Close messages. - + // // Ask the RenderWidgetHost to initiate close. We could be called from deep // in Javascript. If we ask the RendwerWidgetHost to close now, the window // could be closed before the JS finishes executing. So instead, post a @@ -2260,7 +2262,15 @@ if (render_widget_scheduling_state_) render_widget_scheduling_state_->SetHidden(hidden); - layer_tree_view_->SetVisible(!is_hidden_); + // When the RenderWidget is frozen, visibility of the compositor is overridden + // to always be hidden to prevent it from using resources that are not needed. + // Unfortunately the main RenderWidget for a RenderView must be marked visible + // even if the RenderView has a proxy main frame (and the RenderWidget is + // frozen), in order for the RenderView to use the visibility signal from the + // RenderWidget. This is bad. But we don't need to show the compositor to + // satisfy that requirement. + if (!is_frozen_) + layer_tree_view_->SetVisible(!is_hidden_); } void RenderWidget::DidToggleFullscreen() {
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h index 1c2f30f7..7a6d45a9 100644 --- a/content/renderer/render_widget.h +++ b/content/renderer/render_widget.h
@@ -584,7 +584,6 @@ void StopCompositor(); void DoDeferredClose(); - void NotifyOnClose(); gfx::Size GetSizeForWebWidget() const; void ResizeWebWidget();
diff --git a/content/shell/browser/layout_test/layout_test_content_browser_client.cc b/content/shell/browser/layout_test/layout_test_content_browser_client.cc index 54c8835c..95148d3 100644 --- a/content/shell/browser/layout_test/layout_test_content_browser_client.cc +++ b/content/shell/browser/layout_test/layout_test_content_browser_client.cc
@@ -4,7 +4,14 @@ #include "content/shell/browser/layout_test/layout_test_content_browser_client.h" +#include <algorithm> +#include <iterator> +#include <string> +#include <utility> +#include <vector> + #include "base/single_thread_task_runner.h" +#include "base/stl_util.h" #include "base/strings/pattern.h" #include "base/task/post_task.h" #include "content/public/browser/browser_context.h" @@ -14,7 +21,9 @@ #include "content/public/browser/overlay_window.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/resource_dispatcher_host.h" +#include "content/public/browser/site_isolation_policy.h" #include "content/public/browser/storage_partition.h" +#include "content/public/common/content_switches.h" #include "content/shell/browser/layout_test/blink_test_controller.h" #include "content/shell/browser/layout_test/fake_bluetooth_chooser.h" #include "content/shell/browser/layout_test/layout_test_bluetooth_fake_adapter_setter_impl.h" @@ -31,6 +40,7 @@ #include "device/bluetooth/test/fake_bluetooth.h" #include "gpu/config/gpu_switches.h" #include "services/service_manager/public/cpp/binder_registry.h" +#include "url/origin.h" namespace content { namespace { @@ -234,6 +244,41 @@ "https://devtools.oopif.test:8443/", }; + // On platforms with strict Site Isolation, the also isolate WPT origins for + // additional OOPIF coverage. + // + // Don't isolate WPT origins on + // 1) platforms where strict Site Isolation is not the default. + // 2) in layout tests under virtual/not-site-per-process where + // --disable-site-isolation-trials switch is used. + if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites()) { + // The list of hostnames below is based on + // https://web-platform-tests.org/writing-tests/server-features.html + const char* kWptHostnames[] = { + "www.web-platform.test", + "www1.web-platform.test", + "www2.web-platform.test", + "xn--n8j6ds53lwwkrqhv28a.web-platform.test", + "xn--lve-6lad.web-platform.test", + }; + + // The list of schemes and ports below is based on + // third_party/blink/tools/blinkpy/third_party/wpt/wpt.config.json + const char* kOriginTemplates[] = { + "http://%s:8001/", "http://%s:8081/", "https://%s:8444/", + }; + + origins_to_isolate.reserve(origins_to_isolate.size() + + base::size(kWptHostnames) * + base::size(kOriginTemplates)); + for (const char* kWptHostname : kWptHostnames) { + for (const char* kOriginTemplate : kOriginTemplates) { + std::string origin = base::StringPrintf(kOriginTemplate, kWptHostname); + origins_to_isolate.push_back(origin); + } + } + } + // Translate std::vector<std::string> into std::vector<url::Origin>. std::vector<url::Origin> result; result.reserve(origins_to_isolate.size()); @@ -265,14 +310,6 @@ return !block_popups_ || user_gesture; } -bool LayoutTestContentBrowserClient::ShouldEnableStrictSiteIsolation() { - // TODO(lukasza, alexmos): Layout tests should have the same default state of - // site-per-process as everything else, but because of a backlog of layout - // test failures (see https://crbug.com/477150), layout tests still use no - // isolation by default. - return false; -} - bool LayoutTestContentBrowserClient::CanIgnoreCertificateErrorIfNeeded() { return base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kRunWebTests);
diff --git a/content/shell/browser/layout_test/layout_test_content_browser_client.h b/content/shell/browser/layout_test/layout_test_content_browser_client.h index c1f0405..b416ba6 100644 --- a/content/shell/browser/layout_test/layout_test_content_browser_client.h +++ b/content/shell/browser/layout_test/layout_test_content_browser_client.h
@@ -70,7 +70,6 @@ bool user_gesture, bool opener_suppressed, bool* no_javascript_access) override; - bool ShouldEnableStrictSiteIsolation() override; bool CanIgnoreCertificateErrorIfNeeded() override; // ShellContentBrowserClient overrides.
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py index 245eaff..46697a8 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -640,8 +640,6 @@ self.Flaky('conformance/textures/image/' + 'tex-2d-rgb-rgb-unsigned_byte.html', ['linux', 'nvidia'], bug=596622) - self.Flaky('conformance2/context/methods-2.html', - ['linux', 'nvidia'], bug=906212) # NVIDIA P400 OpenGL self.Fail('conformance/limits/gl-max-texture-dimensions.html',
diff --git a/docs/infra/cq.md b/docs/infra/cq.md index 75a2f3e..b7e67a1 100644 --- a/docs/infra/cq.md +++ b/docs/infra/cq.md
@@ -56,7 +56,9 @@ ### What exactly does CQ run? -CQ runs the jobs specified in [cq.cfg](../../infra/config/branch/cq.cfg). +CQ runs the jobs specified in [cq.cfg](../../infra/config/branch/cq.cfg). See +[`cq_builders.md`](cq_builders.md) for an auto generated file with links to +information about the builders on the CQ. Some of these jobs are experimental. This means they are executed on a percentage of CQ builds, and the outcome of the build doesn't affect if the CL
diff --git a/docs/infra/cq_builders.md b/docs/infra/cq_builders.md new file mode 100644 index 0000000..4a55b9c --- /dev/null +++ b/docs/infra/cq_builders.md
@@ -0,0 +1,269 @@ +# List of CQ builders + +This page is auto generated using the script +//infra/config/branch/cq_config_presubmit.py. Do not manually edit. + +[TOC] + +Each builder name links to that builder on Milo. The "Backing builders" links +point to the file used to determine which configurations a builder should copy +when running. These links might 404 or error; they are hard-coded right now, +using common assumptions about how builders are configured. + +## Required builders + +These builders must pass before a CL may land. + +* [android-binary-size](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/android-binary-size) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+android-binary-size)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+android-binary-size)) + +* [android-kitkat-arm-rel](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/android-kitkat-arm-rel) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+android-kitkat-arm-rel)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+android-kitkat-arm-rel)) + +* [android-marshmallow-arm64-rel](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/android-marshmallow-arm64-rel) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+android-marshmallow-arm64-rel)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+android-marshmallow-arm64-rel)) + +* [android_arm64_dbg_recipe](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/android_arm64_dbg_recipe) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+android_arm64_dbg_recipe)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+android_arm64_dbg_recipe)) + +* [android_clang_dbg_recipe](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/android_clang_dbg_recipe) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+android_clang_dbg_recipe)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+android_clang_dbg_recipe)) + +* [android_compile_dbg](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/android_compile_dbg) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+android_compile_dbg)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+android_compile_dbg)) + +* [android_cronet](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/android_cronet) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+android_cronet)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+android_cronet)) + +* [cast_shell_android](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/cast_shell_android) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+cast_shell_android)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+cast_shell_android)) + +* [cast_shell_linux](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/cast_shell_linux) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+cast_shell_linux)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+cast_shell_linux)) + +* [chromeos-amd64-generic-rel](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/chromeos-amd64-generic-rel) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+chromeos-amd64-generic-rel)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+chromeos-amd64-generic-rel)) + +* [chromeos-daisy-rel](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/chromeos-daisy-rel) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+chromeos-daisy-rel)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+chromeos-daisy-rel)) + +* [chromium_presubmit](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/chromium_presubmit) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+chromium_presubmit)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+chromium_presubmit)) + +* [fuchsia_arm64](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/fuchsia_arm64) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+fuchsia_arm64)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+fuchsia_arm64)) + +* [fuchsia_x64](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/fuchsia_x64) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+fuchsia_x64)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+fuchsia_x64)) + +* [ios-simulator](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/ios-simulator) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+ios-simulator)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+ios-simulator)) + +* [linux-chromeos-rel](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux-chromeos-rel) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+linux-chromeos-rel)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+linux-chromeos-rel)) + +* [linux-jumbo-rel](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux-jumbo-rel) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+linux-jumbo-rel)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+linux-jumbo-rel)) + +* [linux-libfuzzer-asan-rel](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux-libfuzzer-asan-rel) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+linux-libfuzzer-asan-rel)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+linux-libfuzzer-asan-rel)) + +* [linux-ozone-rel](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux-ozone-rel) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+linux-ozone-rel)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+linux-ozone-rel)) + +* [linux_chromium_asan_rel_ng](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux_chromium_asan_rel_ng) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+linux_chromium_asan_rel_ng)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+linux_chromium_asan_rel_ng)) + +* [linux_chromium_compile_dbg_ng](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux_chromium_compile_dbg_ng) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+linux_chromium_compile_dbg_ng)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+linux_chromium_compile_dbg_ng)) + +* [linux_chromium_headless_rel](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux_chromium_headless_rel) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+linux_chromium_headless_rel)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+linux_chromium_headless_rel)) + +* [linux_chromium_rel_ng](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux_chromium_rel_ng) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+linux_chromium_rel_ng)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+linux_chromium_rel_ng)) + +* [linux_chromium_tsan_rel_ng](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux_chromium_tsan_rel_ng) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+linux_chromium_tsan_rel_ng)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+linux_chromium_tsan_rel_ng)) + +* [mac_chromium_compile_dbg_ng](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/mac_chromium_compile_dbg_ng) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+mac_chromium_compile_dbg_ng)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+mac_chromium_compile_dbg_ng)) + +* [mac_chromium_rel_ng](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/mac_chromium_rel_ng) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+mac_chromium_rel_ng)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+mac_chromium_rel_ng)) + +* [win10_chromium_x64_rel_ng](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/win10_chromium_x64_rel_ng) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+win10_chromium_x64_rel_ng)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+win10_chromium_x64_rel_ng)) + +* [win7_chromium_rel_ng](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/win7_chromium_rel_ng) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+win7_chromium_rel_ng)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+win7_chromium_rel_ng)) + +* [win_chromium_compile_dbg_ng](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/win_chromium_compile_dbg_ng) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+win_chromium_compile_dbg_ng)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+win_chromium_compile_dbg_ng)) + + +## Optional builders + +These builders optionally run, depending on the files in a +CL. For example, a CL which touches `//gpu/BUILD.gn` would trigger the builder +`android_optional_gpu_tests_rel`, due to the `path_regexp` values for that +builder. + +* [android_optional_gpu_tests_rel](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/android_optional_gpu_tests_rel) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+android_optional_gpu_tests_rel)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+android_optional_gpu_tests_rel)) + + Path regular expressions: + * [`//cc/.+`](https://cs.chromium.org/chromium/src/cc/) + * [`//chrome/browser/vr/.+`](https://cs.chromium.org/chromium/src/chrome/browser/vr/) + * [`//components/viz/.+`](https://cs.chromium.org/chromium/src/components/viz/) + * [`//content/test/gpu/.+`](https://cs.chromium.org/chromium/src/content/test/gpu/) + * [`//gpu/.+`](https://cs.chromium.org/chromium/src/gpu/) + * [`//media/(audio|filters|gpu)/.+`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:media/(audio|filters|gpu)/) + * [`//services/viz/.+`](https://cs.chromium.org/chromium/src/services/viz/) + * [`//testing/trigger_scripts/.+`](https://cs.chromium.org/chromium/src/testing/trigger_scripts/) + * [`//third_party/blink/renderer/modules/webgl/.+`](https://cs.chromium.org/chromium/src/third_party/blink/renderer/modules/webgl/) + * [`//ui/gl/.+`](https://cs.chromium.org/chromium/src/ui/gl/) + +* [closure_compilation](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/closure_compilation) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+closure_compilation)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+closure_compilation)) + + Path regular expressions: + * [`//components/offline_pages/resources/.+`](https://cs.chromium.org/chromium/src/components/offline_pages/resources/) + * [`//third_party/closure_compiler/.+`](https://cs.chromium.org/chromium/src/third_party/closure_compiler/) + * [`//third_party/polymer/.+`](https://cs.chromium.org/chromium/src/third_party/polymer/) + +* [ios-simulator-cronet](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/ios-simulator-cronet) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+ios-simulator-cronet)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+ios-simulator-cronet)) + + Path regular expressions: + * [`//components/cronet/.+`](https://cs.chromium.org/chromium/src/components/cronet/) + * [`//components/grpc_support/.+`](https://cs.chromium.org/chromium/src/components/grpc_support/) + * [`//ios/.+`](https://cs.chromium.org/chromium/src/ios/) + +* [ios-simulator-full-configs](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/ios-simulator-full-configs) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+ios-simulator-full-configs)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+ios-simulator-full-configs)) + + Path regular expressions: + * [`//ios/.+`](https://cs.chromium.org/chromium/src/ios/) + +* [linux-blink-gen-property-trees](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux-blink-gen-property-trees) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+linux-blink-gen-property-trees)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+linux-blink-gen-property-trees)) + + Path regular expressions: + * [`//third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees) + * [`//third_party/WebKit/LayoutTests/flag-specific/enable-blink-gen-property-trees/.+`](https://cs.chromium.org/chromium/src/third_party/WebKit/LayoutTests/flag-specific/enable-blink-gen-property-trees/) + +* [linux_chromium_dbg_ng](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux_chromium_dbg_ng) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+linux_chromium_dbg_ng)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+linux_chromium_dbg_ng)) + + Path regular expressions: + * [`//build/.*check_gn_headers.*`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:build/.*check_gn_headers.*) + +* [linux_layout_tests_layout_ng](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux_layout_tests_layout_ng) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+linux_layout_tests_layout_ng)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+linux_layout_tests_layout_ng)) + + Path regular expressions: + * [`//third_party/Webkit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:third_party/Webkit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG) + * [`//third_party/Webkit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/.+`](https://cs.chromium.org/chromium/src/third_party/Webkit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/) + * [`//third_party/blink/renderer/core/editing/.+`](https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/editing/) + * [`//third_party/blink/renderer/core/(layout|paint)/ng/.+`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:third_party/blink/renderer/core/(layout|paint)/ng/) + * [`//third_party/blink/renderer/platform/fonts/shaping/.+`](https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/fonts/shaping/) + +* [linux_layout_tests_slimming_paint_v2](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux_layout_tests_slimming_paint_v2) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+linux_layout_tests_slimming_paint_v2)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+linux_layout_tests_slimming_paint_v2)) + + Path regular expressions: + * [`//third_party/WebKit/LayoutTests/FlagExpectations/(enable-slimming-paint-v2|enable-blink-gen-property-trees)`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:third_party/WebKit/LayoutTests/FlagExpectations/(enable-slimming-paint-v2|enable-blink-gen-property-trees)) + * [`//third_party/WebKit/LayoutTests/flag-specific/(enable-slimming-paint-v2|enable-blink-gen-property-trees)/.+`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:third_party/WebKit/LayoutTests/flag-specific/(enable-slimming-paint-v2|enable-blink-gen-property-trees)/) + * [`//third_party/blink/renderer/core/layout/compositing/.+`](https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/layout/compositing/) + * [`//third_party/blink/renderer/core/(svg|paint)/.+`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:third_party/blink/renderer/core/(svg|paint)/) + * [`//third_party/blink/renderer/platform/graphics/.+`](https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/graphics/) + +* [linux_mojo](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux_mojo) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+linux_mojo)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+linux_mojo)) + + Path regular expressions: + * [`//services/network/.+`](https://cs.chromium.org/chromium/src/services/network/) + * [`//testing/buildbot/filters/mojo\\.fyi\\.network_.*`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:testing/buildbot/filters/mojo\\.fyi\\.network_.*) + * [`//third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService) + +* [linux_optional_gpu_tests_rel](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux_optional_gpu_tests_rel) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+linux_optional_gpu_tests_rel)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+linux_optional_gpu_tests_rel)) + + Path regular expressions: + * [`//chrome/browser/vr/.+`](https://cs.chromium.org/chromium/src/chrome/browser/vr/) + * [`//content/test/gpu/.+`](https://cs.chromium.org/chromium/src/content/test/gpu/) + * [`//gpu/.+`](https://cs.chromium.org/chromium/src/gpu/) + * [`//media/(audio|filters|gpu)/.+`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:media/(audio|filters|gpu)/) + * [`//testing/trigger_scripts/.+`](https://cs.chromium.org/chromium/src/testing/trigger_scripts/) + * [`//third_party/blink/renderer/modules/webgl/.+`](https://cs.chromium.org/chromium/src/third_party/blink/renderer/modules/webgl/) + * [`//ui/gl/.+`](https://cs.chromium.org/chromium/src/ui/gl/) + +* [linux_vr](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux_vr) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+linux_vr)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+linux_vr)) + + Path regular expressions: + * [`//chrome/browser/vr/.+`](https://cs.chromium.org/chromium/src/chrome/browser/vr/) + +* [mac_optional_gpu_tests_rel](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/mac_optional_gpu_tests_rel) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+mac_optional_gpu_tests_rel)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+mac_optional_gpu_tests_rel)) + + Path regular expressions: + * [`//chrome/browser/vr/.+`](https://cs.chromium.org/chromium/src/chrome/browser/vr/) + * [`//content/test/gpu/.+`](https://cs.chromium.org/chromium/src/content/test/gpu/) + * [`//gpu/.+`](https://cs.chromium.org/chromium/src/gpu/) + * [`//media/(audio|filters|gpu)/.+`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:media/(audio|filters|gpu)/) + * [`//services/shape_detection/.+`](https://cs.chromium.org/chromium/src/services/shape_detection/) + * [`//testing/trigger_scripts/.+`](https://cs.chromium.org/chromium/src/testing/trigger_scripts/) + * [`//third_party/blink/renderer/modules/webgl/.+`](https://cs.chromium.org/chromium/src/third_party/blink/renderer/modules/webgl/) + * [`//ui/gl/.+`](https://cs.chromium.org/chromium/src/ui/gl/) + +* [win_optional_gpu_tests_rel](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/win_optional_gpu_tests_rel) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+win_optional_gpu_tests_rel)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+win_optional_gpu_tests_rel)) + + Path regular expressions: + * [`//chrome/browser/vr/.+`](https://cs.chromium.org/chromium/src/chrome/browser/vr/) + * [`//content/test/gpu/.+`](https://cs.chromium.org/chromium/src/content/test/gpu/) + * [`//device/vr/.+`](https://cs.chromium.org/chromium/src/device/vr/) + * [`//gpu/.+`](https://cs.chromium.org/chromium/src/gpu/) + * [`//media/(audio|filters|gpu)/.+`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:media/(audio|filters|gpu)/) + * [`//testing/trigger_scripts/.+`](https://cs.chromium.org/chromium/src/testing/trigger_scripts/) + * [`//third_party/blink/renderer/modules/vr/.+`](https://cs.chromium.org/chromium/src/third_party/blink/renderer/modules/vr/) + * [`//third_party/blink/renderer/modules/webgl/.+`](https://cs.chromium.org/chromium/src/third_party/blink/renderer/modules/webgl/) + * [`//third_party/blink/renderer/modules/xr/.+`](https://cs.chromium.org/chromium/src/third_party/blink/renderer/modules/xr/) + * [`//third_party/blink/renderer/platform/graphics/gpu/.+`](https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/graphics/gpu/) + * [`//ui/gl/.+`](https://cs.chromium.org/chromium/src/ui/gl/) + +* [linux_trusty_blink_rel](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux_trusty_blink_rel) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+linux_trusty_blink_rel)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+linux_trusty_blink_rel)) + + Path regular expressions: + * [`//cc/.+`](https://cs.chromium.org/chromium/src/cc/) + * [`//third_party/WebKit/LayoutTests/FlagExpectations/(enable-slimming-paint-v2|enable-blink-gen-property-trees)`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:third_party/WebKit/LayoutTests/FlagExpectations/(enable-slimming-paint-v2|enable-blink-gen-property-trees)) + * [`//third_party/WebKit/LayoutTests/flag-specific/(enable-slimming-paint-v2|enable-blink-gen-property-trees)/.+`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:third_party/WebKit/LayoutTests/flag-specific/(enable-slimming-paint-v2|enable-blink-gen-property-trees)/) + * [`//third_party/blink/renderer/core/layout/compositing/.+`](https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/layout/compositing/) + * [`//third_party/blink/renderer/core/(svg|paint)/.+`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:third_party/blink/renderer/core/(svg|paint)/) + * [`//third_party/blink/renderer/platform/graphics/.+`](https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/graphics/) + +* [android_compile_x64_dbg](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/android_compile_x64_dbg) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+android_compile_x64_dbg)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+android_compile_x64_dbg)) + + Path regular expressions: + * [`//sandbox/linux/(bpd_dsl|seccomp-bpf|secomp-bpf-helpers|system_headers|tests)/.+`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:sandbox/linux/(bpd_dsl|seccomp-bpf|secomp-bpf-helpers|system_headers|tests)/) + +* [android_compile_x86_dbg](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/android_compile_x86_dbg) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+android_compile_x86_dbg)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+android_compile_x86_dbg)) + + Path regular expressions: + * [`//sandbox/linux/(bpd_dsl|seccomp-bpf|secomp-bpf-helpers|system_headers|tests)/.+`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:sandbox/linux/(bpd_dsl|seccomp-bpf|secomp-bpf-helpers|system_headers|tests)/) + +* [android_cronet_tester](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/android_cronet_tester) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+android_cronet_tester)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+android_cronet_tester)) + + Path regular expressions: + * [`//components/cronet/.+`](https://cs.chromium.org/chromium/src/components/cronet/) + * [`//components/grpc_support/.+`](https://cs.chromium.org/chromium/src/components/grpc_support/) + + +## Experimental builders + +These builders are run on some percentage of builds. Their results are ignored +by CQ. These are often used to test new configurations before they are added +as required builders. + +* [ios-device](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/ios-device) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+ios-device)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+ios-device)) + + https://crbug.com/739556; make this non-experimental ASAP. + + * Experimental percentage: 10 + +* [ios-device-xcode-clang](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/ios-device-xcode-clang) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+ios-device-xcode-clang)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+ios-device-xcode-clang)) + + https://crbug.com/739556 + + * Experimental percentage: 10 + +* [ios-simulator-xcode-clang](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/ios-simulator-xcode-clang) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+ios-simulator-xcode-clang)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+ios-simulator-xcode-clang)) + + https://crbug.com/739556 + + * Experimental percentage: 10 + +* [linux-chromeos-compile-dbg](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux-chromeos-compile-dbg) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+linux-chromeos-compile-dbg)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+linux-chromeos-compile-dbg)) + + * Experimental percentage: 50 + +* [linux-dcheck-off-rel](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux-dcheck-off-rel) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+linux-dcheck-off-rel)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+linux-dcheck-off-rel)) + + https://crbug.com/833482 + + * Experimental percentage: 10 + +* [linux-goma-rbe-staging-rel](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux-goma-rbe-staging-rel) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+linux-goma-rbe-staging-rel)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+linux-goma-rbe-staging-rel)) + + https://crbug.com/855319 + + * Experimental percentage: 20 + +* [win-libfuzzer-asan-rel](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/win-libfuzzer-asan-rel) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+win-libfuzzer-asan-rel)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+win-libfuzzer-asan-rel)) + + * Experimental percentage: 100 + +* [win7_chromium_rel_loc_exp](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/win7_chromium_rel_loc_exp) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+win7_chromium_rel_loc_exp)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+win7_chromium_rel_loc_exp)) + + * Experimental percentage: 20 +
diff --git a/infra/config/PRESUBMIT.py b/infra/config/PRESUBMIT.py index e51d843..cf1e7f1 100644 --- a/infra/config/PRESUBMIT.py +++ b/infra/config/PRESUBMIT.py
@@ -3,9 +3,35 @@ # found in the LICENSE file. -def CheckChangeOnUpload(input_api, output_api): - return input_api.canned_checks.CheckChangedLUCIConfigs(input_api, output_api) +def _CheckForTranslations(input_api, output_api): + del output_api + return [] + +def _CommonChecks(input_api, output_api): + commands = [] + # TODO(martiniss): Move this check to the root presubmit. It checks to ensure + # that path regexps in cq.cfg reference something locally. + for f in input_api.AffectedFiles(): + local_path = f.LocalPath() + if local_path.endswith('cq.cfg'): + commands.append( + input_api.Command( + name='cq.cfg presubmit', cmd=[ + input_api.python_executable, 'branch/cq_cfg_presubmit.py', + '--check'], + kwargs={}, message=output_api.PresubmitError), + ) + + results = [] + + results.extend(input_api.canned_checks.CheckChangedLUCIConfigs( + input_api, output_api)) + results.extend(input_api.RunTests(commands)) + return results + +def CheckChangeOnUpload(input_api, output_api): + return _CommonChecks(input_api, output_api) def CheckChangeOnCommit(input_api, output_api): - return input_api.canned_checks.CheckChangedLUCIConfigs(input_api, output_api) + return _CommonChecks(input_api, output_api)
diff --git a/infra/config/branch/cq.cfg b/infra/config/branch/cq.cfg index 9c19999..e72daa4 100644 --- a/infra/config/branch/cq.cfg +++ b/infra/config/branch/cq.cfg
@@ -1,6 +1,27 @@ # See http://luci-config.appspot.com/schemas/projects/refs:cq.cfg for the # documentation of this file format. +# This file is also used to auto generate //docs/infra/cq_builders.md. If you +# change this file, run //infra/config/branch/cq_cfg_presubmit.py, which will +# generate that file. That script also requires that the builders in this file +# remain sorted. The script is invoked via presubmit, and will complain if this +# file is change but the documentation isn't. +# +# The auto generated file copies comments made to builders in this file. If you +# comment on the line directly above a builder, that comment will get copied to +# the documentation. +# +# The following comment will get copied. +# +# # This is a great builder! +# builders { name: "chromium_presubmit" } +# +# The following comment will not get copied. +# +# # This is a ok builder! +# +# builders { name: "chromium_presubmit" } + version: 1 cq_status_url: "https://chromium-cq-status.appspot.com" git_repo_url: "https://chromium.googlesource.com/chromium/src" @@ -30,13 +51,50 @@ try_job { buckets { name: "luci.chromium.try" - builders { name: "android_arm64_dbg_recipe" } + + ############################# + # Always required builders. # + ############################# + builders { name: "android-binary-size" } + builders { name: "android-kitkat-arm-rel" } + builders { name: "android-marshmallow-arm64-rel" } + builders { name: "android_arm64_dbg_recipe" } builders { name: "android_clang_dbg_recipe" } builders { name: "android_compile_dbg" } builders { name: "android_cronet" } - builders { name: "android-kitkat-arm-rel" } - builders { name: "android-marshmallow-arm64-rel" } + builders { name: "cast_shell_android" } + builders { name: "cast_shell_linux" } + builders { name: "chromeos-amd64-generic-rel" } + builders { name: "chromeos-daisy-rel" } + builders { + name: "chromium_presubmit" + # Presubmit builder should be re-run every time CQ is triggered + # for last minute lint, OWNERS, etc checks. + disable_reuse: true + } + builders { name: "fuchsia_arm64" } + builders { name: "fuchsia_x64" } + builders { name: "ios-simulator" } + builders { name: "linux-chromeos-rel" } + builders { name: "linux-jumbo-rel" } + builders { name: "linux-libfuzzer-asan-rel" } + builders { name: "linux-ozone-rel" } + builders { name: "linux_chromium_asan_rel_ng" } + builders { name: "linux_chromium_compile_dbg_ng" } + builders { name: "linux_chromium_headless_rel" } + builders { name: "linux_chromium_rel_ng" } + builders { name: "linux_chromium_tsan_rel_ng" } + builders { name: "mac_chromium_compile_dbg_ng" } + builders { name: "mac_chromium_rel_ng" } + builders { name: "win10_chromium_x64_rel_ng" } + builders { name: "win7_chromium_rel_ng"} + builders { name: "win_chromium_compile_dbg_ng" } + + ###################### + # Optional builders. # + ###################### + builders { name: "android_optional_gpu_tests_rel" path_regexp: "cc/.+" @@ -50,35 +108,12 @@ path_regexp: "third_party/blink/renderer/modules/webgl/.+" path_regexp: "ui/gl/.+" } - builders { name: "cast_shell_android" } - builders { name: "cast_shell_linux" } - builders { name: "chromeos-amd64-generic-rel" } - builders { name: "chromeos-daisy-rel" } - builders { - name: "chromium_presubmit" - # Presubmit builder should be re-run every time CQ is triggered - # for last minute lint, OWNERS, etc checks. - disable_reuse: true - } builders { name: "closure_compilation" path_regexp: "components/offline_pages/resources/.+" path_regexp: "third_party/closure_compiler/.+" path_regexp: "third_party/polymer/.+" } - builders { name: "fuchsia_arm64" } - builders { name: "fuchsia_x64" } - # https://crbug.com/739556; make this non-experimental ASAP. - builders { - name: "ios-device" - experiment_percentage: 10 - } - # https://crbug.com/739556 - builders { - name: "ios-device-xcode-clang" - experiment_percentage: 10 - } - builders { name: "ios-simulator" } builders { name: "ios-simulator-cronet" path_regexp: "components/cronet/.+" @@ -90,41 +125,15 @@ name: "ios-simulator-full-configs" path_regexp: "ios/.+" } - # https://crbug.com/739556 - builders { - name: "ios-simulator-xcode-clang" - experiment_percentage: 10 - } builders { name: "linux-blink-gen-property-trees" path_regexp: "third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees" path_regexp: "third_party/WebKit/LayoutTests/flag-specific/enable-blink-gen-property-trees/.+" } - builders { name: "linux-chromeos-rel" } - builders { - name: "linux-chromeos-compile-dbg" - experiment_percentage: 50 - } - builders { name: "linux_chromium_asan_rel_ng" } - builders { name: "linux_chromium_compile_dbg_ng" } builders { name: "linux_chromium_dbg_ng" path_regexp: "build/.*check_gn_headers.*" } - builders { name: "linux_chromium_headless_rel" } - builders { name: "linux_chromium_rel_ng" } - builders { name: "linux_chromium_tsan_rel_ng" } - # https://crbug.com/833482 - builders { - name: "linux-dcheck-off-rel" - experiment_percentage: 10 - } - # https://crbug.com/855319 - builders { - name: "linux-goma-rbe-staging-rel" - experiment_percentage: 20 - } - builders { name: "linux-jumbo-rel" } builders { name: "linux_layout_tests_layout_ng" path_regexp: "third_party/Webkit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG" @@ -141,14 +150,12 @@ path_regexp: "third_party/blink/renderer/core/(svg|paint)/.+" path_regexp: "third_party/blink/renderer/platform/graphics/.+" } - builders { name: "linux-libfuzzer-asan-rel" } builders { name: "linux_mojo" path_regexp: "services/network/.+" path_regexp: "testing/buildbot/filters/mojo\\.fyi\\.network_.*" path_regexp: "third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService" } - builders { name: "linux-ozone-rel" } builders { name: "linux_optional_gpu_tests_rel" path_regexp: "chrome/browser/vr/.+" @@ -163,8 +170,6 @@ name: "linux_vr" path_regexp: "chrome/browser/vr/.+" } - builders { name: "mac_chromium_compile_dbg_ng" } - builders { name: "mac_chromium_rel_ng" } builders { name: "mac_optional_gpu_tests_rel" path_regexp: "chrome/browser/vr/.+" @@ -177,17 +182,6 @@ path_regexp: "ui/gl/.+" } builders { - name: "win-libfuzzer-asan-rel" - experiment_percentage: 100 - } - builders { name: "win10_chromium_x64_rel_ng" } - builders { - name: "win7_chromium_rel_loc_exp" - experiment_percentage: 20 - } - builders { name: "win7_chromium_rel_ng"} - builders { name: "win_chromium_compile_dbg_ng" } - builders { name: "win_optional_gpu_tests_rel" path_regexp: "chrome/browser/vr/.+" path_regexp: "content/test/gpu/.+" @@ -201,6 +195,48 @@ path_regexp: "third_party/blink/renderer/platform/graphics/gpu/.+" path_regexp: "ui/gl/.+" } + + ########################## + # Experimental builders. # + ########################## + + # https://crbug.com/739556; make this non-experimental ASAP. + builders { + name: "ios-device" + experiment_percentage: 10 + } + # https://crbug.com/739556 + builders { + name: "ios-device-xcode-clang" + experiment_percentage: 10 + } + # https://crbug.com/739556 + builders { + name: "ios-simulator-xcode-clang" + experiment_percentage: 10 + } + builders { + name: "linux-chromeos-compile-dbg" + experiment_percentage: 50 + } + # https://crbug.com/833482 + builders { + name: "linux-dcheck-off-rel" + experiment_percentage: 10 + } + # https://crbug.com/855319 + builders { + name: "linux-goma-rbe-staging-rel" + experiment_percentage: 20 + } + builders { + name: "win-libfuzzer-asan-rel" + experiment_percentage: 100 + } + builders { + name: "win7_chromium_rel_loc_exp" + experiment_percentage: 20 + } } buckets {
diff --git a/infra/config/branch/cq_cfg_presubmit.py b/infra/config/branch/cq_cfg_presubmit.py new file mode 100755 index 0000000..9d2fe21 --- /dev/null +++ b/infra/config/branch/cq_cfg_presubmit.py
@@ -0,0 +1,310 @@ +#!/usr/bin/env python +# Copyright (c) 2018 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import argparse +import difflib +import os +import string +import sys + + +# Path to the root of the current chromium checkout. +CHROMIUM_DIR = os.path.abspath(os.path.join( + os.path.dirname(__file__), '..', '..', '..')) + + +MD_HEADER = """# List of CQ builders + +This page is auto generated using the script +//infra/config/branch/cq_config_presubmit.py. Do not manually edit. + +[TOC] + +Each builder name links to that builder on Milo. The "Backing builders" links +point to the file used to determine which configurations a builder should copy +when running. These links might 404 or error; they are hard-coded right now, +using common assumptions about how builders are configured. +""" + + +REQUIRED_HEADER = """ +These builders must pass before a CL may land.""" + + +OPTIONAL_HEADER = """These builders optionally run, depending on the files in a +CL. For example, a CL which touches `//gpu/BUILD.gn` would trigger the builder +`android_optional_gpu_tests_rel`, due to the `path_regexp` values for that +builder.""" + + +EXPERIMENTAL_HEADER = """ +These builders are run on some percentage of builds. Their results are ignored +by CQ. These are often used to test new configurations before they are added +as required builders.""" + + +BUILDER_VIEW_URL = ( + 'https://ci.chromium.org/p/chromium/builders/luci.chromium.try/') + + +CODE_SEARCH_BASE = 'https://cs.chromium.org/' + + +TRYBOT_SOURCE_URL = CODE_SEARCH_BASE + 'search/?q=file:trybots.py+' + + +CQ_CONFIG_LOCATION_URL = ( + CODE_SEARCH_BASE + 'search/?q=package:%5Echromium$+file:cq.cfg+') + + +REGEX_SEARCH_URL = CODE_SEARCH_BASE + 'search/?q=package:%5Echromium$+' + + +def parse_text_proto_message(lines): + """Parses a text proto. LOW QUALITY, MAY EASILY BREAK. + + If you really need to parse text protos, use the actual python library for + protobufs. This exists because the .proto file for cq.cfg lives in another + repository. + """ + data = {} + + linenum = 0 + # Tracks the current comment. Gets cleared if there's a blank line. Is added + # to submessages, to allow for builders to contain comments. + current_comment = None + while linenum < len(lines): + line = lines[linenum].strip() + if not line: + current_comment = None + linenum += 1 + elif line.startswith('#'): + if current_comment: + current_comment += '\n' + line[1:] + else: + current_comment = line[1:] + linenum += 1 + elif '{' in line: + # Sub message. Put before the ':' clause so that it correctly handles one + # line messages. + end = linenum + count = 0 + newlines = [] + while end < len(lines): + inner_line = lines[end] + if '{' in inner_line: + count += 1 + if '}' in inner_line: + count -= 1 + + if end == linenum: + newline = inner_line.split('{', 1)[1] + if count == 0: + newline = newline.split('}')[0] + newlines.append(newline) + elif count == 0: + newlines.append(inner_line.split('}')[0]) + else: + newlines.append(inner_line) + end += 1 + if count == 0: + break + name = line.split('{')[0].strip() + value = parse_text_proto_message(newlines) + if current_comment: + value['comment'] = current_comment + current_comment = None + + if name in data: + data[name].append(value) + else: + data[name] = [value] + linenum = end + elif ':' in line: + # It's a field + name, value = line.split(':', 1) + value = value.strip() + if value.startswith('"'): + value = value.strip('"') + + if name in data: + data[name].append(value) + else: + data[name] = [value] + linenum += 1 + else: + raise ValueError('Invalid line (number %d):\n%s' % (linenum, line)) + + return data + + +class BuilderList(object): + def __init__(self, builders): + self.builders = builders + + def sort(self): + """Sorts the builder list. + + Sorts the builders in place. Orders them into three groups: experimental, + required, and optional.""" + self.builders.sort(key=lambda b: '%s|%s|%s' % ( + 'z' if b.get('experiment_percentage') else 'a', + 'z' if b.get('path_regexp') else 'a', + b['name'])) + + def by_section(self): + required = [] + experimental = [] + optional = [] + for b in self.builders: + # Don't handle if something is both optional and experimental + if b.get('path_regexp'): + optional.append(b) + elif b.get('experiment_percentage'): + experimental.append(b) + else: + required.append(b) + + return required, optional, experimental + + +class CQConfig(object): + def __init__(self, lines): + self._value = parse_text_proto_message(lines) + + @staticmethod + def from_file(path): + with open(path) as f: + lines = f.readlines() + + return CQConfig(lines) + + @property + def version(self): + return int(self._value['version'][0]) + + def builder_list(self, pred=None): + """Returns a list of builders. + + pred is a predicate used to decide if a builder should be returned. It takes + the bucket and builder as arguments.""" + items = [] + for bucket in ( + self._value['verifiers'][0]['try_job'][0]['buckets']): + for b in bucket['builders']: + if pred and not pred(bucket, b): + continue + items.append(b) + return BuilderList(items) + + def get_markdown_doc(self): + lines = [] + for l in MD_HEADER.split('\n'): + lines.append(l) + + bl = self.builder_list() + req, opt, exp = bl.by_section() + for title, header, builders in ( + ('Required builders', REQUIRED_HEADER, req), + ('Optional builders', OPTIONAL_HEADER, opt), + ('Experimental builders', EXPERIMENTAL_HEADER, exp), + ): + lines.append('## %s' % title) + lines.append('') + for l in header.strip().split('\n'): + lines.append(l) + lines.append('') + for b in builders: + lines.append( + '* [%s](%s) ([`cq.cfg` entry](%s)) ([matching builders](%s))' % ( + b['name'][0], BUILDER_VIEW_URL + b['name'][0], + CQ_CONFIG_LOCATION_URL + b['name'][0], + TRYBOT_SOURCE_URL + b['name'][0],)) + lines.append('') + if 'comment' in b: + for l in b['comment'].split('\n'): + lines.append(' ' + l.strip()) + lines.append('') + if 'path_regexp' in b: + lines.append(' Path regular expressions:') + for regex in b['path_regexp']: + regex_title = '//' + regex.lstrip('/') + url = None + if regex.endswith('.+'): + regex = regex[:-len('.+')] + if all( + # Equals sign and dashes used by layout tests. + c in string.ascii_letters + string.digits + '/-_=' + for c in regex): + # Assume the regex is targeting a single path, direct link to + # it. Check to make sure we don't have weird characters, like + # ()|, which could mean it's a regex. + url = CODE_SEARCH_BASE + 'chromium/src/' + regex + lines.append(' * [`%s`](%s)' % ( + regex_title, url or REGEX_SEARCH_URL + 'file:' + regex)) + lines.append('') + if 'experiment_percentage' in b: + lines.append(' * Experimental percentage: %s' % ( + b['experiment_percentage'][0])) + lines.append('') + lines.append('') + + return '\n'.join(lines) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + '-c', '--check', action='store_true', help= + 'Do consistency checks of cq.cfg and generated files. Used during' + 'presubmit. Causes the tool to not generate any files.') + args = parser.parse_args() + + exit_code = 0 + + cfg = CQConfig.from_file(os.path.join( + CHROMIUM_DIR, 'infra', 'config', 'branch', 'cq.cfg')) + if cfg.version != 1: + raise ValueError("Expected version 1, got %r" % cfg.version) + + # Only force sorting on luci.chromium.try builders. Others should go away soon + # anyways... + bl = cfg.builder_list(lambda bucket, builder: bucket == 'luci.chromium.try') + names = [b['name'][0] for b in bl.builders] + bl.sort() # Changes the bl, so the next line is sorted. + sorted_names = [b['name'][0] for b in bl.builders] + if sorted_names != names: + print 'ERROR: cq.cfg is unsorted.', + if args.check: + print + else: + print ' Please sort as follows:' + for line in difflib.unified_diff( + names, + sorted_names, fromfile='current', tofile='sorted'): + print line + exit_code = 1 + + if args.check: + # TODO(martiniss): Add a check for path_regexp, to make sure they're valid + # paths. + with open(os.path.join( + CHROMIUM_DIR, 'docs', 'infra', 'cq_builders.md')) as f: + if cfg.get_markdown_doc() != f.read(): + print ( + 'Markdown file is out of date. Please run ' + '`//infra/config/branch/cq_cfg_presubmit.py to regenerate the ' + 'docs.') + exit_code = 1 + else: + with open(os.path.join( + CHROMIUM_DIR, 'docs', 'infra', 'cq_builders.md'), 'w') as f: + f.write(cfg.get_markdown_doc()) + + return exit_code + + +if __name__ == '__main__': + sys.exit(main())
diff --git a/infra/config/global/luci-scheduler-dev.cfg b/infra/config/global/luci-scheduler-dev.cfg index aa26630..4616dd00 100644 --- a/infra/config/global/luci-scheduler-dev.cfg +++ b/infra/config/global/luci-scheduler-dev.cfg
@@ -109,3 +109,21 @@ # TODO(smut): Adjust frequency. schedule: "with 300s interval" } + +job { + # One trigger/schedule for each DUT pool to regularly flash. + id: "cros-dut-flash-scheduler-kevin" + acl_sets: "default" + # Run this early in MTV's morning (ie: UTC's late morning). + schedule: "0 10 * * * " + buildbucket: { + server: "cr-buildbucket-dev.appspot.com" + bucket: "luci.chromium.ci" + builder: "cros-dut-flash-scheduler" + # All the properties needed to specify a single DUT pool. + properties: "swarming_server:chromium-swarm-dev.appspot.com" + properties: "swarming_pool:luci.chromium.ci" + properties: "device_type:kevin" + properties: "bb_host:cr-buildbucket-dev.appspot.com" + } +}
diff --git a/ios/chrome/browser/tabs/BUILD.gn b/ios/chrome/browser/tabs/BUILD.gn index 124e8eb..c75639d8 100644 --- a/ios/chrome/browser/tabs/BUILD.gn +++ b/ios/chrome/browser/tabs/BUILD.gn
@@ -197,6 +197,7 @@ "//ios/web/public/test", "//ios/web/public/test/fakes", "//ios/web/test/fakes:fakes", + "//ios/web/web_state:navigation_context", "//net", "//testing/gmock", "//testing/gtest",
diff --git a/ios/chrome/browser/tabs/DEPS b/ios/chrome/browser/tabs/DEPS index 6787c46..0b437c3d 100644 --- a/ios/chrome/browser/tabs/DEPS +++ b/ios/chrome/browser/tabs/DEPS
@@ -7,6 +7,7 @@ ], "^tab_unittest\.mm$": [ "+ios/web/web_state/ui/crw_web_controller.h", + "+ios/web/web_state/navigation_context_impl.h", "+ios/web/navigation/navigation_manager_impl.h", "+ios/web/web_state/web_state_impl.h", "+ios/web/test/fakes/crw_fake_back_forward_list.h",
diff --git a/ios/chrome/browser/tabs/tab_unittest.mm b/ios/chrome/browser/tabs/tab_unittest.mm index 67f6373a..b58b46d5 100644 --- a/ios/chrome/browser/tabs/tab_unittest.mm +++ b/ios/chrome/browser/tabs/tab_unittest.mm
@@ -48,6 +48,7 @@ #import "ios/web/public/test/fakes/fake_navigation_context.h" #include "ios/web/public/test/test_web_thread_bundle.h" #import "ios/web/test/fakes/crw_fake_back_forward_list.h" +#import "ios/web/web_state/navigation_context_impl.h" #import "ios/web/web_state/ui/crw_web_controller.h" #import "ios/web/web_state/web_state_impl.h" #import "net/base/mac/url_conversions.h" @@ -237,9 +238,13 @@ NSString* title) { DCHECK_EQ(tab_.webState, web_state_impl_.get()); - web::FakeNavigationContext context1; - context1.SetUrl(user_url); - web_state_impl_->OnNavigationStarted(&context1); + std::unique_ptr<web::NavigationContextImpl> context1 = + web::NavigationContextImpl::CreateNavigationContext( + web_state_impl_.get(), user_url, + /*has_user_gesture=*/true, + ui::PageTransition::PAGE_TRANSITION_AUTO_BOOKMARK, + /*is_renderer_initiated=*/true); + web_state_impl_->OnNavigationStarted(context1.get()); web::Referrer empty_referrer; web_state_impl_->GetNavigationManagerImpl().AddPendingItem( @@ -247,9 +252,13 @@ web::NavigationInitiationType::RENDERER_INITIATED, web::NavigationManager::UserAgentOverrideOption::INHERIT); - web::FakeNavigationContext context2; - context2.SetUrl(redirect_url); - web_state_impl_->OnNavigationStarted(&context2); + std::unique_ptr<web::NavigationContextImpl> context2 = + web::NavigationContextImpl::CreateNavigationContext( + web_state_impl_.get(), redirect_url, + /*has_user_gesture=*/true, + ui::PageTransition::PAGE_TRANSITION_AUTO_BOOKMARK, + /*is_renderer_initiated=*/true); + web_state_impl_->OnNavigationStarted(context2.get()); if (GetParam() == NavigationManagerChoice::WK_BASED) { [fake_wk_list_ @@ -257,9 +266,9 @@ } web_state_impl_->GetNavigationManagerImpl().CommitPendingItem(); - context2.SetHasCommitted(true); + context2->SetHasCommitted(true); web_state_impl_->UpdateHttpResponseHeaders(redirect_url); - web_state_impl_->OnNavigationFinished(&context2); + web_state_impl_->OnNavigationFinished(context2.get()); web_state_impl_->SetIsLoading(true); base::string16 new_title = base::SysNSStringToUTF16(title);
diff --git a/ios/chrome/browser/ui/BUILD.gn b/ios/chrome/browser/ui/BUILD.gn index 332de7cf..2ce5acc 100644 --- a/ios/chrome/browser/ui/BUILD.gn +++ b/ios/chrome/browser/ui/BUILD.gn
@@ -311,7 +311,6 @@ "//ios/chrome/browser/ui/activity_services/requirements", "//ios/chrome/browser/ui/alert_coordinator", "//ios/chrome/browser/ui/app_launcher", - "//ios/chrome/browser/ui/authentication/consent_bump", "//ios/chrome/browser/ui/autofill:autofill", "//ios/chrome/browser/ui/autofill/manual_fill", "//ios/chrome/browser/ui/bookmarks", @@ -354,7 +353,6 @@ "//ios/chrome/browser/ui/print", "//ios/chrome/browser/ui/qr_scanner:coordinator", "//ios/chrome/browser/ui/reading_list", - "//ios/chrome/browser/ui/recent_tabs", "//ios/chrome/browser/ui/sad_tab", "//ios/chrome/browser/ui/sad_tab:coordinator", "//ios/chrome/browser/ui/sad_tab:features",
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_accessory_view_controller.mm b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_accessory_view_controller.mm index c84d0c8..a3edfa79 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_accessory_view_controller.mm +++ b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_accessory_view_controller.mm
@@ -39,7 +39,7 @@ } // namespace -static NSTimeInterval MFAnimationDuration = 0.20; +static NSTimeInterval MFAnimationDuration = 0; @interface ManualFillAccessoryViewController ()
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm index 98917ab..eabe70e7 100644 --- a/ios/chrome/browser/ui/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -113,8 +113,6 @@ #import "ios/chrome/browser/ui/alert_coordinator/alert_coordinator.h" #import "ios/chrome/browser/ui/alert_coordinator/repost_form_coordinator.h" #import "ios/chrome/browser/ui/app_launcher/app_launcher_coordinator.h" -#import "ios/chrome/browser/ui/authentication/consent_bump/consent_bump_coordinator.h" -#import "ios/chrome/browser/ui/authentication/consent_bump/consent_bump_coordinator_delegate.h" #import "ios/chrome/browser/ui/autofill/manual_fill/password_coordinator.h" #import "ios/chrome/browser/ui/background_generator.h" #import "ios/chrome/browser/ui/bookmarks/bookmark_interaction_controller.h" @@ -175,9 +173,7 @@ #import "ios/chrome/browser/ui/presenters/vertical_animation_container.h" #import "ios/chrome/browser/ui/print/print_controller.h" #import "ios/chrome/browser/ui/reading_list/offline_page_native_content.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_coordinator.h" #import "ios/chrome/browser/ui/reading_list/reading_list_menu_notifier.h" -#import "ios/chrome/browser/ui/recent_tabs/recent_tabs_coordinator.h" #include "ios/chrome/browser/ui/sad_tab/features.h" #import "ios/chrome/browser/ui/sad_tab/sad_tab_coordinator.h" #import "ios/chrome/browser/ui/sad_tab/sad_tab_legacy_coordinator.h" @@ -415,7 +411,6 @@ @interface BrowserViewController ()<ActivityServicePresentation, BubblePresenterDelegate, CaptivePortalDetectorTabHelperDelegate, - ConsentBumpCoordinatorDelegate, CRWNativeContentProvider, CRWWebStateDelegate, DialogPresenterDelegate, @@ -479,9 +474,6 @@ // Used to display the Voice Search UI. Nil if not visible. scoped_refptr<VoiceSearchController> _voiceSearchController; - // Used to display the Reading List. - ChromeCoordinator* _readingListCoordinator; - // Used to display the Find In Page UI. Nil if not visible. FindBarControllerIOS* _findBarController; @@ -627,8 +619,6 @@ // for the presentation of a new tab. Can be used to record performance metrics. @property(nonatomic, strong, nullable) ProceduralBlock foregroundTabWasAddedCompletionBlock; -// Coordinator for Recent Tabs. -@property(nonatomic, strong) ChromeCoordinator* recentTabsCoordinator; // Coordinator for tablet tab strip. @property(nonatomic, strong) TabStripLegacyCoordinator* tabStripCoordinator; // Coordinator for Infobars. @@ -697,9 +687,6 @@ // Whether the safe area insets should be used to adjust the viewport. @property(nonatomic, readonly) BOOL usesSafeInsetsForViewportAdjustments; -// Coordinator to ask the user for the new consent. -@property(nonatomic, strong) ConsentBumpCoordinator* consentBumpCoordinator; - // BVC initialization // ------------------ // If the BVC is initialized with a valid browser state & tab model immediately, @@ -848,13 +835,6 @@ // Adds the given url to the reading list. - (void)addToReadingListURL:(const GURL&)URL title:(NSString*)title; -// Recent Tabs -// ------------ -// Creates the right RecentTabs Coordinator, once we stop supporting the legacy -// implementation we can delete this method and start the coordinator on -// |showRecentTabs|. -- (void)createRecentTabsCoordinator; - @end @implementation BrowserViewController @@ -871,7 +851,6 @@ @synthesize activityOverlayCoordinator = _activityOverlayCoordinator; @synthesize foregroundTabWasAddedCompletionBlock = _foregroundTabWasAddedCompletionBlock; -@synthesize recentTabsCoordinator = _recentTabsCoordinator; @synthesize tabStripCoordinator = _tabStripCoordinator; @synthesize tabStripView = _tabStripView; @synthesize popupMenuCoordinator = _popupMenuCoordinator; @@ -895,7 +874,6 @@ // DialogPresenterDelegate property @synthesize dialogPresenterDelegateIsPresenting = _dialogPresenterDelegateIsPresenting; -@synthesize consentBumpCoordinator = _consentBumpCoordinator; #pragma mark - Object lifecycle @@ -1780,8 +1758,6 @@ self.typingShield = nil; if (_voiceSearchController) _voiceSearchController->SetDispatcher(nil); - _readingListCoordinator = nil; - self.recentTabsCoordinator = nil; self.primaryToolbarCoordinator = nil; self.secondaryToolbarContainerCoordinator = nil; self.secondaryToolbarCoordinator = nil; @@ -3019,17 +2995,6 @@ IDS_IOS_READING_LIST_SNACKBAR_MESSAGE)]; } -#pragma mark - Private Methods: Recent Tabs - -- (void)createRecentTabsCoordinator { - RecentTabsCoordinator* recentTabsCoordinator = - [[RecentTabsCoordinator alloc] initWithBaseViewController:self - browserState:_browserState]; - recentTabsCoordinator.loader = self; - recentTabsCoordinator.dispatcher = self.dispatcher; - self.recentTabsCoordinator = recentTabsCoordinator; -} - #pragma mark - ** Protocol Implementations and Helpers ** #pragma mark - BubblePresenterDelegate @@ -4484,14 +4449,6 @@ [self addToReadingListURL:[command URL] title:[command title]]; } -- (void)showReadingList { - _readingListCoordinator = [[ReadingListCoordinator alloc] - initWithBaseViewController:self - browserState:self.browserState - loader:self]; - [_readingListCoordinator start]; -} - - (void)preloadVoiceSearch { // Preload VoiceSearchController and views and view controllers needed // for voice search. @@ -4614,24 +4571,6 @@ [_bookmarkInteractionController presentBookmarks]; } -- (void)showRecentTabs { - // TODO(crbug.com/825431): If BVC's clearPresentedState is ever called (such - // as in tearDown after a failed egtest), then this coordinator is left in a - // started state even though its corresponding VC is no longer on screen. - // That causes issues when the coordinator is started again and we destroy the - // old mediator without disconnecting it first. Temporarily work around these - // issues by not having a long lived coordinator. A longer-term solution will - // require finding a way to stop this coordinator so that the mediator is - // properly disconnected and destroyed and does not live longer than its - // associated VC. - if (self.recentTabsCoordinator) { - [self.recentTabsCoordinator stop]; - self.recentTabsCoordinator = nil; - } - [self createRecentTabsCoordinator]; - [self.recentTabsCoordinator start]; -} - - (void)requestDesktopSite { if (self.userAgentType != web::UserAgentType::MOBILE) return; @@ -4694,24 +4633,6 @@ } } -- (void)showConsentBumpIfNeeded { - DCHECK(!self.consentBumpCoordinator); - if (![ConsentBumpCoordinator - shouldShowConsentBumpWithBrowserState:_browserState]) { - return; - } - self.consentBumpCoordinator = - [[ConsentBumpCoordinator alloc] initWithBaseViewController:self - browserState:_browserState]; - self.consentBumpCoordinator.delegate = self; - [self.consentBumpCoordinator start]; - self.consentBumpCoordinator.viewController.modalPresentationStyle = - UIModalPresentationFormSheet; - [self presentViewController:self.consentBumpCoordinator.viewController - animated:YES - completion:nil]; -} - - (void)focusFakebox { id nativeController = [self nativeControllerForTab:self.tabModel.currentTab]; DCHECK([nativeController conformsToProtocol:@protocol(NewTabPageOwning)]); @@ -5437,23 +5358,6 @@ [self.dispatcher showSyncPassphraseSettingsFromViewController:self]; } -#pragma mark - ConsentBumpCoordinatorDelegate - -- (void)consentBumpCoordinator:(ConsentBumpCoordinator*)coordinator - didFinishNeedingToShowSettings:(BOOL)shouldShowSettings { - DCHECK(self.consentBumpCoordinator); - DCHECK(self.consentBumpCoordinator.viewController); - auto completion = ^{ - if (shouldShowSettings) { - [self.dispatcher showGoogleServicesSettingsFromViewController:self]; - } - }; - [self.consentBumpCoordinator.viewController - dismissViewControllerAnimated:YES - completion:completion]; - self.consentBumpCoordinator = nil; -} - #pragma mark - NewTabPageTabHelperDelegate - (void)newTabPageHelperDidChangeVisibility:(NewTabPageTabHelper*)NTPHelper
diff --git a/ios/chrome/browser/ui/commands/BUILD.gn b/ios/chrome/browser/ui/commands/BUILD.gn index 8076e435..1cc1670 100644 --- a/ios/chrome/browser/ui/commands/BUILD.gn +++ b/ios/chrome/browser/ui/commands/BUILD.gn
@@ -8,6 +8,7 @@ "activity_service_commands.h", "application_commands.h", "browser_commands.h", + "browser_coordinator_commands.h", "browsing_data_commands.h", "command_dispatcher.h", "command_dispatcher.mm",
diff --git a/ios/chrome/browser/ui/commands/browser_commands.h b/ios/chrome/browser/ui/commands/browser_commands.h index bf10a63..141eaae2 100644 --- a/ios/chrome/browser/ui/commands/browser_commands.h +++ b/ios/chrome/browser/ui/commands/browser_commands.h
@@ -8,6 +8,7 @@ #import <Foundation/Foundation.h> #import "ios/chrome/browser/ui/commands/activity_service_commands.h" +#import "ios/chrome/browser/ui/commands/browser_coordinator_commands.h" #import "ios/chrome/browser/ui/commands/page_info_commands.h" #import "ios/chrome/browser/ui/commands/popup_menu_commands.h" #import "ios/chrome/browser/ui/commands/qr_scanner_commands.h" @@ -19,8 +20,11 @@ // Protocol for commands that will generally be handled by the "current tab", // which in practice is the BrowserViewController instance displaying the tab. +// TODO(crbug.com/906662) : Extract BrowserCoordinatorCommands from +// BrowserCommands. @protocol BrowserCommands<NSObject, ActivityServiceCommands, + BrowserCoordinatorCommands, PageInfoCommands, PopupMenuCommands, QRScannerCommands, @@ -50,9 +54,6 @@ // Adds a page to the reading list using data in |command|. - (void)addToReadingList:(ReadingListAddCommand*)command; -// Shows the Reading List UI. -- (void)showReadingList; - // Preloads voice search on the current BVC. - (void)preloadVoiceSearch; @@ -86,9 +87,6 @@ // Shows the bookmarks manager. - (void)showBookmarksManager; -// Shows recent tabs. -- (void)showRecentTabs; - // Requests the "desktop" version of the current page in the active tab. - (void)requestDesktopSite; @@ -102,9 +100,6 @@ // Prepares the browser to display a popup menu. - (void)prepareForPopupMenuPresentation:(PopupMenuCommandType)type; -// Shows the consent bump if it is required. -- (void)showConsentBumpIfNeeded; - // Animates the NTP fakebox to the focused position and focuses the real // omnibox. - (void)focusFakebox;
diff --git a/ios/chrome/browser/ui/commands/browser_coordinator_commands.h b/ios/chrome/browser/ui/commands/browser_coordinator_commands.h new file mode 100644 index 0000000..a636167a70 --- /dev/null +++ b/ios/chrome/browser/ui/commands/browser_coordinator_commands.h
@@ -0,0 +1,26 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_COMMANDS_BROWSER_COORDINATOR_COMMANDS_H_ +#define IOS_CHROME_BROWSER_UI_COMMANDS_BROWSER_COORDINATOR_COMMANDS_H_ + +#import <Foundation/Foundation.h> + +// Protocol for commands that will be handled by the BrowserCoordinator. +// TODO(crbug.com/906662) : Rename this protocol to one that is more descriptive +// and representative of the contents. +@protocol BrowserCoordinatorCommands + +// Shows the consent bump if it is required. +- (void)showConsentBumpIfNeeded; + +// Shows the Reading List UI. +- (void)showReadingList; + +// Shows recent tabs. +- (void)showRecentTabs; + +@end + +#endif // IOS_CHROME_BROWSER_UI_COMMANDS_BROWSER_COORDINATOR_COMMANDS_H_
diff --git a/ios/chrome/browser/ui/main/BUILD.gn b/ios/chrome/browser/ui/main/BUILD.gn index 7327f287..7ca2843 100644 --- a/ios/chrome/browser/ui/main/BUILD.gn +++ b/ios/chrome/browser/ui/main/BUILD.gn
@@ -27,10 +27,13 @@ "//ios/chrome/browser/sessions:serialisation", "//ios/chrome/browser/tabs", "//ios/chrome/browser/tabs:tabs_internal", + "//ios/chrome/browser/ui/authentication/consent_bump", "//ios/chrome/browser/ui/autofill", "//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/coordinators:chrome_coordinators", "//ios/chrome/browser/ui/qr_scanner:coordinator", + "//ios/chrome/browser/ui/reading_list", + "//ios/chrome/browser/ui/recent_tabs", "//ios/chrome/browser/ui/snackbar", "//ios/public/provider/chrome/browser", ]
diff --git a/ios/chrome/browser/ui/main/browser_coordinator.mm b/ios/chrome/browser/ui/main/browser_coordinator.mm index 272aaf7c..07902c8 100644 --- a/ios/chrome/browser/ui/main/browser_coordinator.mm +++ b/ios/chrome/browser/ui/main/browser_coordinator.mm
@@ -4,19 +4,25 @@ #import "ios/chrome/browser/ui/main/browser_coordinator.h" +#import "ios/chrome/browser/ui/authentication/consent_bump/consent_bump_coordinator.h" +#import "ios/chrome/browser/ui/authentication/consent_bump/consent_bump_coordinator_delegate.h" #import "ios/chrome/browser/ui/autofill/form_input_accessory_coordinator.h" #import "ios/chrome/browser/ui/browser_view_controller.h" #import "ios/chrome/browser/ui/browser_view_controller_dependency_factory.h" #import "ios/chrome/browser/ui/commands/application_commands.h" +#import "ios/chrome/browser/ui/commands/browser_coordinator_commands.h" #import "ios/chrome/browser/ui/commands/command_dispatcher.h" #import "ios/chrome/browser/ui/qr_scanner/qr_scanner_legacy_coordinator.h" +#import "ios/chrome/browser/ui/reading_list/reading_list_coordinator.h" +#import "ios/chrome/browser/ui/recent_tabs/recent_tabs_coordinator.h" #import "ios/chrome/browser/ui/snackbar/snackbar_coordinator.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif -@interface BrowserCoordinator ()<FormInputAccessoryCoordinatorDelegate> +@interface BrowserCoordinator ()<ConsentBumpCoordinatorDelegate, + FormInputAccessoryCoordinatorDelegate> // Handles command dispatching. @property(nonatomic, strong) CommandDispatcher* dispatcher; @@ -25,25 +31,37 @@ // Child Coordinators, listed in alphabetical order. // ================================================= +// Coordinator to ask the user for the new consent. +@property(nonatomic, strong) ConsentBumpCoordinator* consentBumpCoordinator; + // Coordinator in charge of the presenting autofill options above the // keyboard. @property(nonatomic, strong) FormInputAccessoryCoordinator* formInputAccessoryCoordinator; -// Coordinator for displaying snackbars. -@property(nonatomic, strong) SnackbarCoordinator* snackbarCoordinator; - // Coordinator for the QR scanner. @property(nonatomic, strong) QRScannerLegacyCoordinator* qrScannerCoordinator; +// Coordinator for displaying the Reading List. +@property(nonatomic, strong) ReadingListCoordinator* readingListCoordinator; + +// Coordinator for Recent Tabs. +@property(nonatomic, strong) RecentTabsCoordinator* recentTabsCoordinator; + +// Coordinator for displaying snackbars. +@property(nonatomic, strong) SnackbarCoordinator* snackbarCoordinator; + @end @implementation BrowserCoordinator @synthesize dispatcher = _dispatcher; -// Private child coordinators +// Child coordinators +@synthesize consentBumpCoordinator = _consentBumpCoordinator; @synthesize formInputAccessoryCoordinator = _formInputAccessoryCoordinator; -@synthesize snackbarCoordinator = _snackbarCoordinator; @synthesize qrScannerCoordinator = _qrScannerCoordinator; +@synthesize readingListCoordinator = _readingListCoordinator; +@synthesize recentTabsCoordinator = _recentTabsCoordinator; +@synthesize snackbarCoordinator = _snackbarCoordinator; #pragma mark - ChromeCoordinator @@ -53,11 +71,15 @@ self.dispatcher = [[CommandDispatcher alloc] init]; [self createViewController]; [self startChildCoordinators]; + [self.dispatcher + startDispatchingToTarget:self + forProtocol:@protocol(BrowserCoordinatorCommands)]; [super start]; } - (void)stop { [super stop]; + [self.dispatcher stopDispatchingToTarget:self]; [self stopChildCoordinators]; [self destroyViewController]; self.dispatcher = nil; @@ -91,6 +113,9 @@ // Dispatcher should be instantiated so that it can be passed to child // coordinators. DCHECK(self.dispatcher); + + /* ConsentBumpCoordinator is created and started by a BrowserCommand */ + self.formInputAccessoryCoordinator = [[FormInputAccessoryCoordinator alloc] initWithBaseViewController:self.viewController browserState:self.browserState @@ -98,25 +123,109 @@ self.formInputAccessoryCoordinator.delegate = self; [self.formInputAccessoryCoordinator start]; - self.snackbarCoordinator = [[SnackbarCoordinator alloc] init]; - self.snackbarCoordinator.dispatcher = self.dispatcher; - [self.snackbarCoordinator start]; - self.qrScannerCoordinator = [[QRScannerLegacyCoordinator alloc] initWithBaseViewController:self.viewController]; self.qrScannerCoordinator.dispatcher = self.dispatcher; + + /* ReadingListCoordinator is created and started by a BrowserCommand */ + + /* RecentTabsCoordinator is created and started by a BrowserCommand */ + + self.snackbarCoordinator = [[SnackbarCoordinator alloc] init]; + self.snackbarCoordinator.dispatcher = self.dispatcher; + [self.snackbarCoordinator start]; } // Stops child coordinators. - (void)stopChildCoordinators { + [self.consentBumpCoordinator stop]; + self.consentBumpCoordinator = nil; + [self.formInputAccessoryCoordinator stop]; self.formInputAccessoryCoordinator = nil; - [self.snackbarCoordinator stop]; - self.snackbarCoordinator = nil; - [self.qrScannerCoordinator stop]; self.qrScannerCoordinator = nil; + + [self.readingListCoordinator stop]; + self.readingListCoordinator = nil; + + [self.recentTabsCoordinator stop]; + self.recentTabsCoordinator = nil; + + [self.snackbarCoordinator stop]; + self.snackbarCoordinator = nil; +} + +#pragma mark - BrowserCoordinatorCommands + +- (void)showConsentBumpIfNeeded { + DCHECK(!self.consentBumpCoordinator); + if (![ConsentBumpCoordinator + shouldShowConsentBumpWithBrowserState:self.browserState]) { + return; + } + self.consentBumpCoordinator = [[ConsentBumpCoordinator alloc] + initWithBaseViewController:self.viewController + browserState:self.browserState]; + self.consentBumpCoordinator.delegate = self; + [self.consentBumpCoordinator start]; + self.consentBumpCoordinator.viewController.modalPresentationStyle = + UIModalPresentationFormSheet; + [self.viewController + presentViewController:self.consentBumpCoordinator.viewController + animated:YES + completion:nil]; +} + +- (void)showReadingList { + self.readingListCoordinator = [[ReadingListCoordinator alloc] + initWithBaseViewController:self.viewController + browserState:self.browserState + loader:self.viewController]; + [self.readingListCoordinator start]; +} + +- (void)showRecentTabs { + // TODO(crbug.com/825431): If BVC's clearPresentedState is ever called (such + // as in tearDown after a failed egtest), then this coordinator is left in a + // started state even though its corresponding VC is no longer on screen. + // That causes issues when the coordinator is started again and we destroy the + // old mediator without disconnecting it first. Temporarily work around these + // issues by not having a long lived coordinator. A longer-term solution will + // require finding a way to stop this coordinator so that the mediator is + // properly disconnected and destroyed and does not live longer than its + // associated VC. + if (self.recentTabsCoordinator) { + [self.recentTabsCoordinator stop]; + self.recentTabsCoordinator = nil; + } + + self.recentTabsCoordinator = [[RecentTabsCoordinator alloc] + initWithBaseViewController:self.viewController + browserState:self.browserState]; + self.recentTabsCoordinator.loader = self.viewController; + self.recentTabsCoordinator.dispatcher = self.applicationCommandHandler; + [self.recentTabsCoordinator start]; +} + +#pragma mark - ConsentBumpCoordinatorDelegate + +- (void)consentBumpCoordinator:(ConsentBumpCoordinator*)coordinator + didFinishNeedingToShowSettings:(BOOL)shouldShowSettings { + DCHECK(self.consentBumpCoordinator); + DCHECK(self.consentBumpCoordinator.viewController); + auto completion = ^{ + if (shouldShowSettings) { + [self.applicationCommandHandler + showGoogleServicesSettingsFromViewController:self.viewController]; + } + }; + [self.consentBumpCoordinator.viewController + dismissViewControllerAnimated:YES + completion:completion]; + [self.consentBumpCoordinator stop]; + self.consentBumpCoordinator = nil; } #pragma mark - FormInputAccessoryCoordinatorDelegate
diff --git a/ios/chrome/browser/ui/recent_tabs/recent_tabs_coordinator.h b/ios/chrome/browser/ui/recent_tabs/recent_tabs_coordinator.h index 5d39548..4fc4d5ca 100644 --- a/ios/chrome/browser/ui/recent_tabs/recent_tabs_coordinator.h +++ b/ios/chrome/browser/ui/recent_tabs/recent_tabs_coordinator.h
@@ -10,13 +10,12 @@ #import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h" @protocol ApplicationCommands; -@protocol BrowserCommands; @protocol UrlLoader; // Coordinator that presents Recent Tabs. @interface RecentTabsCoordinator : ChromeCoordinator // The dispatcher for this Coordinator. -@property(nonatomic, weak) id<ApplicationCommands, BrowserCommands> dispatcher; +@property(nonatomic, weak) id<ApplicationCommands> dispatcher; // URL loader being managed by this Coordinator. @property(nonatomic, weak) id<UrlLoader> loader; @end
diff --git a/ios/chrome/browser/ui/sad_tab/features.cc b/ios/chrome/browser/ui/sad_tab/features.cc index 88251fe0..ac5cc11c 100644 --- a/ios/chrome/browser/ui/sad_tab/features.cc +++ b/ios/chrome/browser/ui/sad_tab/features.cc
@@ -5,4 +5,4 @@ #include "ios/chrome/browser/ui/sad_tab/features.h" const base::Feature kPresentSadTabInViewController{ - "PresentSadTabInViewController", base::FEATURE_DISABLED_BY_DEFAULT}; + "PresentSadTabInViewController", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/ios/chrome/browser/ui/settings/google_services_settings_egtest.mm b/ios/chrome/browser/ui/settings/google_services_settings_egtest.mm index dd09d54..9bb32d2 100644 --- a/ios/chrome/browser/ui/settings/google_services_settings_egtest.mm +++ b/ios/chrome/browser/ui/settings/google_services_settings_egtest.mm
@@ -147,6 +147,11 @@ // Tests that "Activity and Interactions" switch should be disabled when the // "History" sync is off. - (void)testActivityAndInteractionsDisabledWithHistoryDisabled { +// TODO(crbug.com/906680): Re-enable this test when it's fixed. +#if TARGET_IPHONE_SIMULATOR + EARL_GREY_TEST_DISABLED(@"Test disabled on simulators."); +#endif + [SigninEarlGreyUI signinWithIdentity:[SigninEarlGreyUtils fakeIdentity1]]; [self resetUnifiedConsent]; [self openGoogleServicesSettings];
diff --git a/ios/chrome/browser/ui/toolbar/primary_toolbar_view_controller.mm b/ios/chrome/browser/ui/toolbar/primary_toolbar_view_controller.mm index 1f9c43aa..40e150d9 100644 --- a/ios/chrome/browser/ui/toolbar/primary_toolbar_view_controller.mm +++ b/ios/chrome/browser/ui/toolbar/primary_toolbar_view_controller.mm
@@ -78,8 +78,13 @@ - (void)setScrollProgressForTabletOmnibox:(CGFloat)progress { [super setScrollProgressForTabletOmnibox:progress]; - self.view.locationBarBottomConstraint.constant = - [self verticalMarginForLocationBarForFullscreenProgress:1] * progress; + if (progress == 1) { + self.view.locationBarContainer.transform = CGAffineTransformIdentity; + } else { + self.view.locationBarContainer.transform = CGAffineTransformMakeTranslation( + 0, [self verticalMarginForLocationBarForFullscreenProgress:1] * + (progress - 1)); + } self.view.locationBarContainer.alpha = progress; // When the locationBarContainer is hidden, show the |fakeOmniboxTarget|.
diff --git a/ios/web/web_state/BUILD.gn b/ios/web/web_state/BUILD.gn index ccf460c..3074ddb0 100644 --- a/ios/web/web_state/BUILD.gn +++ b/ios/web/web_state/BUILD.gn
@@ -58,6 +58,7 @@ source_set("navigation_context") { deps = [ "//base", + "//ios/web/navigation:core", "//ios/web/public", ]
diff --git a/ios/web/web_state/navigation_context_impl.h b/ios/web/web_state/navigation_context_impl.h index f70f4e92..b815cdca 100644 --- a/ios/web/web_state/navigation_context_impl.h +++ b/ios/web/web_state/navigation_context_impl.h
@@ -85,6 +85,10 @@ bool IsNativeContentPresented() const; void SetIsNativeContentPresented(bool is_native_content_presented); + // true if this navigation context is a placeholder navigation. + bool IsPlaceholderNavigation() const; + void SetPlaceholderNavigation(bool flag); + private: NavigationContextImpl(WebState* web_state, const GURL& url, @@ -109,6 +113,7 @@ bool is_loading_error_page_ = false; bool is_loading_html_string_ = false; bool is_native_content_presented_ = false; + bool is_placeholder_navigation_ = false; DISALLOW_COPY_AND_ASSIGN(NavigationContextImpl); };
diff --git a/ios/web/web_state/navigation_context_impl.mm b/ios/web/web_state/navigation_context_impl.mm index ad1f0f7d..7a5895d4 100644 --- a/ios/web/web_state/navigation_context_impl.mm +++ b/ios/web/web_state/navigation_context_impl.mm
@@ -175,6 +175,14 @@ is_native_content_presented_ = is_native_content_presented; } +bool NavigationContextImpl::IsPlaceholderNavigation() const { + return is_placeholder_navigation_; +} + +void NavigationContextImpl::SetPlaceholderNavigation(bool flag) { + is_placeholder_navigation_ = flag; +} + NavigationContextImpl::NavigationContextImpl(WebState* web_state, const GURL& url, bool has_user_gesture,
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm index e41cb30..7c89e06 100644 --- a/ios/web/web_state/ui/crw_web_controller.mm +++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -472,7 +472,7 @@ // information about the navigation that triggered the document/URL change. // TODO(stuartmorgan): The code conflates URL changes and document object // changes; the two need to be separated and handled differently. -- (void)webPageChangedWithContext:(const web::NavigationContext*)context; +- (void)webPageChangedWithContext:(const web::NavigationContextImpl*)context; // Resets any state that is associated with a specific document object (e.g., // page interaction tracking). - (void)resetDocumentSpecificState; @@ -637,7 +637,8 @@ - (std::unique_ptr<web::NavigationContextImpl>) registerLoadRequestForURL:(const GURL&)URL sameDocumentNavigation:(BOOL)sameDocumentNavigation - hasUserGesture:(BOOL)hasUserGesture; + hasUserGesture:(BOOL)hasUserGesture + placeholderNavigation:(BOOL)placeholderNavigation; // Prepares web controller and delegates for anticipated page change. // Allows several methods to invoke webWill/DidAddPendingURL on anticipated page // change, using the same cached request and calculated transition types. @@ -647,7 +648,8 @@ referrer:(const web::Referrer&)referrer transition:(ui::PageTransition)transition sameDocumentNavigation:(BOOL)sameDocumentNavigation - hasUserGesture:(BOOL)hasUserGesture; + hasUserGesture:(BOOL)hasUserGesture + placeholderNavigation:(BOOL)placeholderNavigation; // Maps WKNavigationType to ui::PageTransition. - (ui::PageTransition)pageTransitionFromNavigationType: (WKNavigationType)navigationType; @@ -1369,7 +1371,8 @@ - (std::unique_ptr<web::NavigationContextImpl>) registerLoadRequestForURL:(const GURL&)URL sameDocumentNavigation:(BOOL)sameDocumentNavigation - hasUserGesture:(BOOL)hasUserGesture { + hasUserGesture:(BOOL)hasUserGesture + placeholderNavigation:(BOOL)placeholderNavigation { // Get the navigation type from the last main frame load request, and try to // map that to a PageTransition. WKNavigationType navigationType = @@ -1384,7 +1387,8 @@ referrer:emptyReferrer transition:transition sameDocumentNavigation:sameDocumentNavigation - hasUserGesture:(BOOL)hasUserGesture]; + hasUserGesture:hasUserGesture + placeholderNavigation:placeholderNavigation]; context->SetWKNavigationType(navigationType); return context; } @@ -1394,7 +1398,8 @@ referrer:(const web::Referrer&)referrer transition:(ui::PageTransition)transition sameDocumentNavigation:(BOOL)sameDocumentNavigation - hasUserGesture:(BOOL)hasUserGesture { + hasUserGesture:(BOOL)hasUserGesture + placeholderNavigation:(BOOL)placeholderNavigation { // Transfer time is registered so that further transitions within the time // envelope are not also registered as links. _lastTransferTimeInSeconds = CFAbsoluteTimeGetCurrent(); @@ -1454,6 +1459,7 @@ web::NavigationContextImpl::CreateNavigationContext( _webStateImpl, requestURL, hasUserGesture, transition, isRendererInitiated); + context->SetPlaceholderNavigation(placeholderNavigation); // TODO(crbug.com/676129): LegacyNavigationManagerImpl::AddPendingItem does // not create a pending item in case of reload. Remove this workaround once @@ -1794,8 +1800,9 @@ // load for a provisional load failure. Rewrite the context URL to actual URL // so the navigation event is broadcasted. // TODO(crbug.com/803503) Clean up callbcks for native error. - if (IsPlaceholderUrl(context->GetUrl())) { + if (context->IsPlaceholderNavigation()) { context->SetUrl(item->GetURL()); + context->SetPlaceholderNavigation(false); } [self loadNativeViewWithSuccess:NO navigationContext:context]; _webStateImpl->SetIsLoading(false); @@ -1848,7 +1855,8 @@ referrer:referrer transition:self.currentTransition sameDocumentNavigation:NO - hasUserGesture:YES]; + hasUserGesture:YES + placeholderNavigation:NO]; [self loadNativeViewWithSuccess:YES navigationContext:navigationContext.get()]; _loadPhase = web::PAGE_LOADED; @@ -1870,7 +1878,8 @@ std::unique_ptr<web::NavigationContextImpl> navigationContext = [self registerLoadRequestForURL:placeholderURL sameDocumentNavigation:NO - hasUserGesture:NO]; + hasUserGesture:NO + placeholderNavigation:YES]; [_navigationStates setContext:std::move(navigationContext) forNavigation:navigation]; return [_navigationStates contextForNavigation:navigation]; @@ -1903,7 +1912,8 @@ std::unique_ptr<web::NavigationContextImpl> navigationContext = [self registerLoadRequestForURL:item->GetURL() sameDocumentNavigation:NO - hasUserGesture:NO]; + hasUserGesture:NO + placeholderNavigation:NO]; WKNavigation* navigation = [_webView loadHTMLString:@"" baseURL:net::NSURLWithGURL(item->GetURL())]; @@ -2030,7 +2040,8 @@ referrer:self.currentNavItemReferrer transition:ui::PageTransition::PAGE_TRANSITION_RELOAD sameDocumentNavigation:NO - hasUserGesture:YES]; + hasUserGesture:YES + placeholderNavigation:NO]; navigationContext->SetIsRendererInitiated(isRendererInitiated); _webStateImpl->OnNavigationStarted(navigationContext.get()); [self didStartLoading]; @@ -2067,7 +2078,8 @@ referrer:self.currentNavItemReferrer transition:ui::PageTransition::PAGE_TRANSITION_RELOAD sameDocumentNavigation:NO - hasUserGesture:YES]; + hasUserGesture:YES + placeholderNavigation:NO]; [_navigationStates setContext:std::move(navigationContext) forNavigation:navigation]; } else { @@ -2195,7 +2207,10 @@ // placeholder URLs because this may be the only opportunity to update // |isLoading| for native view reload. - if (context && IsWKInternalUrl(context->GetUrl())) + if (context && context->IsPlaceholderNavigation()) + return; + + if (context && IsRestoreSessionUrl(context->GetUrl())) return; if (IsRestoreSessionUrl(net::GURLWithNSURL(_webView.URL))) @@ -2912,7 +2927,7 @@ // TODO(stuartmorgan): This method conflates document changes and URL changes; // we should be distinguishing better, and be clear about the expected // WebDelegate and WCO callbacks in each case. -- (void)webPageChangedWithContext:(const web::NavigationContext*)context { +- (void)webPageChangedWithContext:(const web::NavigationContextImpl*)context { DCHECK_EQ(_loadPhase, web::LOAD_REQUESTED); web::Referrer referrer = [self currentReferrer]; @@ -2931,7 +2946,7 @@ [self didStartLoading]; // Do not commit pending item in the middle of loading a placeholder URL. The // item will be committed when the native content or webUI is displayed. - if (!IsPlaceholderUrl(context->GetUrl())) { + if (!context->IsPlaceholderNavigation()) { self.navigationManagerImpl->CommitPendingItem(); } } @@ -4174,7 +4189,8 @@ referrer:web::Referrer() transition:loadHTMLTransition sameDocumentNavigation:NO - hasUserGesture:true]; + hasUserGesture:YES + placeholderNavigation:NO]; } context->SetIsRendererInitiated(false); context->SetLoadingHtmlString(true); @@ -4370,10 +4386,11 @@ action.navigationType == WKNavigationTypeBackForward) { // WKBackForwardList would have already been updated for back/forward // navigation. Create the pending item here to match. - std::unique_ptr<web::NavigationContextImpl> context = [self - registerLoadRequestForURL:net::GURLWithNSURL(action.request.URL) - sameDocumentNavigation:NO - hasUserGesture:[_pendingNavigationInfo hasUserGesture]]; + std::unique_ptr<web::NavigationContextImpl> context = + [self registerLoadRequestForURL:requestURL + sameDocumentNavigation:NO + hasUserGesture:[_pendingNavigationInfo hasUserGesture] + placeholderNavigation:IsPlaceholderUrl(requestURL)]; [_pendingNavigationInfo setPendingBackForwardContext:std::move(context)]; } @@ -4616,7 +4633,8 @@ return; } - if (context->GetUrl() != webViewURL) { + if (context->GetUrl() != webViewURL && + !context->IsPlaceholderNavigation()) { // Update last seen URL because it may be changed by WKWebView (f.e. by // performing characters escaping). web::NavigationItem* item = web::GetItemWithUniqueID( @@ -4675,7 +4693,8 @@ std::unique_ptr<web::NavigationContextImpl> navigationContext = [self registerLoadRequestForURL:webViewURL sameDocumentNavigation:NO - hasUserGesture:[_pendingNavigationInfo hasUserGesture]]; + hasUserGesture:[_pendingNavigationInfo hasUserGesture] + placeholderNavigation:IsPlaceholderUrl(webViewURL)]; _webStateImpl->OnNavigationStarted(navigationContext.get()); [_navigationStates setContext:std::move(navigationContext) forNavigation:navigation]; @@ -4824,7 +4843,8 @@ // because redirect callback was not called. if (@available(iOS 12, *)) { // rdar://37547029 was fixed on iOS 12. - } else if (context && context->GetUrl() != webViewURL) { + } else if (context && !context->IsPlaceholderNavigation() && + context->GetUrl() != webViewURL) { [self didReceiveRedirectForNavigation:context withURL:webViewURL]; } } @@ -4923,7 +4943,7 @@ // Do not update the HTML5 history state or states of the last committed item // for placeholder page because the actual navigation item will not be // committed until the native content or WebUI is shown. - if (context && !IsPlaceholderUrl(context->GetUrl()) && + if (context && !context->IsPlaceholderNavigation() && !context->GetUrl().SchemeIs(url::kAboutScheme)) { [self updateSSLStatusForCurrentNavigationItem]; [self updateHTML5HistoryState]; @@ -5286,7 +5306,8 @@ std::unique_ptr<web::NavigationContextImpl> newContext = [self registerLoadRequestForURL:webViewURL sameDocumentNavigation:isSameDocumentNavigation - hasUserGesture:NO]; + hasUserGesture:NO + placeholderNavigation:IsPlaceholderUrl(webViewURL)]; [self webPageChangedWithContext:newContext.get()]; newContext->SetHasCommitted(!isSameDocumentNavigation); _webStateImpl->OnNavigationFinished(newContext.get()); @@ -5533,7 +5554,8 @@ // 4.) Back-forward same document navigation newNavigationContext = [self registerLoadRequestForURL:newURL sameDocumentNavigation:YES - hasUserGesture:NO]; + hasUserGesture:NO + placeholderNavigation:NO]; // Use the current title for items created by same document navigations. auto* pendingItem = self.navigationManagerImpl->GetPendingItem(); @@ -5653,7 +5675,8 @@ referrer:self.currentNavItemReferrer transition:self.currentTransition sameDocumentNavigation:sameDocumentNavigation - hasUserGesture:YES]; + hasUserGesture:YES + placeholderNavigation:NO]; WKNavigation* navigation = [self loadPOSTRequest:request]; [_navigationStates setContext:std::move(navigationContext) forNavigation:navigation]; @@ -5671,7 +5694,8 @@ referrer:self.currentNavItemReferrer transition:self.currentTransition sameDocumentNavigation:sameDocumentNavigation - hasUserGesture:YES]; + hasUserGesture:YES + placeholderNavigation:NO]; navigationContext->SetIsRendererInitiated(false); WKNavigation* navigation = [self loadRequest:request]; [_navigationStates setContext:std::move(navigationContext) @@ -5714,7 +5738,8 @@ referrer:self.currentNavItemReferrer transition:self.currentTransition sameDocumentNavigation:sameDocumentNavigation - hasUserGesture:YES]; + hasUserGesture:YES + placeholderNavigation:NO]; navigationContext->SetIsRendererInitiated(false); WKNavigation* navigation = nil; if (navigationURL == net::GURLWithNSURL([_webView URL])) {
diff --git a/ios/web/web_state/web_state_impl.h b/ios/web/web_state/web_state_impl.h index 7e83c0a..6063ba8 100644 --- a/ios/web/web_state/web_state_impl.h +++ b/ios/web/web_state/web_state_impl.h
@@ -46,7 +46,7 @@ struct ContextMenuParams; struct FaviconURL; struct LoadCommittedDetails; -class NavigationContext; +class NavigationContextImpl; class NavigationManager; class SessionCertificatePolicyCacheImpl; class WebInterstitialImpl; @@ -78,12 +78,12 @@ void SetWebController(CRWWebController* web_controller); // Notifies the observers that a navigation has started. - void OnNavigationStarted(web::NavigationContext* context); + void OnNavigationStarted(web::NavigationContextImpl* context); // Notifies the observers that a navigation has finished. For same-document // navigations notifies the observers about favicon URLs update using // candidates received in OnFaviconUrlUpdated. - void OnNavigationFinished(web::NavigationContext* context); + void OnNavigationFinished(web::NavigationContextImpl* context); // Called when current window's canGoBack / canGoForward state was changed. void OnBackForwardStateChanged();
diff --git a/ios/web/web_state/web_state_impl.mm b/ios/web/web_state/web_state_impl.mm index f983c67..eade297 100644 --- a/ios/web/web_state/web_state_impl.mm +++ b/ios/web/web_state/web_state_impl.mm
@@ -735,23 +735,27 @@ }]; } -void WebStateImpl::OnNavigationStarted(web::NavigationContext* context) { +void WebStateImpl::OnNavigationStarted(web::NavigationContextImpl* context) { // Navigation manager loads internal URLs to restore session history and // create back-forward entries for Native View and WebUI. Do not trigger // external callbacks. - if (wk_navigation_util::IsWKInternalUrl(context->GetUrl())) + if (context->IsPlaceholderNavigation() || + wk_navigation_util::IsRestoreSessionUrl(context->GetUrl())) { return; + } for (auto& observer : observers_) observer.DidStartNavigation(this, context); } -void WebStateImpl::OnNavigationFinished(web::NavigationContext* context) { +void WebStateImpl::OnNavigationFinished(web::NavigationContextImpl* context) { // Navigation manager loads internal URLs to restore session history and // create back-forward entries for Native View and WebUI. Do not trigger // external callbacks. - if (wk_navigation_util::IsWKInternalUrl(context->GetUrl())) + if (context->IsPlaceholderNavigation() || + wk_navigation_util::IsRestoreSessionUrl(context->GetUrl())) { return; + } for (auto& observer : observers_) observer.DidFinishNavigation(this, context);
diff --git a/ios/web/web_state/web_state_impl_unittest.mm b/ios/web/web_state/web_state_impl_unittest.mm index 5746425..ad0ac21 100644 --- a/ios/web/web_state/web_state_impl_unittest.mm +++ b/ios/web/web_state/web_state_impl_unittest.mm
@@ -415,7 +415,7 @@ // Test that DidFinishNavigation() is called. ASSERT_FALSE(observer->did_finish_navigation_info()); const GURL url("http://test"); - std::unique_ptr<web::NavigationContext> context = + std::unique_ptr<NavigationContextImpl> context = NavigationContextImpl::CreateNavigationContext( web_state_.get(), url, /*has_user_gesture=*/true, ui::PageTransition::PAGE_TRANSITION_AUTO_BOOKMARK, @@ -505,22 +505,27 @@ // Tests that placeholder navigations are not visible to WebStateObservers. TEST_P(WebStateImplTest, PlaceholderNavigationNotExposedToObservers) { TestWebStateObserver observer(web_state_.get()); - FakeNavigationContext context; - context.SetUrl( - wk_navigation_util::CreatePlaceholderUrlForUrl(GURL("chrome://newtab"))); - + GURL placeholder_url = + wk_navigation_util::CreatePlaceholderUrlForUrl(GURL("chrome://newtab")); + std::unique_ptr<NavigationContextImpl> context = + NavigationContextImpl::CreateNavigationContext( + web_state_.get(), placeholder_url, + /*has_user_gesture=*/true, + ui::PageTransition::PAGE_TRANSITION_AUTO_BOOKMARK, + /*is_renderer_initiated=*/true); + context->SetPlaceholderNavigation(true); // Test that OnPageLoaded() is not called. - web_state_->OnPageLoaded(context.GetUrl(), true /* load_success */); + web_state_->OnPageLoaded(placeholder_url, /*load_success=*/true); EXPECT_FALSE(observer.load_page_info()); - web_state_->OnPageLoaded(context.GetUrl(), false /* load_success */); + web_state_->OnPageLoaded(placeholder_url, /*load_success=*/false); EXPECT_FALSE(observer.load_page_info()); // Test that OnNavigationStarted() is not called. - web_state_->OnNavigationStarted(&context); + web_state_->OnNavigationStarted(context.get()); EXPECT_FALSE(observer.did_start_navigation_info()); // Test that OnNavigationFinished() is not called. - web_state_->OnNavigationFinished(&context); + web_state_->OnNavigationFinished(context.get()); EXPECT_FALSE(observer.did_finish_navigation_info()); } @@ -666,8 +671,12 @@ // Test that DidStartNavigation() is called. EXPECT_FALSE(observer->did_start_navigation_called()); - FakeNavigationContext context; - web_state_->OnNavigationStarted(&context); + std::unique_ptr<NavigationContextImpl> context = + NavigationContextImpl::CreateNavigationContext( + web_state_.get(), GURL::EmptyGURL(), /*has_user_gesture=*/true, + ui::PageTransition::PAGE_TRANSITION_AUTO_BOOKMARK, + /*is_renderer_initiated=*/true); + web_state_->OnNavigationStarted(context.get()); EXPECT_TRUE(observer->did_start_navigation_called()); // Test that WebStateDidStartLoading() is called. @@ -927,9 +936,13 @@ auto observer = std::make_unique<TestWebStateObserver>(web_state_.get()); // No callback if icons has not been fetched yet. - FakeNavigationContext context; - context.SetIsSameDocument(true); - web_state_->OnNavigationFinished(&context); + std::unique_ptr<NavigationContextImpl> context = + NavigationContextImpl::CreateNavigationContext( + web_state_.get(), GURL::EmptyGURL(), + /*has_user_gesture=*/false, ui::PageTransition::PAGE_TRANSITION_LINK, + /*is_renderer_initiated=*/false); + context->SetIsSameDocument(true); + web_state_->OnNavigationFinished(context.get()); EXPECT_FALSE(observer->update_favicon_url_candidates_info()); // Callback is called when icons were fetched. @@ -942,7 +955,7 @@ // Callback is now called after same-document navigation. observer = std::make_unique<TestWebStateObserver>(web_state_.get()); - web_state_->OnNavigationFinished(&context); + web_state_->OnNavigationFinished(context.get()); ASSERT_TRUE(observer->update_favicon_url_candidates_info()); ASSERT_EQ(1U, observer->update_favicon_url_candidates_info()->candidates.size()); @@ -959,14 +972,14 @@ // Document change navigation does not call callback. observer = std::make_unique<TestWebStateObserver>(web_state_.get()); - context.SetIsSameDocument(false); - web_state_->OnNavigationFinished(&context); + context->SetIsSameDocument(false); + web_state_->OnNavigationFinished(context.get()); EXPECT_FALSE(observer->update_favicon_url_candidates_info()); // Previous candidates were invalidated by the document change. No callback // if icons has not been fetched yet. - context.SetIsSameDocument(true); - web_state_->OnNavigationFinished(&context); + context->SetIsSameDocument(true); + web_state_->OnNavigationFinished(context.get()); EXPECT_FALSE(observer->update_favicon_url_candidates_info()); }
diff --git a/net/base/host_port_pair.h b/net/base/host_port_pair.h index a5ee6bd..1efb721e 100644 --- a/net/base/host_port_pair.h +++ b/net/base/host_port_pair.h
@@ -40,6 +40,8 @@ return std::tie(port_, host_) < std::tie(other.port_, other.host_); } + bool operator==(const HostPortPair& other) const { return Equals(other); } + // Equality test of contents. (Probably another violation of style guide). bool Equals(const HostPortPair& other) const { return host_ == other.host_ && port_ == other.port_;
diff --git a/net/dns/host_cache.cc b/net/dns/host_cache.cc index dc348add..bacb6f1 100644 --- a/net/dns/host_cache.cc +++ b/net/dns/host_cache.cc
@@ -4,11 +4,11 @@ #include "net/dns/host_cache.h" -#include <utility> +#include <algorithm> -#include "base/logging.h" #include "base/metrics/field_trial.h" #include "base/metrics/histogram_macros.h" +#include "base/numerics/safe_conversions.h" #include "base/strings/string_number_conversions.h" #include "base/time/default_tick_clock.h" #include "base/trace_event/trace_event.h" @@ -43,9 +43,18 @@ const char kNetworkChangesKey[] = "network_changes"; const char kErrorKey[] = "error"; const char kAddressesKey[] = "addresses"; +const char kTextRecordsKey[] = "text_records"; +const char kHostnameResultsKey[] = "hostname_results"; +const char kHostPortsKey[] = "host_ports"; -bool AddressListFromListValue(const base::ListValue* value, AddressList* list) { - list->clear(); +bool AddressListFromListValue(const base::ListValue* value, + base::Optional<AddressList>* out_list) { + if (!value) { + out_list->reset(); + return true; + } + + out_list->emplace(); for (auto it = value->begin(); it != value->end(); it++) { IPAddress address; std::string addr_string; @@ -53,7 +62,7 @@ !address.AssignFromIPLiteral(addr_string)) { return false; } - list->push_back(IPEndPoint(address, 0)); + out_list->value().push_back(IPEndPoint(address, 0)); } return true; } @@ -105,20 +114,6 @@ HostCache::Key::Key() : Key("", DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY) {} -HostCache::Entry::Entry(int error, - const AddressList& addresses, - Source source, - base::TimeDelta ttl) - : error_(error), addresses_(addresses), source_(source), ttl_(ttl) { - DCHECK(ttl >= base::TimeDelta()); -} - -HostCache::Entry::Entry(int error, const AddressList& addresses, Source source) - : error_(error), - addresses_(addresses), - source_(source), - ttl_(base::TimeDelta::FromSeconds(-1)) {} - HostCache::Entry::~Entry() = default; HostCache::Entry::Entry(HostCache::Entry&& entry) = default; @@ -129,6 +124,8 @@ int network_changes) : error_(entry.error()), addresses_(entry.addresses()), + text_records_(entry.text_records()), + hostnames_(entry.hostnames()), source_(entry.source()), ttl_(entry.ttl()), expires_(now + ttl), @@ -137,12 +134,16 @@ stale_hits_(0) {} HostCache::Entry::Entry(int error, - const AddressList& addresses, + const base::Optional<AddressList>& addresses, + base::Optional<std::vector<std::string>>&& text_records, + base::Optional<std::vector<HostPortPair>>&& hostnames, Source source, base::TimeTicks expires, int network_changes) : error_(error), addresses_(addresses), + text_records_(std::move(text_records)), + hostnames_(std::move(hostnames)), source_(source), ttl_(base::TimeDelta::FromSeconds(-1)), expires_(expires), @@ -246,21 +247,69 @@ auto it = entries_.find(key); if (it != entries_.end()) { bool is_stale = it->second.IsStale(now, network_changes_); - AddressListDeltaType delta = - FindAddressListDeltaType(it->second.addresses(), entry.addresses()); - RecordSet(is_stale ? SET_UPDATE_STALE : SET_UPDATE_VALID, now, &it->second, - entry, delta); + + base::Optional<AddressListDeltaType> addresses_delta; + if (entry.addresses() || it->second.addresses()) { + if (entry.addresses() && it->second.addresses()) { + addresses_delta = FindAddressListDeltaType( + it->second.addresses().value(), entry.addresses().value()); + } else { + addresses_delta = DELTA_DISJOINT; + } + } // Else no addresses in old or new, so nullopt delta. + + // For non-address results, delta is only considered for whole-list + // equality. The meaning of partial list equality varies too much depending + // on the context of a DNS record. + base::Optional<AddressListDeltaType> nonaddress_delta; + if (entry.text_records() || it->second.text_records() || + entry.hostnames() || it->second.hostnames()) { + if (entry.text_records() == it->second.text_records() && + entry.hostnames() == it->second.hostnames()) { + nonaddress_delta = DELTA_IDENTICAL; + } else if (entry.text_records() == it->second.text_records() || + entry.hostnames() == it->second.hostnames()) { + nonaddress_delta = DELTA_OVERLAP; + } else { + nonaddress_delta = DELTA_DISJOINT; + } + } // Else no nonaddress results in old or new, so nullopt delta. + + AddressListDeltaType overall_delta; + if (!addresses_delta && !nonaddress_delta) { + // No results in old or new is IDENTICAL. + overall_delta = DELTA_IDENTICAL; + } else if (!addresses_delta) { + overall_delta = nonaddress_delta.value(); + } else if (!nonaddress_delta) { + overall_delta = addresses_delta.value(); + } else if (addresses_delta == DELTA_DISJOINT && + nonaddress_delta == DELTA_DISJOINT) { + overall_delta = DELTA_DISJOINT; + } else if (addresses_delta == DELTA_DISJOINT || + nonaddress_delta == DELTA_DISJOINT) { + // If only some result types are DISJOINT, some match and we have OVERLAP. + overall_delta = DELTA_OVERLAP; + } else { + // No DISJOINT result types, so we have at least partial match. Take the + // least matching amount (highest enum value). + overall_delta = + std::max(addresses_delta.value(), nonaddress_delta.value()); + } + + LogRecordSet(is_stale ? SET_UPDATE_STALE : SET_UPDATE_VALID, now, + &it->second, entry, overall_delta); // TODO(juliatuttle): Remember some old metadata (hit count or frequency or // something like that) if it's useful for better eviction algorithms? result_changed = - entry.error() == OK && - (it->second.error() != entry.error() || delta != DELTA_IDENTICAL); + entry.error() == OK && (it->second.error() != entry.error() || + overall_delta != DELTA_IDENTICAL); entries_.erase(it); } else { result_changed = true; if (size() == max_entries_) EvictOneEntry(now); - RecordSet(SET_INSERT, now, nullptr, entry, DELTA_DISJOINT); + LogRecordSet(SET_INSERT, now, nullptr, entry, DELTA_DISJOINT); } AddEntry(Key(key), Entry(entry, now, ttl, network_changes_)); @@ -367,12 +416,35 @@ if (entry.error() != OK) { entry_dict->SetInteger(kErrorKey, entry.error()); } else { - const AddressList& addresses = entry.addresses(); - // Append all of the resolved addresses. - auto addresses_value = std::make_unique<base::ListValue>(); - for (size_t i = 0; i < addresses.size(); ++i) - addresses_value->AppendString(addresses[i].ToStringWithoutPort()); - entry_dict->SetList(kAddressesKey, std::move(addresses_value)); + if (entry.addresses()) { + // Append all of the resolved addresses. + base::ListValue addresses_value; + for (const IPEndPoint& address : entry.addresses().value()) { + addresses_value.GetList().emplace_back(address.ToStringWithoutPort()); + } + entry_dict->SetKey(kAddressesKey, std::move(addresses_value)); + } + + if (entry.text_records()) { + // Append all resolved text records. + base::ListValue text_list_value; + for (const std::string& text_record : entry.text_records().value()) { + text_list_value.GetList().emplace_back(text_record); + } + entry_dict->SetKey(kTextRecordsKey, std::move(text_list_value)); + } + + if (entry.hostnames()) { + // Append all the resolved hostnames. + base::ListValue hostnames_value; + base::ListValue host_ports_value; + for (const HostPortPair& hostname : entry.hostnames().value()) { + hostnames_value.GetList().emplace_back(hostname.host()); + host_ports_value.GetList().emplace_back(hostname.port()); + } + entry_dict->SetKey(kHostnameResultsKey, std::move(hostnames_value)); + entry_dict->SetKey(kHostPortsKey, std::move(host_ports_value)); + } } entry_list->Append(std::move(entry_dict)); @@ -386,15 +458,8 @@ return false; std::string hostname; - int dns_query_type; HostResolverFlags flags; - int host_resolver_source; - int error = OK; std::string expiration; - base::ListValue empty_list; - const base::ListValue* addresses_value = &empty_list; - AddressList address_list; - if (!entry_dict->GetString(kHostnameKey, &hostname) || !entry_dict->GetInteger(kFlagsKey, &flags) || !entry_dict->GetString(kExpirationKey, &expiration)) { @@ -406,25 +471,39 @@ // TODO(crbug.com/846423): Remove kAddressFamilyKey support after a enough // time has passed to minimize loss-of-persistence impact from backwards // incompatibility. - if (!entry_dict->GetInteger(kDnsQueryTypeKey, &dns_query_type)) { + int dns_query_type_val; + DnsQueryType dns_query_type; + if (entry_dict->GetInteger(kDnsQueryTypeKey, &dns_query_type_val)) { + dns_query_type = static_cast<DnsQueryType>(dns_query_type_val); + } else { int address_family; if (!entry_dict->GetInteger(kAddressFamilyKey, &address_family)) { return false; } - dns_query_type = static_cast<int>(AddressFamilyToDnsQueryType( - static_cast<AddressFamily>(address_family))); + dns_query_type = AddressFamilyToDnsQueryType( + static_cast<AddressFamily>(address_family)); } // HostResolverSource is optional. + int host_resolver_source; if (!entry_dict->GetInteger(kHostResolverSourceKey, &host_resolver_source)) { host_resolver_source = static_cast<int>(HostResolverSource::ANY); } - // Only one of these fields should be in the dictionary. - if (!entry_dict->GetInteger(kErrorKey, &error) && - !entry_dict->GetList(kAddressesKey, &addresses_value)) { - return false; + int error = OK; + const base::ListValue* addresses_value = nullptr; + const base::ListValue* text_records_value = nullptr; + const base::ListValue* hostname_records_value = nullptr; + const base::ListValue* host_ports_value = nullptr; + if (!entry_dict->GetInteger(kErrorKey, &error)) { + entry_dict->GetList(kAddressesKey, &addresses_value); + entry_dict->GetList(kTextRecordsKey, &text_records_value); + + if (entry_dict->GetList(kHostnameResultsKey, &hostname_records_value) != + entry_dict->GetList(kHostPortsKey, &host_ports_value)) { + return false; + } } int64_t time_internal; @@ -435,19 +514,60 @@ tick_clock_->NowTicks() - (base::Time::Now() - base::Time::FromInternalValue(time_internal)); - Key key(hostname, static_cast<DnsQueryType>(dns_query_type), flags, - static_cast<HostResolverSource>(host_resolver_source)); - if (error == OK && - !AddressListFromListValue(addresses_value, &address_list)) { + base::Optional<AddressList> address_list; + if (!AddressListFromListValue(addresses_value, &address_list)) { return false; } + base::Optional<std::vector<std::string>> text_records; + if (text_records_value) { + text_records.emplace(); + for (const base::Value& value : text_records_value->GetList()) { + if (!value.is_string()) + return false; + text_records.value().push_back(value.GetString()); + } + } + + base::Optional<std::vector<HostPortPair>> hostname_records; + if (hostname_records_value) { + DCHECK(host_ports_value); + if (hostname_records_value->GetList().size() != + host_ports_value->GetList().size()) { + return false; + } + + hostname_records.emplace(); + for (size_t i = 0; i < hostname_records_value->GetList().size(); ++i) { + if (!hostname_records_value->GetList()[i].is_string() || + !host_ports_value->GetList()[i].is_int() || + !base::IsValueInRangeForNumericType<uint16_t>( + host_ports_value->GetList()[i].GetInt())) { + return false; + } + hostname_records.value().push_back( + HostPortPair(hostname_records_value->GetList()[i].GetString(), + base::checked_cast<uint16_t>( + host_ports_value->GetList()[i].GetInt()))); + } + } + + // Assume an empty address list if we have an address type and no results. + if (IsAddressType(dns_query_type) && !address_list && !text_records && + !hostname_records) { + address_list.emplace(); + } + + Key key(hostname, dns_query_type, flags, + static_cast<HostResolverSource>(host_resolver_source)); + // If the key is already in the cache, assume it's more recent and don't // replace the entry. If the cache is already full, don't bother // prioritizing what to evict, just stop restoring. auto found = entries_.find(key); if (found == entries_.end() && size() < max_entries_) { - AddEntry(key, Entry(error, address_list, Entry::SOURCE_UNKNOWN, + AddEntry(key, Entry(error, address_list, std::move(text_records), + std::move(hostname_records), Entry::SOURCE_UNKNOWN, expiration_time, network_changes_ - 1)); } } @@ -491,11 +611,11 @@ entries_.erase(oldest_it); } -void HostCache::RecordSet(SetOutcome outcome, - base::TimeTicks now, - const Entry* old_entry, - const Entry& new_entry, - AddressListDeltaType delta) { +void HostCache::LogRecordSet(SetOutcome outcome, + base::TimeTicks now, + const Entry* old_entry, + const Entry& new_entry, + AddressListDeltaType delta) { CACHE_HISTOGRAM_ENUM("Set", outcome, MAX_SET_OUTCOME); switch (outcome) { case SET_INSERT: @@ -510,7 +630,7 @@ stale.network_changes); CACHE_HISTOGRAM_COUNT("UpdateStale.StaleHits", stale.stale_hits); if (old_entry->error() == OK && new_entry.error() == OK) { - RecordUpdateStale(delta, stale); + LogRecordUpdateStale(delta, stale); } break; } @@ -520,8 +640,8 @@ } } -void HostCache::RecordUpdateStale(AddressListDeltaType delta, - const EntryStaleness& stale) { +void HostCache::LogRecordUpdateStale(AddressListDeltaType delta, + const EntryStaleness& stale) { CACHE_HISTOGRAM_ENUM("UpdateStale.AddressListDelta", delta, MAX_DELTA_TYPE); switch (delta) { case DELTA_IDENTICAL:
diff --git a/net/dns/host_cache.h b/net/dns/host_cache.h index ffd63c14..87c3dbfa 100644 --- a/net/dns/host_cache.h +++ b/net/dns/host_cache.h
@@ -12,14 +12,19 @@ #include <memory> #include <string> #include <tuple> +#include <utility> +#include <vector> #include "base/gtest_prod_util.h" +#include "base/logging.h" #include "base/macros.h" +#include "base/optional.h" #include "base/threading/thread_checker.h" #include "base/time/time.h" #include "net/base/address_family.h" #include "net/base/address_list.h" #include "net/base/expiring_cache.h" +#include "net/base/host_port_pair.h" #include "net/base/net_export.h" #include "net/dns/dns_util.h" #include "net/dns/host_resolver_source.h" @@ -89,17 +94,33 @@ SOURCE_HOSTS, }; - Entry(int error, - const AddressList& addresses, - Source source, - base::TimeDelta ttl); + template <typename T> + Entry(int error, T&& results, Source source, base::TimeDelta ttl) + : error_(error), source_(source), ttl_(ttl) { + DCHECK(ttl >= base::TimeDelta()); + SetResult(std::forward<T>(results)); + } + // Use when |ttl| is unknown. - Entry(int error, const AddressList& addresses, Source source); + template <typename T> + Entry(int error, T&& results, Source source) + : error_(error), + source_(source), + ttl_(base::TimeDelta::FromSeconds(-1)) { + SetResult(std::forward<T>(results)); + } + Entry(Entry&& entry); ~Entry(); int error() const { return error_; } - const AddressList& addresses() const { return addresses_; } + const base::Optional<AddressList>& addresses() const { return addresses_; } + const base::Optional<std::vector<std::string>>& text_records() const { + return text_records_; + } + const base::Optional<std::vector<HostPortPair>>& hostnames() const { + return hostnames_; + } Source source() const { return source_; } bool has_ttl() const { return ttl_ >= base::TimeDelta(); } base::TimeDelta ttl() const { return ttl_; } @@ -118,11 +139,21 @@ int network_changes); Entry(int error, - const AddressList& addresses, + const base::Optional<AddressList>& addresses, + base::Optional<std::vector<std::string>>&& text_results, + base::Optional<std::vector<HostPortPair>>&& hostnames, Source source, base::TimeTicks expires, int network_changes); + void SetResult(AddressList addresses) { addresses_ = std::move(addresses); } + void SetResult(std::vector<std::string> text_records) { + text_records_ = std::move(text_records); + } + void SetResult(std::vector<HostPortPair> hostnames) { + hostnames_ = std::move(hostnames); + } + int total_hits() const { return total_hits_; } int stale_hits() const { return stale_hits_; } @@ -134,8 +165,10 @@ // The resolve results for this entry. int error_; - AddressList addresses_; - // Where addresses_ were obtained (e.g. DNS lookup, hosts file, etc). + base::Optional<AddressList> addresses_; + base::Optional<std::vector<std::string>> text_records_; + base::Optional<std::vector<HostPortPair>> hostnames_; + // Where results were obtained (e.g. DNS lookup, hosts file, etc). Source source_; // TTL obtained from the nameserver. Negative if unknown. base::TimeDelta ttl_; @@ -243,13 +276,13 @@ Entry* LookupInternal(const Key& key); - void RecordSet(SetOutcome outcome, - base::TimeTicks now, - const Entry* old_entry, - const Entry& new_entry, - AddressListDeltaType delta); - void RecordUpdateStale(AddressListDeltaType delta, - const EntryStaleness& stale); + void LogRecordSet(SetOutcome outcome, + base::TimeTicks now, + const Entry* old_entry, + const Entry& new_entry, + AddressListDeltaType delta); + void LogRecordUpdateStale(AddressListDeltaType delta, + const EntryStaleness& stale); void RecordLookup(LookupOutcome outcome, base::TimeTicks now, const Entry* entry);
diff --git a/net/dns/host_cache_unittest.cc b/net/dns/host_cache_unittest.cc index b75becc..38932d2 100644 --- a/net/dns/host_cache_unittest.cc +++ b/net/dns/host_cache_unittest.cc
@@ -694,8 +694,11 @@ const HostCache::Entry* result1 = restored_cache.LookupStale(key1, now, &stale); EXPECT_TRUE(result1); - EXPECT_EQ(1u, result1->addresses().size()); - EXPECT_EQ(address_ipv4, result1->addresses().front().address()); + ASSERT_TRUE(result1->addresses()); + EXPECT_FALSE(result1->text_records()); + EXPECT_FALSE(result1->hostnames()); + EXPECT_EQ(1u, result1->addresses().value().size()); + EXPECT_EQ(address_ipv4, result1->addresses().value().front().address()); EXPECT_EQ(1, stale.network_changes); // Time to TimeTicks conversion is fuzzy, so just check that expected and // actual expiration times are close. @@ -707,9 +710,10 @@ const HostCache::Entry* result2 = restored_cache.LookupStale(key2, now, &stale); EXPECT_TRUE(result2); - EXPECT_EQ(2u, result2->addresses().size()); - EXPECT_EQ(address_ipv6, result2->addresses().front().address()); - EXPECT_EQ(address_ipv4, result2->addresses().back().address()); + ASSERT_TRUE(result2->addresses()); + EXPECT_EQ(2u, result2->addresses().value().size()); + EXPECT_EQ(address_ipv6, result2->addresses().value().front().address()); + EXPECT_EQ(address_ipv4, result2->addresses().value().back().address()); EXPECT_EQ(1, stale.network_changes); EXPECT_GT(base::TimeDelta::FromMilliseconds(100), (base::TimeDelta::FromSeconds(-3) - stale.expired_by).magnitude()); @@ -717,18 +721,77 @@ // The "foobar3.com" entry is the new one, not the restored one. const HostCache::Entry* result3 = restored_cache.Lookup(key3, now); EXPECT_TRUE(result3); - EXPECT_EQ(1u, result3->addresses().size()); - EXPECT_EQ(address_ipv4, result3->addresses().front().address()); + ASSERT_TRUE(result3->addresses()); + EXPECT_EQ(1u, result3->addresses().value().size()); + EXPECT_EQ(address_ipv4, result3->addresses().value().front().address()); // The "foobar4.com" entry is still present and usable. const HostCache::Entry* result4 = restored_cache.Lookup(key4, now); EXPECT_TRUE(result4); - EXPECT_EQ(1u, result4->addresses().size()); - EXPECT_EQ(address_ipv4, result4->addresses().front().address()); + ASSERT_TRUE(result4->addresses()); + EXPECT_EQ(1u, result4->addresses().value().size()); + EXPECT_EQ(address_ipv4, result4->addresses().value().front().address()); EXPECT_EQ(3u, restored_cache.last_restore_size()); } +TEST(HostCacheTest, SerializeAndDeserialize_Text) { + base::TimeTicks now; + + base::TimeDelta ttl = base::TimeDelta::FromSeconds(99); + std::vector<std::string> text_records({"foo", "bar"}); + HostCache::Key key("example.com", DnsQueryType::A, 0, + HostResolverSource::DNS); + HostCache::Entry entry(OK, text_records, HostCache::Entry::SOURCE_DNS, ttl); + EXPECT_TRUE(entry.text_records()); + + HostCache cache(kMaxCacheEntries); + cache.Set(key, entry, now, ttl); + EXPECT_EQ(1u, cache.size()); + + base::ListValue serialized_cache; + cache.GetAsListValue(&serialized_cache, false /* include_staleness */); + HostCache restored_cache(kMaxCacheEntries); + restored_cache.RestoreFromListValue(serialized_cache); + + ASSERT_EQ(1u, cache.size()); + const HostCache::Entry* result = cache.Lookup(key, now); + ASSERT_TRUE(result); + EXPECT_FALSE(result->addresses()); + ASSERT_TRUE(result->text_records()); + EXPECT_FALSE(result->hostnames()); + EXPECT_EQ(text_records, result->text_records().value()); +} + +TEST(HostCacheTest, SerializeAndDeserialize_Hostname) { + base::TimeTicks now; + + base::TimeDelta ttl = base::TimeDelta::FromSeconds(99); + std::vector<HostPortPair> hostnames( + {HostPortPair("example.com", 95), HostPortPair("chromium.org", 122)}); + HostCache::Key key("example.com", DnsQueryType::A, 0, + HostResolverSource::DNS); + HostCache::Entry entry(OK, hostnames, HostCache::Entry::SOURCE_DNS, ttl); + EXPECT_TRUE(entry.hostnames()); + + HostCache cache(kMaxCacheEntries); + cache.Set(key, entry, now, ttl); + EXPECT_EQ(1u, cache.size()); + + base::ListValue serialized_cache; + cache.GetAsListValue(&serialized_cache, false /* include_staleness */); + HostCache restored_cache(kMaxCacheEntries); + restored_cache.RestoreFromListValue(serialized_cache); + + ASSERT_EQ(1u, cache.size()); + const HostCache::Entry* result = cache.Lookup(key, now); + ASSERT_TRUE(result); + EXPECT_FALSE(result->addresses()); + EXPECT_FALSE(result->text_records()); + ASSERT_TRUE(result->hostnames()); + EXPECT_EQ(hostnames, result->hostnames().value()); +} + TEST(HostCacheTest, PersistenceDelegate) { const base::TimeDelta kTTL = base::TimeDelta::FromSeconds(10); HostCache cache(kMaxCacheEntries);
diff --git a/net/dns/host_resolver_impl.cc b/net/dns/host_resolver_impl.cc index 47cf9efd..6411200f 100644 --- a/net/dns/host_resolver_impl.cc +++ b/net/dns/host_resolver_impl.cc
@@ -1933,7 +1933,7 @@ } if (entry.error() == OK && !req->parameters().is_speculative) { req->set_address_results(EnsurePortOnAddressList( - entry.addresses(), req->request_host().port())); + entry.addresses().value(), req->request_host().port())); } req->OnJobCompleted(this, entry.error()); @@ -2519,7 +2519,8 @@ if (*net_error == OK) { if (cache_entry->has_ttl()) RecordTTL(cache_entry->ttl()); - *addresses = EnsurePortOnAddressList(cache_entry->addresses(), host_port); + *addresses = + EnsurePortOnAddressList(cache_entry->addresses().value(), host_port); } return true; }
diff --git a/net/dns/mock_host_resolver.cc b/net/dns/mock_host_resolver.cc index 51d913c..9a292fe 100644 --- a/net/dns/mock_host_resolver.cc +++ b/net/dns/mock_host_resolver.cc
@@ -455,7 +455,8 @@ if (entry) { rv = entry->error(); if (rv == OK) - *addresses = AddressList::CopyWithPort(entry->addresses(), host.port()); + *addresses = + AddressList::CopyWithPort(entry->addresses().value(), host.port()); } } return rv;
diff --git a/net/docs/life-of-a-url-request.md b/net/docs/life-of-a-url-request.md index a31288e..2e7b152 100644 --- a/net/docs/life-of-a-url-request.md +++ b/net/docs/life-of-a-url-request.md
@@ -1,10 +1,10 @@ # Life of a URLRequest This document is intended as an overview of the core layers of the network -stack, their basic responsibilities, how they fit together, and where some of -the pain points are, without going into too much detail. Though it touches a -bit on child processes and the content/loader stack, the focus is on net/ -itself. +stack and the network service, their basic responsibilities, and how they fit +together, without going into too much detail. This doc assumes the network +service is enabled, though the network service is not yet enabled by default +on any platform. It's particularly targeted at people new to the Chrome network stack, but should also be useful for team members who may be experts at some parts of the @@ -15,40 +15,25 @@ If you notice any inaccuracies in this document, or feel that things could be better explained, please do not hesitate to submit patches. + # Anatomy of the Network Stack +The network stack is located in //net/ in the Chrome repo, and uses the +namespace "net". Whenever a class name in this doc has no namespace, it can +generally be assumed it's in //net/ and is in the net namespace. + The top-level network stack object is the URLRequestContext. The context has non-owning pointers to everything needed to create and issue a URLRequest. The context must outlive all requests that use it. Creating a context is a rather complicated process, and it's recommended that most consumers use URLRequestContextBuilder to do this. -Chrome has a number of different URLRequestContexts, as there is often a need to -keep cookies, caches, and socket pools separate for different types of requests. -Here are the main ones used by Chrome browser: - -* The system URLRequestContext, also owned by the IOThread, used for requests -that aren't associated with a profile. -* Each profile, including incognito profiles, has a number of URLRequestContexts -that are created as needed: - * The main URLRequestContext is mostly created in ProfileIOData, though it - has a couple components that are passed in from content's StoragePartition - code. Several other components are shared with the system URLRequestContext, - like the HostResolver. - * Each non-incognito profile also has a media request context, which uses a - different on-disk cache than the main request context. This prevents a - single huge media file from evicting everything else in the cache. (See also - crbug.com/789657) - * On desktop platforms, each profile has a request context for extensions. - * Each profile has two contexts for each isolated app (One for media, one - for everything else). - The primary use of the URLRequestContext is to create URLRequest objects using URLRequestContext::CreateRequest(). The URLRequest is the main interface used -by consumers of the network stack. It is used to make the actual requests to a -server. Each URLRequest tracks a single request across all redirects until an -error occurs, it's canceled, or a final response is received, with a (possibly -empty) body. +by direct consumers of the network stack. It use used to drive requests for +http, https, ftp, and some data URLs. Each URLRequest tracks a single request +across all redirects until an error occurs, it's canceled, or a final response +is received, with a (possibly empty) body. The HttpNetworkSession is another major network stack object. It owns the HttpStreamFactory, the socket pools, and the HTTP/2 and QUIC session pools. It @@ -63,94 +48,130 @@ # How many "Delegates"? -The network stack informs the embedder of important events for a request using -two main interfaces: the URLRequest::Delegate interface and the NetworkDelegate +A URLRequest informs the consumer of important events for a request using two +main interfaces: the URLRequest::Delegate interface and the NetworkDelegate interface. The URLRequest::Delegate interface consists of a small set of callbacks needed -to let the embedder drive a request forward. URLRequest::Delegates generally own -the URLRequest. +to let the embedder drive a request forward. The NetworkDelegate is an object +pointed to by the URLRequestContext and shared by all requests, and includes +callbacks corresponding to most of the URLRequest::Delegate's callbacks, as +well as an assortment of other methods. -The NetworkDelegate is an object pointed to by the URLRequestContext and shared -by all requests, and includes callbacks corresponding to most of the -URLRequest::Delegate's callbacks, as well as an assortment of other methods. The -NetworkDelegate is optional, while the URLRequest::Delegate is not. +# The Network Service and Mojo + +The network service, which lives in //services/network/, wraps //net/ objects, +and provides cross-process network APIs and their implementations for the rest +of Chrome. The network service uses the namespace "network" for all its classes. +The Mojo interfaces it provides are in the network::mojom namespace. Mojo is +Chrome's IPC layer. Generally there's a network::mojom::FooPtr proxy object in +the consumer's process which also implements the network::mojom::Foo interface. +When the proxy object's methods are invoked, it passes the call and all its +arguments over a Mojo IPC channel to another the implementation of the +network::mojom::Foo interface in the network service (typically implemented by a +class named network::Foo), which may be running in another process, or possibly +another thread in the consumer's process. + +The network::NetworkService object is singleton that is used by Chrome to create +all other network service objects. The primary objects it is used to create are +the network::NetworkContexts, each of which owns its own mostly independent +URLRequestContext. Chrome has a number of different NetworkContexts, as there +is often a need to keep cookies, caches, and socket pools separate for different +types of requests, depending on what's making the request. Here are the main +NetworkContexts used by Chrome: + +* The system NetworkContext, created and owned by Chrome's +SystemNetworkContextManager, is used for requests that aren't associated with +particular user or Profile. It has no on-disk storage, so loses all state, like +cookies, after each browser restart. It has no in-memory http cache, either. +SystemNetworkContextManager also sets up global network service preferences. +* Each Chrome Profile, including incognito Profiles, has its own NetworkContext. +Except for incognito and guest profiles, these contexts store information in +their own on-disk store, which includes cookies and an HTTP cache, among other +things. Each of these NetworkContexts is owned by a StoragePartition object in +the browser process, and created by a Profile's ProfileNetworkContextService. +* On platforms that support apps, each Profile has a NetworkContext for each app +installed on that Profile. As with the main NetworkContext, these may have +on-disk data, depending on the Profile and the App. # Life of a Simple URLRequest -A request for data is normally dispatched from a child to the browser process. -There a URLRequest is created to drive the request. A protocol-specific job -(e.g. HTTP, data, file) is attached to the request. That job first checks the -cache, and then creates a network connection object, if necessary, to actually -fetch the data. That connection object interacts with network socket pools to -potentially re-use sockets; the socket pools create and connect a socket if -there is no appropriate existing socket. Once that socket exists, the HTTP -request is dispatched, the response read and parsed, and the result returned -back up the stack and sent over to the child process. +A request for data is dispatched from some other process which results in +creating a network::URLLoader in the network process. The URLLoader then +creates a URLRequest to drive the request. A protocol-specific job +(e.g. HTTP, data, file) is attached to the request. In the HTTP case, that job +first checks the cache, and then creates a network connection object, if +necessary, to actually fetch the data. That connection object interacts with +network socket pools to potentially re-use sockets; the socket pools create and +connect a socket if there is no appropriate existing socket. Once that socket +exists, the HTTP request is dispatched, the response read and parsed, and the +result returned back up the stack and sent over to the child process. Of course, it's not quite that simple :-}. -Consider a simple request issued by a child process. Suppose it's an HTTP -request, the response is uncompressed, no matching entry in the cache, and there -are no idle sockets connected to the server in the socket pool. +Consider a simple request issued by some process other than the network +service's process. Suppose it's an HTTP request, the response is uncompressed, +no matching entry in the cache, and there are no idle sockets connected to the +server in the socket pool. Continuing with a "simple" URLRequest, here's a bit more detail on how things work. -### Request starts in a child process +### Request starts in some (non-network) process Summary: -* A user (e.g. the WebURLLoaderImpl for Blink) asks ResourceDispatcher to start -the request. -* ResourceDispatcher sends an IPC to the ResourceDispatcherHost in the -browser process. +* A consumer (e.g. the content::ResourceDispatcher for Blink, the +content::NavigationURLLoaderImpl for frame navigations, or a +network::SimpleURLLoader) passes a network::ResourceRequest object and +network::mojom::URLLoaderClient Mojo channel to a +network::mojom::URLLoaderFactory, and tells it to create and start a +network::mojom::URLLoader. +* Mojo sends the network::ResourceRequest over an IPC pipe to a +network::URLLoaderFactory in the network process. -Chrome has a single browser process, which handles network requests and tab -management, among other things, and multiple child processes, which are -generally sandboxed so can't send out network requests directly. There are -multiple types of child processes (renderer, GPU, plugin, etc). The renderer -processes are the ones that layout webpages and run HTML. +Chrome has a single browser process which handles starting and configuring other +processes, tab management, and navigation, among other things, and multiple +child processes, which are generally sandboxed and have no network access +themselves, apart from the network service (Which either runs in its own +process, or potentially in the browser process to preserve RAM). There are +multiple types of child processes (renderer, GPU, plugin, network, etc). The +renderer processes are the ones that layout webpages and run HTML. -Each child process has at most one ResourceDispatcher, which is responsible for -all URL request-related communication with the browser process. When something -in another process needs to issue a resource request, it calls into the -ResourceDispatcher to start a request. A RequestPeer is passed in to receive -messages related to the request. When started, the -ResourceDispatcher assigns the request a per-renderer ID, and then sends the -ID, along with all information needed to issue the request, to the -ResourceDispatcherHost in the browser process. +The browser process creates the top level network::mojom::NetworkContext +objects, and uses them to create network::mojom::URLLoaderFactories, which it +can set some security-related options on, before vending them to child +processes. Child processes can then use them to directly talk to the network +service. -### ResourceDispatcherHost sets up the request in the browser process +A consumer that wants to make a network request gets a URLLoaderFactory through +some manner, assembles a bunch of parameters in the large ResourceRequest +object, creates a network::mojom::URLLoaderClient Mojo channel for the +network::mojom::URLLoader to use to talk back to it, and then passes them to +the URLLoaderFactory, which returns a URLLoader object that it can use to +manage the network request. + +### network::URLLoaderFactory sets up the request in the browser process Summary: -* ResourceDispatcherHost uses the URLRequestContext to create the URLRequest. -* ResourceDispatcherHost creates a ResourceLoader and a chain of -ResourceHandlers to manage the URLRequest. -* ResourceLoader starts the URLRequest. +* network::URLLoaderFactory creates a network::URLLoader. +* network::URLLoader uses the network::NetworkContext's URLRequestContext to +create and start a URLRequest. -The ResourceDispatcherHost (RDH), along with most of the network stack, lives -on the browser process's IO thread. The browser process only has one RDH, -which is responsible for handling all network requests initiated by -ResourceDispatchers in all child processes, not just renderer processes. -Requests initiated in the browser process don't go through the RDH, with some -exceptions. +The URLLoaderFactory, along with all NetworkContexts and most of the network +stack, lives on a single thread in the network service. It gets a reconstituted +ResourceRequest object from the Mojo pipe, does some checks to make sure it +can service the request, and if so, creates a URLLoader, passing the request and +the NetworkContext associated with the URLLoaderFactory. -When the RDH sees the request, it calls into a URLRequestContext to create the -URLRequest. The URLRequestContext has pointers to all the network stack -objects needed to issue the request over the network, such as the cache, cookie -store, and host resolver. The RDH then creates a chain of ResourceHandlers -each of which can monitor/modify/delay/cancel the URLRequest and the -information it returns. The only one of these I'll talk about here is the -AsyncResourceHandler, which is the last ResourceHandler in the chain. The RDH -then creates a ResourceLoader (which is the URLRequest::Delegate), passes -ownership of the URLRequest and the ResourceHandler chain to it, and then starts -the ResourceLoader. - -The ResourceLoader checks that none of the ResourceHandlers want to cancel, -modify, or delay the request, and then finally starts the URLRequest. +The URLLoader then calls into a URLRequestContext to create the URLRequest. The +URLRequestContext has pointers to all the network stack objects needed to issue +the request over the network, such as the cache, cookie store, and host +resolver. The URLLoader then calls into the ResourceScheduler, which may delay +starting the request, based on priority and other activity. Eventually, the +ResourceScheduler starts the request. ### Check the cache, request an HttpStream @@ -222,10 +243,9 @@ * HttpBasicStream sends the request, and waits for the response. * The HttpBasicStream sends the response headers back to the HttpNetworkTransaction. -* The response headers are sent up to the URLRequest, to the ResourceLoader, -and down through the ResourceHandler chain. -* They're then sent by the the last ResourceHandler in the chain (the -AsyncResourceHandler) to the ResourceDispatcher, with an IPC. +* The response headers are sent up through the URLRequest, to the +network::URLLoader. +* They're then sent to the network::mojom::URLLoaderClient via Mojo. The HttpNetworkTransaction passes the request headers to the HttpBasicStream, which uses an HttpStreamParser to (finally) format the request headers and body @@ -235,56 +255,46 @@ response headers, and then passes them up through both the HttpNetworkTransaction and HttpCache::Transaction to the URLRequestHttpJob. The URLRequestHttpJob saves any cookies, if needed, and then passes the headers up -to the URLRequest and on to the ResourceLoader. - -The ResourceLoader passes them through the chain of ResourceHandlers, and then -they make their way to the AsyncResourceHandler. The AsyncResourceHandler uses -the renderer process ID ("child ID") to figure out which process the request -was associated with, and then sends the headers along with the request ID to -that process's ResourceDispatcher. The ResourceDispatcher uses the ID to -figure out which RequestPeer the headers should be sent to, which -sends them on to the RequestPeer. +to the URLRequest and on to the network::URLLoader, which sends the data over +a Mojo pipe to the network::mojom::URLLoaderClient, passed in to the URLLoader +when it was created. ### Response body is read Summary: -* AsyncResourceHandler allocates a 512k ring buffer of shared memory to read -the body of the request. -* AsyncResourceHandler tells the ResourceLoader to read the response body to -the buffer, 32kB at a time. -* AsyncResourceHandler informs the ResourceDispatcher of each read using -cross-process IPCs. -* ResourceDispatcher tells the AsyncResourceHandler when it's done with the -data with each read, so it knows when parts of the buffer can be reused. +* network::URLLoader creates a raw Mojo data pipe, and passes one end to the +network::mojom::URLLoaderClient. +* The URLLoader requests shared memory buffer from the Mojo data pipe. +* The URLLoader tells the URLRequest to write to the memory buffer, and tells +the pipe when data has been written to the buffer. +* The last two steps repeat until the request is complete. -Without waiting to hear back from the ResourceDispatcher, the ResourceLoader -tells its ResourceHandler chain to allocate memory to receive the response -body. The AsyncResourceHandler creates a 512KB ring buffer of shared memory, -and then passes the first 32KB of it to the ResourceLoader for the first read. -The ResourceLoader then passes a 32KB body read request down through the -URLRequest all the way down to the HttpStreamParser. Once some data is read, -possibly less than 32KB, the number of bytes read makes its way back to the -AsyncResourceHandler, which passes the shared memory buffer and the offset and -amount of data read to the renderer process. - -The AsyncResourceHandler relies on ACKs from the renderer to prevent it from -overwriting data that the renderer has yet to consume. This process repeats -until the response body is completely read. +Without waiting to hear back from the network::mojom::URLLoaderClient, the +network::URLLoader allocates a raw mojo data pipe, and passes the client the +read end of the pipe. The URLLoader then grabs an IPC buffer from the pipe, +and passes a 64KB body read request down through the URLRequest all the way +down to the HttpStreamParser. Once some data is read, possibly less than 64KB, +the number of bytes read makes its way back to the URLLoader, which then tells +the Mojo pipe the read was complete, and then requests another buffer from the +pipe, to continue writing data to. The pipe may apply back pressure, to limit +the amount of unconsumed data that can be in shared memory buffers at once. +This process repeats until the response body is completely read. ### URLRequest is destroyed Summary: -* When complete, the RDH deletes the ResourceLoader, which deletes the -URLRequest and the ResourceHandler chain. +* When complete, the network::URLLoaderFactory deletes the network::URLLoader, +which deletes the URLRequest. * During destruction, the HttpNetworkTransaction determines if the socket is reusable, and if so, tells the HttpBasicStream to return it to the socket pool. -When the URLRequest informs the ResourceLoader it's complete, the -ResourceLoader tells the ResourceHandlers, and the AsyncResourceHandler tells -the ResourceDispatcher the request is complete. The RDH then deletes -ResourceLoader, which deletes the URLRequest and ResourceHandler chain. +When the URLRequest informs the network::URLLoader the request is complete, the +URLLoader passes the message along to the network::mojom::URLLoaderClient, over +its Mojo pipe, before telling the URLLoaderFactory to destroy the URLLoader, +which results in destroying the URLRequest and closing all Mojo pipes related to +the request. When the HttpNetworkTransaction is being torn down, it figures out if the socket is reusable. If not, it tells the HttpBasicStream to close the socket. @@ -341,11 +351,9 @@ ## Cancellation -A request can be cancelled by the child process, by any of the -ResourceHandlers in the chain, or by the ResourceDispatcherHost itself. When the -cancellation message reaches the URLRequest, it passes on the fact it's been -cancelled back to the ResourceLoader, which then sends the message down the -ResourceHandler chain. +A consumer can cancel a request at any time by deleting the +network::mojom::URLLoader pipe used by the request. This will cause the +network::URLLoader to destroy itself and its URLRequest. When an HttpNetworkTransaction for a cancelled request is being torn down, it figures out if the socket the HttpStream owns can potentially be reused, based @@ -366,18 +374,24 @@ entry, even if the headers indicated there will be a body. The URLRequestHttpJob then checks with the URLRequest if the redirect should be -followed. The URLRequest then informs the ResourceLoader about the redirect, to -give it a chance to cancel the request. The information makes its way down -through the AsyncResourceHandler into the other process, via the -ResourceDispatcher. Whatever issued the original request then checks if the -redirect should be followed. +followed. The URLRequest then informs the network::URLLoader about the redirect, +which passes information about the redirect to network::mojom::URLLoaderClient, +in the consumer process. Whatever issued the original request then checks +if the redirect should be followed. -The ResourceDispatcher then asynchronously sends a message back to either -follow the redirect or cancel the request. In either case, the old -HttpTransaction is destroyed, and the HttpNetworkTransaction attempts to drain -the socket for reuse, just as in the cancellation case. If the redirect is -followed, the URLRequest calls into the URLRequestJobFactory to create a new -URLRequestJob, and then starts it. +If the redirect should be followed, the URLLoaderClient calls back into the +URLLoader over the network::mojom::URLLoader Mojo interface, which tells the +URLRequest to follow the redirect. The URLRequest then creates a new +URLRequestJob to send the new request. If the URLLoaderClient chooses to +cancel the request instead, it can delete the network::mojom::URLLoader +pipe, just like the cancellation case discussed above. In either case, the +old HttpTransaction is destroyed, and the HttpNetworkTransaction attempts to +drain the socket for reuse, as discussed in the previous section. + +In some cases, the consumer may choose to handle a redirect itself, like +passing off the redirect to a ServiceWorker. In this case, the consumer cancels +the request and then call into some other network::mojom::URLLoaderFactory +the new URL to continue the request. ## Filters (gzip, deflate, brotli, etc) @@ -546,8 +560,13 @@ ## Non-HTTP Schemes -The URLRequestJobFactory has a ProtocolHander for each supported scheme. -Non-HTTP URLRequests have their own ProtocolHandlers. Some are implemented in -net/, (like FTP, file, and data, though the renderer handles some data URLs -internally), and others are implemented in content/ or chrome (like blob, -chrome, and chrome-extension). +The URLRequestJobFactory has a ProtocolHander for ftp, http, https, and data +URLs, though most data URLs are handled directly in the renderer. For other +schemes, and non-network code that can intercept HTTP/HTTPS requests (Like +ServiceWorker, or extensions), there's typically another +network::mojom::URLLoaderFactory class that is used instead of +network::URLLoaderFactory. These URLLoaderFactories are not part of the +network service. Some of these are web standards and handled in content/ +code (Like blob:// and file:// URLs), while other of these are +chrome-specific, and implemented in chrome/ (like chrome:// and +chrome-extension:// URLs).
diff --git a/net/http/transport_security_state_static.json b/net/http/transport_security_state_static.json index b85d278a..fa48265 100644 --- a/net/http/transport_security_state_static.json +++ b/net/http/transport_security_state_static.json
@@ -61087,7 +61087,7 @@ "policy": "custom", "mode": "force-https", "include_subdomains": true, "expect_ct": true, - "expect_ct_report_uri": "https://report-uri.cloudflare.com/expect-ct" + "expect_ct_report_uri": "https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct" }, { "name": "weeblrpress.com",
diff --git a/net/quic/quic_flags_list.h b/net/quic/quic_flags_list.h index f4ebcde..653a291 100644 --- a/net/quic/quic_flags_list.h +++ b/net/quic/quic_flags_list.h
@@ -310,3 +310,9 @@ // If true, QuicSpdyStream::WritevBody() will convert iovs into QuicMemSliceSpan // and call WriteMemSlices instead. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_call_write_mem_slices, false) + +// If true, enables the BBS4 and BBS5 connection options, which reduce BBR's +// pacing rate in STARTUP as more losses occur as a fraction of CWND. +QUIC_FLAG(bool, + FLAGS_quic_reloadable_flag_quic_bbr_startup_rate_reduction, + false)
diff --git a/net/third_party/http2/decoder/decode_http2_structures_test.cc b/net/third_party/http2/decoder/decode_http2_structures_test.cc index 5538bb8..2578ae50 100644 --- a/net/third_party/http2/decoder/decode_http2_structures_test.cc +++ b/net/third_party/http2/decoder/decode_http2_structures_test.cc
@@ -105,12 +105,12 @@ { // Realistic input. const char kData[] = { - 0x00, 0x00, 0x05, // Payload length: 5 - 0x01, // Frame type: HEADERS - 0x08, // Flags: PADDED - 0x00, 0x00, 0x00, 0x01, // Stream ID: 1 - 0x04, // Padding length: 4 - 0x00, 0x00, 0x00, 0x00, // Padding bytes + '\x00', '\x00', '\x05', // Payload length: 5 + '\x01', // Frame type: HEADERS + '\x08', // Flags: PADDED + '\x00', '\x00', '\x00', '\x01', // Stream ID: 1 + '\x04', // Padding length: 4 + '\x00', '\x00', '\x00', '\x00', // Padding bytes }; DecodeLeadingStructure(kData); if (!HasFailure()) { @@ -123,10 +123,10 @@ { // Unlikely input. const char kData[] = { - 0xffu, 0xffu, 0xffu, // Payload length: uint24 max - 0xffu, // Frame type: Unknown - 0xffu, // Flags: Unknown/All - 0xffu, 0xffu, 0xffu, 0xffu, // Stream ID: uint31 max, plus R-bit + '\xff', '\xff', '\xff', // Payload length: uint24 max + '\xff', // Frame type: Unknown + '\xff', // Flags: Unknown/All + '\xff', '\xff', '\xff', '\xff', // Stream ID: uint31 max, plus R-bit }; DecodeLeadingStructure(kData); if (!HasFailure()) { @@ -150,8 +150,8 @@ TEST_F(PriorityFieldsDecoderTest, DecodesLiteral) { { const char kData[] = { - 0x80u, 0x00, 0x00, 0x05, // Exclusive (yes) and Dependency (5) - 0xffu, // Weight: 256 (after adding 1) + '\x80', '\x00', '\x00', '\x05', // Exclusive (yes) and Dependency (5) + '\xff', // Weight: 256 (after adding 1) }; DecodeLeadingStructure(kData); if (!HasFailure()) { @@ -162,9 +162,9 @@ } { const char kData[] = { - 0x7f, 0xffu, - 0xffu, 0xffu, // Exclusive (no) and Dependency (0x7fffffff) - 0x00, // Weight: 1 (after adding 1) + '\x7f', '\xff', + '\xff', '\xff', // Exclusive (no) and Dependency (0x7fffffff) + '\x00', // Weight: 1 (after adding 1) }; DecodeLeadingStructure(kData); if (!HasFailure()) { @@ -187,7 +187,7 @@ TEST_F(RstStreamFieldsDecoderTest, DecodesLiteral) { { const char kData[] = { - 0x00, 0x00, 0x00, 0x01, // Error: PROTOCOL_ERROR + '\x00', '\x00', '\x00', '\x01', // Error: PROTOCOL_ERROR }; DecodeLeadingStructure(kData); if (!HasFailure()) { @@ -197,7 +197,8 @@ } { const char kData[] = { - 0xffu, 0xffu, 0xffu, 0xffu, // Error: max uint32 (Unknown error code) + '\xff', '\xff', '\xff', + '\xff', // Error: max uint32 (Unknown error code) }; DecodeLeadingStructure(kData); if (!HasFailure()) { @@ -219,8 +220,8 @@ TEST_F(SettingFieldsDecoderTest, DecodesLiteral) { { const char kData[] = { - 0x00, 0x01, // Setting: HEADER_TABLE_SIZE - 0x00, 0x00, 0x40, 0x00, // Value: 16K + '\x00', '\x01', // Setting: HEADER_TABLE_SIZE + '\x00', '\x00', '\x40', '\x00', // Value: 16K }; DecodeLeadingStructure(kData); if (!HasFailure()) { @@ -232,8 +233,8 @@ } { const char kData[] = { - 0x00, 0x00, // Setting: Unknown (0) - 0xffu, 0xffu, 0xffu, 0xffu, // Value: max uint32 + '\x00', '\x00', // Setting: Unknown (0) + '\xff', '\xff', '\xff', '\xff', // Value: max uint32 }; DecodeLeadingStructure(kData); if (!HasFailure()) { @@ -255,7 +256,7 @@ TEST_F(PushPromiseFieldsDecoderTest, DecodesLiteral) { { const char kData[] = { - 0x00, 0x01, 0x8au, 0x92u, // Promised Stream ID: 101010 + '\x00', '\x01', '\x8a', '\x92', // Promised Stream ID: 101010 }; DecodeLeadingStructure(kData); if (!HasFailure()) { @@ -266,7 +267,8 @@ // Promised stream id has R-bit (reserved for future use) set, which // should be cleared by the decoder. const char kData[] = { - 0xffu, 0xffu, 0xffu, 0xffu, // Promised Stream ID: max uint31 and R-bit + '\xff', '\xff', '\xff', + '\xff', // Promised Stream ID: max uint31 and R-bit }; DecodeLeadingStructure(kData); if (!HasFailure()) { @@ -287,7 +289,7 @@ { // Each byte is different, so can detect if order changed. const char kData[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', }; DecodeLeadingStructure(kData); if (!HasFailure()) { @@ -298,7 +300,7 @@ { // All zeros, detect problems handling NULs. const char kData[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', }; DecodeLeadingStructure(kData); if (!HasFailure()) { @@ -308,7 +310,7 @@ } { const char kData[] = { - 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, + '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', }; DecodeLeadingStructure(kData); if (!HasFailure()) { @@ -330,8 +332,8 @@ TEST_F(GoAwayFieldsDecoderTest, DecodesLiteral) { { const char kData[] = { - 0x00, 0x00, 0x00, 0x00, // Last Stream ID: 0 - 0x00, 0x00, 0x00, 0x00, // Error: NO_ERROR (0) + '\x00', '\x00', '\x00', '\x00', // Last Stream ID: 0 + '\x00', '\x00', '\x00', '\x00', // Error: NO_ERROR (0) }; DecodeLeadingStructure(kData); if (!HasFailure()) { @@ -342,8 +344,8 @@ } { const char kData[] = { - 0x00, 0x00, 0x00, 0x01, // Last Stream ID: 1 - 0x00, 0x00, 0x00, 0x0d, // Error: HTTP_1_1_REQUIRED + '\x00', '\x00', '\x00', '\x01', // Last Stream ID: 1 + '\x00', '\x00', '\x00', '\x0d', // Error: HTTP_1_1_REQUIRED }; DecodeLeadingStructure(kData); if (!HasFailure()) { @@ -354,8 +356,10 @@ } { const char kData[] = { - 0xffu, 0xffu, 0xffu, 0xffu, // Last Stream ID: max uint31 and R-bit - 0xffu, 0xffu, 0xffu, 0xffu, // Error: max uint32 (Unknown error code) + '\xff', '\xff', + '\xff', '\xff', // Last Stream ID: max uint31 and R-bit + '\xff', '\xff', + '\xff', '\xff', // Error: max uint32 (Unknown error code) }; DecodeLeadingStructure(kData); if (!HasFailure()) { @@ -378,7 +382,7 @@ TEST_F(WindowUpdateFieldsDecoderTest, DecodesLiteral) { { const char kData[] = { - 0x00, 0x01, 0x00, 0x00, // Window Size Increment: 2 ^ 16 + '\x00', '\x01', '\x00', '\x00', // Window Size Increment: 2 ^ 16 }; DecodeLeadingStructure(kData); if (!HasFailure()) { @@ -389,7 +393,7 @@ // Increment must be non-zero, but we need to be able to decode the invalid // zero to detect it. const char kData[] = { - 0x00, 0x00, 0x00, 0x00, // Window Size Increment: 0 + '\x00', '\x00', '\x00', '\x00', // Window Size Increment: 0 }; DecodeLeadingStructure(kData); if (!HasFailure()) { @@ -402,7 +406,7 @@ // clang-format off const char kData[] = { // Window Size Increment: max uint31 and R-bit - 0xffu, 0xffu, 0xffu, 0xffu, + '\xff', '\xff', '\xff', '\xff', }; // clang-format on DecodeLeadingStructure(kData); @@ -424,7 +428,7 @@ TEST_F(AltSvcFieldsDecoderTest, DecodesLiteral) { { const char kData[] = { - 0x00, 0x00, // Origin Length: 0 + '\x00', '\x00', // Origin Length: 0 }; DecodeLeadingStructure(kData); if (!HasFailure()) { @@ -433,7 +437,7 @@ } { const char kData[] = { - 0x00, 0x14, // Origin Length: 20 + '\x00', '\x14', // Origin Length: 20 }; DecodeLeadingStructure(kData); if (!HasFailure()) { @@ -442,7 +446,7 @@ } { const char kData[] = { - 0xffu, 0xffu, // Origin Length: uint16 max + '\xff', '\xff', // Origin Length: uint16 max }; DecodeLeadingStructure(kData); if (!HasFailure()) {
diff --git a/net/third_party/http2/decoder/http2_frame_decoder_test.cc b/net/third_party/http2/decoder/http2_frame_decoder_test.cc index f74c9115..96b8aaa 100644 --- a/net/third_party/http2/decoder/http2_frame_decoder_test.cc +++ b/net/third_party/http2/decoder/http2_frame_decoder_test.cc
@@ -226,10 +226,11 @@ TEST_F(Http2FrameDecoderTest, DataEmpty) { const char kFrameData[] = { - 0x00, 0x00, 0x00, // Payload length: 0 - 0x00, // DATA - 0x00, // Flags: none - 0x00, 0x00, 0x00, 0x00, // Stream ID: 0 (invalid but unchecked here) + '\x00', '\x00', '\x00', // Payload length: 0 + '\x00', // DATA + '\x00', // Flags: none + '\x00', '\x00', '\x00', + '\x00', // Stream ID: 0 (invalid but unchecked here) }; Http2FrameHeader header(0, Http2FrameType::DATA, 0, 0); FrameParts expected(header, ""); @@ -238,10 +239,10 @@ TEST_F(Http2FrameDecoderTest, HeadersEmpty) { const char kFrameData[] = { - 0x00, 0x00, 0x00, // Payload length: 0 - 0x01, // HEADERS - 0x00, // Flags: none - 0x00, 0x00, 0x00, 0x01, // Stream ID: 0 (REQUIRES ID) + '\x00', '\x00', '\x00', // Payload length: 0 + '\x01', // HEADERS + '\x00', // Flags: none + '\x00', '\x00', '\x00', '\x01', // Stream ID: 0 (REQUIRES ID) }; Http2FrameHeader header(0, Http2FrameType::HEADERS, 0, 1); FrameParts expected(header, ""); @@ -250,12 +251,12 @@ TEST_F(Http2FrameDecoderTest, Priority) { const char kFrameData[] = { - 0x00, 0x00, 0x05, // Length: 5 - 0x02, // Type: PRIORITY - 0x00, // Flags: none - 0x00, 0x00, 0x00, 0x02, // Stream: 2 - 0x80u, 0x00, 0x00, 0x01, // Parent: 1 (Exclusive) - 0x10, // Weight: 17 + '\x00', '\x00', '\x05', // Length: 5 + '\x02', // Type: PRIORITY + '\x00', // Flags: none + '\x00', '\x00', '\x00', '\x02', // Stream: 2 + '\x80', '\x00', '\x00', '\x01', // Parent: 1 (Exclusive) + '\x10', // Weight: 17 }; Http2FrameHeader header(5, Http2FrameType::PRIORITY, 0, 2); FrameParts expected(header); @@ -265,11 +266,11 @@ TEST_F(Http2FrameDecoderTest, RstStream) { const char kFrameData[] = { - 0x00, 0x00, 0x04, // Length: 4 - 0x03, // Type: RST_STREAM - 0x00, // Flags: none - 0x00, 0x00, 0x00, 0x01, // Stream: 1 - 0x00, 0x00, 0x00, 0x01, // Error: PROTOCOL_ERROR + '\x00', '\x00', '\x04', // Length: 4 + '\x03', // Type: RST_STREAM + '\x00', // Flags: none + '\x00', '\x00', '\x00', '\x01', // Stream: 1 + '\x00', '\x00', '\x00', '\x01', // Error: PROTOCOL_ERROR }; Http2FrameHeader header(4, Http2FrameType::RST_STREAM, 0, 1); FrameParts expected(header); @@ -279,10 +280,10 @@ TEST_F(Http2FrameDecoderTest, SettingsEmpty) { const char kFrameData[] = { - 0x00, 0x00, 0x00, // Length: 0 - 0x04, // Type: SETTINGS - 0x00, // Flags: none - 0x00, 0x00, 0x00, 0x01, // Stream: 1 (invalid but unchecked here) + '\x00', '\x00', '\x00', // Length: 0 + '\x04', // Type: SETTINGS + '\x00', // Flags: none + '\x00', '\x00', '\x00', '\x01', // Stream: 1 (invalid but unchecked here) }; Http2FrameHeader header(0, Http2FrameType::SETTINGS, 0, 1); EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, header)); @@ -290,10 +291,10 @@ TEST_F(Http2FrameDecoderTest, SettingsAck) { const char kFrameData[] = { - 0x00, 0x00, 0x00, // Length: 6 - 0x04, // Type: SETTINGS - 0x01, // Flags: ACK - 0x00, 0x00, 0x00, 0x00, // Stream: 0 + '\x00', '\x00', '\x00', // Length: 6 + '\x04', // Type: SETTINGS + '\x01', // Flags: ACK + '\x00', '\x00', '\x00', '\x00', // Stream: 0 }; Http2FrameHeader header(0, Http2FrameType::SETTINGS, Http2FrameFlag::ACK, 0); FrameParts expected(header); @@ -302,11 +303,13 @@ TEST_F(Http2FrameDecoderTest, PushPromiseMinimal) { const char kFrameData[] = { - 0x00, 0x00, 0x04, // Payload length: 4 - 0x05, // PUSH_PROMISE - 0x04, // Flags: END_HEADERS - 0x00, 0x00, 0x00, 0x02, // Stream: 2 (invalid but unchecked here) - 0x00, 0x00, 0x00, 0x01, // Promised: 1 (invalid but unchecked here) + '\x00', '\x00', '\x04', // Payload length: 4 + '\x05', // PUSH_PROMISE + '\x04', // Flags: END_HEADERS + '\x00', '\x00', '\x00', + '\x02', // Stream: 2 (invalid but unchecked here) + '\x00', '\x00', '\x00', + '\x01', // Promised: 1 (invalid but unchecked here) }; Http2FrameHeader header(4, Http2FrameType::PUSH_PROMISE, Http2FrameFlag::END_HEADERS, 2); @@ -317,12 +320,12 @@ TEST_F(Http2FrameDecoderTest, Ping) { const char kFrameData[] = { - 0x00, 0x00, 0x08, // Length: 8 - 0x06, // Type: PING - 0xfeu, // Flags: no valid flags - 0x00, 0x00, 0x00, 0x00, // Stream: 0 - 's', 'o', 'm', 'e', // "some" - 'd', 'a', 't', 'a', // "data" + '\x00', '\x00', '\x08', // Length: 8 + '\x06', // Type: PING + '\xfe', // Flags: no valid flags + '\x00', '\x00', '\x00', '\x00', // Stream: 0 + 's', 'o', 'm', 'e', // "some" + 'd', 'a', 't', 'a', // "data" }; Http2FrameHeader header(8, Http2FrameType::PING, 0, 0); FrameParts expected(header); @@ -333,12 +336,12 @@ TEST_F(Http2FrameDecoderTest, PingAck) { const char kFrameData[] = { - 0x00, 0x00, 0x08, // Length: 8 - 0x06, // Type: PING - 0xffu, // Flags: ACK (plus all invalid flags) - 0x00, 0x00, 0x00, 0x00, // Stream: 0 - 's', 'o', 'm', 'e', // "some" - 'd', 'a', 't', 'a', // "data" + '\x00', '\x00', '\x08', // Length: 8 + '\x06', // Type: PING + '\xff', // Flags: ACK (plus all invalid flags) + '\x00', '\x00', '\x00', '\x00', // Stream: 0 + 's', 'o', 'm', 'e', // "some" + 'd', 'a', 't', 'a', // "data" }; Http2FrameHeader header(8, Http2FrameType::PING, Http2FrameFlag::ACK, 0); FrameParts expected(header); @@ -349,12 +352,12 @@ TEST_F(Http2FrameDecoderTest, GoAwayMinimal) { const char kFrameData[] = { - 0x00, 0x00, 0x08, // Length: 8 (no opaque data) - 0x07, // Type: GOAWAY - 0xffu, // Flags: 0xff (no valid flags) - 0x00, 0x00, 0x00, 0x01, // Stream: 1 (invalid but unchecked here) - 0x80u, 0x00, 0x00, 0xffu, // Last: 255 (plus R bit) - 0x00, 0x00, 0x00, 0x09, // Error: COMPRESSION_ERROR + '\x00', '\x00', '\x08', // Length: 8 (no opaque data) + '\x07', // Type: GOAWAY + '\xff', // Flags: 0xff (no valid flags) + '\x00', '\x00', '\x00', '\x01', // Stream: 1 (invalid but unchecked here) + '\x80', '\x00', '\x00', '\xff', // Last: 255 (plus R bit) + '\x00', '\x00', '\x00', '\x09', // Error: COMPRESSION_ERROR }; Http2FrameHeader header(8, Http2FrameType::GOAWAY, 0, 1); FrameParts expected(header); @@ -365,11 +368,11 @@ TEST_F(Http2FrameDecoderTest, WindowUpdate) { const char kFrameData[] = { - 0x00, 0x00, 0x04, // Length: 4 - 0x08, // Type: WINDOW_UPDATE - 0x0f, // Flags: 0xff (no valid flags) - 0x00, 0x00, 0x00, 0x01, // Stream: 1 - 0x80u, 0x00, 0x04, 0x00, // Incr: 1024 (plus R bit) + '\x00', '\x00', '\x04', // Length: 4 + '\x08', // Type: WINDOW_UPDATE + '\x0f', // Flags: 0xff (no valid flags) + '\x00', '\x00', '\x00', '\x01', // Stream: 1 + '\x80', '\x00', '\x04', '\x00', // Incr: 1024 (plus R bit) }; Http2FrameHeader header(4, Http2FrameType::WINDOW_UPDATE, 0, 1); FrameParts expected(header); @@ -379,10 +382,11 @@ TEST_F(Http2FrameDecoderTest, ContinuationEmpty) { const char kFrameData[] = { - 0x00, 0x00, 0x00, // Payload length: 0 - 0x09, // CONTINUATION - 0x00, // Flags: none - 0x00, 0x00, 0x00, 0x00, // Stream ID: 0 (invalid but unchecked here) + '\x00', '\x00', '\x00', // Payload length: 0 + '\x09', // CONTINUATION + '\x00', // Flags: none + '\x00', '\x00', '\x00', + '\x00', // Stream ID: 0 (invalid but unchecked here) }; Http2FrameHeader header(0, Http2FrameType::CONTINUATION, 0, 0); FrameParts expected(header); @@ -391,11 +395,12 @@ TEST_F(Http2FrameDecoderTest, AltSvcMinimal) { const char kFrameData[] = { - 0x00, 0x00, 0x02, // Payload length: 2 - 0x0a, // ALTSVC - 0xffu, // Flags: none (plus 0xff) - 0x00, 0x00, 0x00, 0x00, // Stream ID: 0 (invalid but unchecked here) - 0x00, 0x00, // Origin Length: 0 + '\x00', '\x00', '\x02', // Payload length: 2 + '\x0a', // ALTSVC + '\xff', // Flags: none (plus 0xff) + '\x00', '\x00', '\x00', + '\x00', // Stream ID: 0 (invalid but unchecked here) + '\x00', '\x00', // Origin Length: 0 }; Http2FrameHeader header(2, Http2FrameType::ALTSVC, 0, 0); FrameParts expected(header); @@ -406,10 +411,10 @@ TEST_F(Http2FrameDecoderTest, UnknownEmpty) { const char kFrameData[] = { - 0x00, 0x00, 0x00, // Payload length: 0 - 0x20, // 32 (unknown) - 0xffu, // Flags: all - 0x00, 0x00, 0x00, 0x00, // Stream ID: 0 + '\x00', '\x00', '\x00', // Payload length: 0 + '\x20', // 32 (unknown) + '\xff', // Flags: all + '\x00', '\x00', '\x00', '\x00', // Stream ID: 0 }; Http2FrameHeader header(0, static_cast<Http2FrameType>(32), 0xff, 0); FrameParts expected(header); @@ -421,11 +426,11 @@ TEST_F(Http2FrameDecoderTest, DataPayload) { const char kFrameData[] = { - 0x00, 0x00, 0x03, // Payload length: 7 - 0x00, // DATA - 0x80u, // Flags: 0x80 - 0x00, 0x00, 0x02, 0x02, // Stream ID: 514 - 'a', 'b', 'c', // Data + '\x00', '\x00', '\x03', // Payload length: 7 + '\x00', // DATA + '\x80', // Flags: 0x80 + '\x00', '\x00', '\x02', '\x02', // Stream ID: 514 + 'a', 'b', 'c', // Data }; Http2FrameHeader header(3, Http2FrameType::DATA, 0, 514); FrameParts expected(header, "abc"); @@ -434,11 +439,11 @@ TEST_F(Http2FrameDecoderTest, HeadersPayload) { const char kFrameData[] = { - 0x00, 0x00, 0x03, // Payload length: 3 - 0x01, // HEADERS - 0x05, // Flags: END_STREAM | END_HEADERS - 0x00, 0x00, 0x00, 0x02, // Stream ID: 0 (REQUIRES ID) - 'a', 'b', 'c', // HPACK fragment (doesn't have to be valid) + '\x00', '\x00', '\x03', // Payload length: 3 + '\x01', // HEADERS + '\x05', // Flags: END_STREAM | END_HEADERS + '\x00', '\x00', '\x00', '\x02', // Stream ID: 0 (REQUIRES ID) + 'a', 'b', 'c', // HPACK fragment (doesn't have to be valid) }; Http2FrameHeader header( 3, Http2FrameType::HEADERS, @@ -449,12 +454,12 @@ TEST_F(Http2FrameDecoderTest, HeadersPriority) { const char kFrameData[] = { - 0x00, 0x00, 0x05, // Payload length: 5 - 0x01, // HEADERS - 0x20, // Flags: PRIORITY - 0x00, 0x00, 0x00, 0x02, // Stream ID: 0 (REQUIRES ID) - 0x00, 0x00, 0x00, 0x01, // Parent: 1 (Not Exclusive) - 0xffu, // Weight: 256 + '\x00', '\x00', '\x05', // Payload length: 5 + '\x01', // HEADERS + '\x20', // Flags: PRIORITY + '\x00', '\x00', '\x00', '\x02', // Stream ID: 0 (REQUIRES ID) + '\x00', '\x00', '\x00', '\x01', // Parent: 1 (Not Exclusive) + '\xff', // Weight: 256 }; Http2FrameHeader header(5, Http2FrameType::HEADERS, Http2FrameFlag::PRIORITY, 2); @@ -465,14 +470,14 @@ TEST_F(Http2FrameDecoderTest, Settings) { const char kFrameData[] = { - 0x00, 0x00, 0x0c, // Length: 12 - 0x04, // Type: SETTINGS - 0x00, // Flags: none - 0x00, 0x00, 0x00, 0x00, // Stream: 0 - 0x00, 0x04, // Param: INITIAL_WINDOW_SIZE - 0x0a, 0x0b, 0x0c, 0x0d, // Value: 168496141 - 0x00, 0x02, // Param: ENABLE_PUSH - 0x00, 0x00, 0x00, 0x03, // Value: 3 (invalid but unchecked here) + '\x00', '\x00', '\x0c', // Length: 12 + '\x04', // Type: SETTINGS + '\x00', // Flags: none + '\x00', '\x00', '\x00', '\x00', // Stream: 0 + '\x00', '\x04', // Param: INITIAL_WINDOW_SIZE + '\x0a', '\x0b', '\x0c', '\x0d', // Value: 168496141 + '\x00', '\x02', // Param: ENABLE_PUSH + '\x00', '\x00', '\x00', '\x03', // Value: 3 (invalid but unchecked here) }; Http2FrameHeader header(12, Http2FrameType::SETTINGS, 0, 0); FrameParts expected(header); @@ -485,12 +490,12 @@ TEST_F(Http2FrameDecoderTest, PushPromisePayload) { const char kFrameData[] = { - 0x00, 0x00, 7, // Payload length: 7 - 0x05, // PUSH_PROMISE - 0x04, // Flags: END_HEADERS - 0x00, 0x00, 0x00, 0xffu, // Stream ID: 255 - 0x00, 0x00, 0x01, 0x00, // Promised: 256 - 'a', 'b', 'c', // HPACK fragment (doesn't have to be valid) + '\x00', '\x00', 7, // Payload length: 7 + '\x05', // PUSH_PROMISE + '\x04', // Flags: END_HEADERS + '\x00', '\x00', '\x00', '\xff', // Stream ID: 255 + '\x00', '\x00', '\x01', '\x00', // Promised: 256 + 'a', 'b', 'c', // HPACK fragment (doesn't have to be valid) }; Http2FrameHeader header(7, Http2FrameType::PUSH_PROMISE, Http2FrameFlag::END_HEADERS, 255); @@ -501,13 +506,13 @@ TEST_F(Http2FrameDecoderTest, GoAwayOpaqueData) { const char kFrameData[] = { - 0x00, 0x00, 0x0e, // Length: 14 - 0x07, // Type: GOAWAY - 0xffu, // Flags: 0xff (no valid flags) - 0x80u, 0x00, 0x00, 0x00, // Stream: 0 (plus R bit) - 0x00, 0x00, 0x01, 0x00, // Last: 256 - 0x00, 0x00, 0x00, 0x03, // Error: FLOW_CONTROL_ERROR - 'o', 'p', 'a', 'q', 'u', 'e', + '\x00', '\x00', '\x0e', // Length: 14 + '\x07', // Type: GOAWAY + '\xff', // Flags: 0xff (no valid flags) + '\x80', '\x00', '\x00', '\x00', // Stream: 0 (plus R bit) + '\x00', '\x00', '\x01', '\x00', // Last: 256 + '\x00', '\x00', '\x00', '\x03', // Error: FLOW_CONTROL_ERROR + 'o', 'p', 'a', 'q', 'u', 'e', }; Http2FrameHeader header(14, Http2FrameType::GOAWAY, 0, 0); FrameParts expected(header, "opaque"); @@ -518,11 +523,11 @@ TEST_F(Http2FrameDecoderTest, ContinuationPayload) { const char kFrameData[] = { - 0x00, 0x00, 0x03, // Payload length: 3 - 0x09, // CONTINUATION - 0xffu, // Flags: END_HEADERS | 0xfb - 0x00, 0x00, 0x00, 0x02, // Stream ID: 2 - 'a', 'b', 'c', // Data + '\x00', '\x00', '\x03', // Payload length: 3 + '\x09', // CONTINUATION + '\xff', // Flags: END_HEADERS | 0xfb + '\x00', '\x00', '\x00', '\x02', // Stream ID: 2 + 'a', 'b', 'c', // Data }; Http2FrameHeader header(3, Http2FrameType::CONTINUATION, Http2FrameFlag::END_HEADERS, 2); @@ -532,13 +537,13 @@ TEST_F(Http2FrameDecoderTest, AltSvcPayload) { const char kFrameData[] = { - 0x00, 0x00, 0x08, // Payload length: 3 - 0x0a, // ALTSVC - 0x00, // Flags: none - 0x00, 0x00, 0x00, 0x02, // Stream ID: 2 - 0x00, 0x03, // Origin Length: 0 - 'a', 'b', 'c', // Origin - 'd', 'e', 'f', // Value + '\x00', '\x00', '\x08', // Payload length: 3 + '\x0a', // ALTSVC + '\x00', // Flags: none + '\x00', '\x00', '\x00', '\x02', // Stream ID: 2 + '\x00', '\x03', // Origin Length: 0 + 'a', 'b', 'c', // Origin + 'd', 'e', 'f', // Value }; Http2FrameHeader header(8, Http2FrameType::ALTSVC, 0, 2); FrameParts expected(header); @@ -548,11 +553,11 @@ TEST_F(Http2FrameDecoderTest, UnknownPayload) { const char kFrameData[] = { - 0x00, 0x00, 0x03, // Payload length: 3 - 0x30, // 48 (unknown) - 0x00, // Flags: none - 0x00, 0x00, 0x00, 0x02, // Stream ID: 2 - 'a', 'b', 'c', // Payload + '\x00', '\x00', '\x03', // Payload length: 3 + '\x30', // 48 (unknown) + '\x00', // Flags: none + '\x00', '\x00', '\x00', '\x02', // Stream ID: 2 + 'a', 'b', 'c', // Payload }; Http2FrameHeader header(3, static_cast<Http2FrameType>(48), 0, 2); FrameParts expected(header, "abc"); @@ -564,13 +569,13 @@ TEST_F(Http2FrameDecoderTest, DataPayloadAndPadding) { const char kFrameData[] = { - 0x00, 0x00, 0x07, // Payload length: 7 - 0x00, // DATA - 0x09, // Flags: END_STREAM | PADDED - 0x00, 0x00, 0x00, 0x02, // Stream ID: 0 (REQUIRES ID) - 0x03, // Pad Len - 'a', 'b', 'c', // Data - 0x00, 0x00, 0x00, // Padding + '\x00', '\x00', '\x07', // Payload length: 7 + '\x00', // DATA + '\x09', // Flags: END_STREAM | PADDED + '\x00', '\x00', '\x00', '\x02', // Stream ID: 0 (REQUIRES ID) + '\x03', // Pad Len + 'a', 'b', 'c', // Data + '\x00', '\x00', '\x00', // Padding }; Http2FrameHeader header(7, Http2FrameType::DATA, Http2FrameFlag::END_STREAM | Http2FrameFlag::PADDED, @@ -582,13 +587,13 @@ TEST_F(Http2FrameDecoderTest, HeadersPayloadAndPadding) { const char kFrameData[] = { - 0x00, 0x00, 0x07, // Payload length: 7 - 0x01, // HEADERS - 0x08, // Flags: PADDED - 0x00, 0x00, 0x00, 0x02, // Stream ID: 0 (REQUIRES ID) - 0x03, // Pad Len - 'a', 'b', 'c', // HPACK fragment (doesn't have to be valid) - 0x00, 0x00, 0x00, // Padding + '\x00', '\x00', '\x07', // Payload length: 7 + '\x01', // HEADERS + '\x08', // Flags: PADDED + '\x00', '\x00', '\x00', '\x02', // Stream ID: 0 (REQUIRES ID) + '\x03', // Pad Len + 'a', 'b', 'c', // HPACK fragment (doesn't have to be valid) + '\x00', '\x00', '\x00', // Padding }; Http2FrameHeader header(7, Http2FrameType::HEADERS, Http2FrameFlag::PADDED, 2); @@ -599,15 +604,15 @@ TEST_F(Http2FrameDecoderTest, HeadersPayloadPriorityAndPadding) { const char kFrameData[] = { - 0x00, 0x00, 0x0c, // Payload length: 12 - 0x01, // HEADERS - 0xffu, // Flags: all, including undefined - 0x00, 0x00, 0x00, 0x02, // Stream ID: 0 (REQUIRES ID) - 0x03, // Pad Len - 0x80u, 0x00, 0x00, 0x01, // Parent: 1 (Exclusive) - 0x10, // Weight: 17 - 'a', 'b', 'c', // HPACK fragment (doesn't have to be valid) - 0x00, 0x00, 0x00, // Padding + '\x00', '\x00', '\x0c', // Payload length: 12 + '\x01', // HEADERS + '\xff', // Flags: all, including undefined + '\x00', '\x00', '\x00', '\x02', // Stream ID: 0 (REQUIRES ID) + '\x03', // Pad Len + '\x80', '\x00', '\x00', '\x01', // Parent: 1 (Exclusive) + '\x10', // Weight: 17 + 'a', 'b', 'c', // HPACK fragment (doesn't have to be valid) + '\x00', '\x00', '\x00', // Padding }; Http2FrameHeader header(12, Http2FrameType::HEADERS, Http2FrameFlag::END_STREAM | @@ -622,14 +627,14 @@ TEST_F(Http2FrameDecoderTest, PushPromisePayloadAndPadding) { const char kFrameData[] = { - 0x00, 0x00, 11, // Payload length: 11 - 0x05, // PUSH_PROMISE - 0xffu, // Flags: END_HEADERS | PADDED | 0xf3 - 0x00, 0x00, 0x00, 0x01, // Stream ID: 1 - 0x03, // Pad Len - 0x00, 0x00, 0x00, 0x02, // Promised: 2 - 'a', 'b', 'c', // HPACK fragment (doesn't have to be valid) - 0x00, 0x00, 0x00, // Padding + '\x00', '\x00', 11, // Payload length: 11 + '\x05', // PUSH_PROMISE + '\xff', // Flags: END_HEADERS | PADDED | 0xf3 + '\x00', '\x00', '\x00', '\x01', // Stream ID: 1 + '\x03', // Pad Len + '\x00', '\x00', '\x00', '\x02', // Promised: 2 + 'a', 'b', 'c', // HPACK fragment (doesn't have to be valid) + '\x00', '\x00', '\x00', // Padding }; Http2FrameHeader header(11, Http2FrameType::PUSH_PROMISE, Http2FrameFlag::END_HEADERS | Http2FrameFlag::PADDED, @@ -645,10 +650,10 @@ TEST_F(Http2FrameDecoderTest, DataMissingPadLengthField) { const char kFrameData[] = { - 0x00, 0x00, 0x00, // Payload length: 0 - 0x00, // DATA - 0x08, // Flags: PADDED - 0x00, 0x00, 0x00, 0x01, // Stream ID: 1 + '\x00', '\x00', '\x00', // Payload length: 0 + '\x00', // DATA + '\x08', // Flags: PADDED + '\x00', '\x00', '\x00', '\x01', // Stream ID: 1 }; Http2FrameHeader header(0, Http2FrameType::DATA, Http2FrameFlag::PADDED, 1); FrameParts expected(header); @@ -658,12 +663,12 @@ TEST_F(Http2FrameDecoderTest, HeaderPaddingTooLong) { const char kFrameData[] = { - 0x00, 0x00, 0x02, // Payload length: 0 - 0x01, // HEADERS - 0x08, // Flags: PADDED - 0x00, 0x01, 0x00, 0x00, // Stream ID: 65536 - 0xffu, // Pad Len: 255 - 0x00, // Only one byte of padding + '\x00', '\x00', '\x02', // Payload length: 0 + '\x01', // HEADERS + '\x08', // Flags: PADDED + '\x00', '\x01', '\x00', '\x00', // Stream ID: 65536 + '\xff', // Pad Len: 255 + '\x00', // Only one byte of padding }; Http2FrameHeader header(2, Http2FrameType::HEADERS, Http2FrameFlag::PADDED, 65536); @@ -674,11 +679,11 @@ TEST_F(Http2FrameDecoderTest, HeaderMissingPriority) { const char kFrameData[] = { - 0x00, 0x00, 0x04, // Payload length: 0 - 0x01, // HEADERS - 0x20, // Flags: PRIORITY - 0x00, 0x01, 0x00, 0x00, // Stream ID: 65536 - 0x00, 0x00, 0x00, 0x00, // Priority (truncated) + '\x00', '\x00', '\x04', // Payload length: 0 + '\x01', // HEADERS + '\x20', // Flags: PRIORITY + '\x00', '\x01', '\x00', '\x00', // Stream ID: 65536 + '\x00', '\x00', '\x00', '\x00', // Priority (truncated) }; Http2FrameHeader header(4, Http2FrameType::HEADERS, Http2FrameFlag::PRIORITY, 65536); @@ -687,11 +692,11 @@ TEST_F(Http2FrameDecoderTest, PriorityTooShort) { const char kFrameData[] = { - 0x00, 0x00, 0x04, // Length: 5 - 0x02, // Type: PRIORITY - 0x00, // Flags: none - 0x00, 0x00, 0x00, 0x02, // Stream: 2 - 0x80u, 0x00, 0x00, 0x01, // Parent: 1 (Exclusive) + '\x00', '\x00', '\x04', // Length: 5 + '\x02', // Type: PRIORITY + '\x00', // Flags: none + '\x00', '\x00', '\x00', '\x02', // Stream: 2 + '\x80', '\x00', '\x00', '\x01', // Parent: 1 (Exclusive) }; Http2FrameHeader header(4, Http2FrameType::PRIORITY, 0, 2); EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); @@ -699,11 +704,11 @@ TEST_F(Http2FrameDecoderTest, RstStreamTooShort) { const char kFrameData[] = { - 0x00, 0x00, 0x03, // Length: 4 - 0x03, // Type: RST_STREAM - 0x00, // Flags: none - 0x00, 0x00, 0x00, 0x01, // Stream: 1 - 0x00, 0x00, 0x00, // Truncated + '\x00', '\x00', '\x03', // Length: 4 + '\x03', // Type: RST_STREAM + '\x00', // Flags: none + '\x00', '\x00', '\x00', '\x01', // Stream: 1 + '\x00', '\x00', '\x00', // Truncated }; Http2FrameHeader header(3, Http2FrameType::RST_STREAM, 0, 1); EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); @@ -713,14 +718,14 @@ // invalid. TEST_F(Http2FrameDecoderTest, SettingsWrongSize) { const char kFrameData[] = { - 0x00, 0x00, 0x09, // Length: 2 - 0x04, // Type: SETTINGS - 0x00, // Flags: none - 0x00, 0x00, 0x00, 0x00, // Stream: 0 - 0x00, 0x02, // Param: ENABLE_PUSH - 0x00, 0x00, 0x00, 0x03, // Value: 1 - 0x00, 0x04, // Param: INITIAL_WINDOW_SIZE - 0x00, // Value: Truncated + '\x00', '\x00', '\x09', // Length: 2 + '\x04', // Type: SETTINGS + '\x00', // Flags: none + '\x00', '\x00', '\x00', '\x00', // Stream: 0 + '\x00', '\x02', // Param: ENABLE_PUSH + '\x00', '\x00', '\x00', '\x03', // Value: 1 + '\x00', '\x04', // Param: INITIAL_WINDOW_SIZE + '\x00', // Value: Truncated }; Http2FrameHeader header(9, Http2FrameType::SETTINGS, 0, 0); FrameParts expected(header); @@ -731,11 +736,11 @@ TEST_F(Http2FrameDecoderTest, PushPromiseTooShort) { const char kFrameData[] = { - 0x00, 0x00, 3, // Payload length: 3 - 0x05, // PUSH_PROMISE - 0x00, // Flags: none - 0x00, 0x00, 0x00, 0x01, // Stream ID: 1 - 0x00, 0x00, 0x00, // Truncated promise id + '\x00', '\x00', 3, // Payload length: 3 + '\x05', // PUSH_PROMISE + '\x00', // Flags: none + '\x00', '\x00', '\x00', '\x01', // Stream ID: 1 + '\x00', '\x00', '\x00', // Truncated promise id }; Http2FrameHeader header(3, Http2FrameType::PUSH_PROMISE, 0, 1); EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); @@ -743,12 +748,12 @@ TEST_F(Http2FrameDecoderTest, PushPromisePaddedTruncatedPromise) { const char kFrameData[] = { - 0x00, 0x00, 4, // Payload length: 4 - 0x05, // PUSH_PROMISE - 0x08, // Flags: PADDED - 0x00, 0x00, 0x00, 0x01, // Stream ID: 1 - 0x00, // Pad Len - 0x00, 0x00, 0x00, // Truncated promise id + '\x00', '\x00', 4, // Payload length: 4 + '\x05', // PUSH_PROMISE + '\x08', // Flags: PADDED + '\x00', '\x00', '\x00', '\x01', // Stream ID: 1 + '\x00', // Pad Len + '\x00', '\x00', '\x00', // Truncated promise id }; Http2FrameHeader header(4, Http2FrameType::PUSH_PROMISE, Http2FrameFlag::PADDED, 1); @@ -757,12 +762,12 @@ TEST_F(Http2FrameDecoderTest, PingTooShort) { const char kFrameData[] = { - 0x00, 0x00, 0x07, // Length: 8 - 0x06, // Type: PING - 0xfeu, // Flags: no valid flags - 0x00, 0x00, 0x00, 0x00, // Stream: 0 - 's', 'o', 'm', 'e', // "some" - 'd', 'a', 't', // Too little + '\x00', '\x00', '\x07', // Length: 8 + '\x06', // Type: PING + '\xfe', // Flags: no valid flags + '\x00', '\x00', '\x00', '\x00', // Stream: 0 + 's', 'o', 'm', 'e', // "some" + 'd', 'a', 't', // Too little }; Http2FrameHeader header(7, Http2FrameType::PING, 0, 0); EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); @@ -770,10 +775,10 @@ TEST_F(Http2FrameDecoderTest, GoAwayTooShort) { const char kFrameData[] = { - 0x00, 0x00, 0x00, // Length: 0 - 0x07, // Type: GOAWAY - 0xffu, // Flags: 0xff (no valid flags) - 0x00, 0x00, 0x00, 0x00, // Stream: 0 + '\x00', '\x00', '\x00', // Length: 0 + '\x07', // Type: GOAWAY + '\xff', // Flags: 0xff (no valid flags) + '\x00', '\x00', '\x00', '\x00', // Stream: 0 }; Http2FrameHeader header(0, Http2FrameType::GOAWAY, 0, 0); EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); @@ -781,11 +786,11 @@ TEST_F(Http2FrameDecoderTest, WindowUpdateTooShort) { const char kFrameData[] = { - 0x00, 0x00, 0x03, // Length: 3 - 0x08, // Type: WINDOW_UPDATE - 0x0f, // Flags: 0xff (no valid flags) - 0x00, 0x00, 0x00, 0x01, // Stream: 1 - 0x80u, 0x00, 0x04, // Truncated + '\x00', '\x00', '\x03', // Length: 3 + '\x08', // Type: WINDOW_UPDATE + '\x0f', // Flags: 0xff (no valid flags) + '\x00', '\x00', '\x00', '\x01', // Stream: 1 + '\x80', '\x00', '\x04', // Truncated }; Http2FrameHeader header(3, Http2FrameType::WINDOW_UPDATE, 0, 1); EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); @@ -793,11 +798,11 @@ TEST_F(Http2FrameDecoderTest, AltSvcTruncatedOriginLength) { const char kFrameData[] = { - 0x00, 0x00, 0x01, // Payload length: 3 - 0x0a, // ALTSVC - 0x00, // Flags: none - 0x00, 0x00, 0x00, 0x02, // Stream ID: 2 - 0x00, // Origin Length: truncated + '\x00', '\x00', '\x01', // Payload length: 3 + '\x0a', // ALTSVC + '\x00', // Flags: none + '\x00', '\x00', '\x00', '\x02', // Stream ID: 2 + '\x00', // Origin Length: truncated }; Http2FrameHeader header(1, Http2FrameType::ALTSVC, 0, 2); EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); @@ -805,12 +810,12 @@ TEST_F(Http2FrameDecoderTest, AltSvcTruncatedOrigin) { const char kFrameData[] = { - 0x00, 0x00, 0x05, // Payload length: 3 - 0x0a, // ALTSVC - 0x00, // Flags: none - 0x00, 0x00, 0x00, 0x02, // Stream ID: 2 - 0x00, 0x04, // Origin Length: 4 (too long) - 'a', 'b', 'c', // Origin + '\x00', '\x00', '\x05', // Payload length: 3 + '\x0a', // ALTSVC + '\x00', // Flags: none + '\x00', '\x00', '\x00', '\x02', // Stream ID: 2 + '\x00', '\x04', // Origin Length: 4 (too long) + 'a', 'b', 'c', // Origin }; Http2FrameHeader header(5, Http2FrameType::ALTSVC, 0, 2); EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); @@ -824,13 +829,13 @@ TEST_F(Http2FrameDecoderTest, BeyondMaximum) { decoder_.set_maximum_payload_size(2); const char kFrameData[] = { - 0x00, 0x00, 0x07, // Payload length: 7 - 0x00, // DATA - 0x09, // Flags: END_STREAM | PADDED - 0x00, 0x00, 0x00, 0x02, // Stream ID: 0 (REQUIRES ID) - 0x03, // Pad Len - 'a', 'b', 'c', // Data - 0x00, 0x00, 0x00, // Padding + '\x00', '\x00', '\x07', // Payload length: 7 + '\x00', // DATA + '\x09', // Flags: END_STREAM | PADDED + '\x00', '\x00', '\x00', '\x02', // Stream ID: 0 (REQUIRES ID) + '\x03', // Pad Len + 'a', 'b', 'c', // Data + '\x00', '\x00', '\x00', // Padding }; Http2FrameHeader header(7, Http2FrameType::DATA, Http2FrameFlag::END_STREAM | Http2FrameFlag::PADDED, @@ -854,13 +859,13 @@ TEST_F(Http2FrameDecoderTest, PriorityTooLong) { const char kFrameData[] = { - 0x00, 0x00, 0x06, // Length: 5 - 0x02, // Type: PRIORITY - 0x00, // Flags: none - 0x00, 0x00, 0x00, 0x02, // Stream: 2 - 0x80u, 0x00, 0x00, 0x01, // Parent: 1 (Exclusive) - 0x10, // Weight: 17 - 0x00, // Too much + '\x00', '\x00', '\x06', // Length: 5 + '\x02', // Type: PRIORITY + '\x00', // Flags: none + '\x00', '\x00', '\x00', '\x02', // Stream: 2 + '\x80', '\x00', '\x00', '\x01', // Parent: 1 (Exclusive) + '\x10', // Weight: 17 + '\x00', // Too much }; Http2FrameHeader header(6, Http2FrameType::PRIORITY, 0, 2); EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); @@ -868,12 +873,12 @@ TEST_F(Http2FrameDecoderTest, RstStreamTooLong) { const char kFrameData[] = { - 0x00, 0x00, 0x05, // Length: 4 - 0x03, // Type: RST_STREAM - 0x00, // Flags: none - 0x00, 0x00, 0x00, 0x01, // Stream: 1 - 0x00, 0x00, 0x00, 0x01, // Error: PROTOCOL_ERROR - 0x00, // Too much + '\x00', '\x00', '\x05', // Length: 4 + '\x03', // Type: RST_STREAM + '\x00', // Flags: none + '\x00', '\x00', '\x00', '\x01', // Stream: 1 + '\x00', '\x00', '\x00', '\x01', // Error: PROTOCOL_ERROR + '\x00', // Too much }; Http2FrameHeader header(5, Http2FrameType::RST_STREAM, 0, 1); EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); @@ -881,12 +886,12 @@ TEST_F(Http2FrameDecoderTest, SettingsAckTooLong) { const char kFrameData[] = { - 0x00, 0x00, 0x06, // Length: 6 - 0x04, // Type: SETTINGS - 0x01, // Flags: ACK - 0x00, 0x00, 0x00, 0x00, // Stream: 0 - 0x00, 0x00, // Extra - 0x00, 0x00, 0x00, 0x00, // Extra + '\x00', '\x00', '\x06', // Length: 6 + '\x04', // Type: SETTINGS + '\x01', // Flags: ACK + '\x00', '\x00', '\x00', '\x00', // Stream: 0 + '\x00', '\x00', // Extra + '\x00', '\x00', '\x00', '\x00', // Extra }; Http2FrameHeader header(6, Http2FrameType::SETTINGS, Http2FrameFlag::ACK, 0); EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); @@ -894,13 +899,13 @@ TEST_F(Http2FrameDecoderTest, PingAckTooLong) { const char kFrameData[] = { - 0x00, 0x00, 0x09, // Length: 8 - 0x06, // Type: PING - 0xffu, // Flags: ACK | 0xfe - 0x00, 0x00, 0x00, 0x00, // Stream: 0 - 's', 'o', 'm', 'e', // "some" - 'd', 'a', 't', 'a', // "data" - 0x00, // Too much + '\x00', '\x00', '\x09', // Length: 8 + '\x06', // Type: PING + '\xff', // Flags: ACK | 0xfe + '\x00', '\x00', '\x00', '\x00', // Stream: 0 + 's', 'o', 'm', 'e', // "some" + 'd', 'a', 't', 'a', // "data" + '\x00', // Too much }; Http2FrameHeader header(9, Http2FrameType::PING, Http2FrameFlag::ACK, 0); EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); @@ -908,12 +913,12 @@ TEST_F(Http2FrameDecoderTest, WindowUpdateTooLong) { const char kFrameData[] = { - 0x00, 0x00, 0x05, // Length: 5 - 0x08, // Type: WINDOW_UPDATE - 0x0f, // Flags: 0xff (no valid flags) - 0x00, 0x00, 0x00, 0x01, // Stream: 1 - 0x80u, 0x00, 0x04, 0x00, // Incr: 1024 (plus R bit) - 0x00, // Too much + '\x00', '\x00', '\x05', // Length: 5 + '\x08', // Type: WINDOW_UPDATE + '\x0f', // Flags: 0xff (no valid flags) + '\x00', '\x00', '\x00', '\x01', // Stream: 1 + '\x80', '\x00', '\x04', '\x00', // Incr: 1024 (plus R bit) + '\x00', // Too much }; Http2FrameHeader header(5, Http2FrameType::WINDOW_UPDATE, 0, 1); EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
diff --git a/net/third_party/http2/hpack/decoder/hpack_entry_decoder_test.cc b/net/third_party/http2/hpack/decoder/hpack_entry_decoder_test.cc index 952dbf1d..cf0e9fc 100644 --- a/net/third_party/http2/hpack/decoder/hpack_entry_decoder_test.cc +++ b/net/third_party/http2/hpack/decoder/hpack_entry_decoder_test.cc
@@ -56,7 +56,7 @@ TEST_F(HpackEntryDecoderTest, IndexedHeader_Literals) { { - const char input[] = {0x82u}; // == Index 2 == + const char input[] = {'\x82'}; // == Index 2 == DecodeBuffer b(input); auto do_check = [this]() { VERIFY_AND_RETURN_SUCCESS(collector_.ValidateIndexedHeader(2)); @@ -67,7 +67,7 @@ } collector_.Clear(); { - const char input[] = {0xfeu}; // == Index 126 == + const char input[] = {'\xfe'}; // == Index 126 == DecodeBuffer b(input); auto do_check = [this]() { VERIFY_AND_RETURN_SUCCESS(collector_.ValidateIndexedHeader(126)); @@ -78,7 +78,7 @@ } collector_.Clear(); { - const char input[] = {0xffu, 0x00}; // == Index 127 == + const char input[] = {'\xff', '\x00'}; // == Index 127 == DecodeBuffer b(input); auto do_check = [this]() { VERIFY_AND_RETURN_SUCCESS(collector_.ValidateIndexedHeader(127));
diff --git a/net/third_party/http2/hpack/decoder/hpack_string_decoder_test.cc b/net/third_party/http2/hpack/decoder/hpack_string_decoder_test.cc index 996895da..57a6f3c 100644 --- a/net/third_party/http2/hpack/decoder/hpack_string_decoder_test.cc +++ b/net/third_party/http2/hpack/decoder/hpack_string_decoder_test.cc
@@ -81,7 +81,7 @@ TEST_F(HpackStringDecoderTest, DecodeEmptyString) { { Validator validator = ValidateDoneAndEmpty(MakeValidator("", kCompressed)); - const char kData[] = {0x80u}; + const char kData[] = {'\x80'}; DecodeBuffer b(kData); EXPECT_TRUE( DecodeAndValidateSeveralWays(&b, kMayReturnZeroOnFirst, validator)); @@ -90,7 +90,7 @@ // Make sure it stops after decoding the empty string. Validator validator = ValidateDoneAndOffset(1, MakeValidator("", kUncompressed)); - const char kData[] = {0x00, 0xffu}; + const char kData[] = {'\x00', '\xff'}; DecodeBuffer b(kData); EXPECT_EQ(2u, b.Remaining()); EXPECT_TRUE(
diff --git a/net/third_party/http2/hpack/tools/hpack_block_builder_test.cc b/net/third_party/http2/hpack/tools/hpack_block_builder_test.cc index 4cd786e..33e8a5f 100644 --- a/net/third_party/http2/hpack/tools/hpack_block_builder_test.cc +++ b/net/third_party/http2/hpack/tools/hpack_block_builder_test.cc
@@ -115,9 +115,9 @@ b.AppendIndexedHeader(kStaticTableMethodGET); b.AppendIndexedHeader(kStaticTableSchemeHttp); b.AppendIndexedHeader(kStaticTablePathSlash); - const char kHuffmanWwwExampleCom[] = {0xf1u, 0xe3u, 0xc2u, 0xe5u, - 0xf2u, 0x3au, 0x6bu, 0xa0u, - 0xabu, 0x90u, 0xf4u, 0xffu}; + const char kHuffmanWwwExampleCom[] = {'\xf1', '\xe3', '\xc2', '\xe5', + '\xf2', '\x3a', '\x6b', '\xa0', + '\xab', '\x90', '\xf4', '\xff'}; b.AppendNameIndexAndLiteralValue( HpackEntryType::kIndexedLiteralHeader, 1, kCompressed, Http2StringPiece(kHuffmanWwwExampleCom, sizeof kHuffmanWwwExampleCom)); @@ -139,7 +139,7 @@ b.AppendDynamicTableSizeUpdate(0); EXPECT_EQ(1u, b.size()); - const char kData[] = {0x20}; + const char kData[] = {'\x20'}; Http2StringPiece expected(kData, sizeof kData); EXPECT_EQ(expected, b.buffer()); } @@ -148,7 +148,7 @@ b.AppendDynamicTableSizeUpdate(4096); // The default size. EXPECT_EQ(3u, b.size()); - const char kData[] = {0x3f, 0xe1u, 0x1f}; + const char kData[] = {'\x3f', '\xe1', '\x1f'}; Http2StringPiece expected(kData, sizeof kData); EXPECT_EQ(expected, b.buffer()); } @@ -157,7 +157,8 @@ b.AppendDynamicTableSizeUpdate(1000000000000); // A very large value. EXPECT_EQ(7u, b.size()); - const char kData[] = {0x3fu, 0xe1u, 0x9fu, 0x94u, 0xa5u, 0x8du, 0x1du}; + const char kData[] = {'\x3f', '\xe1', '\x9f', '\x94', + '\xa5', '\x8d', '\x1d'}; Http2StringPiece expected(kData, sizeof kData); EXPECT_EQ(expected, b.buffer()); }
diff --git a/net/third_party/quic/core/congestion_control/bbr_sender.cc b/net/third_party/quic/core/congestion_control/bbr_sender.cc index 7546844..02b29f5 100644 --- a/net/third_party/quic/core/congestion_control/bbr_sender.cc +++ b/net/third_party/quic/core/congestion_control/bbr_sender.cc
@@ -127,6 +127,8 @@ is_app_limited_recovery_(false), slower_startup_(false), rate_based_startup_(false), + startup_rate_reduction_multiplier_(0), + startup_bytes_lost_(0), initial_conservation_in_startup_(CONSERVATION), enable_ack_aggregation_during_startup_(false), expire_ack_aggregation_in_startup_(false), @@ -267,6 +269,18 @@ if (config.HasClientRequestedIndependentOption(kBBS3, perspective)) { initial_conservation_in_startup_ = GROWTH; } + if (GetQuicReloadableFlag(quic_bbr_startup_rate_reduction) && + config.HasClientRequestedIndependentOption(kBBS4, perspective)) { + rate_based_startup_ = true; + // Hits 1.25x pacing multiplier when ~2/3 CWND is lost. + startup_rate_reduction_multiplier_ = 1; + } + if (GetQuicReloadableFlag(quic_bbr_startup_rate_reduction) && + config.HasClientRequestedIndependentOption(kBBS5, perspective)) { + rate_based_startup_ = true; + // Hits 1.25x pacing multiplier when ~1/3 CWND is lost. + startup_rate_reduction_multiplier_ = 2; + } if (config.HasClientRequestedIndependentOption(kBBR4, perspective)) { max_ack_height_.SetWindowLength(2 * kBandwidthWindowSize); } @@ -446,6 +460,9 @@ void BbrSender::DiscardLostPackets(const LostPacketVector& lost_packets) { for (const LostPacket& packet : lost_packets) { sampler_.OnPacketLost(packet.packet_number); + if (startup_rate_reduction_multiplier_ != 0 && mode_ == STARTUP) { + startup_bytes_lost_ += packet.bytes_lost; + } } } @@ -749,7 +766,23 @@ return; } - // Do not decrease the pacing rate during the startup. + // Slow the pacing rate in STARTUP by the bytes_lost / CWND. + if (startup_rate_reduction_multiplier_ != 0 && has_ever_detected_loss && + has_non_app_limited_sample_) { + if (startup_bytes_lost_ > congestion_window_) { + pacing_rate_ = BandwidthEstimate(); + } else { + pacing_rate_ = + (1 - (startup_bytes_lost_ * startup_rate_reduction_multiplier_ * + 1.0f / congestion_window_)) * + target_rate; + // Ensure the pacing rate doesn't drop below the bandwidth estimate. + pacing_rate_ = std::max(pacing_rate_, BandwidthEstimate()); + } + return; + } + + // Do not decrease the pacing rate during startup. pacing_rate_ = std::max(pacing_rate_, target_rate); }
diff --git a/net/third_party/quic/core/congestion_control/bbr_sender.h b/net/third_party/quic/core/congestion_control/bbr_sender.h index a8b2ea2..a33f65f 100644 --- a/net/third_party/quic/core/congestion_control/bbr_sender.h +++ b/net/third_party/quic/core/congestion_control/bbr_sender.h
@@ -369,6 +369,12 @@ bool slower_startup_; // When true, disables packet conservation in STARTUP. bool rate_based_startup_; + // When non-zero, decreases the rate in STARTUP by the total number of bytes + // lost in STARTUP divided by CWND. + uint8_t startup_rate_reduction_multiplier_; + // Sum of bytes lost in STARTUP. + QuicByteCount startup_bytes_lost_; + // Used as the initial packet conservation mode when first entering recovery. RecoveryState initial_conservation_in_startup_; // When true, add the most recent ack aggregation measurement during STARTUP.
diff --git a/net/third_party/quic/core/congestion_control/bbr_sender_test.cc b/net/third_party/quic/core/congestion_control/bbr_sender_test.cc index 11d366e29..9b13a9d6 100644 --- a/net/third_party/quic/core/congestion_control/bbr_sender_test.cc +++ b/net/third_party/quic/core/congestion_control/bbr_sender_test.cc
@@ -1152,6 +1152,106 @@ EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited); } +// Ensures no change in congestion window in STARTUP after loss, but that the +// rate decreases. +TEST_F(BbrSenderTest, SimpleTransferStartupRateReduction) { + SetQuicReloadableFlag(quic_bbr_startup_rate_reduction, true); + CreateSmallBufferSetup(); + + SetConnectionOption(kBBS4); + + // Run until the full bandwidth is reached and check how many rounds it was. + bbr_sender_.AddBytesToTransfer(12 * 1024 * 1024); + bool used_conservation_cwnd = false; + bool simulator_result = simulator_.RunUntilOrTimeout( + [this, &used_conservation_cwnd]() { + if (!sender_->ExportDebugState().is_at_full_bandwidth && + sender_->GetCongestionWindow() < + sender_->ExportDebugState().congestion_window) { + used_conservation_cwnd = true; + } + // Exit once a loss is hit. + return bbr_sender_.connection()->GetStats().packets_lost > 0 || + sender_->ExportDebugState().is_at_full_bandwidth; + }, + QuicTime::Delta::FromSeconds(5)); + ASSERT_TRUE(simulator_result); + EXPECT_TRUE(sender_->InRecovery()); + EXPECT_FALSE(used_conservation_cwnd); + EXPECT_EQ(BbrSender::STARTUP, sender_->ExportDebugState().mode); + EXPECT_NE(0u, bbr_sender_.connection()->GetStats().packets_lost); + + // Lose each outstanding packet and the pacing rate decreases. + const QuicBandwidth original_pacing_rate = sender_->PacingRate(0); + QuicBandwidth pacing_rate = original_pacing_rate; + const QuicByteCount original_cwnd = sender_->GetCongestionWindow(); + LostPacketVector lost_packets; + lost_packets.push_back(LostPacket(0, kMaxPacketSize)); + QuicPacketNumber largest_sent = + bbr_sender_.connection()->sent_packet_manager().GetLargestSentPacket(); + for (QuicPacketNumber packet_number = + bbr_sender_.connection()->sent_packet_manager().GetLeastUnacked(); + packet_number <= largest_sent; ++packet_number) { + lost_packets[0].packet_number = packet_number; + sender_->OnCongestionEvent(false, 0, clock_->Now(), {}, lost_packets); + EXPECT_EQ(original_cwnd, sender_->GetCongestionWindow()); + EXPECT_GT(original_pacing_rate, sender_->PacingRate(0)); + EXPECT_GE(pacing_rate, sender_->PacingRate(0)); + EXPECT_LE(sender_->BandwidthEstimate(), sender_->PacingRate(0)); + pacing_rate = sender_->PacingRate(0); + } +} + +// Ensures no change in congestion window in STARTUP after loss, but that the +// rate decreases twice as fast as BBS4. +TEST_F(BbrSenderTest, SimpleTransferDoubleStartupRateReduction) { + SetQuicReloadableFlag(quic_bbr_startup_rate_reduction, true); + CreateSmallBufferSetup(); + + SetConnectionOption(kBBS5); + + // Run until the full bandwidth is reached and check how many rounds it was. + bbr_sender_.AddBytesToTransfer(12 * 1024 * 1024); + bool used_conservation_cwnd = false; + bool simulator_result = simulator_.RunUntilOrTimeout( + [this, &used_conservation_cwnd]() { + if (!sender_->ExportDebugState().is_at_full_bandwidth && + sender_->GetCongestionWindow() < + sender_->ExportDebugState().congestion_window) { + used_conservation_cwnd = true; + } + // Exit once a loss is hit. + return bbr_sender_.connection()->GetStats().packets_lost > 0 || + sender_->ExportDebugState().is_at_full_bandwidth; + }, + QuicTime::Delta::FromSeconds(5)); + ASSERT_TRUE(simulator_result); + EXPECT_TRUE(sender_->InRecovery()); + EXPECT_FALSE(used_conservation_cwnd); + EXPECT_EQ(BbrSender::STARTUP, sender_->ExportDebugState().mode); + EXPECT_NE(0u, bbr_sender_.connection()->GetStats().packets_lost); + + // Lose each outstanding packet and the pacing rate decreases. + const QuicBandwidth original_pacing_rate = sender_->PacingRate(0); + QuicBandwidth pacing_rate = original_pacing_rate; + const QuicByteCount original_cwnd = sender_->GetCongestionWindow(); + LostPacketVector lost_packets; + lost_packets.push_back(LostPacket(0, kMaxPacketSize)); + QuicPacketNumber largest_sent = + bbr_sender_.connection()->sent_packet_manager().GetLargestSentPacket(); + for (QuicPacketNumber packet_number = + bbr_sender_.connection()->sent_packet_manager().GetLeastUnacked(); + packet_number <= largest_sent; ++packet_number) { + lost_packets[0].packet_number = packet_number; + sender_->OnCongestionEvent(false, 0, clock_->Now(), {}, lost_packets); + EXPECT_EQ(original_cwnd, sender_->GetCongestionWindow()); + EXPECT_GT(original_pacing_rate, sender_->PacingRate(0)); + EXPECT_GE(pacing_rate, sender_->PacingRate(0)); + EXPECT_LE(sender_->BandwidthEstimate(), sender_->PacingRate(0)); + pacing_rate = sender_->PacingRate(0); + } +} + TEST_F(BbrSenderTest, DerivedPacingGainStartup) { SetQuicReloadableFlag(quic_bbr_slower_startup3, true); CreateDefaultSetup();
diff --git a/net/third_party/quic/core/crypto/crypto_protocol.h b/net/third_party/quic/core/crypto/crypto_protocol.h index 8bee977..b4c185c 100644 --- a/net/third_party/quic/core/crypto/crypto_protocol.h +++ b/net/third_party/quic/core/crypto/crypto_protocol.h
@@ -86,6 +86,10 @@ // conservation in BBR STARTUP const QuicTag kBBS3 = TAG('B', 'B', 'S', '3'); // Slowstart packet // conservation in BBR STARTUP +const QuicTag kBBS4 = TAG('B', 'B', 'S', '4'); // Reduce rate in STARTUP by + // bytes_lost / CWND. +const QuicTag kBBS5 = TAG('B', 'B', 'S', '5'); // Reduce rate in STARTUP by + // 2 * bytes_lost / CWND. const QuicTag kBBRR = TAG('B', 'B', 'R', 'R'); // Rate-based recovery in BBR const QuicTag kBBR1 = TAG('B', 'B', 'R', '1'); // DEPRECATED const QuicTag kBBR2 = TAG('B', 'B', 'R', '2'); // DEPRECATED
diff --git a/services/audio/loopback_stream.cc b/services/audio/loopback_stream.cc index 9755a46..11d741b21 100644 --- a/services/audio/loopback_stream.cc +++ b/services/audio/loopback_stream.cc
@@ -376,29 +376,35 @@ // or more intervals. const int frames_per_buffer = mix_bus_->frames(); frames_elapsed_ += frames_per_buffer; - const base::TimeTicks now = clock_->NowTicks(); - const int64_t required_frames_elapsed = - (now - first_generate_time_).InMicroseconds() * - output_params_.sample_rate() / base::Time::kMicrosecondsPerSecond; - if (frames_elapsed_ < required_frames_elapsed) { - TRACE_EVENT_INSTANT1("audio", "GenerateMoreAudio Is Behind", - TRACE_EVENT_SCOPE_THREAD, "frames_behind", - (required_frames_elapsed - frames_elapsed_)); - // Audio generation has fallen behind. Skip-ahead the frame counter so that - // audio generation will resume for the next buffer after the one that - // should be generating right now. http://crbug.com/847487 - const int64_t required_buffers_elapsed = - ((required_frames_elapsed + frames_per_buffer - 1) / frames_per_buffer); - frames_elapsed_ = (required_buffers_elapsed + 1) * frames_per_buffer; - } next_generate_time_ = first_generate_time_ + base::TimeDelta::FromMicroseconds(frames_elapsed_ * base::Time::kMicrosecondsPerSecond / output_params_.sample_rate()); + const base::TimeTicks now = clock_->NowTicks(); + if (next_generate_time_ < now) { + TRACE_EVENT_INSTANT1("audio", "GenerateMoreAudio Is Behind", + TRACE_EVENT_SCOPE_THREAD, u8"µsec_behind", + (now - next_generate_time_).InMicroseconds()); + // Audio generation has fallen behind. Skip-ahead the frame counter so that + // audio generation will resume for the next buffer after the one that + // should be generating right now. http://crbug.com/847487 + const int64_t target_frame_count = + (now - first_generate_time_).InMicroseconds() * + output_params_.sample_rate() / base::Time::kMicrosecondsPerSecond; + frames_elapsed_ = + (target_frame_count / frames_per_buffer + 1) * frames_per_buffer; + next_generate_time_ = + first_generate_time_ + + base::TimeDelta::FromMicroseconds(frames_elapsed_ * + base::Time::kMicrosecondsPerSecond / + output_params_.sample_rate()); + } - // Use the OneShotTimer to call this method again at the desired time. - DCHECK_GE(next_generate_time_ - now, base::TimeDelta()); + // Note: It's acceptable for |next_generate_time_| to be slightly before |now| + // due to integer truncation behaviors in the math above. The timer task + // started below will just run immediately and there will be no harmful + // effects in the next GenerateMoreAudio() call. http://crbug.com/847487 timer_->Start(FROM_HERE, next_generate_time_ - now, this, &FlowNetwork::GenerateMoreAudio); }
diff --git a/services/device/time_zone_monitor/time_zone_monitor_linux.cc b/services/device/time_zone_monitor/time_zone_monitor_linux.cc index aae2faa8..bceb85f 100644 --- a/services/device/time_zone_monitor/time_zone_monitor_linux.cc +++ b/services/device/time_zone_monitor/time_zone_monitor_linux.cc
@@ -17,7 +17,7 @@ #include "base/memory/ref_counted.h" #include "base/sequenced_task_runner.h" #include "base/stl_util.h" -#include "base/threading/thread_restrictions.h" +#include "base/threading/scoped_blocking_call.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" @@ -88,9 +88,15 @@ ~TimeZoneMonitorLinuxImpl() { DCHECK(!owner_); } void StartWatchingOnFileThread() { - base::AssertBlockingAllowedDeprecated(); DCHECK(file_task_runner_->RunsTasksInCurrentSequence()); + auto callback = + base::BindRepeating(&TimeZoneMonitorLinuxImpl::OnTimeZoneFileChanged, + base::RetainedRef(this)); + + base::ScopedBlockingCall scoped_blocking_call( + base::BlockingType::MAY_BLOCK); + // There is no true standard for where time zone information is actually // stored. glibc uses /etc/localtime, uClibc uses /etc/TZ, and some older // systems store the name of the time zone file within /usr/share/zoneinfo @@ -101,10 +107,6 @@ const char* const kFilesToWatch[] = { "/etc/localtime", "/etc/timezone", "/etc/TZ", }; - - auto callback = - base::BindRepeating(&TimeZoneMonitorLinuxImpl::OnTimeZoneFileChanged, - base::RetainedRef(this)); for (size_t index = 0; index < arraysize(kFilesToWatch); ++index) { file_path_watchers_.push_back(std::make_unique<base::FilePathWatcher>()); file_path_watchers_.back()->Watch(base::FilePath(kFilesToWatch[index]),
diff --git a/services/network/BUILD.gn b/services/network/BUILD.gn index 5301bd1..749cace 100644 --- a/services/network/BUILD.gn +++ b/services/network/BUILD.gn
@@ -193,6 +193,8 @@ "cert_verifier_with_trust_anchors.h", "cert_verify_proc_chromeos.cc", "cert_verify_proc_chromeos.h", + "nss_temp_certs_cache_chromeos.cc", + "nss_temp_certs_cache_chromeos.h", ] } @@ -338,6 +340,7 @@ sources += [ "cert_verifier_with_trust_anchors_unittest.cc", "cert_verify_proc_chromeos_unittest.cc", + "nss_temp_certs_cache_chromeos_unittest.cc", ] }
diff --git a/services/network/network_context.cc b/services/network/network_context.cc index 8e4d8eb..7def63c 100644 --- a/services/network/network_context.cc +++ b/services/network/network_context.cc
@@ -104,6 +104,7 @@ #include "net/cert/multi_threaded_cert_verifier.h" #include "services/network/cert_verifier_with_trust_anchors.h" #include "services/network/cert_verify_proc_chromeos.h" +#include "services/network/nss_temp_certs_cache_chromeos.h" #endif #if !defined(OS_IOS) @@ -993,9 +994,17 @@ } #if defined(OS_CHROMEOS) -void NetworkContext::UpdateTrustAnchors( - const net::CertificateList& trust_anchors) { - cert_verifier_with_trust_anchors_->SetTrustAnchors(trust_anchors); +void NetworkContext::UpdateAdditionalCertificates( + mojom::AdditionalCertificatesPtr additional_certificates) { + if (!additional_certificates) { + nss_temp_certs_cache_.reset(); + cert_verifier_with_trust_anchors_->SetTrustAnchors(net::CertificateList()); + return; + } + nss_temp_certs_cache_ = std::make_unique<network::NSSTempCertsCacheChromeOS>( + additional_certificates->all_certificates); + cert_verifier_with_trust_anchors_->SetTrustAnchors( + additional_certificates->trust_anchors); } #endif @@ -1980,8 +1989,8 @@ cert_verifier_with_trust_anchors_ = new CertVerifierWithTrustAnchors( base::Bind(&NetworkContext::TrustAnchorUsed, base::Unretained(this))); - cert_verifier_with_trust_anchors_->SetTrustAnchors( - params_->initial_trust_anchors); + UpdateAdditionalCertificates( + std::move(params_->initial_additional_certificates)); cert_verifier_with_trust_anchors_->InitializeOnIOThread(verify_proc); cert_verifier = base::WrapUnique(cert_verifier_with_trust_anchors_); }
diff --git a/services/network/network_context.h b/services/network/network_context.h index 1752ada..d105ee7 100644 --- a/services/network/network_context.h +++ b/services/network/network_context.h
@@ -76,6 +76,7 @@ class NetworkService; class NetworkServiceProxyDelegate; class MdnsResponderManager; +class NSSTempCertsCacheChromeOS; class P2PSocketManager; class ProxyLookupRequest; class ResourceScheduler; @@ -210,7 +211,8 @@ void SetAcceptLanguage(const std::string& new_accept_language) override; void SetEnableReferrers(bool enable_referrers) override; #if defined(OS_CHROMEOS) - void UpdateTrustAnchors(const net::CertificateList& trust_anchors) override; + void UpdateAdditionalCertificates( + mojom::AdditionalCertificatesPtr additional_certificates) override; #endif #if BUILDFLAG(IS_CT_SUPPORTED) void SetCTPolicy( @@ -499,6 +501,9 @@ #if defined(OS_CHROMEOS) CertVerifierWithTrustAnchors* cert_verifier_with_trust_anchors_ = nullptr; + // Additional certificates made available to NSS cert validation as temporary + // certificates. + std::unique_ptr<network::NSSTempCertsCacheChromeOS> nss_temp_certs_cache_; #endif // Created on-demand. Null if unused.
diff --git a/services/network/nss_temp_certs_cache_chromeos.cc b/services/network/nss_temp_certs_cache_chromeos.cc new file mode 100644 index 0000000..cd20188f --- /dev/null +++ b/services/network/nss_temp_certs_cache_chromeos.cc
@@ -0,0 +1,28 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/network/nss_temp_certs_cache_chromeos.h" + +#include "net/cert/x509_util_nss.h" + +namespace network { + +NSSTempCertsCacheChromeOS::NSSTempCertsCacheChromeOS( + const net::CertificateList& certificates) { + for (const auto& certificate : certificates) { + net::ScopedCERTCertificate x509_cert = + net::x509_util::CreateCERTCertificateFromX509Certificate( + certificate.get()); + if (!x509_cert) { + LOG(ERROR) << "Unable to create CERTCertificate"; + continue; + } + + temp_certs_.push_back(std::move(x509_cert)); + } +} + +NSSTempCertsCacheChromeOS::~NSSTempCertsCacheChromeOS() {} + +} // namespace network
diff --git a/chrome/browser/chromeos/policy/temp_certs_cache_nss.h b/services/network/nss_temp_certs_cache_chromeos.h similarity index 69% rename from chrome/browser/chromeos/policy/temp_certs_cache_nss.h rename to services/network/nss_temp_certs_cache_chromeos.h index d305dc1..bda81c6 100644 --- a/chrome/browser/chromeos/policy/temp_certs_cache_nss.h +++ b/services/network/nss_temp_certs_cache_chromeos.h
@@ -2,21 +2,22 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_CHROMEOS_POLICY_TEMP_CERTS_CACHE_NSS_H_ -#define CHROME_BROWSER_CHROMEOS_POLICY_TEMP_CERTS_CACHE_NSS_H_ +#ifndef SERVICES_NETWORK_NSS_TEMP_CERTS_CACHE_CHROMEOS_H_ +#define SERVICES_NETWORK_NSS_TEMP_CERTS_CACHE_CHROMEOS_H_ +#include "base/component_export.h" #include "base/macros.h" #include "net/cert/scoped_nss_types.h" #include "net/cert/x509_certificate.h" -namespace policy { +namespace network { // Holds NSS temporary certificates in memory as ScopedCERTCertificates, making // them available e.g. for client certificate discovery. -class TempCertsCacheNSS { +class COMPONENT_EXPORT(NETWORK_SERVICE) NSSTempCertsCacheChromeOS { public: - explicit TempCertsCacheNSS(const net::CertificateList& certificates); - ~TempCertsCacheNSS(); + explicit NSSTempCertsCacheChromeOS(const net::CertificateList& certificates); + ~NSSTempCertsCacheChromeOS(); private: // The actual cache of NSS temporary certificates. @@ -30,9 +31,9 @@ // permanent databases, nor are the trust settings mutated to trust them. net::ScopedCERTCertificateList temp_certs_; - DISALLOW_COPY_AND_ASSIGN(TempCertsCacheNSS); + DISALLOW_COPY_AND_ASSIGN(NSSTempCertsCacheChromeOS); }; -} // namespace policy +} // namespace network -#endif // CHROME_BROWSER_CHROMEOS_POLICY_TEMP_CERTS_CACHE_NSS_H_ +#endif // SERVICES_NETWORK_NSS_TEMP_CERTS_CACHE_CHROMEOS_H_
diff --git a/chrome/browser/chromeos/policy/temp_certs_cache_nss_unittest.cc b/services/network/nss_temp_certs_cache_chromeos_unittest.cc similarity index 87% rename from chrome/browser/chromeos/policy/temp_certs_cache_nss_unittest.cc rename to services/network/nss_temp_certs_cache_chromeos_unittest.cc index 41e7355a..b1b995d 100644 --- a/chrome/browser/chromeos/policy/temp_certs_cache_nss_unittest.cc +++ b/services/network/nss_temp_certs_cache_chromeos_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/chromeos/policy/temp_certs_cache_nss.h" +#include "services/network/nss_temp_certs_cache_chromeos.h" #include <cert.h> #include <certdb.h> @@ -23,14 +23,14 @@ #include "net/test/test_data_directory.h" #include "testing/gtest/include/gtest/gtest.h" -namespace policy { +namespace network { namespace { -class TempCertsCacheNSSTest : public testing::Test { +class NSSTempCertsCacheChromeOSTest : public testing::Test { public: - TempCertsCacheNSSTest() {} - ~TempCertsCacheNSSTest() override {} + NSSTempCertsCacheChromeOSTest() {} + ~NSSTempCertsCacheChromeOSTest() override {} protected: // Checks if the certificate stored in |pem_cert_file| can be found in the @@ -92,17 +92,17 @@ } private: - DISALLOW_COPY_AND_ASSIGN(TempCertsCacheNSSTest); + DISALLOW_COPY_AND_ASSIGN(NSSTempCertsCacheChromeOSTest); }; // Checks that a certificate made available through the -// TempCertsCacheNSS can be found by NSS. We specifically check for +// NSSTempCertsCacheChromeOS can be found by NSS. We specifically check for // lookup through the CERT_FindCertByName function, as this is what is used in // client certificate matching (see MatchClientCertificateIssuers in // net/third_party/nss/ssl/cmpcert.cc). Additionally, checks that the -// certificate is not available after the TempCertsCacheNSS goes out of +// certificate is not available after the NSSTempCertsCacheChromeOS goes out of // scope. -TEST_F(TempCertsCacheNSSTest, CertMadeAvailable) { +TEST_F(NSSTempCertsCacheChromeOSTest, CertMadeAvailable) { base::FilePath cert_file_path = net::GetTestCertsDirectory().AppendASCII("client_1_ca.pem"); { @@ -113,7 +113,7 @@ x509_authority_cert.data(), x509_authority_cert.length(), net::X509Certificate::Format::FORMAT_AUTO); - TempCertsCacheNSS cache(x509_authority_certs); + NSSTempCertsCacheChromeOS cache(x509_authority_certs); bool cert_available = false; ASSERT_NO_FATAL_FAILURE( @@ -128,4 +128,4 @@ } } // namespace -} // namespace policy +} // namespace network
diff --git a/services/network/public/mojom/network_context.mojom b/services/network/public/mojom/network_context.mojom index 8f3b73d..c1d6e7f 100644 --- a/services/network/public/mojom/network_context.mojom +++ b/services/network/public/mojom/network_context.mojom
@@ -81,6 +81,15 @@ ProxyList bad_proxies) => (); }; +[EnableIf=is_chromeos] +struct AdditionalCertificates { + // List of all additional certificates. + array<X509Certificate> all_certificates; + + // List of additional trust anchors. + array<X509Certificate> trust_anchors; +}; + // Parameters for constructing a network context. struct NetworkContextParams { // Name used by memory tools to identify the context. @@ -244,9 +253,10 @@ [EnableIf=is_chromeos] string username_hash; - // Initial list of additional trust anchors. + // Initial additional certificates that will be used for certificate + // validation. [EnableIf=is_chromeos] - array<X509Certificate> initial_trust_anchors; + AdditionalCertificates? initial_additional_certificates; // Parameters for constructing the cookie manager. CookieManagerParams? cookie_manager_params; @@ -523,7 +533,7 @@ // Updates the additional trust anchors for certificate verification. [EnableIf=is_chromeos] - UpdateTrustAnchors(array<X509Certificate> trust_anchors); + UpdateAdditionalCertificates(AdditionalCertificates? additional_certificates); // Updates the CT policy to be used for requests. Only applies if the // NetworkContextParams set enforce_chrome_ct_policy to true.
diff --git a/services/network/test/test_network_context.h b/services/network/test/test_network_context.h index f6c03e0..0c47c8c 100644 --- a/services/network/test/test_network_context.h +++ b/services/network/test/test_network_context.h
@@ -89,7 +89,8 @@ void SetAcceptLanguage(const std::string& new_accept_language) override {} void SetEnableReferrers(bool enable_referrers) override {} #if defined(OS_CHROMEOS) - void UpdateTrustAnchors(const net::CertificateList& trust_anchors) override {} + void UpdateAdditionalCertificates( + mojom::AdditionalCertificatesPtr additional_certificates) override {} #endif #if BUILDFLAG(IS_CT_SUPPORTED) void SetCTPolicy(
diff --git a/services/proxy_resolver/host_resolver_mojo.cc b/services/proxy_resolver/host_resolver_mojo.cc index b9b3fac6..dde987f 100644 --- a/services/proxy_resolver/host_resolver_mojo.cc +++ b/services/proxy_resolver/host_resolver_mojo.cc
@@ -153,7 +153,8 @@ if (!entry) return net::ERR_DNS_CACHE_MISS; - *addresses = net::AddressList::CopyWithPort(entry->addresses(), info.port()); + *addresses = + net::AddressList::CopyWithPort(entry->addresses().value(), info.port()); return entry->error(); }
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.cc b/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.cc index 29d07d2ec..b8708ff 100644 --- a/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.cc +++ b/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.cc
@@ -8,7 +8,7 @@ #include "base/format_macros.h" #include "base/strings/stringprintf.h" #include "base/trace_event/memory_dump_manager.h" -#include "base/trace_event/trace_event_argument.h" +#include "base/trace_event/traced_value.h" #include "build/build_config.h" namespace memory_instrumentation {
diff --git a/services/tracing/public/cpp/perfetto/traced_value_proto_writer.cc b/services/tracing/public/cpp/perfetto/traced_value_proto_writer.cc index c8e16e6..c861b9a 100644 --- a/services/tracing/public/cpp/perfetto/traced_value_proto_writer.cc +++ b/services/tracing/public/cpp/perfetto/traced_value_proto_writer.cc
@@ -8,7 +8,7 @@ #include "base/hash.h" #include "base/json/string_escape.h" #include "base/trace_event/trace_event.h" -#include "base/trace_event/trace_event_argument.h" +#include "base/trace_event/traced_value.h" #include "base/values.h" #include "services/tracing/public/cpp/perfetto/heap_scattered_stream_delegate.h" #include "third_party/perfetto/include/perfetto/protozero/message_handle.h"
diff --git a/services/tracing/public/cpp/perfetto/traced_value_proto_writer_unittest.cc b/services/tracing/public/cpp/perfetto/traced_value_proto_writer_unittest.cc index e268f219..d4bbd5e 100644 --- a/services/tracing/public/cpp/perfetto/traced_value_proto_writer_unittest.cc +++ b/services/tracing/public/cpp/perfetto/traced_value_proto_writer_unittest.cc
@@ -7,7 +7,7 @@ #include <memory> #include <string> -#include "base/trace_event/trace_event_argument.h" +#include "base/trace_event/traced_value.h" #include "services/tracing/public/cpp/perfetto/heap_scattered_stream_delegate.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/perfetto/protos/perfetto/trace/chrome/chrome_trace_event.pb.h"
diff --git a/services/ws/common/util.h b/services/ws/common/util.h index 36d0694..4c2c6576 100644 --- a/services/ws/common/util.h +++ b/services/ws/common/util.h
@@ -19,6 +19,11 @@ return static_cast<ClientSpecificId>(id & 0xFFFFFFFF); } +inline Id BuildTransportId(ClientSpecificId connection_id, + ClientSpecificId window_id) { + return (static_cast<Id>(connection_id) << 32) | static_cast<Id>(window_id); +} + } // namespace ws #endif // SERVICES_WS_COMMON_UTIL_H_
diff --git a/services/ws/window_service.cc b/services/ws/window_service.cc index bc14d3d7..d49190fe 100644 --- a/services/ws/window_service.cc +++ b/services/ws/window_service.cc
@@ -79,10 +79,6 @@ DCHECK(window_trees_.empty()); } -ClientSpecificId WindowService::GetFirstWindowTreeClientId() const { - return decrement_client_ids_ ? kInitialClientIdDecrement : kInitialClientId; -} - ServerWindow* WindowService::GetServerWindowForWindowCreateIfNecessary( aura::Window* window) { ServerWindow* server_window = ServerWindow::GetMayBeNull(window); @@ -131,6 +127,17 @@ return server_window && server_window->IsTopLevel(); } +ws::Id WindowService::GetTopLevelWindowId(aura::Window* window) { + ServerWindow* server_window = ServerWindow::GetMayBeNull(window); + if (!server_window || !server_window->IsTopLevel()) + return kInvalidTransportId; + + const ws::WindowTree* owning_tree = server_window->owning_window_tree(); + return BuildTransportId( + owning_tree->client_id(), + owning_tree->ClientWindowIdForWindow(window).sink_id()); +} + aura::Window* WindowService::GetWindowByClientId(Id transport_id) { const ClientSpecificId client_id = ClientIdFromTransportId(transport_id); WindowTree* window_tree = GetTreeById(client_id);
diff --git a/services/ws/window_service.h b/services/ws/window_service.h index 9d23e9e..221f822e 100644 --- a/services/ws/window_service.h +++ b/services/ws/window_service.h
@@ -87,9 +87,6 @@ aura::Env* env = nullptr); ~WindowService() override; - // Returns the id of the first WindowTreeClient. - ClientSpecificId GetFirstWindowTreeClientId() const; - // Gets the ServerWindow for |window|, creating if necessary. ServerWindow* GetServerWindowForWindowCreateIfNecessary(aura::Window* window); @@ -113,6 +110,10 @@ // Returns true if |window| hosts a remote client and is a toplevel window. static bool IsTopLevelWindow(const aura::Window* window); + // Returns the transport id for |window|. If |window| is not a top-level + // window, returns kInvalidTransportId. + ws::Id GetTopLevelWindowId(aura::Window* window); + // Returns the window representing the specified id. aura::Window* GetWindowByClientId(Id transport_id);
diff --git a/skia/BUILD.gn b/skia/BUILD.gn index 84b14809..6db6d7b 100644 --- a/skia/BUILD.gn +++ b/skia/BUILD.gn
@@ -9,7 +9,6 @@ import("//gpu/vulkan/features.gni") import("//printing/buildflags/buildflags.gni") import("//testing/test.gni") -import("//testing/libfuzzer/fuzzer_test.gni") import("//third_party/skia/gn/shared_sources.gni") import("//third_party/skia/third_party/skcms/skcms.gni") @@ -864,155 +863,8 @@ } } -# Build Skia fuzzers from OSS-Fuzz on Windows since Windows is not supported by -# OSS-Fuzz. -if (is_win && use_libfuzzer) { - static_library("skia_fuzzer_lib") { - sources = [ - "//third_party/skia/fuzz/Fuzz.cpp", - "//third_party/skia/fuzz/FuzzCommon.cpp", - ] - configs += [ ":skia_library_config" ] - - # Use public_deps so each fuzzer_test doesn't need to explicitly depend on - # ":skia". - public_deps = [ - ":skia", - ] - } - - static_library("skia_encoder_fuzzer_lib") { - sources = [ - "//third_party/skia/fuzz/FuzzEncoders.cpp", - ] - configs += [ ":skia_library_config" ] - deps = [ - ":skia", - ] - } - - # TODO(metzman): Enable the other fuzzers that cannot yet build in Chromium. - fuzzer_test("skia_region_deserialize_fuzzer") { - sources = [ - "//third_party/skia/fuzz/oss_fuzz/FuzzRegionDeserialize.cpp", - ] - additional_configs = [ ":skia_library_config" ] - defines = [ "IS_FUZZING_WITH_LIBFUZZER" ] - deps = [ - ":skia_fuzzer_lib", - ] - } - - fuzzer_test("skia_image_filter_deserialize_fuzzer") { - sources = [ - "//third_party/skia/fuzz/oss_fuzz/FuzzImageFilterDeserialize.cpp", - ] - additional_configs = [ ":skia_library_config" ] - defines = [ "IS_FUZZING_WITH_LIBFUZZER" ] - deps = [ - ":skia_fuzzer_lib", - ] - } - - fuzzer_test("skia_region_set_path_fuzzer") { - sources = [ - "//third_party/skia/fuzz/oss_fuzz/FuzzRegionSetPath.cpp", - ] - additional_configs = [ ":skia_library_config" ] - defines = [ "IS_FUZZING_WITH_LIBFUZZER" ] - deps = [ - ":skia_fuzzer_lib", - ] - } - - fuzzer_test("skia_textblob_deserialize_fuzzer") { - sources = [ - "//third_party/skia/fuzz/oss_fuzz/FuzzTextBlobDeserialize.cpp", - ] - additional_configs = [ ":skia_library_config" ] - defines = [ "IS_FUZZING_WITH_LIBFUZZER" ] - deps = [ - ":skia_fuzzer_lib", - ] - } - - fuzzer_test("skia_path_deserialize_fuzzer") { - sources = [ - "//third_party/skia/fuzz/oss_fuzz/FuzzPathDeserialize.cpp", - ] - additional_configs = [ ":skia_library_config" ] - defines = [ "IS_FUZZING_WITH_LIBFUZZER" ] - deps = [ - ":skia_fuzzer_lib", - ] - } - - fuzzer_test("skia_image_decode_fuzzer") { - sources = [ - "//third_party/skia/fuzz/oss_fuzz/FuzzImage.cpp", - ] - additional_configs = [ ":skia_library_config" ] - defines = [ "IS_FUZZING_WITH_LIBFUZZER" ] - deps = [ - ":skia_fuzzer_lib", - ] - } - - fuzzer_test("skia_png_encoder_fuzzer") { - sources = [ - "//third_party/skia/fuzz/oss_fuzz/FuzzPNGEncoder.cpp", - ] - additional_configs = [ ":skia_library_config" ] - defines = [ "IS_FUZZING_WITH_LIBFUZZER" ] - deps = [ - ":skia_encoder_fuzzer_lib", - ":skia_fuzzer_lib", - ] - } - - fuzzer_test("skia_jpeg_encoder_fuzzer") { - sources = [ - "//third_party/skia/fuzz/oss_fuzz/FuzzJPEGEncoder.cpp", - ] - additional_configs = [ ":skia_library_config" ] - defines = [ "IS_FUZZING_WITH_LIBFUZZER" ] - deps = [ - ":skia_encoder_fuzzer_lib", - ":skia_fuzzer_lib", - ] - } - - fuzzer_test("skia_webp_encoder_fuzzer") { - sources = [ - "//third_party/skia/fuzz/oss_fuzz/FuzzWEBPEncoder.cpp", - ] - additional_configs = [ ":skia_library_config" ] - defines = [ "IS_FUZZING_WITH_LIBFUZZER" ] - deps = [ - ":skia_encoder_fuzzer_lib", - ":skia_fuzzer_lib", - ] - } - - fuzzer_test("skia_skjson_fuzzer") { - sources = [ - "//third_party/skia/fuzz/oss_fuzz/FuzzJSON.cpp", - ] - additional_configs = [ ":skia_library_config" ] - defines = [ "IS_FUZZING_WITH_LIBFUZZER" ] - deps = [ - ":skia_fuzzer_lib", - ] - } - - fuzzer_test("skia_image_decode_incremental_fuzzer") { - sources = [ - "//third_party/skia/fuzz/oss_fuzz/FuzzIncrementalImage.cpp", - ] - additional_configs = [ ":skia_library_config" ] - defines = [ "IS_FUZZING_WITH_LIBFUZZER" ] - deps = [ - ":skia_fuzzer_lib", - ] - } +group("fuzzers") { + deps = [ + "//skia/tools/fuzzers", + ] }
diff --git a/skia/tools/fuzzers/BUILD.gn b/skia/tools/fuzzers/BUILD.gn new file mode 100644 index 0000000..d28c893 --- /dev/null +++ b/skia/tools/fuzzers/BUILD.gn
@@ -0,0 +1,155 @@ +# Copyright (c) 2018 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//testing/libfuzzer/fuzzer_test.gni") + +group("fuzzers") { +} + +# Build Skia fuzzers from OSS-Fuzz on Windows since Windows is not supported by +# OSS-Fuzz. +if (is_win && use_libfuzzer) { + source_set("skia_fuzzer_sources") { + testonly = true + sources = [ + "//skia/tools/fuzzers/fuzzer_environment.cc", + "//third_party/skia/fuzz/Fuzz.cpp", + "//third_party/skia/fuzz/FuzzCommon.cpp", + ] + + # Use public_deps and public_configs so each fuzzer_test doesn't need to + # explicitly depend on "//skia" and "//skia:skia_library_config". + public_deps = [ + "//skia", + ] + public_configs = [ "//skia:skia_library_config" ] + deps = [ + "//base/test:test_support", + ] + } + + static_library("skia_encoder_fuzzer_lib") { + sources = [ + "//third_party/skia/fuzz/FuzzEncoders.cpp", + ] + configs += [ "//skia:skia_library_config" ] + deps = [ + "//skia", + ] + } + + # TODO(metzman): Enable the other fuzzers that cannot yet build in Chromium. + fuzzer_test("skia_region_deserialize_fuzzer") { + sources = [ + "//third_party/skia/fuzz/oss_fuzz/FuzzRegionDeserialize.cpp", + ] + defines = [ "IS_FUZZING_WITH_LIBFUZZER" ] + deps = [ + ":skia_fuzzer_sources", + ] + } + + fuzzer_test("skia_image_filter_deserialize_fuzzer") { + sources = [ + "//third_party/skia/fuzz/oss_fuzz/FuzzImageFilterDeserialize.cpp", + ] + defines = [ "IS_FUZZING_WITH_LIBFUZZER" ] + deps = [ + ":skia_fuzzer_sources", + ] + } + + fuzzer_test("skia_region_set_path_fuzzer") { + sources = [ + "//third_party/skia/fuzz/oss_fuzz/FuzzRegionSetPath.cpp", + ] + defines = [ "IS_FUZZING_WITH_LIBFUZZER" ] + deps = [ + ":skia_fuzzer_sources", + ] + } + + fuzzer_test("skia_textblob_deserialize_fuzzer") { + sources = [ + "//third_party/skia/fuzz/oss_fuzz/FuzzTextBlobDeserialize.cpp", + ] + defines = [ "IS_FUZZING_WITH_LIBFUZZER" ] + deps = [ + ":skia_fuzzer_sources", + ] + } + + fuzzer_test("skia_path_deserialize_fuzzer") { + sources = [ + "//third_party/skia/fuzz/oss_fuzz/FuzzPathDeserialize.cpp", + ] + defines = [ "IS_FUZZING_WITH_LIBFUZZER" ] + deps = [ + ":skia_fuzzer_sources", + ] + } + + fuzzer_test("skia_image_decode_fuzzer") { + sources = [ + "//third_party/skia/fuzz/oss_fuzz/FuzzImage.cpp", + ] + defines = [ "IS_FUZZING_WITH_LIBFUZZER" ] + deps = [ + ":skia_fuzzer_sources", + ] + } + + fuzzer_test("skia_png_encoder_fuzzer") { + sources = [ + "//third_party/skia/fuzz/oss_fuzz/FuzzPNGEncoder.cpp", + ] + defines = [ "IS_FUZZING_WITH_LIBFUZZER" ] + deps = [ + ":skia_encoder_fuzzer_lib", + ":skia_fuzzer_sources", + ] + } + + fuzzer_test("skia_jpeg_encoder_fuzzer") { + sources = [ + "//third_party/skia/fuzz/oss_fuzz/FuzzJPEGEncoder.cpp", + ] + defines = [ "IS_FUZZING_WITH_LIBFUZZER" ] + deps = [ + ":skia_encoder_fuzzer_lib", + ":skia_fuzzer_sources", + ] + } + + fuzzer_test("skia_webp_encoder_fuzzer") { + sources = [ + "//third_party/skia/fuzz/oss_fuzz/FuzzWEBPEncoder.cpp", + ] + defines = [ "IS_FUZZING_WITH_LIBFUZZER" ] + deps = [ + ":skia_encoder_fuzzer_lib", + ":skia_fuzzer_sources", + ] + } + + fuzzer_test("skia_skjson_fuzzer") { + sources = [ + "//third_party/skia/fuzz/oss_fuzz/FuzzJSON.cpp", + ] + defines = [ "IS_FUZZING_WITH_LIBFUZZER" ] + deps = [ + ":skia_fuzzer_sources", + ] + } + + fuzzer_test("skia_image_decode_incremental_fuzzer") { + sources = [ + "//third_party/skia/fuzz/oss_fuzz/FuzzIncrementalImage.cpp", + ] + defines = [ "IS_FUZZING_WITH_LIBFUZZER" ] + deps = [ + ":skia_fuzzer_sources", + ] + } +}
diff --git a/skia/tools/fuzzers/fuzzer_environment.cc b/skia/tools/fuzzers/fuzzer_environment.cc new file mode 100644 index 0000000..72f10a7 --- /dev/null +++ b/skia/tools/fuzzers/fuzzer_environment.cc
@@ -0,0 +1,19 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/test/test_discardable_memory_allocator.h" + +namespace { + +class Environment { + base::TestDiscardableMemoryAllocator test_memory_allocator_; + + public: + Environment() { + base::DiscardableMemoryAllocator::SetInstance(&test_memory_allocator_); + } +}; + +static Environment env; +}; // namespace
diff --git a/testing/buildbot/README.md b/testing/buildbot/README.md index e1cdb92..516f2260 100644 --- a/testing/buildbot/README.md +++ b/testing/buildbot/README.md
@@ -5,6 +5,16 @@ In addition to specifying what tests run on which builders, they also specify special arguments and constraints for the tests. +Adding a new test suite? + +The bar for adding new test suites is high. New test suites result in extra +linking time for builders, and sending binaries around to the swarming bots. +This is especially onerous for suites such as browser_tests (more than 300MB +as of this writing). Unless there is a compelling reason to have a standalone +suite, include your tests in existing test suites. For example, all +InProcessBrowserTests should be in browser_tests. Similarly any unit-tests in +components should be in components_unittests. + ## A tour of the directory * <master_name\>.json -- buildbot configuration json files. These are used to
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 77b7748..9db351c 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -5920,11 +5920,7 @@ { "args": [ "--additional-driver-flag", - "--site-per-process", - "--additional-driver-flag", - "--isolate-origins=http://www.web-platform.test:8001/,http://www1.web-platform.test:8001/,http://www2.web-platform.test:8001/,http://xn--n8j6ds53lwwkrqhv28a.web-platform.test:8001/,http://xn--lve-6lad.web-platform.test:8001/,http://www.web-platform.test:8081/,http://www1.web-platform.test:8081/,http://www2.web-platform.test:8081/,http://xn--n8j6ds53lwwkrqhv28a.web-platform.test:8081/,http://xn--lve-6lad.web-platform.test:8081/,https://www.web-platform.test:8444/,https://www1.web-platform.test:8444/,https://www2.web-platform.test:8444/,https://xn--n8j6ds53lwwkrqhv28a.web-platform.test:8444/,https://xn--lve-6lad.web-platform.test:8444/", - "--additional-expectations", - "src/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process", + "--disable-site-isolation-trials", "--num-retries=3" ], "isolate_name": "webkit_layout_tests_exparchive", @@ -5934,7 +5930,7 @@ ], "script": "//third_party/blink/tools/merge_web_test_results.py" }, - "name": "site_per_process_webkit_layout_tests", + "name": "not_site_per_process_webkit_layout_tests", "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -7348,11 +7344,7 @@ { "args": [ "--additional-driver-flag", - "--site-per-process", - "--additional-driver-flag", - "--isolate-origins=http://www.web-platform.test:8001/,http://www1.web-platform.test:8001/,http://www2.web-platform.test:8001/,http://xn--n8j6ds53lwwkrqhv28a.web-platform.test:8001/,http://xn--lve-6lad.web-platform.test:8001/,http://www.web-platform.test:8081/,http://www1.web-platform.test:8081/,http://www2.web-platform.test:8081/,http://xn--n8j6ds53lwwkrqhv28a.web-platform.test:8081/,http://xn--lve-6lad.web-platform.test:8081/,https://www.web-platform.test:8444/,https://www1.web-platform.test:8444/,https://www2.web-platform.test:8444/,https://xn--n8j6ds53lwwkrqhv28a.web-platform.test:8444/,https://xn--lve-6lad.web-platform.test:8444/", - "--additional-expectations", - "src/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process", + "--disable-site-isolation-trials", "--num-retries=3" ], "isolate_name": "webkit_layout_tests_exparchive", @@ -7362,7 +7354,7 @@ ], "script": "//third_party/blink/tools/merge_web_test_results.py" }, - "name": "site_per_process_webkit_layout_tests", + "name": "not_site_per_process_webkit_layout_tests", "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true,
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json index 46e65ee..d6100c1b 100644 --- a/testing/buildbot/chromium.linux.json +++ b/testing/buildbot/chromium.linux.json
@@ -1552,11 +1552,7 @@ { "args": [ "--additional-driver-flag", - "--site-per-process", - "--additional-driver-flag", - "--isolate-origins=http://www.web-platform.test:8001/,http://www1.web-platform.test:8001/,http://www2.web-platform.test:8001/,http://xn--n8j6ds53lwwkrqhv28a.web-platform.test:8001/,http://xn--lve-6lad.web-platform.test:8001/,http://www.web-platform.test:8081/,http://www1.web-platform.test:8081/,http://www2.web-platform.test:8081/,http://xn--n8j6ds53lwwkrqhv28a.web-platform.test:8081/,http://xn--lve-6lad.web-platform.test:8081/,https://www.web-platform.test:8444/,https://www1.web-platform.test:8444/,https://www2.web-platform.test:8444/,https://xn--n8j6ds53lwwkrqhv28a.web-platform.test:8444/,https://xn--lve-6lad.web-platform.test:8444/", - "--additional-expectations", - "src/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process", + "--disable-site-isolation-trials", "--num-retries=3" ], "isolate_name": "webkit_layout_tests_exparchive", @@ -1566,7 +1562,7 @@ ], "script": "//third_party/blink/tools/merge_web_test_results.py" }, - "name": "site_per_process_webkit_layout_tests", + "name": "not_site_per_process_webkit_layout_tests", "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -4164,11 +4160,7 @@ { "args": [ "--additional-driver-flag", - "--site-per-process", - "--additional-driver-flag", - "--isolate-origins=http://www.web-platform.test:8001/,http://www1.web-platform.test:8001/,http://www2.web-platform.test:8001/,http://xn--n8j6ds53lwwkrqhv28a.web-platform.test:8001/,http://xn--lve-6lad.web-platform.test:8001/,http://www.web-platform.test:8081/,http://www1.web-platform.test:8081/,http://www2.web-platform.test:8081/,http://xn--n8j6ds53lwwkrqhv28a.web-platform.test:8081/,http://xn--lve-6lad.web-platform.test:8081/,https://www.web-platform.test:8444/,https://www1.web-platform.test:8444/,https://www2.web-platform.test:8444/,https://xn--n8j6ds53lwwkrqhv28a.web-platform.test:8444/,https://xn--lve-6lad.web-platform.test:8444/", - "--additional-expectations", - "src/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process", + "--disable-site-isolation-trials", "--num-retries=3" ], "isolate_name": "webkit_layout_tests_exparchive", @@ -4178,7 +4170,7 @@ ], "script": "//third_party/blink/tools/merge_web_test_results.py" }, - "name": "site_per_process_webkit_layout_tests", + "name": "not_site_per_process_webkit_layout_tests", "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true,
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index 9b75cfd..73d293b 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -839,6 +839,14 @@ }, }, }, + 'not_site_per_process_webkit_layout_tests': { + 'remove_from': [ + # chromium.linux + # TODO(dpranke): Should we be running this step on Linux Tests (dbg)(1)? + 'Linux Tests (dbg)(1)', + 'Linux Tests (dbg)(1)(32)', + ], + }, 'notification_helper_unittests': { 'remove_from': [ # The test uses WinRT, which only exists in Windows 8 or above. @@ -921,14 +929,6 @@ }, }, }, - 'site_per_process_webkit_layout_tests': { - 'remove_from': [ - # chromium.linux - # TODO(dpranke): Should we be running this step on Linux Tests (dbg)(1)? - 'Linux Tests (dbg)(1)', - 'Linux Tests (dbg)(1)(32)', - ], - }, 'sizes': { 'remove_from': [ 'win32-dbg',
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index afc832d..a8b885f 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -1821,14 +1821,15 @@ 'linux_specific_chromium_isolated_scripts': { 'devtools_closure_compile': {}, 'devtools_eslint': {}, - 'site_per_process_webkit_layout_tests': { + 'not_site_per_process_webkit_layout_tests': { + # not_site_per_process_webkit_layout_tests provides coverage for + # running Layout Tests without site-per-process. This is the mode used + # on Android and Android bots currently do not run the full set of + # layout tests. Running in this mode on linux compensates for lack of + # direct Android coverage. 'args': [ '--additional-driver-flag', - '--site-per-process', - '--additional-driver-flag', - '--isolate-origins=http://www.web-platform.test:8001/,http://www1.web-platform.test:8001/,http://www2.web-platform.test:8001/,http://xn--n8j6ds53lwwkrqhv28a.web-platform.test:8001/,http://xn--lve-6lad.web-platform.test:8001/,http://www.web-platform.test:8081/,http://www1.web-platform.test:8081/,http://www2.web-platform.test:8081/,http://xn--n8j6ds53lwwkrqhv28a.web-platform.test:8081/,http://xn--lve-6lad.web-platform.test:8081/,https://www.web-platform.test:8444/,https://www1.web-platform.test:8444/,https://www2.web-platform.test:8444/,https://xn--n8j6ds53lwwkrqhv28a.web-platform.test:8444/,https://xn--lve-6lad.web-platform.test:8444/', - '--additional-expectations', - 'src/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process', + '--disable-site-isolation-trials', # layout test failures are retried 3 times when '--test-list' is not # passed, but 0 times when '--test-list' is passed. We want to always
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index ea771e5f..87889b1 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -1105,25 +1105,6 @@ ] } ], - "BlockTabUnders": [ - { - "platforms": [ - "android", - "chromeos", - "linux", - "mac", - "windows" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "BlockTabUnders" - ] - } - ] - } - ], "BookmarkInProductHelp": [ { "platforms": [
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 index c9236509..fc99895 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
@@ -840,3 +840,4 @@ Bug(none) compositing/overflow/siblings-with-border-radius-ancestor.html [ Failure ] Bug(none) compositing/overflow/grandchild-composited-with-border-radius-ancestor.html [ Failure ] Bug(none) paint/invalidation/float-offscreen.html [ Failure ] +Bug(none) compositing/video/video-controls-squashing.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process b/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process deleted file mode 100644 index 5c8bdef5..0000000 --- a/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process +++ /dev/null
@@ -1,121 +0,0 @@ -# These tests currently fail when they run with --site-per-process. -# See https://crbug.com/477150. - -# https://crbug.com/793127: NOTREACHED() from clamy@ tickled by frame consolidation CL? -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/793127 virtual/outofblink-cors-ns/http/tests/security/upgrade-insecure-requests/iframe-upgrade.https.html [ Crash ] -crbug.com/793127 external/wpt/content-security-policy/securitypolicyviolation/upgrade-insecure-requests-reporting.https.html [ Crash ] - -# https://crbug.com/769508: PlzNavigate-related, not-yet-investigated failures. -crbug.com/769508 fast/css/acid2.html [ Failure ] - -# https://crbug.com/765779: unique name trouble with PlzNavigate -crbug.com/765779 http/tests/loading/bad-server-subframe.html [ Failure ] - -# https://crbug.com/393285: Text-autosizing doesn't support OOPIFs. -# https://crbug.com/667551: Pixel dumps don't support OOPIFs. -# Both of the bugs above need to be fixed, before enabling the tests below. -crbug.com/393285 http/tests/text-autosizing/narrow-iframe.html [ Failure Crash ] -crbug.com/393285 http/tests/text-autosizing/wide-iframe.html [ Failure Crash ] - -# https://crbug.com/669083: console messages mismatch (origin-only VS full-URI) -crbug.com/669083 http/tests/security/frameNavigation/xss-DENIED-top-navigation-without-user-gesture.html [ Failure ] -crbug.com/669083 virtual/outofblink-cors/http/tests/security/frameNavigation/xss-DENIED-top-navigation-without-user-gesture.html [ Failure ] -crbug.com/669083 virtual/outofblink-cors-ns/http/tests/security/frameNavigation/xss-DENIED-top-navigation-without-user-gesture.html [ Failure ] - -# https://crbug.com/608015 - node.contentDocument is undefined. -crbug.com/608015 http/tests/inspector-protocol/access-inspected-object.js [ Failure Timeout ] - -# https://crbug.com/771003 - Dump history from all processes in layout tests -crbug.com/771003 http/tests/security/mixedContent/insecure-iframe-in-main-frame.html [ Failure ] -crbug.com/771003 virtual/outofblink-cors/http/tests/security/mixedContent/insecure-iframe-in-main-frame.html [ Failure ] -crbug.com/771003 virtual/outofblink-cors-ns/http/tests/security/mixedContent/insecure-iframe-in-main-frame.html [ Failure ] - -# https://crbug.com/585188 - testRunner.addOriginAccessAllowListEntry is not replicated to OOPIFs. -crbug.com/585188 http/tests/xmlhttprequest/origin-whitelisting-all.html [ Failure ] -crbug.com/585188 virtual/outofblink-cors/http/tests/xmlhttprequest/origin-whitelisting-all.html [ Failure ] -crbug.com/585188 http/tests/xmlhttprequest/origin-whitelisting-ip-addresses.html [ Failure ] -crbug.com/585188 virtual/outofblink-cors/http/tests/xmlhttprequest/origin-whitelisting-ip-addresses.html [ Failure ] - -# https://crbug.com/606594 - UaF of delegate_ in WebFrameTestClient::willSendRequest -# https://crbug.com/786510 - test tries to access cross-origin document body -crbug.com/606594 http/tests/local/serviceworker/fetch-request-body-file.html [ Skip ] - -# https://crbug.com/616626 - allow_universal_access_from_file_urls doesn't work with --site-per-process. -# https://crbug.com/665058 - EventSender drag-and-drop simulation doesn't support OOPIFs. -crbug.com/665058 http/tests/local/drag-over-remote-content.html [ Crash ] - -# https://crbug.com/619662 - Expected console output differences. -crbug.com/619662 http/tests/navigation/cross-origin-fragment-navigation-is-async.html [ Failure ] -crbug.com/619662 virtual/outofblink-cors/http/tests/navigation/cross-origin-fragment-navigation-is-async.html [ Failure ] -crbug.com/619662 virtual/outofblink-cors-ns/http/tests/navigation/cross-origin-fragment-navigation-is-async.html [ Failure ] -crbug.com/619662 virtual/stable/http/tests/navigation/cross-origin-fragment-navigation-is-async.html [ Failure ] - -# https://crbug.com/623268 - Can't inspect OOPIFs from main page's DevTools window. -crbug.com/623268 http/tests/inspector-protocol/request-mixed-content-status-blockable.js [ Timeout ] -crbug.com/623268 http/tests/inspector-protocol/request-mixed-content-status-none.js [ Timeout ] -crbug.com/623268 http/tests/inspector-protocol/request-mixed-content-status-optionally-blockable.js [ Timeout ] -crbug.com/623268 http/tests/devtools/console-cross-origin-iframe-logging.js [ Timeout ] - -# https://crbug.com/645641 - test_runner.cc(1863) Check failed: -# layout_test_runtime_flags_.have_top_loading_frame() -crbug.com/645641 external/wpt/html/syntax/parsing/html5lib_tests19.html [ Crash Failure ] - -# http/ flaky tests w/ --site-per-process -crbug.com/678482 http/tests/devtools/debugger/fetch-breakpoints.js [ Timeout Pass ] -crbug.com/678491 http/tests/misc/webtiming-no-origin.html [ Crash Pass ] - -# Slow tests. These are listed in SlowTests listed here also because -# expectations are unfortunately not inherited automatically (e.g. see -# https://crbug.com/594216) -crbug.com/451577 http/tests/devtools/network/network-datareceived.js [ Timeout Pass ] -crbug.com/24182 http/tests/perf/large-inlined-script.html [ Timeout Pass ] - -# https://crbug.com/650348: Remove input event forwarding path from RenderFrameProxies -# This test needs to be modified to not rely on EventSender passing mouse events directly to an OOPIF. -crbug.com/650348 http/tests/webaudio/autoplay-crossorigin.html [ Timeout ] - -# https://crbug.com/778372: Unique name conflict with old entries? -crbug.com/778372 external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects.html [ Crash ] - -# https://crbug.com/819800: Feature policy propagation trouble? Test synchronization issue? -crbug.com/819800 external/wpt/payment-request/allowpaymentrequest/setting-allowpaymentrequest-timing.https.sub.html [ Failure ] - -# The tests below set document.domain. Such tests are skipped, because they -# cannot work when same-site WPT origins are isolated from each other via -# --isolate-origins cmdline flag (which is how bots run the -# |site_per_process_webkit_layout_tests| step). Note that -# https://crbug.com/783416 tracks adding a WPT origin that is cross-site, but -# even after this bug is fixed we may decide to keep the current -# --isolate-origins coverage and therefore the tests might end up being skipped -# for the foreseeable future. -Bug(none) external/wpt/html/browsers/origin/relaxing-the-same-origin-restriction [ Skip ] -Bug(none) external/wpt/FileAPI/url/multi-global-origin-serialization.sub.html [ Skip ] -Bug(none) virtual/mojo-blob-urls/external/wpt/FileAPI/url/multi-global-origin-serialization.sub.html [ Skip ] -Bug(none) external/wpt/dom/events/EventListener-incumbent-global-1.sub.html [ Skip ] -Bug(none) external/wpt/dom/events/EventListener-incumbent-global-2.sub.html [ Skip ] -Bug(none) external/wpt/html/browsers/history/the-location-interface/allow_prototype_cycle_through_location.sub.html [ Skip ] -Bug(none) external/wpt/html/browsers/history/the-location-interface/location-prototype-setting-same-origin-domain.sub.html [ Skip ] -Bug(none) external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects-on-new-window.html [ Skip ] -Bug(none) external/wpt/html/browsers/the-windowproxy-exotic-object/windowproxy-prototype-setting-same-origin-domain.sub.html [ Skip ] -Bug(none) external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-domain-success.sub.html [ Skip ] -Bug(none) external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-similar-but-cross-origin-success.sub.html [ Skip ] -Bug(none) virtual/sharedarraybuffer/external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-domain-success.sub.html [ Skip ] -Bug(none) virtual/sharedarraybuffer/external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-similar-but-cross-origin-success.sub.html [ Skip ] -Bug(none) external/wpt/wasm/serialization/window-domain-success.sub.html [ Skip ] -Bug(none) external/wpt/wasm/serialization/window-similar-but-cross-origin-success.sub.html [ Skip ] - -# Layout tests don't work for printing cross-site frames. -crbug.com/822372 http/tests/printing/cross-site-frame.html [ Crash ] -crbug.com/822372 http/tests/printing/cross-site-frame-scrolled.html [ Crash ] - -# TODO(lukasza, alexmos): Triage these failures. -crbug.com/801992 http/tests/misc/iframe-script-modify-attr.html [ Pass Crash ] -crbug.com/807675 http/tests/images/image-decode-in-frame.html [ Crash Failure ] - -# https://crbug.com/872952: Autoplay is still disabled if there is no gesture. -crbug.com/872952 http/tests/media/autoplay/document-user-activation-feature-policy-iframe-no-gesture.html [ Failure Pass Timeout ] - -# https://crbug.com/895001: Blink layout tests with cross-origin mouse clicks can fail without slow path hit testing -crbug.com/895001 external/wpt/html/user-activation/message-event-activation-api-iframe-cross-origin.sub.tentative.html [ Timeout Pass ]
diff --git a/third_party/WebKit/LayoutTests/NeverFixTests b/third_party/WebKit/LayoutTests/NeverFixTests index bf0035c..03737586 100644 --- a/third_party/WebKit/LayoutTests/NeverFixTests +++ b/third_party/WebKit/LayoutTests/NeverFixTests
@@ -2075,3 +2075,43 @@ virtual/speech-with-unified-autoplay/external/wpt/speech-api/SpeechRecognition-stop-manual.https.html [ WontFix ] external/wpt/pointerevents/pointerevent_pointermove-manual.html [ WontFix ] [ Retina ] external/wpt/pointerevents/pointerevent_touch-action-table-test_touch-manual.html [ WontFix ] + +# ====== Tests incompatible with the default Site Isolation from here ====== +# See also third_party/WebKit/LayoutTests/virtual/not-site-per-process/README.md +# +# When modifying the list of files that behave differently with and without +# OOPIFs, please consider modifying all the locations below: +# - LayoutTests/NeverFixTests (the section here) +# - LayoutTests/VirtualTestSuites (virtual/not-site-per-process suite) +# - LayoutTests/virtual/not-site-per-process/README.md + +# Tests permanently disabled with Site Isolation (e.g. tests that use +# document.domain are are therefore inherently incompatible with isolation of +# WPT origins): +Bug(none) external/wpt/html/browsers/origin/relaxing-the-same-origin-restriction [ WontFix ] +Bug(none) external/wpt/FileAPI/url/multi-global-origin-serialization.sub.html [ WontFix ] +Bug(none) virtual/mojo-blob-urls/external/wpt/FileAPI/url/multi-global-origin-serialization.sub.html [ WontFix ] +Bug(none) external/wpt/dom/events/EventListener-incumbent-global-1.sub.html [ WontFix ] +Bug(none) external/wpt/dom/events/EventListener-incumbent-global-2.sub.html [ WontFix ] +Bug(none) external/wpt/html/browsers/history/the-location-interface/allow_prototype_cycle_through_location.sub.html [ WontFix ] +Bug(none) external/wpt/html/browsers/history/the-location-interface/location-prototype-setting-same-origin-domain.sub.html [ WontFix ] +Bug(none) external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects-on-new-window.html [ WontFix ] +Bug(none) external/wpt/html/browsers/the-windowproxy-exotic-object/windowproxy-prototype-setting-same-origin-domain.sub.html [ WontFix ] +Bug(none) external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-domain-success.sub.html [ WontFix ] +Bug(none) external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-similar-but-cross-origin-success.sub.html [ WontFix ] +Bug(none) virtual/sharedarraybuffer/external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-domain-success.sub.html [ WontFix ] +Bug(none) virtual/sharedarraybuffer/external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-similar-but-cross-origin-success.sub.html [ WontFix ] +Bug(none) external/wpt/wasm/serialization/window-domain-success.sub.html [ WontFix ] +Bug(none) external/wpt/wasm/serialization/window-similar-but-cross-origin-success.sub.html [ WontFix ] + +# Code cache isolation tests only make sense if either +# 1) site isolation is disabled or +# (covered by virtual/not-site-per-process/.../isolated-code-cache) +# 2) site isolation is enabled together with --enable-features=IsolatedCodeCache +# (covered by virtual/site-isolated-code-cache/.../isolated-code-cache) +# but don't make sense if +# 3) site isolation is enabled without also enabling +# IsolatedCodeCache (tests disabled by the test expectation below). +Bug(none) http/tests/devtools/isolated-code-cache/cross-origin-test.js [ WontFix ] + +# ====== Tests incompatible with the default Site Isolation until here ======
diff --git a/third_party/WebKit/LayoutTests/SlowTests b/third_party/WebKit/LayoutTests/SlowTests index 28278ef..8905091 100644 --- a/third_party/WebKit/LayoutTests/SlowTests +++ b/third_party/WebKit/LayoutTests/SlowTests
@@ -592,6 +592,7 @@ crbug.com/874695 external/wpt/html/browsers/history/joint-session-history/joint-session-history-remove-iframe.html [ Slow ] crbug.com/874695 external/wpt/html/browsers/offline/application-cache-api/api_status_idle.https.html [ Slow ] crbug.com/874695 external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects.html [ Slow ] +crbug.com/874695 virtual/not-site-per-process/external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects.html [ Slow ] crbug.com/874695 external/wpt/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-tokenization-noopener.html [ Slow ] crbug.com/874695 external/wpt/html/browsers/windows/noreferrer-window-name.html [ Slow ] crbug.com/874695 external/wpt/html/dom/documents/resource-metadata-management/document-lastModified-01.html [ Slow ] @@ -638,6 +639,7 @@ crbug.com/874695 external/wpt/html/user-activation/activation-api-iframe-no-activate.tenative.html [ Slow ] crbug.com/874695 external/wpt/html/user-activation/activation-thru-contextmenu-event-manual.html [ Slow ] crbug.com/874695 external/wpt/html/user-activation/message-event-activation-api-iframe-cross-origin.sub.tentative.html [ Slow ] +crbug.com/874695 virtual/not-site-per-process/external/wpt/html/user-activation/message-event-activation-api-iframe-cross-origin.sub.tentative.html [ Slow ] crbug.com/874695 external/wpt/IndexedDB/interleaved-cursors-large.html [ Slow ] crbug.com/874695 external/wpt/IndexedDB/interleaved-cursors-small.html [ Slow ] crbug.com/874695 external/wpt/IndexedDB/nested-cloning-large-multiple.html [ Slow ] @@ -660,6 +662,7 @@ crbug.com/874695 external/wpt/orientation-sensor/AbsoluteOrientationSensor.https.html [ Slow ] crbug.com/874695 external/wpt/orientation-sensor/RelativeOrientationSensor.https.html [ Slow ] crbug.com/874695 external/wpt/payment-request/allowpaymentrequest/setting-allowpaymentrequest-timing.https.sub.html [ Slow ] +crbug.com/874695 virtual/not-site-per-process/external/wpt/payment-request/allowpaymentrequest/setting-allowpaymentrequest-timing.https.sub.html [ Slow ] crbug.com/874695 external/wpt/performance-timeline/po-observe.html [ Slow ] crbug.com/874695 external/wpt/picture-in-picture/leave-picture-in-picture.html [ Slow ] crbug.com/874695 external/wpt/picture-in-picture/picture-in-picture-window.html [ Slow ] @@ -860,7 +863,6 @@ crbug.com/874695 http/tests/devtools/audits2/audits2-limited-run.js [ Slow ] crbug.com/874695 http/tests/devtools/audits2/audits2-successful-run.js [ Slow ] crbug.com/874695 http/tests/devtools/console/console-correct-suggestions.js [ Slow ] -crbug.com/874695 http/tests/devtools/console-cross-origin-iframe-logging.js [ Slow ] crbug.com/874695 http/tests/devtools/editor/text-editor-formatter.js [ Slow ] crbug.com/874695 http/tests/devtools/inspect-iframe-from-different-domain.js [ Slow ] crbug.com/874695 http/tests/devtools/oopif/oopif-cookies-refresh.js [ Slow ] @@ -955,8 +957,11 @@ crbug.com/874695 http/tests/images/png-progressive-load.html [ Slow ] crbug.com/874695 http/tests/images/webp-progressive-load.html [ Slow ] crbug.com/874695 http/tests/inspector-protocol/request-mixed-content-status-blockable.js [ Slow ] +crbug.com/874695 virtual/not-site-per-process/http/tests/inspector-protocol/request-mixed-content-status-blockable.js [ Slow ] crbug.com/874695 http/tests/inspector-protocol/request-mixed-content-status-none.js [ Slow ] +crbug.com/874695 virtual/not-site-per-process/http/tests/inspector-protocol/request-mixed-content-status-none.js [ Slow ] crbug.com/874695 http/tests/inspector-protocol/request-mixed-content-status-optionally-blockable.js [ Slow ] +crbug.com/874695 virtual/not-site-per-process/http/tests/inspector-protocol/request-mixed-content-status-optionally-blockable.js [ Slow ] crbug.com/874695 http/tests/media/controls/toggle-class-with-state-source-buffer.html [ Slow ] crbug.com/874695 http/tests/media/preload-conditions.html [ Slow ] crbug.com/874695 http/tests/media/video-buffered.html [ Slow ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index e359937..a4e3da25 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -13,7 +13,6 @@ crbug.com/807686 crbug.com/24182 jquery/manipulation.html [ Timeout Pass ] - # See crbug.com/891427. These tests either fail or become flaky on one or more # platforms when --enable-display-compositor-pixel-dump is turned on. They need # triage. Note that these overlap with several existing entries in this @@ -99,6 +98,71 @@ crbug.com/887140 hdr/video-canvas-alpha.html [ Failure ] +# ====== Site Isolation failures from here ====== +# See also third_party/WebKit/LayoutTests/virtual/not-site-per-process/README.md +# +# When modifying the list of files that behave differently with and without +# OOPIFs, please consider modifying all the locations below: +# - LayoutTests/TestExpectations (the section here) +# - LayoutTests/VirtualTestSuites (virtual/not-site-per-process suite) +# - LayoutTests/virtual/not-site-per-process/README.md + +# Tests temporarily disabled with Site Isolation - test issues or test harness +# issues (e.g. missing OOPIF support in the test harness). +# TODO(lukasza, alexmos): Burn down this list. +crbug.com/585188 http/tests/xmlhttprequest/origin-whitelisting-all.html [ Failure ] +crbug.com/585188 http/tests/xmlhttprequest/origin-whitelisting-ip-addresses.html [ Failure ] +crbug.com/585188 virtual/outofblink-cors/http/tests/xmlhttprequest/origin-whitelisting-all.html [ Failure ] +crbug.com/585188 virtual/outofblink-cors/http/tests/xmlhttprequest/origin-whitelisting-ip-addresses.html [ Failure ] +crbug.com/606594 http/tests/local/serviceworker/fetch-request-body-file.html [ Skip ] +crbug.com/645641 external/wpt/html/syntax/parsing/html5lib_tests19.html [ Crash Failure ] +crbug.com/650348 http/tests/webaudio/autoplay-crossorigin.html [ Timeout ] +crbug.com/665058 http/tests/local/drag-over-remote-content.html [ Crash ] +crbug.com/771003 http/tests/security/mixedContent/insecure-iframe-in-main-frame.html [ Failure ] +crbug.com/771003 virtual/outofblink-cors-ns/http/tests/security/mixedContent/insecure-iframe-in-main-frame.html [ Failure ] +crbug.com/771003 virtual/outofblink-cors/http/tests/security/mixedContent/insecure-iframe-in-main-frame.html [ Failure ] + +# Tests temporarily disabled with Site Isolation - known differences in product +# behavior (either accepted for the long-term, or for the short-term): +# TODO(lukasza, alexmos): Burn down this list. +# Text auto-sizing: +crbug.com/393285 http/tests/text-autosizing/narrow-iframe.html [ Failure Crash ] +crbug.com/393285 http/tests/text-autosizing/wide-iframe.html [ Failure Crash ] +# Console message differences (e.g. full URI vs origin-only): +crbug.com/619662 http/tests/navigation/cross-origin-fragment-navigation-is-async.html [ Failure ] +crbug.com/619662 virtual/outofblink-cors-ns/http/tests/navigation/cross-origin-fragment-navigation-is-async.html [ Failure ] +crbug.com/619662 virtual/outofblink-cors/http/tests/navigation/cross-origin-fragment-navigation-is-async.html [ Failure ] +crbug.com/619662 virtual/stable/http/tests/navigation/cross-origin-fragment-navigation-is-async.html [ Failure ] +crbug.com/669083 http/tests/security/frameNavigation/xss-DENIED-top-navigation-without-user-gesture.html [ Failure ] +crbug.com/669083 virtual/outofblink-cors-ns/http/tests/security/frameNavigation/xss-DENIED-top-navigation-without-user-gesture.html [ Failure ] +crbug.com/669083 virtual/outofblink-cors/http/tests/security/frameNavigation/xss-DENIED-top-navigation-without-user-gesture.html [ Failure ] +crbug.com/886588 external/wpt/dom/events/EventListener-addEventListener.sub.window.html [ Failure ] + +# Tests temporarily disabled with Site Isolation - uninvestigated bugs: +# TODO(lukasza, alexmos): Burn down this list. +crbug.com/608015 http/tests/inspector-protocol/access-inspected-object.js [ Failure Timeout ] +crbug.com/623268 http/tests/inspector-protocol/request-mixed-content-status-blockable.js [ Timeout ] +crbug.com/623268 http/tests/inspector-protocol/request-mixed-content-status-none.js [ Timeout ] +crbug.com/623268 http/tests/inspector-protocol/request-mixed-content-status-optionally-blockable.js [ Timeout ] +crbug.com/678482 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/769508 fast/css/acid2.html [ Failure ] +crbug.com/778372 external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects.html [ Crash ] +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-ns/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 ] +crbug.com/807675 http/tests/images/image-decode-in-frame.html [ Crash Failure ] +crbug.com/819800 external/wpt/payment-request/allowpaymentrequest/setting-allowpaymentrequest-timing.https.sub.html [ Failure ] +crbug.com/822372 http/tests/printing/cross-site-frame-scrolled.html [ Crash ] +crbug.com/822372 http/tests/printing/cross-site-frame.html [ Crash ] +crbug.com/872952 http/tests/media/autoplay/document-user-activation-feature-policy-iframe-no-gesture.html [ Failure Pass Timeout ] +crbug.com/895001 external/wpt/html/user-activation/message-event-activation-api-iframe-cross-origin.sub.tentative.html [ Timeout Pass ] +crbug.com/901502 http/tests/devtools/oopif/oopif-storage.js [ Pass Failure ] +# ====== Site Isolation failures until here ====== + # ====== Oilpan-only failures from here ====== # Most of these actually cause the tests to report success, rather than # failure. Expected outputs will be adjusted for the better once Oilpan @@ -1749,7 +1813,7 @@ crbug.com/667560 [ Debug ] http/tests/devtools/elements/styles-3/styles-change-node-while-editing.js [ Pass Failure ] crbug.com/778515 http/tests/devtools/elements/styles-3/styles-add-new-rule.js [ Pass Failure ] -crbug.com/667560 [ Win ] http/tests/devtools/console-cross-origin-iframe-logging.js [ Pass Timeout ] +crbug.com/667560 http/tests/devtools/console-cross-origin-iframe-logging.js [ Pass Timeout ] crbug.com/778391 http/tests/devtools/elements/styles-3/styles-add-new-rule-tab.js [ Pass Failure ] crbug.com/778391 http/tests/devtools/elements/styles-3/styles-disable-inherited.js [ Pass Failure ] @@ -4038,9 +4102,9 @@ crbug.com/798864 [ Android ] external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/serialization-via-idb.any.worker.html [ Failure ] crbug.com/798864 [ Android ] external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/serialization-via-notifications-api.any.html [ Failure ] crbug.com/798864 [ Android ] external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/serialization-via-notifications-api.any.worker.html [ Failure ] -crbug.com/798864 [ Android ] external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-domain-success.sub.html [ Failure ] +crbug.com/798864 [ Android ] virtual/not-site-per-process/external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-domain-success.sub.html [ Failure ] crbug.com/798864 [ Android ] external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-serviceworker-failure.https.html [ Failure ] -crbug.com/798864 [ Android ] external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-similar-but-cross-origin-success.sub.html [ Failure ] +crbug.com/798864 [ Android ] virtual/not-site-per-process/external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-similar-but-cross-origin-success.sub.html [ Failure ] crbug.com/798864 [ Android ] external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-simple-success.html [ Failure ] crbug.com/798864 [ Android ] external/wpt/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/canblock-dedicatedworker.html [ Failure ] crbug.com/798864 [ Android ] external/wpt/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-agent-formalism/canblock-serviceworker.https.html [ Failure ] @@ -4713,7 +4777,7 @@ crbug.com/839332 [ Mac ] virtual/video-surface-layer/media/video-no-audio.html [ Pass Failure ] # This will break for now -crbug.com/841933 http/tests/webaudio/autoplay-crossorigin.html [ Skip ] +crbug.com/841933 virtual/not-site-per-process/http/tests/webaudio/autoplay-crossorigin.html [ Skip ] # Sheriff 2018-05-22 crbug.com/845610 [ Win ] http/tests/inspector-protocol/target/target-browser-context.js [ Pass Failure ] @@ -5279,5 +5343,5 @@ crbug.com/905827 [ Mac10.13 ] fast/dom/StyleSheet/stylesheet-move-between-documents-crash.html [ Failure Pass ] #Sheriff 2018-11-19 -crbug.com/906591 [ Win10 ] printing/single-line-must-not-be-split-into-two-pages.html [ Failure ] -crbug.com/906591 [ Win10 ] virtual/threaded/printing/single-line-must-not-be-split-into-two-pages.html [ Failure ] +crbug.com/906591 printing/single-line-must-not-be-split-into-two-pages.html [ Failure ] +crbug.com/906591 virtual/threaded/printing/single-line-must-not-be-split-into-two-pages.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/VirtualTestSuites b/third_party/WebKit/LayoutTests/VirtualTestSuites index d8194cf..b86771e0 100644 --- a/third_party/WebKit/LayoutTests/VirtualTestSuites +++ b/third_party/WebKit/LayoutTests/VirtualTestSuites
@@ -801,5 +801,225 @@ "base": "http/tests/devtools/isolated-code-cache", "args": ["--enable-features=IsolatedCodeCache", "--site-per-process"] + }, + { + "prefix": "not-site-per-process", + "base": "http/tests/devtools/isolated-code-cache", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "external/wpt/FileAPI/url/multi-global-origin-serialization.sub.html", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "external/wpt/content-security-policy/securitypolicyviolation/upgrade-insecure-requests-reporting.https.html", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "external/wpt/dom/events/EventListener-addEventListener.sub.window.js", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "external/wpt/dom/events/EventListener-incumbent-global-1.sub.html", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "external/wpt/dom/events/EventListener-incumbent-global-2.sub.html", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "external/wpt/html/browsers/history/the-location-interface/allow_prototype_cycle_through_location.sub.html", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "external/wpt/html/browsers/history/the-location-interface/location-prototype-setting-same-origin-domain.sub.html", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects-on-new-window.html", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects.html", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "external/wpt/html/browsers/origin/relaxing-the-same-origin-restriction", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "external/wpt/html/browsers/the-windowproxy-exotic-object/windowproxy-prototype-setting-same-origin-domain.sub.html", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-domain-success.sub.html", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-similar-but-cross-origin-success.sub.html", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "external/wpt/html/syntax/parsing/html5lib_tests19.html", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "external/wpt/html/user-activation/message-event-activation-api-iframe-cross-origin.sub.tentative.html", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "external/wpt/payment-request/allowpaymentrequest/setting-allowpaymentrequest-timing.https.sub.html", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "external/wpt/wasm/serialization/window-domain-success.sub.html", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "external/wpt/wasm/serialization/window-similar-but-cross-origin-success.sub.html", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "fast/css/acid2.html", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "http/tests/devtools/debugger/fetch-breakpoints.js", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "http/tests/devtools/oopif/oopif-storage.js", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "http/tests/images/image-decode-in-frame.html", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "http/tests/inspector-protocol/access-inspected-object.js", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "http/tests/inspector-protocol/request-mixed-content-status-blockable.js", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "http/tests/inspector-protocol/request-mixed-content-status-none.js", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "http/tests/inspector-protocol/request-mixed-content-status-optionally-blockable.js", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "http/tests/loading/bad-server-subframe.html", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "http/tests/local/drag-over-remote-content.html", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "http/tests/local/serviceworker/fetch-request-body-file.html", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "http/tests/media/autoplay/document-user-activation-feature-policy-iframe-no-gesture.html", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "http/tests/misc/iframe-script-modify-attr.html", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "http/tests/misc/webtiming-no-origin.html", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "http/tests/navigation/cross-origin-fragment-navigation-is-async.html", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "http/tests/printing/cross-site-frame-scrolled.html", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "http/tests/printing/cross-site-frame.html", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "http/tests/security/frameNavigation/xss-DENIED-top-navigation-without-user-gesture.html", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "http/tests/security/mixedContent/insecure-iframe-in-main-frame.html", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "http/tests/security/upgrade-insecure-requests/iframe-upgrade.https.html", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "http/tests/text-autosizing/narrow-iframe.html", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "http/tests/text-autosizing/wide-iframe.html", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "http/tests/webaudio/autoplay-crossorigin.html", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "http/tests/xmlhttprequest/origin-whitelisting-all.html", + "args": ["--disable-site-isolation-trials"] + }, + { + "prefix": "not-site-per-process", + "base": "http/tests/xmlhttprequest/origin-whitelisting-ip-addresses.html", + "args": ["--disable-site-isolation-trials"] } ]
diff --git a/third_party/WebKit/LayoutTests/compositing/video/video-controls-squashing.html b/third_party/WebKit/LayoutTests/compositing/video/video-controls-squashing.html new file mode 100644 index 0000000..4a1af663 --- /dev/null +++ b/third_party/WebKit/LayoutTests/compositing/video/video-controls-squashing.html
@@ -0,0 +1,27 @@ +<!doctype HTML> +<style> +.container { + border-radius: 8px; + overflow: hidden; +} + +video { + display: block; + width: 200px; + height: 200px; + background: lightblue; +} + +.bluebutton { + position: relative; + top: -20px; + height: 100px; + width: 100px; + background: blue; +} +</style> +Should show a video with a blue square on it that is not clipped to the video. +<div class="container"> + <video src="../../media/content/test.webm"></video> + <div class="bluebutton"></div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json index b85274cb..38da7d4 100644 --- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json +++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json
@@ -180122,71 +180122,36 @@ {} ] ], - "svg/geometry/parsing/cx-computed-expected.txt": [ - [ - {} - ] - ], "svg/geometry/parsing/cx-invalid-expected.txt": [ [ {} ] ], - "svg/geometry/parsing/cy-computed-expected.txt": [ - [ - {} - ] - ], "svg/geometry/parsing/cy-invalid-expected.txt": [ [ {} ] ], - "svg/geometry/parsing/r-computed-expected.txt": [ - [ - {} - ] - ], "svg/geometry/parsing/r-invalid-expected.txt": [ [ {} ] ], - "svg/geometry/parsing/rx-computed-expected.txt": [ - [ - {} - ] - ], "svg/geometry/parsing/rx-invalid-expected.txt": [ [ {} ] ], - "svg/geometry/parsing/ry-computed-expected.txt": [ - [ - {} - ] - ], "svg/geometry/parsing/ry-invalid-expected.txt": [ [ {} ] ], - "svg/geometry/parsing/x-computed-expected.txt": [ - [ - {} - ] - ], "svg/geometry/parsing/x-invalid-expected.txt": [ [ {} ] ], - "svg/geometry/parsing/y-computed-expected.txt": [ - [ - {} - ] - ], "svg/geometry/parsing/y-invalid-expected.txt": [ [ {} @@ -269739,6 +269704,12 @@ {} ] ], + "svg/painting/parsing/stroke-width-computed.svg": [ + [ + "/svg/painting/parsing/stroke-width-computed.svg", + {} + ] + ], "svg/painting/parsing/stroke-width-invalid.svg": [ [ "/svg/painting/parsing/stroke-width-invalid.svg", @@ -317311,7 +317282,7 @@ "testharness" ], "css/css-align/gaps/column-gap-parsing-001.html": [ - "a0a92a911e29aba357a8c39c2f8afe7d48e83a97", + "7feeddf85127ba82ad1713c1b970be6816faf11e", "testharness" ], "css/css-align/gaps/gap-animation-001.html": [ @@ -317343,19 +317314,19 @@ "reftest" ], "css/css-align/gaps/gap-parsing-001.html": [ - "0a2a9bda7c69f998baff8bbb085bfb07faa590e4", + "9ff3872114dcfbf2ccbbddb41c1e0f2b1fa1edb0", "testharness" ], "css/css-align/gaps/grid-column-gap-parsing-001.html": [ - "66d81998b668ef54734beca6640f6bba3cc8d717", + "baec0641cdaef532e12a1ba2511991cb86ffa14b", "testharness" ], "css/css-align/gaps/grid-gap-parsing-001.html": [ - "aa43f772996b208b05b2908eb2fba3479548a20d", + "fc10b620f1d02c1933007f3f2b68cbd98cdb60bd", "testharness" ], "css/css-align/gaps/grid-row-gap-parsing-001.html": [ - "e394ea1446b08f7b8d12d1fd1b9b4918e96ee8fb", + "d3b44f4bd7206e965a6c96a24888a3923cbccc28", "testharness" ], "css/css-align/gaps/row-gap-animation-001.html": [ @@ -317371,7 +317342,7 @@ "testharness" ], "css/css-align/gaps/row-gap-parsing-001.html": [ - "71b971d3a8a18cc7cd9710ac00ffe10e4f4111e4", + "59be718cee487270658c18c1b69c6f0be89ae53c", "testharness" ], "css/css-align/inheritance.html": [ @@ -341375,7 +341346,7 @@ "reftest" ], "css/css-paint-api/registered-property-interpolation-004.https.html": [ - "1596a934b396a0f7b7d0c4daa3580f172eaaf2c8", + "430326a0663281678dc6133a9d0b7cf6889352e3", "reftest" ], "css/css-paint-api/registered-property-interpolation-005.https.html": [ @@ -341447,7 +341418,7 @@ "reftest" ], "css/css-paint-api/registered-property-value-009.https.html": [ - "795770f9a2eea785b086ef8ba5b3a895c0402a4a", + "2ce2a0d56bd6a8bf230c5bae4790c633c34643c6", "reftest" ], "css/css-paint-api/registered-property-value-010.https.html": [ @@ -341931,7 +341902,7 @@ "support" ], "css/css-properties-values-api/registered-property-computation.html": [ - "2525e43ef51e1e5af94426346e51a68b87fea055", + "b1e5d23738b9dda1ea280dfd321bc5b2838b519a", "testharness" ], "css/css-properties-values-api/registered-property-cssom.html": [ @@ -341939,7 +341910,7 @@ "testharness" ], "css/css-properties-values-api/registered-property-initial.html": [ - "77aa9cd11a3eabfd154cc98869699e6f24c64c5c", + "82a012e2f68532761b18428c3eaed9479ec8c7e5", "testharness" ], "css/css-properties-values-api/resources/utils.js": [ @@ -343515,7 +343486,7 @@ "testharness" ], "css/css-shapes/shape-outside/values/shape-margin-003-expected.txt": [ - "62062868c8521252076f86441576bf4d126915e8", + "104e0bb978653db65bf16fbc5ce0552dfce44f6c", "support" ], "css/css-shapes/shape-outside/values/shape-margin-003.html": [ @@ -343579,7 +343550,7 @@ "testharness" ], "css/css-shapes/shape-outside/values/shape-outside-circle-010-expected.txt": [ - "3ce035e80a4438cb40f0655de14c492f8017ab04", + "f6d4093fb00555dffe00a4fa6601887fa0b6fbf1", "support" ], "css/css-shapes/shape-outside/values/shape-outside-circle-010.html": [ @@ -343587,7 +343558,7 @@ "testharness" ], "css/css-shapes/shape-outside/values/shape-outside-circle-011-expected.txt": [ - "fb6a89f0e67552cd6d9fb631b7ef92f4bea6961e", + "823faea146d58624135b8be1d3e8b40392964e68", "support" ], "css/css-shapes/shape-outside/values/shape-outside-circle-011.html": [ @@ -343643,7 +343614,7 @@ "testharness" ], "css/css-shapes/shape-outside/values/shape-outside-ellipse-010-expected.txt": [ - "7a8a2075dcbde4ac56361829759eb1b47ea418ad", + "d2bcdb95138fecd7a04cb98956a8027c55e04f5c", "support" ], "css/css-shapes/shape-outside/values/shape-outside-ellipse-010.html": [ @@ -343651,7 +343622,7 @@ "testharness" ], "css/css-shapes/shape-outside/values/shape-outside-ellipse-011-expected.txt": [ - "27a37189e0e10a3465195289fe4c29dc816db206", + "ebe434e047586370070a202bdafb56599b300af9", "support" ], "css/css-shapes/shape-outside/values/shape-outside-ellipse-011.html": [ @@ -343699,7 +343670,7 @@ "testharness" ], "css/css-shapes/shape-outside/values/shape-outside-inset-008-expected.txt": [ - "5f10cf98031e6e1a52f6f62eba27e8310b4e8157", + "b969e062ea7e2350987cb41b776cfb60010610e8", "support" ], "css/css-shapes/shape-outside/values/shape-outside-inset-008.html": [ @@ -343707,7 +343678,7 @@ "testharness" ], "css/css-shapes/shape-outside/values/shape-outside-inset-009-expected.txt": [ - "0d19e73dbb7f0af9606e2e4c8ab508d28483ae46", + "4a387910582b289d12e908f71614c77c223a171a", "support" ], "css/css-shapes/shape-outside/values/shape-outside-inset-009.html": [ @@ -343739,7 +343710,7 @@ "testharness" ], "css/css-shapes/shape-outside/values/shape-outside-polygon-006-expected.txt": [ - "299a6712158c4774b368dbea7dcf190e13064edf", + "f6747faa635680d2f1aaf812f0eb0f972d221057", "support" ], "css/css-shapes/shape-outside/values/shape-outside-polygon-006.html": [ @@ -354523,7 +354494,7 @@ "reftest" ], "css/css-transforms/transforms-support-calc-expected.txt": [ - "f58ab6ddfe4e3704446cdca6ab169f80c2cdd4b5", + "3e16e0ca86bde1b0371515ac76f51630fb8249bc", "support" ], "css/css-transforms/transforms-support-calc.html": [ @@ -354531,7 +354502,7 @@ "testharness" ], "css/css-transforms/translate-getComputedStyle.html": [ - "1e6759d1b0cccac754c62dde85102f052c73ff42", + "46a2c309020b5c66daba37f4d39879998b750214", "testharness" ], "css/css-transforms/translate-optional-second-001.html": [ @@ -369539,7 +369510,7 @@ "support" ], "css/motion/offset-supports-calc.html": [ - "79aa9a9f50acd57848df17908390c770d7b88976", + "9ec737e6a87198e390b4adc0c0cc5a349dc1bc43", "testharness" ], "css/motion/parsing/offset-anchor-parsing-invalid.html": [ @@ -417399,7 +417370,7 @@ "testharness" ], "payment-request/payment-response/complete-method-manual.https.html": [ - "a9da9eed9cbaed0540ef542f75896f532a60d13e", + "0e24de84f9b9c70b4a9f8964c7934ef7b8edb918", "manual" ], "payment-request/payment-response/helpers.js": [ @@ -417439,7 +417410,7 @@ "manual" ], "payment-request/payment-response/retry-method-manual.https.html": [ - "16ed15e54902b93485ee3be7a2635823e8763b06", + "69bda5ed3f32010c601ebb1cbff1c086a9ab4477", "manual" ], "payment-request/payment-response/shippingAddress-attribute-manual.https.html": [ @@ -433790,12 +433761,8 @@ "760328ac31818d86a9410fd7c412d803e30416a2", "testharness" ], - "svg/geometry/parsing/cx-computed-expected.txt": [ - "3bc668f75db08208aa67f8498384c1e35ef9df6a", - "support" - ], "svg/geometry/parsing/cx-computed.svg": [ - "5a408ba4d28f1acf36f2bde6767b65bc5401cf48", + "95c39fa0920c9a2ad53f36de769eacae90e77aff", "testharness" ], "svg/geometry/parsing/cx-invalid-expected.txt": [ @@ -433810,12 +433777,8 @@ "e7f627ac721fcc90597314ef0c97765566c343b3", "testharness" ], - "svg/geometry/parsing/cy-computed-expected.txt": [ - "3924738568928d31b04ecfb255466b7d357d1504", - "support" - ], "svg/geometry/parsing/cy-computed.svg": [ - "97a41aed9c1621c8da0f5318cf1a08339867d03f", + "23b56cbe79410616bddb7c687d7076ad922fea9c", "testharness" ], "svg/geometry/parsing/cy-invalid-expected.txt": [ @@ -433830,12 +433793,8 @@ "4372c36ea225328926030830e895f64858e73784", "testharness" ], - "svg/geometry/parsing/r-computed-expected.txt": [ - "06df88a859de902b7bf796120b9e9e56bffe84b9", - "support" - ], "svg/geometry/parsing/r-computed.svg": [ - "fc8ea983ff00e82e61fbc8b974657c1956391f8e", + "b0f6bb0f671267c4895413ff749f8a7a96f2cb5a", "testharness" ], "svg/geometry/parsing/r-invalid-expected.txt": [ @@ -433850,12 +433809,8 @@ "70cd5503b795cef3f5db7eb4db1034d63b3e63fc", "testharness" ], - "svg/geometry/parsing/rx-computed-expected.txt": [ - "4a7473248a0e6a913282ec7cc733a03929da4aed", - "support" - ], "svg/geometry/parsing/rx-computed.svg": [ - "7e4c42d29304a1f03e712149960356c5e0c7464b", + "a3210801ae3f748ba1612ff88d73cb438e5eb6b1", "testharness" ], "svg/geometry/parsing/rx-invalid-expected.txt": [ @@ -433870,12 +433825,8 @@ "e2b628f1de4bd8e2a3fec98fda1aa76b6af79b87", "testharness" ], - "svg/geometry/parsing/ry-computed-expected.txt": [ - "d4cfd52e00f1c276f2e7db9706af8cbbeeaa4832", - "support" - ], "svg/geometry/parsing/ry-computed.svg": [ - "390d63dc7e5aa9802edea9ad2193695e1dbdb688", + "b274199cec30beda41fda815b01f7445e2a9ffbf", "testharness" ], "svg/geometry/parsing/ry-invalid-expected.txt": [ @@ -433890,12 +433841,8 @@ "4ce5bec4084cf0e6cf1e6744701b756cc18e2f91", "testharness" ], - "svg/geometry/parsing/x-computed-expected.txt": [ - "b7b5a0d3fc426b529122aa553e5ccf74eb401b35", - "support" - ], "svg/geometry/parsing/x-computed.svg": [ - "f7da0ed9564380250bff469f388bf1a88d31a43a", + "9355ea3ae95767b9cee92d49b4f1d1809e2edc06", "testharness" ], "svg/geometry/parsing/x-invalid-expected.txt": [ @@ -433910,12 +433857,8 @@ "5ff2fbd831d7373faee706538f08528dc4ac8a99", "testharness" ], - "svg/geometry/parsing/y-computed-expected.txt": [ - "71c245f57f18e8a6a445c381948efb896df4ccd2", - "support" - ], "svg/geometry/parsing/y-computed.svg": [ - "83ef887da671eb532661c00e113118d6daa2e4b4", + "6c425e4f518eff45f781bd9ad4b6bab51126f2df", "testharness" ], "svg/geometry/parsing/y-invalid-expected.txt": [ @@ -434082,12 +434025,16 @@ "4499b9249a84a9d7de4a5a101993ad14f9cc21c9", "testharness" ], + "svg/painting/parsing/stroke-width-computed.svg": [ + "c9284be9a13a633872d9abb670f1c4390b540030", + "testharness" + ], "svg/painting/parsing/stroke-width-invalid.svg": [ "0d3f63d077f29a0a36f6443164dc7f24421a3f62", "testharness" ], "svg/painting/parsing/stroke-width-valid.svg": [ - "312b8923046a2944c052b085dabcf94aab25196a", + "02bca189f74fe91088ebe913f848b80dfc24868c", "testharness" ], "svg/painting/reftests/markers-orient-001-ref.svg": [ @@ -436727,7 +436674,7 @@ "support" ], "web-animations/animation-model/animation-types/accumulation-per-property-expected.txt": [ - "949315d5fcb6d93b2ac5ce71f7f2c2078d910de9", + "27a349b10bde8c291aece41e93b16190f3034133", "support" ], "web-animations/animation-model/animation-types/accumulation-per-property.html": [ @@ -436735,7 +436682,7 @@ "testharness" ], "web-animations/animation-model/animation-types/addition-per-property-expected.txt": [ - "482d5373d90e2ef706c606ca7eebc34978049e10", + "75190da20f6d5a3a8856432131a20130527ddbb3", "support" ], "web-animations/animation-model/animation-types/addition-per-property.html": [ @@ -436747,7 +436694,7 @@ "testharness" ], "web-animations/animation-model/animation-types/interpolation-per-property-expected.txt": [ - "6a24e5f47ff35cbedda98bf6793952d27f1e7a0d", + "afd0cfa2ec220a5eff1649acc6365892d5cae9d1", "support" ], "web-animations/animation-model/animation-types/interpolation-per-property.html": [ @@ -436759,7 +436706,7 @@ "support" ], "web-animations/animation-model/animation-types/property-types.js": [ - "519e38ae8aea2a6e5d762af56069ebddbb231838", + "9382c6297b9bb07ae06f95fbd099bcda5727a85f", "support" ], "web-animations/animation-model/animation-types/visibility.html": [
diff --git a/third_party/WebKit/LayoutTests/external/wpt/.well-known/origin-policy/policy-features b/third_party/WebKit/LayoutTests/external/wpt/.well-known/origin-policy/policy-features new file mode 100644 index 0000000..143ff58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/.well-known/origin-policy/policy-features
@@ -0,0 +1,6 @@ +{ + "feature-policy": [ + "camera 'self' https://example.org", + "geolocation https://example.org/" + ] +}
diff --git a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/abort.https.window.js b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/abort.https.window.js index b699406..9cc8c25 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/abort.https.window.js +++ b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/abort.https.window.js
@@ -8,7 +8,7 @@ backgroundFetchTest(async (test, backgroundFetch) => { const registration = await backgroundFetch.fetch( uniqueId(), - ['resources/feature-name.txt', '/serviceworker/resources/slow-response.php']); + ['resources/feature-name.txt', '/common/slow.py']); assert_true(await registration.abort()); assert_false(await registration.abort()); @@ -18,7 +18,7 @@ backgroundFetchTest(async (test, backgroundFetch) => { const registration = await backgroundFetch.fetch( uniqueId(), - ['resources/feature-name.txt', '/serviceworker/resources/slow-response.php']); + ['resources/feature-name.txt', '/common/slow.py']); await new Promise(resolve => { let aborted = false; @@ -63,7 +63,7 @@ backgroundFetchTest(async (test, backgroundFetch) => { const registration = await backgroundFetch.fetch( - uniqueId(), '/serviceworker/resources/slow-response.php'); + uniqueId(), '/common/slow.py'); assert_true(await registration.abort()); const {results} = await getMessageFromServiceWorker();
diff --git a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/fetch-uploads.https.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/fetch-uploads.https.window-expected.txt new file mode 100644 index 0000000..b422061 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/fetch-uploads.https.window-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Fetch with an upload should work promise_test: Unhandled rejection with value: object "TypeError: Requests with a body are not yet supported. For updates check http://crbug.com/774054" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/fetch-uploads.https.window.js b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/fetch-uploads.https.window.js new file mode 100644 index 0000000..c53b2996 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/fetch-uploads.https.window.js
@@ -0,0 +1,23 @@ +// META: script=/service-workers/service-worker/resources/test-helpers.sub.js +// META: script=resources/utils.js +'use strict'; + +// Covers basic functionality provided by BackgroundFetchManager.fetch(). +// Specifically, when `fetch` contains request uploads. +// https://wicg.github.io/background-fetch/#background-fetch-manager-fetch + +backgroundFetchTest(async (test, backgroundFetch) => { + const uploadData = 'Background Fetch!'; + const request = + new Request('resources/upload.py', {method: 'POST', body: uploadData}); + + await backgroundFetch.fetch(uniqueId(), request); + const {type, eventRegistration, results} = await getMessageFromServiceWorker(); + + assert_equals(type, 'backgroundfetchsuccess'); + assert_equals(results.length, 1); + assert_equals(eventRegistration.result, 'success'); + assert_equals(eventRegistration.failureReason, ''); + assert_equals(results[0].text, uploadData); + +}, 'Fetch with an upload should work'); \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/fetch.https.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/fetch.https.window-expected.txt index c2f9ace..d2026e32 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/fetch.https.window-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/fetch.https.window-expected.txt
@@ -9,7 +9,6 @@ PASS Registration object gets updated values when a background fetch completes. PASS Background Fetch that exceeds the quota throws a QuotaExceededError FAIL Fetches can have requests with duplicate URLs promise_test: Unhandled rejection with value: object "TypeError: Fetches with duplicate requests are not yet supported. Consider adding query params to make the requests unique. For updates check http://crbug.com/871174" -FAIL Fetches can have requests with a body promise_test: Unhandled rejection with value: object "TypeError: Requests with a body are not yet supported. For updates check http://crbug.com/774054" PASS recordsAvailable is false after onbackgroundfetchsuccess finishes execution. PASS Using Background Fetch to fetch a non-existent resource should fail. PASS Fetches with mixed content should fail.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/fetch.https.window.js b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/fetch.https.window.js index aee777d..52d29db5 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/fetch.https.window.js +++ b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/fetch.https.window.js
@@ -196,27 +196,6 @@ }, 'Fetches can have requests with duplicate URLs'); backgroundFetchTest(async (test, backgroundFetch) => { - const request = - new Request('resources/feature-name.txt', - {method: 'POST', body: 'TestBody'}); - - const registration = await backgroundFetch.fetch('my-id', request); - - const {type, eventRegistration, results} = await getMessageFromServiceWorker(); - assert_equals('backgroundfetchsuccess', type); - assert_equals(results.length, 1); - - assert_equals(eventRegistration.id, registration.id); - assert_equals(eventRegistration.failureReason, ''); - - assert_true(results[0].url.includes('resources/feature-name.txt')); - assert_equals(results[0].status, 200); - assert_equals(results[0].text, 'Background Fetch'); - - -}, 'Fetches can have requests with a body'); - -backgroundFetchTest(async (test, backgroundFetch) => { const registrationId = uniqueId(); const registration = await backgroundFetch.fetch(registrationId, 'resources/feature-name.txt'); @@ -319,4 +298,5 @@ assert_equals(eventRegistration.result, 'success'); assert_equals(eventRegistration.failureReason, ''); -}, 'Matching to a non-existing request should work'); \ No newline at end of file +}, 'Matching to a non-existing request should work'); +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/resources/upload.py b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/resources/upload.py new file mode 100644 index 0000000..585144e --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/resources/upload.py
@@ -0,0 +1,3 @@ +# Simply returns the request body to check if the upload succeeded. +def main(request, response): + return 200, [("Content-Type", request.headers['content-type'])], request.body
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/dom/documents/dom-tree-accessors/document.title-not-in-html-svg.html b/third_party/WebKit/LayoutTests/external/wpt/html/dom/documents/dom-tree-accessors/document.title-not-in-html-svg.html new file mode 100644 index 0000000..40eccd3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/dom/documents/dom-tree-accessors/document.title-not-in-html-svg.html
@@ -0,0 +1,27 @@ +<!DOCTYPE html> +<link rel="author" title="Rob Buis" href="mailto:rbuis@igalia.com"> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#document.title"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> + +function newXMLDocument() { + return document.implementation.createDocument(null, "foo", null); +} + +test(function() { + var doc = newXMLDocument(); + assert_equals(doc.title, ""); + doc.title = "fail"; + assert_equals(doc.title, ""); +}, "Should not be able to set document title in XML document"); + +test(function() { + var doc = newXMLDocument(); + doc.documentElement.appendChild(document.createElementNS("http://www.w3.org/1999/xhtml", "html:title")); + assert_equals(doc.title, ""); + doc.title = "fail"; + assert_equals(doc.title, ""); +}, "Should not be able to set document title in XML document with html:title element"); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/origin-policy/origin-policy-features.https.tentative.html b/third_party/WebKit/LayoutTests/external/wpt/origin-policy/origin-policy-features.https.tentative.html new file mode 100644 index 0000000..b5dbe3e --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/origin-policy/origin-policy-features.https.tentative.html
@@ -0,0 +1,16 @@ +<!DOCTYPE HTML> +<html> +<head> + <script src='/resources/testharness.js'></script> + <script src='/resources/testharnessreport.js'></script> +</head> +<body> + <script> + async_test(t => { + assert_false(document.policy.allowsFeature('geolocation')); + assert_true(document.policy.allowsFeature('camera')); + t.done(); + }, "Origin-Policy-based Feature policy"); + </script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/origin-policy/origin-policy-features.https.tentative.html.headers b/third_party/WebKit/LayoutTests/external/wpt/origin-policy/origin-policy-features.https.tentative.html.headers new file mode 100644 index 0000000..3e5ab40 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/origin-policy/origin-policy-features.https.tentative.html.headers
@@ -0,0 +1 @@ +Sec-Origin-Policy: policy-features
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-response/complete-method-manual.https.html b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-response/complete-method-manual.https.html index a9da9ee..0e24de8 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-response/complete-method-manual.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-response/complete-method-manual.https.html
@@ -12,12 +12,15 @@ button.disabled = true; const { response, request } = await getPaymentRequestResponse(); promise_test(async t => { + let completePromise; + let invalidComplete; + let afterComplete; try { // We .complete() as normal, using the passed test value - const completePromise = response.complete(result); + completePromise = response.complete(result); assert_true(completePromise instanceof Promise, "returns a promise"); // Immediately calling complete() again yields a rejected promise. - const invalidComplete = response.complete(result); + invalidComplete = response.complete(result); await promise_rejects(t, "InvalidStateError", invalidComplete); // but the original promise is unaffected const returnedValue = await completePromise; @@ -28,7 +31,7 @@ ); // We now call .complete() again, to force an exception // because [[complete]] is true. - const afterComplete = response.complete(result); + afterComplete = response.complete(result); await promise_rejects(t, "InvalidStateError", afterComplete); button.innerHTML = `✅ ${button.textContent}`; } catch (err) { @@ -41,7 +44,7 @@ afterComplete, ]); assert_equals( - allPromises.length, + allPromises.size, 3, "Calling complete() multiple times is always a new object." ); @@ -68,7 +71,7 @@ </button> </li> <li> - <button onclick="runManualTest({completeWith: 'unknown'}, this)"> + <button onclick="runManualTest({completeWith: undefined}, this)"> Passing no argument defaults to "unknown", eventually closing the sheet and doesn't throw. </button> @@ -79,10 +82,18 @@ </button> </li> <li> - <button onclick="runManualTest({completeWith: 'fail'}, this).then(done)"> + <button onclick="runManualTest({completeWith: 'fail'}, this)"> Passing "fail" eventually closes the sheet and doesn't throw. </button> </li> + <li> + <button onclick="runManualTest({completeWith: 'unknown'}, this)"> + Passing "unknown" eventually closes the sheet and doesn't throw. + </button> + </li> + <li> + <button onclick="done()">Done!</button> + </li> </ol> <small> If you find a buggy test, please <a href="https://github.com/web-platform-tests/wpt/issues">file a bug</a>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-response/retry-method-manual.https.html b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-response/retry-method-manual.https.html index 16ed15e5..69bda5e 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-response/retry-method-manual.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-response/retry-method-manual.https.html
@@ -55,12 +55,30 @@ promise_test(async t => { const { response } = await getPaymentRequestResponse(); const retryPromise = response.retry(); + const completePromise1 = response.complete("success"); + const completePromise2 = response.complete("failure"); + assert_not_equals( + completePromise1, + completePromise2, + "complete() must return unique promises" + ); await promise_rejects( t, "InvalidStateError", - response.complete("success"), + completePromise1, "Calling complete() while retrying rejects with an InvalidStateError" ); + await promise_rejects( + t, + "InvalidStateError", + completePromise2, + "Calling complete() while retrying rejects with an InvalidStateError" + ); + assert_not_equals( + completePromise1, + completePromise2, + "complete() must return unique promises" + ); await retryPromise; await response.complete("success"); }, button.textContent.trim());
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/embedded/image-embedding-svg-with-viewport-units.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/embedded/image-embedding-svg-with-viewport-units.svg new file mode 100644 index 0000000..6feb54b --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/embedded/image-embedding-svg-with-viewport-units.svg
@@ -0,0 +1,10 @@ +<svg xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:h="http://www.w3.org/1999/xhtml"> + <metadata> + <title><image> embedding SVG image with viewport units</title> + <h:link rel="match" href="support/green-rect-100x100.svg"/> + </metadata> + <image xlink:href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><rect width='50vw' height='50vh' fill='green'/></svg>" + width="200" height="200"/> +</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/embedded/support/green-rect-100x100.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/embedded/support/green-rect-100x100.svg new file mode 100644 index 0000000..1209414 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/embedded/support/green-rect-100x100.svg
@@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg"> + <rect width="100" height="100" fill="green"/> +</svg>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/site-per-process/http/tests/inspector-protocol/network/raw-headers-for-protected-document-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/disable-site-isolation-trials/http/tests/inspector-protocol/network/raw-headers-for-protected-document-expected.txt similarity index 92% rename from third_party/WebKit/LayoutTests/flag-specific/site-per-process/http/tests/inspector-protocol/network/raw-headers-for-protected-document-expected.txt rename to third_party/WebKit/LayoutTests/flag-specific/disable-site-isolation-trials/http/tests/inspector-protocol/network/raw-headers-for-protected-document-expected.txt index daf6459..16ba086 100644 --- a/third_party/WebKit/LayoutTests/flag-specific/site-per-process/http/tests/inspector-protocol/network/raw-headers-for-protected-document-expected.txt +++ b/third_party/WebKit/LayoutTests/flag-specific/disable-site-isolation-trials/http/tests/inspector-protocol/network/raw-headers-for-protected-document-expected.txt
@@ -4,5 +4,5 @@ Set-Cookie: name=value <script src="http://devtools.oopif.test:8000/inspector-protocol/network/resources/cookie.pl"> -Set-Cookie: undefined +Set-Cookie: name=value
diff --git a/third_party/WebKit/LayoutTests/flag-specific/site-per-process/http/tests/inspector-protocol/network/security-info-on-response-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/disable-site-isolation-trials/http/tests/inspector-protocol/network/security-info-on-response-expected.txt similarity index 81% rename from third_party/WebKit/LayoutTests/flag-specific/site-per-process/http/tests/inspector-protocol/network/security-info-on-response-expected.txt rename to third_party/WebKit/LayoutTests/flag-specific/disable-site-isolation-trials/http/tests/inspector-protocol/network/security-info-on-response-expected.txt index 0ca4430..547fe81 100644 --- a/third_party/WebKit/LayoutTests/flag-specific/site-per-process/http/tests/inspector-protocol/network/security-info-on-response-expected.txt +++ b/third_party/WebKit/LayoutTests/flag-specific/disable-site-isolation-trials/http/tests/inspector-protocol/network/security-info-on-response-expected.txt
@@ -1,5 +1,5 @@ Tests that security details are reported, even in the case of site isolation. Security state: insecure -Set-Cookie: undefined +Set-Cookie: name=value
diff --git a/third_party/WebKit/LayoutTests/flag-specific/site-per-process/external/wpt/dom/events/EventListener-addEventListener.sub.window-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/site-per-process/external/wpt/dom/events/EventListener-addEventListener.sub.window-expected.txt deleted file mode 100644 index d925bb0..0000000 --- a/third_party/WebKit/LayoutTests/flag-specific/site-per-process/external/wpt/dom/events/EventListener-addEventListener.sub.window-expected.txt +++ /dev/null
@@ -1,4 +0,0 @@ -This is a testharness.js-based test. -FAIL EventListener.addEventListener doesn't throw when a cross origin object is passed in. Failed to execute 'addEventListener' on 'EventTarget': The callback provided as parameter 2 is a cross origin object. -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/network/raw-headers-for-protected-document-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/network/raw-headers-for-protected-document-expected.txt index 16ba086..daf6459 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/network/raw-headers-for-protected-document-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/network/raw-headers-for-protected-document-expected.txt
@@ -4,5 +4,5 @@ Set-Cookie: name=value <script src="http://devtools.oopif.test:8000/inspector-protocol/network/resources/cookie.pl"> -Set-Cookie: name=value +Set-Cookie: undefined
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/network/security-info-on-response-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/network/security-info-on-response-expected.txt index 547fe81..0ca4430 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/network/security-info-on-response-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/network/security-info-on-response-expected.txt
@@ -1,5 +1,5 @@ Tests that security details are reported, even in the case of site isolation. Security state: insecure -Set-Cookie: name=value +Set-Cookie: undefined
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/video-paint-invalidation-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/video-paint-invalidation-expected.txt index e2b1cf40..9f880cef 100644 --- a/third_party/WebKit/LayoutTests/paint/invalidation/video-paint-invalidation-expected.txt +++ b/third_party/WebKit/LayoutTests/paint/invalidation/video-paint-invalidation-expected.txt
@@ -24,16 +24,18 @@ "drawsContent": false }, { - "name": "Squashing Containment Layer", - "drawsContent": false - }, - { "name": "LayoutFlexibleBox (relative positioned) DIV class='sizing-small test-mode phase-ready state-stopped'", "position": [8, 8], "bounds": [320, 240] }, { - "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV)", + "name": "LayoutBlockFlow (positioned) DIV", + "position": [8, 8], + "bounds": [320, 240], + "drawsContent": false + }, + { + "name": "LayoutFlexibleBox DIV", "position": [8, 8], "bounds": [320, 240] }
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/video/video-controls-squashing-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/video/video-controls-squashing-expected.png new file mode 100644 index 0000000..c663e2dd --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/video/video-controls-squashing-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/image/canvas-composite-repaint-by-all-imagesource-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/image/canvas-composite-repaint-by-all-imagesource-expected.txt index 89bf264..f68a5f7 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/image/canvas-composite-repaint-by-all-imagesource-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/image/canvas-composite-repaint-by-all-imagesource-expected.txt
@@ -466,18 +466,15 @@ "drawsContent": false }, { - "name": "Squashing Containment Layer", - "drawsContent": false - }, - { "name": "LayoutFlexibleBox (relative positioned) DIV class='sizing-small phase-ready state-stopped'", "position": [15, 859], "bounds": [150, 60] }, { - "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV)", + "name": "LayoutBlockFlow (positioned) DIV", "position": [15, 859], - "bounds": [150, 60] + "bounds": [150, 60], + "drawsContent": false } ] }
diff --git a/third_party/WebKit/LayoutTests/platform/mac/compositing/video/video-controls-squashing-expected.png b/third_party/WebKit/LayoutTests/platform/mac/compositing/video/video-controls-squashing-expected.png new file mode 100644 index 0000000..cc3dc94e --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac/compositing/video/video-controls-squashing-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/compositing/video/video-poster-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/compositing/video/video-poster-expected.txt index f01c7710..e90e866 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/compositing/video/video-poster-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/mac/compositing/video/video-poster-expected.txt
@@ -76,18 +76,15 @@ "drawsContent": false }, { - "name": "Squashing Containment Layer", - "drawsContent": false - }, - { "name": "LayoutFlexibleBox (relative positioned) DIV class='sizing-small phase-ready state-stopped'", "position": [8, 8], "bounds": [352, 288] }, { - "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV)", + "name": "LayoutBlockFlow (positioned) DIV", "position": [8, 8], - "bounds": [352, 288] + "bounds": [352, 288], + "drawsContent": false } ] }
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/image/canvas-composite-repaint-by-all-imagesource-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/image/canvas-composite-repaint-by-all-imagesource-expected.txt index 53b6b0a..b0b8f757 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/image/canvas-composite-repaint-by-all-imagesource-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/image/canvas-composite-repaint-by-all-imagesource-expected.txt
@@ -466,18 +466,15 @@ "drawsContent": false }, { - "name": "Squashing Containment Layer", - "drawsContent": false - }, - { "name": "LayoutFlexibleBox (relative positioned) DIV class='sizing-small phase-ready state-stopped'", "position": [15, 854], "bounds": [150, 60] }, { - "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV)", + "name": "LayoutBlockFlow (positioned) DIV", "position": [15, 854], - "bounds": [150, 60] + "bounds": [150, 60], + "drawsContent": false } ] }
diff --git a/third_party/WebKit/LayoutTests/platform/win/compositing/video/video-controls-squashing-expected.png b/third_party/WebKit/LayoutTests/platform/win/compositing/video/video-controls-squashing-expected.png new file mode 100644 index 0000000..e09a30a --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win/compositing/video/video-controls-squashing-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/compositing/video/video-poster-expected.txt b/third_party/WebKit/LayoutTests/platform/win/compositing/video/video-poster-expected.txt index d5a38eef..1737809 100644 --- a/third_party/WebKit/LayoutTests/platform/win/compositing/video/video-poster-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win/compositing/video/video-poster-expected.txt
@@ -76,18 +76,15 @@ "drawsContent": false }, { - "name": "Squashing Containment Layer", - "drawsContent": false - }, - { "name": "LayoutFlexibleBox (relative positioned) DIV class='sizing-small phase-ready state-stopped'", "position": [8, 8], "bounds": [352, 288] }, { - "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV)", + "name": "LayoutBlockFlow (positioned) DIV", "position": [8, 8], - "bounds": [352, 288] + "bounds": [352, 288], + "drawsContent": false } ] }
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/image/canvas-composite-repaint-by-all-imagesource-expected.txt b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/image/canvas-composite-repaint-by-all-imagesource-expected.txt index 3dc2f94..5957b1d 100644 --- a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/image/canvas-composite-repaint-by-all-imagesource-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/image/canvas-composite-repaint-by-all-imagesource-expected.txt
@@ -466,18 +466,15 @@ "drawsContent": false }, { - "name": "Squashing Containment Layer", - "drawsContent": false - }, - { "name": "LayoutFlexibleBox (relative positioned) DIV class='sizing-small phase-ready state-stopped'", "position": [15, 859], "bounds": [150, 60] }, { - "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV)", + "name": "LayoutBlockFlow (positioned) DIV", "position": [15, 859], - "bounds": [150, 60] + "bounds": [150, 60], + "drawsContent": false } ] }
diff --git a/third_party/WebKit/LayoutTests/virtual/not-site-per-process/README.md b/third_party/WebKit/LayoutTests/virtual/not-site-per-process/README.md new file mode 100644 index 0000000..6fc09489 --- /dev/null +++ b/third_party/WebKit/LayoutTests/virtual/not-site-per-process/README.md
@@ -0,0 +1,55 @@ +# virtual/not-site-per-process + +## Summary + +Layout tests use the default site isolation from the platform they are +run on. For example, strict site isolation (aka site-per-process) is +used on desktop platforms. + +Additionally, on platforms where strict site isolation is enabled, +layout tests opt into slightly stricter isolation and enabling isolating +same-site origins used by Web Platform Tests. This ensures that features +covered by WPT also provide sufficient coverage of how these feature +behave in presence of out-of-process iframes. + +Tests under `virtual/not-site-per-process` are run with +`--disable-site-isolation-trials` cmdline flag which turns off site +isolation. This is needed to preserve test coverage provided by around +60 tests that fail when run with site isolation. + +When modifying the list of files that behave differently with and without +OOPIFs, please consider modifying all the locations below: +- LayoutTests/VirtualTestSuites (virtual/not-site-per-process suite) +- LayoutTests/virtual/not-site-per-process/README.md +- LayoutTests/TestExpectations and/or LayoutTests/NeverFixTests + ("Site Isolation failures" section) + + +## Tests incompatible with WPT origin isolation + +The following tests modify `document.domain` and are therefore incompatible with +isolation of WPT origins. The tests need to stay under +`virtual/not-site-per-process` forever. These tests are covered by +`LayoutTests/NeverFixTests` expectations file. + +- external/wpt/html/browsers/origin/relaxing-the-same-origin-restriction +- external/wpt/FileAPI/url/multi-global-origin-serialization.sub.html +- external/wpt/dom/events/EventListener-incumbent-global-1.sub.html +- external/wpt/dom/events/EventListener-incumbent-global-2.sub.html +- external/wpt/html/browsers/history/the-location-interface/allow_prototype_cycle_through_location.sub.html +- external/wpt/html/browsers/history/the-location-interface/location-prototype-setting-same-origin-domain.sub.html +- external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects-on-new-window.html +- external/wpt/html/browsers/the-windowproxy-exotic-object/windowproxy-prototype-setting-same-origin-domain.sub.html +- external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-domain-success.sub.html +- external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-similar-but-cross-origin-success.sub.html +- external/wpt/wasm/serialization/window-domain-success.sub.html +- external/wpt/wasm/serialization/window-similar-but-cross-origin-success.sub.html + +## Tests that need further investigation and/or decisions + +Remaining tests need further investigation as they may either 1) hide +previously unknown OOPIF-related bugs or 2) expose known OOPIF-related +differences in product behavior or 3) expose known OOPIF-support issues +in tests or in the test harness. Over time, such tests should be +removed from `virtual/not-site-per-process`. These tests are covered +by `LayoutTests/TestExpectations` file.
diff --git a/third_party/blink/common/origin_policy/origin_policy_parser.cc b/third_party/blink/common/origin_policy/origin_policy_parser.cc index 98e0bc1..df42efe 100644 --- a/third_party/blink/common/origin_policy/origin_policy_parser.cc +++ b/third_party/blink/common/origin_policy/origin_policy_parser.cc
@@ -33,7 +33,12 @@ return false; base::Value* csp = json->FindKey("content-security-policy"); - return !csp || ParseContentSecurityPolicies(*csp); + bool csp_ok = !csp || ParseContentSecurityPolicies(*csp); + + base::Value* features = json->FindKey("feature-policy"); + bool features_ok = !features || ParseFeaturePolicies(*features); + + return csp_ok && features_ok; } bool OriginPolicyParser::ParseContentSecurityPolicies( @@ -63,4 +68,23 @@ return true; } +bool OriginPolicyParser::ParseFeaturePolicies(const base::Value& policies) { + if (!policies.is_list()) + return false; + + bool ok = true; + for (const auto& feature : policies.GetList()) { + ok &= ParseFeaturePolicy(feature); + } + return ok; +} + +bool OriginPolicyParser::ParseFeaturePolicy(const base::Value& policy) { + if (!policy.is_string()) + return false; + + policy_->features_.push_back(policy.GetString()); + return true; +} + } // namespace blink
diff --git a/third_party/blink/common/origin_policy/origin_policy_parser.h b/third_party/blink/common/origin_policy/origin_policy_parser.h index abc7a7b..5deb3bc 100644 --- a/third_party/blink/common/origin_policy/origin_policy_parser.h +++ b/third_party/blink/common/origin_policy/origin_policy_parser.h
@@ -29,6 +29,8 @@ bool DoParse(base::StringPiece); bool ParseContentSecurityPolicies(const base::Value&); bool ParseContentSecurityPolicy(const base::Value&); + bool ParseFeaturePolicies(const base::Value&); + bool ParseFeaturePolicy(const base::Value&); std::unique_ptr<OriginPolicy> policy_;
diff --git a/third_party/blink/common/origin_policy/origin_policy_unittest.cc b/third_party/blink/common/origin_policy/origin_policy_unittest.cc index 76fafcc7..13f8dbc 100644 --- a/third_party/blink/common/origin_policy/origin_policy_unittest.cc +++ b/third_party/blink/common/origin_policy/origin_policy_unittest.cc
@@ -137,3 +137,38 @@ )"); ASSERT_FALSE(policy->GetContentSecurityPolicies()[0].report_only); } + +TEST(OriginPolicy, FeatureOne) { + auto policy = blink::OriginPolicy::From(R"( + { "feature-policy": ["geolocation 'self' http://maps.google.com"] } )"); + ASSERT_EQ(1U, policy->GetFeaturePolicies().size()); + ASSERT_EQ("geolocation 'self' http://maps.google.com", + policy->GetFeaturePolicies()[0]); +} + +TEST(OriginPolicy, FeatureTwo) { + auto policy = blink::OriginPolicy::From(R"( + { "feature-policy": ["geolocation 'self' http://maps.google.com", + "camera https://example.com"]} )"); + ASSERT_EQ(2U, policy->GetFeaturePolicies().size()); + ASSERT_EQ("geolocation 'self' http://maps.google.com", + policy->GetFeaturePolicies()[0]); + ASSERT_EQ("camera https://example.com", policy->GetFeaturePolicies()[1]); +} + +TEST(OriginPolicy, FeatureTwoPolicies) { + auto policy = blink::OriginPolicy::From(R"( + { "feature-policy": ["geolocation 'self' http://maps.google.com"], + "feature-policy": ["camera https://example.com"] } )"); + + // TODO(vogelheim): Determine whether this is the correct behaviour. + ASSERT_EQ(1U, policy->GetFeaturePolicies().size()); +} + +TEST(OriginPolicy, FeatureComma) { + auto policy = blink::OriginPolicy::From(R"( + { "feature-policy": ["geolocation 'self' http://maps.google.com, camera https://example.com"]} )"); + + // TODO: Determine what to do with this case ! + ASSERT_EQ(1U, policy->GetFeaturePolicies().size()); +}
diff --git a/third_party/blink/public/common/origin_policy/origin_policy.h b/third_party/blink/public/common/origin_policy/origin_policy.h index c86631c..5c4583fb 100644 --- a/third_party/blink/public/common/origin_policy/origin_policy.h +++ b/third_party/blink/public/common/origin_policy/origin_policy.h
@@ -28,12 +28,17 @@ }; const std::vector<CSP>& GetContentSecurityPolicies() const { return csp_; } + const std::vector<std::string>& GetFeaturePolicies() const { + return features_; + } + private: friend class OriginPolicyParser; OriginPolicy(); std::vector<CSP> csp_; + std::vector<std::string> features_; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index dc92675..d1b6ad7 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -1681,31 +1681,25 @@ void Document::setTitle(const String& title) { // Title set by JavaScript -- overrides any title elements. - if (!title_element_) { - if (IsHTMLDocument() || IsXHTMLDocument()) { + Element* element = documentElement(); + if (IsSVGSVGElement(element)) { + if (!title_element_) { + title_element_ = SVGTitleElement::Create(*this); + element->InsertBefore(title_element_.Get(), element->firstChild()); + } + if (auto* svg_title = ToSVGTitleElementOrNull(title_element_)) + svg_title->SetText(title); + } else if (element && element->IsHTMLElement()) { + if (!title_element_) { HTMLElement* head_element = head(); if (!head_element) return; title_element_ = HTMLTitleElement::Create(*this); head_element->AppendChild(title_element_.Get()); - } else if (IsSVGDocument()) { - Element* element = documentElement(); - if (!IsSVGSVGElement(element)) - return; - title_element_ = SVGTitleElement::Create(*this); - element->InsertBefore(title_element_.Get(), element->firstChild()); } - } else { - if (!IsHTMLDocument() && !IsXHTMLDocument() && !IsSVGDocument()) - title_element_ = nullptr; + if (auto* html_title = ToHTMLTitleElementOrNull(title_element_)) + html_title->setText(title); } - - if (auto* html_title = ToHTMLTitleElementOrNull(title_element_)) - html_title->setText(title); - else if (auto* svg_title = ToSVGTitleElementOrNull(title_element_)) - svg_title->SetText(title); - else - UpdateTitle(title); } void Document::SetTitleElement(Element* title_element) {
diff --git a/third_party/blink/renderer/core/exported/web_frame_test.cc b/third_party/blink/renderer/core/exported/web_frame_test.cc index ca882ba..46e5042 100644 --- a/third_party/blink/renderer/core/exported/web_frame_test.cc +++ b/third_party/blink/renderer/core/exported/web_frame_test.cc
@@ -11524,6 +11524,60 @@ << visual_viewport.VisibleRectInDocument().ToString() << "]"; } +// Test bubbling a document (End key) scroll from an inner iframe. This test +// passes if it does not crash. https://crbug.com/904247. +TEST_F(WebFrameSimTest, ScrollToEndBubblingCrash) { + WebView().Resize(WebSize(500, 300)); + WebView().GetPage()->GetSettings().SetScrollAnimatorEnabled(false); + + SimRequest request("https://example.com/test.html", "text/html"); + LoadURL("https://example.com/test.html"); + request.Complete(R"HTML( + <!DOCTYPE html> + <style> + body, html { + width: 100%; + height: 100%; + margin: 0; + } + #frame { + width: 100%; + height: 100%; + border: 0; + } + </style> + <iframe id="frame" srcdoc=" + <!DOCTYPE html> + <style>html {height: 300%;}</style> + "></iframe> + )HTML"); + + Compositor().BeginFrame(); + RunPendingTasks(); + + // Focus the iframe. + WebView().AdvanceFocus(false); + + WebKeyboardEvent key_event(WebInputEvent::kRawKeyDown, + WebInputEvent::kNoModifiers, + WebInputEvent::GetStaticTimeStampForTests()); + key_event.windows_key_code = VKEY_END; + + // Scroll the iframe to the end. + key_event.SetType(WebInputEvent::kRawKeyDown); + WebView().HandleInputEvent(WebCoalescedInputEvent(key_event)); + key_event.SetType(WebInputEvent::kKeyUp); + WebView().HandleInputEvent(WebCoalescedInputEvent(key_event)); + + Compositor().BeginFrame(); + + // End key should now bubble from the iframe up to the main viewport. + key_event.SetType(WebInputEvent::kRawKeyDown); + WebView().HandleInputEvent(WebCoalescedInputEvent(key_event)); + key_event.SetType(WebInputEvent::kKeyUp); + WebView().HandleInputEvent(WebCoalescedInputEvent(key_event)); +} + // Basic smoke test of the paint path used by the Android disambiguation popup. TEST_F(WebFrameSimTest, DisambiguationPopupPixelTest) { WebView().Resize(WebSize(400, 600));
diff --git a/third_party/blink/renderer/core/input/scroll_manager.cc b/third_party/blink/renderer/core/input/scroll_manager.cc index ae744f5..68e636a 100644 --- a/third_party/blink/renderer/core/input/scroll_manager.cc +++ b/third_party/blink/renderer/core/input/scroll_manager.cc
@@ -187,10 +187,10 @@ if (!current_node.GetLayoutBox()) return false; - // We need to always add the root scroller in the main frame even if the - // viewport isn't scrollable since we can always pinch-zoom and scroll as - // well as for overscroll effects. - if (current_node.IsEffectiveRootScroller() && frame_->IsMainFrame()) + // We need to always add the global root scroller even if it isn't scrollable + // since we can always pinch-zoom and scroll as well as for overscroll + // effects. + if (current_node.GetLayoutBox()->IsGlobalRootScroller()) return true; ScrollableArea* scrollable_area =
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc index 491b95a..aaa30cf4 100644 --- a/third_party/blink/renderer/core/loader/document_loader.cc +++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -1129,6 +1129,29 @@ previous_security_origin); } +// Helper function: Merge the feature policy strings from HTTP headers and the +// origin policy (if any). +// Headers go first, which means that the per-page headers override the +// origin policy features. +void MergeFeaturesFromOriginPolicy(WTF::String& feature_policy, + const String& origin_policy_string) { + if (origin_policy_string.IsEmpty()) + return; + + std::unique_ptr<OriginPolicy> origin_policy = OriginPolicy::From( + StringUTF8Adaptor(origin_policy_string).AsStringPiece()); + if (!origin_policy) + return; + + for (const std::string& policy : origin_policy->GetFeaturePolicies()) { + if (!feature_policy.IsEmpty()) { + feature_policy.append(','); + } + feature_policy.append( + WTF::String::FromUTF8(policy.data(), policy.length())); + } +} + void DocumentLoader::InstallNewDocument( const KURL& url, Document* owner_document, @@ -1246,8 +1269,10 @@ // FeaturePolicy is reset in the browser process on commit, so this needs to // be initialized and replicated to the browser process after commit messages // are sent in didCommitNavigation(). - document->ApplyFeaturePolicyFromHeader( + WTF::String feature_policy( response_.HttpHeaderField(http_names::kFeaturePolicy)); + MergeFeaturesFromOriginPolicy(feature_policy, request_.GetOriginPolicy()); + document->ApplyFeaturePolicyFromHeader(feature_policy); GetFrameLoader().DispatchDidClearDocumentOfWindowObject(); }
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.cc b/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.cc index 60fcf54..3881838 100644 --- a/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.cc +++ b/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.cc
@@ -238,6 +238,9 @@ layer->DirectCompositingReasons()); } + if (layer->GetLayoutObject().IsVideo()) + info.is_under_video = true; + bool should_recurse = layer->ChildNeedsCompositingInputsUpdate() || update_type == kForceUpdate; @@ -360,6 +363,8 @@ if (info.needs_reparent_scroll && layout_object.StyleRef().IsStacked()) properties.scroll_parent = info.scrolling_ancestor; + properties.is_under_video = info.is_under_video; + layer->UpdateAncestorDependentCompositingInputs(properties); }
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.h b/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.h index 5303a1e9..823f156 100644 --- a/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.h +++ b/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.h
@@ -61,6 +61,8 @@ bool needs_reparent_scroll = false; bool needs_reparent_scroll_for_absolute = false; bool needs_reparent_scroll_for_fixed = false; + + bool is_under_video = false; }; void UpdateRecursive(PaintLayer*, UpdateType, AncestorInfo);
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner.cc b/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner.cc index 1e011f6df..e048a9f2 100644 --- a/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner.cc +++ b/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner.cc
@@ -135,15 +135,10 @@ const PaintLayer& squashing_layer = squashing_state.most_recent_mapping->OwningLayer(); - // FIXME: this special case for video exists only to deal with corner cases - // where a LayoutVideo does not report that it needs to be directly - // composited. Video does not currently support sharing a backing, but this - // could be generalized in the future. The following layout tests fail if we - // permit the video to share a backing with other layers. - // - // compositing/video/video-controls-layer-creation.html - if (layer->GetLayoutObject().IsVideo() || - squashing_layer.GetLayoutObject().IsVideo()) + // Don't squash into or out of any thing underneath a video, including the + // user-agent shadow DOM for controls. This is is to work around a + // bug involving overflow clip of videos. See crbug.com/900602. + if (layer->IsUnderVideo() || squashing_layer.IsUnderVideo()) return SquashingDisallowedReason::kSquashingVideoIsDisallowed; // Don't squash iframes, frames or plugins.
diff --git a/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc b/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc index 30cfec7..d21a2b7 100644 --- a/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc +++ b/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc
@@ -282,8 +282,8 @@ base::TimeTicks timestamp) { // The callback is safe from race-condition only when running on main-thread. DCHECK(ThreadState::Current()->IsMainThread()); - // Not guranteed to be non-empty, because record can be removed before the - // callback. + // Not guranteed to be non-empty, because records can be removed between + // callback registration and invocation. while (records_pending_timing_.size() > 0) { DOMNodeId node_id = records_pending_timing_.front(); if (!id_record_map_.Contains(node_id)) {
diff --git a/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc b/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc index 37f41fb..8da96b7 100644 --- a/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc +++ b/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc
@@ -231,6 +231,52 @@ EXPECT_EQ(LargestPaintStoredResult(), base::TimeTicks()); } +TEST_F(ImagePaintTimingDetectorTest, + LargestImagePaint_NodeRemovedBetweenRegistrationAndInvocation) { + SetBodyInnerHTML(R"HTML( + <div id="parent"> + <img id="target"></img> + </div> + )HTML"); + SetImageAndPaint("target", 5, 5); + UpdateAllLifecyclePhasesForTest(); + + GetDocument().getElementById("parent")->RemoveChild( + GetDocument().getElementById("target")); + + InvokeCallback(); + + ImageRecord* record; + record = FindLargestPaintCandidate(); + EXPECT_FALSE(record); +} + +TEST_F(ImagePaintTimingDetectorTest, LargestImagePaint_IgnoreReAttached) { + SetBodyInnerHTML(R"HTML( + <div id="parent"> + </div> + )HTML"); + HTMLImageElement* image = HTMLImageElement::Create(GetDocument()); + image->setAttribute("id", "target"); + GetDocument().getElementById("parent")->AppendChild(image); + SetImageAndPaint("target", 5, 5); + UpdateAllLifecyclePhasesAndInvokeCallbackIfAny(); + ImageRecord* record; + record = FindLargestPaintCandidate(); + EXPECT_TRUE(record); + + GetDocument().getElementById("parent")->RemoveChild(image); + UpdateAllLifecyclePhasesAndInvokeCallbackIfAny(); + record = FindLargestPaintCandidate(); + EXPECT_FALSE(record); + + GetDocument().getElementById("parent")->AppendChild(image); + SetImageAndPaint("target", 5, 5); + UpdateAllLifecyclePhasesAndInvokeCallbackIfAny(); + record = FindLargestPaintCandidate(); + EXPECT_TRUE(record); +} + // This test dipicts a situation when a smaller image has loaded, but a larger // image is loading. When we call analyze, the result will be empty because // we don't know when the largest image will finish loading. We wait until
diff --git a/third_party/blink/renderer/core/paint/paint_layer.h b/third_party/blink/renderer/core/paint/paint_layer.h index bf62c42..232b549 100644 --- a/third_party/blink/renderer/core/paint/paint_layer.h +++ b/third_party/blink/renderer/core/paint/paint_layer.h
@@ -754,6 +754,8 @@ IntRect unclipped_absolute_bounding_box; const LayoutBoxModelObject* clipping_container = nullptr; + + bool is_under_video = false; }; void SetNeedsCompositingInputsUpdate(); @@ -822,6 +824,9 @@ const PaintLayer* MaskAncestor() const { return GetAncestorDependentCompositingInputs().mask_ancestor; } + bool IsUnderVideo() const { + return GetAncestorDependentCompositingInputs().is_under_video; + } bool HasDescendantWithClipPath() const { DCHECK(!needs_descendant_dependent_flags_update_); return has_descendant_with_clip_path_;
diff --git a/third_party/blink/tools/blinkpy/common/net/buildbot_unittest.py b/third_party/blink/tools/blinkpy/common/net/buildbot_unittest.py index cce42c0..231b923 100644 --- a/third_party/blink/tools/blinkpy/common/net/buildbot_unittest.py +++ b/third_party/blink/tools/blinkpy/common/net/buildbot_unittest.py
@@ -107,7 +107,7 @@ def fetch_file(_): return ('ADD_RESULTS(%s);' % (json.dumps( [{"TestType": "webkit_layout_tests (with patch)"}, - {"TestType": "site_per_process_webkit_layout_tests (with patch)"}, + {"TestType": "not_site_per_process_webkit_layout_tests (with patch)"}, {"TestType": "webkit_layout_tests (retry with patch)"}, {"TestType": "base_unittests (with patch)"}])))
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/README.chromium b/third_party/blink/tools/blinkpy/third_party/wpt/README.chromium index b9745167..ae06882bb 100644 --- a/third_party/blink/tools/blinkpy/third_party/wpt/README.chromium +++ b/third_party/blink/tools/blinkpy/third_party/wpt/README.chromium
@@ -28,9 +28,7 @@ - update `WPT_HOST_AND_PORTS` in `//third_party/blink/tools/blinkpy/web_tests/port/driver.py` -- update bot configs (e.g. `Site Isolation Linux` bot forces OOPIFs by using - `--isolate-origins=http://www.web-platform.test:8001/` as specified in - `//testing/buildbot/chromium.fyi.json`). +- update LayoutTestContentBrowserClient::GetOriginsRequiringDedicatedProcess() checkout.sh ===========
diff --git a/third_party/blink/tools/blinkpy/web_tests/lint_test_expectations.py b/third_party/blink/tools/blinkpy/web_tests/lint_test_expectations.py index 190ab13..5b7acc9 100644 --- a/third_party/blink/tools/blinkpy/web_tests/lint_test_expectations.py +++ b/third_party/blink/tools/blinkpy/web_tests/lint_test_expectations.py
@@ -87,10 +87,17 @@ failures = [] for suite in virtual_suites: + # A virtual test suite needs either + # - a top-level README.md (e.g. virtual/foo/README.md) + # - a README.txt for each covered dir/file (e.g. + # virtual/foo/http/tests/README.txt, virtual/foo/fast/README.txt, ...) comps = [layout_tests_dir] + suite.name.split('/') + ['README.txt'] - path_to_readme = fs.join(*comps) - if not fs.exists(path_to_readme): - failure = '{} is missing (each virtual suite must have one).'.format(path_to_readme) + path_to_readme_txt = fs.join(*comps) + comps = [layout_tests_dir] + suite.name.split('/')[:2] + ['README.md'] + path_to_readme_md = fs.join(*comps) + if not fs.exists(path_to_readme_txt) and not fs.exists(path_to_readme_md): + failure = '{} and {} are both missing (each virtual suite must have one).'.format( + path_to_readme_txt, path_to_readme_md) _log.error(failure) failures.append(failure) if failures:
diff --git a/third_party/sqlite/BUILD.gn b/third_party/sqlite/BUILD.gn index fac654a..74c1608 100644 --- a/third_party/sqlite/BUILD.gn +++ b/third_party/sqlite/BUILD.gn
@@ -3,6 +3,7 @@ # found in the LICENSE file. import("//build/config/dcheck_always_on.gni") +import("//build/config/sanitizers/sanitizers.gni") import("//testing/libfuzzer/fuzzer_test.gni") # Compile-time options passed to SQLite. @@ -188,7 +189,8 @@ } } - if (use_fuzzing_engine && (is_debug || dcheck_always_on)) { + if (use_fuzzing_engine && use_sanitizer_coverage && + (is_debug || dcheck_always_on)) { # Enable SQLite's assert() macros. defines += [ "SQLITE_DEBUG" ] @@ -208,10 +210,11 @@ # sqlite3Fts3InitTok). cflags += [ "-Wno-unused-function" ] - if (use_fuzzing_engine && (is_debug || dcheck_always_on)) { + if (use_fuzzing_engine && use_sanitizer_coverage && + (is_debug || dcheck_always_on)) { cflags += [ "-Wno-implicit-function-declaration", - "-Wno-string-conversion" + "-Wno-string-conversion", ] } } @@ -376,9 +379,7 @@ } fuzzer_test("sqlite3_ossfuzz_fuzzer") { - include_dirs = [ - ".", - ] + include_dirs = [ "." ] sources = [ "src/test/ossfuzz.c", ]
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 0aabee49..b6df1de 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -31653,6 +31653,7 @@ <int value="2" label="ClosedRelaunch"/> <int value="3" label="ClosedFail"/> <int value="4" label="ClosedAbort"/> + <int value="5" label="ClosedFailAndIgnore"/> </enum> <enum name="MachKernReturn">
diff --git a/tools/perf/generate_legacy_perf_dashboard_json.py b/tools/perf/generate_legacy_perf_dashboard_json.py index 3b39aff4..b61b7df8 100755 --- a/tools/perf/generate_legacy_perf_dashboard_json.py +++ b/tools/perf/generate_legacy_perf_dashboard_json.py
@@ -73,11 +73,12 @@ def __init__(self): self.important = False - self.value = 0.0 + self.values = [] + self.mean = 0.0 self.stddev = 0.0 def __str__(self): - result = _FormatHumanReadable(self.value) + result = _FormatHumanReadable(self.mean) if self.stddev: result += '+/-%s' % _FormatHumanReadable(self.stddev) return result @@ -100,7 +101,7 @@ """Returns a dictionary mapping trace names to [value, stddev].""" traces_dict = {} for name, trace in self.traces.items(): - traces_dict[name] = [str(trace.value), str(trace.stddev)] + traces_dict[name] = [str(trace.mean), str(trace.stddev)] return traces_dict @@ -141,37 +142,43 @@ graph = self._graphs.get(graph_name, self.Graph()) graph.units = (match_dict['UNITS'] or '').strip() trace = graph.traces.get(trace_name, self.Trace()) - trace.value = match_dict['VALUE'] + value = match_dict['VALUE'] trace.important = match_dict['IMPORTANT'] or False # Compute the mean and standard deviation for a list or a histogram, # or the numerical value of a scalar value. - if trace.value.startswith('['): + if value.startswith('['): try: - value_list = [float(x) for x in trace.value.strip('[],').split(',')] + value_list = [float(x) for x in value.strip('[],').split(',')] except ValueError: # Report, but ignore, corrupted data lines. (Lines that are so badly # broken that they don't even match the RESULTS_REGEX won't be # detected.) - logging.warning("Bad test output: '%s'" % trace.value.strip()) + logging.warning("Bad test output: '%s'" % value.strip()) return - trace.value, trace.stddev, filedata = self._CalculateStatistics( - value_list, trace_name) + trace.values += value_list + trace.mean, trace.stddev, filedata = self._CalculateStatistics( + trace.values, trace_name) assert filedata is not None for filename in filedata: self._PrependLog(filename, filedata[filename]) - elif trace.value.startswith('{'): - stripped = trace.value.strip('{},') + elif value.startswith('{'): + stripped = value.strip('{},') try: - trace.value, trace.stddev = [float(x) for x in stripped.split(',')] + trace.mean, trace.stddev = [float(x) for x in stripped.split(',')] except ValueError: - logging.warning("Bad test output: '%s'" % trace.value.strip()) + logging.warning("Bad test output: '%s'" % value.strip()) return else: try: - trace.value = float(trace.value) + trace.values.append(float(value)) + trace.mean, trace.stddev, filedata = self._CalculateStatistics( + trace.values, trace_name) + assert filedata is not None + for filename in filedata: + self._PrependLog(filename, filedata[filename]) except ValueError: - logging.warning("Bad test output: '%s'" % trace.value.strip()) + logging.warning("Bad test output: '%s'" % value.strip()) return graph.traces[trace_name] = trace @@ -183,8 +190,14 @@ """ charts = {} for graph_name, graph in self._graphs.iteritems(): + traces = graph.BuildTracesDict() + + # Traces should contain exactly two elements: [mean, stddev]. + for _, trace in traces.iteritems(): + assert len(trace) == 2 + graph_dict = collections.OrderedDict([ - ('traces', graph.BuildTracesDict()), + ('traces', traces), ('units', str(graph.units)), ])
diff --git a/tools/perf/testdata/artificial_graph-summary.dat b/tools/perf/testdata/artificial_graph-summary.dat index 7ef13d59..fac0d13 100644 --- a/tools/perf/testdata/artificial_graph-summary.dat +++ b/tools/perf/testdata/artificial_graph-summary.dat
@@ -1 +1 @@ -{"traces": {"trace_with_one_sample": ["177.0", "0.0"], "trace_with_one_sample_comma": ["177.0", "0.0"], "trace_with_three_samples": ["140.0", "43.2049379894"], "trace_with_three_samples_comma": ["140.0", "43.2049379894"]}, "units": "you-nits"} +{"units": "you-nits", "traces": {"trace_with_three_samples": ["140.0", "43.2049379894"], "trace_with_multiple_samples": ["250.0", "111.803398875"], "trace_with_one_sample_comma": ["177.0", "0.0"], "trace_with_one_sample": ["177.0", "0.0"], "trace_with_three_samples_comma": ["140.0", "43.2049379894"]}} \ No newline at end of file
diff --git a/tools/perf/testdata/graphing_processor.log b/tools/perf/testdata/graphing_processor.log index 868c725fc..a71b2a27 100644 --- a/tools/perf/testdata/graphing_processor.log +++ b/tools/perf/testdata/graphing_processor.log
@@ -47,3 +47,10 @@ RESULT artificial_graph: trace_with_one_sample_comma= [177.0,] you-nits RESULT artificial_graph: trace_with_three_samples= [100.0,120.0,200.0] you-nits RESULT artificial_graph: trace_with_three_samples_comma= [100.0,120.0,200.0,] you-nits + +# Artificial log output to test multiple results with the same name + +RESULT artificial_graph: trace_with_multiple_samples= 100 you-nits +RESULT artificial_graph: trace_with_multiple_samples= 200 you-nits +RESULT artificial_graph: trace_with_multiple_samples= 300 you-nits +RESULT artificial_graph: trace_with_multiple_samples= 400 you-nits
diff --git a/ui/android/java/src/org/chromium/ui/base/WindowAndroid.java b/ui/android/java/src/org/chromium/ui/base/WindowAndroid.java index c15283ae..30320dc0 100644 --- a/ui/android/java/src/org/chromium/ui/base/WindowAndroid.java +++ b/ui/android/java/src/org/chromium/ui/base/WindowAndroid.java
@@ -773,7 +773,7 @@ * Return the current window token, or null. */ @CalledByNative - private IBinder getWindowToken() { + protected IBinder getWindowToken() { Activity activity = activityFromContext(mContextRef.get()); if (activity == null) return null; Window window = activity.getWindow();
diff --git a/ui/android/java/src/org/chromium/ui/resources/ResourceExtractor.java b/ui/android/java/src/org/chromium/ui/resources/ResourceExtractor.java index 5af31fc6..6d7fda3 100644 --- a/ui/android/java/src/org/chromium/ui/resources/ResourceExtractor.java +++ b/ui/android/java/src/org/chromium/ui/resources/ResourceExtractor.java
@@ -39,6 +39,7 @@ private static final String V8_SNAPSHOT_DATA_FILENAME = "snapshot_blob.bin"; private static final String FALLBACK_LOCALE = "en-US"; private static final String COMPRESSED_LOCALES_DIR = "locales"; + private static final String COMPRESSED_LOCALES_FALLBACK_DIR = "fallback-locales"; private static final int BUFFER_SIZE = 16 * 1024; private class ExtractTask extends AsyncTask<Void> { @@ -173,6 +174,10 @@ // // Where <lang> is an Android-specific ISO-639-1 language identifier. // + // * With the exception of the fallback (English) pak files which are stored + // in the base module under: + // assets/locales-fallback/<locale>.pak + // // Moreover, when the bundle uses APK splits, there is no guarantee that the split // corresponding to the current device locale is installed yet, but the one matching // uiLanguage should be there, since the value is determined by loading a resource string @@ -193,6 +198,10 @@ assetManager, COMPRESSED_LOCALES_DIR, activeLocales.get(0) + ".pak")) { // This is a regular APK, and all pak files are available. localesSrcDir = COMPRESSED_LOCALES_DIR; + } else if (assetPathHasFile(assetManager, COMPRESSED_LOCALES_FALLBACK_DIR, + activeLocales.get(0) + ".pak")) { + // This is a fallback language pak file. + localesSrcDir = COMPRESSED_LOCALES_FALLBACK_DIR; } else { // This is an app bundle, but the split containing the pak files for the current UI // locale is *not* installed yet. This should never happen in theory, and there is
diff --git a/ui/aura/local/window_port_local.cc b/ui/aura/local/window_port_local.cc index 417285a..e690a42 100644 --- a/ui/aura/local/window_port_local.cc +++ b/ui/aura/local/window_port_local.cc
@@ -192,6 +192,12 @@ UpdateLocalSurfaceId(); } +void WindowPortLocal::InvalidateLocalSurfaceId() { + if (!parent_local_surface_id_allocator_) + return; + parent_local_surface_id_allocator_->Invalidate(); +} + viz::ScopedSurfaceIdAllocator WindowPortLocal::GetSurfaceIdAllocator( base::OnceCallback<void()> allocation_task) { return viz::ScopedSurfaceIdAllocator(
diff --git a/ui/aura/local/window_port_local.h b/ui/aura/local/window_port_local.h index 5ee3101..d0744d6b 100644 --- a/ui/aura/local/window_port_local.h +++ b/ui/aura/local/window_port_local.h
@@ -51,6 +51,7 @@ void AllocateLocalSurfaceId() override; viz::ScopedSurfaceIdAllocator GetSurfaceIdAllocator( base::OnceCallback<void()> allocation_task) override; + void InvalidateLocalSurfaceId() override; void UpdateLocalSurfaceIdFromEmbeddedClient( const viz::LocalSurfaceIdAllocation& embedded_client_local_surface_id_allocation) override;
diff --git a/ui/aura/mus/window_port_mus.cc b/ui/aura/mus/window_port_mus.cc index 60a58a11..d26cdabf 100644 --- a/ui/aura/mus/window_port_mus.cc +++ b/ui/aura/mus/window_port_mus.cc
@@ -519,6 +519,10 @@ std::move(allocation_task)); } +void WindowPortMus::InvalidateLocalSurfaceId() { + parent_local_surface_id_allocator_.Invalidate(); +} + void WindowPortMus::UpdateLocalSurfaceIdFromEmbeddedClient( const viz::LocalSurfaceIdAllocation& embedded_client_local_surface_id_allocation) {
diff --git a/ui/aura/mus/window_port_mus.h b/ui/aura/mus/window_port_mus.h index 9569eb6..19a24cf 100644 --- a/ui/aura/mus/window_port_mus.h +++ b/ui/aura/mus/window_port_mus.h
@@ -297,6 +297,7 @@ viz::ScopedSurfaceIdAllocator GetSurfaceIdAllocator( base::OnceCallback<void()> allocation_task) override; const viz::LocalSurfaceIdAllocation& GetLocalSurfaceIdAllocation() override; + void InvalidateLocalSurfaceId() override; void OnEventTargetingPolicyChanged() override; bool ShouldRestackTransientChildren() override; void RegisterFrameSinkId(const viz::FrameSinkId& frame_sink_id) override;
diff --git a/ui/aura/mus/window_tree_client.cc b/ui/aura/mus/window_tree_client.cc index 286f3fb..f2894704 100644 --- a/ui/aura/mus/window_tree_client.cc +++ b/ui/aura/mus/window_tree_client.cc
@@ -222,6 +222,11 @@ return valid_wait; } +WindowMus* WindowTreeClient::GetWindowByServerId(ws::Id id) { + IdToWindowMap::const_iterator it = windows_.find(id); + return it != windows_.end() ? it->second : nullptr; +} + void WindowTreeClient::SetCanFocus(Window* window, bool can_focus) { DCHECK(tree_); DCHECK(window); @@ -374,11 +379,6 @@ } } -WindowMus* WindowTreeClient::GetWindowByServerId(ws::Id id) { - IdToWindowMap::const_iterator it = windows_.find(id); - return it != windows_.end() ? it->second : nullptr; -} - bool WindowTreeClient::IsWindowKnown(aura::Window* window) { WindowMus* window_mus = WindowMus::Get(window); // NOTE: this function explicitly checks for a null WindowMus as it may be
diff --git a/ui/aura/mus/window_tree_client.h b/ui/aura/mus/window_tree_client.h index a7b8245..7f47dcea 100644 --- a/ui/aura/mus/window_tree_client.h +++ b/ui/aura/mus/window_tree_client.h
@@ -128,6 +128,8 @@ const base::Optional<uint32_t>& id() const { return id_; } + WindowMus* GetWindowByServerId(ws::Id id); + void SetCanFocus(Window* window, bool can_focus); void SetCanAcceptDrops(WindowMus* window, bool can_accept_drops); void SetEventTargetingPolicy(WindowMus* window, @@ -242,8 +244,6 @@ void RegisterWindowMus(WindowMus* window); - WindowMus* GetWindowByServerId(ws::Id id); - bool IsWindowKnown(aura::Window* window); // Returns the oldest InFlightChange that matches |change|.
diff --git a/ui/aura/test/env_test_helper.h b/ui/aura/test/env_test_helper.h index e583cfed9..0dde0c2 100644 --- a/ui/aura/test/env_test_helper.h +++ b/ui/aura/test/env_test_helper.h
@@ -57,6 +57,7 @@ env_->mode_ = mode; if (mode == Env::Mode::MUS) env_->EnableMusOSExchangeDataProvider(); + env_->in_mus_shutdown_ = false; return old_mode; }
diff --git a/ui/aura/test/mus/change_completion_waiter.cc b/ui/aura/test/mus/change_completion_waiter.cc index 95c5b09..5741c6f3 100644 --- a/ui/aura/test/mus/change_completion_waiter.cc +++ b/ui/aura/test/mus/change_completion_waiter.cc
@@ -113,7 +113,20 @@ void WaitForAllChangesToComplete(WindowTreeClient* client) { if (Env::GetInstance()->mode() == Env::Mode::LOCAL) return; - AllChangesCompletedWaiter(client ? client : GetWindowTreeClient()).Wait(); + if (!client) + client = GetWindowTreeClient(); + + // Wait for any local changes. + AllChangesCompletedWaiter(client).Wait(); + + // Do this to flush any incoming calls from the server. + WindowTreeClientTestApi(client).FlushForTesting(); + + // And wait for any outgoing calls. + AllChangesCompletedWaiter(client).Wait(); + + // In theory we could keep doing the above until there are no more outgoing + // requests. } } // namespace test
diff --git a/ui/aura/window.cc b/ui/aura/window.cc index df706aa5..03a1cb5 100644 --- a/ui/aura/window.cc +++ b/ui/aura/window.cc
@@ -1141,6 +1141,10 @@ return port_->GetLocalSurfaceIdAllocation(); } +void Window::InvalidateLocalSurfaceId() { + port_->InvalidateLocalSurfaceId(); +} + void Window::UpdateLocalSurfaceIdFromEmbeddedClient( const base::Optional<viz::LocalSurfaceIdAllocation>& embedded_client_local_surface_id_allocation) {
diff --git a/ui/aura/window.h b/ui/aura/window.h index e8ca96b..f0cca07 100644 --- a/ui/aura/window.h +++ b/ui/aura/window.h
@@ -419,6 +419,10 @@ // Returns the current viz::LocalSurfaceIdAllocation. const viz::LocalSurfaceIdAllocation& GetLocalSurfaceIdAllocation() const; + // Marks the current viz::LocalSurfaceId as invalid. AllocateLocalSurfaceId + // must be called before submitting new CompositorFrames. + void InvalidateLocalSurfaceId(); + // Sets the current viz::LocalSurfaceId, in cases where the embedded client // has allocated one. Also sets child sequence number component of the // viz::LocalSurfaceId allocator.
diff --git a/ui/aura/window_port.h b/ui/aura/window_port.h index 00fc1840..4c4073a 100644 --- a/ui/aura/window_port.h +++ b/ui/aura/window_port.h
@@ -115,6 +115,10 @@ virtual viz::ScopedSurfaceIdAllocator GetSurfaceIdAllocator( base::OnceCallback<void()> allocation_task) = 0; + // Marks the current viz::LocalSurfaceId as invalid. AllocateLocalSurfaceId + // must be called before submitting new CompositorFrames. + virtual void InvalidateLocalSurfaceId() = 0; + virtual void UpdateLocalSurfaceIdFromEmbeddedClient( const viz::LocalSurfaceIdAllocation& embedded_client_local_surface_id_allocation) = 0;
diff --git a/ui/aura/window_port_for_shutdown.cc b/ui/aura/window_port_for_shutdown.cc index cbb6698..5ff4b04 100644 --- a/ui/aura/window_port_for_shutdown.cc +++ b/ui/aura/window_port_for_shutdown.cc
@@ -58,6 +58,7 @@ } void WindowPortForShutdown::AllocateLocalSurfaceId() {} +void WindowPortForShutdown::InvalidateLocalSurfaceId() {} void WindowPortForShutdown::UpdateLocalSurfaceIdFromEmbeddedClient( const viz::LocalSurfaceIdAllocation& embedded_client_local_surface_id_allocation) {}
diff --git a/ui/aura/window_port_for_shutdown.h b/ui/aura/window_port_for_shutdown.h index 6f9d357..4d7bd08 100644 --- a/ui/aura/window_port_for_shutdown.h +++ b/ui/aura/window_port_for_shutdown.h
@@ -43,6 +43,7 @@ void AllocateLocalSurfaceId() override; viz::ScopedSurfaceIdAllocator GetSurfaceIdAllocator( base::OnceCallback<void()> allocation_task) override; + void InvalidateLocalSurfaceId() override; void UpdateLocalSurfaceIdFromEmbeddedClient( const viz::LocalSurfaceIdAllocation& embedded_client_local_surface_id_allocation) override;
diff --git a/ui/gfx/image/image_unittest.cc b/ui/gfx/image/image_unittest.cc index a38cfd9b..c25b09ac 100644 --- a/ui/gfx/image/image_unittest.cc +++ b/ui/gfx/image/image_unittest.cc
@@ -249,15 +249,7 @@ #endif } -// TODO(crbug.com/153782): disable this test as it fails on iOS retina devices. -#if defined(OS_IOS) -#define MAYBE_MultiResolutionPNGToPlatform \ - DISABLED_MultiResolutionPNGToPlatform -#else -#define MAYBE_MultiResolutionPNGToPlatform \ - MultiResolutionPNGToPlatform -#endif -TEST_F(ImageTest, MAYBE_MultiResolutionPNGToPlatform) { +TEST_F(ImageTest, MultiResolutionPNGToPlatform) { const int kSize1x = 25; const int kSize2x = 50; @@ -307,15 +299,7 @@ // The platform types use the platform provided encoding/decoding of PNGs. Make // sure these work with the Skia Encode/Decode. -// TODO(crbug.com/153782): disable this test as it fails on iOS retina devices. -#if defined(OS_IOS) -#define MAYBE_PNGEncodeFromSkiaDecodeToPlatform \ - DISABLED_PNGEncodeFromSkiaDecodeToPlatform -#else -#define MAYBE_PNGEncodeFromSkiaDecodeToPlatform \ - PNGEncodeFromSkiaDecodeToPlatform -#endif -TEST_F(ImageTest, MAYBE_PNGEncodeFromSkiaDecodeToPlatform) { +TEST_F(ImageTest, PNGEncodeFromSkiaDecodeToPlatform) { // Force the conversion sequence skia to png to platform_type. gfx::Image from_bitmap = gfx::Image::CreateFrom1xBitmap( gt::CreateBitmap(25, 25));
diff --git a/ui/keyboard/keyboard_controller.cc b/ui/keyboard/keyboard_controller.cc index e020a79e..f157e37 100644 --- a/ui/keyboard/keyboard_controller.cc +++ b/ui/keyboard/keyboard_controller.cc
@@ -149,6 +149,47 @@ KEYBOARD_CONTROL_MAX); } +class InputMethodKeyboardController : public ui::InputMethodKeyboardController { + public: + explicit InputMethodKeyboardController( + KeyboardController* keyboard_controller) + : keyboard_controller_(keyboard_controller) {} + + ~InputMethodKeyboardController() override = default; + + // ui::InputMethodKeyboardController + bool DisplayVirtualKeyboard() override { + // Calling |ShowKeyboardInternal| may move the keyboard to another display. + if (keyboard_controller_->IsKeyboardEnableRequested() && + !keyboard_controller_->keyboard_locked()) { + keyboard_controller_->ShowKeyboard(false /* locked */); + return true; + } + return false; + } + + void DismissVirtualKeyboard() override { + keyboard_controller_->HideKeyboardByUser(); + } + + void AddObserver( + ui::InputMethodKeyboardControllerObserver* observer) override { + // TODO: Implement. + } + + void RemoveObserver( + ui::InputMethodKeyboardControllerObserver* observer) override { + // TODO: Implement. + } + + bool IsKeyboardVisible() override { + return keyboard_controller_->IsKeyboardVisible(); + } + + private: + KeyboardController* keyboard_controller_; +}; + } // namespace // Observer for both keyboard show and hide animations. It should be owned by @@ -178,7 +219,9 @@ }; KeyboardController::KeyboardController() - : ime_observer_(this), + : input_method_keyboard_controller_( + std::make_unique<InputMethodKeyboardController>(this)), + ime_observer_(this), weak_factory_report_lingering_state_(this), weak_factory_will_hide_(this) { DCHECK_EQ(g_keyboard_controller, nullptr); @@ -233,6 +276,10 @@ if (parent_container_) DeactivateKeyboard(); + aura::Window* keyboard_window = GetKeyboardWindow(); + if (keyboard_window) + keyboard_window->RemoveObserver(this); + // Return to the INITIAL state to ensure that transitions entering a state // is equal to transitions leaving the state. if (state_ != KeyboardControllerState::INITIAL) @@ -577,10 +624,6 @@ base::TimeDelta::FromMilliseconds(kHideKeyboardDelayMs)); } -void KeyboardController::DismissVirtualKeyboard() { - HideKeyboardByUser(); -} - // private void KeyboardController::HideAnimationFinished() { if (state_ == KeyboardControllerState::HIDDEN) { @@ -1041,26 +1084,6 @@ container_behavior_->SetDraggableArea(rect); } -// InputMethodKeyboardController overrides: - -bool KeyboardController::DisplayVirtualKeyboard() { - // Calling |ShowKeyboardInternal| may move the keyboard to another display. - if (keyboard::IsKeyboardEnabled() && !keyboard_locked_) { - ShowKeyboardInternal(display::Display()); - return true; - } - return false; -} -void KeyboardController::AddObserver( - ui::InputMethodKeyboardControllerObserver* observer) { - // TODO: Implement me -} - -void KeyboardController::RemoveObserver( - ui::InputMethodKeyboardControllerObserver* observer) { - // TODO: Implement me -} - bool KeyboardController::IsKeyboardVisible() { if (state_ == KeyboardControllerState::SHOWN) { DCHECK(IsEnabled()); @@ -1088,8 +1111,10 @@ ime_observer_.RemoveAll(); ime_observer_.Add(ime); - // TODO(https://crbug.com/845780): Investigate whether this does anything. - OnTextInputStateChanged(ime->GetTextInputClient()); + // Note: We used to call OnTextInputStateChanged(ime->GetTextInputClient()) + // here, but that can trigger HideKeyboardImplicitlyBySystem() from a call to + // ShowKeyboard() when using mojo APIs in Chrome (SingleProcessMash) if + // ime->GetTextInputClient() isn't focused. } void KeyboardController::EnsureCaretInWorkArea(
diff --git a/ui/keyboard/keyboard_controller.h b/ui/keyboard/keyboard_controller.h index 99b1d6f..1214f328 100644 --- a/ui/keyboard/keyboard_controller.h +++ b/ui/keyboard/keyboard_controller.h
@@ -69,11 +69,9 @@ // Provides control of the virtual keyboard, including enabling/disabling the // keyboard and controlling its visibility. -class KEYBOARD_EXPORT KeyboardController - : public ui::InputMethodObserver, - public aura::WindowObserver, - public ui::InputMethodKeyboardController, - public ContainerBehavior::Delegate { +class KEYBOARD_EXPORT KeyboardController : public ui::InputMethodObserver, + public aura::WindowObserver, + public ContainerBehavior::Delegate { public: KeyboardController(); ~KeyboardController() override; @@ -240,14 +238,11 @@ // Sets floating keyboard draggable rect. void SetDraggableArea(const gfx::Rect& rect); - // InputMethodKeyboardController overrides: - bool DisplayVirtualKeyboard() override; - void DismissVirtualKeyboard() override; - void AddObserver( - ui::InputMethodKeyboardControllerObserver* observer) override; - void RemoveObserver( - ui::InputMethodKeyboardControllerObserver* observer) override; - bool IsKeyboardVisible() override; + bool IsKeyboardVisible(); + + ui::InputMethodKeyboardController* input_method_keyboard_controller() { + return input_method_keyboard_controller_.get(); + } bool keyboard_locked() const { return keyboard_locked_; } void set_keyboard_locked(bool lock) { keyboard_locked_ = lock; } @@ -385,6 +380,8 @@ void MarkKeyboardLoadFinished(); std::unique_ptr<KeyboardUI> ui_; + std::unique_ptr<ui::InputMethodKeyboardController> + input_method_keyboard_controller_; KeyboardLayoutDelegate* layout_delegate_ = nullptr; ScopedObserver<ui::InputMethod, ui::InputMethodObserver> ime_observer_;
diff --git a/ui/message_center/views/notification_view.cc b/ui/message_center/views/notification_view.cc index 7094e2d..2c88dd4 100644 --- a/ui/message_center/views/notification_view.cc +++ b/ui/message_center/views/notification_view.cc
@@ -146,6 +146,8 @@ // NotificationView //////////////////////////////////////////////////////////// void NotificationView::CreateOrUpdateViews(const Notification& notification) { + top_view_count_ = 0; + CreateOrUpdateTitleView(notification); CreateOrUpdateMessageView(notification); CreateOrUpdateProgressBarView(notification); @@ -370,10 +372,12 @@ title_view_->SetLineLimit(kMaxTitleLines); title_view_->SetColor(kRegularTextColor); title_view_->SetBorder(MakeTextBorder(padding, 3, 0)); - top_view_->AddChildView(title_view_); + top_view_->AddChildViewAt(title_view_, top_view_count_); } else { title_view_->SetText(title); } + + top_view_count_++; } void NotificationView::CreateOrUpdateMessageView( @@ -396,12 +400,13 @@ message_view_->SetLineHeight(kMessageLineHeight); message_view_->SetColor(kRegularTextColor); message_view_->SetBorder(MakeTextBorder(padding, 4, 0)); - top_view_->AddChildView(message_view_); + top_view_->AddChildViewAt(message_view_, top_view_count_); } else { message_view_->SetText(text); } message_view_->SetVisible(notification.items().empty()); + top_view_count_++; } base::string16 NotificationView::FormatContextMessage( @@ -440,10 +445,12 @@ context_message_view_->SetLineHeight(kMessageLineHeight); context_message_view_->SetColor(kDimTextColor); context_message_view_->SetBorder(MakeTextBorder(padding, 4, 0)); - top_view_->AddChildView(context_message_view_); + top_view_->AddChildViewAt(context_message_view_, top_view_count_); } else { context_message_view_->SetText(message); } + + top_view_count_++; } void NotificationView::CreateOrUpdateProgressBarView( @@ -461,11 +468,12 @@ progress_bar_view_ = new views::ProgressBar(); progress_bar_view_->SetBorder(MakeProgressBarBorder( kProgressBarTopPadding, kProgressBarBottomPadding)); - top_view_->AddChildView(progress_bar_view_); + top_view_->AddChildViewAt(progress_bar_view_, top_view_count_); } progress_bar_view_->SetValue(notification.progress() / 100.0); progress_bar_view_->SetVisible(notification.items().empty()); + top_view_count_++; } void NotificationView::CreateOrUpdateListItemViews( @@ -485,7 +493,7 @@ NotificationItemView* item_view = new NotificationItemView(items[i]); item_view->SetBorder(MakeTextBorder(padding, i ? 0 : 4, 0)); item_views_.push_back(item_view); - top_view_->AddChildView(item_view); + top_view_->AddChildViewAt(item_view, top_view_count_++); } }
diff --git a/ui/message_center/views/notification_view.h b/ui/message_center/views/notification_view.h index b0869eba..76db06f 100644 --- a/ui/message_center/views/notification_view.h +++ b/ui/message_center/views/notification_view.h
@@ -62,6 +62,7 @@ FRIEND_TEST_ALL_PREFIXES(NotificationViewTest, TestImageSizing); FRIEND_TEST_ALL_PREFIXES(NotificationViewTest, UpdateButtonsStateTest); FRIEND_TEST_ALL_PREFIXES(NotificationViewTest, UpdateButtonCountTest); + FRIEND_TEST_ALL_PREFIXES(NotificationViewTest, UpdateViewsOrderingTest); friend class NotificationViewTest; @@ -108,6 +109,10 @@ std::unique_ptr<views::ImageView> small_image_view_; NotificationControlButtonsView* control_buttons_view_; + // Counter for view layouting, which is used during the CreateOrUpdate* + // phases to keep track of the view ordering. See crbug.com/901045 + int top_view_count_; + DISALLOW_COPY_AND_ASSIGN(NotificationView); };
diff --git a/ui/message_center/views/notification_view_md.cc b/ui/message_center/views/notification_view_md.cc index 04911581..d7fed2f 100644 --- a/ui/message_center/views/notification_view_md.cc +++ b/ui/message_center/views/notification_view_md.cc
@@ -477,6 +477,8 @@ // //////////////////////////////////////////////////////////// void NotificationViewMD::CreateOrUpdateViews(const Notification& notification) { + left_content_count_ = 0; + CreateOrUpdateContextTitleView(notification); CreateOrUpdateTitleView(notification); CreateOrUpdateMessageView(notification); @@ -801,10 +803,12 @@ title_view_->SetFontList(font_list); title_view_->SetHorizontalAlignment(gfx::ALIGN_LEFT); title_view_->SetEnabledColor(kRegularTextColorMD); - left_content_->AddChildView(title_view_); + left_content_->AddChildViewAt(title_view_, left_content_count_); } else { title_view_->SetText(title); } + + left_content_count_++; } void NotificationViewMD::CreateOrUpdateMessageView( @@ -827,12 +831,13 @@ message_view_->SetLineLimit(kMaxLinesForMessageView); message_view_->SetColor(kDimTextColorMD); - left_content_->AddChildView(message_view_); + left_content_->AddChildViewAt(message_view_, left_content_count_); } else { message_view_->SetText(text); } message_view_->SetVisible(notification.items().empty()); + left_content_count_++; } void NotificationViewMD::CreateOrUpdateCompactTitleMessageView( @@ -846,12 +851,14 @@ } if (!compact_title_message_view_) { compact_title_message_view_ = new CompactTitleMessageView(); - left_content_->AddChildView(compact_title_message_view_); + left_content_->AddChildViewAt(compact_title_message_view_, + left_content_count_); } compact_title_message_view_->set_title(notification.title()); compact_title_message_view_->set_message(notification.message()); left_content_->InvalidateLayout(); + left_content_count_++; } void NotificationViewMD::CreateOrUpdateProgressBarView( @@ -871,7 +878,7 @@ /* allow_round_corner */ false); progress_bar_view_->SetBorder( views::CreateEmptyBorder(kProgressBarTopPadding, 0, 0, 0)); - left_content_->AddChildView(progress_bar_view_); + left_content_->AddChildViewAt(progress_bar_view_, left_content_count_); } progress_bar_view_->SetValue(notification.progress() / 100.0); @@ -881,6 +888,8 @@ header_row_->SetProgress(notification.progress()); else header_row_->ClearProgress(); + + left_content_count_++; } void NotificationViewMD::CreateOrUpdateProgressStatusView( @@ -902,10 +911,11 @@ status_view_->SetHorizontalAlignment(gfx::ALIGN_LEFT); status_view_->SetEnabledColor(kDimTextColorMD); status_view_->SetBorder(views::CreateEmptyBorder(kStatusTextPadding)); - left_content_->AddChildView(status_view_); + left_content_->AddChildViewAt(status_view_, left_content_count_); } status_view_->SetText(notification.progress_status()); + left_content_count_++; } void NotificationViewMD::CreateOrUpdateListItemViews( @@ -920,7 +930,7 @@ ++i) { std::unique_ptr<views::View> item_view = CreateItemView(items[i]); item_views_.push_back(item_view.get()); - left_content_->AddChildView(item_view.release()); + left_content_->AddChildViewAt(item_view.release(), left_content_count_++); } list_items_count_ = items.size();
diff --git a/ui/message_center/views/notification_view_md.h b/ui/message_center/views/notification_view_md.h index d897066..0fa2810 100644 --- a/ui/message_center/views/notification_view_md.h +++ b/ui/message_center/views/notification_view_md.h
@@ -222,6 +222,7 @@ FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, UseImageAsIcon); FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, NotificationWithoutIcon); FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, InlineSettings); + FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, UpdateViewsOrderingTest); friend class NotificationViewMDTest; @@ -292,6 +293,10 @@ views::View* action_buttons_row_ = nullptr; NotificationInputContainerMD* inline_reply_ = nullptr; + // Counter for view layouting, which is used during the CreateOrUpdate* + // phases to keep track of the view ordering. See crbug.com/901045 + int left_content_count_; + // Views for inline settings. views::RadioButton* block_all_button_ = nullptr; views::RadioButton* dont_block_button_ = nullptr;
diff --git a/ui/message_center/views/notification_view_md_unittest.cc b/ui/message_center/views/notification_view_md_unittest.cc index 3bc20c67..f0319d9 100644 --- a/ui/message_center/views/notification_view_md_unittest.cc +++ b/ui/message_center/views/notification_view_md_unittest.cc
@@ -344,6 +344,36 @@ EXPECT_EQ(nullptr, notification_view()->icon_view_); } +TEST_F(NotificationViewMDTest, UpdateViewsOrderingTest) { + EXPECT_NE(nullptr, notification_view()->title_view_); + EXPECT_NE(nullptr, notification_view()->message_view_); + EXPECT_EQ(0, notification_view()->left_content_->GetIndexOf( + notification_view()->title_view_)); + EXPECT_EQ(1, notification_view()->left_content_->GetIndexOf( + notification_view()->message_view_)); + + std::unique_ptr<Notification> notification = CreateSimpleNotification(); + notification->set_title(base::string16()); + + notification_view()->CreateOrUpdateViews(*notification); + + EXPECT_EQ(nullptr, notification_view()->title_view_); + EXPECT_NE(nullptr, notification_view()->message_view_); + EXPECT_EQ(0, notification_view()->left_content_->GetIndexOf( + notification_view()->message_view_)); + + notification->set_title(base::UTF8ToUTF16("title")); + + notification_view()->CreateOrUpdateViews(*notification); + + EXPECT_NE(nullptr, notification_view()->title_view_); + EXPECT_NE(nullptr, notification_view()->message_view_); + EXPECT_EQ(0, notification_view()->left_content_->GetIndexOf( + notification_view()->title_view_)); + EXPECT_EQ(1, notification_view()->left_content_->GetIndexOf( + notification_view()->message_view_)); +} + TEST_F(NotificationViewMDTest, TestIconSizing) { // TODO(tetsui): Remove duplicated integer literal in CreateOrUpdateIconView. const int kNotificationIconSize = 36;
diff --git a/ui/message_center/views/notification_view_unittest.cc b/ui/message_center/views/notification_view_unittest.cc index 7b96f171..f10c742 100644 --- a/ui/message_center/views/notification_view_unittest.cc +++ b/ui/message_center/views/notification_view_unittest.cc
@@ -28,6 +28,7 @@ #include "ui/message_center/public/cpp/message_center_constants.h" #include "ui/message_center/public/cpp/notification.h" #include "ui/message_center/public/cpp/notification_types.h" +#include "ui/message_center/views/bounded_label.h" #include "ui/message_center/views/message_view_factory.h" #include "ui/message_center/views/notification_button.h" #include "ui/message_center/views/notification_control_buttons_view.h" @@ -284,6 +285,35 @@ EXPECT_TRUE(NULL != notification_view()->icon_view_); } +TEST_F(NotificationViewTest, UpdateViewsOrderingTest) { + EXPECT_NE(nullptr, notification_view()->title_view_); + EXPECT_NE(nullptr, notification_view()->message_view_); + EXPECT_EQ(0, notification_view()->top_view_->GetIndexOf( + notification_view()->title_view_)); + EXPECT_EQ(1, notification_view()->top_view_->GetIndexOf( + notification_view()->message_view_)); + + notification()->set_title(base::string16()); + + notification_view()->CreateOrUpdateViews(*notification()); + + EXPECT_EQ(nullptr, notification_view()->title_view_); + EXPECT_NE(nullptr, notification_view()->message_view_); + EXPECT_EQ(0, notification_view()->top_view_->GetIndexOf( + notification_view()->message_view_)); + + notification()->set_title(base::UTF8ToUTF16("title")); + + notification_view()->CreateOrUpdateViews(*notification()); + + EXPECT_NE(nullptr, notification_view()->title_view_); + EXPECT_NE(nullptr, notification_view()->message_view_); + EXPECT_EQ(0, notification_view()->top_view_->GetIndexOf( + notification_view()->title_view_)); + EXPECT_EQ(1, notification_view()->top_view_->GetIndexOf( + notification_view()->message_view_)); +} + TEST_F(NotificationViewTest, CreateOrUpdateTestSettingsButton) { data()->settings_button_handler = SettingsButtonHandler::INLINE; Notification notification(
diff --git a/ui/ozone/platform/scenic/scenic_window.cc b/ui/ozone/platform/scenic/scenic_window.cc index 840f441..e0c38fe 100644 --- a/ui/ozone/platform/scenic/scenic_window.cc +++ b/ui/ozone/platform/scenic/scenic_window.cc
@@ -191,14 +191,16 @@ screen->OnWindowBoundsChanged(window_id_, size_rect); // Set node shape to rectangle that matches size of the view. - scenic::Rectangle rect(&scenic_session_, size_dips_.width(), - size_dips_.height()); + scenic::Rectangle rect(&scenic_session_, 1.f, 1.f); shape_node_.SetShape(rect); // Translate the node by half of the view dimensions to put it in the center // of the view. - shape_node_.SetTranslation(size_dips_.width() / 2.0, - size_dips_.height() / 2.0, 0.f); + node_.SetTranslation(size_dips_.width() / 2.0, size_dips_.height() / 2.0, + 0.f); + + // Scale the node so that surface rect can always be 1x1. + node_.SetScale(size_dips_.width(), size_dips_.height(), 1.f); // This is necessary when using vulkan because ImagePipes are presented // separately and we need to make sure our sizes change is committed.
diff --git a/ui/views/controls/native/native_view_host.cc b/ui/views/controls/native/native_view_host.cc index bef81e99..270f22b0 100644 --- a/ui/views/controls/native/native_view_host.cc +++ b/ui/views/controls/native/native_view_host.cc
@@ -206,6 +206,11 @@ return native_wrapper_->GetCursor(event.x(), event.y()); } +void NativeViewHost::SetVisible(bool visible) { + native_wrapper_->SetVisible(visible); + View::SetVisible(visible); +} + //////////////////////////////////////////////////////////////////////////////// // NativeViewHost, private:
diff --git a/ui/views/controls/native/native_view_host.h b/ui/views/controls/native/native_view_host.h index ec0b8e9..5c47f29 100644 --- a/ui/views/controls/native/native_view_host.h +++ b/ui/views/controls/native/native_view_host.h
@@ -98,6 +98,7 @@ void OnFocus() override; gfx::NativeViewAccessible GetNativeViewAccessible() override; gfx::NativeCursor GetCursor(const ui::MouseEvent& event) override; + void SetVisible(bool visible) override; protected: bool GetNeedsNotificationWhenVisibleBoundsChange() const override;
diff --git a/ui/views/controls/native/native_view_host_aura.cc b/ui/views/controls/native/native_view_host_aura.cc index 7efa51a3..dabae67 100644 --- a/ui/views/controls/native/native_view_host_aura.cc +++ b/ui/views/controls/native/native_view_host_aura.cc
@@ -233,6 +233,13 @@ return gfx::kNullCursor; } +void NativeViewHostAura::SetVisible(bool visible) { + if (!visible) + host_->native_view()->Hide(); + else + host_->native_view()->Show(); +} + void NativeViewHostAura::OnWindowBoundsChanged( aura::Window* window, const gfx::Rect& old_bounds,
diff --git a/ui/views/controls/native/native_view_host_aura.h b/ui/views/controls/native/native_view_host_aura.h index 0adf8fb3..1e247145 100644 --- a/ui/views/controls/native/native_view_host_aura.h +++ b/ui/views/controls/native/native_view_host_aura.h
@@ -44,6 +44,7 @@ gfx::NativeView GetNativeViewContainer() const override; gfx::NativeViewAccessible GetNativeViewAccessible() override; gfx::NativeCursor GetCursor(int x, int y) override; + void SetVisible(bool visible) override; private: friend class NativeViewHostAuraTest;
diff --git a/ui/views/controls/native/native_view_host_mac.h b/ui/views/controls/native/native_view_host_mac.h index f46e575e..08a0ce3 100644 --- a/ui/views/controls/native/native_view_host_mac.h +++ b/ui/views/controls/native/native_view_host_mac.h
@@ -51,6 +51,7 @@ gfx::NativeView GetNativeViewContainer() const override; gfx::NativeViewAccessible GetNativeViewAccessible() override; gfx::NativeCursor GetCursor(int x, int y) override; + void SetVisible(bool visible) override; private: // Return the BridgedNativeWidgetHostImpl for this hosted view.
diff --git a/ui/views/controls/native/native_view_host_mac.mm b/ui/views/controls/native/native_view_host_mac.mm index 07d7165..7ce36315 100644 --- a/ui/views/controls/native/native_view_host_mac.mm +++ b/ui/views/controls/native/native_view_host_mac.mm
@@ -261,6 +261,10 @@ return gfx::kNullCursor; } +void NativeViewHostMac::SetVisible(bool visible) { + [native_view_ setHidden:!visible]; +} + // static NativeViewHostWrapper* NativeViewHostWrapper::CreateWrapper( NativeViewHost* host) {
diff --git a/ui/views/controls/native/native_view_host_wrapper.h b/ui/views/controls/native/native_view_host_wrapper.h index 07cf9f1..acd9b2f 100644 --- a/ui/views/controls/native/native_view_host_wrapper.h +++ b/ui/views/controls/native/native_view_host_wrapper.h
@@ -90,6 +90,11 @@ // in the native view. virtual gfx::NativeCursor GetCursor(int x, int y) = 0; + // Sets the visibility of the gfx::NativeView. This differs from + // {Show,Hide}Widget because it doesn't affect the placement, size, + // or clipping of the view. + virtual void SetVisible(bool visible) = 0; + // Creates a platform-specific instance of an object implementing this // interface. static NativeViewHostWrapper* CreateWrapper(NativeViewHost* host);
diff --git a/ui/views/controls/webview/webview.cc b/ui/views/controls/webview/webview.cc index 2a4cc7e..15e497f 100644 --- a/ui/views/controls/webview/webview.cc +++ b/ui/views/controls/webview/webview.cc
@@ -129,6 +129,10 @@ if (crashed_overlay_view_) { RemoveChildView(crashed_overlay_view_); + // Show the hosted web contents view iff the crashed + // overlay is NOT showing, to ensure hit testing is + // correct on Mac. See https://crbug.com/896508 + holder_->SetVisible(true); if (!crashed_overlay_view_->owned_by_client()) delete crashed_overlay_view_; } @@ -136,6 +140,7 @@ crashed_overlay_view_ = crashed_overlay_view; if (crashed_overlay_view_) { AddChildView(crashed_overlay_view_); + holder_->SetVisible(false); crashed_overlay_view_->SetBoundsRect(gfx::Rect(size())); }
diff --git a/webrunner/browser/frame_impl_browsertest.cc b/webrunner/browser/frame_impl_browsertest.cc index f3e2759..63df269 100644 --- a/webrunner/browser/frame_impl_browsertest.cc +++ b/webrunner/browser/frame_impl_browsertest.cc
@@ -892,7 +892,8 @@ // MessagePortImpl to self-destruct and tear down its FIDL channel. { base::RunLoop run_loop; - message_port.set_error_handler([&run_loop]() { run_loop.Quit(); }); + message_port.set_error_handler( + [&run_loop](zx_status_t status) { run_loop.Quit(); }); controller->LoadUrl(url::kAboutBlankURL, nullptr); CheckRunWithTimeout(&run_loop); }