diff --git a/DEPS b/DEPS index 7e7aec5..e4968401 100644 --- a/DEPS +++ b/DEPS
@@ -121,11 +121,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': '6d7f9d6f289944332986c2534d5a5ff1028897fb', + 'skia_revision': '77e1ccf3cd19ed079a3c590a67f28f0fa1d73511', # 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': '414f4dc3f8876dbe57ffaff5e861bbc25589b5bb', + 'v8_revision': 'fd65a392b935d2ab32423ad6f803e8568e014a8a', # 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. @@ -145,7 +145,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': '5a6d70c82d6a2b4617265b2e3d5cac339cd04246', + 'pdfium_revision': '587891b979df5a7e58897aa702db48806bd90900', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other. @@ -169,7 +169,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling NaCl # and whatever else without interference from each other. - 'nacl_revision': 'df9028d670fe6f66e56b74d27d65e1fa7a440569', + 'nacl_revision': '1e2123822ca7424ac63ecdf241af0da87d3ec740', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling freetype # and whatever else without interference from each other. @@ -229,7 +229,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': '5ec2d1a8cdafdcabbc081da58f847e3c0c6f77f2', + 'spv_tools_revision': '9d04f82befe1cbbe21b39e07ab9255d06cb37872', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -245,7 +245,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': '292c0c31f25cf7c5c9adbdf04dd6be2adfa5e0b0', + 'dawn_revision': '2745f37875fb0a78e984d9f379df3c493d62613c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -679,7 +679,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'b2c827c6440e0c07397673af44403c63423d32ed', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'bf081d0b4ada31320123d3ab81cd43acce737d0e', 'condition': 'checkout_linux', }, @@ -1199,7 +1199,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'a2b35635aaef3e9301d69f77f9a0a3fd99291b08', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '503da9435084305869cda5bfe861bcb103c93d71', + Var('webrtc_git') + '/src.git' + '@' + 'aabac232b1a35d73a0f4cbfa7d746a0532bca159', 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d', @@ -1230,7 +1230,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@61b9ca0657a3527fffb66c45d3d15a506593a095', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@534fc360f6c5d274ac513ca1acfe81d8e9c39b5e', 'condition': 'checkout_src_internal', },
diff --git a/apps/launcher.cc b/apps/launcher.cc index 4d19f8f..0955e75 100644 --- a/apps/launcher.cc +++ b/apps/launcher.cc
@@ -35,6 +35,7 @@ #include "extensions/browser/extension_registry.h" #include "extensions/browser/granted_file_entry.h" #include "extensions/browser/lazy_background_task_queue.h" +#include "extensions/browser/lazy_context_id.h" #include "extensions/browser/process_manager.h" #include "extensions/common/api/app_runtime.h" #include "extensions/common/extension.h" @@ -293,7 +294,7 @@ extensions::LazyBackgroundTaskQueue::Get(context_); if (queue->ShouldEnqueueTask(context_, app)) { queue->AddPendingTask( - context_, extension_id, + extensions::LazyContextId(context_, extension_id), base::Bind(&PlatformAppPathLauncher::GrantAccessToFilesAndLaunch, this)); return;
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index fd982b8..e235cee 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -1494,7 +1494,7 @@ deps = [ ":ash", - ":test_support_without_content", + ":test_support", "//ash/app_list/presenter", "//ash/public/cpp", "//base", @@ -1526,7 +1526,7 @@ deps = [ ":ash_shell_lib", - ":test_support_without_content", + ":test_support", "//ash/components/quick_launch:lib", "//ash/components/quick_launch/public/mojom", "//ash/components/shortcut_viewer:lib", @@ -1886,7 +1886,7 @@ ":ash", ":ash_service_resources", ":ash_unittests_catalog_source", - ":test_support_without_content", + ":test_support", "//ash/app_list:test_support", "//ash/app_list/presenter", "//ash/app_menu", @@ -2006,7 +2006,7 @@ ] deps = [ - ":test_support_without_content", + ":test_support", "//ash/public/cpp", "//base/test:test_support", "//cc/base", @@ -2041,50 +2041,9 @@ ] } -static_library("test_support_without_content") { +static_library("test_support") { testonly = true sources = [ - "test/ash_test_environment_default.cc", - ] - - public_deps = [ - ":test_support_common", - ] - - deps = [ - "//base", - "//base/test:test_support", - "//skia", - ] -} - -static_library("test_support_with_content") { - testonly = true - sources = [ - "test/ash_test_environment_content.cc", - "test/ash_test_environment_content.h", - ] - configs += [ "//build/config:precompiled_headers" ] - - public_deps = [ - ":test_support_common", - "//content/public/browser", - "//content/test:test_support", - "//services/network:test_support", - "//skia", - "//ui/views/controls/webview", - ] -} - -# Internal target consumed by |test_support_with_content| and -# |test_support_without_content|. This target contains all the test support -# files, with the exception of an implementation of AshTestEnvironment. -# Consumers of ash should use one of |test_support_with_content| or -# |test_support_without_content|. -static_library("test_support_common") { - testonly = true - visibility = [ ":*" ] - sources = [ "accessibility/test_accessibility_controller_client.cc", "accessibility/test_accessibility_controller_client.h", "app_list/test/app_list_test_helper.cc", @@ -2156,7 +2115,6 @@ "system/unified/unified_system_tray_test_api.h", "test/ash_test_base.cc", "test/ash_test_base.h", - "test/ash_test_environment.h", "test/ash_test_helper.cc", "test/ash_test_helper.h", "test/ash_test_suite.cc", @@ -2267,7 +2225,7 @@ testonly = true configs += [ "//build/config:precompiled_headers" ] public_deps = [ - ":test_support_without_content", + ":test_support", "//ash", ] sources = [ @@ -2275,7 +2233,7 @@ "test/ash_interactive_ui_test_base.h", ] deps = [ - ":test_support_with_content", + ":test_support", "//base", "//mojo/core/embedder", "//skia",
diff --git a/ash/accelerators/ash_focus_manager_factory.cc b/ash/accelerators/ash_focus_manager_factory.cc index ff179ec..3c4af4d 100644 --- a/ash/accelerators/ash_focus_manager_factory.cc +++ b/ash/accelerators/ash_focus_manager_factory.cc
@@ -101,12 +101,9 @@ AshFocusManagerFactory::~AshFocusManagerFactory() = default; std::unique_ptr<views::FocusManager> AshFocusManagerFactory::CreateFocusManager( - views::Widget* widget, - bool desktop_widget) { + views::Widget* widget) { return std::make_unique<views::FocusManager>( - widget, desktop_widget - ? nullptr - : std::make_unique<PostTargetAcceleratorHandler>()); + widget, std::make_unique<PostTargetAcceleratorHandler>()); } } // namespace ash
diff --git a/ash/accelerators/ash_focus_manager_factory.h b/ash/accelerators/ash_focus_manager_factory.h index f3d34727..898bf70d 100644 --- a/ash/accelerators/ash_focus_manager_factory.h +++ b/ash/accelerators/ash_focus_manager_factory.h
@@ -20,8 +20,7 @@ protected: // views::FocusManagerFactory overrides: std::unique_ptr<views::FocusManager> CreateFocusManager( - views::Widget* widget, - bool desktop_widget) override; + views::Widget* widget) override; private: DISALLOW_COPY_AND_ASSIGN(AshFocusManagerFactory);
diff --git a/ash/components/shortcut_viewer/BUILD.gn b/ash/components/shortcut_viewer/BUILD.gn index 51dd0d7..96eee1e 100644 --- a/ash/components/shortcut_viewer/BUILD.gn +++ b/ash/components/shortcut_viewer/BUILD.gn
@@ -63,7 +63,7 @@ ] deps = [ ":lib", - "//ash:test_support_without_content", + "//ash:test_support", "//base/test:test_support", "//services/ws/public/cpp/input_devices:test_support", "//testing/gtest",
diff --git a/ash/shelf/login_shelf_view.cc b/ash/shelf/login_shelf_view.cc index f9c9ccbe..eac4157 100644 --- a/ash/shelf/login_shelf_view.cc +++ b/ash/shelf/login_shelf_view.cc
@@ -140,7 +140,7 @@ login_constants::kButtonDisabledAlpha))); SetFocusBehavior(FocusBehavior::ALWAYS); SetInstallFocusRingOnFocus(true); - focus_ring()->set_is_opaque(); + focus_ring()->SetColor(kFocusBorderColor); SetFocusPainter(nullptr); SetInkDropMode(InkDropMode::ON); set_has_ink_drop_action_on_click(true); @@ -228,7 +228,7 @@ : MenuButton(text, this), ui::SimpleMenuModel(this) { SetFocusBehavior(FocusBehavior::ALWAYS); SetInstallFocusRingOnFocus(true); - focus_ring()->set_is_opaque(); + focus_ring()->SetColor(kFocusBorderColor); SetFocusPainter(nullptr); SetInkDropMode(InkDropMode::ON); set_has_ink_drop_action_on_click(true);
diff --git a/ash/system/tray/tray_background_view.cc b/ash/system/tray/tray_background_view.cc index fc7ee01..2cce998b 100644 --- a/ash/system/tray/tray_background_view.cc +++ b/ash/system/tray/tray_background_view.cc
@@ -41,6 +41,7 @@ #include "ui/views/background.h" #include "ui/views/layout/fill_layout.h" #include "ui/views/painter.h" +#include "ui/views/view_properties.h" #include "ui/wm/core/window_animations.h" namespace { @@ -166,6 +167,9 @@ SetLayoutManager(std::make_unique<views::FillLayout>()); SetBackground(std::unique_ptr<views::Background>(background_)); + SetInstallFocusRingOnFocus(true); + focus_ring()->SetColor(kFocusBorderColor); + SetFocusPainter(nullptr); AddChildView(tray_container_); @@ -260,19 +264,6 @@ } } -void TrayBackgroundView::Layout() { - ActionableView::Layout(); - - // The tray itself expands to the right and bottom edge of the screen to make - // sure clicking on the edges brings up the popup. However, the focus border - // should be only around the container. - gfx::Rect paint_bounds(GetBackgroundBounds()); - paint_bounds.Inset(gfx::Insets(-kFocusBorderThickness)); - SetFocusPainter(views::Painter::CreateSolidFocusPainter( - kFocusBorderColor, kFocusBorderThickness, - GetLocalBounds().InsetsFrom(paint_bounds))); -} - const char* TrayBackgroundView::GetClassName() const { return kViewClassName; } @@ -461,17 +452,25 @@ } gfx::Rect TrayBackgroundView::GetBackgroundBounds() const { - gfx::Insets insets = GetBackgroundInsets(); gfx::Rect bounds = GetLocalBounds(); - bounds.Inset(insets); + bounds.Inset(GetBackgroundInsets()); return bounds; } +void TrayBackgroundView::OnBoundsChanged(const gfx::Rect& previous_bounds) { + const int border_radius = ShelfConstants::control_border_radius(); + auto path = std::make_unique<SkPath>(); + path->addRoundRect(gfx::RectToSkRect(GetBackgroundBounds()), border_radius, + border_radius); + SetProperty(views::kHighlightPathKey, path.release()); + ActionableView::OnBoundsChanged(previous_bounds); +} + std::unique_ptr<views::InkDropMask> TrayBackgroundView::CreateInkDropMask() const { - const int border_radius = ShelfConstants::control_border_radius(); - return std::make_unique<views::RoundRectInkDropMask>( - size(), GetBackgroundInsets(), border_radius); + // Bypass ActionableView to use the default ink-drop mask created from the + // highlight path. + return Button::CreateInkDropMask(); } bool TrayBackgroundView::ShouldEnterPushedState(const ui::Event& event) {
diff --git a/ash/system/tray/tray_background_view.h b/ash/system/tray/tray_background_view.h index c33bcd7c..b2cbd5a 100644 --- a/ash/system/tray/tray_background_view.h +++ b/ash/system/tray/tray_background_view.h
@@ -48,7 +48,6 @@ const char* GetClassName() const override; void AboutToRequestFocusFromTabTraversal(bool reverse) override; void GetAccessibleNodeData(ui::AXNodeData* node_data) override; - void Layout() override; void ChildPreferredSizeChanged(views::View* child) override; // ActionableView: @@ -130,6 +129,7 @@ protected: // ActionableView: + void OnBoundsChanged(const gfx::Rect& previous_bounds) override; std::unique_ptr<views::InkDropMask> CreateInkDropMask() const override; bool ShouldEnterPushedState(const ui::Event& event) override; bool PerformAction(const ui::Event& event) override;
diff --git a/ash/test/DEPS b/ash/test/DEPS index 6c2cd01..7408db2 100644 --- a/ash/test/DEPS +++ b/ash/test/DEPS
@@ -7,14 +7,6 @@ ] specific_include_rules = { - # ash_test_environment_content is only compiled with content. - "ash_test_environment_content\.*": [ - "+content/public/browser/browser_thread.h", - "+content/public/browser/network_service_instance.h", - "+content/public/test/web_contents_tester.h", - "+content/public/test/test_browser_thread_bundle.h", - "+services/network/test/test_network_connection_tracker.h", - ], "ash_test_helper\.cc": [ "+ash/host", "+chromeos/cryptohome",
diff --git a/ash/test/ash_test_base.cc b/ash/test/ash_test_base.cc index daa7b1f0..2af9508 100644 --- a/ash/test/ash_test_base.cc +++ b/ash/test/ash_test_base.cc
@@ -24,7 +24,6 @@ #include "ash/shell.h" #include "ash/shell/toplevel_window.h" #include "ash/system/status_area_widget.h" -#include "ash/test/ash_test_environment.h" #include "ash/test/ash_test_helper.h" #include "ash/test_screenshot_delegate.h" #include "ash/test_shell_delegate.h" @@ -35,6 +34,7 @@ #include "ash/ws/window_service_owner.h" #include "base/memory/ptr_util.h" #include "base/run_loop.h" +#include "base/test/scoped_task_environment.h" #include "components/account_id/account_id.h" #include "components/user_manager/user_names.h" #include "mojo/public/cpp/bindings/map.h" @@ -127,12 +127,12 @@ ///////////////////////////////////////////////////////////////////////////// AshTestBase::AshTestBase() - : setup_called_(false), teardown_called_(false), start_session_(true) { - ash_test_environment_ = AshTestEnvironment::Create(); - + : scoped_task_environment_( + std::make_unique<base::test::ScopedTaskEnvironment>( + base::test::ScopedTaskEnvironment::MainThreadType::UI)) { // Must initialize |ash_test_helper_| here because some tests rely on // AshTestBase methods before they call AshTestBase::SetUp(). - ash_test_helper_.reset(new AshTestHelper(ash_test_environment_.get())); + ash_test_helper_ = std::make_unique<AshTestHelper>(); } AshTestBase::~AshTestBase() { @@ -193,6 +193,10 @@ return Shell::GetPrimaryRootWindowController()->shelf(); } +void AshTestBase::DestroyScopedTaskEnvironment() { + scoped_task_environment_.reset(); +} + // static UnifiedSystemTray* AshTestBase::GetPrimaryUnifiedSystemTray() { return GetPrimaryShelf()->GetStatusAreaWidget()->unified_system_tray();
diff --git a/ash/test/ash_test_base.h b/ash/test/ash_test_base.h index ebb04f3..3315bb0 100644 --- a/ash/test/ash_test_base.h +++ b/ash/test/ash_test_base.h
@@ -26,6 +26,12 @@ class WindowDelegate; } // namespace aura +namespace base { +namespace test { +class ScopedTaskEnvironment; +} +} // namespace base + namespace display { class Display; class DisplayManager; @@ -59,7 +65,6 @@ namespace ash { class AppListTestHelper; -class AshTestEnvironment; class AshTestHelper; class Shelf; class TestScreenshotDelegate; @@ -81,6 +86,10 @@ // Returns the unified system tray on the primary display. static UnifiedSystemTray* GetPrimaryUnifiedSystemTray(); + // AshTestBase creates a ScopedTaskEnvironment. This may not be appropriate in + // some environments. Use this to destroy it. + void DestroyScopedTaskEnvironment(); + // Call this only if this code is being run outside of ash, for example, in // browser tests that use AshTestBase. This disables CHECKs that are // applicable only when used inside ash. @@ -244,14 +253,14 @@ private: void CreateWindowTreeIfNecessary(); - bool setup_called_; - bool teardown_called_; + bool setup_called_ = false; + bool teardown_called_ = false; // |SetUp()| doesn't activate session if this is set to false. - bool start_session_; + bool start_session_ = true; // |SetUp()| doesn't inject local-state PrefService into Shell if this is // set to false. bool provide_local_state_ = true; - std::unique_ptr<AshTestEnvironment> ash_test_environment_; + std::unique_ptr<base::test::ScopedTaskEnvironment> scoped_task_environment_; std::unique_ptr<AshTestHelper> ash_test_helper_; std::unique_ptr<ui::test::EventGenerator> event_generator_;
diff --git a/ash/test/ash_test_environment.h b/ash/test/ash_test_environment.h deleted file mode 100644 index 1a503df..0000000 --- a/ash/test/ash_test_environment.h +++ /dev/null
@@ -1,42 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_TEST_ASH_TEST_ENVIRONMENT_H_ -#define ASH_TEST_ASH_TEST_ENVIRONMENT_H_ - -#include <memory> - -namespace ash { - -class AshTestViewsDelegate; - -// AshTestEnvironment creates objects specific to an environment. Two -// environments are provided, one for content (AshTestEnvironmentContent) -// and one without content (AshTestEnvironmentDefault). -// -// AshTestBase creates an AshTestEnvironment by way of -// AshTestEnvironment::Create(). The implementation of Create() depends upon -// the ash target that was linked against: //ash:test_support_with_content -// includes AshTestEnvironmentContent and -// //ash:test_support_without_content includes AshTestEnvironmentDefault. -class AshTestEnvironment { - public: - virtual ~AshTestEnvironment() {} - - // Creates the object appropriate to the current environment. - static std::unique_ptr<AshTestEnvironment> Create(); - - // Called from AshTestHelper::SetUp()/TearDown(). - virtual void SetUp() {} - virtual void TearDown() {} - - virtual std::unique_ptr<AshTestViewsDelegate> CreateViewsDelegate() = 0; - - protected: - AshTestEnvironment() {} -}; - -} // namespace ash - -#endif // ASH_TEST_ASH_TEST_ENVIRONMENT_H_
diff --git a/ash/test/ash_test_environment_content.cc b/ash/test/ash_test_environment_content.cc deleted file mode 100644 index d78ea11..0000000 --- a/ash/test/ash_test_environment_content.cc +++ /dev/null
@@ -1,58 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/test/ash_test_environment_content.h" - -#include <memory> - -#include "ash/test/ash_test_views_delegate.h" -#include "content/public/browser/network_service_instance.h" -#include "content/public/test/test_browser_thread_bundle.h" -#include "content/public/test/web_contents_tester.h" -#include "services/network/test/test_network_connection_tracker.h" - -namespace ash { -namespace { - -std::unique_ptr<content::WebContents> CreateWebContents( - content::BrowserContext* browser_context) { - return content::WebContentsTester::CreateTestWebContents(browser_context, - nullptr); -} - -} // namespace - -// static -std::unique_ptr<AshTestEnvironment> AshTestEnvironment::Create() { - return std::make_unique<AshTestEnvironmentContent>(); -} - -AshTestEnvironmentContent::AshTestEnvironmentContent() - : network_connection_tracker_( - network::TestNetworkConnectionTracker::CreateInstance()), - thread_bundle_(std::make_unique<content::TestBrowserThreadBundle>()) { - content::SetNetworkConnectionTrackerForTesting( - network::TestNetworkConnectionTracker::GetInstance()); -} - -AshTestEnvironmentContent::~AshTestEnvironmentContent() { - content::SetNetworkConnectionTrackerForTesting(nullptr); -} - -void AshTestEnvironmentContent::SetUp() { - scoped_web_contents_creator_ = - std::make_unique<views::WebView::ScopedWebContentsCreatorForTesting>( - base::BindRepeating(&CreateWebContents)); -} - -void AshTestEnvironmentContent::TearDown() { - scoped_web_contents_creator_.reset(); -} - -std::unique_ptr<AshTestViewsDelegate> -AshTestEnvironmentContent::CreateViewsDelegate() { - return std::make_unique<AshTestViewsDelegate>(); -} - -} // namespace ash
diff --git a/ash/test/ash_test_environment_content.h b/ash/test/ash_test_environment_content.h deleted file mode 100644 index d620d35..0000000 --- a/ash/test/ash_test_environment_content.h +++ /dev/null
@@ -1,45 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_TEST_ASH_TEST_ENVIRONMENT_CONTENT_H_ -#define ASH_TEST_ASH_TEST_ENVIRONMENT_CONTENT_H_ - -#include "ash/test/ash_test_environment.h" -#include "base/macros.h" -#include "ui/views/controls/webview/webview.h" - -namespace content { -class TestBrowserThreadBundle; -} - -namespace network { -class TestNetworkConnectionTracker; -} - -namespace ash { - -// AshTestEnvironment implementation for tests that use content. -class AshTestEnvironmentContent : public AshTestEnvironment { - public: - AshTestEnvironmentContent(); - ~AshTestEnvironmentContent() override; - - // AshTestEnvironment: - void SetUp() override; - void TearDown() override; - std::unique_ptr<AshTestViewsDelegate> CreateViewsDelegate() override; - - private: - std::unique_ptr<network::TestNetworkConnectionTracker> - network_connection_tracker_; - std::unique_ptr<content::TestBrowserThreadBundle> thread_bundle_; - std::unique_ptr<views::WebView::ScopedWebContentsCreatorForTesting> - scoped_web_contents_creator_; - - DISALLOW_COPY_AND_ASSIGN(AshTestEnvironmentContent); -}; - -} // namespace ash - -#endif // ASH_TEST_ASH_TEST_ENVIRONMENT_CONTENT_H_
diff --git a/ash/test/ash_test_environment_default.cc b/ash/test/ash_test_environment_default.cc deleted file mode 100644 index b53795a..0000000 --- a/ash/test/ash_test_environment_default.cc +++ /dev/null
@@ -1,44 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/test/ash_test_environment.h" - -#include <memory> - -#include "ash/test/ash_test_views_delegate.h" -#include "base/run_loop.h" -#include "base/test/scoped_task_environment.h" - -namespace ash { -namespace { - -class AshTestEnvironmentDefault : public AshTestEnvironment { - public: - AshTestEnvironmentDefault() - : scoped_task_environment_( - base::test::ScopedTaskEnvironment::MainThreadType::UI) {} - - ~AshTestEnvironmentDefault() override { - base::RunLoop().RunUntilIdle(); - } - - // AshTestEnvironment: - std::unique_ptr<AshTestViewsDelegate> CreateViewsDelegate() override { - return std::make_unique<AshTestViewsDelegate>(); - } - - private: - base::test::ScopedTaskEnvironment scoped_task_environment_; - - DISALLOW_COPY_AND_ASSIGN(AshTestEnvironmentDefault); -}; - -} // namespace - -// static -std::unique_ptr<AshTestEnvironment> AshTestEnvironment::Create() { - return std::make_unique<AshTestEnvironmentDefault>(); -} - -} // namespace ash
diff --git a/ash/test/ash_test_helper.cc b/ash/test/ash_test_helper.cc index e36b1a6..991caf7 100644 --- a/ash/test/ash_test_helper.cc +++ b/ash/test/ash_test_helper.cc
@@ -20,7 +20,6 @@ #include "ash/shell.h" #include "ash/shell_init_params.h" #include "ash/system/screen_layout_observer.h" -#include "ash/test/ash_test_environment.h" #include "ash/test/ash_test_views_delegate.h" #include "ash/test_shell_delegate.h" #include "ash/ws/window_service_owner.h" @@ -108,9 +107,8 @@ DISALLOW_COPY_AND_ASSIGN(TestGpuInterfaceProvider); }; -AshTestHelper::AshTestHelper(AshTestEnvironment* ash_test_environment) - : ash_test_environment_(ash_test_environment), - command_line_(std::make_unique<base::test::ScopedCommandLine>()) { +AshTestHelper::AshTestHelper() + : command_line_(std::make_unique<base::test::ScopedCommandLine>()) { ui::test::EnableTestConfigForPlatformWindows(); } @@ -145,7 +143,9 @@ display::ResetDisplayIdForTest(); wm_state_ = std::make_unique<::wm::WMState>(); - test_views_delegate_ = ash_test_environment_->CreateViewsDelegate(); + // Only create a ViewsDelegate if the test didn't create one already. + if (!views::ViewsDelegate::GetInstance()) + test_views_delegate_ = std::make_unique<AshTestViewsDelegate>(); // Disable animations during tests. zero_duration_mode_.reset(new ui::ScopedAnimationDurationScaleMode( @@ -178,7 +178,6 @@ chromeos::CrasAudioHandler::InitializeForTesting(); chromeos::SystemSaltGetter::Initialize(); - ash_test_environment_->SetUp(); // Reset the global state for the cursor manager. This includes the // last cursor visibility state, etc. ::wm::CursorManager::ResetCursorVisibilityStateForTest(); @@ -254,7 +253,6 @@ // Suspend the tear down until all resources are returned via // CompositorFrameSinkClient::ReclaimResources() base::RunLoop().RunUntilIdle(); - ash_test_environment_->TearDown(); chromeos::SystemSaltGetter::Shutdown(); chromeos::CrasAudioHandler::Shutdown();
diff --git a/ash/test/ash_test_helper.h b/ash/test/ash_test_helper.h index 58b1f1e..f306f6d6 100644 --- a/ash/test/ash_test_helper.h +++ b/ash/test/ash_test_helper.h
@@ -53,7 +53,6 @@ namespace ash { class AppListTestHelper; -class AshTestEnvironment; class AshTestViewsDelegate; class TestKeyboardControllerObserver; class TestShellDelegate; @@ -62,7 +61,7 @@ // root window and an ash::Shell instance with a test delegate. class AshTestHelper { public: - explicit AshTestHelper(AshTestEnvironment* ash_test_environment); + AshTestHelper(); ~AshTestHelper(); // Creates the ash::Shell and performs associated initialization. Set @@ -95,8 +94,6 @@ return test_views_delegate_.get(); } - AshTestEnvironment* ash_test_environment() { return ash_test_environment_; } - display::Display GetSecondaryDisplay(); TestSessionControllerClient* test_session_controller_client() { @@ -135,7 +132,6 @@ std::unique_ptr<chromeos::system::ScopedFakeStatisticsProvider> statistics_provider_; - AshTestEnvironment* ash_test_environment_; // Not owned. TestShellDelegate* test_shell_delegate_ = nullptr; // Owned by ash::Shell. std::unique_ptr<ui::ScopedAnimationDurationScaleMode> zero_duration_mode_;
diff --git a/ash/test/ash_test_helper_unittest.cc b/ash/test/ash_test_helper_unittest.cc index 056a4766..113bb9f4 100644 --- a/ash/test/ash_test_helper_unittest.cc +++ b/ash/test/ash_test_helper_unittest.cc
@@ -4,7 +4,7 @@ #include "ash/test/ash_test_helper.h" -#include "ash/test/ash_test_environment.h" +#include "base/test/scoped_task_environment.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/aura/window_event_dispatcher.h" #include "ui/views/widget/widget.h" @@ -20,8 +20,7 @@ void SetUp() override { testing::Test::SetUp(); - ash_test_environment_ = AshTestEnvironment::Create(); - ash_test_helper_.reset(new AshTestHelper(ash_test_environment_.get())); + ash_test_helper_ = std::make_unique<AshTestHelper>(); ash_test_helper_->SetUp(true); } @@ -32,10 +31,10 @@ AshTestHelper* ash_test_helper() { return ash_test_helper_.get(); } - protected: - std::unique_ptr<AshTestEnvironment> ash_test_environment_; - private: + base::test::ScopedTaskEnvironment scoped_task_environment_{ + base::test::ScopedTaskEnvironment::MainThreadType::UI}; + std::unique_ptr<AshTestHelper> ash_test_helper_; DISALLOW_COPY_AND_ASSIGN(AshTestHelperTest);
diff --git a/base/strings/string_util.cc b/base/strings/string_util.cc index fd177e3..5e2d0ee 100644 --- a/base/strings/string_util.cc +++ b/base/strings/string_util.cc
@@ -20,7 +20,6 @@ #include <limits> #include <vector> -#include "base/bit_cast.h" #include "base/logging.h" #include "base/macros.h" #include "base/no_destructor.h" @@ -371,16 +370,6 @@ output->clear(); } -#if defined(WCHAR_T_IS_UTF16) -StringPiece16 CastToStringPiece16(WStringPiece wide) { - return StringPiece16(bit_cast<const char16*>(wide.data()), wide.size()); -} - -WStringPiece CastToWStringPiece(StringPiece16 utf16) { - return WStringPiece(bit_cast<const wchar_t*>(utf16.data()), utf16.size()); -} -#endif // defined(WCHAR_T_IS_UTF16) - TrimPositions TrimWhitespace(const string16& input, TrimPositions positions, string16* output) {
diff --git a/base/strings/string_util.h b/base/strings/string_util.h index f5f8da6..a309bbf0 100644 --- a/base/strings/string_util.h +++ b/base/strings/string_util.h
@@ -17,7 +17,9 @@ #include <vector> #include "base/base_export.h" +#include "base/bit_cast.h" #include "base/compiler_specific.h" +#include "base/stl_util.h" #include "base/strings/string16.h" #include "base/strings/string_piece.h" // For implicit conversions. #include "build/build_config.h" @@ -230,12 +232,31 @@ std::string* output); #if defined(WCHAR_T_IS_UTF16) +// Utility functions to access the underlying string buffer as a wide char +// pointer. +inline wchar_t* wdata(char16* str) { + return bit_cast<wchar_t*>(str); +} + +inline wchar_t* wdata(string16& str) { + return bit_cast<wchar_t*>(data(str)); +} + +inline const wchar_t* wdata(StringPiece16 str) { + return bit_cast<const wchar_t*>(str.data()); +} + // In case wchar_t is UTF-16 StringPiece16 and WStringPiece can be effieciently // converted into each other. // Note: These functions will only become useful once base::char16 is char16_t // on all platforms: https://crbug.com/911896 -BASE_EXPORT StringPiece16 CastToStringPiece16(WStringPiece wide); -BASE_EXPORT WStringPiece CastToWStringPiece(StringPiece16 utf16); +inline StringPiece16 CastToStringPiece16(WStringPiece wide) { + return StringPiece16(bit_cast<const char16*>(wide.data()), wide.size()); +} + +inline WStringPiece CastToWStringPiece(StringPiece16 utf16) { + return WStringPiece(wdata(utf16), utf16.size()); +} #endif // defined(WCHAR_T_IS_UTF16) // Trims any whitespace from either end of the input string.
diff --git a/base/strings/string_util_unittest.cc b/base/strings/string_util_unittest.cc index d924285d..6951da7 100644 --- a/base/strings/string_util_unittest.cc +++ b/base/strings/string_util_unittest.cc
@@ -10,10 +10,12 @@ #include <stdint.h> #include <algorithm> +#include <type_traits> #include "base/macros.h" #include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" +#include "build/build_config.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -228,6 +230,33 @@ EXPECT_EQ(output.compare(""), 0); } +#if defined(WCHAR_T_IS_UTF16) +TEST(StringUtilTest, wdata) { + char16 rw_buffer[10] = {}; + static_assert(std::is_same<wchar_t*, decltype(wdata(rw_buffer))>::value, ""); + EXPECT_EQ(rw_buffer, wdata(rw_buffer)); + + string16 rw_str(10, '\0'); + static_assert(std::is_same<wchar_t*, decltype(wdata(rw_str))>::value, ""); + EXPECT_EQ(rw_str.data(), wdata(rw_str)); + + const char16 ro_buffer[10] = {}; + static_assert(std::is_same<const wchar_t*, decltype(wdata(ro_buffer))>::value, + ""); + EXPECT_EQ(ro_buffer, wdata(ro_buffer)); + + const string16 ro_str(10, '\0'); + static_assert(std::is_same<const wchar_t*, decltype(wdata(ro_str))>::value, + ""); + EXPECT_EQ(ro_str.data(), wdata(ro_str)); + + StringPiece16 piece = ro_buffer; + static_assert(std::is_same<const wchar_t*, decltype(wdata(piece))>::value, + ""); + EXPECT_EQ(piece.data(), wdata(piece)); +} +#endif // defined(WCHAR_T_IS_UTF16) + TEST(StringUtilTest, TrimWhitespace) { string16 output; // Allow contents to carry over to next testcase for (const auto& value : trim_cases) {
diff --git a/base/threading/platform_thread_posix.cc b/base/threading/platform_thread_posix.cc index dff4525..7b71b9db 100644 --- a/base/threading/platform_thread_posix.cc +++ b/base/threading/platform_thread_posix.cc
@@ -264,8 +264,9 @@ // Joining another thread may block the current thread for a long time, since // the thread referred to by |thread_handle| may still be running long-lived / // blocking tasks. - base::internal::ScopedBlockingCallWithBaseSyncPrimitives scoped_blocking_call( - base::BlockingType::MAY_BLOCK); + // TODO(https://crbug.com/707362): Make this a + // ScopedBlockingCallWithBaseSyncPrimitives. + base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::MAY_BLOCK); CHECK_EQ(0, pthread_join(thread_handle.platform_handle(), nullptr)); }
diff --git a/base/threading/platform_thread_win.cc b/base/threading/platform_thread_win.cc index 67618d30..f6c63ac 100644 --- a/base/threading/platform_thread_win.cc +++ b/base/threading/platform_thread_win.cc
@@ -274,8 +274,9 @@ // Record the event that this thread is blocking upon (for hang diagnosis). base::debug::ScopedThreadJoinActivity thread_activity(&thread_handle); - base::internal::ScopedBlockingCallWithBaseSyncPrimitives scoped_blocking_call( - base::BlockingType::MAY_BLOCK); + // TODO(https://crbug.com/707362): Make this a + // ScopedBlockingCallWithBaseSyncPrimitives. + base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::MAY_BLOCK); // Wait for the thread to exit. It should already have terminated but make // sure this assumption is valid.
diff --git a/base/threading/thread_restrictions.h b/base/threading/thread_restrictions.h index 591c420..d4f6c94 100644 --- a/base/threading/thread_restrictions.h +++ b/base/threading/thread_restrictions.h
@@ -96,9 +96,8 @@ class BrowserProcessImpl; class HistogramSynchronizer; -class KeyStorageLinux; class NativeBackendKWallet; -class StartupTimeBomb; +class KeyStorageLinux; namespace android_webview { class AwFormDatabaseService; @@ -133,11 +132,10 @@ class CategorizedWorkerPool; class GpuProcessTransportFactory; class NestedMessagePumpAndroid; -class SandboxHostLinux; class ScopedAllowWaitForDebugURL; -class ServiceWorkerSubresourceLoader; class SessionStorageDatabase; class SoftwareOutputDeviceMus; +class ServiceWorkerSubresourceLoader; class SynchronousCompositor; class SynchronousCompositorHost; class SynchronousCompositorSyncCallBridge; @@ -177,9 +175,6 @@ class ScopedIPCSupport; } } -namespace printing { -class PrinterQuery; -} namespace rlz_lib { class FinancialPing; } @@ -191,9 +186,7 @@ } namespace net { class MultiThreadedCertVerifierScopedAllowBaseSyncPrimitives; -class MultiThreadedProxyResolverScopedAllowJoinOnIO; class NetworkChangeNotifierMac; -class NetworkConfigWatcherMacThread; namespace internal { class AddressTrackerLinux; } @@ -398,18 +391,15 @@ // Allowed usage: friend class ::BrowserProcessImpl; // http://crbug.com/125207 friend class ::KeyStorageLinux; - friend class ::StartupTimeBomb; friend class Thread; friend class android::JavaHandlerThread; friend class base::MessageLoopImpl; friend class base::StackSamplingProfiler; - friend class content::SandboxHostLinux; friend class content::ScopedAllowWaitForDebugURL; friend class content::SynchronousCompositor; friend class content::SynchronousCompositorHost; friend class content::SynchronousCompositorSyncCallBridge; friend class mojo::SyncCallRestrictions; - friend class net::NetworkConfigWatcherMacThread; friend class viz::HostGpuMemoryBufferManager; // Usage that should be fixed: @@ -424,11 +414,8 @@ friend class disk_cache::InFlightIO; // http://crbug.com/74623 friend class gpu::GpuChannelHost; // http://crbug.com/125264 friend class midi::TaskService; // https://crbug.com/796830 + friend class net::NetworkChangeNotifierMac; // http://crbug.com/125097 friend class net::internal::AddressTrackerLinux; // http://crbug.com/125097 - friend class net:: - MultiThreadedProxyResolverScopedAllowJoinOnIO; // http://crbug.com/69710 - friend class net::NetworkChangeNotifierMac; // http://crbug.com/125097 - friend class printing::PrinterQuery; // http://crbug.com/66082 // Not used in production yet, https://crbug.com/844078. friend class service_manager::ServiceProcessLauncher; friend class ui::WindowResizeHelperMac; // http://crbug.com/902829
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index 41c02b5..e08275d 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -ea9dcf76f8c34b7bb92bf26a358530bb2f8539c0 \ No newline at end of file +4b11ec4b112443c09d942261fcc7c33fdad99046 \ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 10877275..e3f3159 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -ddeddaca09f7c81db6f467eb3d879b3d18fb8454 \ No newline at end of file +24a01f26ee4236e84d0b573527e9f36e00b2fc34 \ No newline at end of file
diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml index 4935f17..1253ef05 100644 --- a/chrome/android/java/AndroidManifest.xml +++ b/chrome/android/java/AndroidManifest.xml
@@ -519,14 +519,6 @@ {{ self.chrome_activity_common() }}> {{ self.extra_web_rendering_activity_definitions() }} </activity> - <activity android:name="org.chromium.chrome.browser.FullscreenActivity" - android:theme="@style/MainTheme" - android:exported="false" - android:noHistory="true" - {{ self.chrome_activity_common() }} - {{ self.supports_video_persistence() }} > - {{ self.extra_web_rendering_activity_definitions() }} - </activity> <activity android:name="org.chromium.chrome.browser.NoTouchActivity" android:theme="@style/MainTheme" android:exported="false"
diff --git a/chrome/android/java/res_autofill_assistant/layout/autofill_assistant_details.xml b/chrome/android/java/res_autofill_assistant/layout/autofill_assistant_details.xml new file mode 100644 index 0000000..2ad1b18 --- /dev/null +++ b/chrome/android/java/res_autofill_assistant/layout/autofill_assistant_details.xml
@@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2018 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. --> + +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="64dp" + android:background="@drawable/autofill_assistant_details_bg" + android:padding="8dp" + android:visibility="gone" + android:orientation="horizontal"> + <org.chromium.ui.widget.ChromeImageView + android:id="@+id/details_image" + android:layout_width="@dimen/autofill_assistant_details_image_size" + android:layout_height="@dimen/autofill_assistant_details_image_size" + android:layout_marginEnd="16dp" + android:scaleType="centerCrop"/> + + <LinearLayout android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <!-- The top line of the details --> + <LinearLayout android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="5dp" + android:layout_marginEnd="5dp" + android:orientation="horizontal"> + <TextView + android:id="@+id/details_title" + android:layout_width="0dp" + android:layout_weight="1" + android:layout_height="match_parent" + android:textAppearance="@style/TextAppearance.DetailsTitle" + android:singleLine="true" + android:requiresFadingEdge="horizontal" + android:fadingEdgeLength="20dp" + android:ellipsize="none"/> + <!-- Some space between the fading edge of the prev. element and the next element. --> + <Space android:layout_height="match_parent" + android:layout_width="10dp"/> + <!-- The total purchase price in the current locale, e.g. '$123.00' or '123.00 €'. --> + <TextView + android:id="@+id/total_price" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:textAppearance="@style/TextAppearance.DetailsTitle" + android:singleLine="true"/> + </LinearLayout> + + <!-- The bottom line of the details --> + <LinearLayout android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:layout_marginEnd="5dp"> + <TextView + android:id="@+id/details_text" + android:layout_width="0dp" + android:layout_weight="1" + android:layout_height="match_parent" + android:textAppearance="@style/BlackCaption" + android:singleLine="true" + android:requiresFadingEdge="horizontal" + android:fadingEdgeLength="20dp" + android:ellipsize="none"/> + <!-- Some space between the fading edge of the prev. element and the next element. --> + <Space android:layout_height="match_parent" + android:layout_width="10dp"/> + <TextView + android:id="@+id/purchase_summary" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:textAppearance="@style/BlackCaption" + android:singleLine="true"/> + </LinearLayout> + </LinearLayout> +</LinearLayout> \ No newline at end of file
diff --git a/chrome/android/java/res_autofill_assistant/layout/autofill_assistant_sheet.xml b/chrome/android/java/res_autofill_assistant/layout/autofill_assistant_sheet.xml index 2567cd2..bdccf7a9 100644 --- a/chrome/android/java/res_autofill_assistant/layout/autofill_assistant_sheet.xml +++ b/chrome/android/java/res_autofill_assistant/layout/autofill_assistant_sheet.xml
@@ -99,45 +99,8 @@ app:colorBackground="@color/modern_grey_100" app:colorProgress="@color/modern_blue_600" /> - <LinearLayout - android:id="@+id/details" - android:layout_width="match_parent" - android:layout_height="64dp" - android:background="@drawable/autofill_assistant_details_bg" - android:padding="8dp" - android:visibility="gone" - android:orientation="horizontal"> - <org.chromium.ui.widget.ChromeImageView - android:id="@+id/details_image" - android:layout_width="@dimen/autofill_assistant_details_image_size" - android:layout_height="@dimen/autofill_assistant_details_image_size" - android:layout_marginEnd="16dp" - android:scaleType="centerCrop"/> - <LinearLayout - android:layout_width="match_parent" - android:layout_height="match_parent" - android:orientation="vertical"> - <TextView - android:id="@+id/details_title" - android:layout_width="wrap_content" - android:minWidth="184dp" - android:layout_height="16dp" - android:layout_marginBottom="2dp" - android:layout_marginTop="7dp" - android:gravity="bottom" - android:textAppearance="@style/TextAppearance.DetailsTitle" - android:maxLines="1" - android:ellipsize="end"/> - <TextView - android:id="@+id/details_text" - android:layout_width="match_parent" - android:layout_height="16dp" - android:gravity="top" - android:textAppearance="@style/BlackCaption" - android:maxLines="1" - android:ellipsize="end"/> - </LinearLayout> - </LinearLayout> + <include layout="@layout/autofill_assistant_details" + android:id="@+id/details"/> <HorizontalScrollView android:id="@+id/carousel_scroll"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java index 6d9178b..871e087 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -724,13 +724,6 @@ (ControlContainer) findViewById(R.id.control_container); controlContainer.getToolbarResourceAdapter().invalidate(null); } - - @Override - public void onContentChanged(Tab tab) { - if (getBottomSheet() != null) { - setStatusBarColor(tab, TabThemeColorHelper.get(tab).getDefaultColor()); - } - } }; if (mAssistStatusHandler != null) { @@ -1729,7 +1722,7 @@ * * Returns the tab being displayed by this ChromeActivity instance. This allows differentiation * between ChromeActivity subclasses that swap between multiple tabs (e.g. ChromeTabbedActivity) - * and subclasses that only display one Tab (e.g. FullScreenActivity and DocumentActivity). + * and subclasses that only display one Tab (e.g. DocumentActivity). * * The default implementation grabs the tab currently selected by the TabModel, which may be * null if the Tab does not exist or the system is not initialized. @@ -2467,14 +2460,6 @@ public void onExitVr() {} /** - * Whether this Activity supports moving a {@link Tab} to the {@link FullscreenActivity} when it - * enters fullscreen. - */ - public boolean supportsFullscreenActivity() { - return false; - } - - /** * @return Whether this Activity supports showing contextual suggestions in a bottom sheet. */ public boolean supportsContextualSuggestionsBottomSheet() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivitySessionTracker.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivitySessionTracker.java index 04ee22408..9b2da40 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivitySessionTracker.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivitySessionTracker.java
@@ -126,7 +126,7 @@ } /** - * Called when a top-level Chrome activity (ChromeTabbedActivity, FullscreenActivity) is + * Called when a top-level Chrome activity (ChromeTabbedActivity, CustomTabActivity) is * started in foreground. It will not be called again when other Chrome activities take over * (see onStart()), that is, when correct activity calls startActivity() for another Chrome * activity.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java index 665487b4..30ce40f5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
@@ -212,8 +212,6 @@ public static final String EXPLICIT_LANGUAGE_ASK = "ExplicitLanguageAsk"; public static final String EXPLORE_SITES = "ExploreSites"; public static final String FCM_INVALIDATIONS = "FCMInvalidations"; - // When enabled, fullscreen WebContents will be moved to a new Activity. Coming soon... - public static final String FULLSCREEN_ACTIVITY = "FullscreenActivity"; public static final String GESTURE_NAVIGATION = "GestureNavigation"; public static final String GRANT_NOTIFICATIONS_TO_DSE = "GrantNotificationsToDSE"; public static final String GENERIC_SENSOR_EXTRA_CLASSES = "GenericSensorExtraClasses";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java index 1ec40968..3b4510c5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -2381,11 +2381,6 @@ } @Override - public boolean supportsFullscreenActivity() { - return !VrModuleProvider.getDelegate().isInVr(); - } - - @Override public boolean supportsContextualSuggestionsBottomSheet() { return true; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/FullscreenActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/FullscreenActivity.java deleted file mode 100644 index ed7b845..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/FullscreenActivity.java +++ /dev/null
@@ -1,212 +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. - -package org.chromium.chrome.browser; - -import android.content.ComponentName; -import android.content.Intent; -import android.os.Bundle; -import android.provider.Browser; -import android.util.SparseArray; -import android.view.ViewGroup; - -import org.chromium.base.ActivityState; -import org.chromium.base.ApplicationStatus; -import org.chromium.base.Log; -import org.chromium.chrome.browser.compositor.layouts.LayoutManager; -import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager; -import org.chromium.chrome.browser.fullscreen.FullscreenOptions; -import org.chromium.chrome.browser.tab.Tab; -import org.chromium.chrome.browser.util.IntentUtils; -import org.chromium.content_public.browser.ScreenOrientationProvider; -import org.chromium.content_public.browser.WebContentsObserver; - -/** - * An Activity used to display fullscreen WebContents. - * - * This Activity used to be called FullscreenWebContentsActivity and extended FullScreenActivity. - * When FullScreenActivity was renamed to SingleTabActivity, this was changed to FullscreenActivity. - */ -public class FullscreenActivity extends SingleTabActivity { - private static final String TAG = "FullscreenActivity"; - - private static final SparseArray<Tab> sTabsToSteal = new SparseArray<>(); - - private WebContentsObserver mWebContentsObserver; - - @Override - protected Tab createTab() { - assert getIntent().hasExtra(IntentHandler.EXTRA_TAB_ID); - - final Tab tab = getTabToSteal(IntentUtils.safeGetIntExtra( - getIntent(), IntentHandler.EXTRA_TAB_ID, Tab.INVALID_TAB_ID)); - - FullscreenOptions options = IntentUtils.safeGetParcelableExtra( - getIntent(), IntentHandler.EXTRA_FULLSCREEN_OPTIONS); - - tab.reparent(this, createTabDelegateFactory()); - - tab.getFullscreenManager().setTab(tab); - tab.enterFullscreenMode(options); - - mWebContentsObserver = new WebContentsObserver(tab.getWebContents()) { - @Override - public void didFinishNavigation(String url, boolean isInMainFrame, boolean isErrorPage, - boolean hasCommitted, boolean isSameDocument, boolean isFragmentNavigation, - boolean isRendererInitiated, boolean isDownload, Integer pageTransition, - int errorCode, String errorDescription, int httpStatusCode) { - if (hasCommitted && isInMainFrame) { - // Notify the renderer to permanently hide the top controls since they do - // not apply to fullscreen content views. - tab.updateBrowserControlsState(tab.getBrowserControlsStateConstraints(), true); - } - } - }; - return tab; - } - - @Override - public void finishNativeInitialization() { - initializeCompositorContent(new LayoutManager(getCompositorViewHolder()), null /* urlBar */, - (ViewGroup) findViewById(android.R.id.content), null /* controlContainer */); - - if (getFullscreenManager() != null) getFullscreenManager().setTab(getActivityTab()); - super.finishNativeInitialization(); - } - - @Override - protected void initializeToolbar() {} - - @Override - protected ChromeFullscreenManager createFullscreenManager() { - // Create a Fullscreen manager that won't change the Tab's fullscreen state when the - // Activity ends - we handle leaving fullscreen ourselves. - return new ChromeFullscreenManager( - this, ChromeFullscreenManager.ControlsPosition.NONE, false); - } - - @Override - public boolean supportsFullscreenActivity() { - return true; - } - - public static void enterFullscreenMode(final Tab tab, FullscreenOptions options) { - if (tab.getFullscreenManager() == null) { - Log.w(TAG, "Cannot toggle fullscreen, manager is null."); - return; - } - - if (tab.getFullscreenManager().getTab() == tab) { - tab.getFullscreenManager().setTab(null); - } - - launchFullscreenActivityThenStealTab(tab, options); - } - - public static void exitFullscreenMode(final Tab tab) { - if (tab.getFullscreenManager() == null) { - Log.w(TAG, "Cannot toggle fullscreen, manager is null."); - return; - } - - if (tab.getFullscreenManager().getTab() == tab) { - tab.getFullscreenManager().setTab(null); - } - - reparentTabToOriginalOwner(tab); - } - - private static void reparentTabToOriginalOwner(final Tab tab) { - ChromeActivity activity = tab.getActivity(); - - // On Android O, if you return to a portrait Activity from one locked in landscape, the - // Activity gets config changes signalling it has been changed to landscape and back again. - // I believe this is a bug. Since the FullscreenActivity may have had its orientation locked - // to landscape for the video, we unlock it so it doesn't trigger an erroneous config change - // in the receiving Activity. - ScreenOrientationProvider.unlockOrientation(activity.getWindowAndroid()); - - // If reparenting is triggered by the back button, this has already been called. If not we - // must call it to restore everything to a good state before sending the Tab back. - activity.exitFullscreenIfShowing(); - - Intent intent = new Intent(); - intent.putExtra(Browser.EXTRA_APPLICATION_ID, activity.getPackageName()); - // By default Intents from Chrome open in the current tab. We add this extra to prevent - // clobbering the top tab. - intent.putExtra(Browser.EXTRA_CREATE_NEW_TAB, true); - - // Send back to the Activity it came from. - ComponentName parent = IntentUtils.safeGetParcelableExtra( - activity.getIntent(), IntentHandler.EXTRA_PARENT_COMPONENT); - if (parent != null) { - intent.setComponent(parent); - } else { - Log.d(TAG, "Cannot return fullscreen tab to parent Activity."); - // Tab.detachAndStartReparenting will give the intent a default component if it - // has none. - } - - // TODO(peconn): Can we not put this in onStop? - ChromeActivity tabActivity = tab.getActivity(); - if (tabActivity instanceof FullscreenActivity) { - FullscreenActivity fullscreenActivity = (FullscreenActivity) tabActivity; - if (fullscreenActivity.mWebContentsObserver != null) { - fullscreenActivity.mWebContentsObserver.destroy(); - fullscreenActivity.mWebContentsObserver = null; - } - } - - tab.detachAndStartReparenting(intent, null, () -> { - // The Tab's FullscreenManager changes when it is moved. - tab.getFullscreenManager().setTab(tab); - - // TODO(peconn): Will this not already happen? - tab.exitFullscreenMode(); - }); - } - - private static void launchFullscreenActivityThenStealTab(Tab tab, FullscreenOptions options) { - ChromeActivity activity = tab.getActivity(); - - sTabsToSteal.put(tab.getId(), tab); - - Intent intent = new Intent(); - intent.setClass(activity, FullscreenActivity.class); - intent.putExtra(IntentHandler.EXTRA_TAB_ID, tab.getId()); - intent.putExtra(IntentHandler.EXTRA_FULLSCREEN_OPTIONS, options); - intent.putExtra(IntentHandler.EXTRA_PARENT_COMPONENT, activity.getComponentName()); - intent.putExtra(Browser.EXTRA_APPLICATION_ID, activity.getPackageName()); - // In multiwindow mode we want both activities to be able to launch independent - // FullscreenActivity's. - intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK); - - activity.startActivity(intent); - } - - public static boolean shouldUseFullscreenActivity(Tab tab) { - if (!ChromeFeatureList.isEnabled(ChromeFeatureList.FULLSCREEN_ACTIVITY)) return false; - - ChromeActivity activity = tab.getActivity(); - if (!activity.supportsFullscreenActivity()) return false; - - // FullscreenActivity transitions involve Intent-ing to a new Activity. If the current - // Activity is not in the foreground we don't want to do this (as it would re-launch - // Chrome). - return ApplicationStatus.getStateForActivity(activity) == ActivityState.RESUMED; - } - - private static Tab getTabToSteal(int id) { - Tab tab = sTabsToSteal.get(id); - assert tab != null; - - sTabsToSteal.remove(id); - return tab; - } - - @Override - protected Tab restoreTab(Bundle savedInstanceState) { - return null; - } -}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java index 60391d9..1941e76 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java
@@ -335,8 +335,8 @@ } @CalledByNative - private void onShowDetails(String title, String url, String description, String mId, int year, - int month, int day, int hour, int minute, int second) { + private void onShowDetails(String title, String url, String description, String mId, + String price, int year, int month, int day, int hour, int minute, int second) { Date date; if (year > 0 && month > 0 && day > 0 && hour >= 0 && minute >= 0 && second >= 0) { Calendar calendar = Calendar.getInstance(); @@ -348,8 +348,10 @@ date = null; } - maybeUpdateDetails(new Details( - title, url, date, description, mId, /* isFinal= */ true, Collections.emptySet())); + if (price.length() == 0) price = null; + + maybeUpdateDetails(new Details(title, url, date, description, mId, price, + /* isFinal= */ true, Collections.emptySet())); } @CalledByNative
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/Details.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/Details.java index f678f27..f796203 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/Details.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/Details.java
@@ -35,6 +35,7 @@ int DESCRIPTION = 3; int MID = 4; int IS_FINAL = 5; + int PRICE = 6; } private final String mTitle; @@ -44,22 +45,30 @@ private final String mDescription; private final String mMid; private final boolean mIsFinal; + /** + * The correctly formatted price for the client locale, including the currency. + * Example: '$20.50' or '20.50 €'. + */ + @Nullable + private final String mPrice; + /** Contains the fields that have changed when merging with other Details object. */ private final Set<Integer> mFieldsChanged; // NOTE: When adding a new field, update the isEmpty and toJSONObject methods. static final Details EMPTY_DETAILS = - new Details("", "", null, "", "", false, Collections.emptySet()); + new Details("", "", null, "", "", null, false, Collections.emptySet()); private static final String RFC_3339_FORMAT_WITHOUT_TIMEZONE = "yyyy'-'MM'-'dd'T'HH':'mm':'ss"; Details(String title, String url, @Nullable Date date, String description, String mId, - boolean isFinal, Set<Integer> fieldsChanged) { + @Nullable String price, boolean isFinal, Set<Integer> fieldsChanged) { this.mTitle = title; this.mUrl = url; this.mDate = date; this.mDescription = description; this.mMid = mId; + this.mPrice = price; this.mIsFinal = isFinal; this.mFieldsChanged = fieldsChanged; } @@ -85,12 +94,18 @@ return mMid; } + @Nullable + String getPrice() { + return mPrice; + } + JSONObject toJSONObject() { // Details are part of the feedback form, hence they need a JSON representation. Map<String, String> movieDetails = new HashMap<>(); movieDetails.put("title", mTitle); movieDetails.put("url", mUrl); movieDetails.put("mId", mMid); + if (mPrice != null) movieDetails.put("price", mPrice); if (mDate != null) movieDetails.put("date", mDate.toString()); movieDetails.put("description", mDescription); return new JSONObject(movieDetails); @@ -147,7 +162,8 @@ } } - return new Details(title, /* url= */ "", date, description, mId, /* isFinal= */ false, + return new Details(title, /* url= */ "", date, description, mId, /* price= */ null, + /* isFinal= */ false, /* fieldsChanged= */ Collections.emptySet()); } @@ -163,8 +179,8 @@ static Details merge(Details oldDetails, Details newDetails) { if (oldDetails.isEmpty()) { return new Details(newDetails.getTitle(), newDetails.getUrl(), newDetails.getDate(), - newDetails.getDescription(), newDetails.getMid(), newDetails.isFinal(), - Collections.emptySet()); + newDetails.getDescription(), newDetails.getMid(), newDetails.getPrice(), + newDetails.isFinal(), Collections.emptySet()); } Set<Integer> changedFields = new HashSet<>(); @@ -196,7 +212,15 @@ String description = oldDetails.getDescription().isEmpty() ? newDetails.getDescription() : oldDetails.getDescription(); + String price = oldDetails.getPrice(); + if (price == null) { + price = newDetails.getPrice(); + } else if (newDetails.getPrice() != null && !newDetails.getPrice().equals(price)) { + price = newDetails.getPrice(); + changedFields.add(DetailsField.PRICE); + } + boolean isFinal = newDetails.isFinal(); - return new Details(title, url, date, description, mId, isFinal, changedFields); + return new Details(title, url, date, description, mId, price, isFinal, changedFields); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ActivityHostImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ActivityHostImpl.java index e86f371..8a94cba7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ActivityHostImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ActivityHostImpl.java
@@ -61,4 +61,9 @@ public void setTopBarHeight(int heightInPx) { mModuleCoordinator.setTopBarHeight(heightInPx); } + + @Override + public void setTopBarMinHeight(int heightInPx) { + // Do nothing for now. + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ModuleHostImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ModuleHostImpl.java index 9d24c53..c675060 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ModuleHostImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ModuleHostImpl.java
@@ -10,7 +10,7 @@ * The implementation of {@link IModuleHost}. */ public class ModuleHostImpl extends BaseModuleHost { - private static final int VERSION = 7; + private static final int VERSION = 8; private static final int MINIMUM_MODULE_VERSION = 1; private final Context mApplicationContext;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadForegroundService.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadForegroundService.java index 53d3e94..f382932b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadForegroundService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadForegroundService.java
@@ -184,7 +184,7 @@ stopForegroundInternal(ServiceCompat.STOP_FOREGROUND_REMOVE); } } - + stopSelf(); return notificationHandledProperly; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/ChromeFullscreenManager.java b/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/ChromeFullscreenManager.java index db23ffa..d5902b5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/ChromeFullscreenManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/ChromeFullscreenManager.java
@@ -79,7 +79,7 @@ public @interface ControlsPosition { /** Controls are at the top, eg normal ChromeTabbedActivity. */ int TOP = 0; - /** Controls are not present, eg FullscreenActivity. */ + /** Controls are not present, eg NoTouchActivity. */ int NONE = 1; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/TopSnackbarView.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/TopSnackbarView.java index f0fce2b..8324f3d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/TopSnackbarView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/TopSnackbarView.java
@@ -11,7 +11,6 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeActivity; -import org.chromium.chrome.browser.FullscreenActivity; import org.chromium.chrome.browser.snackbar.Snackbar; import org.chromium.chrome.browser.snackbar.SnackbarView; @@ -58,8 +57,6 @@ private int getOffsetFromTop() { if (!(mActivity instanceof ChromeActivity)) return 0; - if (mActivity instanceof FullscreenActivity) return 0; - ChromeActivity chromeActivity = (ChromeActivity) mActivity; if (chromeActivity.getFullscreenManager().getContentOffset() == 0) return 0;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/ContentSettingsResources.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/ContentSettingsResources.java index ff8ccfa..cfd6027 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/ContentSettingsResources.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/ContentSettingsResources.java
@@ -8,6 +8,7 @@ import android.content.res.Resources; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; +import android.os.Build; import android.support.annotation.Nullable; import org.chromium.base.ApiCompatibilityUtils; @@ -359,10 +360,21 @@ */ public static int[] getTriStateSettingDescriptionIDs(int contentType) { if (contentType == ContentSettingsType.CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER) { - int[] descriptionIDs = {R.string.website_settings_category_protected_content_allowed, - R.string.website_settings_category_protected_content_ask, - R.string.website_settings_category_protected_content_blocked}; - return descriptionIDs; + // The recommended setting is different on different android versions depending on + // whether per-origin provisioning is available. See https://crbug.com/904883. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + int[] descriptionIDs = { + R.string.website_settings_category_protected_content_allowed_recommended, + R.string.website_settings_category_protected_content_ask, + R.string.website_settings_category_protected_content_blocked}; + return descriptionIDs; + } else { + int[] descriptionIDs = { + R.string.website_settings_category_protected_content_allowed, + R.string.website_settings_category_protected_content_ask_recommended, + R.string.website_settings_category_protected_content_blocked}; + return descriptionIDs; + } } assert false;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/services/gcm/InvalidationGcmUpstreamSender.java b/chrome/android/java/src/org/chromium/chrome/browser/services/gcm/InvalidationGcmUpstreamSender.java index ec49171d..ac216a55 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/services/gcm/InvalidationGcmUpstreamSender.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/services/gcm/InvalidationGcmUpstreamSender.java
@@ -20,9 +20,9 @@ import org.chromium.base.ThreadUtils; import org.chromium.base.task.AsyncTask; import org.chromium.chrome.browser.init.ProcessInitializationHandler; -import org.chromium.chrome.browser.signin.OAuth2TokenService; import org.chromium.components.signin.AccountManagerFacade; import org.chromium.components.signin.ChromeSigninController; +import org.chromium.components.signin.OAuth2TokenService; import org.chromium.components.sync.SyncConstants; import java.io.IOException;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/IdentityServicesProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/IdentityServicesProvider.java index 888b68e..006956e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/IdentityServicesProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/IdentityServicesProvider.java
@@ -7,6 +7,7 @@ import org.chromium.base.ThreadUtils; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.components.signin.AccountTrackerService; +import org.chromium.components.signin.OAuth2TokenService; /** * Provides access to sign-in related services that are profile-keyed on the native side. Java @@ -21,5 +22,13 @@ return result; } + public static OAuth2TokenService getOAuth2TokenService() { + ThreadUtils.assertOnUiThread(); + OAuth2TokenService result = nativeGetOAuth2TokenService(Profile.getLastUsedProfile()); + assert result != null; + return result; + } + private static native AccountTrackerService nativeGetAccountTrackerService(Profile profile); + private static native OAuth2TokenService nativeGetOAuth2TokenService(Profile profile); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java index 1d6d03b..2b6807b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java
@@ -25,6 +25,7 @@ import org.chromium.components.signin.AccountManagerFacade; import org.chromium.components.signin.AccountTrackerService; import org.chromium.components.signin.ChromeSigninController; +import org.chromium.components.signin.OAuth2TokenService; import org.chromium.components.sync.AndroidSyncSettings; import java.io.IOException; @@ -116,7 +117,7 @@ mProfileSyncService = ProfileSyncService.get(); mSigninManager = SigninManager.get(); mAccountTrackerService = IdentityServicesProvider.getAccountTrackerService(); - mOAuth2TokenService = OAuth2TokenService.getForProfile(Profile.getLastUsedProfile()); + mOAuth2TokenService = IdentityServicesProvider.getOAuth2TokenService(); mChromeSigninController = ChromeSigninController.get(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabContextMenuItemDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabContextMenuItemDelegate.java index a1cc654..4497f513 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabContextMenuItemDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabContextMenuItemDelegate.java
@@ -243,7 +243,7 @@ if (packageManager.queryIntentActivities(chromeIntent, 0).isEmpty()) return; } - // For "Open in Chrome" from the context menu in FullscreenActivity we want to bypass + // For "Open in Chrome" from the context menu in WebappActivity we want to bypass // CustomTab, and this flag ensures we open in TabbedChrome. chromeIntent.putExtra(LaunchIntentDispatcher.EXTRA_IS_ALLOWED_TO_RETURN_TO_PARENT, false);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java index 188660f3..739bbb6c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java
@@ -28,7 +28,6 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.AppHooks; import org.chromium.chrome.browser.ChromeActivity; -import org.chromium.chrome.browser.FullscreenActivity; import org.chromium.chrome.browser.RepostFormWarningDialog; import org.chromium.chrome.browser.SwipeRefreshHandler; import org.chromium.chrome.browser.document.DocumentUtils; @@ -228,21 +227,12 @@ @Override public void enterFullscreenModeForTab(boolean prefersNavigationBar) { - FullscreenOptions options = new FullscreenOptions(prefersNavigationBar); - if (FullscreenActivity.shouldUseFullscreenActivity(mTab)) { - FullscreenActivity.enterFullscreenMode(mTab, options); - } else { - mTab.enterFullscreenMode(options); - } + mTab.enterFullscreenMode(new FullscreenOptions(prefersNavigationBar)); } @Override public void exitFullscreenModeForTab() { - if (FullscreenActivity.shouldUseFullscreenActivity(mTab)) { - FullscreenActivity.exitFullscreenMode(mTab); - } else { - mTab.exitFullscreenMode(); - } + mTab.exitFullscreenMode(); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappAuthenticator.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappAuthenticator.java index 9e3b9bf..032010e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappAuthenticator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappAuthenticator.java
@@ -33,13 +33,13 @@ import javax.crypto.spec.SecretKeySpec; /** - * Authenticate the source of Intents to launch web apps (see e.g. {@link #FullScreenActivity}). + * Authenticate the source of Intents to launch web apps (see {@link #WebappLauncherActivity}). * * Chrome does not keep a store of valid URLs for installed web apps (because it cannot know when * any have been uninstalled). Therefore, upon installation, it tells the Launcher a message * authentication code (MAC) along with the URL for the web app, and then Chrome can verify the MAC - * when starting e.g. {@link #FullScreenActivity}. Chrome can thus distinguish between legitimate, - * installed web apps and arbitrary other URLs. + * when starting e.g. {@link #WebappLauncherActivity}. Chrome can thus distinguish between + * legitimate, installed web apps and arbitrary other URLs. */ public class WebappAuthenticator { private static final String TAG = "WebappAuthenticator";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/FullscreenControlContainer.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/FullscreenControlContainer.java deleted file mode 100644 index bd6755a..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/FullscreenControlContainer.java +++ /dev/null
@@ -1,73 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.chrome.browser.widget; - -import android.content.Context; -import android.graphics.Color; -import android.graphics.Rect; -import android.util.AttributeSet; -import android.view.View; - -import org.chromium.chrome.browser.compositor.layouts.eventfilter.EdgeSwipeHandler; -import org.chromium.chrome.browser.compositor.resources.ResourceFactory; -import org.chromium.chrome.browser.widget.ClipDrawableProgressBar.DrawingInfo; -import org.chromium.ui.resources.dynamics.ViewResourceAdapter; - -/** - * The control container used by the FullscreenActivity. - */ -public class FullscreenControlContainer - extends ViewResourceFrameLayout implements ControlContainer { - private class FullscreenViewResourceAdapter extends ViewResourceAdapter { - private final Rect mToolbarRect = new Rect(); - private final Rect mLocationBarContentRect = new Rect(); - - public FullscreenViewResourceAdapter(View view) { - super(view); - } - - @Override - public long createNativeResource() { - mToolbarRect.set(0, 0, getWidth(), getHeight()); - mLocationBarContentRect.set(0, 0, getWidth(), getHeight()); - return ResourceFactory.createToolbarContainerResource( - mToolbarRect, mLocationBarContentRect, 0); - } - } - - /** Constructor for inflating from XML. */ - public FullscreenControlContainer(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - public void initWithToolbar(int toolbarLayoutId) {} - - @Override - protected final ViewResourceAdapter createResourceAdapter() { - return new FullscreenViewResourceAdapter(this); - } - - @Override - public ViewResourceAdapter getToolbarResourceAdapter() { - return getResourceAdapter(); - } - - @Override - public void getProgressBarDrawingInfo(DrawingInfo drawingInfoOut) {} - - @Override - public void setSwipeHandler(EdgeSwipeHandler handler) {} - - @Override - public int getToolbarBackgroundColor() { - return Color.WHITE; - } - - @Override - public View getView() { - return this; - } -}
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd index fbf0071..31c0efd 100644 --- a/chrome/android/java/strings/android_chrome_strings.grd +++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -1017,9 +1017,15 @@ <message name="IDS_WEBSITE_SETTINGS_CATEGORY_CLIPBOARD_BLOCKED_LIST" desc="Summary text explaining that the clipboard permission is set to block read access on some sites. To be shown in the list of permission categories."> Blocked from reading clipboard </message> - <message name="IDS_WEBSITE_SETTINGS_CATEGORY_PROTECTED_CONTENT_ALLOWED" desc="Summary text explaining that sites are allowed to play protected content and that it is the recommended setting."> + <message name="IDS_WEBSITE_SETTINGS_CATEGORY_PROTECTED_CONTENT_ALLOWED_RECOMMENDED" desc="Summary text explaining that sites are allowed to play protected content and that it is the recommended setting."> Allow sites to play protected content (recommended) </message> + <message name="IDS_WEBSITE_SETTINGS_CATEGORY_PROTECTED_CONTENT_ALLOWED" desc="Summary text explaining that sites are allowed to play protected content."> + Allow sites to play protected content + </message> + <message name="IDS_WEBSITE_SETTINGS_CATEGORY_PROTECTED_CONTENT_ASK_RECOMMENDED" desc="Summary text explaining that sites need to ask for permission before playing protected content and that it is the recommended setting."> + Ask before allowing sites to play protected content (recommended) + </message> <message name="IDS_WEBSITE_SETTINGS_CATEGORY_PROTECTED_CONTENT_ASK" desc="Summary text explaining that sites need to ask for permission before playing protected content."> Ask before allowing sites to play protected content </message>
diff --git a/chrome/android/java/strings/android_chrome_strings_grd/IDS_WEBSITE_SETTINGS_CATEGORY_PROTECTED_CONTENT_ALLOWED.png.sha1 b/chrome/android/java/strings/android_chrome_strings_grd/IDS_WEBSITE_SETTINGS_CATEGORY_PROTECTED_CONTENT_ALLOWED.png.sha1 index 1b23859..a2f99011 100644 --- a/chrome/android/java/strings/android_chrome_strings_grd/IDS_WEBSITE_SETTINGS_CATEGORY_PROTECTED_CONTENT_ALLOWED.png.sha1 +++ b/chrome/android/java/strings/android_chrome_strings_grd/IDS_WEBSITE_SETTINGS_CATEGORY_PROTECTED_CONTENT_ALLOWED.png.sha1
@@ -1 +1 @@ -e8943113528b0aab722fe4d777832797a5f2e35a \ No newline at end of file +1c4b0186b4be157c61bf2d1e56b12102627c0218 \ No newline at end of file
diff --git a/chrome/android/java/strings/android_chrome_strings_grd/IDS_WEBSITE_SETTINGS_CATEGORY_PROTECTED_CONTENT_ALLOWED_RECOMMENDED.png.sha1 b/chrome/android/java/strings/android_chrome_strings_grd/IDS_WEBSITE_SETTINGS_CATEGORY_PROTECTED_CONTENT_ALLOWED_RECOMMENDED.png.sha1 new file mode 100644 index 0000000..fd053e5 --- /dev/null +++ b/chrome/android/java/strings/android_chrome_strings_grd/IDS_WEBSITE_SETTINGS_CATEGORY_PROTECTED_CONTENT_ALLOWED_RECOMMENDED.png.sha1
@@ -0,0 +1 @@ +74913771c6f31ecb202842ac0e430594f2135c55 \ No newline at end of file
diff --git a/chrome/android/java/strings/android_chrome_strings_grd/IDS_WEBSITE_SETTINGS_CATEGORY_PROTECTED_CONTENT_ASK_RECOMMENDED.png.sha1 b/chrome/android/java/strings/android_chrome_strings_grd/IDS_WEBSITE_SETTINGS_CATEGORY_PROTECTED_CONTENT_ASK_RECOMMENDED.png.sha1 new file mode 100644 index 0000000..1d75ed02 --- /dev/null +++ b/chrome/android/java/strings/android_chrome_strings_grd/IDS_WEBSITE_SETTINGS_CATEGORY_PROTECTED_CONTENT_ASK_RECOMMENDED.png.sha1
@@ -0,0 +1 @@ +e97f3e55f43fe40d0d8615543e18e63f6e3144fc \ No newline at end of file
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index 32e599d..e9fd8548 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -47,7 +47,6 @@ "java/src/org/chromium/chrome/browser/DelayedScreenLockIntentHandler.java", "java/src/org/chromium/chrome/browser/DevToolsServer.java", "java/src/org/chromium/chrome/browser/FileProviderHelper.java", - "java/src/org/chromium/chrome/browser/FullscreenActivity.java", "java/src/org/chromium/chrome/browser/InsetObserverView.java", "java/src/org/chromium/chrome/browser/IntentHandler.java", "java/src/org/chromium/chrome/browser/IntentHeadersRecorder.java", @@ -1445,7 +1444,6 @@ "java/src/org/chromium/chrome/browser/signin/ConsentTextTracker.java", "java/src/org/chromium/chrome/browser/signin/DisplayableProfileData.java", "java/src/org/chromium/chrome/browser/signin/GoogleActivityController.java", - "java/src/org/chromium/chrome/browser/signin/OAuth2TokenService.java", "java/src/org/chromium/chrome/browser/signin/PersonalizedSigninPromoView.java", "java/src/org/chromium/chrome/browser/signin/ProfileDataCache.java", "java/src/org/chromium/chrome/browser/signin/SignOutDialogFragment.java", @@ -1740,7 +1738,6 @@ "java/src/org/chromium/chrome/browser/widget/FadingShadow.java", "java/src/org/chromium/chrome/browser/widget/FadingShadowView.java", "java/src/org/chromium/chrome/browser/widget/FeatureHighlightProvider.java", - "java/src/org/chromium/chrome/browser/widget/FullscreenControlContainer.java", "java/src/org/chromium/chrome/browser/widget/ListMenuButton.java", "java/src/org/chromium/chrome/browser/widget/LoadingView.java", "java/src/org/chromium/chrome/browser/widget/MaterialProgressBar.java", @@ -1861,7 +1858,6 @@ "javatests/src/org/chromium/chrome/browser/ExampleUiCaptureTest.java", "javatests/src/org/chromium/chrome/browser/FeaturesAnnotationsTest.java", "javatests/src/org/chromium/chrome/browser/FocusedEditableTextFieldZoomTest.java", - "javatests/src/org/chromium/chrome/browser/FullscreenActivityTest.java", "javatests/src/org/chromium/chrome/browser/HTTPSTabsOpenedFromExternalAppTest.java", "javatests/src/org/chromium/chrome/browser/InstalledAppTest.java", "javatests/src/org/chromium/chrome/browser/IntentHandlerTest.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/FullscreenActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/FullscreenActivityTest.java deleted file mode 100644 index d15082f4..0000000 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/FullscreenActivityTest.java +++ /dev/null
@@ -1,224 +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. - -package org.chromium.chrome.browser; - -import static android.view.View.SYSTEM_UI_FLAG_LOW_PROFILE; - -import android.app.Activity; -import android.app.Instrumentation; -import android.support.test.InstrumentationRegistry; -import android.support.test.filters.MediumTest; -import android.view.View; - -import org.junit.After; -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.Callback; -import org.chromium.base.ThreadUtils; -import org.chromium.base.test.util.CommandLineFlags; -import org.chromium.base.test.util.FlakyTest; -import org.chromium.chrome.browser.fullscreen.FullscreenOptions; -import org.chromium.chrome.browser.tab.EmptyTabObserver; -import org.chromium.chrome.browser.tab.Tab; -import org.chromium.chrome.test.ChromeActivityTestRule; -import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -import org.chromium.content_public.browser.WebContents; -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; -import org.chromium.media.MediaSwitches; -import org.chromium.net.test.EmbeddedTestServer; - -import java.util.concurrent.TimeoutException; - -/** - * Tests for FullscreenActivity. - */ -@RunWith(ChromeJUnit4ClassRunner.class) -@CommandLineFlags. -Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, MediaSwitches.AUTOPLAY_NO_GESTURE_REQUIRED_POLICY, - "enable-features=" + ChromeFeatureList.FULLSCREEN_ACTIVITY}) -public class FullscreenActivityTest { - private static final String TEST_PATH = "/content/test/data/media/video-player.html"; - private static final String VIDEO_ID = "video"; - - @Rule - public ChromeActivityTestRule<ChromeTabbedActivity> mActivityTestRule = - new ChromeActivityTestRule<>(ChromeTabbedActivity.class); - - private EmbeddedTestServer mTestServer; - private ChromeTabbedActivity mActivity; - - @Before - public void setUp() throws InterruptedException { - mTestServer = EmbeddedTestServer.createAndStartServer( - InstrumentationRegistry.getInstrumentation().getContext()); - mActivityTestRule.startMainActivityWithURL(mTestServer.getURL(TEST_PATH)); - mActivity = mActivityTestRule.getActivity(); - } - - @After - public void tearDown() { - mTestServer.stopAndDestroyServer(); - } - - /** - * Tests that the window system visibility has flags set that indicate it is fullscreen. This is - * useful because there is a slight discrepancy between when the webpage thinks it is fullscreen - * and when the window thinks it is fullscreen that can lead to a race condition during tests. - */ - private static boolean hasFullscreenFlags(View view) { - return (view.getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LOW_PROFILE) - == SYSTEM_UI_FLAG_LOW_PROFILE; - } - - /* - * Clicks on the fullscreen button in the test page, waits for the FullscreenActivity - * to be started and for it to go fullscreen. - */ - private FullscreenActivity enterFullscreen() throws Throwable { - // Start playback to guarantee it's properly loaded. - WebContents webContents = mActivity.getCurrentWebContents(); - Assert.assertTrue(DOMUtils.isMediaPaused(webContents, VIDEO_ID)); - DOMUtils.playMedia(webContents, VIDEO_ID); - DOMUtils.waitForMediaPlay(webContents, VIDEO_ID); - - // Trigger requestFullscreen() via a click on a button. - Assert.assertTrue(DOMUtils.clickNode(webContents, "fullscreen")); - - final FullscreenActivity fullscreenActivity = - ChromeActivityTestRule.waitFor(FullscreenActivity.class); - - CriteriaHelper.pollInstrumentationThread(new Criteria() { - @Override - public boolean isSatisfied() { - try { - Tab tab = fullscreenActivity.getActivityTab(); - return DOMUtils.isFullscreen(tab.getWebContents()) - && hasFullscreenFlags(tab.getContentView()); - } catch (InterruptedException | TimeoutException e) { - throw new RuntimeException(e); - } - } - }); - - return fullscreenActivity; - } - - /** - * Enters then exits fullscreen, ensuring that FullscreenActivity is started, that - * the original ChromeTabbedActivity is brough back to the foreground and that the Tab remains - * active throughout. - * @param exit A Callback to exit fullscreen. - */ - private void testFullscreenAndExit(Callback<ChromeActivity> exit) throws Throwable { - Activity original = mActivity; - Tab tab = mActivity.getActivityTab(); - - FullscreenActivity fullscreenActivity = enterFullscreen(); - Assert.assertSame(tab, fullscreenActivity.getActivityTab()); - - exit.onResult(fullscreenActivity); - - ChromeTabbedActivity activity = ChromeActivityTestRule.waitFor(ChromeTabbedActivity.class); - - // Ensure we haven't started a new ChromeTabbedActivity, https://crbug.com/729805, - // https://crbug.com/729932. - Assert.assertSame(original, activity); - Assert.assertSame(tab, mActivity.getActivityTab()); - } - - /** - * Toggles fullscreen to check FullscreenActivity has been started. - */ - @Test - @MediumTest - public void testFullscreen() throws Throwable { - testFullscreenAndExit( - activity -> DOMUtils.exitFullscreen(activity.getCurrentWebContents())); - } - - /** - * Enters fullscreen then presses the back button to exit. - */ - @Test - @MediumTest - public void testExitOnBack() throws Throwable { - testFullscreenAndExit(activity -> { - try { - ThreadUtils.runOnUiThreadBlocking(() -> activity.onBackPressed()); - } catch (Throwable t) { - throw new RuntimeException(t); - } - }); - } - - /** - * Tests that no flags change on the ChromeTabbedActivity when going fullscreen. - */ - @Test - @MediumTest - public void testFullscreenFlags() throws Throwable { - int old = mActivity.getTabsView().getSystemUiVisibility(); - - FullscreenActivity fullscreenActivity = enterFullscreen(); - DOMUtils.exitFullscreen(fullscreenActivity.getCurrentWebContents()); - - ChromeActivityTestRule.waitFor(ChromeTabbedActivity.class); - - Assert.assertEquals(old, mActivity.getTabsView().getSystemUiVisibility()); - } - - /** - * When a FullscreenActivity goes to the background it exits fullscreen if the video is paused. - * In this case we want to exit fullscreen normally, not through Intenting back to the CTA, - * since this will appear to relaunch Chrome. - */ - @Test - @MediumTest - @FlakyTest(message = "crbug.com/906831") - public void testNoIntentWhenInBackground() throws Throwable { - final Boolean[] isTabFullscreen = new Boolean[1]; - Tab tab = mActivity.getActivityTab(); - tab.addObserver(new EmptyTabObserver() { - @Override - public void onEnterFullscreenMode(Tab tab, FullscreenOptions options) { - isTabFullscreen[0] = true; - } - @Override - public void onExitFullscreenMode(Tab tab) { - isTabFullscreen[0] = false; - } - }); - - enterFullscreen(); - Assert.assertTrue(isTabFullscreen[0]); - DOMUtils.pauseMedia(tab.getWebContents(), VIDEO_ID); - - // Add a monitor to track any intents launched to a ChromeTabbedActivity. - Instrumentation.ActivityMonitor monitor = new Instrumentation.ActivityMonitor( - ChromeTabbedActivity.class.getName(), null, true); - InstrumentationRegistry.getInstrumentation().addMonitor(monitor); - - Assert.assertEquals(0, monitor.getHits()); - - // Move Chrome to the background. - ThreadUtils.runOnUiThreadBlocking(() -> mActivity.moveTaskToBack(true)); - - // Wait for the Tab to leave fullscreen. - CriteriaHelper.pollUiThread(new Criteria() { - @Override - public boolean isSatisfied() { - return !isTabFullscreen[0]; - } - }); - - Assert.assertEquals(0, monitor.getHits()); - } -}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/VideoFullscreenOrientationLockChromeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/VideoFullscreenOrientationLockChromeTest.java index 38443d9..c35ce48 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/VideoFullscreenOrientationLockChromeTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/VideoFullscreenOrientationLockChromeTest.java
@@ -38,8 +38,7 @@ @RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, MediaSwitches.AUTOPLAY_NO_GESTURE_REQUIRED_POLICY, - "enable-features=VideoFullscreenOrientationLock", - "disable-features=" + ChromeFeatureList.FULLSCREEN_ACTIVITY}) + "enable-features=VideoFullscreenOrientationLock"}) public class VideoFullscreenOrientationLockChromeTest { @Rule public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java index b285629..1c2d997 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java
@@ -172,6 +172,7 @@ -> uiDelegate.showDetails(new Details(movieTitle, /* url = */ "", Calendar.getInstance().getTime(), movieDescription, /* mId = */ "", + /* price = */ null, /* isFinal= */ true, Collections.emptySet())))); TextView detailsTitle = (TextView) bottomSheet.findViewById(R.id.details_title); TextView detailsText = (TextView) bottomSheet.findViewById(R.id.details_text);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java index 480ef0b..b9fafa1 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
@@ -114,8 +114,7 @@ @RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, ContextualSearchFieldTrial.ONLINE_DETECTION_DISABLED, - "disable-features=" + ChromeFeatureList.CONTEXTUAL_SEARCH_ML_TAP_SUPPRESSION, - "disable-features=" + ChromeFeatureList.FULLSCREEN_ACTIVITY}) + "disable-features=" + ChromeFeatureList.CONTEXTUAL_SEARCH_ML_TAP_SUPPRESSION}) @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) @RetryOnFailure public class ContextualSearchManagerTest {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/fullscreen/FullscreenManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/fullscreen/FullscreenManagerTest.java index 385abb53..91405f1 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/fullscreen/FullscreenManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/fullscreen/FullscreenManagerTest.java
@@ -67,7 +67,6 @@ @RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add({ ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, - "disable-features=" + ChromeFeatureList.FULLSCREEN_ACTIVITY, "enable-blink-features=FullscreenUnprefixed,FullscreenOptions", }) @RetryOnFailure
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/OAuth2TokenServiceIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/OAuth2TokenServiceIntegrationTest.java index a7d6a67..5ef40ca 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/OAuth2TokenServiceIntegrationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/OAuth2TokenServiceIntegrationTest.java
@@ -18,12 +18,12 @@ import org.chromium.base.ThreadUtils; import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.util.RetryOnFailure; -import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.test.util.ApplicationData; import org.chromium.chrome.test.util.browser.signin.SigninTestUtil; import org.chromium.components.signin.AccountIdProvider; import org.chromium.components.signin.AccountManagerFacade; import org.chromium.components.signin.ChromeSigninController; +import org.chromium.components.signin.OAuth2TokenService; import org.chromium.components.signin.test.util.AccountHolder; import org.chromium.components.signin.test.util.FakeAccountManagerDelegate; import org.chromium.content_public.browser.test.NativeLibraryTestRule; @@ -74,7 +74,7 @@ seedAccountTrackerService(); // Get a reference to the service. - mOAuth2TokenService = OAuth2TokenService.getForProfile(Profile.getLastUsedProfile()); + mOAuth2TokenService = IdentityServicesProvider.getOAuth2TokenService(); // Set up observer. mObserver = new TestObserver();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/OAuth2TokenServiceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/OAuth2TokenServiceTest.java index 35013b0..453f130be 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/OAuth2TokenServiceTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/OAuth2TokenServiceTest.java
@@ -19,6 +19,7 @@ import org.chromium.base.test.util.Feature; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.components.signin.AccountManagerFacade; +import org.chromium.components.signin.OAuth2TokenService; import org.chromium.components.signin.test.util.AccountHolder; import org.chromium.components.signin.test.util.FakeAccountManagerDelegate;
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt index dfb0658..9d69c6a 100644 --- a/chrome/android/profiles/newest.txt +++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-73.0.3644.0_rc-r1.afdo.bz2 \ No newline at end of file +chromeos-chrome-amd64-73.0.3645.0_rc-r1.afdo.bz2 \ No newline at end of file
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index d47500f..4c1e6b3 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -7884,9 +7884,12 @@ <message name="IDS_PROTECTED_MEDIA_IDENTIFIER_PERMISSION_FRAGMENT" desc="Permission fragment shown in the permissions bubble when a web page requests access to the computer's protected media identifier."> Know your unique device identifier </message> - <message name="IDS_PROTECTED_MEDIA_IDENTIFIER_INFOBAR_TEXT" desc="Text requesting permission for a site to access protected media identifier. It shows the origin of the URL."> + <message name="IDS_PROTECTED_MEDIA_IDENTIFIER_PER_ORIGIN_PROVISIONING_INFOBAR_TEXT" desc="Text requesting permission for a site to access protected media identifier. It shows the origin of the URL."> <ph name="URL">$1<ex>https://www.youtube.com</ex></ph> wants to play protected content. Your device’s identity will be verified by Google. </message> + <message name="IDS_PROTECTED_MEDIA_IDENTIFIER_PER_DEVICE_PROVISIONING_INFOBAR_TEXT" desc="Text requesting permission for a site to access protected media identifier. It shows the origin of the URL."> + <ph name="URL">$1<ex>https://www.youtube.com</ex></ph> wants to play protected content. Your device's identity will be verified by Google and may be accessed by this site. + </message> </if> <message name="IDS_MANAGE_PASSWORDS_CONFIRM_GENERATED_TEXT" desc="A message that the browser shows after saving a password it has autogenerated for the user. This message appears in a bubble and contains a link to all the user's saved autogenerated passwords. The link text is a separate string in the translation console and appears here as placeholder text."> View and manage saved passwords in your <ph name="SAVED_PASSWORDS_STORE">$1<ex>Google Account</ex></ph>
diff --git a/chrome/app/generated_resources_grd/IDS_PROTECTED_MEDIA_IDENTIFIER_PER_DEVICE_PROVISIONING_INFOBAR_TEXT.png.sha1 b/chrome/app/generated_resources_grd/IDS_PROTECTED_MEDIA_IDENTIFIER_PER_DEVICE_PROVISIONING_INFOBAR_TEXT.png.sha1 new file mode 100644 index 0000000..a71290f --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_PROTECTED_MEDIA_IDENTIFIER_PER_DEVICE_PROVISIONING_INFOBAR_TEXT.png.sha1
@@ -0,0 +1 @@ +9bdd8ad34fe7ce26f5d5f0325a42bada2b559d0c \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_PROTECTED_MEDIA_IDENTIFIER_PER_ORIGIN_PROVISIONING_INFOBAR_TEXT.png.sha1 b/chrome/app/generated_resources_grd/IDS_PROTECTED_MEDIA_IDENTIFIER_PER_ORIGIN_PROVISIONING_INFOBAR_TEXT.png.sha1 new file mode 100644 index 0000000..4131dd1 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_PROTECTED_MEDIA_IDENTIFIER_PER_ORIGIN_PROVISIONING_INFOBAR_TEXT.png.sha1
@@ -0,0 +1 @@ +c636d8f77888d8d20f71b8fb9272282230f12531 \ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index a16ff5f..87c965e 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -2537,8 +2537,6 @@ "search_engines/template_url_service_android.cc", "search_engines/template_url_service_android.h", "signin/identity_services_provider_android.cc", - "signin/oauth2_token_service_delegate_android.cc", - "signin/oauth2_token_service_delegate_android.h", "ssl/security_state_model_android.cc", "sync/glue/synced_tab_delegate_android.cc", "sync/glue/synced_tab_delegate_android.h", @@ -2936,6 +2934,8 @@ "resource_coordinator/tab_manager_web_contents_data.h", "resource_coordinator/tab_metrics_logger.cc", "resource_coordinator/tab_metrics_logger.h", + "resource_coordinator/tracing_lifecycle_unit_observer.cc", + "resource_coordinator/tracing_lifecycle_unit_observer.h", "resource_coordinator/usage_clock.cc", "resource_coordinator/usage_clock.h", "search/background/ntp_background_data.cc", @@ -4883,7 +4883,6 @@ "../android/java/src/org/chromium/chrome/browser/sessions/SessionTabHelper.java", "../android/java/src/org/chromium/chrome/browser/signin/AccountManagementScreenHelper.java", "../android/java/src/org/chromium/chrome/browser/signin/IdentityServicesProvider.java", - "../android/java/src/org/chromium/chrome/browser/signin/OAuth2TokenService.java", "../android/java/src/org/chromium/chrome/browser/signin/SigninInvestigator.java", "../android/java/src/org/chromium/chrome/browser/signin/SigninManager.java", "../android/java/src/org/chromium/chrome/browser/signin/SigninPromoUtil.java",
diff --git a/chrome/browser/android/autofill_assistant/ui_controller_android.cc b/chrome/browser/android/autofill_assistant/ui_controller_android.cc index 47baa74..2e04c0b6 100644 --- a/chrome/browser/android/autofill_assistant/ui_controller_android.cc +++ b/chrome/browser/android/autofill_assistant/ui_controller_android.cc
@@ -427,8 +427,9 @@ base::android::ConvertUTF8ToJavaString(env, details.title()), base::android::ConvertUTF8ToJavaString(env, details.url()), base::android::ConvertUTF8ToJavaString(env, details.description()), - base::android::ConvertUTF8ToJavaString(env, details.m_id()), year, month, - day, hour, minute, second); + base::android::ConvertUTF8ToJavaString(env, details.m_id()), + base::android::ConvertUTF8ToJavaString(env, details.total_price()), year, + month, day, hour, minute, second); } void UiControllerAndroid::ShowProgressBar(int progress,
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc index edc0fd7..270bb99 100644 --- a/chrome/browser/android/chrome_feature_list.cc +++ b/chrome/browser/android/chrome_feature_list.cc
@@ -111,7 +111,6 @@ &kDownloadHomeShowStorageInfo, &kEphemeralTab, &kExploreSites, - &kFullscreenActivity, &kGestureNavigation, &kHandleMediaIntents, &kHideUserDataFromIncognitoNotifications, @@ -303,9 +302,6 @@ const base::Feature kExploreSites{"ExploreSites", base::FEATURE_DISABLED_BY_DEFAULT}; -const base::Feature kFullscreenActivity{"FullscreenActivity", - base::FEATURE_DISABLED_BY_DEFAULT}; - const base::Feature kGestureNavigation{"GestureNavigation", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chrome/browser/android/chrome_feature_list.h b/chrome/browser/android/chrome_feature_list.h index d45aa92..e18398b 100644 --- a/chrome/browser/android/chrome_feature_list.h +++ b/chrome/browser/android/chrome_feature_list.h
@@ -48,7 +48,6 @@ extern const base::Feature kDownloadHomeShowStorageInfo; extern const base::Feature kEphemeralTab; extern const base::Feature kExploreSites; -extern const base::Feature kFullscreenActivity; extern const base::Feature kGestureNavigation; extern const base::Feature kHandleMediaIntents; extern const base::Feature kHideUserDataFromIncognitoNotifications;
diff --git a/chrome/browser/android/metrics/android_profile_session_durations_service_factory.cc b/chrome/browser/android/metrics/android_profile_session_durations_service_factory.cc index dcbb3bc..b2fbe1b 100644 --- a/chrome/browser/android/metrics/android_profile_session_durations_service_factory.cc +++ b/chrome/browser/android/metrics/android_profile_session_durations_service_factory.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/android/metrics/android_profile_session_durations_service_factory.h" #include "chrome/browser/android/metrics/android_profile_session_durations_service.h" +#include "chrome/browser/profiles/incognito_helpers.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/signin/identity_manager_factory.h" @@ -56,6 +57,16 @@ identity_manager); } +content::BrowserContext* +AndroidProfileSessionDurationsServiceFactory::GetBrowserContextToUse( + content::BrowserContext* context) const { + // Session time in incognito is counted towards the session time in the + // regular profile. That means that for a user that is signed in and syncing + // in their regular profile and that is browsing in incognito profile, + // Chromium will record the session time as being signed in and syncing. + return chrome::GetBrowserContextRedirectedInIncognito(context); +} + bool AndroidProfileSessionDurationsServiceFactory::ServiceIsNULLWhileTesting() const { return true;
diff --git a/chrome/browser/android/metrics/android_profile_session_durations_service_factory.h b/chrome/browser/android/metrics/android_profile_session_durations_service_factory.h index 2c5c923..9de1cc77 100644 --- a/chrome/browser/android/metrics/android_profile_session_durations_service_factory.h +++ b/chrome/browser/android/metrics/android_profile_session_durations_service_factory.h
@@ -5,7 +5,7 @@ #ifndef CHROME_BROWSER_ANDROID_METRICS_ANDROID_PROFILE_SESSION_DURATIONS_SERVICE_FACTORY_H_ #define CHROME_BROWSER_ANDROID_METRICS_ANDROID_PROFILE_SESSION_DURATIONS_SERVICE_FACTORY_H_ -#include "chrome/browser/signin/gaia_cookie_manager_service_factory.h" +#include "base/memory/singleton.h" #include "components/keyed_service/content/browser_context_keyed_service_factory.h" class AndroidProfileSessionDurationsService; @@ -34,6 +34,8 @@ // BrowserContextKeyedServiceFactory: KeyedService* BuildServiceInstanceFor( content::BrowserContext* context) const override; + content::BrowserContext* GetBrowserContextToUse( + content::BrowserContext* context) const override; bool ServiceIsNULLWhileTesting() const override; DISALLOW_COPY_AND_ASSIGN(AndroidProfileSessionDurationsServiceFactory);
diff --git a/chrome/browser/android/signin/signin_manager_android.cc b/chrome/browser/android/signin/signin_manager_android.cc index cd743d0..fa3a5af 100644 --- a/chrome/browser/android/signin/signin_manager_android.cc +++ b/chrome/browser/android/signin/signin_manager_android.cc
@@ -27,7 +27,6 @@ #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/signin/account_tracker_service_factory.h" #include "chrome/browser/signin/identity_manager_factory.h" -#include "chrome/browser/signin/oauth2_token_service_delegate_android.h" #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" #include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/common/pref_names.h" @@ -40,6 +39,7 @@ #include "components/prefs/pref_service.h" #include "components/signin/core/browser/account_consistency_method.h" #include "components/signin/core/browser/account_tracker_service.h" +#include "components/signin/core/browser/oauth2_token_service_delegate_android.h" #include "components/signin/core/browser/profile_oauth2_token_service.h" #include "components/signin/core/browser/signin_metrics.h" #include "components/signin/core/browser/signin_pref_names.h"
diff --git a/chrome/browser/autofill/manual_filling_controller_impl.cc b/chrome/browser/autofill/manual_filling_controller_impl.cc index eed2df4..f03c88b 100644 --- a/chrome/browser/autofill/manual_filling_controller_impl.cc +++ b/chrome/browser/autofill/manual_filling_controller_impl.cc
@@ -37,8 +37,8 @@ web_contents->SetUserData( UserDataKey(), - base::WrapUnique(new ManualFillingControllerImpl( - web_contents, std::move(pwd_controller), std::move(view)))); + std::make_unique<ManualFillingControllerImpl>( + web_contents, std::move(pwd_controller), std::move(view))); } void ManualFillingControllerImpl::OnAutomaticGenerationStatusChanged(
diff --git a/chrome/browser/autofill/manual_filling_controller_impl.h b/chrome/browser/autofill/manual_filling_controller_impl.h index 213f75f..d827351 100644 --- a/chrome/browser/autofill/manual_filling_controller_impl.h +++ b/chrome/browser/autofill/manual_filling_controller_impl.h
@@ -20,6 +20,11 @@ : public ManualFillingController, public content::WebContentsUserData<ManualFillingControllerImpl> { public: + // Constructor that allows to inject a mock or fake view. + ManualFillingControllerImpl( + content::WebContents* web_contents, + base::WeakPtr<PasswordAccessoryController> pwd_controller, + std::unique_ptr<ManualFillingViewInterface> view); ~ManualFillingControllerImpl() override; // ManualFillingController: @@ -61,12 +66,6 @@ // Required for construction via |CreateForWebContents|: explicit ManualFillingControllerImpl(content::WebContents* contents); - // Constructor that allows to inject a mock or fake view. - ManualFillingControllerImpl( - content::WebContents* web_contents, - base::WeakPtr<PasswordAccessoryController> pwd_controller, - std::unique_ptr<ManualFillingViewInterface> view); - // The tab for which this class is scoped. content::WebContents* web_contents_;
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index 830ebaa..3bb5f6d 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -1487,6 +1487,8 @@ "policy/device_auto_update_time_restrictions_decoder.h", "policy/device_auto_update_time_restrictions_utils.cc", "policy/device_auto_update_time_restrictions_utils.h", + "policy/device_cloud_external_data_policy_observer.cc", + "policy/device_cloud_external_data_policy_observer.h", "policy/device_cloud_policy_initializer.cc", "policy/device_cloud_policy_initializer.h", "policy/device_cloud_policy_manager_chromeos.cc", @@ -2334,6 +2336,7 @@ "policy/upload_job_unittest.cc", "policy/user_cloud_policy_manager_chromeos_unittest.cc", "policy/user_cloud_policy_store_chromeos_unittest.cc", + "policy/user_cloud_policy_token_forwarder_unittest.cc", "power/auto_screen_brightness/adapter_unittest.cc", "power/auto_screen_brightness/als_reader_impl_unittest.cc", "power/auto_screen_brightness/brightness_monitor_impl_unittest.cc",
diff --git a/chrome/browser/chromeos/arc/auth/arc_auth_service_browsertest.cc b/chrome/browser/chromeos/arc/auth/arc_auth_service_browsertest.cc index 4a9458e..a389530 100644 --- a/chrome/browser/chromeos/arc/auth/arc_auth_service_browsertest.cc +++ b/chrome/browser/chromeos/arc/auth/arc_auth_service_browsertest.cc
@@ -35,6 +35,7 @@ #include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/browser/ui/app_list/arc/arc_data_removal_dialog.h" #include "chrome/browser/ui/ash/multi_user/multi_user_util.h" +#include "chrome/common/chrome_switches.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/testing_profile.h" #include "chromeos/account_manager/account_manager.h" @@ -59,6 +60,7 @@ #include "components/signin/core/browser/account_tracker_service.h" #include "components/user_manager/scoped_user_manager.h" #include "components/user_manager/user_manager.h" +#include "components/user_manager/user_names.h" #include "content/public/browser/browser_task_traits.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" @@ -263,9 +265,6 @@ identity_test_environment_adaptor_->identity_test_env(); identity_test_env->SetAutomaticIssueOfAccessTokens(true); identity_test_env->MakePrimaryAccountAvailable(kFakeUserName); - identity_test_env->identity_manager() - ->GetAccountsMutator() - ->LoadAccountsFromDisk(kFakeUserName); profile()->GetPrefs()->SetBoolean(prefs::kArcSignedIn, true); profile()->GetPrefs()->SetBoolean(prefs::kArcTermsAccepted, true); @@ -469,6 +468,19 @@ ArcAuthServiceTest::SetUp(); } + void SetUpCommandLine(base::CommandLine* command_line) override { + // Configure primary profile to be a guest profile, because the + // AccountManager can't deal with regular profiles in tests. + // https://crbug.com/915628 + command_line->AppendSwitch(chromeos::switches::kGuestSession); + command_line->AppendSwitch(switches::kIncognito); + command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "hash"); + command_line->AppendSwitchASCII( + chromeos::switches::kLoginUser, + user_manager::GuestAccountId().GetUserEmail()); + ArcAuthServiceTest::SetUpCommandLine(command_line); + } + AccountInfo SetupGaiaAccount(const std::string& email, const std::string& token) { SetAccountAndProfile(user_manager::USER_TYPE_REGULAR);
diff --git a/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service_unittest.cc b/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service_unittest.cc index 0ed8e53..97fa01c 100644 --- a/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service_unittest.cc +++ b/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service_unittest.cc
@@ -10,7 +10,6 @@ #include <vector> #include "ash/public/cpp/ash_pref_names.h" -#include "ash/test/ash_test_base.h" #include "base/macros.h" #include "base/memory/scoped_refptr.h" #include "base/run_loop.h" @@ -22,12 +21,12 @@ #include "chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client_test_helper.h" #include "chrome/browser/ui/ash/tablet_mode_client.h" #include "chrome/common/pref_names.h" +#include "chrome/test/base/chrome_ash_test_base.h" #include "chrome/test/base/testing_profile.h" #include "components/arc/arc_features.h" #include "components/arc/arc_service_manager.h" #include "components/arc/test/test_browser_context.h" #include "components/crx_file/id_util.h" -#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/ime/chromeos/extension_ime_util.h" #include "ui/base/ime/chromeos/mock_input_method_manager.h" @@ -35,6 +34,7 @@ #include "ui/base/ime/ime_bridge.h" #include "ui/base/ime/mock_ime_input_context_handler.h" #include "ui/base/ime/mock_input_method.h" +#include "ui/base/ui_base_features.h" namespace arc { namespace { @@ -167,9 +167,9 @@ DISALLOW_COPY_AND_ASSIGN(TestIMEInputContextHandler); }; -// TODO(crbug.com/890677): Stop inheriting ash::AshTestBase once ash::Shell +// TODO(crbug.com/890677): Stop inheriting ChromeAshTestBase once ash::Shell // dependency is removed from ArcInputMethodManagerService. -class ArcInputMethodManagerServiceTest : public ash::AshTestBase { +class ArcInputMethodManagerServiceTest : public ChromeAshTestBase { protected: ArcInputMethodManagerServiceTest() : arc_service_manager_(std::make_unique<ArcServiceManager>()) {} @@ -188,7 +188,7 @@ } void SetUp() override { - ash::AshTestBase::SetUp(); + ChromeAshTestBase::SetUp(); SetRunningOutsideAsh(); ui::IMEBridge::Initialize(); input_method_manager_ = new TestInputMethodManager(); @@ -216,7 +216,7 @@ tablet_mode_client_.reset(nullptr); chromeos::input_method::InputMethodManager::Shutdown(); ui::IMEBridge::Shutdown(); - ash::AshTestBase::TearDown(); + ChromeAshTestBase::TearDown(); } private: @@ -714,6 +714,10 @@ } TEST_F(ArcInputMethodManagerServiceTest, DisableFallbackVirtualKeyboard) { + // TODO(crbug.com/910240): fix for mash. + if (features::IsSingleProcessMash()) + return; + namespace ceiu = chromeos::extension_ime_util; using crx_file::id_util::GenerateId;
diff --git a/chrome/browser/chromeos/arc/tracing/arc_tracing_bridge.cc b/chrome/browser/chromeos/arc/tracing/arc_tracing_bridge.cc index 0c0f798..ddfc403 100644 --- a/chrome/browser/chromeos/arc/tracing/arc_tracing_bridge.cc +++ b/chrome/browser/chromeos/arc/tracing/arc_tracing_bridge.cc
@@ -441,11 +441,13 @@ ArcTracingBridge::ArcTracingAgent::ArcTracingAgent(ArcTracingBridge* bridge) : BaseAgent( - content::ServiceManagerConnection::GetForProcess()->GetConnector(), + kChromeTraceEventLabel, tracing::mojom::TraceDataType::ARRAY, base::kNullProcessId), - bridge_(bridge) {} + bridge_(bridge) { + Connect(content::ServiceManagerConnection::GetForProcess()->GetConnector()); +} ArcTracingBridge::ArcTracingAgent::~ArcTracingAgent() = default;
diff --git a/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service_unittest.cc b/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service_unittest.cc index 247e0d3..f2224bc 100644 --- a/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service_unittest.cc +++ b/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service_unittest.cc
@@ -10,7 +10,6 @@ #include "ash/public/interfaces/constants.mojom.h" #include "ash/shell.h" -#include "ash/test/ash_test_base.h" #include "base/bind.h" #include "base/files/scoped_temp_dir.h" #include "chrome/browser/chromeos/arc/arc_session_manager.h" @@ -18,6 +17,7 @@ #include "chrome/browser/chromeos/arc/voice_interaction/highlighter_controller_client.h" #include "chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client.h" #include "chrome/browser/ui/browser.h" +#include "chrome/test/base/chrome_ash_test_base.h" #include "chrome/test/base/test_browser_window.h" #include "chrome/test/base/test_browser_window_aura.h" #include "chrome/test/base/testing_profile.h" @@ -126,12 +126,12 @@ } // namespace -class ArcVoiceInteractionFrameworkServiceTest : public ash::AshTestBase { +class ArcVoiceInteractionFrameworkServiceTest : public ChromeAshTestBase { public: ArcVoiceInteractionFrameworkServiceTest() = default; void SetUp() override { - AshTestBase::SetUp(); + ChromeAshTestBase::SetUp(); SetRunningOutsideAsh(); // Setup test profile. ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); @@ -184,7 +184,7 @@ arc_session_manager_.reset(); session_manager_.reset(); profile_.reset(); - AshTestBase::TearDown(); + ChromeAshTestBase::TearDown(); } protected:
diff --git a/chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client_unittest.cc b/chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client_unittest.cc index 62a5f902..148e5b6 100644 --- a/chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client_unittest.cc +++ b/chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client_unittest.cc
@@ -5,12 +5,12 @@ #include "chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client.h" #include "ash/shell.h" -#include "ash/test/ash_test_base.h" #include "base/bind.h" #include "base/files/scoped_temp_dir.h" #include "chrome/browser/chromeos/arc/arc_session_manager.h" #include "chrome/browser/chromeos/arc/voice_interaction/fake_voice_interaction_controller.h" #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h" +#include "chrome/test/base/chrome_ash_test_base.h" #include "chrome/test/base/testing_profile.h" #include "components/arc/arc_prefs.h" #include "components/arc/arc_util.h" @@ -22,7 +22,7 @@ namespace arc { -class VoiceInteractionControllerClientTest : public ash::AshTestBase { +class VoiceInteractionControllerClientTest : public ChromeAshTestBase { public: VoiceInteractionControllerClientTest() : fake_user_manager_( @@ -30,7 +30,7 @@ ~VoiceInteractionControllerClientTest() override = default; void SetUp() override { - AshTestBase::SetUp(); + ChromeAshTestBase::SetUp(); // Setup test profile. ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); @@ -64,7 +64,7 @@ voice_interaction_controller_.reset(); voice_interaction_controller_client_.reset(); profile_.reset(); - AshTestBase::TearDown(); + ChromeAshTestBase::TearDown(); } FakeVoiceInteractionController* voice_interaction_controller() {
diff --git a/chrome/browser/chromeos/authpolicy/auth_policy_credentials_manager.cc b/chrome/browser/chromeos/authpolicy/auth_policy_credentials_manager.cc index 1201097..ff36e20 100644 --- a/chrome/browser/chromeos/authpolicy/auth_policy_credentials_manager.cc +++ b/chrome/browser/chromeos/authpolicy/auth_policy_credentials_manager.cc
@@ -23,7 +23,6 @@ #include "chrome/browser/notifications/notification_display_service.h" #include "chrome/browser/notifications/notification_display_service_factory.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" #include "chrome/common/pref_names.h" #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" @@ -37,7 +36,6 @@ #include "chromeos/network/network_state.h" #include "chromeos/network/network_state_handler.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" -#include "components/signin/core/browser/profile_oauth2_token_service.h" #include "dbus/message.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" @@ -93,7 +91,7 @@ return adjusted_config; } -// Sets up Chrome OS Account Manager and starts |ProfileOAuth2TokenService|. +// Sets up Chrome OS Account Manager. // |profile| is a non-owning pointer to |Profile|. // |object_guid| is the Active Directory Object GUID for the Device Account. void SetupAccountManager(Profile* profile, const std::string& object_guid) { @@ -113,11 +111,6 @@ object_guid, account_manager::AccountType::ACCOUNT_TYPE_ACTIVE_DIRECTORY}, AccountManager::kActiveDirectoryDummyToken); - - // Needed to work with Secondary Accounts in Chrome OS Account Manager. The - // value of |primary_account_id| doesn't matter. - ProfileOAuth2TokenServiceFactory::GetForProfile(profile)->LoadCredentials( - std::string() /* primary_account_id */); } } // namespace @@ -413,7 +406,6 @@ : BrowserContextKeyedServiceFactory( "AuthPolicyCredentialsManager", BrowserContextDependencyManager::GetInstance()) { - DependsOn(ProfileOAuth2TokenServiceFactory::GetInstance()); } AuthPolicyCredentialsManagerFactory::~AuthPolicyCredentialsManagerFactory() {}
diff --git a/chrome/browser/chromeos/child_accounts/screen_time_controller.cc b/chrome/browser/chromeos/child_accounts/screen_time_controller.cc index d66402c..ba64beb 100644 --- a/chrome/browser/chromeos/child_accounts/screen_time_controller.cc +++ b/chrome/browser/chromeos/child_accounts/screen_time_controller.cc
@@ -34,7 +34,6 @@ constexpr char kScreenStateNextStateChangeTime[] = "next_state_change_time"; constexpr char kScreenStateNextPolicyType[] = "next_active_policy"; constexpr char kScreenStateNextUnlockTime[] = "next_unlock_time"; -constexpr char kScreenStateLastStateChanged[] = "last_state_changed"; } // namespace @@ -216,8 +215,6 @@ base::Value(static_cast<int>(state.next_state_active_policy))); state_dict->SetKey(kScreenStateNextUnlockTime, base::Value(state.next_unlock_time.ToDoubleT())); - state_dict->SetKey(kScreenStateLastStateChanged, - base::Value(state.last_state_changed.ToDoubleT())); pref_service_->Set(prefs::kScreenTimeLastState, *state_dict); pref_service_->CommitPendingWrite(); @@ -302,14 +299,6 @@ return base::nullopt; result.next_unlock_time = base::Time::FromDoubleT(next_unlock_time->GetDouble()); - - // Verify last_state_changed from the pref is a double value. - const base::Value* last_state_changed = - last_state->FindKey(kScreenStateLastStateChanged); - if (!last_state_changed || !last_state_changed->is_double()) - return base::nullopt; - result.last_state_changed = - base::Time::FromDoubleT(last_state_changed->GetDouble()); return result; }
diff --git a/chrome/browser/chromeos/child_accounts/usage_time_limit_processor.cc b/chrome/browser/chromeos/child_accounts/usage_time_limit_processor.cc index 0017288f..4da5353b 100644 --- a/chrome/browser/chromeos/child_accounts/usage_time_limit_processor.cc +++ b/chrome/browser/chromeos/child_accounts/usage_time_limit_processor.cc
@@ -292,17 +292,6 @@ state.next_unlock_time = GetNextUnlockTime(); - if (!previous_state_) - return state; - - if (previous_state_->is_locked == state.is_locked && - previous_state_->active_policy == state.active_policy) { - state.last_state_changed = previous_state_->last_state_changed; - return state; - } - - state.last_state_changed = current_time_; - return state; }
diff --git a/chrome/browser/chromeos/child_accounts/usage_time_limit_processor.h b/chrome/browser/chromeos/child_accounts/usage_time_limit_processor.h index ebcc23b..19f9bc5 100644 --- a/chrome/browser/chromeos/child_accounts/usage_time_limit_processor.h +++ b/chrome/browser/chromeos/child_accounts/usage_time_limit_processor.h
@@ -150,9 +150,6 @@ // This is the next time that the user's session will be unlocked. This is // only set when is_locked=true; base::Time next_unlock_time; - - // Last time the state changed. - base::Time last_state_changed; }; // Returns the current state of the user session with the given usage time limit
diff --git a/chrome/browser/chromeos/child_accounts/usage_time_limit_processor_unittest.cc b/chrome/browser/chromeos/child_accounts/usage_time_limit_processor_unittest.cc index 9c12188..3becedf 100644 --- a/chrome/browser/chromeos/child_accounts/usage_time_limit_processor_unittest.cc +++ b/chrome/browser/chromeos/child_accounts/usage_time_limit_processor_unittest.cc
@@ -174,8 +174,6 @@ if (actual.is_locked) ASSERT_EQ(expected.next_unlock_time, actual.next_unlock_time); - - ASSERT_EQ(expected.last_state_changed, actual.last_state_changed); } namespace internal { @@ -385,7 +383,6 @@ expected_state_one.is_time_usage_limit_enabled = false; expected_state_one.next_state_change_time = monday_time_window_limit_start; expected_state_one.next_state_active_policy = ActivePolicies::kFixedLimit; - expected_state_one.last_state_changed = base::Time(); AssertEqState(expected_state_one, state_one); @@ -401,7 +398,6 @@ expected_state_two.next_state_change_time = monday_time_window_limit_end; expected_state_two.next_state_active_policy = ActivePolicies::kFixedLimit; expected_state_two.next_unlock_time = tuesday_time_window_limit_end; - expected_state_two.last_state_changed = time_two; AssertEqState(expected_state_two, state_two); @@ -417,7 +413,6 @@ expected_state_three.is_time_usage_limit_enabled = false; expected_state_three.next_state_change_time = friday_time_window_limit_start; expected_state_three.next_state_active_policy = ActivePolicies::kFixedLimit; - expected_state_three.last_state_changed = time_three; AssertEqState(expected_state_three, state_three); } @@ -451,7 +446,6 @@ expected_state_one.next_state_change_time = TimeFromString("Tue, 2 Jan 2018 10:00"); expected_state_one.next_state_active_policy = ActivePolicies::kUsageLimit; - expected_state_one.last_state_changed = base::Time(); AssertEqState(expected_state_one, state_one); @@ -468,7 +462,6 @@ expected_state_two.next_state_change_time = time_two + base::TimeDelta::FromMinutes(60); expected_state_two.next_state_active_policy = ActivePolicies::kUsageLimit; - expected_state_two.last_state_changed = base::Time(); AssertEqState(expected_state_two, state_two); @@ -490,7 +483,6 @@ expected_state_three.next_state_active_policy = ActivePolicies::kNoActivePolicy; expected_state_three.next_unlock_time = wednesday_reset_time; - expected_state_three.last_state_changed = time_three; AssertEqState(expected_state_three, state_three); } @@ -525,7 +517,6 @@ expected_state_one.next_state_change_time = time_one + base::TimeDelta::FromMinutes(40); expected_state_one.next_state_active_policy = ActivePolicies::kUsageLimit; - expected_state_one.last_state_changed = base::Time(); AssertEqState(expected_state_one, state_one); @@ -546,7 +537,6 @@ expected_state_two.next_state_change_time = monday_time_window_limit_start; expected_state_two.next_state_active_policy = ActivePolicies::kFixedLimit; expected_state_two.next_unlock_time = TimeFromString("Tue, 2 Jan 2018 8:30"); - expected_state_two.last_state_changed = time_two; AssertEqState(expected_state_two, state_two); @@ -568,7 +558,6 @@ ActivePolicies::kNoActivePolicy; expected_state_three.next_unlock_time = TimeFromString("Tue, 2 Jan 2018 8:30"); - expected_state_three.last_state_changed = time_three; AssertEqState(expected_state_three, state_three); @@ -585,7 +574,6 @@ expected_state_four.next_state_change_time = TimeFromString("Fri, 5 Jan 2018 21:00"); expected_state_four.next_state_active_policy = ActivePolicies::kFixedLimit; - expected_state_four.last_state_changed = time_four; AssertEqState(expected_state_four, state_four); } @@ -616,7 +604,6 @@ expected_state_one.time_usage_limit_started = time_one; expected_state_one.next_unlock_time = TimeFromString("Sat, 6 Jan 2018 6:00 PST"); - expected_state_one.last_state_changed = base::Time(); AssertEqState(expected_state_one, state_one); } @@ -643,7 +630,6 @@ TimeFromString("Tue, 2 Jan 2018 0:00"); expected_state_one.next_state_active_policy = ActivePolicies::kNoActivePolicy; expected_state_one.next_unlock_time = TimeFromString("Tue, 2 Jan 2018 0:00"); - expected_state_one.last_state_changed = base::Time(); AssertEqState(expected_state_one, state_one); } @@ -676,7 +662,6 @@ expected_state_one.next_state_change_time = TimeFromString("Mon, 8 Jan 2018 18:00 GMT+0800"); expected_state_one.next_state_active_policy = ActivePolicies::kFixedLimit; - expected_state_one.last_state_changed = base::Time(); AssertEqState(expected_state_one, state_one); @@ -700,7 +685,6 @@ expected_state_two.next_state_active_policy = ActivePolicies::kNoActivePolicy; expected_state_two.next_unlock_time = TimeFromString("Tue, 2 Jan 2018 8:00 GMT+0800"); - expected_state_two.last_state_changed = time_two; AssertEqState(expected_state_two, state_two); } @@ -733,7 +717,6 @@ expected_state_one.next_state_change_time = TimeFromString("Mon, 1 Jan 2018 22:30 PST"); expected_state_one.next_state_active_policy = ActivePolicies::kUsageLimit; - expected_state_one.last_state_changed = base::Time(); AssertEqState(expected_state_one, state_one); @@ -755,7 +738,6 @@ expected_state_two.next_state_active_policy = ActivePolicies::kNoActivePolicy; expected_state_two.next_unlock_time = TimeFromString("Tue, 2 Jan 2018 8:00 PST"); - expected_state_two.last_state_changed = time_two; AssertEqState(expected_state_two, state_two); } @@ -783,7 +765,6 @@ expected_state_one.next_state_change_time = TimeFromString("Sun, 7 Jan 2018 15:20 PST"); expected_state_one.next_state_active_policy = ActivePolicies::kUsageLimit; - expected_state_one.last_state_changed = base::Time(); AssertEqState(expected_state_one, state_one); @@ -802,7 +783,6 @@ expected_state_two.next_state_active_policy = ActivePolicies::kNoActivePolicy; expected_state_two.next_unlock_time = TimeFromString("Mon, 8 Jan 2018 6:00 PST"); - expected_state_two.last_state_changed = time_two; AssertEqState(expected_state_two, state_two); @@ -825,7 +805,6 @@ ActivePolicies::kNoActivePolicy; // This should be TimeFromString("Sun, 14 Jan 2018 7:00 PST"), crbug/902348: expected_state_three.next_unlock_time = base::Time(); - expected_state_three.last_state_changed = time_three; AssertEqState(expected_state_three, state_three); } @@ -856,7 +835,6 @@ expected_state_one.next_state_active_policy = ActivePolicies::kNoActivePolicy; expected_state_one.next_unlock_time = TimeFromString("Tue, 2 Jan 2018 6:00 PST"); - expected_state_one.last_state_changed = base::Time(); AssertEqState(expected_state_one, state_one); @@ -874,7 +852,6 @@ expected_state_two.next_state_active_policy = ActivePolicies::kNoActivePolicy; expected_state_two.next_unlock_time = TimeFromString("Tue, 2 Jan 2018 6:00 PST"); - expected_state_two.last_state_changed = base::Time(); AssertEqState(expected_state_two, state_two); @@ -892,7 +869,6 @@ expected_state_three.next_state_active_policy = ActivePolicies::kNoActivePolicy; expected_state_three.next_unlock_time = base::Time(); - expected_state_three.last_state_changed = time_three; AssertEqState(expected_state_three, state_three); } @@ -947,7 +923,6 @@ expected_night_state.next_state_active_policy = ActivePolicies::kNoActivePolicy; expected_night_state.next_unlock_time = window_limit_end_time; - expected_night_state.last_state_changed = base::Time(); AssertEqState(expected_night_state, night_state); @@ -964,7 +939,6 @@ expected_morning_state.next_state_active_policy = ActivePolicies::kNoActivePolicy; expected_morning_state.next_unlock_time = window_limit_end_time; - expected_morning_state.last_state_changed = base::Time(); AssertEqState(expected_morning_state, morning_state); } @@ -1021,7 +995,6 @@ ActivePolicies::kNoActivePolicy; expected_night_state.next_unlock_time = usage_limit_reset_time; expected_night_state.time_usage_limit_started = night_time; - expected_night_state.last_state_changed = base::Time(); AssertEqState(expected_night_state, night_state); @@ -1039,7 +1012,6 @@ ActivePolicies::kNoActivePolicy; expected_morning_state.next_unlock_time = usage_limit_reset_time; expected_morning_state.time_usage_limit_started = night_time; - expected_morning_state.last_state_changed = base::Time(); AssertEqState(expected_morning_state, morning_state); } @@ -1070,7 +1042,6 @@ expected_state_one.next_state_active_policy = ActivePolicies::kNoActivePolicy; expected_state_one.next_unlock_time = TimeFromString("Sun, 7 Jan 2018 8:30 GMT"); - expected_state_one.last_state_changed = base::Time(); AssertEqState(expected_state_one, state_one); } @@ -1102,7 +1073,6 @@ expected_state_one.next_state_active_policy = ActivePolicies::kNoActivePolicy; expected_state_one.next_unlock_time = TimeFromString("Sun, 7 Jan 2018 6:00 GMT"); - expected_state_one.last_state_changed = base::Time(); AssertEqState(expected_state_one, state_one); } @@ -1134,7 +1104,6 @@ expected_state_one.next_state_active_policy = ActivePolicies::kNoActivePolicy; expected_state_one.next_unlock_time = TimeFromString("Sun, 7 Jan 2018 6:00 PST"); - expected_state_one.last_state_changed = base::Time(); AssertEqState(expected_state_one, state_one); } @@ -1167,7 +1136,6 @@ expected_state_one.next_state_active_policy = ActivePolicies::kFixedLimit; expected_state_one.next_unlock_time = TimeFromString("Mon, 1 Jan 2018 20:00 PST"); - expected_state_one.last_state_changed = base::Time(); AssertEqState(expected_state_one, state_one); @@ -1185,7 +1153,6 @@ expected_state_two.next_state_active_policy = ActivePolicies::kNoActivePolicy; expected_state_two.next_unlock_time = TimeFromString("Mon, 1 Jan 2018 20:00 PST"); - expected_state_two.last_state_changed = time_two; AssertEqState(expected_state_two, state_two); @@ -1202,7 +1169,6 @@ expected_state_three.next_state_change_time = TimeFromString("Mon, 8 Jan 2018 18:00 PST"); expected_state_three.next_state_active_policy = ActivePolicies::kFixedLimit; - expected_state_three.last_state_changed = time_three; AssertEqState(expected_state_three, state_three); } @@ -1232,7 +1198,6 @@ expected_state_one.next_state_change_time = TimeFromString("Mon, 8 Jan 2018 10:00 PST"); expected_state_one.next_state_active_policy = ActivePolicies::kFixedLimit; - expected_state_one.last_state_changed = base::Time(); AssertEqState(expected_state_one, state_one); @@ -1254,7 +1219,6 @@ expected_state_two.next_state_active_policy = ActivePolicies::kNoActivePolicy; expected_state_two.next_unlock_time = TimeFromString("Mon, 1 Jan 2018 20:00 PST"); - expected_state_two.last_state_changed = time_two; AssertEqState(expected_state_two, state_two); @@ -1271,7 +1235,6 @@ expected_state_three.next_state_change_time = TimeFromString("Mon, 8 Jan 2018 10:00 PST"); expected_state_three.next_state_active_policy = ActivePolicies::kFixedLimit; - expected_state_three.last_state_changed = time_three; AssertEqState(expected_state_three, state_three); } @@ -1304,7 +1267,6 @@ expected_state_one.next_state_active_policy = ActivePolicies::kNoActivePolicy; expected_state_one.next_unlock_time = TimeFromString("Thu, 4 Jan 2018 6:00 BRT"); - expected_state_one.last_state_changed = base::Time(); AssertEqState(expected_state_one, state_one); @@ -1325,7 +1287,6 @@ expected_state_two.time_usage_limit_started = time_one; expected_state_two.next_state_change_time = base::Time(); expected_state_two.next_state_active_policy = ActivePolicies::kNoActivePolicy; - expected_state_two.last_state_changed = time_two; AssertEqState(expected_state_two, state_two); @@ -1351,7 +1312,6 @@ ActivePolicies::kNoActivePolicy; expected_state_three.next_unlock_time = TimeFromString("Thu, 4 Jan 2018 6:00 BRT"); - expected_state_three.last_state_changed = time_three; AssertEqState(expected_state_three, state_three); @@ -1373,7 +1333,6 @@ expected_state_four.next_state_change_time = TimeFromString("Wed, 3 Jan 2018 18:00 BRT"); expected_state_four.next_state_active_policy = ActivePolicies::kUsageLimit; - expected_state_four.last_state_changed = time_four; AssertEqState(expected_state_four, state_four); } @@ -1410,7 +1369,6 @@ expected_state_one.next_state_active_policy = ActivePolicies::kUsageLimit; expected_state_one.next_unlock_time = TimeFromString("Thu, 4 Jan 2018 6:00 BRT"); - expected_state_one.last_state_changed = base::Time(); AssertEqState(expected_state_one, state_one); @@ -1431,7 +1389,6 @@ expected_state_two.next_state_change_time = TimeFromString("Thu, 4 Jan 2018 6:00 BRT"); expected_state_two.next_state_active_policy = ActivePolicies::kUsageLimit; - expected_state_two.last_state_changed = time_two; AssertEqState(expected_state_two, state_two); @@ -1452,7 +1409,6 @@ expected_state_three.next_state_active_policy = ActivePolicies::kUsageLimit; expected_state_three.next_unlock_time = TimeFromString("Fri, 5 Jan 2018 6:00 BRT"); - expected_state_three.last_state_changed = time_three; AssertEqState(expected_state_three, state_three); @@ -1473,7 +1429,6 @@ ActivePolicies::kNoActivePolicy; expected_state_four.next_unlock_time = TimeFromString("Sat, 6 Jan 2018 6:00 BRT"); - expected_state_four.last_state_changed = time_three; AssertEqState(expected_state_four, state_four); @@ -1489,7 +1444,6 @@ expected_state_five.next_state_change_time = TimeFromString("Wed, 10 Jan 2018 6:00 BRT"); expected_state_five.next_state_active_policy = ActivePolicies::kUsageLimit; - expected_state_five.last_state_changed = time_five; AssertEqState(expected_state_five, state_five); } @@ -1523,7 +1477,6 @@ expected_state_one.next_state_active_policy = ActivePolicies::kUsageLimit; expected_state_one.next_unlock_time = TimeFromString("Thu, 4 Jan 2018 6:00 BRT"); - expected_state_one.last_state_changed = base::Time(); AssertEqState(expected_state_one, state_one); @@ -1543,7 +1496,6 @@ expected_state_two.next_state_active_policy = ActivePolicies::kNoActivePolicy; expected_state_two.next_unlock_time = TimeFromString("Fri, 5 Jan 2018 6:00 BRT"); - expected_state_two.last_state_changed = base::Time(); AssertEqState(expected_state_two, state_two); @@ -1565,7 +1517,6 @@ expected_state_three.next_state_change_time = TimeFromString("Wed, 10 Jan 2018 6:00 BRT"); expected_state_three.next_state_active_policy = ActivePolicies::kUsageLimit; - expected_state_three.last_state_changed = time_three; AssertEqState(expected_state_three, state_three); }
diff --git a/chrome/browser/chromeos/events/event_rewriter_unittest.cc b/chrome/browser/chromeos/events/event_rewriter_unittest.cc index d132da8..56c495f 100644 --- a/chrome/browser/chromeos/events/event_rewriter_unittest.cc +++ b/chrome/browser/chromeos/events/event_rewriter_unittest.cc
@@ -7,7 +7,6 @@ #include "ash/shell.h" #include "ash/sticky_keys/sticky_keys_controller.h" #include "ash/sticky_keys/sticky_keys_overlay.h" -#include "ash/test/ash_test_base.h" #include "base/command_line.h" #include "base/macros.h" #include "base/memory/ptr_util.h" @@ -18,6 +17,7 @@ #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h" #include "chrome/browser/chromeos/preferences.h" #include "chrome/common/pref_names.h" +#include "chrome/test/base/chrome_ash_test_base.h" #include "chromeos/chromeos_switches.h" #include "components/prefs/pref_member.h" #include "components/sync_preferences/testing_pref_service_syncable.h" @@ -113,7 +113,7 @@ namespace chromeos { -class EventRewriterTest : public ash::AshTestBase { +class EventRewriterTest : public ChromeAshTestBase { public: EventRewriterTest() : fake_user_manager_(new chromeos::FakeChromeUserManager), @@ -128,11 +128,11 @@ delegate_->set_pref_service_for_testing(prefs()); rewriter_ = std::make_unique<ui::EventRewriterChromeOS>(delegate_.get(), nullptr); - AshTestBase::SetUp(); + ChromeAshTestBase::SetUp(); } void TearDown() override { - AshTestBase::TearDown(); + ChromeAshTestBase::TearDown(); // Shutdown() deletes the IME mock object. chromeos::input_method::Shutdown(); } @@ -2357,7 +2357,7 @@ }; // Tests of event rewriting that depend on the Ash window manager. -class EventRewriterAshTest : public ash::AshTestBase { +class EventRewriterAshTest : public ChromeAshTestBase { public: EventRewriterAshTest() : source_(&buffer_), @@ -2406,7 +2406,7 @@ } void SetUp() override { - AshTestBase::SetUp(); + ChromeAshTestBase::SetUp(); sticky_keys_controller_ = ash::Shell::Get()->sticky_keys_controller(); delegate_ = std::make_unique<EventRewriterDelegateImpl>(nullptr); delegate_->set_pref_service_for_testing(prefs()); @@ -2419,7 +2419,7 @@ void TearDown() override { rewriter_.reset(); - AshTestBase::TearDown(); + ChromeAshTestBase::TearDown(); } protected:
diff --git a/chrome/browser/chromeos/file_manager/file_browser_handlers.cc b/chrome/browser/chromeos/file_manager/file_browser_handlers.cc index 34752e8..7a276ef 100644 --- a/chrome/browser/chromeos/file_manager/file_browser_handlers.cc +++ b/chrome/browser/chromeos/file_manager/file_browser_handlers.cc
@@ -38,6 +38,7 @@ #include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_util.h" #include "extensions/browser/lazy_background_task_queue.h" +#include "extensions/browser/lazy_context_id.h" #include "extensions/common/extension_set.h" #include "extensions/common/manifest_handlers/background_info.h" #include "extensions/common/url_pattern.h" @@ -356,7 +357,7 @@ return; } queue->AddPendingTask( - profile_, extension_->id(), + extensions::LazyContextId(profile_, extension_->id()), base::BindOnce( &FileBrowserHandlerExecutor::SetupPermissionsAndDispatchEvent, weak_ptr_factory_.GetWeakPtr(),
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc index 400fba6..bb32618 100644 --- a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc +++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
@@ -16,6 +16,7 @@ #include "components/session_manager/core/session_manager.h" #include "components/user_manager/user_manager.h" #include "services/identity/public/cpp/identity_manager.h" +#include "services/identity/public/cpp/identity_test_utils.h" #include "ui/keyboard/public/keyboard_switches.h" namespace file_manager { @@ -978,14 +979,10 @@ account_id, base::UTF8ToUTF16(info.display_name)); Profile* profile = chromeos::ProfileHelper::GetProfileByUserIdHashForTest(info.hash); - // TODO(https://crbug.com/814307): We can't use - // identity::MakePrimaryAccountAvailable from identity_test_utils.h here - // because that DCHECKs that the SigninManager isn't authenticated yet. - // Here, it *can* be already authenticated if a PRE_ test previously set up - // the user. - IdentityManagerFactory::GetForProfile(profile) - ->SetPrimaryAccountSynchronouslyForTests(info.gaia_id, info.email, - "refresh_token"); + identity::IdentityManager* identity_manager = + IdentityManagerFactory::GetForProfile(profile); + if (!identity_manager->HasPrimaryAccount()) + identity::MakePrimaryAccountAvailable(identity_manager, info.email); } GuestMode GetGuestMode() const override { return NOT_IN_GUEST_MODE; }
diff --git a/chrome/browser/chromeos/login/session/user_session_manager.cc b/chrome/browser/chromeos/login/session/user_session_manager.cc index da0a4a9..d2dc1cb 100644 --- a/chrome/browser/chromeos/login/session/user_session_manager.cc +++ b/chrome/browser/chromeos/login/session/user_session_manager.cc
@@ -2040,8 +2040,11 @@ } void UserSessionManager::StartAccountManagerMigration(Profile* profile) { - chromeos::AccountManagerMigratorFactory::GetForBrowserContext(profile) - ->Start(); + // |migrator| is nullptr for incognito profiles. + auto* migrator = + chromeos::AccountManagerMigratorFactory::GetForBrowserContext(profile); + if (migrator) + migrator->Start(); } EasyUnlockKeyManager* UserSessionManager::GetEasyUnlockKeyManager() {
diff --git a/chrome/browser/chromeos/login/signin/oauth2_login_manager.cc b/chrome/browser/chromeos/login/signin/oauth2_login_manager.cc index e8f4e539..8cf91a0d 100644 --- a/chrome/browser/chromeos/login/signin/oauth2_login_manager.cc +++ b/chrome/browser/chromeos/login/signin/oauth2_login_manager.cc
@@ -80,12 +80,6 @@ } void OAuth2LoginManager::RestoreSessionFromSavedTokens() { - // Just return if there is a pending TokenService::LoadCredentials call. - // Session restore continues in OnRefreshTokenAvailable when the call - // finishes. - if (pending_token_service_load_) - return; - ProfileOAuth2TokenService* token_service = GetTokenService(); const std::string primary_account_id = GetPrimaryAccountId(); if (token_service->RefreshTokenIsAvailable(primary_account_id)) { @@ -93,7 +87,7 @@ FireRefreshTokensLoaded(); VerifySessionCookies(); } else { - VLOG(1) << "Loading OAuth2 refresh token from database."; + VLOG(1) << "Waiting for OAuth2 refresh token being loaded from database."; // Flag user with unknown token status in case there are no saved tokens // and OnRefreshTokenAvailable is not called. Flagging it here would @@ -102,9 +96,6 @@ user_manager::UserManager::Get()->SaveUserOAuthStatus( AccountId::FromUserEmail(primary_account_id), user_manager::User::OAUTH_TOKEN_STATUS_UNKNOWN); - - pending_token_service_load_ = true; - token_service->LoadCredentials(primary_account_id); } } @@ -148,7 +139,6 @@ AccountId::FromUserEmail(user_email), user_manager::User::OAUTH2_TOKEN_STATUS_VALID); - pending_token_service_load_ = false; VerifySessionCookies(); } }
diff --git a/chrome/browser/chromeos/policy/device_cloud_external_data_policy_observer.cc b/chrome/browser/chromeos/policy/device_cloud_external_data_policy_observer.cc new file mode 100644 index 0000000..c825a496 --- /dev/null +++ b/chrome/browser/chromeos/policy/device_cloud_external_data_policy_observer.cc
@@ -0,0 +1,83 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/policy/device_cloud_external_data_policy_observer.h" + +#include "base/bind.h" +#include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h" +#include "chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.h" +#include "components/policy/core/common/external_data_fetcher.h" + +namespace policy { + +void DeviceCloudExternalDataPolicyObserver::Delegate::OnDeviceExternalDataSet( + const std::string& policy) {} + +void DeviceCloudExternalDataPolicyObserver::Delegate:: + OnDeviceExternalDataCleared(const std::string& policy) {} + +void DeviceCloudExternalDataPolicyObserver::Delegate:: + OnDeviceExternalDataFetched(const std::string& policy, + std::unique_ptr<std::string> data) {} + +DeviceCloudExternalDataPolicyObserver::Delegate::~Delegate() {} + +DeviceCloudExternalDataPolicyObserver::DeviceCloudExternalDataPolicyObserver( + PolicyService* policy_service, + const std::string& policy, + Delegate* delegate) + : policy_service_(policy_service), + policy_(policy), + delegate_(delegate), + weak_factory_(this) { + policy_service_->AddObserver(POLICY_DOMAIN_CHROME, this); +} + +DeviceCloudExternalDataPolicyObserver:: + ~DeviceCloudExternalDataPolicyObserver() { + policy_service_->RemoveObserver(POLICY_DOMAIN_CHROME, this); +} + +void DeviceCloudExternalDataPolicyObserver::OnPolicyUpdated( + const PolicyNamespace& ns, + const PolicyMap& previous, + const PolicyMap& current) { + DCHECK(ns == PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())); + + const PolicyMap::Entry* previous_entry = previous.Get(policy_); + const PolicyMap::Entry* current_entry = current.Get(policy_); + if ((!previous_entry && current_entry) || + (previous_entry && !current_entry) || + (previous_entry && current_entry && + !previous_entry->Equals(*current_entry))) { + HandleExternalDataPolicyUpdate(current_entry); + } +} + +void DeviceCloudExternalDataPolicyObserver::HandleExternalDataPolicyUpdate( + const PolicyMap::Entry* entry) { + if (!entry) { + delegate_->OnDeviceExternalDataCleared(policy_); + return; + } + + delegate_->OnDeviceExternalDataSet(policy_); + + // Invalidate any pending callbacks. They are fetching outdated data. + weak_factory_.InvalidateWeakPtrs(); + if (entry->external_data_fetcher) { + entry->external_data_fetcher->Fetch(base::BindRepeating( + &DeviceCloudExternalDataPolicyObserver::OnDeviceExternalDataFetched, + weak_factory_.GetWeakPtr())); + } else { + NOTREACHED(); + } +} + +void DeviceCloudExternalDataPolicyObserver::OnDeviceExternalDataFetched( + std::unique_ptr<std::string> data) { + delegate_->OnDeviceExternalDataFetched(policy_, std::move(data)); +} + +} // namespace policy
diff --git a/chrome/browser/chromeos/policy/device_cloud_external_data_policy_observer.h b/chrome/browser/chromeos/policy/device_cloud_external_data_policy_observer.h new file mode 100644 index 0000000..8f10e4a --- /dev/null +++ b/chrome/browser/chromeos/policy/device_cloud_external_data_policy_observer.h
@@ -0,0 +1,85 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_POLICY_DEVICE_CLOUD_EXTERNAL_DATA_POLICY_OBSERVER_H_ +#define CHROME_BROWSER_CHROMEOS_POLICY_DEVICE_CLOUD_EXTERNAL_DATA_POLICY_OBSERVER_H_ + +#include <memory> +#include <string> + +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "components/policy/core/common/policy_map.h" +#include "components/policy/core/common/policy_namespace.h" +#include "components/policy/core/common/policy_service.h" + +namespace policy { + +// Helper for implementing policies referencing external data: This class +// observes a given |policy_| and fetches the external data that it references +// for the device. Notifications are emitted when an external data reference is +// set, cleared or an external data fetch completes successfully. +// +// State is kept at runtime only: External data references that already exist +// when the class is instantiated are considered new, causing a notification to +// be emitted that an external data reference has been set and the referenced +// external data to be fetched. +class DeviceCloudExternalDataPolicyObserver : public PolicyService::Observer { + public: + class Delegate { + public: + // Invoked when an device external data reference is set. + virtual void OnDeviceExternalDataSet(const std::string& policy); + + // Invoked when the device external data reference is cleared. + virtual void OnDeviceExternalDataCleared(const std::string& policy); + + // Invoked when the device external data has been fetched. + // Failed fetches are retried and the method is called only when a fetch + // eventually succeeds. If a fetch fails permanently (e.g. because the + // external data reference specifies an invalid URL), the method is not + // called at all. + virtual void OnDeviceExternalDataFetched(const std::string& policy, + std::unique_ptr<std::string> data); + + protected: + virtual ~Delegate(); + }; + + // |policy_service| should be the device policy service. + DeviceCloudExternalDataPolicyObserver(PolicyService* policy_service, + const std::string& policy, + Delegate* delegate); + ~DeviceCloudExternalDataPolicyObserver() override; + + // PolicyService::Observer: + void OnPolicyUpdated(const PolicyNamespace& ns, + const PolicyMap& previous, + const PolicyMap& current) override; + + private: + // Handles the new policy map |entry| by canceling any external data fetch + // currently in progress, emitting a notification that an external data + // reference has been cleared (if |entry| is NULL) or set (otherwise), + // starting a new external data fetch in the latter case. + void HandleExternalDataPolicyUpdate(const PolicyMap::Entry* entry); + + void OnDeviceExternalDataFetched(std::unique_ptr<std::string> data); + + PolicyService* const policy_service_; + + // The policy that |this| observes. + const std::string policy_; + + // Delegate that takes care of policy data updates. Cannot be null. + Delegate* const delegate_; + + base::WeakPtrFactory<DeviceCloudExternalDataPolicyObserver> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(DeviceCloudExternalDataPolicyObserver); +}; + +} // namespace policy + +#endif // CHROME_BROWSER_CHROMEOS_POLICY_DEVICE_CLOUD_EXTERNAL_DATA_POLICY_OBSERVER_H_
diff --git a/chrome/browser/chromeos/policy/device_cloud_external_data_policy_observer_browsertest.cc b/chrome/browser/chromeos/policy/device_cloud_external_data_policy_observer_browsertest.cc new file mode 100644 index 0000000..fa505ad --- /dev/null +++ b/chrome/browser/chromeos/policy/device_cloud_external_data_policy_observer_browsertest.cc
@@ -0,0 +1,195 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/policy/device_cloud_external_data_policy_observer.h" + +#include <string> + +#include "base/bind.h" +#include "base/path_service.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" +#include "chrome/browser/chromeos/policy/cloud_external_data_manager_base_test_util.h" +#include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h" +#include "chrome/common/chrome_paths.h" +#include "chromeos/settings/cros_settings_names.h" +#include "components/policy/core/common/policy_service.h" +#include "components/policy/policy_constants.h" +#include "net/test/embedded_test_server/embedded_test_server.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace policy { + +namespace { + +const char kExternalDataPath[] = "policy/printers_configuration.json"; +const char kExternalDataPathUpdated[] = + "policy/printers_configuration_updated.json"; + +// The name of an External Data Policy in Device Policy. +const char* const kPolicyName = key::kDeviceNativePrinters; + +class MockDeviceCloudExternalDataPolicyObserverDelegate + : public DeviceCloudExternalDataPolicyObserver::Delegate { + public: + MockDeviceCloudExternalDataPolicyObserverDelegate() {} + + void OnDeviceExternalDataFetched(const std::string& policy, + std::unique_ptr<std::string> data) override { + OnDeviceExternalDataFetchedProxy(policy, data.get()); + } + + MOCK_METHOD1(OnDeviceExternalDataSet, void(const std::string&)); + MOCK_METHOD1(OnDeviceExternalDataCleared, void(const std::string&)); + MOCK_METHOD2(OnDeviceExternalDataFetchedProxy, + void(const std::string&, std::string*)); +}; + +} // namespace + +class DeviceCloudExternalDataPolicyObserverTest + : public DevicePolicyCrosBrowserTest { + public: + DeviceCloudExternalDataPolicyObserverTest() {} + + protected: + void SetUpOnMainThread() override { + EXPECT_TRUE(embedded_test_server()->Start()); + DevicePolicyCrosBrowserTest::SetUpOnMainThread(); + + BrowserPolicyConnectorChromeOS* policy_connector = + g_browser_process->platform_part()->browser_policy_connector_chromeos(); + ASSERT_TRUE(policy_connector); + PolicyService* policy_service = policy_connector->GetPolicyService(); + ASSERT_TRUE(policy_service->IsInitializationComplete(POLICY_DOMAIN_CHROME)); + + observer_ = std::make_unique<DeviceCloudExternalDataPolicyObserver>( + policy_service, kPolicyName, &mock_delegate_); + + policy_change_registrar_ = std::make_unique<PolicyChangeRegistrar>( + policy_service, PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())); + policy_change_registrar_->Observe( + kPolicyName, + base::BindRepeating( + &DeviceCloudExternalDataPolicyObserverTest::PolicyChangedCallback, + base::Unretained(this))); + + policy_change_waiting_run_loop_ = std::make_unique<base::RunLoop>(); + } + + void TearDownOnMainThread() override { + observer_.reset(); + policy_change_registrar_.reset(); + DevicePolicyCrosBrowserTest::TearDownOnMainThread(); + } + + void SetDeviceNativePrintersExternalData(const std::string& policy) { + device_policy() + ->payload() + .mutable_native_device_printers() + ->set_external_policy(policy); + RefreshDevicePolicy(); + WaitUntilPolicyChanged(); + } + + void ClearDeviceNativePrintersExternalData() { + device_policy()->payload().clear_native_device_printers(); + RefreshDevicePolicy(); + WaitUntilPolicyChanged(); + } + + std::string ReadExternalDataFile(const std::string& file_path) { + base::FilePath test_data_dir; + EXPECT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir)); + std::string external_data; + { + base::ScopedAllowBlockingForTesting allow_blocking; + EXPECT_TRUE(base::ReadFileToString(test_data_dir.AppendASCII(file_path), + &external_data)); + } + return external_data; + } + + MockDeviceCloudExternalDataPolicyObserverDelegate mock_delegate_; + + private: + void PolicyChangedCallback(const base::Value* old_value, + const base::Value* new_value) { + policy_change_waiting_run_loop_->Quit(); + } + + void WaitUntilPolicyChanged() { + policy_change_waiting_run_loop_->Run(); + policy_change_waiting_run_loop_.reset(new base::RunLoop()); + } + + std::unique_ptr<DeviceCloudExternalDataPolicyObserver> observer_; + std::unique_ptr<PolicyChangeRegistrar> policy_change_registrar_; + std::unique_ptr<base::RunLoop> policy_change_waiting_run_loop_; +}; + +IN_PROC_BROWSER_TEST_F(DeviceCloudExternalDataPolicyObserverTest, + DataSetAndDataClearedCalled) { + EXPECT_CALL(mock_delegate_, OnDeviceExternalDataSet(kPolicyName)); + EXPECT_CALL(mock_delegate_, OnDeviceExternalDataCleared(kPolicyName)); + + SetDeviceNativePrintersExternalData(test::ConstructExternalDataPolicy( + *embedded_test_server(), kExternalDataPath)); + ClearDeviceNativePrintersExternalData(); +} + +IN_PROC_BROWSER_TEST_F(DeviceCloudExternalDataPolicyObserverTest, PolicyIsSet) { + EXPECT_CALL(mock_delegate_, OnDeviceExternalDataSet(kPolicyName)); + + base::RunLoop run_loop; + EXPECT_CALL(mock_delegate_, + OnDeviceExternalDataFetchedProxy( + kPolicyName, testing::Pointee(testing::StrEq( + ReadExternalDataFile(kExternalDataPath))))) + .WillOnce(testing::Invoke([&run_loop](const std::string&, std::string*) { + run_loop.QuitClosure().Run(); + })); + + SetDeviceNativePrintersExternalData(test::ConstructExternalDataPolicy( + *embedded_test_server(), kExternalDataPath)); + run_loop.Run(); +} + +IN_PROC_BROWSER_TEST_F(DeviceCloudExternalDataPolicyObserverTest, + PolicyIsUpdated) { + EXPECT_CALL(mock_delegate_, OnDeviceExternalDataSet(kPolicyName)); + + base::RunLoop run_loop; + EXPECT_CALL(mock_delegate_, + OnDeviceExternalDataFetchedProxy( + kPolicyName, testing::Pointee(testing::StrEq( + ReadExternalDataFile(kExternalDataPath))))) + .WillOnce(testing::Invoke([&run_loop](const std::string&, std::string*) { + run_loop.QuitClosure().Run(); + })); + + SetDeviceNativePrintersExternalData(test::ConstructExternalDataPolicy( + *embedded_test_server(), kExternalDataPath)); + run_loop.Run(); + + EXPECT_CALL(mock_delegate_, OnDeviceExternalDataSet(kPolicyName)); + + base::RunLoop run_loop_updated; + EXPECT_CALL( + mock_delegate_, + OnDeviceExternalDataFetchedProxy( + kPolicyName, testing::Pointee(testing::StrEq( + ReadExternalDataFile(kExternalDataPathUpdated))))) + .WillOnce(testing::Invoke( + [&run_loop_updated](const std::string&, std::string*) { + run_loop_updated.QuitClosure().Run(); + })); + + SetDeviceNativePrintersExternalData(test::ConstructExternalDataPolicy( + *embedded_test_server(), kExternalDataPathUpdated)); + run_loop_updated.Run(); +} + +} // namespace policy
diff --git a/chrome/browser/chromeos/policy/remote_commands/device_command_screenshot_job_unittest.cc b/chrome/browser/chromeos/policy/remote_commands/device_command_screenshot_job_unittest.cc index 4f0ccda0..bfd8e40 100644 --- a/chrome/browser/chromeos/policy/remote_commands/device_command_screenshot_job_unittest.cc +++ b/chrome/browser/chromeos/policy/remote_commands/device_command_screenshot_job_unittest.cc
@@ -8,7 +8,6 @@ #include <utility> #include <vector> -#include "ash/test/ash_test_base.h" #include "base/json/json_writer.h" #include "base/macros.h" #include "base/run_loop.h" @@ -17,6 +16,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "base/values.h" +#include "chrome/test/base/chrome_ash_test_base.h" #include "components/policy/proto/device_management_backend.pb.h" #include "content/public/browser/browser_thread.h" #include "content/public/test/test_browser_thread_bundle.h" @@ -188,7 +188,7 @@ } // namespace -class DeviceCommandScreenshotTest : public ash::AshTestBase { +class DeviceCommandScreenshotTest : public ChromeAshTestBase { public: void VerifyResults(RemoteCommandJob* job, RemoteCommandJob::Status expected_status, @@ -197,7 +197,7 @@ protected: DeviceCommandScreenshotTest(); - // ash::AshTestBase: + // ChromeAshTestBase: void SetUp() override; void InitializeScreenshotJob(RemoteCommandJob* job, @@ -222,7 +222,7 @@ } void DeviceCommandScreenshotTest::SetUp() { - ash::AshTestBase::SetUp(); + ChromeAshTestBase::SetUp(); test_start_time_ = base::TimeTicks::Now(); }
diff --git a/chrome/browser/chromeos/policy/remote_commands/device_command_set_volume_job_unittest.cc b/chrome/browser/chromeos/policy/remote_commands/device_command_set_volume_job_unittest.cc index fc2bf6e..cb7bf33 100644 --- a/chrome/browser/chromeos/policy/remote_commands/device_command_set_volume_job_unittest.cc +++ b/chrome/browser/chromeos/policy/remote_commands/device_command_set_volume_job_unittest.cc
@@ -6,13 +6,13 @@ #include <memory> -#include "ash/test/ash_test_base.h" #include "base/bind.h" #include "base/bind_helpers.h" #include "base/json/json_writer.h" #include "base/memory/ptr_util.h" #include "base/run_loop.h" #include "base/values.h" +#include "chrome/test/base/chrome_ash_test_base.h" #include "chromeos/audio/cras_audio_handler.h" #include "testing/gtest/include/gtest/gtest.h" @@ -57,7 +57,7 @@ } // namespace -class DeviceCommandSetVolumeTest : public ash::AshTestBase { +class DeviceCommandSetVolumeTest : public ChromeAshTestBase { protected: DeviceCommandSetVolumeTest(); @@ -74,7 +74,7 @@ DeviceCommandSetVolumeTest::DeviceCommandSetVolumeTest() {} void DeviceCommandSetVolumeTest::SetUp() { - ash::AshTestBase::SetUp(); + ChromeAshTestBase::SetUp(); test_start_time_ = base::TimeTicks::Now(); }
diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.cc b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.cc index 6935fe1..70aae10 100644 --- a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.cc +++ b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.cc
@@ -11,6 +11,7 @@ #include "base/bind_helpers.h" #include "base/callback_helpers.h" #include "base/command_line.h" +#include "base/feature_list.h" #include "base/logging.h" #include "base/memory/singleton.h" #include "base/metrics/histogram_functions.h" @@ -35,6 +36,7 @@ #include "chrome/browser/policy/cloud/remote_commands_invalidator_impl.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/chrome_content_client.h" +#include "chrome/common/chrome_features.h" #include "chromeos/chromeos_switches.h" #include "components/crash/core/common/crash_key.h" #include "components/invalidation/impl/profile_invalidation_provider.h" @@ -96,6 +98,14 @@ UMA_HISTOGRAM_ENUMERATION(kUMAReregistrationResult, registration_result); } +// Returns whether user with |account_id| is a child. Returns false if user with +// |account_id| is not found. +bool IsChildUser(const AccountId& account_id) { + const user_manager::User* const user = + user_manager::UserManager::Get()->FindUser(account_id); + return user && user->GetType() == user_manager::USER_TYPE_CHILD; +} + // This class is used to subscribe for notifications that the current profile is // being shut down. class UserCloudPolicyManagerChromeOSNotifierFactory @@ -298,6 +308,11 @@ } } +bool UserCloudPolicyManagerChromeOS::RequiresOAuthTokenForChildUser() const { + return IsChildUser(account_id_) && + base::FeatureList::IsEnabled(features::kDMServerOAuthForChildUser); +} + void UserCloudPolicyManagerChromeOS::OnWildcardCheckCompleted( const std::string& username, WildcardLoginChecker::Result result) { @@ -547,9 +562,7 @@ return; // Don't apply enterprise defaults for Child user. - const user_manager::User* const user = - user_manager::UserManager::Get()->FindUser(account_id_); - if (user && user->GetType() == user_manager::USER_TYPE_CHILD) + if (IsChildUser(account_id_)) return; SetEnterpriseUsersDefaults(policy_map);
diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h index d9c17e9..5d6c23a 100644 --- a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h +++ b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h
@@ -122,7 +122,11 @@ // this method once available. // The |access_token| can then be used to authenticate the registration // request to the DMServer. - void OnAccessTokenAvailable(const std::string& access_token); + virtual void OnAccessTokenAvailable(const std::string& access_token); + + // Whether OAuth2 token is required for DMServer requests (policy fetch, + // uploading status report) for child user. + bool RequiresOAuthTokenForChildUser() const; // Returns true if the underlying CloudPolicyClient is already registered. bool IsClientRegistered() const; @@ -275,7 +279,7 @@ base::debug::StackTrace connect_callstack_; // The AccountId associated with the user whose policy is being loaded. - AccountId account_id_; + const AccountId account_id_; // The callback to invoke if the user session should be shutdown. This is // injected in the constructor to make it easier to write tests.
diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_token_forwarder.cc b/chrome/browser/chromeos/policy/user_cloud_policy_token_forwarder.cc index 1be64e09..cc0356f3 100644 --- a/chrome/browser/chromeos/policy/user_cloud_policy_token_forwarder.cc +++ b/chrome/browser/chromeos/policy/user_cloud_policy_token_forwarder.cc
@@ -4,6 +4,12 @@ #include "chrome/browser/chromeos/policy/user_cloud_policy_token_forwarder.h" +#include "base/bind.h" +#include "base/location.h" +#include "base/logging.h" +#include "base/time/clock.h" +#include "base/time/default_clock.h" +#include "base/timer/timer.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h" #include "components/policy/core/common/cloud/cloud_policy_core.h" @@ -13,14 +19,21 @@ namespace policy { +// static +constexpr base::TimeDelta UserCloudPolicyTokenForwarder::kFetchTokenRetryDelay; + UserCloudPolicyTokenForwarder::UserCloudPolicyTokenForwarder( UserCloudPolicyManagerChromeOS* manager, identity::IdentityManager* identity_manager) - : manager_(manager), identity_manager_(identity_manager) { + : manager_(manager), + identity_manager_(identity_manager), + refresh_oauth_token_timer_(std::make_unique<base::RepeatingTimer>()), + clock_(base::DefaultClock::GetInstance()), + weak_ptr_factory_(this) { // Start by waiting for the CloudPolicyService to be initialized, so that // we can check if it already has a DMToken or not. if (manager_->core()->service()->IsInitializationComplete()) { - Initialize(); + StartRequest(); } else { manager_->core()->service()->AddObserver(this); } @@ -30,18 +43,46 @@ void UserCloudPolicyTokenForwarder::Shutdown() { access_token_fetcher_.reset(); + refresh_oauth_token_timer_.reset(); manager_->core()->service()->RemoveObserver(this); } void UserCloudPolicyTokenForwarder:: OnCloudPolicyServiceInitializationCompleted() { - Initialize(); + StartRequest(); } -void UserCloudPolicyTokenForwarder::Initialize() { +bool UserCloudPolicyTokenForwarder::IsTokenFetchInProgressForTesting() const { + return access_token_fetcher_.get() != nullptr; +} + +bool UserCloudPolicyTokenForwarder::IsTokenRefreshScheduledForTesting() const { + return refresh_oauth_token_timer_ && refresh_oauth_token_timer_->IsRunning(); +} + +base::Optional<base::TimeDelta> +UserCloudPolicyTokenForwarder::GetTokenRefreshDelayForTesting() const { + return IsTokenRefreshScheduledForTesting() + ? refresh_oauth_token_timer_->GetCurrentDelay() + : base::Optional<base::TimeDelta>(); +} + +void UserCloudPolicyTokenForwarder::OverrideTimeForTesting( + const base::Clock* clock, + const base::TickClock* tick_clock, + scoped_refptr<base::SequencedTaskRunner> task_runner) { + clock_ = clock; + refresh_oauth_token_timer_ = + std::make_unique<base::RepeatingTimer>(tick_clock); + refresh_oauth_token_timer_->SetTaskRunner(task_runner); +} + +void UserCloudPolicyTokenForwarder::StartRequest() { + refresh_oauth_token_timer_->Stop(); // TODO(mnissler): Once a better way to reconfirm whether a user is on the - // login whitelist is available, there is no reason to fetch the OAuth2 token - // here if the client is already registered, so check and bail out here. + // login whitelist is available there is no reason to fetch the OAuth2 token + // for regular user here if the client is already registered. If it is not + // recurring token fetch for child user check and bail out here. identity::ScopeSet scopes; scopes.insert(GaiaConstants::kDeviceManagementServiceOAuth); scopes.insert(GaiaConstants::kOAuthWrapBridgeUserInfoScope); @@ -60,21 +101,44 @@ DCHECK(access_token_fetcher_); if (error.state() == GoogleServiceAuthError::NONE) { - manager_->OnAccessTokenAvailable(token_info.token); + oauth_token_ = std::move(token_info); + manager_->OnAccessTokenAvailable(oauth_token_->token); } else { - // This should seldom happen: if the user is signing in for the first time - // then this was an online signin and network errors are unlikely; if the - // user had already signed in before then they should have policy cached, - // and Initialize() wouldn't have been invoked. Still, something - // just went wrong (server 500, or something). Currently we don't recover in - // this case, and we'll just try to register for policy again on the next - // signin. + // This should seldom happen for initial policy fetch for regular user: if + // the user is signing in for the first time then this was an online signin + // and network errors are unlikely; if the user had already signed in before + // then they should have policy cached, and StartRequest() wouldn't have + // been invoked. Still, something just went wrong (server 500, or + // something). Currently we don't recover in this case, and we'll just try + // to register for policy again on the next signin. // TODO(joaodasilva, atwilson): consider blocking signin when this happens, // so that the user has to try again before getting into the session. That // would guarantee that a session always has fresh policy, or at least // enforces a cached policy. + // In case of child user we keep refreshing the token and failed fetch will + // be retried after some delay. } - Shutdown(); + + if (!manager_->RequiresOAuthTokenForChildUser()) { + Shutdown(); + return; + } + + // Schedule fetching fresh OAuth token after current token expiration, if + // UserCloudPolicyManagerChromeOS needs valid OAuth token all the time. + access_token_fetcher_.reset(); + // Retry after delay, if token request fails or the new token is expired. + const base::Time now = clock_->Now(); + base::TimeDelta time_to_next_refresh = + (oauth_token_ && oauth_token_->expiration_time >= now) + ? oauth_token_->expiration_time - now + : UserCloudPolicyTokenForwarder::kFetchTokenRetryDelay; + VLOG(1) << "Next OAuth token refresh for DMServer auth in: " + << time_to_next_refresh; + refresh_oauth_token_timer_->Start( + FROM_HERE, time_to_next_refresh, + base::BindRepeating(&UserCloudPolicyTokenForwarder::StartRequest, + weak_ptr_factory_.GetWeakPtr())); } } // namespace policy
diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_token_forwarder.h b/chrome/browser/chromeos/policy/user_cloud_policy_token_forwarder.h index f600ced..1a0874f 100644 --- a/chrome/browser/chromeos/policy/user_cloud_policy_token_forwarder.h +++ b/chrome/browser/chromeos/policy/user_cloud_policy_token_forwarder.h
@@ -4,14 +4,25 @@ #ifndef CHROME_BROWSER_CHROMEOS_POLICY_USER_CLOUD_POLICY_TOKEN_FORWARDER_H_ #define CHROME_BROWSER_CHROMEOS_POLICY_USER_CLOUD_POLICY_TOKEN_FORWARDER_H_ + #include <memory> #include "base/macros.h" +#include "base/memory/scoped_refptr.h" +#include "base/memory/weak_ptr.h" +#include "base/optional.h" +#include "base/time/time.h" #include "components/keyed_service/core/keyed_service.h" #include "components/policy/core/common/cloud/cloud_policy_service.h" #include "google_apis/gaia/google_service_auth_error.h" #include "services/identity/public/cpp/identity_manager.h" +namespace base { +class Clock; +class RepeatingTimer; +class SequencedTaskRunner; +} // namespace base + namespace identity { class PrimaryAccountAccessTokenFetcher; } @@ -20,15 +31,20 @@ class UserCloudPolicyManagerChromeOS; -// A PKS that observes a IdentityManager and mints the policy access -// token for the UserCloudPolicyManagerChromeOS, when the token service becomes -// ready. This service decouples the UserCloudPolicyManagerChromeOS from -// depending directly on the IdentityManager, since it is initialized -// much earlier. -class UserCloudPolicyTokenForwarder - : public KeyedService, - public CloudPolicyService::Observer { +// A PKS that observes an IdentityManager and mints the policy access +// token for the UserCloudPolicyManagerChromeOS. First token is fetched when the +// token service becomes ready. After that if needed a new token is fetched when +// the previous one is expected to expire. This service decouples the +// UserCloudPolicyManagerChromeOS from depending directly on the +// IdentityManager, since it is initialized much earlier. +class UserCloudPolicyTokenForwarder : public KeyedService, + public CloudPolicyService::Observer { public: + // Delay to token fetch retry attempt in case token fetch failed or returned + // invalid data. + static constexpr base::TimeDelta kFetchTokenRetryDelay = + base::TimeDelta::FromMinutes(5); + // The factory of this PKS depends on the factories of these two arguments, // so this object will be Shutdown() first and these pointers can be used // until that point. @@ -42,8 +58,24 @@ // CloudPolicyService::Observer: void OnCloudPolicyServiceInitializationCompleted() override; + // Returns whether OAuth token fetch is currently in progress. + bool IsTokenFetchInProgressForTesting() const; + + // Returns whether next OAuth token refresh is scheduled. + bool IsTokenRefreshScheduledForTesting() const; + + // Returns delay to next token refresh if it is scheduled. + base::Optional<base::TimeDelta> GetTokenRefreshDelayForTesting() const; + + // Overrides elements responsible for time progression to allow testing. + // Affects time calculation and timer objects. + void OverrideTimeForTesting( + const base::Clock* clock, + const base::TickClock* tick_clock, + scoped_refptr<base::SequencedTaskRunner> task_runner); + private: - void Initialize(); + void StartRequest(); void OnAccessTokenFetchCompleted(GoogleServiceAuthError error, identity::AccessTokenInfo token_info); @@ -52,6 +84,18 @@ std::unique_ptr<identity::PrimaryAccountAccessTokenFetcher> access_token_fetcher_; + // Last fetched OAuth token. + base::Optional<identity::AccessTokenInfo> oauth_token_; + + // Timer that measures time to the next OAuth token refresh. Not initialized + // if token refresh is not scheduled. + std::unique_ptr<base::RepeatingTimer> refresh_oauth_token_timer_; + + // Points to the base::DefaultClock by default. + const base::Clock* clock_; + + base::WeakPtrFactory<UserCloudPolicyTokenForwarder> weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(UserCloudPolicyTokenForwarder); };
diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_token_forwarder_unittest.cc b/chrome/browser/chromeos/policy/user_cloud_policy_token_forwarder_unittest.cc new file mode 100644 index 0000000..307c75c --- /dev/null +++ b/chrome/browser/chromeos/policy/user_cloud_policy_token_forwarder_unittest.cc
@@ -0,0 +1,425 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/policy/user_cloud_policy_token_forwarder.h" + +#include <memory> +#include <string> + +#include "base/bind.h" +#include "base/files/file_path.h" +#include "base/macros.h" +#include "base/memory/ptr_util.h" +#include "base/memory/scoped_refptr.h" +#include "base/optional.h" +#include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_feature_list.h" +#include "base/test/test_mock_time_task_runner.h" +#include "base/test/test_simple_task_runner.h" +#include "base/time/time.h" +#include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h" +#include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h" +#include "chrome/browser/signin/identity_test_environment_profile_adaptor.h" +#include "chrome/common/chrome_features.h" +#include "chrome/test/base/testing_browser_process.h" +#include "chrome/test/base/testing_profile.h" +#include "chrome/test/base/testing_profile_manager.h" +#include "chromeos/dbus/dbus_thread_manager.h" +#include "components/account_id/account_id.h" +#include "components/policy/core/common/cloud/mock_cloud_external_data_manager.h" +#include "components/policy/core/common/cloud/mock_cloud_policy_client.h" +#include "components/policy/core/common/cloud/mock_cloud_policy_service.h" +#include "components/policy/core/common/cloud/mock_cloud_policy_store.h" +#include "components/sync_preferences/pref_service_syncable.h" +#include "components/user_manager/scoped_user_manager.h" +#include "components/user_manager/user_manager.h" +#include "components/user_manager/user_type.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "google_apis/gaia/gaia_constants.h" +#include "google_apis/gaia/google_service_auth_error.h" +#include "services/identity/public/cpp/identity_manager.h" +#include "services/identity/public/cpp/identity_test_environment.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace policy { + +namespace { + +constexpr char kEmail[] = "email@gmail.com"; +constexpr char kGaiaId[] = "gaia_id"; +constexpr char kOAuthToken[] = "oauth_token"; + +constexpr base::TimeDelta kTokenLifetime = base::TimeDelta::FromMinutes(30); + +} // namespace + +// Mock of UserCloudPolicyManagerChromeOS used to verify calls from +// UserCloudPolicyTokenForwarder. +class MockUserCloudPolicyManagerChromeOS + : public UserCloudPolicyManagerChromeOS { + public: + MockUserCloudPolicyManagerChromeOS( + Profile* profile, + const AccountId& account_id, + const scoped_refptr<base::SequencedTaskRunner>& task_runner) + : UserCloudPolicyManagerChromeOS( + profile, + std::make_unique<MockCloudPolicyStore>(), + std::make_unique<MockCloudExternalDataManager>(), + base::FilePath() /* component_policy_cache_path */, + UserCloudPolicyManagerChromeOS::PolicyEnforcement::kPolicyRequired, + base::TimeDelta::FromMinutes(1) /* policy_refresh_timeout */, + base::BindOnce(&MockUserCloudPolicyManagerChromeOS::OnFatalError, + base::Unretained(this)), + account_id, + task_runner) {} + + ~MockUserCloudPolicyManagerChromeOS() override = default; + + MOCK_METHOD1(OnAccessTokenAvailable, void(const std::string&)); + + private: + void OnFatalError() {} + + DISALLOW_COPY_AND_ASSIGN(MockUserCloudPolicyManagerChromeOS); +}; + +class UserCloudPolicyTokenForwarderTest : public testing::Test { + protected: + static chromeos::FakeChromeUserManager* GetFakeUserManager() { + return static_cast<chromeos::FakeChromeUserManager*>( + user_manager::UserManager::Get()); + } + + UserCloudPolicyTokenForwarderTest() + : mock_time_task_runner_( + base::MakeRefCounted<base::TestMockTimeTaskRunner>()), + user_manager_enabler_( + std::make_unique<chromeos::FakeChromeUserManager>()), + profile_manager_(std::make_unique<TestingProfileManager>( + TestingBrowserProcess::GetGlobal())), + store_(std::make_unique<MockCloudPolicyStore>()) {} + + ~UserCloudPolicyTokenForwarderTest() override = default; + + void SetUp() override { + chromeos::DBusThreadManager::Initialize(); + ASSERT_TRUE(profile_manager_->SetUp()); + scoped_feature_list_.InitAndEnableFeature( + features::kDMServerOAuthForChildUser); + } + + void TearDown() override { + user_policy_manager_->core()->Disconnect(); + chromeos::DBusThreadManager::Shutdown(); + } + + // Creates user with given |user_type|. Initializes identity test environment + // and user policy manager. + void CreateUserWithType(user_manager::UserType user_type) { + const AccountId account_id = + AccountId::FromUserEmailGaiaId(kEmail, kGaiaId); + TestingProfile::TestingFactories factories; + IdentityTestEnvironmentProfileAdaptor:: + AppendIdentityTestEnvironmentFactories(&factories); + TestingProfile* profile = profile_manager_->CreateTestingProfile( + account_id.GetUserEmail(), + std::unique_ptr<sync_preferences::PrefServiceSyncable>(), + base::UTF8ToUTF16(account_id.GetUserEmail()), 0 /* avatar_id */, + std::string() /* supervised_user_id */, std::move(factories)); + + identity_test_env_profile_adaptor_ = + std::make_unique<IdentityTestEnvironmentProfileAdaptor>(profile); + identity_test_env_profile_adaptor_->identity_test_env() + ->MakePrimaryAccountAvailable(kEmail); + + chromeos::FakeChromeUserManager* user_manager = GetFakeUserManager(); + user_manager->AddUser(account_id); + user_manager->AddUserWithAffiliationAndTypeAndProfile( + account_id, false /* is_affiliated */, user_type, profile); + user_manager->SwitchActiveUser(account_id); + ASSERT_TRUE(user_manager->GetActiveUser()); + + user_policy_manager_ = std::make_unique<MockUserCloudPolicyManagerChromeOS>( + profile, account_id, mock_time_task_runner_); + std::unique_ptr<MockCloudPolicyClient> client = + std::make_unique<MockCloudPolicyClient>(); + CloudPolicyClient* client_ptr = client.get(); + user_policy_manager_->core()->ConnectForTesting( + std::make_unique<MockCloudPolicyService>(client_ptr, store_.get()), + std::move(client)); + } + + // Creates token forwarder for tests. Should be called after user is created + // with CreateUserWithType(). + std::unique_ptr<UserCloudPolicyTokenForwarder> CreateTokenForwarder() { + auto token_forwarder = std::make_unique<UserCloudPolicyTokenForwarder>( + user_policy_manager_.get(), + identity_test_env_profile_adaptor_->identity_test_env() + ->identity_manager()); + token_forwarder->OverrideTimeForTesting( + mock_time_task_runner_->GetMockClock(), + mock_time_task_runner_->GetMockTickClock(), mock_time_task_runner_); + return token_forwarder; + } + + // Issues OAuth token for device management scope for any pending token + // requests. Blocks waiting for the request if there are no pending requests. + void IssueOAuthToken(const std::string& token, base::Time expiration) { + identity::ScopeSet scopes; + scopes.insert(GaiaConstants::kDeviceManagementServiceOAuth); + scopes.insert(GaiaConstants::kOAuthWrapBridgeUserInfoScope); + identity_test_env_profile_adaptor_->identity_test_env() + ->WaitForAccessTokenRequestIfNecessaryAndRespondWithTokenForScopes( + token, expiration, std::string() /*id_token*/, scopes); + } + + // Issues OAuth token error for any pending token requests. Blocks waiting for + // the request if there are no pending requests. + void IssueOAuthTokenError() { + identity_test_env_profile_adaptor_->identity_test_env() + ->WaitForAccessTokenRequestIfNecessaryAndRespondWithError( + GoogleServiceAuthError( + GoogleServiceAuthError::State::SERVICE_UNAVAILABLE)); + } + + // Simulates CloudPolicyService changing state to initialized. + // CloudPolicyService waits for the store to be initialized. When + // NotifyStoreLoaded() is called the service updates its state to initialized + // and informs listeners by calling + // OnCloudPolicyServiceInitializationCompleted(). + void SimulateCloudPolicyServiceInitialized() { store_->NotifyStoreLoaded(); } + + content::TestBrowserThreadBundle thread_bundle_; + + std::unique_ptr<MockUserCloudPolicyManagerChromeOS> user_policy_manager_; + + scoped_refptr<base::TestMockTimeTaskRunner> mock_time_task_runner_; + + private: + user_manager::ScopedUserManager user_manager_enabler_; + + std::unique_ptr<TestingProfileManager> profile_manager_; + std::unique_ptr<IdentityTestEnvironmentProfileAdaptor> + identity_test_env_profile_adaptor_; + std::unique_ptr<MockCloudPolicyStore> store_; + + base::test::ScopedFeatureList scoped_feature_list_; + + DISALLOW_COPY_AND_ASSIGN(UserCloudPolicyTokenForwarderTest); +}; + +TEST_F(UserCloudPolicyTokenForwarderTest, + RegularUserWaitingForServiceInitialization) { + CreateUserWithType(user_manager::UserType::USER_TYPE_REGULAR); + + // Initialized CloudPolicyService is needed to start token fetch. + // Simulate CloudPolicyService initialization after token forwarder was + // created. Token forwarder should wait with sending request. + std::unique_ptr<UserCloudPolicyTokenForwarder> token_forwarder = + CreateTokenForwarder(); + EXPECT_FALSE(token_forwarder->IsTokenFetchInProgressForTesting()); + EXPECT_FALSE(token_forwarder->IsTokenRefreshScheduledForTesting()); + + SimulateCloudPolicyServiceInitialized(); + EXPECT_TRUE(token_forwarder->IsTokenFetchInProgressForTesting()); + EXPECT_FALSE(token_forwarder->IsTokenRefreshScheduledForTesting()); + + EXPECT_CALL(*user_policy_manager_, OnAccessTokenAvailable(kOAuthToken)) + .Times(1); + IssueOAuthToken(kOAuthToken, mock_time_task_runner_->Now() + kTokenLifetime); + EXPECT_FALSE(token_forwarder->IsTokenFetchInProgressForTesting()); + EXPECT_FALSE(token_forwarder->IsTokenRefreshScheduledForTesting()); +} + +TEST_F(UserCloudPolicyTokenForwarderTest, RegularUserServiceInitialized) { + CreateUserWithType(user_manager::UserType::USER_TYPE_REGULAR); + + // Initialized CloudPolicyService is needed to start token fetch. + // Simulate CloudPolicyService initialization before token forwarder was + // created. Token forwarder should send request right away. + SimulateCloudPolicyServiceInitialized(); + + std::unique_ptr<UserCloudPolicyTokenForwarder> token_forwarder = + CreateTokenForwarder(); + EXPECT_TRUE(token_forwarder->IsTokenFetchInProgressForTesting()); + EXPECT_FALSE(token_forwarder->IsTokenRefreshScheduledForTesting()); +} + +TEST_F(UserCloudPolicyTokenForwarderTest, + RegularUserShutdownBeforeTokenFetched) { + CreateUserWithType(user_manager::UserType::USER_TYPE_REGULAR); + + SimulateCloudPolicyServiceInitialized(); + + EXPECT_CALL(*user_policy_manager_, OnAccessTokenAvailable(kOAuthToken)) + .Times(0); + + std::unique_ptr<UserCloudPolicyTokenForwarder> token_forwarder = + CreateTokenForwarder(); + EXPECT_TRUE(token_forwarder->IsTokenFetchInProgressForTesting()); + EXPECT_FALSE(token_forwarder->IsTokenRefreshScheduledForTesting()); + + token_forwarder->Shutdown(); + EXPECT_FALSE(token_forwarder->IsTokenFetchInProgressForTesting()); + EXPECT_FALSE(token_forwarder->IsTokenRefreshScheduledForTesting()); +} + +TEST_F(UserCloudPolicyTokenForwarderTest, RegularUserTokenFetchFailed) { + CreateUserWithType(user_manager::UserType::USER_TYPE_REGULAR); + + SimulateCloudPolicyServiceInitialized(); + + std::unique_ptr<UserCloudPolicyTokenForwarder> token_forwarder = + CreateTokenForwarder(); + EXPECT_TRUE(token_forwarder->IsTokenFetchInProgressForTesting()); + EXPECT_FALSE(token_forwarder->IsTokenRefreshScheduledForTesting()); + + EXPECT_CALL(*user_policy_manager_, OnAccessTokenAvailable(kOAuthToken)) + .Times(0); + IssueOAuthTokenError(); + EXPECT_FALSE(token_forwarder->IsTokenFetchInProgressForTesting()); + EXPECT_FALSE(token_forwarder->IsTokenRefreshScheduledForTesting()); +} + +TEST_F(UserCloudPolicyTokenForwarderTest, + ChildUserWaitingForServiceInitialization) { + CreateUserWithType(user_manager::UserType::USER_TYPE_CHILD); + + // Initialized CloudPolicyService is needed to start token fetch. + // Simulate CloudPolicyService initialization after token forwarder was + // created. Token forwarder should wait with sending request. + std::unique_ptr<UserCloudPolicyTokenForwarder> token_forwarder = + CreateTokenForwarder(); + EXPECT_FALSE(token_forwarder->IsTokenFetchInProgressForTesting()); + EXPECT_FALSE(token_forwarder->IsTokenRefreshScheduledForTesting()); + + SimulateCloudPolicyServiceInitialized(); + EXPECT_TRUE(token_forwarder->IsTokenFetchInProgressForTesting()); + EXPECT_FALSE(token_forwarder->IsTokenRefreshScheduledForTesting()); + + EXPECT_CALL(*user_policy_manager_, OnAccessTokenAvailable(kOAuthToken)) + .Times(1); + IssueOAuthToken(kOAuthToken, mock_time_task_runner_->Now() + kTokenLifetime); + EXPECT_FALSE(token_forwarder->IsTokenFetchInProgressForTesting()); + EXPECT_TRUE(token_forwarder->IsTokenRefreshScheduledForTesting()); + EXPECT_EQ(token_forwarder->GetTokenRefreshDelayForTesting(), kTokenLifetime); + + token_forwarder->Shutdown(); + EXPECT_FALSE(token_forwarder->IsTokenFetchInProgressForTesting()); + EXPECT_FALSE(token_forwarder->IsTokenRefreshScheduledForTesting()); +} + +TEST_F(UserCloudPolicyTokenForwarderTest, ChildUserServiceInitialized) { + CreateUserWithType(user_manager::UserType::USER_TYPE_CHILD); + + // Initialized CloudPolicyService is needed to start token fetch. + // Simulate CloudPolicyService initialization before token forwarder was + // created. Token forwarder should send request right away. + SimulateCloudPolicyServiceInitialized(); + + std::unique_ptr<UserCloudPolicyTokenForwarder> token_forwarder = + CreateTokenForwarder(); + EXPECT_TRUE(token_forwarder->IsTokenFetchInProgressForTesting()); + EXPECT_FALSE(token_forwarder->IsTokenRefreshScheduledForTesting()); +} + +TEST_F(UserCloudPolicyTokenForwarderTest, ChildUserShutdownBeforeTokenFetched) { + CreateUserWithType(user_manager::UserType::USER_TYPE_CHILD); + + SimulateCloudPolicyServiceInitialized(); + + EXPECT_CALL(*user_policy_manager_.get(), OnAccessTokenAvailable(kOAuthToken)) + .Times(0); + + std::unique_ptr<UserCloudPolicyTokenForwarder> token_forwarder = + CreateTokenForwarder(); + EXPECT_TRUE(token_forwarder->IsTokenFetchInProgressForTesting()); + EXPECT_FALSE(token_forwarder->IsTokenRefreshScheduledForTesting()); + + token_forwarder->Shutdown(); + EXPECT_FALSE(token_forwarder->IsTokenFetchInProgressForTesting()); + EXPECT_FALSE(token_forwarder->IsTokenRefreshScheduledForTesting()); +} + +TEST_F(UserCloudPolicyTokenForwarderTest, ChildUserExpiredToken) { + CreateUserWithType(user_manager::UserType::USER_TYPE_CHILD); + + SimulateCloudPolicyServiceInitialized(); + + std::unique_ptr<UserCloudPolicyTokenForwarder> token_forwarder = + CreateTokenForwarder(); + + EXPECT_CALL(*user_policy_manager_, OnAccessTokenAvailable(kOAuthToken)) + .Times(1); + IssueOAuthToken(kOAuthToken, mock_time_task_runner_->Now() - kTokenLifetime); + EXPECT_FALSE(token_forwarder->IsTokenFetchInProgressForTesting()); + EXPECT_TRUE(token_forwarder->IsTokenRefreshScheduledForTesting()); + // If the token is expired then next token fetch is scheduled with the default + // retry delay. + EXPECT_EQ(token_forwarder->GetTokenRefreshDelayForTesting(), + UserCloudPolicyTokenForwarder::kFetchTokenRetryDelay); + + token_forwarder->Shutdown(); + EXPECT_FALSE(token_forwarder->IsTokenFetchInProgressForTesting()); + EXPECT_FALSE(token_forwarder->IsTokenRefreshScheduledForTesting()); +} + +TEST_F(UserCloudPolicyTokenForwarderTest, ChildUserTokenFetchFailed) { + CreateUserWithType(user_manager::UserType::USER_TYPE_CHILD); + + SimulateCloudPolicyServiceInitialized(); + + EXPECT_CALL(*user_policy_manager_, OnAccessTokenAvailable(kOAuthToken)) + .Times(0); + + std::unique_ptr<UserCloudPolicyTokenForwarder> token_forwarder = + CreateTokenForwarder(); + + IssueOAuthTokenError(); + EXPECT_FALSE(token_forwarder->IsTokenFetchInProgressForTesting()); + EXPECT_TRUE(token_forwarder->IsTokenRefreshScheduledForTesting()); + // If the token fetch fails then next token fetch is scheduled with the + // default retry delay. + EXPECT_EQ(token_forwarder->GetTokenRefreshDelayForTesting(), + UserCloudPolicyTokenForwarder::kFetchTokenRetryDelay); + + token_forwarder->Shutdown(); + EXPECT_FALSE(token_forwarder->IsTokenFetchInProgressForTesting()); + EXPECT_FALSE(token_forwarder->IsTokenRefreshScheduledForTesting()); +} + +TEST_F(UserCloudPolicyTokenForwarderTest, ChildUserRecurringTokenFetch) { + CreateUserWithType(user_manager::UserType::USER_TYPE_CHILD); + SimulateCloudPolicyServiceInitialized(); + std::unique_ptr<UserCloudPolicyTokenForwarder> token_forwarder = + CreateTokenForwarder(); + + // First token fetch should schedule another fetch when token lifetime ends. + EXPECT_CALL(*user_policy_manager_, OnAccessTokenAvailable(kOAuthToken)) + .Times(1); + IssueOAuthToken(kOAuthToken, mock_time_task_runner_->Now() + kTokenLifetime); + EXPECT_EQ(token_forwarder->GetTokenRefreshDelayForTesting(), kTokenLifetime); + + // Advance the time long enough that new token request is posted. + mock_time_task_runner_->FastForwardBy(kTokenLifetime); + EXPECT_TRUE(token_forwarder->IsTokenFetchInProgressForTesting()); + EXPECT_FALSE(token_forwarder->IsTokenRefreshScheduledForTesting()); + + // Issue new token and observe that new fetch was scheduled (different token + // lifetime). + EXPECT_CALL(*user_policy_manager_, OnAccessTokenAvailable(kOAuthToken)) + .Times(1); + IssueOAuthToken(kOAuthToken, + mock_time_task_runner_->Now() + kTokenLifetime * 2); + EXPECT_FALSE(token_forwarder->IsTokenFetchInProgressForTesting()); + EXPECT_TRUE(token_forwarder->IsTokenRefreshScheduledForTesting()); + EXPECT_EQ(token_forwarder->GetTokenRefreshDelayForTesting(), + kTokenLifetime * 2); + + token_forwarder->Shutdown(); +} + +} // namespace policy
diff --git a/chrome/browser/devtools/device/android_device_manager.cc b/chrome/browser/devtools/device/android_device_manager.cc index 8dcb5b60..2d6c4ed 100644 --- a/chrome/browser/devtools/device/android_device_manager.cc +++ b/chrome/browser/devtools/device/android_device_manager.cc
@@ -540,10 +540,9 @@ if (!thread_) return; // Shut down thread on a thread other than UI so it can join a thread. - base::PostTaskWithTraits( - FROM_HERE, - {base::WithBaseSyncPrimitives(), base::TaskPriority::BEST_EFFORT}, - base::BindOnce(&HandlerThread::StopThread, thread_)); + base::PostTaskWithTraits(FROM_HERE, + {base::MayBlock(), base::TaskPriority::BEST_EFFORT}, + base::BindOnce(&HandlerThread::StopThread, thread_)); } // static
diff --git a/chrome/browser/devtools/devtools_embedder_message_dispatcher.cc b/chrome/browser/devtools/devtools_embedder_message_dispatcher.cc index 46fe046..7c0aff8 100644 --- a/chrome/browser/devtools/devtools_embedder_message_dispatcher.cc +++ b/chrome/browser/devtools/devtools_embedder_message_dispatcher.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/devtools/devtools_embedder_message_dispatcher.h" +#include <memory> + #include "base/bind.h" #include "base/values.h" @@ -102,7 +104,7 @@ return true; } -} // namespace +} // namespace /** * Dispatcher for messages sent from the frontend running in an @@ -151,10 +153,10 @@ }; // static -DevToolsEmbedderMessageDispatcher* +std::unique_ptr<DevToolsEmbedderMessageDispatcher> DevToolsEmbedderMessageDispatcher::CreateForDevToolsFrontend( Delegate* delegate) { - DispatcherImpl* d = new DispatcherImpl(); + auto d = std::make_unique<DispatcherImpl>(); d->RegisterHandler("bringToFront", &Delegate::ActivateWindow, delegate); d->RegisterHandler("closeWindow", &Delegate::CloseWindow, delegate);
diff --git a/chrome/browser/devtools/devtools_embedder_message_dispatcher.h b/chrome/browser/devtools/devtools_embedder_message_dispatcher.h index 7c1a20bb..db79338 100644 --- a/chrome/browser/devtools/devtools_embedder_message_dispatcher.h +++ b/chrome/browser/devtools/devtools_embedder_message_dispatcher.h
@@ -6,6 +6,7 @@ #define CHROME_BROWSER_DEVTOOLS_DEVTOOLS_EMBEDDER_MESSAGE_DISPATCHER_H_ #include <map> +#include <memory> #include <string> #include "base/callback.h" @@ -109,8 +110,8 @@ const std::string& method, const base::ListValue* params) = 0; - static DevToolsEmbedderMessageDispatcher* CreateForDevToolsFrontend( - Delegate* delegate); + static std::unique_ptr<DevToolsEmbedderMessageDispatcher> + CreateForDevToolsFrontend(Delegate* delegate); }; #endif // CHROME_BROWSER_DEVTOOLS_DEVTOOLS_EMBEDDER_MESSAGE_DISPATCHER_H_
diff --git a/chrome/browser/devtools/devtools_ui_bindings.cc b/chrome/browser/devtools/devtools_ui_bindings.cc index 285d9829..b2bb8790 100644 --- a/chrome/browser/devtools/devtools_ui_bindings.cc +++ b/chrome/browser/devtools/devtools_ui_bindings.cc
@@ -544,8 +544,8 @@ web_contents_); // Register on-load actions. - embedder_message_dispatcher_.reset( - DevToolsEmbedderMessageDispatcher::CreateForDevToolsFrontend(this)); + embedder_message_dispatcher_ = + DevToolsEmbedderMessageDispatcher::CreateForDevToolsFrontend(this); } DevToolsUIBindings::~DevToolsUIBindings() {
diff --git a/chrome/browser/download/notification/download_notification_interactive_uitest.cc b/chrome/browser/download/notification/download_notification_interactive_uitest.cc index c959179..bdaa5510 100644 --- a/chrome/browser/download/notification/download_notification_interactive_uitest.cc +++ b/chrome/browser/download/notification/download_notification_interactive_uitest.cc
@@ -40,6 +40,7 @@ #include "net/test/embedded_test_server/embedded_test_server.h" #include "net/test/url_request/url_request_slow_download_job.h" #include "services/identity/public/cpp/identity_manager.h" +#include "services/identity/public/cpp/identity_test_utils.h" #include "ui/base/l10n/l10n_util.h" #include "url/gurl.h" @@ -877,14 +878,11 @@ base::UTF8ToUTF16(info.display_name)); Profile* profile = chromeos::ProfileHelper::GetProfileByUserIdHashForTest(info.hash); - // TODO(https://crbug.com/814307): We can't use - // identity::MakePrimaryAccountAvailable from identity_test_utils.h here - // because that DCHECKs that the SigninManager isn't authenticated yet. - // Here, it *can* be already authenticated if a PRE_ test previously set up - // the user. - IdentityManagerFactory::GetForProfile(profile) - ->SetPrimaryAccountSynchronouslyForTests(info.gaia_id, info.email, - "refresh_token"); + + identity::IdentityManager* identity_manager = + IdentityManagerFactory::GetForProfile(profile); + if (!identity_manager->HasPrimaryAccount()) + identity::MakePrimaryAccountAvailable(identity_manager, info.email); } std::unique_ptr<NotificationDisplayServiceTester> display_service1_;
diff --git a/chrome/browser/extensions/api/feedback_private/chrome_feedback_private_delegate.cc b/chrome/browser/extensions/api/feedback_private/chrome_feedback_private_delegate.cc index 086796d4..eeab5b33 100644 --- a/chrome/browser/extensions/api/feedback_private/chrome_feedback_private_delegate.cc +++ b/chrome/browser/extensions/api/feedback_private/chrome_feedback_private_delegate.cc
@@ -172,10 +172,12 @@ system_logs::SysLogsFetcherCallback callback) const { if (!original_sys_logs || !system_logs::ContainsIwlwifiLogs(original_sys_logs.get())) { + VLOG(1) << "WiFi dump logs are not present."; std::move(callback).Run(std::move(original_sys_logs)); return; } + VLOG(1) << "Fetching WiFi dump logs."; system_logs::SystemLogsFetcher* fetcher = new system_logs::SystemLogsFetcher(true /* scrub_data */); fetcher->AddSource(std::make_unique<system_logs::IwlwifiDumpLogSource>());
diff --git a/chrome/browser/extensions/devtools_util.cc b/chrome/browser/extensions/devtools_util.cc index 1435663..2936711b 100644 --- a/chrome/browser/extensions/devtools_util.cc +++ b/chrome/browser/extensions/devtools_util.cc
@@ -8,6 +8,7 @@ #include "chrome/browser/profiles/profile.h" #include "extensions/browser/extension_host.h" #include "extensions/browser/lazy_background_task_queue.h" +#include "extensions/browser/lazy_context_id.h" #include "extensions/browser/process_manager.h" #include "extensions/common/extension.h" @@ -34,7 +35,8 @@ std::make_unique<LazyContextTaskQueue::ContextInfo>(host)); } else { LazyBackgroundTaskQueue::Get(profile)->AddPendingTask( - profile, extension->id(), base::BindOnce(&InspectExtensionHost)); + LazyContextId(profile, extension->id()), + base::BindOnce(&InspectExtensionHost)); } }
diff --git a/chrome/browser/extensions/extension_system_factory.cc b/chrome/browser/extensions/extension_system_factory.cc index fbfe42d..1375bf2 100644 --- a/chrome/browser/extensions/extension_system_factory.cc +++ b/chrome/browser/extensions/extension_system_factory.cc
@@ -9,8 +9,7 @@ #include "chrome/browser/extensions/install_verifier_factory.h" #include "chrome/browser/policy/profile_policy_connector_factory.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" -#include "chrome/browser/signin/signin_manager_factory.h" +#include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/ui/global_error/global_error_service_factory.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" #include "extensions/browser/declarative_user_script_manager_factory.h" @@ -56,9 +55,8 @@ DependsOn(DeclarativeUserScriptManagerFactory::GetInstance()); DependsOn(EventRouterFactory::GetInstance()); // This depends on ExtensionDownloader, which depends on - // ProfileOAuth2TokenService and SigninManager for webstore authentication. - DependsOn(ProfileOAuth2TokenServiceFactory::GetInstance()); - DependsOn(SigninManagerFactory::GetInstance()); + // IdentityManager for webstore authentication. + DependsOn(IdentityManagerFactory::GetInstance()); } ExtensionSystemSharedFactory::~ExtensionSystemSharedFactory() {
diff --git a/chrome/browser/extensions/extension_util.cc b/chrome/browser/extensions/extension_util.cc index 7a66177..24f465f5f 100644 --- a/chrome/browser/extensions/extension_util.cc +++ b/chrome/browser/extensions/extension_util.cc
@@ -21,6 +21,7 @@ #include "chrome/browser/extensions/shared_module_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/webui/extensions/extension_icon_source.h" #include "chrome/browser/web_applications/extensions/bookmark_app_util.h" #include "chrome/common/chrome_features.h" @@ -376,5 +377,12 @@ web_contents->GetMainFrame()->GetLastCommittedURL()); } +bool IsWebContentsInAppWindow(content::WebContents* web_contents) { + // TODO(loyso): Unify this check as a util (including + // MaybeCreateHostedAppController). + Browser* browser = chrome::FindBrowserWithWebContents(web_contents); + return browser && browser->hosted_app_controller(); +} + } // namespace util } // namespace extensions
diff --git a/chrome/browser/extensions/extension_util.h b/chrome/browser/extensions/extension_util.h index 8e56d09..c395032 100644 --- a/chrome/browser/extensions/extension_util.h +++ b/chrome/browser/extensions/extension_util.h
@@ -17,6 +17,7 @@ namespace content { class BrowserContext; +class WebContents; } namespace gfx { @@ -125,6 +126,10 @@ // if there are none or the tab's is not secure. const Extension* GetPwaForSecureActiveTab(Browser* browser); +// Returns true if the |web_contents| belongs to a browser that is a windowed +// app. +bool IsWebContentsInAppWindow(content::WebContents* web_contents); + } // namespace util } // namespace extensions
diff --git a/chrome/browser/extensions/system_display/display_info_provider_chromeos_unittest.cc b/chrome/browser/extensions/system_display/display_info_provider_chromeos_unittest.cc index 77f245e..e9c08635 100644 --- a/chrome/browser/extensions/system_display/display_info_provider_chromeos_unittest.cc +++ b/chrome/browser/extensions/system_display/display_info_provider_chromeos_unittest.cc
@@ -12,7 +12,6 @@ #include "ash/public/cpp/ash_switches.h" #include "ash/public/interfaces/constants.mojom.h" #include "ash/shell.h" -#include "ash/test/ash_test_base.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "base/command_line.h" #include "base/macros.h" @@ -20,6 +19,7 @@ #include "base/strings/stringprintf.h" #include "chrome/browser/extensions/system_display/display_info_provider_chromeos.h" #include "chrome/browser/ui/ash/tablet_mode_client.h" +#include "chrome/test/base/chrome_ash_test_base.h" #include "content/public/test/test_service_manager_context.h" #include "extensions/common/api/system_display.h" #include "services/service_manager/public/cpp/connector.h" @@ -46,7 +46,7 @@ std::move(callback).Run(); } -class DisplayInfoProviderChromeosTest : public ash::AshTestBase { +class DisplayInfoProviderChromeosTest : public ChromeAshTestBase { public: DisplayInfoProviderChromeosTest() {} @@ -56,7 +56,7 @@ base::CommandLine::ForCurrentProcess()->AppendSwitch( switches::kUseFirstDisplayAsInternal); - ash::AshTestBase::SetUp(); + ChromeAshTestBase::SetUp(); // Note: for now we have two instances of CrosDisplayConfig, one owned by // ash::Shell and this one. Since CrosDisplayConfig just provides an
diff --git a/chrome/browser/extensions/updater/chrome_extension_downloader_factory.cc b/chrome/browser/extensions/updater/chrome_extension_downloader_factory.cc index 61f92d7..43095db 100644 --- a/chrome/browser/extensions/updater/chrome_extension_downloader_factory.cc +++ b/chrome/browser/extensions/updater/chrome_extension_downloader_factory.cc
@@ -11,14 +11,13 @@ #include "chrome/browser/extensions/updater/extension_updater_switches.h" #include "chrome/browser/google/google_brand.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" -#include "chrome/browser/signin/signin_manager_factory.h" -#include "components/signin/core/browser/profile_oauth2_token_service.h" +#include "chrome/browser/signin/identity_manager_factory.h" #include "components/signin/core/browser/signin_manager.h" #include "components/update_client/update_query_params.h" #include "content/public/browser/storage_partition.h" #include "content/public/common/service_manager_connection.h" #include "extensions/browser/updater/extension_downloader.h" +#include "services/identity/public/cpp/identity_manager.h" #include "services/network/public/cpp/shared_url_loader_factory.h" using extensions::ExtensionDownloader; @@ -68,15 +67,11 @@ // ExtensionUpdater is owned by ExtensionService. // ExtensionService is owned by ExtensionSystemImpl::Shared. // ExtensionSystemImpl::Shared is a KeyedService. Its factory - // (ExtensionSystemSharedFactory) specifies that it depends on SigninManager - // and ProfileOAuth2TokenService. - // Hence, the SigninManager and ProfileOAuth2TokenService instances are - // guaranteed to outlive |downloader|. + // (ExtensionSystemSharedFactory) specifies that it depends on + // IdentityManager. Hence, the IdentityManager instance is guaranteed to + // outlive |downloader|. // TODO(843519): Make this lifetime relationship more explicit/cleaner. - downloader->SetWebstoreAuthenticationCapabilities( - base::BindRepeating( - &SigninManagerBase::GetAuthenticatedAccountId, - base::Unretained(SigninManagerFactory::GetForProfile(profile))), - ProfileOAuth2TokenServiceFactory::GetForProfile(profile)); + downloader->SetIdentityManager( + IdentityManagerFactory::GetForProfile(profile)); return downloader; }
diff --git a/chrome/browser/extensions/updater/extension_updater_unittest.cc b/chrome/browser/extensions/updater/extension_updater_unittest.cc index 2745a560..f318867 100644 --- a/chrome/browser/extensions/updater/extension_updater_unittest.cc +++ b/chrome/browser/extensions/updater/extension_updater_unittest.cc
@@ -67,12 +67,12 @@ #include "extensions/common/extension.h" #include "extensions/common/extension_urls.h" #include "extensions/common/manifest_constants.h" -#include "google_apis/gaia/fake_oauth2_token_service.h" #include "net/base/backoff_entry.h" #include "net/base/escape.h" #include "net/base/load_flags.h" #include "net/http/http_request_headers.h" #include "services/data_decoder/public/cpp/test_data_decoder_service.h" +#include "services/identity/public/cpp/identity_test_environment.h" #include "services/network/public/cpp/simple_url_loader.h" #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" #include "services/network/test/test_url_loader_factory.h" @@ -312,7 +312,6 @@ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) : prefs_(prefs), pending_extension_manager_(prefs->profile()), - fake_account_id_("bobloblaw@lawblog.example.com"), downloader_delegate_override_(NULL), test_shared_url_loader_factory_(url_loader_factory) {} @@ -334,11 +333,11 @@ PrefService* pref_service() { return prefs_->pref_service(); } - FakeOAuth2TokenService* fake_token_service() { - return fake_token_service_.get(); + identity::IdentityTestEnvironment* identity_test_env() { + return identity_test_env_.get(); } - const std::string& fake_account_id() { return fake_account_id_; } + const std::string& account_id() { return account_info_.account_id; } // Creates test extensions and inserts them into list. The name and // version are all based on their index. If |update_url| is non-null, it @@ -396,20 +395,18 @@ std::unique_ptr<ExtensionDownloader> CreateExtensionDownloaderWithIdentity( ExtensionDownloaderDelegate* delegate) { - fake_token_service_.reset(new FakeOAuth2TokenService()); - fake_token_service_->AddAccount(fake_account_id_); + identity_test_env_ = std::make_unique<identity::IdentityTestEnvironment>(); + account_info_ = identity_test_env_->MakePrimaryAccountAvailable( + "bobloblaw@lawblog.example.com"); std::unique_ptr<ExtensionDownloader> downloader( CreateExtensionDownloader(delegate)); - downloader->SetWebstoreAuthenticationCapabilities( - base::BindRepeating(&MockService::fake_account_id, - base::Unretained(this)), - fake_token_service_.get()); + downloader->SetIdentityManager(identity_test_env_->identity_manager()); return downloader; } - std::string fake_account_id_; - std::unique_ptr<FakeOAuth2TokenService> fake_token_service_; + AccountInfo account_info_; + std::unique_ptr<identity::IdentityTestEnvironment> identity_test_env_; ExtensionDownloaderDelegate* downloader_delegate_override_; @@ -1598,11 +1595,19 @@ net::HTTP_FORBIDDEN); delegate.Wait(); - if (service->fake_token_service()) { - service->fake_token_service()->IssueAllTokensForAccount( - service->fake_account_id(), - OAuth2AccessTokenConsumer::TokenResponse( - kFakeOAuth2Token, base::Time::Now(), std::string())); + // Only call out to WaitForAccessTokenRequest(...) method below if + // HTTPS is in use in a google domain and oauth is explicitly enabled. + // Otherwise, test will await an access token request that have not + // (and will not) happen. + // + // Note that in case the condition below isn't satisfied, the download + // proceeds normally, but the request does not carry an 'Authorization' + // HTTP header. + if (enable_oauth2 && test_url.DomainIs("google.com") && + test_url.SchemeIsCryptographic()) { + service->identity_test_env() + ->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken( + service->account_id(), kFakeOAuth2Token, base::Time::Now()); } bool using_oauth2 = false;
diff --git a/chrome/browser/media/webrtc/desktop_media_list_ash_unittest.cc b/chrome/browser/media/webrtc/desktop_media_list_ash_unittest.cc index 00bb648..dfc973b 100644 --- a/chrome/browser/media/webrtc/desktop_media_list_ash_unittest.cc +++ b/chrome/browser/media/webrtc/desktop_media_list_ash_unittest.cc
@@ -4,7 +4,6 @@ #include "chrome/browser/media/webrtc/desktop_media_list_ash.h" -#include "ash/test/ash_test_base.h" #include "base/location.h" #include "base/macros.h" #include "base/message_loop/message_loop.h" @@ -13,6 +12,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" #include "chrome/browser/media/webrtc/desktop_media_list_observer.h" +#include "chrome/test/base/chrome_ash_test_base.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/aura/window.h" @@ -33,7 +33,7 @@ void(DesktopMediaList* list, int index)); }; -class DesktopMediaListAshTest : public ash::AshTestBase { +class DesktopMediaListAshTest : public ChromeAshTestBase { public: DesktopMediaListAshTest() {} ~DesktopMediaListAshTest() override {} @@ -41,7 +41,7 @@ void TearDown() override { // Reset the unique_ptr so the list stops refreshing. list_.reset(); - ash::AshTestBase::TearDown(); + ChromeAshTestBase::TearDown(); } void CreateList(content::DesktopMediaID::Type type) {
diff --git a/chrome/browser/media/webrtc/media_stream_devices_controller.cc b/chrome/browser/media/webrtc/media_stream_devices_controller.cc index 7d14694..d173dcac3 100644 --- a/chrome/browser/media/webrtc/media_stream_devices_controller.cc +++ b/chrome/browser/media/webrtc/media_stream_devices_controller.cc
@@ -56,9 +56,6 @@ // |request|. bool ContentTypeIsRequested(ContentSettingsType type, const content::MediaStreamRequest& request) { - if (request.request_type == content::MEDIA_OPEN_DEVICE_PEPPER_ONLY) - return true; - if (type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC) return request.audio_type == content::MEDIA_DEVICE_AUDIO_CAPTURE;
diff --git a/chrome/browser/media/webrtc/media_stream_devices_controller_browsertest.cc b/chrome/browser/media/webrtc/media_stream_devices_controller_browsertest.cc index 34c002c..cae8cb5 100644 --- a/chrome/browser/media/webrtc/media_stream_devices_controller_browsertest.cc +++ b/chrome/browser/media/webrtc/media_stream_devices_controller_browsertest.cc
@@ -898,3 +898,35 @@ EXPECT_EQ(TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED, GetContentSettings()->GetMicrophoneCameraState()); } + +IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest, + PepperAudioRequestNoCamera) { + MediaCaptureDevicesDispatcher::GetInstance()->SetTestVideoCaptureDevices({}); + InitWithUrl(GURL("chrome://version")); + RequestPermissions( + GetWebContents(), + CreateRequestWithType(example_audio_id(), std::string(), + content::MEDIA_OPEN_DEVICE_PEPPER_ONLY), + base::BindOnce(&MediaStreamDevicesControllerTest::OnMediaStreamResponse, + base::Unretained(this))); + + EXPECT_EQ(content::MEDIA_DEVICE_OK, media_stream_result()); + EXPECT_TRUE(CheckDevicesListContains(content::MEDIA_DEVICE_AUDIO_CAPTURE)); + EXPECT_FALSE(CheckDevicesListContains(content::MEDIA_DEVICE_VIDEO_CAPTURE)); +} + +IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest, + PepperVideoRequestNoMic) { + MediaCaptureDevicesDispatcher::GetInstance()->SetTestAudioCaptureDevices({}); + InitWithUrl(GURL("chrome://version")); + RequestPermissions( + GetWebContents(), + CreateRequestWithType(std::string(), example_video_id(), + content::MEDIA_OPEN_DEVICE_PEPPER_ONLY), + base::BindOnce(&MediaStreamDevicesControllerTest::OnMediaStreamResponse, + base::Unretained(this))); + + EXPECT_EQ(content::MEDIA_DEVICE_OK, media_stream_result()); + EXPECT_FALSE(CheckDevicesListContains(content::MEDIA_DEVICE_AUDIO_CAPTURE)); + EXPECT_TRUE(CheckDevicesListContains(content::MEDIA_DEVICE_VIDEO_CAPTURE)); +}
diff --git a/chrome/browser/metrics/desktop_session_duration/desktop_profile_session_durations_service_factory.cc b/chrome/browser/metrics/desktop_session_duration/desktop_profile_session_durations_service_factory.cc index 7b8e2eb1..eeda368 100644 --- a/chrome/browser/metrics/desktop_session_duration/desktop_profile_session_durations_service_factory.cc +++ b/chrome/browser/metrics/desktop_session_duration/desktop_profile_session_durations_service_factory.cc
@@ -56,6 +56,10 @@ content::BrowserContext* DesktopProfileSessionDurationsServiceFactory::GetBrowserContextToUse( content::BrowserContext* context) const { + // Session time in incognito is counted towards the session time in the + // regular profile. That means that for a user that is signed in and syncing + // in their regular profile and that is browsing in incognito profile, + // Chromium will record the session time as being signed in and syncing. return chrome::GetBrowserContextRedirectedInIncognito(context); }
diff --git a/chrome/browser/metrics/thread_watcher.cc b/chrome/browser/metrics/thread_watcher.cc index e30b515f..5a28d60 100644 --- a/chrome/browser/metrics/thread_watcher.cc +++ b/chrome/browser/metrics/thread_watcher.cc
@@ -867,7 +867,7 @@ if (startup_watchdog->IsJoinable()) { // Allow the watchdog thread to shutdown on UI. Watchdog thread shutdowns // very fast. - base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope allow_thread_join; + base::ThreadRestrictions::ScopedAllowIO allow_io; delete startup_watchdog; return; }
diff --git a/chrome/browser/net/proxy_config_monitor.cc b/chrome/browser/net/proxy_config_monitor.cc index 2d08d23e..f1e2875 100644 --- a/chrome/browser/net/proxy_config_monitor.cc +++ b/chrome/browser/net/proxy_config_monitor.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/net/proxy_config_monitor.h" +#include <utility> + #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "chrome/browser/browser_process.h" @@ -35,16 +37,16 @@ // state. #if defined(OS_CHROMEOS) if (chromeos::ProfileHelper::IsSigninProfile(profile)) { - pref_proxy_config_tracker_.reset( + pref_proxy_config_tracker_ = ProxyServiceFactory::CreatePrefProxyConfigTrackerOfLocalState( - g_browser_process->local_state())); + g_browser_process->local_state()); } #endif // defined(OS_CHROMEOS) if (!pref_proxy_config_tracker_) { - pref_proxy_config_tracker_.reset( + pref_proxy_config_tracker_ = ProxyServiceFactory::CreatePrefProxyConfigTrackerOfProfile( - profile->GetPrefs(), g_browser_process->local_state())); + profile->GetPrefs(), g_browser_process->local_state()); } proxy_config_service_ = ProxyServiceFactory::CreateProxyConfigService( @@ -57,9 +59,9 @@ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || !BrowserThread::IsThreadInitialized(BrowserThread::UI)); - pref_proxy_config_tracker_.reset( + pref_proxy_config_tracker_ = ProxyServiceFactory::CreatePrefProxyConfigTrackerOfLocalState( - local_state)); + local_state); proxy_config_service_ = ProxyServiceFactory::CreateProxyConfigService( pref_proxy_config_tracker_.get());
diff --git a/chrome/browser/net/proxy_config_monitor.h b/chrome/browser/net/proxy_config_monitor.h index 172e71b0..c6c1fa51 100644 --- a/chrome/browser/net/proxy_config_monitor.h +++ b/chrome/browser/net/proxy_config_monitor.h
@@ -6,6 +6,7 @@ #define CHROME_BROWSER_NET_PROXY_CONFIG_MONITOR_H_ #include <memory> +#include <string> #include "base/macros.h" #include "build/buildflag.h"
diff --git a/chrome/browser/net/proxy_service_factory.cc b/chrome/browser/net/proxy_service_factory.cc index 47c9f2094..5b436ce9 100644 --- a/chrome/browser/net/proxy_service_factory.cc +++ b/chrome/browser/net/proxy_service_factory.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/net/proxy_service_factory.h" +#include <utility> + #include "base/task/post_task.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" @@ -47,26 +49,27 @@ } // static -PrefProxyConfigTracker* +std::unique_ptr<PrefProxyConfigTracker> ProxyServiceFactory::CreatePrefProxyConfigTrackerOfProfile( PrefService* profile_prefs, PrefService* local_state_prefs) { #if defined(OS_CHROMEOS) - return new chromeos::ProxyConfigServiceImpl(profile_prefs, local_state_prefs, - nullptr); + return std::make_unique<chromeos::ProxyConfigServiceImpl>( + profile_prefs, local_state_prefs, nullptr); #else - return new PrefProxyConfigTrackerImpl(profile_prefs, nullptr); + return std::make_unique<PrefProxyConfigTrackerImpl>(profile_prefs, nullptr); #endif // defined(OS_CHROMEOS) } // static -PrefProxyConfigTracker* +std::unique_ptr<PrefProxyConfigTracker> ProxyServiceFactory::CreatePrefProxyConfigTrackerOfLocalState( PrefService* local_state_prefs) { #if defined(OS_CHROMEOS) - return new chromeos::ProxyConfigServiceImpl(nullptr, local_state_prefs, - nullptr); + return std::make_unique<chromeos::ProxyConfigServiceImpl>( + nullptr, local_state_prefs, nullptr); #else - return new PrefProxyConfigTrackerImpl(local_state_prefs, nullptr); + return std::make_unique<PrefProxyConfigTrackerImpl>(local_state_prefs, + nullptr); #endif // defined(OS_CHROMEOS) }
diff --git a/chrome/browser/net/proxy_service_factory.h b/chrome/browser/net/proxy_service_factory.h index 4bc76b7..5f35c19e 100644 --- a/chrome/browser/net/proxy_service_factory.h +++ b/chrome/browser/net/proxy_service_factory.h
@@ -27,15 +27,15 @@ // profile. On ChromeOS it additionaly tracks local state for shared proxy // settings. This tracker should be used if the profile's preferences should // be respected. On ChromeOS's signin screen this is for example not the case. - static PrefProxyConfigTracker* CreatePrefProxyConfigTrackerOfProfile( - PrefService* profile_prefs, - PrefService* local_state_prefs); + static std::unique_ptr<PrefProxyConfigTracker> + CreatePrefProxyConfigTrackerOfProfile(PrefService* profile_prefs, + PrefService* local_state_prefs); // Creates a PrefProxyConfigTracker that tracks local state only. This tracker // should be used for the system request context and the signin screen // (ChromeOS only). - static PrefProxyConfigTracker* CreatePrefProxyConfigTrackerOfLocalState( - PrefService* local_state_prefs); + static std::unique_ptr<PrefProxyConfigTracker> + CreatePrefProxyConfigTrackerOfLocalState(PrefService* local_state_prefs); private: DISALLOW_IMPLICIT_CONSTRUCTORS(ProxyServiceFactory);
diff --git a/chrome/browser/notifications/platform_notification_service_impl.cc b/chrome/browser/notifications/platform_notification_service_impl.cc index 9411427..c5d65ca 100644 --- a/chrome/browser/notifications/platform_notification_service_impl.cc +++ b/chrome/browser/notifications/platform_notification_service_impl.cc
@@ -367,14 +367,10 @@ gfx::Image::CreateFrom1xBitmap(notification_resources.image)); } - // Badges are only supported on Android, primarily because it's the only - // platform that makes good use of them in the status bar. -#if defined(OS_ANDROID) // TODO(peter): Handle different screen densities instead of always using the // 1x bitmap - crbug.com/585815. notification.set_small_image( gfx::Image::CreateFrom1xBitmap(notification_resources.badge)); -#endif // defined(OS_ANDROID) // Developer supplied action buttons. std::vector<message_center::ButtonInfo> buttons;
diff --git a/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc b/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc index 6fded5f..00c10ed 100644 --- a/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc +++ b/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc
@@ -319,9 +319,7 @@ EXPECT_FALSE(notification.icon().IsEmpty()); EXPECT_EQ(kIconWidth, notification.icon().Width()); EXPECT_EQ(kIconHeight, notification.icon().Height()); - - // Small images (badges) are only supported on Android. - EXPECT_TRUE(notification.small_image().IsEmpty()); + EXPECT_FALSE(notification.small_image().IsEmpty()); // Test that notifications with the same tag replace each other and have // identical ids. @@ -421,7 +419,7 @@ EXPECT_FALSE(all_options_notification.icon().IsEmpty()); EXPECT_EQ(kIconWidth, all_options_notification.icon().Width()); EXPECT_EQ(kIconHeight, all_options_notification.icon().Height()); - EXPECT_TRUE(all_options_notification.small_image().IsEmpty()); + EXPECT_FALSE(all_options_notification.small_image().IsEmpty()); EXPECT_TRUE(all_options_notification.renotify()); EXPECT_TRUE(all_options_notification.silent()); EXPECT_TRUE(all_options_notification.never_timeout());
diff --git a/chrome/browser/password_manager/password_manager_browsertest.cc b/chrome/browser/password_manager/password_manager_browsertest.cc index 0e9ed4b..3abe4c9 100644 --- a/chrome/browser/password_manager/password_manager_browsertest.cc +++ b/chrome/browser/password_manager/password_manager_browsertest.cc
@@ -5,7 +5,6 @@ #include <string> #include <utility> -#include "base/cfi_buildflags.h" #include "base/command_line.h" #include "base/macros.h" #include "base/memory/ptr_util.h" @@ -1129,15 +1128,7 @@ EXPECT_FALSE(prompt_observer->IsSavePromptShownAutomatically()); } -// https://crbug.com/916413 tracks test flakiness on chromium.memory/Linux CFI -#if BUILDFLAG(CFI_CAST_CHECK) || BUILDFLAG(CFI_ICALL_CHECK) || \ - BUILDFLAG(CFI_ENFORCEMENT_DIAGNOSTIC) || BUILDFLAG(CFI_ENFORCEMENT_TRAP) -#define MAYBE_DeleteFrameBeforeSubmit DISABLED_DeleteFrameBeforeSubmit -#else -#define MAYBE_DeleteFrameBeforeSubmit DeleteFrameBeforeSubmit -#endif -IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, - MAYBE_DeleteFrameBeforeSubmit) { +IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, DeleteFrameBeforeSubmit) { NavigateToFile("/password/multi_frames.html"); NavigationObserver observer(WebContents());
diff --git a/chrome/browser/permissions/permission_manager_unittest.cc b/chrome/browser/permissions/permission_manager_unittest.cc index 6fdf63e6..ab0513f 100644 --- a/chrome/browser/permissions/permission_manager_unittest.cc +++ b/chrome/browser/permissions/permission_manager_unittest.cc
@@ -30,6 +30,7 @@ #include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom.h" #if defined(OS_ANDROID) +#include "base/android/build_info.h" #include "chrome/browser/android/chrome_feature_list.h" #include "chrome/browser/android/mock_location_settings.h" #include "chrome/browser/geolocation/geolocation_permission_context_android.h" @@ -52,6 +53,23 @@ DISALLOW_COPY_AND_ASSIGN(PermissionManagerTestingProfile); }; +#if defined(OS_ANDROID) +// See https://crbug.com/904883. +auto GetDefaultProtectedMediaIdentifierPermissionStatus() { + return base::android::BuildInfo::GetInstance()->sdk_int() >= + base::android::SDK_VERSION_MARSHMALLOW + ? PermissionStatus::GRANTED + : PermissionStatus::ASK; +} + +auto GetDefaultProtectedMediaIdentifierContentSetting() { + return base::android::BuildInfo::GetInstance()->sdk_int() >= + base::android::SDK_VERSION_MARSHMALLOW + ? CONTENT_SETTING_ALLOW + : CONTENT_SETTING_ASK; +} +#endif // defined(OS_ANDROID) + } // namespace class PermissionManagerTest : public ChromeRenderViewHostTestHarness { @@ -208,7 +226,7 @@ CheckPermissionStatus(PermissionType::GEOLOCATION, PermissionStatus::ASK); #if defined(OS_ANDROID) CheckPermissionStatus(PermissionType::PROTECTED_MEDIA_IDENTIFIER, - PermissionStatus::GRANTED); + GetDefaultProtectedMediaIdentifierPermissionStatus()); #endif } @@ -241,7 +259,7 @@ PermissionStatusSource::UNSPECIFIED); #if defined(OS_ANDROID) CheckPermissionResult(CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER, - CONTENT_SETTING_ALLOW, + GetDefaultProtectedMediaIdentifierContentSetting(), PermissionStatusSource::UNSPECIFIED); #endif }
diff --git a/chrome/browser/permissions/permission_request_impl.cc b/chrome/browser/permissions/permission_request_impl.cc index a716bb8..d4a744b 100644 --- a/chrome/browser/permissions/permission_request_impl.cc +++ b/chrome/browser/permissions/permission_request_impl.cc
@@ -13,6 +13,7 @@ #if defined(OS_ANDROID) #include "chrome/browser/android/android_theme_resources.h" +#include "media/base/android/media_drm_bridge.h" #else #include "chrome/app/vector_icons/vector_icons.h" #include "components/vector_icons/vector_icons.h" @@ -102,7 +103,10 @@ message_id = IDS_MIDI_SYSEX_INFOBAR_TEXT; break; case CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER: - message_id = IDS_PROTECTED_MEDIA_IDENTIFIER_INFOBAR_TEXT; + message_id = + media::MediaDrmBridge::IsPerOriginProvisioningSupported() + ? IDS_PROTECTED_MEDIA_IDENTIFIER_PER_ORIGIN_PROVISIONING_INFOBAR_TEXT + : IDS_PROTECTED_MEDIA_IDENTIFIER_PER_DEVICE_PROVISIONING_INFOBAR_TEXT; break; case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC: message_id = IDS_MEDIA_CAPTURE_AUDIO_ONLY_INFOBAR_TEXT;
diff --git a/chrome/browser/printing/printer_query.cc b/chrome/browser/printing/printer_query.cc index 09f8e164..cc23687 100644 --- a/chrome/browser/printing/printer_query.cc +++ b/chrome/browser/printing/printer_query.cc
@@ -136,7 +136,7 @@ // http://crbug.com/66082: We're blocking on the PrinterQuery's worker // thread. It's not clear to me if this may result in blocking the current // thread for an unacceptable time. We should probably fix it. - base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope allow_thread_join; + base::ThreadRestrictions::ScopedAllowIO allow_io; worker_->Stop(); worker_.reset(); }
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_data_impl.cc b/chrome/browser/resource_coordinator/local_site_characteristics_data_impl.cc index 1a3bbce..813ec6cf 100644 --- a/chrome/browser/resource_coordinator/local_site_characteristics_data_impl.cc +++ b/chrome/browser/resource_coordinator/local_site_characteristics_data_impl.cc
@@ -8,6 +8,7 @@ #include <vector> #include "base/bind.h" +#include "base/callback.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/strings/stringprintf.h" @@ -122,6 +123,19 @@ .notifications_usage_observation_window); } +bool LocalSiteCharacteristicsDataImpl::DataLoaded() const { + return fully_initialized_; +} + +void LocalSiteCharacteristicsDataImpl::RegisterDataLoadedCallback( + base::OnceClosure&& callback) { + if (fully_initialized_) { + std::move(callback).Run(); + return; + } + data_loaded_callbacks_.emplace_back(std::move(callback)); +} + void LocalSiteCharacteristicsDataImpl::NotifyUpdatesFaviconInBackground() { NotifyFeatureUsage( site_characteristics_.mutable_updates_favicon_in_background(), @@ -269,7 +283,7 @@ } // This object is now in a valid state and can be written in the database. - fully_initialized_ = true; + TransitionToFullyInitialized(); } SiteFeatureUsage LocalSiteCharacteristicsDataImpl::GetFeatureUsage( @@ -371,7 +385,7 @@ } } - fully_initialized_ = true; + TransitionToFullyInitialized(); } void LocalSiteCharacteristicsDataImpl::DecrementNumLoadedBackgroundTabs() { @@ -421,5 +435,12 @@ IncrementFeatureObservationDuration(iter, extra_observation_duration); } +void LocalSiteCharacteristicsDataImpl::TransitionToFullyInitialized() { + fully_initialized_ = true; + for (size_t i = 0; i < data_loaded_callbacks_.size(); ++i) + std::move(data_loaded_callbacks_[i]).Run(); + data_loaded_callbacks_.clear(); +} + } // namespace internal } // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_data_impl.h b/chrome/browser/resource_coordinator/local_site_characteristics_data_impl.h index c0a48bc..02836570 100644 --- a/chrome/browser/resource_coordinator/local_site_characteristics_data_impl.h +++ b/chrome/browser/resource_coordinator/local_site_characteristics_data_impl.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_RESOURCE_COORDINATOR_LOCAL_SITE_CHARACTERISTICS_DATA_IMPL_H_ #define CHROME_BROWSER_RESOURCE_COORDINATOR_LOCAL_SITE_CHARACTERISTICS_DATA_IMPL_H_ +#include "base/callback_forward.h" #include "base/gtest_prod_util.h" #include "base/macros.h" #include "base/memory/ref_counted.h" @@ -83,6 +84,14 @@ SiteFeatureUsage UsesAudioInBackground() const; SiteFeatureUsage UsesNotificationsInBackground() const; + // Returns true if the most authoritative data has been loaded from the + // backing store. + bool DataLoaded() const; + + // Registers a callback to be invoked when the data backing this object is + // loaded from disk, or otherwise authoritatively initialized. + void RegisterDataLoadedCallback(base::OnceClosure&& callback); + // Accessors for load-time performance measurement estimates. // If |num_datum| is zero, there's no estimate available. const ExponentialMovingAverage& load_duration() const { @@ -218,6 +227,8 @@ // |background_session_begin_| to NowTicks(). void FlushFeaturesObservationDurationToProto(); + void TransitionToFullyInitialized(); + // This site's characteristics, contains the features and other values are // measured. SiteCharacteristicsProto site_characteristics_; @@ -261,6 +272,10 @@ // changed since it has been initialized. bool is_dirty_; + // A collection of callbacks to be invoked when this object becomes fully + // initialized. + std::vector<base::OnceClosure> data_loaded_callbacks_; + SEQUENCE_CHECKER(sequence_checker_); base::WeakPtrFactory<LocalSiteCharacteristicsDataImpl> weak_factory_;
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_data_impl_unittest.cc b/chrome/browser/resource_coordinator/local_site_characteristics_data_impl_unittest.cc index 2d8f8c4..159be83 100644 --- a/chrome/browser/resource_coordinator/local_site_characteristics_data_impl_unittest.cc +++ b/chrome/browser/resource_coordinator/local_site_characteristics_data_impl_unittest.cc
@@ -6,6 +6,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/test/bind_test_util.h" #include "base/test/simple_test_tick_clock.h" #include "chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.h" #include "chrome/browser/resource_coordinator/time.h" @@ -696,5 +697,28 @@ local_site_data_ref->NotifySiteUnloaded(TabVisibility::kBackground); } +TEST_F(LocalSiteCharacteristicsDataImplTest, DataLoadedCallbackInvoked) { + ::testing::StrictMock<MockLocalSiteCharacteristicsDatabase> mock_db; + LocalSiteCharacteristicsDatabase::ReadSiteCharacteristicsFromDBCallback + read_cb; + + auto local_site_data = GetDataImplAndInterceptReadCallback( + kDummyOrigin, &destroy_delegate_, &mock_db, &read_cb); + + EXPECT_FALSE(local_site_data->DataLoaded()); + + bool callback_invoked = false; + local_site_data->RegisterDataLoadedCallback( + base::BindLambdaForTesting([&]() { callback_invoked = true; })); + + // Run the callback to indicate that the initialization has completed. + base::Optional<SiteCharacteristicsProto> test_proto = + SiteCharacteristicsProto(); + std::move(read_cb).Run(test_proto); + + EXPECT_TRUE(callback_invoked); + EXPECT_TRUE(local_site_data->DataLoaded()); +} + } // namespace internal } // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_data_reader.cc b/chrome/browser/resource_coordinator/local_site_characteristics_data_reader.cc index 99fa628..c709a66 100644 --- a/chrome/browser/resource_coordinator/local_site_characteristics_data_reader.cc +++ b/chrome/browser/resource_coordinator/local_site_characteristics_data_reader.cc
@@ -34,4 +34,13 @@ return impl_->UsesNotificationsInBackground(); } +bool LocalSiteCharacteristicsDataReader::DataLoaded() const { + return impl_->DataLoaded(); +} + +void LocalSiteCharacteristicsDataReader::RegisterDataLoadedCallback( + base::OnceClosure&& callback) { + impl_->RegisterDataLoadedCallback(std::move(callback)); +} + } // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_data_reader.h b/chrome/browser/resource_coordinator/local_site_characteristics_data_reader.h index 19d858e..9539f0c 100644 --- a/chrome/browser/resource_coordinator/local_site_characteristics_data_reader.h +++ b/chrome/browser/resource_coordinator/local_site_characteristics_data_reader.h
@@ -31,6 +31,8 @@ SiteFeatureUsage UpdatesTitleInBackground() const override; SiteFeatureUsage UsesAudioInBackground() const override; SiteFeatureUsage UsesNotificationsInBackground() const override; + bool DataLoaded() const override; + void RegisterDataLoadedCallback(base::OnceClosure&& callback) override; const internal::LocalSiteCharacteristicsDataImpl* impl_for_testing() const { return impl_.get();
diff --git a/chrome/browser/resource_coordinator/site_characteristics_data_reader.h b/chrome/browser/resource_coordinator/site_characteristics_data_reader.h index 2d1ee53..a127bb2 100644 --- a/chrome/browser/resource_coordinator/site_characteristics_data_reader.h +++ b/chrome/browser/resource_coordinator/site_characteristics_data_reader.h
@@ -7,6 +7,8 @@ #include "chrome/browser/resource_coordinator/local_site_characteristics_feature_usage.h" +#include "base/callback_forward.h" + namespace resource_coordinator { // Pure virtual interface to read the characteristics of an origin. This is a @@ -21,6 +23,16 @@ virtual SiteFeatureUsage UpdatesTitleInBackground() const = 0; virtual SiteFeatureUsage UsesAudioInBackground() const = 0; virtual SiteFeatureUsage UsesNotificationsInBackground() const = 0; + + // Returns true if this reader is fully initialized and serving the most + // authoritative data. This can initially return false as the backing store is + // loaded asynchronously. + virtual bool DataLoaded() const = 0; + + // Registers a callback that will be invoked when the data backing this object + // has been loaded. Note that if "DataLoaded" is true at the time this is + // called it may immediately invoke the callback. + virtual void RegisterDataLoadedCallback(base::OnceClosure&& callback) = 0; }; } // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit_source.cc b/chrome/browser/resource_coordinator/tab_lifecycle_unit_source.cc index 35e29388..f3da8b39 100644 --- a/chrome/browser/resource_coordinator/tab_lifecycle_unit_source.cc +++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit_source.cc
@@ -13,6 +13,7 @@ #include "chrome/browser/resource_coordinator/resource_coordinator_parts.h" #include "chrome/browser/resource_coordinator/tab_lifecycle_unit.h" #include "chrome/browser/resource_coordinator/tab_manager.h" +#include "chrome/browser/resource_coordinator/tracing_lifecycle_unit_observer.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_window.h" @@ -187,8 +188,9 @@ if (GetFocusedTabStripModel() == tab_strip_model && foreground) UpdateFocusedTabTo(lifecycle_unit); - // Add a self-owned observer to the LifecycleUnit to record metrics. + // Add a self-owned observers to record metrics and trace events. lifecycle_unit->AddObserver(new DiscardMetricsLifecycleUnitObserver()); + lifecycle_unit->AddObserver(new TracingLifecycleUnitObserver()); NotifyLifecycleUnitCreated(lifecycle_unit); }
diff --git a/chrome/browser/resource_coordinator/test_lifecycle_unit.cc b/chrome/browser/resource_coordinator/test_lifecycle_unit.cc index 1e4ccc3..310206c 100644 --- a/chrome/browser/resource_coordinator/test_lifecycle_unit.cc +++ b/chrome/browser/resource_coordinator/test_lifecycle_unit.cc
@@ -33,7 +33,7 @@ } base::string16 TestLifecycleUnit::GetTitle() const { - return base::string16(); + return title_; } base::TimeTicks TestLifecycleUnit::GetLastFocusedTime() const {
diff --git a/chrome/browser/resource_coordinator/test_lifecycle_unit.h b/chrome/browser/resource_coordinator/test_lifecycle_unit.h index c8d3096..228f7ac 100644 --- a/chrome/browser/resource_coordinator/test_lifecycle_unit.h +++ b/chrome/browser/resource_coordinator/test_lifecycle_unit.h
@@ -6,6 +6,7 @@ #define CHROME_BROWSER_RESOURCE_COORDINATOR_TEST_LIFECYCLE_UNIT_H_ #include "base/macros.h" +#include "base/strings/string_piece.h" #include "chrome/browser/resource_coordinator/lifecycle_unit_base.h" namespace resource_coordinator { @@ -28,6 +29,8 @@ last_focused_time_ = last_focused_time; } + void SetTitle(base::StringPiece16 title) { title_ = title.as_string(); } + // LifecycleUnit: TabLifecycleUnitExternal* AsTabLifecycleUnitExternal() override; base::string16 GetTitle() const override; @@ -47,6 +50,7 @@ bool Discard(LifecycleUnitDiscardReason discard_reason) override; private: + base::string16 title_; base::TimeTicks last_focused_time_; base::ProcessHandle process_handle_; bool can_discard_ = true;
diff --git a/chrome/browser/resource_coordinator/tracing_lifecycle_unit_observer.cc b/chrome/browser/resource_coordinator/tracing_lifecycle_unit_observer.cc new file mode 100644 index 0000000..265d1b4 --- /dev/null +++ b/chrome/browser/resource_coordinator/tracing_lifecycle_unit_observer.cc
@@ -0,0 +1,86 @@ +// 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/resource_coordinator/tracing_lifecycle_unit_observer.h" + +#include "base/strings/utf_string_conversions.h" +#include "base/trace_event/trace_event.h" +#include "chrome/browser/resource_coordinator/lifecycle_unit.h" + +namespace resource_coordinator { + +namespace { + +bool IsPendingState(LifecycleUnitState state) { + return state == LifecycleUnitState::PENDING_FREEZE || + state == LifecycleUnitState::PENDING_DISCARD || + state == LifecycleUnitState::PENDING_UNFREEZE; +} + +// An event name must be a string that is never destroyed. +const char* GetTabStateEventName(LifecycleUnitState state) { + switch (state) { + case LifecycleUnitState::PENDING_FREEZE: + return kPendingFreezeTracingEventName; + case LifecycleUnitState::PENDING_DISCARD: + return kPendingDiscardTracingEventName; + case LifecycleUnitState::PENDING_UNFREEZE: + return kPendingUnfreezeTracingEventName; + default: + NOTREACHED(); + return nullptr; + } +} + +} // namespace + +const char kPendingFreezeTracingEventName[] = "Tab State: Pending Freeze"; +const char kPendingDiscardTracingEventName[] = "Tab State: Pending Discard"; +const char kPendingUnfreezeTracingEventName[] = "Tab State: Pending Unfreeze"; + +TracingLifecycleUnitObserver::TracingLifecycleUnitObserver() = default; +TracingLifecycleUnitObserver::~TracingLifecycleUnitObserver() = default; + +void TracingLifecycleUnitObserver::OnLifecycleUnitStateChanged( + LifecycleUnit* lifecycle_unit, + LifecycleUnitState last_state, + LifecycleUnitStateChangeReason reason) { + const LifecycleUnitState current_state = lifecycle_unit->GetState(); + if (IsPendingState(current_state)) { + // Emit a state begin event if the current state is a pending state. + EmitStateBeginEvent(GetTabStateEventName(current_state), + base::UTF16ToUTF8(lifecycle_unit->GetTitle()).c_str()); + } else { + // Emit a state end event if the previous state is a pending state. + MaybeEmitStateEndEvent(last_state); + } +} + +void TracingLifecycleUnitObserver::OnLifecycleUnitDestroyed( + LifecycleUnit* lifecycle_unit) { + // Emit a state end event if the final state is a pending state. + MaybeEmitStateEndEvent(lifecycle_unit->GetState()); + + // This is a self-owned object that destroys itself with the LifecycleUnit + // that it observes. + lifecycle_unit->RemoveObserver(this); + delete this; +} + +void TracingLifecycleUnitObserver::MaybeEmitStateEndEvent( + LifecycleUnitState state) { + if (IsPendingState(state)) + EmitStateEndEvent(GetTabStateEventName(state)); +} + +void TracingLifecycleUnitObserver::EmitStateBeginEvent(const char* event_name, + const char* title) { + TRACE_EVENT_ASYNC_BEGIN1("browser", event_name, this, "Title", title); +} + +void TracingLifecycleUnitObserver::EmitStateEndEvent(const char* event_name) { + TRACE_EVENT_ASYNC_END0("browser", event_name, this); +} + +} // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/tracing_lifecycle_unit_observer.h b/chrome/browser/resource_coordinator/tracing_lifecycle_unit_observer.h new file mode 100644 index 0000000..9760a51b --- /dev/null +++ b/chrome/browser/resource_coordinator/tracing_lifecycle_unit_observer.h
@@ -0,0 +1,46 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_RESOURCE_COORDINATOR_TRACING_LIFECYCLE_UNIT_OBSERVER_H_ +#define CHROME_BROWSER_RESOURCE_COORDINATOR_TRACING_LIFECYCLE_UNIT_OBSERVER_H_ + +#include "base/macros.h" +#include "chrome/browser/resource_coordinator/lifecycle_unit_observer.h" +#include "chrome/browser/resource_coordinator/lifecycle_unit_state.mojom.h" + +namespace resource_coordinator { + +using ::mojom::LifecycleUnitState; + +extern const char kPendingFreezeTracingEventName[]; +extern const char kPendingDiscardTracingEventName[]; +extern const char kPendingUnfreezeTracingEventName[]; + +// Observes a LifecycleUnit to generate trace events. +class TracingLifecycleUnitObserver : public LifecycleUnitObserver { + public: + TracingLifecycleUnitObserver(); + ~TracingLifecycleUnitObserver() override; + + // LifecycleUnitObserver: + void OnLifecycleUnitStateChanged( + LifecycleUnit* lifecycle_unit, + LifecycleUnitState last_state, + LifecycleUnitStateChangeReason reason) override; + void OnLifecycleUnitDestroyed(LifecycleUnit* lifecycle_unit) override; + + private: + // Emits a state end event if |state| is a pending state. + void MaybeEmitStateEndEvent(LifecycleUnitState state); + + // Emits tracing events. Virtual for testing. + virtual void EmitStateBeginEvent(const char* event_name, const char* title); + virtual void EmitStateEndEvent(const char* event_name); + + DISALLOW_COPY_AND_ASSIGN(TracingLifecycleUnitObserver); +}; + +} // namespace resource_coordinator + +#endif // CHROME_BROWSER_RESOURCE_COORDINATOR_TRACING_LIFECYCLE_UNIT_OBSERVER_H_
diff --git a/chrome/browser/resource_coordinator/tracing_lifecycle_unit_observer_unittest.cc b/chrome/browser/resource_coordinator/tracing_lifecycle_unit_observer_unittest.cc new file mode 100644 index 0000000..1803dcb9 --- /dev/null +++ b/chrome/browser/resource_coordinator/tracing_lifecycle_unit_observer_unittest.cc
@@ -0,0 +1,105 @@ +// 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/resource_coordinator/tracing_lifecycle_unit_observer.h" + +#include "base/strings/utf_string_conversions.h" +#include "chrome/browser/resource_coordinator/lifecycle_unit_base.h" +#include "chrome/browser/resource_coordinator/test_lifecycle_unit.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using testing::Mock; +using testing::StrEq; +using testing::StrictMock; + +namespace resource_coordinator { + +namespace { + +class MockTracingLifecycleUnitObserver : public TracingLifecycleUnitObserver { + public: + MockTracingLifecycleUnitObserver() = default; + + MOCK_METHOD2(EmitStateBeginEvent, void(const char*, const char*)); + MOCK_METHOD1(EmitStateEndEvent, void(const char*)); + + private: + DISALLOW_COPY_AND_ASSIGN(MockTracingLifecycleUnitObserver); +}; + +} // namespace + +TEST(TracingLifecycleUnitObserverTest, Tracing) { + constexpr LifecycleUnitStateChangeReason kReason = + LifecycleUnitStateChangeReason::BROWSER_INITIATED; + constexpr const char kTitle[] = "Dummy Title"; + + TestLifecycleUnit lifecycle_unit; + lifecycle_unit.SetTitle(base::UTF8ToUTF16(kTitle)); + + // |observer| deletes itself when |lifecycle_unit| goes out of scope. + MockTracingLifecycleUnitObserver* observer = + new StrictMock<MockTracingLifecycleUnitObserver>(); + lifecycle_unit.AddObserver(observer); + + lifecycle_unit.SetState(LifecycleUnitState::ACTIVE, kReason); + + // Pending freeze. + EXPECT_CALL(*observer, + EmitStateBeginEvent(StrEq(kPendingFreezeTracingEventName), + StrEq(kTitle))); + lifecycle_unit.SetState(LifecycleUnitState::PENDING_FREEZE, kReason); + Mock::VerifyAndClearExpectations(observer); + + EXPECT_CALL(*observer, + EmitStateEndEvent(StrEq(kPendingFreezeTracingEventName))); + lifecycle_unit.SetState(LifecycleUnitState::FROZEN, kReason); + Mock::VerifyAndClearExpectations(observer); + + // No pending state. + lifecycle_unit.SetState(LifecycleUnitState::ACTIVE, kReason); + + // No pending state. + lifecycle_unit.SetState(LifecycleUnitState::FROZEN, kReason); + + // Pending unfreeze. + EXPECT_CALL(*observer, + EmitStateBeginEvent(StrEq(kPendingUnfreezeTracingEventName), + StrEq(kTitle))); + lifecycle_unit.SetState(LifecycleUnitState::PENDING_UNFREEZE, kReason); + Mock::VerifyAndClearExpectations(observer); + + EXPECT_CALL(*observer, + EmitStateEndEvent(StrEq(kPendingUnfreezeTracingEventName))); + lifecycle_unit.SetState(LifecycleUnitState::ACTIVE, kReason); + Mock::VerifyAndClearExpectations(observer); + + // Pending discard. + EXPECT_CALL(*observer, + EmitStateBeginEvent(StrEq(kPendingDiscardTracingEventName), + StrEq(kTitle))); + lifecycle_unit.SetState(LifecycleUnitState::PENDING_DISCARD, kReason); + Mock::VerifyAndClearExpectations(observer); + + EXPECT_CALL(*observer, + EmitStateEndEvent(StrEq(kPendingDiscardTracingEventName))); + lifecycle_unit.SetState(LifecycleUnitState::DISCARDED, kReason); + Mock::VerifyAndClearExpectations(observer); + + // Pending freeze twice. + EXPECT_CALL(*observer, + EmitStateBeginEvent(StrEq(kPendingFreezeTracingEventName), + StrEq(kTitle))); + lifecycle_unit.SetState(LifecycleUnitState::PENDING_FREEZE, kReason); + Mock::VerifyAndClearExpectations(observer); + + lifecycle_unit.SetState(LifecycleUnitState::PENDING_FREEZE, kReason); + + // Destruction in a pending state. + EXPECT_CALL(*observer, + EmitStateEndEvent(StrEq(kPendingFreezeTracingEventName))); +} + +} // namespace resource_coordinator
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js index bebc151..08790d15 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js
@@ -230,6 +230,10 @@ onAriaAttributeChanged: function(evt) { if (evt.target.state.editable) return; + // Only report attribute changes on menu list items if it is selected. + if (evt.target.role == RoleType.MENU_LIST_OPTION && !evt.target.selected) + return; + this.onEventIfInRange(evt); },
diff --git a/chrome/browser/resources/omnibox/omnibox.html b/chrome/browser/resources/omnibox/omnibox.html index 6b4c833..7866b6e 100644 --- a/chrome/browser/resources/omnibox/omnibox.html +++ b/chrome/browser/resources/omnibox/omnibox.html
@@ -23,6 +23,12 @@ <p>Input parameters:</p> <p> <label> + <input id="reset-autocomplete-controller" type="checkbox" accesskey="r"> + <span class="accesskey">R</span>eset autocomplete controller + </label> + </p> + <p> + <label> <input id="lock-cursor-position" type="checkbox" accesskey="c"> Lock <span class="accesskey">c</span>ursor position to end of input </label>
diff --git a/chrome/browser/resources/omnibox/omnibox.js b/chrome/browser/resources/omnibox/omnibox.js index a6c07f3..186c70ed 100644 --- a/chrome/browser/resources/omnibox/omnibox.js +++ b/chrome/browser/resources/omnibox/omnibox.js
@@ -33,27 +33,9 @@ /** @private {!mojom.OmniboxPageHandlerProxy} */ this.handler_ = mojom.OmniboxPageHandler.getProxy(); this.handler_.setClientPage(this.callbackRouter_.createProxy()); - } - /** - * Extracts the input text from the text field and sends it to the - * C++ portion of chrome to handle. The C++ code will iteratively - * call handleNewAutocompleteResult as results come in. - */ - makeRequest(inputString, - cursorPosition, - preventInlineAutocomplete, - preferKeyword, - pageClassification) { - // Then, call chrome with a five-element list: - // - first element: the value in the text box - // - second element: the location of the cursor in the text box - // - third element: the value of prevent-inline-autocomplete - // - forth element: the value of prefer-keyword - // - fifth element: the value of page-classification - this.handler_.startOmniboxQuery( - inputString, cursorPosition, preventInlineAutocomplete, preferKeyword, - pageClassification); + /** @type {function(string, boolean, number, boolean, boolean, number)} */ + this.makeRequest = this.handler_.startOmniboxQuery.bind(this.handler_); } } @@ -74,6 +56,7 @@ omniboxOutput.updateQueryInputs(event.detail); browserProxy.makeRequest( event.detail.inputText, + event.detail.resetAutocompleteController, event.detail.cursorPosition, event.detail.preventInlineAutocomplete, event.detail.preferKeyword,
diff --git a/chrome/browser/resources/omnibox/omnibox_inputs.js b/chrome/browser/resources/omnibox/omnibox_inputs.js index 1072676..93309a1 100644 --- a/chrome/browser/resources/omnibox/omnibox_inputs.js +++ b/chrome/browser/resources/omnibox/omnibox_inputs.js
@@ -37,18 +37,18 @@ const onQueryInputsChanged = this.onQueryInputsChanged_.bind(this); const onDisplayInputsChanged = this.onDisplayInputsChanged_.bind(this); - this.$$('input-text').addEventListener('input', onQueryInputsChanged); - - [this.$$('lock-cursor-position'), + [this.$$('input-text'), + this.$$('reset-autocomplete-controller'), + this.$$('lock-cursor-position'), this.$$('prevent-inline-autocomplete'), this.$$('prefer-keyword'), this.$$('page-classification'), - ].forEach(elem => elem.addEventListener('change', onQueryInputsChanged)); + ].forEach(elem => elem.addEventListener('input', onQueryInputsChanged)); [this.$$('show-incomplete-results'), this.$$('show-details'), this.$$('show-all-providers'), - ].forEach(elem => elem.addEventListener('change', onDisplayInputsChanged)); + ].forEach(elem => elem.addEventListener('input', onDisplayInputsChanged)); this.$$('copy-text') .addEventListener('click', () => this.onCopyOutput_('text')); @@ -64,6 +64,8 @@ /** @type {!QueryInputs} */ const queryInputs = { inputText: this.$$('input-text').value, + resetAutocompleteController: + this.$$('reset-autocomplete-controller').checked, cursorPosition: this.cursorPosition_, preventInlineAutocomplete: this.$$('prevent-inline-autocomplete').checked, preferKeyword: this.$$('prefer-keyword').checked,
diff --git a/chrome/browser/resources/omnibox/omnibox_output.js b/chrome/browser/resources/omnibox/omnibox_output.js index 9c04063..7809bea 100644 --- a/chrome/browser/resources/omnibox/omnibox_output.js +++ b/chrome/browser/resources/omnibox/omnibox_output.js
@@ -782,18 +782,20 @@ 'of the result.', ['contents', 'description'], OutputPairProperty), new Column( - ['Can Be Default'], '', 'allowedToBeDefaultMatch', true, - 'A green checkmark indicates that the result can be the default ' + - 'match(i.e., can be the match that pressing enter in the ' + - 'omniboxnavigates to).', + ['D'], '', 'allowedToBeDefaultMatch', true, + 'Can Be Default\nA green checkmark indicates that the result can be ' + + 'the default match (i.e., can be the match that pressing enter ' + + 'in the omnibox navigates to).', ['allowedToBeDefaultMatch'], OutputBooleanProperty), new Column( - ['Starred'], '', 'starred', false, - 'A green checkmark indicates that the result has been bookmarked.', + ['S'], '', 'starred', false, + 'Starred\nA green checkmark indicates that the result has been ' + + 'bookmarked.', ['starred'], OutputBooleanProperty), new Column( - ['Has Tab Match'], '', 'hasTabMatch', false, - 'A green checkmark indicates that the result URL matches an opentab.', + ['T'], '', 'hasTabMatch', false, + 'Has Tab Match\nA green checkmark indicates that the result URL ' + + 'matches an open tab.', ['hasTabMatch'], OutputBooleanProperty), new Column( ['URL'], '', 'destinationUrl', true, 'The URL for the result.', @@ -806,13 +808,14 @@ ['fillIntoEdit', 'inlineAutocompletion'], OutputOverlappingPairProperty), new Column( - ['Del'], '', 'deletable', false, - 'A green checkmark indicates that the result can be deleted from the ' + - 'visit history.', + ['D'], '', 'deletable', false, + 'Deletable\nA green checkmark indicates that the result can be ' + + 'deleted from the visit history.', ['deletable'], OutputBooleanProperty), new Column( - ['Prev'], '', 'fromPrevious', false, '', ['fromPrevious'], - OutputBooleanProperty), + ['P'], '', 'fromPrevious', false, + 'From Previous\nTrue if this match is from a previous result.', + ['fromPrevious'], OutputBooleanProperty), new Column( ['Tran'], 'https://cs.chromium.org/chromium/src/ui/base/page_transition_types.h' + @@ -820,9 +823,9 @@ 'transition', false, 'How the user got to the result.', ['transition'], OutputTextProperty), new Column( - ['Done'], '', 'providerDone', false, - 'A green checkmark indicates that the provider is done looking for ' + - 'more results.', + ['D'], '', 'providerDone', false, + 'Done\nA green checkmark indicates that the provider is done looking ' + + 'for more results.', ['providerDone'], OutputBooleanProperty), new Column( ['Associated Keyword'], '', 'associatedKeyword', false, @@ -834,9 +837,9 @@ 'The keyword of the search engine to be used.', ['keyword'], OutputTextProperty), new Column( - ['Duplicates'], '', 'duplicates', false, - 'The number of matches that have been marked as duplicates of this ' + - 'match.', + ['D'], '', 'duplicates', false, + 'Duplicates\nThe number of matches that have been marked as ' + + 'duplicates of this match.', ['duplicates'], OutputTextProperty), new Column( ['Additional Info'], '', 'additionalInfo', false,
diff --git a/chrome/browser/resources/settings/people_page/sync_account_control.js b/chrome/browser/resources/settings/people_page/sync_account_control.js index c7cf9dd..0e598e6 100644 --- a/chrome/browser/resources/settings/people_page/sync_account_control.js +++ b/chrome/browser/resources/settings/people_page/sync_account_control.js
@@ -250,8 +250,7 @@ * @private */ shouldShowTurnOffButton_: function() { - return !this.hideButtons && !!this.syncStatus.signedIn && - !this.embeddedInSubpage; + return !this.hideButtons && !!this.syncStatus.signedIn; }, /**
diff --git a/chrome/browser/search/one_google_bar/one_google_bar_service_unittest.cc b/chrome/browser/search/one_google_bar/one_google_bar_service_unittest.cc index 85d3425..1994a78b 100644 --- a/chrome/browser/search/one_google_bar/one_google_bar_service_unittest.cc +++ b/chrome/browser/search/one_google_bar/one_google_bar_service_unittest.cc
@@ -57,7 +57,7 @@ public: OneGoogleBarServiceTest() : signin_client_(&pref_service_), - identity_env_(/*use_fake_url_loader_for_gaia_cookie_manager=*/true) { + identity_env_(&test_url_loader_factory_) { // GaiaCookieManagerService calls static methods of AccountTrackerService // which access prefs. AccountTrackerService::RegisterPrefs(pref_service_.registry()); @@ -87,6 +87,7 @@ base::test::ScopedTaskEnvironment task_environment_; sync_preferences::TestingPrefServiceSyncable pref_service_; + network::TestURLLoaderFactory test_url_loader_factory_; TestSigninClient signin_client_; FakeOAuth2TokenService token_service_; identity::IdentityTestEnvironment identity_env_;
diff --git a/chrome/browser/signin/fake_signin_manager_builder.cc b/chrome/browser/signin/fake_signin_manager_builder.cc index 8fedf7e..1f7ab7f 100644 --- a/chrome/browser/signin/fake_signin_manager_builder.cc +++ b/chrome/browser/signin/fake_signin_manager_builder.cc
@@ -30,6 +30,7 @@ FakeSigninManagerForTesting::FakeSigninManagerForTesting(Profile* profile) : FakeSigninManagerBase( ChromeSigninClientFactory::GetForProfile(profile), + ProfileOAuth2TokenServiceFactory::GetForProfile(profile), AccountTrackerServiceFactory::GetForProfile(profile), SigninErrorControllerFactory::GetForProfile(profile)) {} #else
diff --git a/chrome/browser/signin/identity_services_provider_android.cc b/chrome/browser/signin/identity_services_provider_android.cc index ad00785..b965675 100644 --- a/chrome/browser/signin/identity_services_provider_android.cc +++ b/chrome/browser/signin/identity_services_provider_android.cc
@@ -5,7 +5,9 @@ #include "base/android/jni_android.h" #include "chrome/browser/profiles/profile_android.h" #include "chrome/browser/signin/account_tracker_service_factory.h" +#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" #include "components/signin/core/browser/account_tracker_service.h" +#include "components/signin/core/browser/oauth2_token_service_delegate_android.h" #include "jni/IdentityServicesProvider_jni.h" using base::android::JavaParamRef; @@ -20,3 +22,15 @@ AccountTrackerServiceFactory::GetForProfile(profile); return service->GetJavaObject(); } + +static ScopedJavaLocalRef<jobject> +JNI_IdentityServicesProvider_GetOAuth2TokenService( + JNIEnv* env, + const JavaParamRef<jobject>& j_profile_android) { + Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile_android); + ProfileOAuth2TokenService* service = + ProfileOAuth2TokenServiceFactory::GetForProfile(profile); + OAuth2TokenServiceDelegateAndroid* delegate = + static_cast<OAuth2TokenServiceDelegateAndroid*>(service->GetDelegate()); + return delegate->GetJavaObject(); +}
diff --git a/chrome/browser/signin/profile_oauth2_token_service_factory.cc b/chrome/browser/signin/profile_oauth2_token_service_factory.cc index ab4a1e6..a992235 100644 --- a/chrome/browser/signin/profile_oauth2_token_service_factory.cc +++ b/chrome/browser/signin/profile_oauth2_token_service_factory.cc
@@ -21,7 +21,7 @@ #include "components/signin/core/browser/profile_oauth2_token_service.h" #if defined(OS_ANDROID) -#include "chrome/browser/signin/oauth2_token_service_delegate_android.h" +#include "components/signin/core/browser/oauth2_token_service_delegate_android.h" #else #include "chrome/browser/content_settings/cookie_settings_factory.h" #include "chrome/browser/signin/mutable_profile_oauth2_token_service_delegate.h"
diff --git a/chrome/browser/signin/signin_error_notifier_ash_unittest.cc b/chrome/browser/signin/signin_error_notifier_ash_unittest.cc index effc6cd..1e91f89 100644 --- a/chrome/browser/signin/signin_error_notifier_ash_unittest.cc +++ b/chrome/browser/signin/signin_error_notifier_ash_unittest.cc
@@ -11,26 +11,23 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" +#include "base/stl_util.h" #include "build/build_config.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/login/users/mock_user_manager.h" #include "chrome/browser/notifications/notification_display_service_tester.h" -#include "chrome/browser/signin/account_tracker_service_factory.h" -#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" +#include "chrome/browser/signin/identity_test_environment_profile_adaptor.h" #include "chrome/browser/signin/signin_error_notifier_factory_ash.h" #include "chrome/test/base/browser_with_test_window_test.h" #include "chrome/test/base/testing_profile.h" -#include "chrome/test/base/testing_profile_manager.h" -#include "components/signin/core/browser/account_tracker_service.h" -#include "components/signin/core/browser/profile_oauth2_token_service.h" #include "components/user_manager/scoped_user_manager.h" -#include "google_apis/gaia/oauth2_token_service_delegate.h" +#include "services/identity/public/cpp/identity_test_environment.h" +#include "services/identity/public/cpp/identity_test_utils.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/message_center/public/cpp/notification.h" namespace { -const char kTestGaiaId[] = "gaia_id"; const char kTestEmail[] = "email@example.com"; // Notification ID corresponding to kProfileSigninNotificationId + @@ -49,25 +46,42 @@ SigninErrorNotifierFactory::GetForProfile(GetProfile()); display_service_ = std::make_unique<NotificationDisplayServiceTester>(profile()); + + identity_test_env_profile_adaptor_ = + std::make_unique<IdentityTestEnvironmentProfileAdaptor>(GetProfile()); } - void SetAuthError(const GoogleServiceAuthError& error) { - // TODO(https://crbug.com/836212): Do not use the delegate directly, because - // it is internal API. - ProfileOAuth2TokenService* token_service = - ProfileOAuth2TokenServiceFactory::GetForProfile(profile()); - std::string account_id = - AccountTrackerServiceFactory::GetForProfile(profile())->SeedAccountInfo( - kTestGaiaId, kTestEmail); - if (!token_service->RefreshTokenIsAvailable(account_id)) - token_service->UpdateCredentials(account_id, "refresh_token"); - token_service->GetDelegate()->UpdateAuthError(account_id, error); + void TearDown() override { + // Need to be destroyed before the profile associated to this test, which + // will be destroyed as part of the TearDown() process. + identity_test_env_profile_adaptor_.reset(); + + BrowserWithTestWindowTest::TearDown(); + } + + TestingProfile::TestingFactories GetTestingFactories() override { + TestingProfile::TestingFactories testing_factories; + IdentityTestEnvironmentProfileAdaptor:: + AppendIdentityTestEnvironmentFactories(&testing_factories); + return testing_factories; + } + + void SetAuthError(const std::string& account_id, + const GoogleServiceAuthError& error) { + identity::UpdatePersistentErrorOfRefreshTokenForAccount( + identity_test_env()->identity_manager(), account_id, error); + } + + identity::IdentityTestEnvironment* identity_test_env() { + return identity_test_env_profile_adaptor_->identity_test_env(); } protected: std::unique_ptr<NotificationDisplayServiceTester> display_service_; chromeos::MockUserManager* mock_user_manager_; // Not owned. std::unique_ptr<user_manager::ScopedUserManager> user_manager_enabler_; + std::unique_ptr<IdentityTestEnvironmentProfileAdaptor> + identity_test_env_profile_adaptor_; }; TEST_F(SigninErrorNotifierTest, NoNotification) { @@ -77,16 +91,22 @@ TEST_F(SigninErrorNotifierTest, ErrorReset) { EXPECT_FALSE(display_service_->GetNotification(kNotificationId)); + std::string account_id = + identity_test_env()->MakeAccountAvailable(kTestEmail).account_id; SetAuthError( + account_id, GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); EXPECT_TRUE(display_service_->GetNotification(kNotificationId)); - SetAuthError(GoogleServiceAuthError::AuthErrorNone()); + SetAuthError(account_id, GoogleServiceAuthError::AuthErrorNone()); EXPECT_FALSE(display_service_->GetNotification(kNotificationId)); } TEST_F(SigninErrorNotifierTest, ErrorTransition) { + std::string account_id = + identity_test_env()->MakeAccountAvailable(kTestEmail).account_id; SetAuthError( + account_id, GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); base::Optional<message_center::Notification> notification = @@ -96,8 +116,9 @@ EXPECT_FALSE(message.empty()); // Now set another auth error. - SetAuthError(GoogleServiceAuthError( - GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE)); + SetAuthError(account_id, + GoogleServiceAuthError( + GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE)); notification = display_service_->GetNotification(kNotificationId); ASSERT_TRUE(notification); @@ -132,12 +153,14 @@ }; static_assert(arraysize(table) == GoogleServiceAuthError::NUM_STATES, "table size should match number of auth error types"); + std::string account_id = + identity_test_env()->MakeAccountAvailable(kTestEmail).account_id; for (size_t i = 0; i < arraysize(table); ++i) { if (GoogleServiceAuthError::IsDeprecated(table[i].error_state)) continue; - SetAuthError(GoogleServiceAuthError(table[i].error_state)); + SetAuthError(account_id, GoogleServiceAuthError(table[i].error_state)); base::Optional<message_center::Notification> notification = display_service_->GetNotification(kNotificationId); ASSERT_EQ(table[i].is_error, !!notification); @@ -146,7 +169,7 @@ EXPECT_FALSE(notification->message().empty()); EXPECT_EQ((size_t)1, notification->buttons().size()); } - SetAuthError(GoogleServiceAuthError::AuthErrorNone()); + SetAuthError(account_id, GoogleServiceAuthError::AuthErrorNone()); } }
diff --git a/chrome/browser/signin/signin_global_error_unittest.cc b/chrome/browser/signin/signin_global_error_unittest.cc index 6286fbb..3641be9 100644 --- a/chrome/browser/signin/signin_global_error_unittest.cc +++ b/chrome/browser/signin/signin_global_error_unittest.cc
@@ -17,8 +17,7 @@ #include "chrome/browser/profiles/profile_attributes_storage.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/profiles/profile_metrics.h" -#include "chrome/browser/signin/fake_signin_manager_builder.h" -#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" +#include "chrome/browser/signin/identity_test_environment_profile_adaptor.h" #include "chrome/browser/signin/signin_error_controller_factory.h" #include "chrome/browser/signin/signin_global_error_factory.h" #include "chrome/browser/signin/signin_manager_factory.h" @@ -29,17 +28,14 @@ #include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile_manager.h" #include "components/prefs/pref_service.h" -#include "components/signin/core/browser/profile_oauth2_token_service.h" #include "components/signin/core/browser/signin_error_controller.h" -#include "components/signin/core/browser/signin_manager.h" #include "components/sync_preferences/pref_service_syncable.h" #include "content/public/test/test_browser_thread_bundle.h" -#include "google_apis/gaia/oauth2_token_service_delegate.h" +#include "services/identity/public/cpp/identity_test_environment.h" +#include "services/identity/public/cpp/identity_test_utils.h" #include "testing/gtest/include/gtest/gtest.h" -static const char kTestAccountId[] = "id-testuser@test.com"; -static const char kTestGaiaId[] = "gaiaid-testuser@test.com"; -static const char kTestUsername[] = "testuser@test.com"; +static const char kTestEmail[] = "testuser@test.com"; class SigninGlobalErrorTest : public testing::Test { public: @@ -51,20 +47,25 @@ // Create a signed-in profile. TestingProfile::TestingFactories testing_factories; - testing_factories.emplace_back( - SigninManagerFactory::GetInstance(), - base::BindRepeating(&BuildFakeSigninManagerForTesting)); + IdentityTestEnvironmentProfileAdaptor:: + AppendIdentityTestEnvironmentFactories(&testing_factories); + profile_ = profile_manager_.CreateTestingProfile( "Person 1", std::unique_ptr<sync_preferences::PrefServiceSyncable>(), base::UTF8ToUTF16("Person 1"), 0, std::string(), std::move(testing_factories)); - SigninManagerFactory::GetForProfile(profile()) - ->SetAuthenticatedAccountInfo(kTestAccountId, kTestUsername); + identity_test_env_profile_adaptor_ = + std::make_unique<IdentityTestEnvironmentProfileAdaptor>(profile()); + + AccountInfo account_info = + identity_test_env_profile_adaptor_->identity_test_env() + ->MakePrimaryAccountAvailable(kTestEmail); ProfileAttributesEntry* entry; ASSERT_TRUE(profile_manager_.profile_attributes_storage()-> GetProfileAttributesWithPath(profile()->GetPath(), &entry)); - entry->SetAuthInfo(kTestGaiaId, base::UTF8ToUTF16(kTestUsername)); + + entry->SetAuthInfo(account_info.gaia, base::UTF8ToUTF16(kTestEmail)); global_error_ = SigninGlobalErrorFactory::GetForProfile(profile()); error_controller_ = SigninErrorControllerFactory::GetForProfile(profile()); @@ -74,23 +75,29 @@ TestingProfileManager* testing_profile_manager() { return &profile_manager_; } + SigninGlobalError* global_error() { return global_error_; } SigninErrorController* error_controller() { return error_controller_; } void SetAuthError(GoogleServiceAuthError::State state) { - ProfileOAuth2TokenService* token_service = - ProfileOAuth2TokenServiceFactory::GetForProfile(profile()); - token_service->UpdateCredentials(kTestAccountId, "refresh_token"); - // TODO(https://crbug.com/836212): Do not use the delegate directly, because - // it is internal API. - token_service->GetDelegate()->UpdateAuthError( - kTestAccountId, GoogleServiceAuthError(state)); + identity::IdentityTestEnvironment* identity_test_env = + identity_test_env_profile_adaptor_->identity_test_env(); + AccountInfo primary_account_info = + identity_test_env->identity_manager()->GetPrimaryAccountInfo(); + + identity::UpdatePersistentErrorOfRefreshTokenForAccount( + identity_test_env->identity_manager(), primary_account_info.account_id, + GoogleServiceAuthError(state)); } private: content::TestBrowserThreadBundle thread_bundle_; TestingProfileManager profile_manager_; TestingProfile* profile_; + + std::unique_ptr<IdentityTestEnvironmentProfileAdaptor> + identity_test_env_profile_adaptor_; + SigninGlobalError* global_error_; SigninErrorController* error_controller_; };
diff --git a/chrome/browser/signin/signin_manager_factory.cc b/chrome/browser/signin/signin_manager_factory.cc index 710183b..7e9ba743 100644 --- a/chrome/browser/signin/signin_manager_factory.cc +++ b/chrome/browser/signin/signin_manager_factory.cc
@@ -115,7 +115,8 @@ ChromeSigninClientFactory::GetInstance()->GetForProfile(profile); #if defined(OS_CHROMEOS) service = new SigninManagerBase( - client, AccountTrackerServiceFactory::GetForProfile(profile), + client, ProfileOAuth2TokenServiceFactory::GetForProfile(profile), + AccountTrackerServiceFactory::GetForProfile(profile), SigninErrorControllerFactory::GetForProfile(profile)); #else service = new SigninManager(
diff --git a/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client_test_helper.h b/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client_test_helper.h index 833d627..3b789d4 100644 --- a/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client_test_helper.h +++ b/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client_test_helper.h
@@ -20,7 +20,7 @@ // Tests must include a content::TestServiceManagerContext instance. class ChromeKeyboardControllerClientTestHelper { public: - // Use this for tests using AshTestBase. TODO(stevenjb): Update tests to + // Use this for tests using ChromeAshTestBase. TODO(stevenjb): Update tests to // rely on the fake behavior instead. static std::unique_ptr<ChromeKeyboardControllerClientTestHelper> InitializeForAsh();
diff --git a/chrome/browser/ui/ash/launcher/launcher_context_menu_unittest.cc b/chrome/browser/ui/ash/launcher/launcher_context_menu_unittest.cc index defabae..51daff1c 100644 --- a/chrome/browser/ui/ash/launcher/launcher_context_menu_unittest.cc +++ b/chrome/browser/ui/ash/launcher/launcher_context_menu_unittest.cc
@@ -10,7 +10,6 @@ #include "ash/public/cpp/app_menu_constants.h" #include "ash/public/cpp/shelf_item.h" #include "ash/public/cpp/shelf_model.h" -#include "ash/test/ash_test_base.h" #include "base/macros.h" #include "base/run_loop.h" #include "base/strings/stringprintf.h" @@ -31,6 +30,7 @@ #include "chrome/browser/ui/ash/launcher/extension_launcher_context_menu.h" #include "chrome/browser/ui/ash/launcher/internal_app_shelf_context_menu.h" #include "chrome/browser/ui/ash/tablet_mode_client.h" +#include "chrome/test/base/chrome_ash_test_base.h" #include "chrome/test/base/testing_profile.h" #include "components/arc/metrics/arc_metrics_constants.h" #include "components/arc/test/fake_app_instance.h" @@ -63,7 +63,7 @@ return base::StringPrintf("AppInShelfGroup%d", task_id); } -class LauncherContextMenuTest : public ash::AshTestBase { +class LauncherContextMenuTest : public ChromeAshTestBase { protected: LauncherContextMenuTest() = default; ~LauncherContextMenuTest() override = default; @@ -71,7 +71,7 @@ void SetUp() override { arc_test_.SetUp(&profile_); session_manager_ = std::make_unique<session_manager::SessionManager>(); - ash::AshTestBase::SetUp(); + ChromeAshTestBase::SetUp(); model_ = std::make_unique<ash::ShelfModel>(); launcher_controller_ = std::make_unique<ChromeLauncherController>(&profile_, model_.get()); @@ -136,7 +136,7 @@ void TearDown() override { launcher_controller_.reset(); - ash::AshTestBase::TearDown(); + ChromeAshTestBase::TearDown(); } ArcAppTest& arc_test() { return arc_test_; }
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_context_menu_chromeos_unittest.cc b/chrome/browser/ui/ash/multi_user/multi_user_context_menu_chromeos_unittest.cc index ba73aa9..824cc83 100644 --- a/chrome/browser/ui/ash/multi_user/multi_user_context_menu_chromeos_unittest.cc +++ b/chrome/browser/ui/ash/multi_user/multi_user_context_menu_chromeos_unittest.cc
@@ -4,7 +4,6 @@ #include <memory> -#include "ash/test/ash_test_base.h" #include "ash/test/ash_test_helper.h" #include "base/compiler_specific.h" #include "base/format_macros.h" @@ -16,6 +15,7 @@ #include "chrome/browser/ui/ash/multi_user/multi_user_context_menu.h" #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_client.h" #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_client_impl.h" +#include "chrome/test/base/chrome_ash_test_base.h" #include "components/account_id/account_id.h" #include "components/user_manager/scoped_user_manager.h" #include "ui/aura/window.h" @@ -25,7 +25,7 @@ namespace ash { // A test class for preparing the MultiUserContextMenu. -class MultiUserContextMenuChromeOSTest : public AshTestBase { +class MultiUserContextMenuChromeOSTest : public ChromeAshTestBase { public: MultiUserContextMenuChromeOSTest() : fake_user_manager_(new chromeos::FakeChromeUserManager), @@ -69,7 +69,7 @@ }; void MultiUserContextMenuChromeOSTest::SetUp() { - AshTestBase::SetUp(); + ChromeAshTestBase::SetUp(); // MultiUserWindowManager assumes there is a MusClient in single-process mash // mode. @@ -91,7 +91,7 @@ delete window_; ::MultiUserWindowManagerClient::DeleteInstance(); - AshTestBase::TearDown(); + ChromeAshTestBase::TearDown(); } // Check that an unowned window will never create a menu.
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_util_chromeos_unittest.cc b/chrome/browser/ui/ash/multi_user/multi_user_util_chromeos_unittest.cc index af4af93..f5aa2c7 100644 --- a/chrome/browser/ui/ash/multi_user/multi_user_util_chromeos_unittest.cc +++ b/chrome/browser/ui/ash/multi_user/multi_user_util_chromeos_unittest.cc
@@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/test/ash_test_base.h" #include "base/bind.h" #include "base/memory/ptr_util.h" #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h" @@ -10,6 +9,7 @@ #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/signin/identity_test_environment_profile_adaptor.h" #include "chrome/browser/ui/ash/multi_user/multi_user_util.h" +#include "chrome/test/base/chrome_ash_test_base.h" #include "chrome/test/base/testing_profile.h" #include "components/account_id/account_id.h" #include "components/signin/core/browser/account_info.h" @@ -26,13 +26,13 @@ } // namespace -class MultiUserUtilTest : public AshTestBase { +class MultiUserUtilTest : public ChromeAshTestBase { public: MultiUserUtilTest() {} ~MultiUserUtilTest() override {} void SetUp() override { - AshTestBase::SetUp(); + ChromeAshTestBase::SetUp(); fake_user_manager_ = new chromeos::FakeChromeUserManager; user_manager_enabler_ = std::make_unique<user_manager::ScopedUserManager>( @@ -49,7 +49,7 @@ void TearDown() override { identity_test_env_adaptor_.reset(); profile_.reset(); - AshTestBase::TearDown(); + ChromeAshTestBase::TearDown(); } // Add a user to the identity manager with given gaia_id and email.
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_client_impl_unittest.cc b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_client_impl_unittest.cc index 9cc7e221..6b79db02 100644 --- a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_client_impl_unittest.cc +++ b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_client_impl_unittest.cc
@@ -16,8 +16,6 @@ #include "ash/session/session_controller.h" #include "ash/shelf/shelf_constants.h" #include "ash/shell.h" -#include "ash/test/ash_test_base.h" -#include "ash/test/ash_test_environment_content.h" #include "ash/test/ash_test_helper.h" #include "ash/test_shell_delegate.h" #include "ash/wm/mru_window_tracker.h" @@ -52,6 +50,7 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_list.h" +#include "chrome/test/base/chrome_ash_test_base.h" #include "chrome/test/base/test_browser_window_aura.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" @@ -135,13 +134,13 @@ // A test class for preparing the MultiUserWindowManager. It creates // various windows and instantiates the MultiUserWindowManager. -class MultiUserWindowManagerClientImplTest : public AshTestBase { +class MultiUserWindowManagerClientImplTest : public ChromeAshTestBase { public: MultiUserWindowManagerClientImplTest() : fake_user_manager_(new chromeos::FakeChromeUserManager), user_manager_enabler_(base::WrapUnique(fake_user_manager_)) {} - // AshTestBase: + // ChromeAshTestBase: void SetUp() override; void TearDown() override; @@ -309,7 +308,7 @@ chromeos::CrosSettings::Initialize( TestingBrowserProcess::GetGlobal()->local_state()); ash_test_helper()->set_test_shell_delegate(new TestShellDelegateChromeOS); - AshTestBase::SetUp(); + ChromeAshTestBase::SetUp(); ash_test_helper() ->test_session_controller_client() ->set_use_lower_case_user_id(false); @@ -353,7 +352,7 @@ } ::MultiUserWindowManagerClient::DeleteInstance(); - AshTestBase::TearDown(); + ChromeAshTestBase::TearDown(); wallpaper_controller_client_.reset(); profile_manager_.reset(); chromeos::CrosSettings::Shutdown();
diff --git a/chrome/browser/ui/bloated_renderer/bloated_renderer_tab_helper.cc b/chrome/browser/ui/bloated_renderer/bloated_renderer_tab_helper.cc index 7cc1503e..a0d34f1 100644 --- a/chrome/browser/ui/bloated_renderer/bloated_renderer_tab_helper.cc +++ b/chrome/browser/ui/bloated_renderer/bloated_renderer_tab_helper.cc
@@ -12,6 +12,7 @@ #include "content/public/browser/navigation_entry.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/render_process_host.h" +#include "content/public/common/content_features.h" #include "content/public/common/page_importance_signals.h" #include "ui/base/l10n/l10n_util.h" @@ -115,6 +116,9 @@ void BloatedRendererTabHelper::OnRendererIsBloated( content::WebContents* bloated_web_contents, const resource_coordinator::PageNavigationIdentity& page_navigation_id) { + if (!base::FeatureList::IsEnabled(features::kBloatedRendererDetection)) { + return; + } if (web_contents() != bloated_web_contents) { // Ignore if the notification is about a different tab. return;
diff --git a/chrome/browser/ui/bloated_renderer/bloated_renderer_tab_helper_browsertest.cc b/chrome/browser/ui/bloated_renderer/bloated_renderer_tab_helper_browsertest.cc index 861b965b5..14675f3d 100644 --- a/chrome/browser/ui/bloated_renderer/bloated_renderer_tab_helper_browsertest.cc +++ b/chrome/browser/ui/bloated_renderer/bloated_renderer_tab_helper_browsertest.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/ui/bloated_renderer/bloated_renderer_tab_helper.h" +#include "base/test/scoped_feature_list.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/resource_coordinator/utils.h" @@ -13,12 +14,15 @@ #include "chrome/test/base/in_process_browser_test.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_types.h" +#include "content/public/common/content_features.h" #include "content/public/test/test_navigation_observer.h" #include "content/public/test/test_utils.h" using BloatedRendererTabHelperBrowserTest = InProcessBrowserTest; IN_PROC_BROWSER_TEST_F(BloatedRendererTabHelperBrowserTest, ReloadBloatedTab) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(features::kBloatedRendererDetection); content::WindowedNotificationObserver load( content::NOTIFICATION_NAV_ENTRY_COMMITTED, content::NotificationService::AllSources());
diff --git a/chrome/browser/ui/browser_browsertest.cc b/chrome/browser/ui/browser_browsertest.cc index 2cb2def..e6ddbc7e 100644 --- a/chrome/browser/ui/browser_browsertest.cc +++ b/chrome/browser/ui/browser_browsertest.cc
@@ -1766,7 +1766,7 @@ // Close the tab and wait for interstitial detach. This destroys |contents|. content::RunTaskAndWaitForInterstitialDetach( - contents, base::Bind(&chrome::CloseTab, browser())); + contents, base::BindOnce(&chrome::CloseTab, browser())); // interstitial is deleted now. }
diff --git a/chrome/browser/ui/browser_finder_chromeos_unittest.cc b/chrome/browser/ui/browser_finder_chromeos_unittest.cc index 939f31c..5fe2125 100644 --- a/chrome/browser/ui/browser_finder_chromeos_unittest.cc +++ b/chrome/browser/ui/browser_finder_chromeos_unittest.cc
@@ -16,6 +16,7 @@ #include "components/account_id/account_id.h" #include "components/user_manager/scoped_user_manager.h" #include "components/user_manager/user.h" +#include "ui/base/ui_base_features.h" namespace test { @@ -106,6 +107,9 @@ } TEST_F(BrowserFinderChromeOSTest, FindBrowserOwnedByAnotherProfile) { + // TODO(crbug.com/910241): fix for mash. + if (features::IsSingleProcessMash()) + return; set_browser(nullptr); Browser::CreateParams params(profile()->GetOriginalProfile(), true);
diff --git a/chrome/browser/ui/login/login_handler_browsertest.cc b/chrome/browser/ui/login/login_handler_browsertest.cc index e269ff2..2e903af 100644 --- a/chrome/browser/ui/login/login_handler_browsertest.cc +++ b/chrome/browser/ui/login/login_handler_browsertest.cc
@@ -1261,7 +1261,7 @@ // Cancel and wait for the interstitial to detach. LoginHandler* handler = *observer.handlers().begin(); content::RunTaskAndWaitForInterstitialDetach( - contents, base::Bind(&LoginHandler::CancelAuth, handler)); + contents, base::BindOnce(&LoginHandler::CancelAuth, handler)); EXPECT_EQ(expected_hostname, contents->GetVisibleURL().host()); EXPECT_FALSE(contents->ShowingInterstitialPage()); @@ -1359,7 +1359,7 @@ // Cancel auth dialog for www.b.com and wait for the interstitial to detach. LoginHandler* handler = *observer.handlers().begin(); content::RunTaskAndWaitForInterstitialDetach( - contents, base::Bind(&LoginHandler::CancelAuth, handler)); + contents, base::BindOnce(&LoginHandler::CancelAuth, handler)); EXPECT_EQ("www.b.com", contents->GetVisibleURL().host()); EXPECT_FALSE(contents->ShowingInterstitialPage()); } @@ -1418,7 +1418,7 @@ // the correct origin. LoginHandler* handler = *observer.handlers().begin(); content::RunTaskAndWaitForInterstitialDetach( - contents, base::Bind(&LoginHandler::CancelAuth, handler)); + contents, base::BindOnce(&LoginHandler::CancelAuth, handler)); EXPECT_EQ("127.0.0.1", contents->GetVisibleURL().host()); EXPECT_FALSE(contents->ShowingInterstitialPage()); @@ -1476,7 +1476,7 @@ // Cancel the auth prompt. This commits the navigation. LoginHandler* handler = *observer.handlers().begin(); content::RunTaskAndWaitForInterstitialDetach( - contents, base::Bind(&LoginHandler::CancelAuth, handler)); + contents, base::BindOnce(&LoginHandler::CancelAuth, handler)); EXPECT_EQ("127.0.0.1", contents->GetVisibleURL().host()); EXPECT_FALSE(contents->ShowingInterstitialPage()); EXPECT_EQ(auth_url, contents->GetLastCommittedURL());
diff --git a/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest.cc b/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest.cc index 77483ed..a7238cd4 100644 --- a/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest.cc +++ b/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest.cc
@@ -8,6 +8,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/metrics/user_action_tester.h" +#include "chrome/browser/sync/test/integration/profile_sync_service_harness.h" #include "chrome/browser/ui/autofill/popup_constants.h" #include "chrome/browser/ui/autofill/save_card_bubble_controller_impl.h" #include "chrome/browser/ui/browser.h" @@ -39,6 +40,13 @@ using base::Bucket; using testing::ElementsAre; +namespace { +const char kCreditCardUploadForm[] = + "/credit_card_upload_form_address_and_cc.html"; +const char kCreditCardAndShippingUploadForm[] = + "/credit_card_upload_form_shipping_address.html"; +} // namespace + namespace autofill { class SaveCardBubbleViewsFullFormBrowserTest @@ -52,38 +60,6 @@ DISALLOW_COPY_AND_ASSIGN(SaveCardBubbleViewsFullFormBrowserTest); }; -class SaveCardBubbleViewsFullFormWithShippingBrowserTest - : public SaveCardBubbleViewsBrowserTestBase { - protected: - SaveCardBubbleViewsFullFormWithShippingBrowserTest() - : SaveCardBubbleViewsBrowserTestBase( - "/credit_card_upload_form_shipping_address.html") {} - - private: - DISALLOW_COPY_AND_ASSIGN(SaveCardBubbleViewsFullFormWithShippingBrowserTest); -}; - -// Tests the local save bubble. Ensures that local save appears if the RPC to -// Google Payments fails unexpectedly. -IN_PROC_BROWSER_TEST_F( - SaveCardBubbleViewsFullFormBrowserTest, - Local_SubmittingFormShowsBubbleIfGetUploadDetailsRpcFails) { - // Set up the Payments RPC. - SetUploadDetailsRpcServerError(); - - // Submitting the form and having the call to Payments fail should show the - // local save bubble. - // (Must wait for response from Payments before accessing the controller.) - ResetEventWaiterForSequence( - {DialogEvent::REQUESTED_UPLOAD_SAVE, - DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE, - DialogEvent::OFFERED_LOCAL_SAVE}); - FillAndSubmitForm(); - WaitForObservedEvent(); - EXPECT_TRUE( - FindViewInBubbleById(DialogViewId::MAIN_CONTENT_VIEW_LOCAL)->visible()); -} - // Tests the local save bubble. Ensures that clicking the [Save] button // successfully causes the bubble to go away. IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest, @@ -92,16 +68,10 @@ scoped_feature_list_.InitAndDisableFeature( features::kAutofillSaveCardSignInAfterLocalSave); - // Set up the Payments RPC. - SetUploadDetailsRpcPaymentsDeclines(); - - // Submitting the form and having Payments decline offering to save should - // show the local save bubble. - // (Must wait for response from Payments before accessing the controller.) - ResetEventWaiterForSequence( - {DialogEvent::REQUESTED_UPLOAD_SAVE, - DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE, - DialogEvent::OFFERED_LOCAL_SAVE}); + // Submitting the form without signed in user should show the local save + // bubble. + ResetEventWaiterForSequence({DialogEvent::OFFERED_LOCAL_SAVE}); + NavigateTo(kCreditCardUploadForm); FillAndSubmitForm(); WaitForObservedEvent(); EXPECT_TRUE( @@ -132,16 +102,11 @@ scoped_feature_list_.InitAndEnableFeature( features::kAutofillSaveCardImprovedUserConsent); - // Set up the Payments RPC. - SetUploadDetailsRpcPaymentsDeclines(); - // Submitting the form and having Payments decline offering to save should // show the local save bubble. // (Must wait for response from Payments before accessing the controller.) - ResetEventWaiterForSequence( - {DialogEvent::REQUESTED_UPLOAD_SAVE, - DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE, - DialogEvent::OFFERED_LOCAL_SAVE}); + ResetEventWaiterForSequence({DialogEvent::OFFERED_LOCAL_SAVE}); + NavigateTo(kCreditCardUploadForm); FillAndSubmitForm(); WaitForObservedEvent(); EXPECT_TRUE( @@ -166,16 +131,10 @@ scoped_feature_list_.InitAndEnableFeature( features::kAutofillSaveCardSignInAfterLocalSave); - // Set up the Payments RPC. - SetUploadDetailsRpcPaymentsDeclines(); - - // Submitting the form and having Payments decline offering to save should - // show the local save bubble. - // (Must wait for response from Payments before accessing the controller.) - ResetEventWaiterForSequence( - {DialogEvent::REQUESTED_UPLOAD_SAVE, - DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE, - DialogEvent::OFFERED_LOCAL_SAVE}); + // Submitting the form without signed in user should show the local save + // bubble. + ResetEventWaiterForSequence({DialogEvent::OFFERED_LOCAL_SAVE}); + NavigateTo(kCreditCardUploadForm); FillAndSubmitForm(); WaitForObservedEvent(); EXPECT_TRUE( @@ -202,20 +161,24 @@ #endif // Tests the sign in promo bubble. Ensures that the sign-in promo -// is not shown when the user is signed-in and syncing, even if -// the local save bubble is shown. +// is not shown when the user is signed-in and syncing, even if the local save +// bubble is shown. IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest, Local_NoSigninPromoShowsWhenUserIsSyncing) { // Enable the sign-in promo. - scoped_feature_list_.InitAndEnableFeature( - features::kAutofillSaveCardSignInAfterLocalSave); + scoped_feature_list_.InitWithFeatures( + // Enabled + {features::kAutofillUpstream, + features::kAutofillSaveCardSignInAfterLocalSave}, + // Disabled + {}); + + // Start sync. + harness_->SetupSync(); // Set up the Payments RPC. SetUploadDetailsRpcPaymentsDeclines(); - // Sign the user in. - SignInWithFullName("John Smith"); - // Submitting the form and having Payments decline offering to save should // show the local save bubble. // (Must wait for response from Payments before accessing the controller.) @@ -223,6 +186,7 @@ {DialogEvent::REQUESTED_UPLOAD_SAVE, DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE, DialogEvent::OFFERED_LOCAL_SAVE}); + NavigateTo(kCreditCardUploadForm); FillAndSubmitForm(); WaitForObservedEvent(); EXPECT_TRUE( @@ -249,16 +213,10 @@ scoped_feature_list_.InitAndEnableFeature( features::kAutofillSaveCardSignInAfterLocalSave); - // Set up the Payments RPC. - SetUploadDetailsRpcPaymentsDeclines(); - - // Submitting the form and having Payments decline offering to save should - // show the local save bubble. - // (Must wait for response from Payments before accessing the controller.) - ResetEventWaiterForSequence( - {DialogEvent::REQUESTED_UPLOAD_SAVE, - DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE, - DialogEvent::OFFERED_LOCAL_SAVE}); + // Submitting the form without signed in user should show the local save + // bubble. + ResetEventWaiterForSequence({DialogEvent::OFFERED_LOCAL_SAVE}); + NavigateTo(kCreditCardUploadForm); FillAndSubmitForm(); WaitForObservedEvent(); @@ -290,16 +248,10 @@ scoped_feature_list_.InitAndEnableFeature( features::kAutofillSaveCardSignInAfterLocalSave); - // Set up the Payments RPC. - SetUploadDetailsRpcPaymentsDeclines(); - - // Submitting the form and having Payments decline offering to save should - // show the local save bubble. - // (Must wait for response from Payments before accessing the controller.) - ResetEventWaiterForSequence( - {DialogEvent::REQUESTED_UPLOAD_SAVE, - DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE, - DialogEvent::OFFERED_LOCAL_SAVE}); + // Submitting the form without signed in user should show the local save + // bubble. + ResetEventWaiterForSequence({DialogEvent::OFFERED_LOCAL_SAVE}); + NavigateTo(kCreditCardUploadForm); FillAndSubmitForm(); WaitForObservedEvent(); @@ -337,16 +289,10 @@ scoped_feature_list_.InitAndEnableFeature( features::kAutofillSaveCardSignInAfterLocalSave); - // Set up the Payments RPC. - SetUploadDetailsRpcPaymentsDeclines(); - - // Submitting the form and having Payments decline offering to save should - // show the local save bubble. - // (Must wait for response from Payments before accessing the controller.) - ResetEventWaiterForSequence( - {DialogEvent::REQUESTED_UPLOAD_SAVE, - DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE, - DialogEvent::OFFERED_LOCAL_SAVE}); + // Submitting the form without signed in user should show the local save + // bubble. + ResetEventWaiterForSequence({DialogEvent::OFFERED_LOCAL_SAVE}); + NavigateTo(kCreditCardUploadForm); FillAndSubmitForm(); WaitForObservedEvent(); @@ -390,16 +336,10 @@ scoped_feature_list_.InitAndEnableFeature( features::kAutofillSaveCardSignInAfterLocalSave); - // Set up the Payments RPC. - SetUploadDetailsRpcPaymentsDeclines(); - - // Submitting the form and having Payments decline offering to save should - // show the local save bubble. - // (Must wait for response from Payments before accessing the controller.) - ResetEventWaiterForSequence( - {DialogEvent::REQUESTED_UPLOAD_SAVE, - DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE, - DialogEvent::OFFERED_LOCAL_SAVE}); + // Submitting the form without signed in user should show the local save + // bubble. + ResetEventWaiterForSequence({DialogEvent::OFFERED_LOCAL_SAVE}); + NavigateTo(kCreditCardUploadForm); FillAndSubmitForm(); WaitForObservedEvent(); @@ -457,16 +397,10 @@ scoped_feature_list_.InitAndEnableFeature( features::kAutofillSaveCardSignInAfterLocalSave); - // Set up the Payments RPC. - SetUploadDetailsRpcPaymentsDeclines(); - - // Submitting the form and having Payments decline offering to save should - // show the local save bubble. - // (Must wait for response from Payments before accessing the controller.) - ResetEventWaiterForSequence( - {DialogEvent::REQUESTED_UPLOAD_SAVE, - DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE, - DialogEvent::OFFERED_LOCAL_SAVE}); + // Submitting the form without signed in user should show the local save + // bubble. + ResetEventWaiterForSequence({DialogEvent::OFFERED_LOCAL_SAVE}); + NavigateTo(kCreditCardUploadForm); FillAndSubmitForm(); WaitForObservedEvent(); @@ -516,16 +450,10 @@ scoped_feature_list_.InitAndEnableFeature( features::kAutofillSaveCardSignInAfterLocalSave); - // Set up the Payments RPC. - SetUploadDetailsRpcPaymentsDeclines(); - - // Submitting the form and having Payments decline offering to save should - // show the local save bubble. - // (Must wait for response from Payments before accessing the controller.) - ResetEventWaiterForSequence( - {DialogEvent::REQUESTED_UPLOAD_SAVE, - DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE, - DialogEvent::OFFERED_LOCAL_SAVE}); + // Submitting the form without signed in user should show the local save + // bubble. + ResetEventWaiterForSequence({DialogEvent::OFFERED_LOCAL_SAVE}); + NavigateTo(kCreditCardUploadForm); FillAndSubmitForm(); WaitForObservedEvent(); @@ -565,16 +493,10 @@ scoped_feature_list_.InitAndEnableFeature( features::kAutofillSaveCardSignInAfterLocalSave); - // Set up the Payments RPC. - SetUploadDetailsRpcPaymentsDeclines(); - - // Submitting the form and having Payments decline offering to save should - // show the local save bubble. - // (Must wait for response from Payments before accessing the controller.) - ResetEventWaiterForSequence( - {DialogEvent::REQUESTED_UPLOAD_SAVE, - DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE, - DialogEvent::OFFERED_LOCAL_SAVE}); + // Submitting the form without signed in user should show the local save + // bubble. + ResetEventWaiterForSequence({DialogEvent::OFFERED_LOCAL_SAVE}); + NavigateTo(kCreditCardUploadForm); FillAndSubmitForm(); WaitForObservedEvent(); @@ -619,17 +541,10 @@ // Disable the updated UI. scoped_feature_list_.InitAndDisableFeature( features::kAutofillSaveCardImprovedUserConsent); - - // Set up the Payments RPC. - SetUploadDetailsRpcPaymentsDeclines(); - - // Submitting the form and having Payments decline offering to save should - // show the local save bubble. - // (Must wait for response from Payments before accessing the controller.) - ResetEventWaiterForSequence( - {DialogEvent::REQUESTED_UPLOAD_SAVE, - DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE, - DialogEvent::OFFERED_LOCAL_SAVE}); + // Submitting the form without signed in user should show the local save + // bubble. + ResetEventWaiterForSequence({DialogEvent::OFFERED_LOCAL_SAVE}); + NavigateTo(kCreditCardUploadForm); FillAndSubmitForm(); WaitForObservedEvent(); EXPECT_TRUE( @@ -645,16 +560,10 @@ // https://crbug.com/842577 . IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest, Local_SynchronousCloseAfterAsynchronousClose) { - // Set up the Payments RPC. - SetUploadDetailsRpcPaymentsDeclines(); - - // Submitting the form and having Payments decline offering to save should - // show the local save bubble. - // (Must wait for response from Payments before accessing the controller.) - ResetEventWaiterForSequence( - {DialogEvent::REQUESTED_UPLOAD_SAVE, - DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE, - DialogEvent::OFFERED_LOCAL_SAVE}); + // Submitting the form without signed in user should show the local save + // bubble. + ResetEventWaiterForSequence({DialogEvent::OFFERED_LOCAL_SAVE}); + NavigateTo(kCreditCardUploadForm); FillAndSubmitForm(); WaitForObservedEvent(); @@ -683,6 +592,11 @@ // to Google Payments. IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest, Upload_ClickingSaveClosesBubble) { + scoped_feature_list_.InitAndEnableFeature(features::kAutofillUpstream); + + // Start sync. + harness_->SetupSync(); + // Set up the Payments RPC. SetUploadDetailsRpcPaymentsAccepts(); @@ -691,6 +605,7 @@ ResetEventWaiterForSequence( {DialogEvent::REQUESTED_UPLOAD_SAVE, DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE}); + NavigateTo(kCreditCardUploadForm); FillAndSubmitForm(); WaitForObservedEvent(); EXPECT_TRUE( @@ -713,8 +628,15 @@ IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest, Upload_ClickingNoThanksClosesBubble) { // Enable the updated UI. - scoped_feature_list_.InitAndEnableFeature( - features::kAutofillSaveCardImprovedUserConsent); + scoped_feature_list_.InitWithFeatures( + // Enabled + {features::kAutofillSaveCardImprovedUserConsent, + features::kAutofillUpstream}, + // Disabled + {}); + + // Start sync. + harness_->SetupSync(); // Set up the Payments RPC. SetUploadDetailsRpcPaymentsAccepts(); @@ -724,6 +646,7 @@ ResetEventWaiterForSequence( {DialogEvent::REQUESTED_UPLOAD_SAVE, DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE}); + NavigateTo(kCreditCardUploadForm); FillAndSubmitForm(); WaitForObservedEvent(); EXPECT_TRUE( @@ -745,8 +668,14 @@ IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest, Upload_ShouldNotHaveNoThanksButton) { // Disable the updated UI. - scoped_feature_list_.InitAndDisableFeature( - features::kAutofillSaveCardImprovedUserConsent); + scoped_feature_list_.InitWithFeatures( + // Enabled + {features::kAutofillUpstream}, + // Disable the updated UI. + {features::kAutofillSaveCardImprovedUserConsent}); + + // Start sync. + harness_->SetupSync(); // Set up the Payments RPC. SetUploadDetailsRpcPaymentsAccepts(); @@ -756,6 +685,7 @@ ResetEventWaiterForSequence( {DialogEvent::REQUESTED_UPLOAD_SAVE, DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE}); + NavigateTo(kCreditCardUploadForm); FillAndSubmitForm(); WaitForObservedEvent(); EXPECT_TRUE( @@ -770,6 +700,11 @@ // button successfully causes the bubble to go away. IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest, Upload_ClickingCloseClosesBubble) { + scoped_feature_list_.InitAndEnableFeature(features::kAutofillUpstream); + + // Start sync. + harness_->SetupSync(); + // Set up the Payments RPC. SetUploadDetailsRpcPaymentsAccepts(); @@ -778,6 +713,7 @@ ResetEventWaiterForSequence( {DialogEvent::REQUESTED_UPLOAD_SAVE, DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE}); + NavigateTo(kCreditCardUploadForm); FillAndSubmitForm(); WaitForObservedEvent(); EXPECT_TRUE( @@ -793,8 +729,15 @@ IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest, Upload_ShouldNotRequestCardholderNameInHappyPath) { // Enable the EditableCardholderName experiment. - scoped_feature_list_.InitAndEnableFeature( - features::kAutofillUpstreamEditableCardholderName); + scoped_feature_list_.InitWithFeatures( + // Enabled + {features::kAutofillUpstream, + features::kAutofillUpstreamEditableCardholderName}, + // Disabled + {}); + + // Start sync. + harness_->SetupSync(); // Set up the Payments RPC. SetUploadDetailsRpcPaymentsAccepts(); @@ -804,6 +747,7 @@ ResetEventWaiterForSequence( {DialogEvent::REQUESTED_UPLOAD_SAVE, DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE}); + NavigateTo(kCreditCardUploadForm); FillAndSubmitForm(); WaitForObservedEvent(); EXPECT_TRUE( @@ -820,8 +764,15 @@ SaveCardBubbleViewsFullFormBrowserTest, Upload_SubmittingFormWithMissingNamesRequestsCardholderNameIfExpOn) { // Enable the EditableCardholderName experiment. - scoped_feature_list_.InitAndEnableFeature( - features::kAutofillUpstreamEditableCardholderName); + scoped_feature_list_.InitWithFeatures( + // Enabled + {features::kAutofillUpstream, + features::kAutofillUpstreamEditableCardholderName}, + // Disabled + {}); + + // Start sync. + harness_->SetupSync(); // Set up the Payments RPC. SetUploadDetailsRpcPaymentsAccepts(); @@ -832,6 +783,7 @@ ResetEventWaiterForSequence( {DialogEvent::REQUESTED_UPLOAD_SAVE, DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE}); + NavigateTo(kCreditCardUploadForm); FillAndSubmitFormWithoutName(); WaitForObservedEvent(); EXPECT_TRUE( @@ -843,16 +795,24 @@ // Tests the upload save bubble. Ensures that the bubble surfaces a textfield // requesting cardholder name if cardholder name is conflicting. IN_PROC_BROWSER_TEST_F( - SaveCardBubbleViewsFullFormWithShippingBrowserTest, + SaveCardBubbleViewsFullFormBrowserTest, Upload_SubmittingFormWithConflictingNamesRequestsCardholderNameIfExpOn) { // Enable the EditableCardholderName experiment. - scoped_feature_list_.InitAndEnableFeature( - features::kAutofillUpstreamEditableCardholderName); + scoped_feature_list_.InitWithFeatures( + // Enabled + {features::kAutofillUpstream, + features::kAutofillUpstreamEditableCardholderName}, + // Disabled + {}); + + // Start sync. + harness_->SetupSync(); // Set up the Payments RPC. SetUploadDetailsRpcPaymentsAccepts(); // Submit first shipping address form with a conflicting name. + NavigateTo(kCreditCardAndShippingUploadForm); FillAndSubmitFormWithConflictingName(); // Submitting the second form should still show the upload save bubble and @@ -862,6 +822,7 @@ {DialogEvent::REQUESTED_UPLOAD_SAVE, DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE}); FillAndSubmitForm(); + WaitForObservedEvent(); EXPECT_TRUE( FindViewInBubbleById(DialogViewId::MAIN_CONTENT_VIEW_UPLOAD)->visible()); @@ -875,8 +836,15 @@ SaveCardBubbleViewsFullFormBrowserTest, Upload_SaveButtonIsDisabledIfNoCardholderNameAndCardholderNameRequested) { // Enable the EditableCardholderName experiment. - scoped_feature_list_.InitAndEnableFeature( - features::kAutofillUpstreamEditableCardholderName); + scoped_feature_list_.InitWithFeatures( + // Enabled + {features::kAutofillUpstream, + features::kAutofillUpstreamEditableCardholderName}, + // Disabled + {}); + + // Start sync. + harness_->SetupSync(); // Set up the Payments RPC. SetUploadDetailsRpcPaymentsAccepts(); @@ -887,6 +855,7 @@ ResetEventWaiterForSequence( {DialogEvent::REQUESTED_UPLOAD_SAVE, DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE}); + NavigateTo(kCreditCardUploadForm); FillAndSubmitFormWithoutName(); WaitForObservedEvent(); EXPECT_TRUE( @@ -916,8 +885,15 @@ SaveCardBubbleViewsFullFormBrowserTest, Upload_EnteringCardholderNameAndClickingSaveClosesBubbleIfCardholderNameRequested) { // Enable the EditableCardholderName experiment. - scoped_feature_list_.InitAndEnableFeature( - features::kAutofillUpstreamEditableCardholderName); + scoped_feature_list_.InitWithFeatures( + // Enabled + {features::kAutofillUpstream, + features::kAutofillUpstreamEditableCardholderName}, + // Disabled + {}); + + // Start sync. + harness_->SetupSync(); // Set up the Payments RPC. SetUploadDetailsRpcPaymentsAccepts(); @@ -928,6 +904,7 @@ ResetEventWaiterForSequence( {DialogEvent::REQUESTED_UPLOAD_SAVE, DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE}); + NavigateTo(kCreditCardUploadForm); FillAndSubmitFormWithoutName(); WaitForObservedEvent(); EXPECT_TRUE( @@ -960,15 +937,21 @@ SaveCardBubbleViewsFullFormBrowserTest, Upload_RequestedCardholderNameTextfieldIsPrefilledWithFocusName) { // Enable the EditableCardholderName experiment. - scoped_feature_list_.InitAndEnableFeature( - features::kAutofillUpstreamEditableCardholderName); + scoped_feature_list_.InitWithFeatures( + // Enabled + {features::kAutofillUpstream, + features::kAutofillUpstreamEditableCardholderName}, + // Disabled + {}); + + // Start sync. + harness_->SetupSync(); + // Set the user's full name. + SetAccountFullName("John Smith"); // Set up the Payments RPC. SetUploadDetailsRpcPaymentsAccepts(); - // Sign the user in. - SignInWithFullName("John Smith"); - // Submitting the form should show the upload save bubble, along with a // textfield specifically requesting the cardholder name. // (Must wait for response from Payments before accessing the controller.) @@ -976,6 +959,7 @@ {DialogEvent::REQUESTED_UPLOAD_SAVE, DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE}); base::HistogramTester histogram_tester; + NavigateTo(kCreditCardUploadForm); FillAndSubmitFormWithoutName(); WaitForObservedEvent(); EXPECT_TRUE(FindViewInBubbleById(DialogViewId::CARDHOLDER_NAME_TEXTFIELD)); @@ -1000,8 +984,15 @@ SaveCardBubbleViewsFullFormBrowserTest, Upload_RequestedCardholderNameTextfieldIsNotPrefilledWithFocusNameIfMissing) { // Enable the EditableCardholderName experiment. - scoped_feature_list_.InitAndEnableFeature( - features::kAutofillUpstreamEditableCardholderName); + scoped_feature_list_.InitWithFeatures( + // Enabled + {features::kAutofillUpstream, + features::kAutofillUpstreamEditableCardholderName}, + // Disabled + {}); + + // Start sync. + harness_->SetupSync(); // Set up the Payments RPC. SetUploadDetailsRpcPaymentsAccepts(); @@ -1016,6 +1007,7 @@ {DialogEvent::REQUESTED_UPLOAD_SAVE, DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE}); base::HistogramTester histogram_tester; + NavigateTo(kCreditCardUploadForm); FillAndSubmitFormWithoutName(); WaitForObservedEvent(); EXPECT_TRUE(FindViewInBubbleById(DialogViewId::CARDHOLDER_NAME_TEXTFIELD)); @@ -1038,21 +1030,28 @@ SaveCardBubbleViewsFullFormBrowserTest, Upload_CardholderNameRequested_SubmittingPrefilledValueLogsUneditedMetric) { // Enable the EditableCardholderName experiment. - scoped_feature_list_.InitAndEnableFeature( - features::kAutofillUpstreamEditableCardholderName); + scoped_feature_list_.InitWithFeatures( + // Enabled + {features::kAutofillUpstream, + features::kAutofillUpstreamEditableCardholderName}, + // Disabled + {}); + + // Start sync. + harness_->SetupSync(); + // Set the user's full name. + SetAccountFullName("John Smith"); // Set up the Payments RPC. SetUploadDetailsRpcPaymentsAccepts(); - // Sign the user in. - SignInWithFullName("John Smith"); - // Submitting the form should show the upload save bubble, along with a // textfield specifically requesting the cardholder name. // (Must wait for response from Payments before accessing the controller.) ResetEventWaiterForSequence( {DialogEvent::REQUESTED_UPLOAD_SAVE, DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE}); + NavigateTo(kCreditCardUploadForm); FillAndSubmitFormWithoutName(); WaitForObservedEvent(); EXPECT_TRUE(FindViewInBubbleById(DialogViewId::CARDHOLDER_NAME_TEXTFIELD)); @@ -1073,21 +1072,28 @@ SaveCardBubbleViewsFullFormBrowserTest, Upload_CardholderNameRequested_SubmittingChangedValueLogsEditedMetric) { // Enable the EditableCardholderName experiment. - scoped_feature_list_.InitAndEnableFeature( - features::kAutofillUpstreamEditableCardholderName); + scoped_feature_list_.InitWithFeatures( + // Enabled + {features::kAutofillUpstream, + features::kAutofillUpstreamEditableCardholderName}, + // Disabled + {}); + + // Start sync. + harness_->SetupSync(); + // Set the user's full name. + SetAccountFullName("John Smith"); // Set up the Payments RPC. SetUploadDetailsRpcPaymentsAccepts(); - // Sign the user in. - SignInWithFullName("John Smith"); - // Submitting the form should show the upload save bubble, along with a // textfield specifically requesting the cardholder name. // (Must wait for response from Payments before accessing the controller.) ResetEventWaiterForSequence( {DialogEvent::REQUESTED_UPLOAD_SAVE, DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE}); + NavigateTo(kCreditCardUploadForm); FillAndSubmitFormWithoutName(); WaitForObservedEvent(); EXPECT_TRUE(FindViewInBubbleById(DialogViewId::CARDHOLDER_NAME_TEXTFIELD)); @@ -1114,18 +1120,20 @@ Upload_CardholderNameNotPrefilledIfBlankNameExperimentEnabled) { // Enable the EditableCardholderName and BlankCardholderNameField experiments. scoped_feature_list_.InitWithFeatures( - // Enabled - {features::kAutofillUpstreamEditableCardholderName, + {features::kAutofillUpstream, + features::kAutofillUpstreamEditableCardholderName, features::kAutofillUpstreamBlankCardholderNameField}, // Disabled {}); + // Start sync. + harness_->SetupSync(); + // Set the user's full name. + SetAccountFullName("John Smith"); + // Set up the Payments RPC. SetUploadDetailsRpcPaymentsAccepts(); - // Sign the user in. - SignInWithFullName("John Smith"); - // Submitting the form should show the upload save bubble, along with a // textfield specifically requesting the cardholder name. // (Must wait for response from Payments before accessing the controller.) @@ -1133,6 +1141,7 @@ {DialogEvent::REQUESTED_UPLOAD_SAVE, DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE}); base::HistogramTester histogram_tester; + NavigateTo(kCreditCardUploadForm); FillAndSubmitFormWithoutName(); WaitForObservedEvent(); EXPECT_TRUE(FindViewInBubbleById(DialogViewId::CARDHOLDER_NAME_TEXTFIELD)); @@ -1154,11 +1163,68 @@ // gfx::Range of the link. When/if that can be worked around, // create an Upload_ClickingTosLinkClosesBubble test. +// Tests the upload save logic. Ensures that Chrome offers a local save when the +// data is complete, even if Payments rejects the data. +IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest, + Logic_ShouldOfferLocalSaveIfPaymentsDeclines) { + scoped_feature_list_.InitAndEnableFeature(features::kAutofillUpstream); + + // Start sync. + harness_->SetupSync(); + + // Set up the Payments RPC. + SetUploadDetailsRpcPaymentsDeclines(); + + // Submitting the form and having Payments decline offering to save should + // show the local save bubble. + // (Must wait for response from Payments before accessing the controller.) + ResetEventWaiterForSequence( + {DialogEvent::REQUESTED_UPLOAD_SAVE, + DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE, + DialogEvent::OFFERED_LOCAL_SAVE}); + NavigateTo(kCreditCardUploadForm); + FillAndSubmitForm(); + WaitForObservedEvent(); + EXPECT_TRUE( + FindViewInBubbleById(DialogViewId::MAIN_CONTENT_VIEW_LOCAL)->visible()); +} + +// Tests the upload save logic. Ensures that Chrome offers a local save when the +// data is complete, even if the Payments upload fails unexpectedly. +IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest, + Logic_ShouldOfferLocalSaveIfPaymentsFails) { + scoped_feature_list_.InitAndEnableFeature(features::kAutofillUpstream); + + // Start sync. + harness_->SetupSync(); + + // Set up the Payments RPC. + SetUploadDetailsRpcServerError(); + + // Submitting the form and having the call to Payments fail should show the + // local save bubble. + // (Must wait for response from Payments before accessing the controller.) + ResetEventWaiterForSequence( + {DialogEvent::REQUESTED_UPLOAD_SAVE, + DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE, + DialogEvent::OFFERED_LOCAL_SAVE}); + NavigateTo(kCreditCardUploadForm); + FillAndSubmitForm(); + WaitForObservedEvent(); + EXPECT_TRUE( + FindViewInBubbleById(DialogViewId::MAIN_CONTENT_VIEW_LOCAL)->visible()); +} + // Tests the upload save logic. Ensures that Chrome delegates the offer-to-save // call to Payments, and offers to upload save the card if Payments allows it. IN_PROC_BROWSER_TEST_F( SaveCardBubbleViewsFullFormBrowserTest, Logic_CanOfferToSaveEvenIfNothingFoundIfPaymentsAccepts) { + scoped_feature_list_.InitAndEnableFeature(features::kAutofillUpstream); + + // Start sync. + harness_->SetupSync(); + // Set up the Payments RPC. SetUploadDetailsRpcPaymentsAccepts(); @@ -1169,6 +1235,7 @@ ResetEventWaiterForSequence( {DialogEvent::REQUESTED_UPLOAD_SAVE, DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE}); + NavigateTo(kCreditCardUploadForm); FillAndSubmitFormWithCardDetailsOnly(); WaitForObservedEvent(); EXPECT_TRUE( @@ -1182,6 +1249,11 @@ IN_PROC_BROWSER_TEST_F( SaveCardBubbleViewsFullFormBrowserTest, Logic_ShouldNotOfferToSaveIfNothingFoundAndPaymentsDeclines) { + scoped_feature_list_.InitAndEnableFeature(features::kAutofillUpstream); + + // Start sync. + harness_->SetupSync(); + // Set up the Payments RPC. SetUploadDetailsRpcPaymentsDeclines(); @@ -1192,6 +1264,7 @@ ResetEventWaiterForSequence( {DialogEvent::REQUESTED_UPLOAD_SAVE, DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE}); + NavigateTo(kCreditCardUploadForm); FillAndSubmitFormWithCardDetailsOnly(); WaitForObservedEvent(); EXPECT_FALSE(GetSaveCardBubbleViews()); @@ -1201,9 +1274,15 @@ // upload save should be offered, even if CVC is not detected. IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest, Logic_ShouldAttemptToOfferToSaveIfCvcNotFound) { + scoped_feature_list_.InitAndEnableFeature(features::kAutofillUpstream); + + // Start sync. + harness_->SetupSync(); + // Submitting the form should still start the flow of asking Payments if // Chrome should offer to save the card to Google, even though CVC is missing. ResetEventWaiterForSequence({DialogEvent::REQUESTED_UPLOAD_SAVE}); + NavigateTo(kCreditCardUploadForm); FillAndSubmitFormWithoutCvc(); WaitForObservedEvent(); } @@ -1212,10 +1291,16 @@ // upload save should be offered, even if the detected CVC is invalid. IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest, Logic_ShouldAttemptToOfferToSaveIfInvalidCvcFound) { + scoped_feature_list_.InitAndEnableFeature(features::kAutofillUpstream); + + // Start sync. + harness_->SetupSync(); + // Submitting the form should still start the flow of asking Payments if // Chrome should offer to save the card to Google, even though the provided // CVC is invalid. ResetEventWaiterForSequence({DialogEvent::REQUESTED_UPLOAD_SAVE}); + NavigateTo(kCreditCardUploadForm); FillAndSubmitFormWithInvalidCvc(); WaitForObservedEvent(); } @@ -1225,10 +1310,16 @@ // detected. IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest, Logic_ShouldAttemptToOfferToSaveIfNameNotFound) { + scoped_feature_list_.InitAndEnableFeature(features::kAutofillUpstream); + + // Start sync. + harness_->SetupSync(); + // Submitting the form should still start the flow of asking Payments if // Chrome should offer to save the card to Google, even though name is // missing. ResetEventWaiterForSequence({DialogEvent::REQUESTED_UPLOAD_SAVE}); + NavigateTo(kCreditCardUploadForm); FillAndSubmitFormWithoutName(); WaitForObservedEvent(); } @@ -1236,9 +1327,15 @@ // Tests the upload save logic. Ensures that Chrome lets Payments decide whether // upload save should be offered, even if multiple conflicting names are // detected. -IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormWithShippingBrowserTest, +IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest, Logic_ShouldAttemptToOfferToSaveIfNamesConflict) { + scoped_feature_list_.InitAndEnableFeature(features::kAutofillUpstream); + + // Start sync. + harness_->SetupSync(); + // Submit first shipping address form with a conflicting name. + NavigateTo(kCreditCardAndShippingUploadForm); FillAndSubmitFormWithConflictingName(); // Submitting the form should still start the flow of asking Payments if @@ -1253,10 +1350,16 @@ // upload save should be offered, even if billing address is not detected. IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest, Logic_ShouldAttemptToOfferToSaveIfAddressNotFound) { + scoped_feature_list_.InitAndEnableFeature(features::kAutofillUpstream); + + // Start sync. + harness_->SetupSync(); + // Submitting the form should still start the flow of asking Payments if // Chrome should offer to save the card to Google, even though billing address // is missing. ResetEventWaiterForSequence({DialogEvent::REQUESTED_UPLOAD_SAVE}); + NavigateTo(kCreditCardUploadForm); FillAndSubmitFormWithoutAddress(); WaitForObservedEvent(); } @@ -1264,9 +1367,15 @@ // Tests the upload save logic. Ensures that Chrome lets Payments decide whether // upload save should be offered, even if multiple conflicting billing address // postal codes are detected. -IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormWithShippingBrowserTest, +IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest, Logic_ShouldAttemptToOfferToSaveIfPostalCodesConflict) { + scoped_feature_list_.InitAndEnableFeature(features::kAutofillUpstream); + + // Start sync. + harness_->SetupSync(); + // Submit first shipping address form with a conflicting postal code. + NavigateTo(kCreditCardAndShippingUploadForm); FillAndSubmitFormWithConflictingPostalCode(); // Submitting the form should still start the flow of asking Payments if @@ -1282,6 +1391,11 @@ IN_PROC_BROWSER_TEST_F( SaveCardBubbleViewsFullFormBrowserTest, Upload_DecliningUploadDoesNotLogUserAcceptedCardOriginUMA) { + scoped_feature_list_.InitAndEnableFeature(features::kAutofillUpstream); + + // Start sync. + harness_->SetupSync(); + // Set up the Payments RPC. SetUploadDetailsRpcPaymentsAccepts(); @@ -1291,6 +1405,7 @@ ResetEventWaiterForSequence( {DialogEvent::REQUESTED_UPLOAD_SAVE, DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE}); + NavigateTo(kCreditCardUploadForm); FillAndSubmitForm(); WaitForObservedEvent(); EXPECT_TRUE( @@ -1313,8 +1428,15 @@ SaveCardBubbleViewsFullFormBrowserTest, Upload_SubmittingFormWithMissingExpirationDateRequestsExpirationDate) { // Enable the EditableExpirationDate experiment. - scoped_feature_list_.InitAndEnableFeature( - features::kAutofillUpstreamEditableExpirationDate); + scoped_feature_list_.InitWithFeatures( + // Enabled + {features::kAutofillUpstreamEditableExpirationDate, + features::kAutofillUpstream}, + // Disabled + {}); + + // Start sync. + harness_->SetupSync(); // Set up the Payments RPC. SetUploadDetailsRpcPaymentsAccepts(); @@ -1326,6 +1448,7 @@ ResetEventWaiterForSequence( {DialogEvent::REQUESTED_UPLOAD_SAVE, DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE}); + NavigateTo(kCreditCardUploadForm); FillAndSubmitFormWithoutExpirationDate(); WaitForObservedEvent(); EXPECT_TRUE( @@ -1346,8 +1469,15 @@ SaveCardBubbleViewsFullFormBrowserTest, Upload_SubmittingFormWithExpiredExpirationDateRequestsExpirationDate) { // Enable the EditableExpirationDate experiment. - scoped_feature_list_.InitAndEnableFeature( - features::kAutofillUpstreamEditableExpirationDate); + scoped_feature_list_.InitWithFeatures( + // Enabled + {features::kAutofillUpstreamEditableExpirationDate, + features::kAutofillUpstream}, + // Disabled + {}); + + // Start sync. + harness_->SetupSync(); // Set up the Payments RPC. SetUploadDetailsRpcPaymentsAccepts(); @@ -1359,6 +1489,7 @@ ResetEventWaiterForSequence( {DialogEvent::REQUESTED_UPLOAD_SAVE, DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE}); + NavigateTo(kCreditCardUploadForm); FillAndSubmitFormWithExpiredExpirationDate(); WaitForObservedEvent(); EXPECT_TRUE( @@ -1379,11 +1510,15 @@ SaveCardBubbleViewsFullFormBrowserTest, Logic_ShouldNotOfferToSaveIfSubmittingExpiredExpirationDateAndExpOff) { // Disable the EditableExpirationDate experiment. - scoped_feature_list_.InitAndDisableFeature( - features::kAutofillUpstreamEditableExpirationDate); + scoped_feature_list_.InitWithFeatures( + // Enabled + {features::kAutofillUpstream}, + // Disabled + {features::kAutofillUpstreamEditableExpirationDate}); // The credit card will not be imported if the expiration date is expired and // experiment is off. + NavigateTo(kCreditCardUploadForm); FillAndSubmitFormWithExpiredExpirationDate(); EXPECT_FALSE(GetSaveCardBubbleViews()); } @@ -1394,11 +1529,15 @@ SaveCardBubbleViewsFullFormBrowserTest, Logic_ShouldNotOfferToSaveIfMissingExpirationDateAndExpOff) { // Disable the EditableExpirationDate experiment. - scoped_feature_list_.InitAndDisableFeature( - features::kAutofillUpstreamEditableExpirationDate); + scoped_feature_list_.InitWithFeatures( + // Enabled + {features::kAutofillUpstream}, + // Disabled + {features::kAutofillUpstreamEditableExpirationDate}); // The credit card will not be imported if there is no expiration date and // experiment is off. + NavigateTo(kCreditCardUploadForm); FillAndSubmitFormWithoutExpirationDate(); EXPECT_FALSE(GetSaveCardBubbleViews()); } @@ -1408,8 +1547,15 @@ IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest, Upload_ShouldNotRequestExpirationDateInHappyPath) { // Enable the EditableExpirationDate experiment. - scoped_feature_list_.InitAndEnableFeature( - features::kAutofillUpstreamEditableExpirationDate); + scoped_feature_list_.InitWithFeatures( + // Enabled + {features::kAutofillUpstreamEditableExpirationDate, + features::kAutofillUpstream}, + // Disabled + {}); + + // Start sync. + harness_->SetupSync(); // Set up the Payments RPC. SetUploadDetailsRpcPaymentsAccepts(); @@ -1419,6 +1565,7 @@ ResetEventWaiterForSequence( {DialogEvent::REQUESTED_UPLOAD_SAVE, DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE}); + NavigateTo(kCreditCardUploadForm); FillAndSubmitForm(); WaitForObservedEvent(); EXPECT_TRUE( @@ -1441,8 +1588,15 @@ SaveCardBubbleViewsFullFormBrowserTest, Upload_SaveButtonStatusResetBetweenExpirationDateSelectionChanges) { // Enable the EditableExpirationDate experiment. - scoped_feature_list_.InitAndEnableFeature( - features::kAutofillUpstreamEditableExpirationDate); + scoped_feature_list_.InitWithFeatures( + // Enabled + {features::kAutofillUpstreamEditableExpirationDate, + features::kAutofillUpstream}, + // Disabled + {}); + + // Start sync. + harness_->SetupSync(); // Set up the Payments RPC. SetUploadDetailsRpcPaymentsAccepts(); @@ -1454,6 +1608,7 @@ ResetEventWaiterForSequence( {DialogEvent::REQUESTED_UPLOAD_SAVE, DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE}); + NavigateTo(kCreditCardUploadForm); FillAndSubmitFormWithoutExpirationDate(); WaitForObservedEvent(); EXPECT_TRUE( @@ -1500,8 +1655,15 @@ SaveCardBubbleViewsFullFormBrowserTest, Upload_SaveButtonIsDisabledIfExpiredExpirationDateAndExpirationDateRequested) { // Enable the EditableExpirationDate experiment. - scoped_feature_list_.InitAndEnableFeature( - features::kAutofillUpstreamEditableExpirationDate); + scoped_feature_list_.InitWithFeatures( + // Enabled + {features::kAutofillUpstreamEditableExpirationDate, + features::kAutofillUpstream}, + // Disabled + {}); + + // Start sync. + harness_->SetupSync(); // Set up the Payments RPC. SetUploadDetailsRpcPaymentsAccepts(); @@ -1513,6 +1675,7 @@ ResetEventWaiterForSequence( {DialogEvent::REQUESTED_UPLOAD_SAVE, DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE}); + NavigateTo(kCreditCardUploadForm); FillAndSubmitFormWithoutExpirationDate(); WaitForObservedEvent(); EXPECT_TRUE(
diff --git a/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest_base.cc b/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest_base.cc index a9ac43e..4c4bbc2 100644 --- a/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest_base.cc +++ b/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest_base.cc
@@ -10,11 +10,10 @@ #include <utility> #include "base/bind.h" -#include "chrome/browser/signin/account_fetcher_service_factory.h" -#include "chrome/browser/signin/account_tracker_service_factory.h" -#include "chrome/browser/signin/fake_account_fetcher_service_builder.h" -#include "chrome/browser/signin/fake_signin_manager_builder.h" +#include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/signin/signin_manager_factory.h" +#include "chrome/browser/sync/profile_sync_service_factory.h" +#include "chrome/browser/sync/test/integration/profile_sync_service_harness.h" #include "chrome/browser/ui/autofill/chrome_autofill_client.h" #include "chrome/browser/ui/autofill/save_card_bubble_controller_impl.h" #include "chrome/browser/ui/browser.h" @@ -30,14 +29,19 @@ #include "components/autofill/core/browser/credit_card_save_manager.h" #include "components/autofill/core/browser/form_data_importer.h" #include "components/autofill/core/browser/payments/payments_client.h" +#include "components/browser_sync/profile_sync_service.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/network_session_configurator/common/network_switches.h" #include "components/signin/core/browser/account_tracker_service.h" #include "components/signin/core/browser/fake_account_fetcher_service.h" +#include "components/sync/test/fake_server/fake_server.h" +#include "components/sync/test/fake_server/fake_server_network_resources.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/test_navigation_observer.h" #include "net/url_request/test_url_fetcher_factory.h" #include "services/device/public/cpp/test/scoped_geolocation_overrider.h" +#include "services/identity/public/cpp/identity_manager.h" +#include "services/identity/public/cpp/identity_test_utils.h" #include "ui/events/base_event_utils.h" #include "ui/views/bubble/bubble_frame_view.h" #include "ui/views/controls/button/button.h" @@ -71,21 +75,38 @@ SaveCardBubbleViewsBrowserTestBase::SaveCardBubbleViewsBrowserTestBase( const std::string& test_file_path) - : test_file_path_(test_file_path) {} + : SyncTest(SINGLE_CLIENT), test_file_path_(test_file_path) {} SaveCardBubbleViewsBrowserTestBase::~SaveCardBubbleViewsBrowserTestBase() {} void SaveCardBubbleViewsBrowserTestBase::SetUpOnMainThread() { + SyncTest::SetUpOnMainThread(); + // Set up the HTTPS server (uses the embedded_test_server). ASSERT_TRUE(embedded_test_server()->InitializeAndListen()); embedded_test_server()->ServeFilesFromSourceDirectory( "components/test/data/autofill"); embedded_test_server()->StartAcceptingConnections(); - // Set up the URL fetcher. By providing an Impl, unexpected calls (sync, etc.) - // won't cause the test to crash. - url_fetcher_factory_ = std::make_unique<net::FakeURLFetcherFactory>( - new net::URLFetcherImplFactory()); + ProfileSyncServiceFactory::GetForProfile(browser()->profile()) + ->OverrideNetworkResourcesForTest( + std::make_unique<fake_server::FakeServerNetworkResources>( + GetFakeServer()->AsWeakPtr())); + + std::string username; +#if defined(OS_CHROMEOS) + // In ChromeOS browser tests, the profile may already by authenticated with + // stub account |user_manager::kStubUserEmail|. + AccountInfo info = IdentityManagerFactory::GetForProfile(browser()->profile()) + ->GetPrimaryAccountInfo(); + username = info.email; +#endif + if (username.empty()) + username = "user@gmail.com"; + + harness_ = ProfileSyncServiceHarness::Create( + browser()->profile(), username, "password", + ProfileSyncServiceHarness::SigninType::FAKE_SIGNIN); // Set up the URL loader factory for the payments client so we can intercept // those network requests too. @@ -112,8 +133,6 @@ // Set up the fake geolocation data. geolocation_overrider_ = std::make_unique<device::ScopedGeolocationOverrider>( kFakeGeolocationLatitude, kFakeGeolocationLongitude); - - NavigateTo(test_file_path_); } void SaveCardBubbleViewsBrowserTestBase::NavigateTo( @@ -166,54 +185,13 @@ event_waiter_->OnEvent(DialogEvent::BUBBLE_CLOSED); } -void SaveCardBubbleViewsBrowserTestBase::SetUpInProcessBrowserTestFixture() { - will_create_browser_context_services_subscription_ = - BrowserContextDependencyManager::GetInstance() - ->RegisterWillCreateBrowserContextServicesCallbackForTesting( - base::BindRepeating(&SaveCardBubbleViewsBrowserTestBase:: - OnWillCreateBrowserContextServices, - base::Unretained(this))); -} - -void SaveCardBubbleViewsBrowserTestBase::OnWillCreateBrowserContextServices( - content::BrowserContext* context) { - // Replace the signin manager and account fetcher service with fakes. - SigninManagerFactory::GetInstance()->SetTestingFactory( - context, base::BindRepeating(&BuildFakeSigninManagerForTesting)); - AccountFetcherServiceFactory::GetInstance()->SetTestingFactory( - context, - base::BindRepeating(&FakeAccountFetcherServiceBuilder::BuildForTests)); -} - -void SaveCardBubbleViewsBrowserTestBase::SignInWithFullName( +void SaveCardBubbleViewsBrowserTestBase::SetAccountFullName( const std::string& full_name) { - // TODO(crbug.com/859761): Can this function be used to remove the - // observer_for_testing_ hack in - // CreditCardSaveManager::IsCreditCardUploadEnabled()? - FakeSigninManagerForTesting* signin_manager = - static_cast<FakeSigninManagerForTesting*>( - SigninManagerFactory::GetInstance()->GetForProfile( - browser()->profile())); - - // Note: Chrome OS tests seem to rely on these specific login values, so - // changing them is probably not recommended. - constexpr char kTestEmail[] = "stub-user@example.com"; - constexpr char kTestGaiaId[] = "stub-user@example.com"; -#if !defined(OS_CHROMEOS) - signin_manager->SignIn(kTestGaiaId, kTestEmail, "password"); -#else - AccountTrackerService* account_tracker_service = - AccountTrackerServiceFactory::GetForProfile(browser()->profile()); - signin_manager->SignIn(account_tracker_service->PickAccountIdForAccount( - kTestGaiaId, kTestEmail)); -#endif - FakeAccountFetcherService* account_fetcher_service = - static_cast<FakeAccountFetcherService*>( - AccountFetcherServiceFactory::GetForProfile(browser()->profile())); - account_fetcher_service->FakeUserInfoFetchSuccess( - signin_manager->GetAuthenticatedAccountId(), kTestEmail, kTestGaiaId, - AccountTrackerService::kNoHostedDomainFound, full_name, - /*given_name=*/std::string(), "locale", "avatar.jpg"); + identity::IdentityManager* identity_manager = + IdentityManagerFactory::GetForProfile(browser()->profile()); + AccountInfo info = identity_manager->GetPrimaryAccountInfo(); + info.full_name = full_name; + identity::UpdateAccountInfoForAccount(identity_manager, info); } void SaveCardBubbleViewsBrowserTestBase::SubmitForm() {
diff --git a/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest_base.h b/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest_base.h index f20f143..7a4c2f4 100644 --- a/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest_base.h +++ b/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest_base.h
@@ -13,6 +13,7 @@ #include "base/command_line.h" #include "base/macros.h" #include "base/test/scoped_feature_list.h" +#include "chrome/browser/sync/test/integration/sync_test.h" #include "chrome/browser/ui/autofill/save_card_bubble_controller_impl.h" #include "chrome/browser/ui/views/autofill/dialog_view_ids.h" #include "chrome/browser/ui/views/autofill/save_card_bubble_views.h" @@ -37,7 +38,7 @@ // Base class for any interactive SaveCardBubbleViews browser test that will // need to show and interact with the offer-to-save bubble. class SaveCardBubbleViewsBrowserTestBase - : public InProcessBrowserTest, + : public SyncTest, public CreditCardSaveManager::ObserverForTest, public SaveCardBubbleControllerImpl::ObserverForTest { public: @@ -76,14 +77,8 @@ void OnBubbleShown() override; void OnBubbleClosed() override; - // BrowserTestBase: - void SetUpInProcessBrowserTestFixture() override; - - // Sets up the ability to sign in the user. - void OnWillCreateBrowserContextServices(content::BrowserContext* context); - - // Signs in the user with the provided |full_name|. - void SignInWithFullName(const std::string& full_name); + // Sets the full name of the signed-in account to the provided |full_name|. + void SetAccountFullName(const std::string& full_name); // Will call JavaScript to fill and submit the form in different ways. void SubmitForm(); @@ -162,6 +157,8 @@ base::test::ScopedFeatureList scoped_feature_list_; + std::unique_ptr<ProfileSyncServiceHarness> harness_; + private: std::unique_ptr<autofill::EventWaiter<DialogEvent>> event_waiter_; std::unique_ptr<net::FakeURLFetcherFactory> url_fetcher_factory_;
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc index 8161fe4e..d95b2a6 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc
@@ -31,6 +31,7 @@ #include "third_party/metrics_proto/omnibox_event.pb.h" #include "ui/base/ime/input_method.h" #include "ui/base/ime/text_edit_commands.h" +#include "ui/base/ui_base_features.h" #include "ui/events/event_utils.h" #include "ui/events/keycodes/dom/dom_code.h" #include "ui/gfx/geometry/rect.h" @@ -664,6 +665,9 @@ } TEST_F(OmniboxViewViewsSteadyStateElisionsTest, GestureTaps) { + // TODO(crbug.com/916256): fix for mash. + if (features::IsSingleProcessMash()) + return; ui::GestureEvent tap_down(0, 0, 0, ui::EventTimeForNow(), ui::GestureEventDetails(ui::ET_GESTURE_TAP_DOWN)); omnibox_textfield_view()->OnGestureEvent(&tap_down);
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view_browsertest.cc b/chrome/browser/ui/views/profiles/profile_chooser_view_browsertest.cc index e90717a6..78db2aa 100644 --- a/chrome/browser/ui/views/profiles/profile_chooser_view_browsertest.cc +++ b/chrome/browser/ui/views/profiles/profile_chooser_view_browsertest.cc
@@ -236,7 +236,14 @@ DISALLOW_COPY_AND_ASSIGN(ProfileChooserViewExtensionsTest); }; -IN_PROC_BROWSER_TEST_F(ProfileChooserViewExtensionsTest, SigninButtonHasFocus) { +// TODO(https://crbug.com/855867): This test is flaky on Windows. +#if defined(OS_WIN) +#define MAYBE_SigninButtonHasFocus DISABLED_SigninButtonHasFocus +#else +#define MAYBE_SigninButtonHasFocus SigninButtonHasFocus +#endif +IN_PROC_BROWSER_TEST_F(ProfileChooserViewExtensionsTest, + MAYBE_SigninButtonHasFocus) { ASSERT_TRUE(profiles::IsMultipleProfilesEnabled()); ASSERT_NO_FATAL_FAILURE(OpenProfileChooserView(browser()));
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view_interactive_uitest.cc b/chrome/browser/ui/views/toolbar/toolbar_view_interactive_uitest.cc index a984bb7..8f3c1c9 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_view_interactive_uitest.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_view_interactive_uitest.cc
@@ -125,7 +125,7 @@ void ToolbarViewInteractiveUITest::FinishDragAndDrop( base::Closure quit_closure) { - base::ScopedAllowBaseSyncPrimitivesForTesting allow_thread_join; + base::ScopedAllowBlockingForTesting allow_thread_join; dnd_thread_.reset(); TestWhileInDragOperation(); ui_controls::SendMouseEventsNotifyWhenDone(ui_controls::LEFT, ui_controls::UP,
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser_unittest.cc b/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser_unittest.cc index 01d482a0..083f591 100644 --- a/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser_unittest.cc +++ b/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser_unittest.cc
@@ -9,9 +9,9 @@ #include "ash/display/display_configuration_controller.h" #include "ash/shell.h" -#include "ash/test/ash_test_base.h" #include "base/run_loop.h" #include "base/strings/string_number_conversions.h" +#include "chrome/test/base/chrome_ash_test_base.h" #include "mojo/public/cpp/bindings/binding.h" #include "services/ws/public/cpp/input_devices/input_device_client_test_api.h" #include "testing/gtest/include/gtest/gtest.h" @@ -73,17 +73,17 @@ DISALLOW_COPY_AND_ASSIGN(TestCrosDisplayConfig); }; -class OobeDisplayChooserTest : public ash::AshTestBase { +class OobeDisplayChooserTest : public ChromeAshTestBase { public: - OobeDisplayChooserTest() : ash::AshTestBase() {} + OobeDisplayChooserTest() : ChromeAshTestBase() {} int64_t GetPrimaryDisplay() { return display::Screen::GetScreen()->GetPrimaryDisplay().id(); } - // ash::AshTestBase: + // ChromeAshTestBase: void SetUp() override { - ash::AshTestBase::SetUp(); + ChromeAshTestBase::SetUp(); cros_display_config_ = std::make_unique<TestCrosDisplayConfig>(); display_chooser_ = std::make_unique<OobeDisplayChooser>();
diff --git a/chrome/browser/ui/webui/omnibox/omnibox.mojom b/chrome/browser/ui/webui/omnibox/omnibox.mojom index 694726c1..4f5c26039 100644 --- a/chrome/browser/ui/webui/omnibox/omnibox.mojom +++ b/chrome/browser/ui/webui/omnibox/omnibox.mojom
@@ -55,6 +55,7 @@ interface OmniboxPageHandler { SetClientPage(OmniboxPage page); StartOmniboxQuery(string input_string, + bool reset_autocomplete_controller, int32 cursor_position, bool prevent_inline_autocomplete, bool prefer_keyword,
diff --git a/chrome/browser/ui/webui/omnibox/omnibox_page_handler.cc b/chrome/browser/ui/webui/omnibox/omnibox_page_handler.cc index a7450a40..ca20ae7 100644 --- a/chrome/browser/ui/webui/omnibox/omnibox_page_handler.cc +++ b/chrome/browser/ui/webui/omnibox/omnibox_page_handler.cc
@@ -189,6 +189,7 @@ } void OmniboxPageHandler::StartOmniboxQuery(const std::string& input_string, + bool reset_autocomplete_controller, int32_t cursor_position, bool prevent_inline_autocomplete, bool prefer_keyword, @@ -198,7 +199,8 @@ // variable (or something else) and some providers will short-circuit // important logic and return stale results. In short, we want the // actual results to not depend on the state of the previous request. - ResetController(); + if (reset_autocomplete_controller) + ResetController(); time_omnibox_started_ = base::Time::Now(); input_ = AutocompleteInput( base::UTF8ToUTF16(input_string), cursor_position,
diff --git a/chrome/browser/ui/webui/omnibox/omnibox_page_handler.h b/chrome/browser/ui/webui/omnibox/omnibox_page_handler.h index bd972c1..f8c8c5c 100644 --- a/chrome/browser/ui/webui/omnibox/omnibox_page_handler.h +++ b/chrome/browser/ui/webui/omnibox/omnibox_page_handler.h
@@ -39,6 +39,7 @@ // mojom::OmniboxPageHandler overrides: void SetClientPage(mojom::OmniboxPagePtr page) override; void StartOmniboxQuery(const std::string& input_string, + bool reset_autocomplete_controller, int32_t cursor_position, bool prevent_inline_autocomplete, bool prefer_keyword,
diff --git a/chrome/browser/ui/window_sizer/window_sizer_ash_unittest.cc b/chrome/browser/ui/window_sizer/window_sizer_ash_unittest.cc index a0eee6b..88b20d9 100644 --- a/chrome/browser/ui/window_sizer/window_sizer_ash_unittest.cc +++ b/chrome/browser/ui/window_sizer/window_sizer_ash_unittest.cc
@@ -4,11 +4,11 @@ #include "ash/public/cpp/window_properties.h" #include "ash/shell.h" -#include "ash/test/ash_test_base.h" #include "base/memory/ptr_util.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/window_sizer/window_sizer_common_unittest.h" #include "chrome/common/chrome_switches.h" +#include "chrome/test/base/chrome_ash_test_base.h" #include "chrome/test/base/test_browser_window_aura.h" #include "chrome/test/base/testing_profile.h" #include "content/public/test/render_view_test.h" @@ -22,7 +22,7 @@ #include "ui/display/screen.h" #include "ui/wm/public/activation_client.h" -class WindowSizerAshTest : public ash::AshTestBase { +class WindowSizerAshTest : public ChromeAshTestBase { public: WindowSizerAshTest() = default; ~WindowSizerAshTest() override = default;
diff --git a/chrome/browser/web_applications/components/BUILD.gn b/chrome/browser/web_applications/components/BUILD.gn index ec2c12d8..953f5d0 100644 --- a/chrome/browser/web_applications/components/BUILD.gn +++ b/chrome/browser/web_applications/components/BUILD.gn
@@ -8,6 +8,8 @@ "install_manager.h", "pending_app_manager.cc", "pending_app_manager.h", + "web_app_audio_focus_id_map.cc", + "web_app_audio_focus_id_map.h", "web_app_constants.h", "web_app_data_retriever.cc", "web_app_data_retriever.h",
diff --git a/chrome/browser/web_applications/components/web_app_audio_focus_id_map.cc b/chrome/browser/web_applications/components/web_app_audio_focus_id_map.cc new file mode 100644 index 0000000..9727e939 --- /dev/null +++ b/chrome/browser/web_applications/components/web_app_audio_focus_id_map.cc
@@ -0,0 +1,25 @@ +// 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/web_applications/components/web_app_audio_focus_id_map.h" + +#include "base/unguessable_token.h" + +namespace web_app { + +WebAppAudioFocusIdMap::WebAppAudioFocusIdMap() = default; + +WebAppAudioFocusIdMap::~WebAppAudioFocusIdMap() = default; + +const base::UnguessableToken& WebAppAudioFocusIdMap::CreateOrGetIdForApp( + const AppId& app_id) { + auto it = ids_.find(app_id); + + if (it == ids_.end()) + it = ids_.emplace(app_id, base::UnguessableToken::Create()).first; + + return it->second; +} + +} // namespace web_app
diff --git a/chrome/browser/web_applications/components/web_app_audio_focus_id_map.h b/chrome/browser/web_applications/components/web_app_audio_focus_id_map.h new file mode 100644 index 0000000..7b22e96 --- /dev/null +++ b/chrome/browser/web_applications/components/web_app_audio_focus_id_map.h
@@ -0,0 +1,40 @@ +// 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_WEB_APPLICATIONS_COMPONENTS_WEB_APP_AUDIO_FOCUS_ID_MAP_H_ +#define CHROME_BROWSER_WEB_APPLICATIONS_COMPONENTS_WEB_APP_AUDIO_FOCUS_ID_MAP_H_ + +#include <map> + +#include "base/macros.h" +#include "chrome/browser/web_applications/components/web_app_helpers.h" + +namespace base { +class UnguessableToken; +} + +namespace web_app { + +// WebAppAudioFocusIdMap stores audio focus group ids for web apps. These group +// ids are shared across all media sessions associated with the web app and are +// used so that the app has separate audio focus from the browser. +class WebAppAudioFocusIdMap { + public: + WebAppAudioFocusIdMap(); + ~WebAppAudioFocusIdMap(); + + protected: + friend class WebAppTabHelperBase; + + const base::UnguessableToken& CreateOrGetIdForApp(const AppId& app_id); + + private: + std::map<AppId, base::UnguessableToken> ids_; + + DISALLOW_COPY_AND_ASSIGN(WebAppAudioFocusIdMap); +}; + +} // namespace web_app + +#endif // CHROME_BROWSER_WEB_APPLICATIONS_COMPONENTS_WEB_APP_AUDIO_FOCUS_ID_MAP_H_
diff --git a/chrome/browser/web_applications/components/web_app_shortcut_mac.h b/chrome/browser/web_applications/components/web_app_shortcut_mac.h index d30061b..c200ea86 100644 --- a/chrome/browser/web_applications/components/web_app_shortcut_mac.h +++ b/chrome/browser/web_applications/components/web_app_shortcut_mac.h
@@ -25,10 +25,6 @@ namespace web_app { -// Returns the full path of the .app shim that would be created by -// CreateShortcuts(). -base::FilePath GetAppInstallPath(const ShortcutInfo& shortcut_info); - // Callback type for MaybeLaunchShortcut. If |shim_process| is valid then the // app shim was launched. using LaunchAppCallback = base::OnceCallback<void(base::Process shim_process)>; @@ -63,7 +59,7 @@ virtual ~WebAppShortcutCreator(); // Returns the base name for the shortcut. - base::FilePath GetShortcutBasename() const; + virtual base::FilePath GetShortcutBasename() const; // Returns a path to the Chrome Apps folder in the relevant applications // folder. E.g. ~/Applications or /Applications. @@ -72,6 +68,10 @@ // The full path to the app bundle under the relevant Applications folder. base::FilePath GetApplicationsShortcutPath() const; + // Returns the paths to app bundles with the given id as found by launch + // services, sorted by preference. + std::vector<base::FilePath> GetAppBundlesById() const; + // The full path to the app bundle under the profile folder. base::FilePath GetInternalShortcutPath() const; @@ -84,10 +84,7 @@ virtual void RevealAppShimInFinder() const; protected: - // Returns a path to an app bundle with the given id. Or an empty path if no - // matching bundle was found. - // Protected and virtual so it can be mocked out for testing. - virtual base::FilePath GetAppBundleById(const std::string& bundle_id) const; + virtual std::vector<base::FilePath> GetAppBundlesByIdUnsorted() const; private: FRIEND_TEST_ALL_PREFIXES(WebAppShortcutCreatorTest, DeleteShortcuts);
diff --git a/chrome/browser/web_applications/components/web_app_shortcut_mac.mm b/chrome/browser/web_applications/components/web_app_shortcut_mac.mm index 37fc2ba4..aeb06ee 100644 --- a/chrome/browser/web_applications/components/web_app_shortcut_mac.mm +++ b/chrome/browser/web_applications/components/web_app_shortcut_mac.mm
@@ -7,6 +7,7 @@ #import <Cocoa/Cocoa.h> #include <stdint.h> +#include <algorithm> #include <map> #include <utility> @@ -187,19 +188,16 @@ const web_app::ShortcutInfo& shortcut_info) { base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::MAY_BLOCK); - // TODO(https://crbug.com/913394): Attempt to locate the shim's path using - // LSCopyApplicationURLsForBundleIdentifier. - base::FilePath shim_path = web_app::GetAppInstallPath(shortcut_info); + web_app::WebAppShortcutCreator shortcut_creator( + web_app::internals::GetShortcutDataDir(shortcut_info), &shortcut_info); - if (shim_path.empty() || !base::PathExists(shim_path) || - !HasSameUserDataDir(shim_path)) { - // The user may have deleted the copy in the Applications folder, use the - // one in the web app's |app_data_dir_|. - base::FilePath app_data_dir = web_app::GetWebAppDataDirectory( - shortcut_info.profile_path, shortcut_info.extension_id, GURL()); - shim_path = app_data_dir.Append(shim_path.BaseName()); - } + // Attempt to locate the shim's path using LaunchServices. + std::vector<base::FilePath> shim_paths = shortcut_creator.GetAppBundlesById(); + // Add as a last resort the copy in the web app's |app_data_dir_|, in case + // the user deleted all other copies. + shim_paths.push_back(shortcut_creator.GetInternalShortcutPath()); + base::FilePath shim_path = shim_paths.front(); if (!base::PathExists(shim_path)) { base::PostTaskWithTraits( FROM_HERE, {content::BrowserThread::UI}, @@ -420,14 +418,6 @@ return true; } -void DeletePathAndParentIfEmpty(const base::FilePath& app_path) { - DCHECK(!app_path.empty()); - base::DeleteFile(app_path, true); - base::FilePath apps_folder = app_path.DirName(); - if (base::IsDirectoryEmpty(apps_folder)) - base::DeleteFile(apps_folder, false); -} - bool IsShimForProfile(const base::FilePath& base_name, const std::string& profile_base_name) { if (!base::StartsWith(base_name.value(), profile_base_name, @@ -680,17 +670,27 @@ } void WebAppShortcutCreator::DeleteShortcuts() { - base::FilePath app_path = GetApplicationsShortcutPath(); - if (!app_path.empty() && HasSameUserDataDir(app_path)) - DeletePathAndParentIfEmpty(app_path); + base::FilePath apps_dir = GetApplicationsDirname(); + bool deleted_instance_in_apps_dir = false; - // In case the user has moved/renamed/copied the app bundle. - base::FilePath bundle_path = GetAppBundleById(GetBundleIdentifier()); - if (!bundle_path.empty() && HasSameUserDataDir(bundle_path)) + // Remove all instances found by LaunchServices. + std::vector<base::FilePath> bundle_paths = GetAppBundlesById(); + for (const auto& bundle_path : bundle_paths) { + deleted_instance_in_apps_dir |= apps_dir.IsParent(bundle_path); base::DeleteFile(bundle_path, true); + } - // Delete the internal one. - DeletePathAndParentIfEmpty(GetInternalShortcutPath()); + // If we just deleted the last entry in Chrome's apps directory, remove the + // apps directory itself. In practice, we never do this, because the the apps + // directory still has its .DS_Store and .localized files. + if (deleted_instance_in_apps_dir && base::IsDirectoryEmpty(apps_dir)) + base::DeleteFile(apps_dir, false); + + // Delete the internal one (and its parent directory if it is empty -- this + // actually does happen often, because the path is rarely viewed in Finder). + base::DeleteFile(GetInternalShortcutPath(), true); + if (base::IsDirectoryEmpty(app_data_dir_)) + base::DeleteFile(app_data_dir_, false); } bool WebAppShortcutCreator::UpdateShortcuts() { @@ -713,8 +713,13 @@ // |g_app_shims_allow_update_and_launch_in_tests| can properly mock out all // the calls below. if (!g_app_shims_allow_update_and_launch_in_tests) { - if (app_path.empty() || !base::PathExists(app_path)) - app_path = GetAppBundleById(GetBundleIdentifier()); + if (app_path.empty() || !base::PathExists(app_path)) { + auto app_paths = GetAppBundlesById(); + if (!app_paths.empty()) + app_path = app_paths.front(); + else + app_path = base::FilePath(); + } if (app_path.empty()) { if (profile_copy_exists && info_->from_bookmark) { @@ -882,19 +887,59 @@ return [plist writeToFile:plist_path atomically:YES]; } -base::FilePath WebAppShortcutCreator::GetAppBundleById( - const std::string& bundle_id) const { +std::vector<base::FilePath> WebAppShortcutCreator::GetAppBundlesByIdUnsorted() + const { base::ScopedCFTypeRef<CFStringRef> bundle_id_cf( - base::SysUTF8ToCFStringRef(bundle_id)); - CFURLRef url_ref = NULL; - OSStatus status = LSFindApplicationForInfo( - kLSUnknownCreator, bundle_id_cf.get(), NULL, NULL, &url_ref); - if (status != noErr) - return base::FilePath(); + base::SysUTF8ToCFStringRef(GetBundleIdentifier())); - base::ScopedCFTypeRef<CFURLRef> url(url_ref); - NSString* path_string = [base::mac::CFToNSCast(url.get()) path]; - return base::FilePath([path_string fileSystemRepresentation]); + // Retrieve the URLs found by LaunchServices. + base::scoped_nsobject<NSArray> urls; + if (@available(macOS 10.10, *)) { + urls.reset(base::mac::CFToNSCast( + LSCopyApplicationURLsForBundleIdentifier(bundle_id_cf.get(), nullptr))); + } else { + base::ScopedCFTypeRef<CFURLRef> cf_url; + LSFindApplicationForInfo(kLSUnknownCreator, bundle_id_cf.get(), NULL, NULL, + cf_url.InitializeInto()); + if (cf_url) + urls.reset([@[ base::mac::CFToNSCast(cf_url) ] retain]); + } + + // Store only those results corresponding to this user data dir. + std::vector<base::FilePath> paths; + for (NSURL* url : urls.get()) { + NSString* path_string = [url path]; + base::FilePath path([path_string fileSystemRepresentation]); + if (HasSameUserDataDir(path)) + paths.push_back(path); + } + return paths; +} + +std::vector<base::FilePath> WebAppShortcutCreator::GetAppBundlesById() const { + std::vector<base::FilePath> paths = GetAppBundlesByIdUnsorted(); + + // Sort the matches by preference. + base::FilePath default_path = GetApplicationsShortcutPath(); + base::FilePath apps_dir = GetApplicationsDirname(); + auto compare = [default_path, apps_dir](const base::FilePath& a, + const base::FilePath& b) { + if (a == b) + return false; + // The default install path is preferred above all others. + if (a == default_path) + return true; + if (b == default_path) + return false; + // Paths in ~/Applications are preferred to paths not in ~/Applications. + bool a_in_apps_dir = apps_dir.IsParent(a); + bool b_in_apps_dir = apps_dir.IsParent(b); + if (a_in_apps_dir != b_in_apps_dir) + return a_in_apps_dir > b_in_apps_dir; + return a < b; + }; + std::sort(paths.begin(), paths.end(), compare); + return paths; } std::string WebAppShortcutCreator::GetBundleIdentifier() const { @@ -915,12 +960,14 @@ } void WebAppShortcutCreator::RevealAppShimInFinder() const { - base::FilePath app_path = GetApplicationsShortcutPath(); - if (app_path.empty()) - return; + // Note that RevealAppShimInFinder is called immediately after requesting to + // build the app shim. This almost always happens before the app shim has + // completed building (and so we just open the Chrome apps folder). // Check if the app shim exists. - if (base::PathExists(app_path)) { + auto app_paths = GetAppBundlesById(); + if (!app_paths.empty()) { + base::FilePath app_path = app_paths.front(); // Use selectFile to show the contents of parent directory with the app // shim selected. [[NSWorkspace sharedWorkspace] @@ -929,20 +976,17 @@ return; } - // Otherwise, go up a directory. - app_path = app_path.DirName(); + // Otherwise, open the Chrome apps folder. + base::FilePath apps_path = GetApplicationsDirname(); + // Check if the Chrome apps folder exists, otherwise go up to ~/Applications. - if (!base::PathExists(app_path)) - app_path = app_path.DirName(); + if (!base::PathExists(apps_path)) + apps_path = apps_path.DirName(); + // Since |app_path| is a directory, use openFile to show the contents of // that directory in Finder. [[NSWorkspace sharedWorkspace] - openFile:base::mac::FilePathToNSString(app_path)]; -} - -base::FilePath GetAppInstallPath(const ShortcutInfo& shortcut_info) { - WebAppShortcutCreator shortcut_creator(base::FilePath(), &shortcut_info); - return shortcut_creator.GetApplicationsShortcutPath(); + openFile:base::mac::FilePathToNSString(apps_path)]; } void MaybeLaunchShortcut(std::unique_ptr<ShortcutInfo> shortcut_info,
diff --git a/chrome/browser/web_applications/components/web_app_shortcut_mac_unittest.mm b/chrome/browser/web_applications/components/web_app_shortcut_mac_unittest.mm index e05c7b4..5296fe3e 100644 --- a/chrome/browser/web_applications/components/web_app_shortcut_mac_unittest.mm +++ b/chrome/browser/web_applications/components/web_app_shortcut_mac_unittest.mm
@@ -48,14 +48,25 @@ : WebAppShortcutCreator(app_data_dir, shortcut_info) {} MOCK_CONST_METHOD0(GetApplicationsDirname, base::FilePath()); - MOCK_CONST_METHOD1(GetAppBundleById, - base::FilePath(const std::string& bundle_id)); + MOCK_CONST_METHOD0(GetAppBundlesByIdUnsorted, std::vector<base::FilePath>()); MOCK_CONST_METHOD0(RevealAppShimInFinder, void()); private: DISALLOW_COPY_AND_ASSIGN(WebAppShortcutCreatorMock); }; +class WebAppShortcutCreatorSortingMock : public web_app::WebAppShortcutCreator { + public: + WebAppShortcutCreatorSortingMock(const base::FilePath& app_data_dir, + const web_app::ShortcutInfo* shortcut_info) + : WebAppShortcutCreator(app_data_dir, shortcut_info) {} + + MOCK_CONST_METHOD0(GetAppBundlesByIdUnsorted, std::vector<base::FilePath>()); + + private: + DISALLOW_COPY_AND_ASSIGN(WebAppShortcutCreatorSortingMock); +}; + std::unique_ptr<web_app::ShortcutInfo> GetShortcutInfo() { std::unique_ptr<web_app::ShortcutInfo> info(new web_app::ShortcutInfo); info->extension_id = "extensionid"; @@ -183,8 +194,10 @@ std::string expected_bundle_id = kFakeChromeBundleId; expected_bundle_id += ".app.Profile-1-" + info_->extension_id; - EXPECT_CALL(shortcut_creator, GetAppBundleById(expected_bundle_id)) - .WillOnce(Return(other_shim_path)); + std::vector<base::FilePath> bundle_by_id_paths; + bundle_by_id_paths.push_back(other_shim_path); + EXPECT_CALL(shortcut_creator, GetAppBundlesByIdUnsorted()) + .WillOnce(Return(bundle_by_id_paths)); EXPECT_TRUE(shortcut_creator.BuildShortcut(other_shim_path)); @@ -194,9 +207,10 @@ EXPECT_FALSE(base::PathExists(shim_path_)); EXPECT_TRUE(base::PathExists(other_shim_path.Append("Contents"))); - // Also test case where GetAppBundleById fails. - EXPECT_CALL(shortcut_creator, GetAppBundleById(expected_bundle_id)) - .WillOnce(Return(base::FilePath())); + // Also test case where GetAppBundlesByIdUnsorted fails. + bundle_by_id_paths.clear(); + EXPECT_CALL(shortcut_creator, GetAppBundlesByIdUnsorted()) + .WillOnce(Return(bundle_by_id_paths)); EXPECT_TRUE(shortcut_creator.BuildShortcut(other_shim_path)); @@ -222,8 +236,10 @@ std::string expected_bundle_id = kFakeChromeBundleId; expected_bundle_id += ".app.Profile-1-" + info_->extension_id; - EXPECT_CALL(shortcut_creator, GetAppBundleById(expected_bundle_id)) - .WillOnce(Return(shim_path_)); + std::vector<base::FilePath> bundle_by_id_paths; + bundle_by_id_paths.push_back(shim_path_); + EXPECT_CALL(shortcut_creator, GetAppBundlesByIdUnsorted()) + .WillOnce(Return(bundle_by_id_paths)); EXPECT_TRUE(shortcut_creator.BuildShortcut(other_shim_path)); @@ -253,8 +269,10 @@ std::string expected_bundle_id = kFakeChromeBundleId; expected_bundle_id += ".app.Profile-1-" + info_->extension_id; - EXPECT_CALL(shortcut_creator, GetAppBundleById(expected_bundle_id)) - .WillOnce(Return(other_shim_path)); + std::vector<base::FilePath> bundle_by_id_paths; + bundle_by_id_paths.push_back(other_shim_path); + EXPECT_CALL(shortcut_creator, GetAppBundlesByIdUnsorted()) + .WillOnce(Return(bundle_by_id_paths)); EXPECT_TRUE(shortcut_creator.CreateShortcuts(SHORTCUT_CREATION_AUTOMATED, web_app::ShortcutLocations())); @@ -359,4 +377,22 @@ web_app::ShortcutLocations())); } +TEST_F(WebAppShortcutCreatorTest, SortAppBundles) { + base::FilePath app_dir("/home/apps"); + NiceMock<WebAppShortcutCreatorSortingMock> shortcut_creator(app_dir, + info_.get()); + base::FilePath a = shortcut_creator.GetApplicationsShortcutPath(); + base::FilePath b = shortcut_creator.GetApplicationsDirname().Append("a"); + base::FilePath c = shortcut_creator.GetApplicationsDirname().Append("z"); + base::FilePath d("/a/b/c"); + base::FilePath e("/z/y/w"); + std::vector<base::FilePath> unsorted = {e, c, a, d, b}; + std::vector<base::FilePath> sorted = {a, b, c, d, e}; + + EXPECT_CALL(shortcut_creator, GetAppBundlesByIdUnsorted()) + .WillOnce(Return(unsorted)); + std::vector<base::FilePath> result = shortcut_creator.GetAppBundlesById(); + EXPECT_EQ(result, sorted); +} + } // namespace web_app
diff --git a/chrome/browser/web_applications/components/web_app_tab_helper_base.cc b/chrome/browser/web_applications/components/web_app_tab_helper_base.cc index 09a7dbf..ef82aa9 100644 --- a/chrome/browser/web_applications/components/web_app_tab_helper_base.cc +++ b/chrome/browser/web_applications/components/web_app_tab_helper_base.cc
@@ -4,6 +4,9 @@ #include "chrome/browser/web_applications/components/web_app_tab_helper_base.h" +#include "base/unguessable_token.h" +#include "chrome/browser/web_applications/components/web_app_audio_focus_id_map.h" +#include "content/public/browser/media_session.h" #include "content/public/browser/navigation_handle.h" namespace web_app { @@ -15,12 +18,26 @@ WebAppTabHelperBase::~WebAppTabHelperBase() = default; +void WebAppTabHelperBase::SetAudioFocusIdMap( + WebAppAudioFocusIdMap* audio_focus_id_map) { + DCHECK(!audio_focus_id_map_ && audio_focus_id_map); + + audio_focus_id_map_ = audio_focus_id_map; +} + void WebAppTabHelperBase::SetAppId(const AppId& app_id) { + if (app_id_ == app_id) + return; + app_id_ = app_id; + + OnAssociatedAppChanged(); } void WebAppTabHelperBase::ResetAppId() { app_id_.clear(); + + OnAssociatedAppChanged(); } void WebAppTabHelperBase::DidFinishNavigation( @@ -42,4 +59,19 @@ new_tab_helper->SetAppId(app_id()); } +void WebAppTabHelperBase::OnAssociatedAppChanged() { + UpdateAudioFocusGroupId(); +} + +void WebAppTabHelperBase::UpdateAudioFocusGroupId() { + if (!app_id_.empty() && IsInAppWindow()) { + audio_focus_group_id_ = audio_focus_id_map_->CreateOrGetIdForApp(app_id_); + } else { + audio_focus_group_id_ = base::UnguessableToken::Null(); + } + + content::MediaSession::Get(web_contents()) + ->SetAudioFocusGroupId(audio_focus_group_id_); +} + } // namespace web_app
diff --git a/chrome/browser/web_applications/components/web_app_tab_helper_base.h b/chrome/browser/web_applications/components/web_app_tab_helper_base.h index c68ae31..d372420 100644 --- a/chrome/browser/web_applications/components/web_app_tab_helper_base.h +++ b/chrome/browser/web_applications/components/web_app_tab_helper_base.h
@@ -6,6 +6,7 @@ #define CHROME_BROWSER_WEB_APPLICATIONS_COMPONENTS_WEB_APP_TAB_HELPER_BASE_H_ #include "base/macros.h" +#include "base/unguessable_token.h" #include "chrome/browser/web_applications/components/web_app_helpers.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" @@ -16,6 +17,8 @@ namespace web_app { +class WebAppAudioFocusIdMap; + // Per-tab web app helper. Allows to associate a tab (web page) with a web app // (or legacy bookmark app). class WebAppTabHelperBase @@ -24,6 +27,11 @@ public: ~WebAppTabHelperBase() override; + // This provides a weak reference to the current audio focus id map instance + // which is owned by WebAppProvider. This is used to ensure that all web + // contents associated with a web app shared the same audio focus group id. + void SetAudioFocusIdMap(WebAppAudioFocusIdMap* audio_focus_id_map); + const AppId& app_id() const { return app_id_; } // Set app_id on web app installation or tab restore. @@ -52,10 +60,28 @@ // app_id_ with it. virtual AppId GetAppId(const GURL& url) = 0; + // Returns whether the associated web contents belongs to an app window. + virtual bool IsInAppWindow() const = 0; + private: + friend class WebAppAudioFocusBrowserTest; + + // Runs any logic when the associated app either changes or is removed. + void OnAssociatedAppChanged(); + + // Updates the audio focus group id based on the current web app. + void UpdateAudioFocusGroupId(); + // WebApp associated with this tab. Empty string if no app associated. AppId app_id_; + // The audio focus group id is used to group media sessions together for apps. + // We store the applied group id locally on the helper for testing. + base::UnguessableToken audio_focus_group_id_ = base::UnguessableToken::Null(); + + // Weak reference to audio focus group id storage. + WebAppAudioFocusIdMap* audio_focus_id_map_ = nullptr; + DISALLOW_COPY_AND_ASSIGN(WebAppTabHelperBase); };
diff --git a/chrome/browser/web_applications/extensions/BUILD.gn b/chrome/browser/web_applications/extensions/BUILD.gn index 57a3815..fc0ed916 100644 --- a/chrome/browser/web_applications/extensions/BUILD.gn +++ b/chrome/browser/web_applications/extensions/BUILD.gn
@@ -72,6 +72,7 @@ sources = [ "pending_bookmark_app_manager_browsertest.cc", + "web_app_audio_focus_browsertest.cc", ] defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ] @@ -84,7 +85,9 @@ "//chrome/browser/web_applications:web_app_group", "//chrome/browser/web_applications:web_applications_on_extensions", "//chrome/browser/web_applications/components", + "//chrome/test:test_support", "//chrome/test:test_support_ui", + "//extensions:test_support", "//extensions/browser", "//extensions/common", "//net:test_support",
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_tab_helper.cc b/chrome/browser/web_applications/extensions/bookmark_app_tab_helper.cc index b8f98f9..2389015 100644 --- a/chrome/browser/web_applications/extensions/bookmark_app_tab_helper.cc +++ b/chrome/browser/web_applications/extensions/bookmark_app_tab_helper.cc
@@ -8,6 +8,7 @@ #include "chrome/browser/web_applications/components/web_app_helpers.h" #include "chrome/browser/web_applications/extensions/bookmark_app_util.h" #include "chrome/common/chrome_features.h" +#include "chrome/common/extensions/api/url_handlers/url_handlers_parser.h" #include "extensions/common/extension.h" #include "url/gurl.h" @@ -55,4 +56,8 @@ return extension ? extension->id() : web_app::AppId(); } +bool BookmarkAppTabHelper::IsInAppWindow() const { + return util::IsWebContentsInAppWindow(web_contents()); +} + } // namespace extensions
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_tab_helper.h b/chrome/browser/web_applications/extensions/bookmark_app_tab_helper.h index a3a93f0..1a95fc81 100644 --- a/chrome/browser/web_applications/extensions/bookmark_app_tab_helper.h +++ b/chrome/browser/web_applications/extensions/bookmark_app_tab_helper.h
@@ -30,6 +30,7 @@ web_app::WebAppTabHelperBase* CloneForWebContents( content::WebContents* web_contents) const override; web_app::AppId GetAppId(const GURL& url) override; + bool IsInAppWindow() const override; private: DISALLOW_COPY_AND_ASSIGN(BookmarkAppTabHelper);
diff --git a/chrome/browser/web_applications/extensions/web_app_audio_focus_browsertest.cc b/chrome/browser/web_applications/extensions/web_app_audio_focus_browsertest.cc new file mode 100644 index 0000000..ce005c0 --- /dev/null +++ b/chrome/browser/web_applications/extensions/web_app_audio_focus_browsertest.cc
@@ -0,0 +1,206 @@ +// 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/macros.h" +#include "chrome/browser/extensions/browsertest_util.h" +#include "chrome/browser/extensions/extension_browsertest.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/web_applications/components/web_app_tab_helper_base.h" +#include "chrome/common/web_application_info.h" +#include "chrome/test/base/ui_test_utils.h" +#include "content/public/browser/notification_service.h" +#include "content/public/test/browser_test_utils.h" +#include "extensions/test/extension_test_message_listener.h" +#include "extensions/test/test_extension_dir.h" +#include "services/media_session/public/cpp/switches.h" + +namespace web_app { + +namespace { + +const char kAudioFocusTestPageURL[] = + "/extensions/audio_focus_web_app/main.html"; + +} // namespace + +// WebAppAudioFocusBrowserTest test that PWAs have separate audio +// focus from the rest of the browser. +class WebAppAudioFocusBrowserTest : public extensions::ExtensionBrowserTest { + public: + WebAppAudioFocusBrowserTest() = default; + ~WebAppAudioFocusBrowserTest() override = default; + + void SetUpCommandLine(base::CommandLine* command_line) override { + InProcessBrowserTest::SetUpCommandLine(command_line); + command_line->AppendSwitch(media_session::switches::kEnableAudioFocus); + } + + bool IsPaused(content::WebContents* web_contents) { + bool result = false; + EXPECT_TRUE(content::ExecuteScriptAndExtractBool(web_contents, "isPaused()", + &result)); + return result; + } + + bool WaitForPause(content::WebContents* web_contents) { + bool result = false; + EXPECT_TRUE(content::ExecuteScriptAndExtractBool( + web_contents, "waitForPause()", &result)); + return result; + } + + bool StartPlaying(content::WebContents* web_contents) { + bool result = false; + return content::ExecuteScriptAndExtractBool(web_contents, "startPlaying()", + &result) && + result; + } + + content::WebContents* AddTestPageTabAtIndex(int index) { + AddTabAtIndex(index, embedded_test_server()->GetURL(kAudioFocusTestPageURL), + ui::PAGE_TRANSITION_TYPED); + content::WebContents* tab = + browser()->tab_strip_model()->GetActiveWebContents(); + EXPECT_TRUE(content::WaitForLoadStop(tab)); + return tab; + } + + const base::UnguessableToken& GetAudioFocusGroupId( + content::WebContents* web_contents) { + WebAppTabHelperBase* helper = + WebAppTabHelperBase::FromWebContents(web_contents); + return helper->audio_focus_group_id_; + } + + private: + DISALLOW_COPY_AND_ASSIGN(WebAppAudioFocusBrowserTest); +}; + +IN_PROC_BROWSER_TEST_F(WebAppAudioFocusBrowserTest, AppHasDifferentAudioFocus) { + ASSERT_TRUE(embedded_test_server()->Start()); + GURL app_url = embedded_test_server()->GetURL(kAudioFocusTestPageURL); + + // Install the PWA. + WebApplicationInfo web_app_info; + web_app_info.app_url = app_url; + web_app_info.scope = app_url.GetWithoutFilename(); + web_app_info.open_as_window = true; + const extensions::Extension* extension = + extensions::browsertest_util::InstallBookmarkApp(browser()->profile(), + std::move(web_app_info)); + ASSERT_TRUE(extension); + + // Check that the extension has the correct type. + EXPECT_TRUE(extension->is_hosted_app()); + EXPECT_TRUE(extension->from_bookmark()); + + // Launch browser with media page. + content::WebContents* tab1 = AddTestPageTabAtIndex(0); + + // Start the test page playing. + EXPECT_TRUE(StartPlaying(tab1)); + + // Launch a second tab in the browser. + content::WebContents* tab2 = AddTestPageTabAtIndex(0); + + // Start the test page playing and check that both tabs now have focus. + EXPECT_TRUE(StartPlaying(tab2)); + EXPECT_FALSE(IsPaused(tab1)); + + // Check that the two tabs have no group id. + EXPECT_EQ(base::UnguessableToken::Null(), GetAudioFocusGroupId(tab1)); + EXPECT_EQ(base::UnguessableToken::Null(), GetAudioFocusGroupId(tab2)); + + // Launch the PWA. + content::WebContents* web_contents; + { + ui_test_utils::UrlLoadObserver url_observer( + app_url, content::NotificationService::AllSources()); + Browser* app_browser = extensions::browsertest_util::LaunchAppBrowser( + browser()->profile(), extension); + url_observer.Wait(); + + web_contents = app_browser->tab_strip_model()->GetActiveWebContents(); + EXPECT_TRUE(content::WaitForLoadStop(web_contents)); + } + + // Start the PWA playing and check that it has a group id. + EXPECT_TRUE(StartPlaying(web_contents)); + const base::UnguessableToken& group_id = GetAudioFocusGroupId(web_contents); + EXPECT_NE(base::UnguessableToken::Null(), group_id); + + // Check that the hosted app took audio focus from the browser tabs. + EXPECT_TRUE(WaitForPause(tab1)); + EXPECT_TRUE(WaitForPause(tab2)); + + // Open a new window from the PWA. It will open in the browser so it should + // have no group id. + { + content::WebContents* new_contents; + OpenWindow(web_contents, app_url, true, true, &new_contents); + EXPECT_EQ(base::UnguessableToken::Null(), + GetAudioFocusGroupId(new_contents)); + } + + // Navigate inside the PWA and make sure we keep the same group id. + { + std::string new_query_string = "t=1"; + url::Component new_query(0, new_query_string.length()); + url::Replacements<char> replacements; + replacements.SetQuery(new_query_string.c_str(), new_query); + GURL new_url = + web_contents->GetLastCommittedURL().ReplaceComponents(replacements); + NavigateInRenderer(web_contents, new_url); + EXPECT_EQ(group_id, GetAudioFocusGroupId(web_contents)); + } + + // Launch a second window for the PWA. It should have the same group id. + { + ui_test_utils::UrlLoadObserver url_observer( + app_url, content::NotificationService::AllSources()); + Browser* app_browser = extensions::browsertest_util::LaunchAppBrowser( + browser()->profile(), extension); + url_observer.Wait(); + + content::WebContents* new_contents = + app_browser->tab_strip_model()->GetActiveWebContents(); + EXPECT_TRUE(content::WaitForLoadStop(new_contents)); + + EXPECT_EQ(group_id, GetAudioFocusGroupId(new_contents)); + } + + // Navigate away and check that the group id is still the same because we are + // part of the same window. + NavigateInRenderer(web_contents, GURL("https://www.example.com")); + EXPECT_EQ(group_id, GetAudioFocusGroupId(web_contents)); +} + +IN_PROC_BROWSER_TEST_F(WebAppAudioFocusBrowserTest, + BookmarkAppHasSameAudioFocus) { + ASSERT_TRUE(embedded_test_server()->Start()); + GURL app_url = embedded_test_server()->GetURL(kAudioFocusTestPageURL); + + // Install the bookmark app. + WebApplicationInfo web_app_info; + web_app_info.app_url = app_url; + web_app_info.scope = app_url.GetWithoutFilename(); + web_app_info.open_as_window = true; + const extensions::Extension* extension = + extensions::browsertest_util::InstallBookmarkApp(profile(), + std::move(web_app_info)); + ASSERT_TRUE(extension); + + // Check that the extension has the correct type. + EXPECT_TRUE(extension->is_hosted_app()); + EXPECT_TRUE(extension->from_bookmark()); + + ui_test_utils::NavigateToURL(browser(), app_url); + content::WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + EXPECT_TRUE(content::WaitForLoadStop(web_contents)); + + EXPECT_EQ(base::UnguessableToken::Null(), GetAudioFocusGroupId(web_contents)); +} + +} // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_provider.cc b/chrome/browser/web_applications/web_app_provider.cc index c3b583a..3dabd94 100644 --- a/chrome/browser/web_applications/web_app_provider.cc +++ b/chrome/browser/web_applications/web_app_provider.cc
@@ -12,6 +12,7 @@ #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/web_applications/bookmark_apps/bookmark_app_install_manager.h" +#include "chrome/browser/web_applications/components/web_app_audio_focus_id_map.h" #include "chrome/browser/web_applications/components/web_app_constants.h" #include "chrome/browser/web_applications/components/web_app_helpers.h" #include "chrome/browser/web_applications/extensions/bookmark_app_tab_helper.h" @@ -51,6 +52,8 @@ } WebAppProvider::WebAppProvider(Profile* profile) { + audio_focus_id_map_ = std::make_unique<WebAppAudioFocusIdMap>(); + if (base::FeatureList::IsEnabled(features::kDesktopPWAsWithoutExtensions)) CreateWebAppsSubsystems(profile); else @@ -114,7 +117,20 @@ else extensions::BookmarkAppTabHelper::CreateForWebContents(web_contents); - return WebAppTabHelperBase::FromWebContents(web_contents); + WebAppTabHelperBase* helper = + WebAppTabHelperBase::FromWebContents(web_contents); + + WebAppProvider* provider = WebAppProvider::GetForWebContents(web_contents); + if (provider) { + // In some tests where Reset() has been called |audio_focus_id_map_| will be + // a nullptr. Therefore, we should recreate it. + if (!provider->audio_focus_id_map_) + provider->audio_focus_id_map_ = std::make_unique<WebAppAudioFocusIdMap>(); + + helper->SetAudioFocusIdMap(provider->audio_focus_id_map_.get()); + } + + return helper; } // static @@ -152,6 +168,7 @@ registrar_.reset(); database_.reset(); database_factory_.reset(); + audio_focus_id_map_.reset(); } void WebAppProvider::Observe(int type,
diff --git a/chrome/browser/web_applications/web_app_provider.h b/chrome/browser/web_applications/web_app_provider.h index 62f5d79c..f53c6841 100644 --- a/chrome/browser/web_applications/web_app_provider.h +++ b/chrome/browser/web_applications/web_app_provider.h
@@ -11,6 +11,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "chrome/browser/web_applications/components/pending_app_manager.h" +#include "chrome/browser/web_applications/components/web_app_helpers.h" #include "components/keyed_service/core/keyed_service.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" @@ -30,6 +31,7 @@ // Forward declarations of generalized interfaces. class PendingAppManager; class InstallManager; +class WebAppAudioFocusIdMap; class WebAppTabHelperBase; // Forward declarations for new extension-independent subsystems. @@ -87,6 +89,7 @@ std::vector<web_app::PendingAppManager::AppInfo>); // New extension-independent subsystems: + std::unique_ptr<WebAppAudioFocusIdMap> audio_focus_id_map_; std::unique_ptr<WebAppDatabaseFactory> database_factory_; std::unique_ptr<WebAppDatabase> database_; std::unique_ptr<WebAppRegistrar> registrar_;
diff --git a/chrome/browser/web_applications/web_app_tab_helper.cc b/chrome/browser/web_applications/web_app_tab_helper.cc index 2520c52..8ce555ee 100644 --- a/chrome/browser/web_applications/web_app_tab_helper.cc +++ b/chrome/browser/web_applications/web_app_tab_helper.cc
@@ -36,4 +36,9 @@ return AppId(); } +bool WebAppTabHelper::IsInAppWindow() const { + // TODO(beccahughes): Implement. + return false; +} + } // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_tab_helper.h b/chrome/browser/web_applications/web_app_tab_helper.h index 333573d..1e6a55a 100644 --- a/chrome/browser/web_applications/web_app_tab_helper.h +++ b/chrome/browser/web_applications/web_app_tab_helper.h
@@ -30,6 +30,7 @@ WebAppTabHelperBase* CloneForWebContents( content::WebContents* web_contents) const override; AppId GetAppId(const GURL& url) override; + bool IsInAppWindow() const override; private: DISALLOW_COPY_AND_ASSIGN(WebAppTabHelper);
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index ef17106..d5c530d 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -151,6 +151,13 @@ const base::Feature kChangePictureVideoMode{"ChangePictureVideoMode", base::FEATURE_ENABLED_BY_DEFAULT}; +#if defined(OS_CHROMEOS) +// Enables passing additional user authentication in requests to DMServer +// (policy fetch, status report upload). +const base::Feature kDMServerOAuthForChildUser{ + "DMServerOAuthForChildUser", base::FEATURE_DISABLED_BY_DEFAULT}; +#endif + #if defined(OS_ANDROID) // Enables clearing of browsing data which is older than given time period. const base::Feature kClearOldBrowsingData{"ClearOldBrowsingData",
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h index 931223b..125efbf99 100644 --- a/chrome/common/chrome_features.h +++ b/chrome/common/chrome_features.h
@@ -96,6 +96,11 @@ COMPONENT_EXPORT(CHROME_FEATURES) extern const base::Feature kChangePictureVideoMode; +#if defined(OS_CHROMEOS) +COMPONENT_EXPORT(CHROME_FEATURES) +extern const base::Feature kDMServerOAuthForChildUser; +#endif + #if defined(OS_ANDROID) COMPONENT_EXPORT(CHROME_FEATURES) extern const base::Feature kClearOldBrowsingData;
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index e1e2b05..4d2e9c7 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -269,7 +269,7 @@ ] public_deps += [ "//ash", - "//ash:test_support_with_content", + "//ash:test_support", "//components/ownership", "//components/user_manager:test_support", "//ui/aura", @@ -1769,6 +1769,7 @@ "../browser/chromeos/policy/blocking_login_browsertest.cc", "../browser/chromeos/policy/browser_policy_connector_chromeos_browsertest.cc", "../browser/chromeos/policy/component_active_directory_policy_browsertest.cc", + "../browser/chromeos/policy/device_cloud_external_data_policy_observer_browsertest.cc", "../browser/chromeos/policy/device_cloud_policy_browsertest.cc", "../browser/chromeos/policy/device_local_account_browsertest.cc", "../browser/chromeos/policy/device_policy_cloud_external_data_manager_browsertest.cc", @@ -1872,7 +1873,7 @@ "../browser/policy/cloud/machine_level_user_cloud_policy_browsertest.cc", ] deps += [ - "//ash:test_support_with_content", + "//ash:test_support", "//ash/public/interfaces:test_interfaces", "//chrome/browser/chromeos:arc_test_support", "//chrome/browser/chromeos:test_support", @@ -2835,7 +2836,6 @@ data_deps = [ "//chrome/test/data/media/engagement/preload:generate_preload_list", "//chrome/test/data/media/engagement/preload:test_data", - "//testing/buildbot/filters:unit_tests_filters", ] data = [ @@ -3135,6 +3135,7 @@ "../browser/resource_coordinator/tab_ranker/tab_score_predictor_unittest.cc", "../browser/resource_coordinator/test_lifecycle_unit.cc", "../browser/resource_coordinator/test_lifecycle_unit.h", + "../browser/resource_coordinator/tracing_lifecycle_unit_observer_unittest.cc", "../browser/resource_coordinator/usage_clock_unittest.cc", # Android does not use the Message Center notification system. @@ -3494,7 +3495,7 @@ "../browser/ui/window_sizer/window_sizer_ash_unittest.cc", ] deps += [ - "//ash:test_support_with_content", + "//ash:test_support", "//ash/public/cpp/resources:ash_public_unscaled_resources", "//ash/strings", "//chrome/browser/resources/chromeos/zip_archiver/cpp:ziparchiver_unittests", @@ -4126,10 +4127,6 @@ ] sources -= [ "../browser/policy/cloud/user_policy_signin_service_unittest.cc" ] - sources += [ - "base/ash_test_environment_chrome.cc", - "base/ash_test_environment_chrome.h", - ] } if (use_x11) { deps += [ "//ui/events/devices" ] @@ -4507,12 +4504,22 @@ "//chrome/common", "//mojo/core/test:test_support", ] + deps = [] if (is_win) { deps = [ "//chrome/install_static/test:test_support", ] } + + if (is_chromeos) { + sources += [ + "base/chrome_ash_test_base.cc", + "base/chrome_ash_test_base.h", + ] + + deps += [ "//ash:test_support" ] + } } if (is_win) {
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/SigninTestUtil.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/SigninTestUtil.java index 72c52d39..f2eba95d 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/SigninTestUtil.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/SigninTestUtil.java
@@ -11,11 +11,11 @@ import org.chromium.base.ContextUtils; import org.chromium.base.ThreadUtils; import org.chromium.chrome.browser.signin.IdentityServicesProvider; -import org.chromium.chrome.browser.signin.OAuth2TokenService; import org.chromium.chrome.browser.signin.SigninHelper; import org.chromium.components.signin.AccountIdProvider; import org.chromium.components.signin.AccountManagerFacade; import org.chromium.components.signin.ChromeSigninController; +import org.chromium.components.signin.OAuth2TokenService; import org.chromium.components.signin.test.util.AccountHolder; import org.chromium.components.signin.test.util.FakeAccountManagerDelegate;
diff --git a/chrome/test/base/ash_test_environment_chrome.cc b/chrome/test/base/ash_test_environment_chrome.cc deleted file mode 100644 index 1635f68..0000000 --- a/chrome/test/base/ash_test_environment_chrome.cc +++ /dev/null
@@ -1,27 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/test/base/ash_test_environment_chrome.h" - -#include "ash/test/ash_test_views_delegate.h" -#include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" -#include "ui/views/views_delegate.h" - -AshTestEnvironmentChrome::AshTestEnvironmentChrome() {} - -AshTestEnvironmentChrome::~AshTestEnvironmentChrome() {} - -std::unique_ptr<ash::AshTestViewsDelegate> -AshTestEnvironmentChrome::CreateViewsDelegate() { - return std::make_unique<ash::AshTestViewsDelegate>(); -} - -void AshTestEnvironmentChrome::TearDown() { - // If initialized, the KioskAppManager will register an observer to - // CrosSettings and will need to be destroyed before it. Having it destroyed - // as part of the teardown will avoid unexpected test failures. - chromeos::KioskAppManager::Shutdown(); - - ash::AshTestEnvironment::TearDown(); -}
diff --git a/chrome/test/base/ash_test_environment_chrome.h b/chrome/test/base/ash_test_environment_chrome.h deleted file mode 100644 index d95de04..0000000 --- a/chrome/test/base/ash_test_environment_chrome.h +++ /dev/null
@@ -1,24 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_TEST_BASE_ASH_TEST_ENVIRONMENT_CHROME_H_ -#define CHROME_TEST_BASE_ASH_TEST_ENVIRONMENT_CHROME_H_ - -#include "ash/test/ash_test_environment.h" -#include "base/macros.h" - -class AshTestEnvironmentChrome : public ash::AshTestEnvironment { - public: - AshTestEnvironmentChrome(); - ~AshTestEnvironmentChrome() override; - - // AshTestEnvironment: - std::unique_ptr<ash::AshTestViewsDelegate> CreateViewsDelegate() override; - void TearDown() override; - - private: - DISALLOW_COPY_AND_ASSIGN(AshTestEnvironmentChrome); -}; - -#endif // CHROME_TEST_BASE_ASH_TEST_ENVIRONMENT_CHROME_H_
diff --git a/chrome/test/base/browser_with_test_window_test.cc b/chrome/test/base/browser_with_test_window_test.cc index 78b00e7..4a049de7 100644 --- a/chrome/test/base/browser_with_test_window_test.cc +++ b/chrome/test/base/browser_with_test_window_test.cc
@@ -34,6 +34,7 @@ #if defined(OS_CHROMEOS) #include "ash/public/cpp/mus_property_mirror_ash.h" #include "ash/test/ash_test_views_delegate.h" +#include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" #include "content/public/browser/context_factory.h" #include "ui/aura/mus/window_tree_client.h" #include "ui/aura/test/env_test_helper.h" @@ -70,9 +71,6 @@ bool hosted_app, content::TestBrowserThreadBundle::Options thread_bundle_options) : thread_bundle_(thread_bundle_options), -#if defined(OS_CHROMEOS) - ash_test_helper_(&ash_test_environment_), -#endif browser_type_(browser_type), hosted_app_(hosted_app) { } @@ -140,6 +138,11 @@ profile_manager_.reset(); #if defined(OS_CHROMEOS) + // If initialized, the KioskAppManager will register an observer to + // CrosSettings and will need to be destroyed before it. Having it destroyed + // as part of the teardown will avoid unexpected test failures. + chromeos::KioskAppManager::Shutdown(); + ash_test_helper_.TearDown(); #elif defined(TOOLKIT_VIEWS) views_test_helper_.reset();
diff --git a/chrome/test/base/browser_with_test_window_test.h b/chrome/test/base/browser_with_test_window_test.h index f4f7f2e4..53204927 100644 --- a/chrome/test/base/browser_with_test_window_test.h +++ b/chrome/test/base/browser_with_test_window_test.h
@@ -20,7 +20,6 @@ #include "ash/test/ash_test_views_delegate.h" #include "chrome/browser/chromeos/login/users/scoped_test_user_manager.h" #include "chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h" -#include "chrome/test/base/ash_test_environment_chrome.h" #else #include "ui/views/test/scoped_views_test_helper.h" #endif @@ -193,7 +192,6 @@ std::unique_ptr<Browser> browser_; #if defined(OS_CHROMEOS) - AshTestEnvironmentChrome ash_test_environment_; ash::AshTestHelper ash_test_helper_; std::unique_ptr<views::MusClient> mus_client_; #elif defined(TOOLKIT_VIEWS)
diff --git a/chrome/test/base/chrome_ash_test_base.cc b/chrome/test/base/chrome_ash_test_base.cc new file mode 100644 index 0000000..1ba0a47 --- /dev/null +++ b/chrome/test/base/chrome_ash_test_base.cc
@@ -0,0 +1,14 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/test/base/chrome_ash_test_base.h" + +#include "content/public/test/test_browser_thread_bundle.h" + +ChromeAshTestBase::ChromeAshTestBase() { + DestroyScopedTaskEnvironment(); + thread_bundle_ = std::make_unique<content::TestBrowserThreadBundle>(); +} + +ChromeAshTestBase::~ChromeAshTestBase() = default;
diff --git a/chrome/test/base/chrome_ash_test_base.h b/chrome/test/base/chrome_ash_test_base.h new file mode 100644 index 0000000..f0971502 --- /dev/null +++ b/chrome/test/base/chrome_ash_test_base.h
@@ -0,0 +1,28 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_TEST_BASE_CHROME_ASH_TEST_BASE_H_ +#define CHROME_TEST_BASE_CHROME_ASH_TEST_BASE_H_ + +#include "ash/test/ash_test_base.h" + +namespace content { +class TestBrowserThreadBundle; +} + +// AshTestBase used in Chrome. +// TODO(crbug.com/890677): Chrome should not have tests subclassing +// AshTestBase. +class ChromeAshTestBase : public ash::AshTestBase { + public: + ChromeAshTestBase(); + ~ChromeAshTestBase() override; + + private: + std::unique_ptr<content::TestBrowserThreadBundle> thread_bundle_; + + DISALLOW_COPY_AND_ASSIGN(ChromeAshTestBase); +}; + +#endif // CHROME_TEST_BASE_CHROME_ASH_TEST_BASE_H_
diff --git a/chrome/test/base/chrome_render_view_host_test_harness.cc b/chrome/test/base/chrome_render_view_host_test_harness.cc index a2c4cc05a..0e1fcd5 100644 --- a/chrome/test/base/chrome_render_view_host_test_harness.cc +++ b/chrome/test/base/chrome_render_view_host_test_harness.cc
@@ -37,15 +37,17 @@ AccountTrackerServiceFactory::GetForProfile(profile); SigninErrorController* signin_error_controller = SigninErrorControllerFactory::GetForProfile(profile); + ProfileOAuth2TokenService* token_service = + ProfileOAuth2TokenServiceFactory::GetForProfile(profile); #if defined (OS_CHROMEOS) - std::unique_ptr<SigninManagerBase> signin(new SigninManagerBase( - signin_client, account_tracker_service, signin_error_controller)); + std::unique_ptr<SigninManagerBase> signin( + new SigninManagerBase(signin_client, token_service, + account_tracker_service, signin_error_controller)); signin->Initialize(NULL); return std::move(signin); #else std::unique_ptr<FakeSigninManager> manager(new FakeSigninManager( - signin_client, ProfileOAuth2TokenServiceFactory::GetForProfile(profile), - account_tracker_service, + signin_client, token_service, account_tracker_service, GaiaCookieManagerServiceFactory::GetForProfile(profile), signin_error_controller)); manager->Initialize(g_browser_process->local_state());
diff --git a/chrome/test/base/testing_profile.cc b/chrome/test/base/testing_profile.cc index f5040d5..13bc5a43 100644 --- a/chrome/test/base/testing_profile.cc +++ b/chrome/test/base/testing_profile.cc
@@ -125,7 +125,7 @@ #endif #if defined(OS_ANDROID) -#include "chrome/browser/signin/oauth2_token_service_delegate_android.h" +#include "components/signin/core/browser/oauth2_token_service_delegate_android.h" #else // !defined(OS_ANDROID) #include "chrome/browser/ui/zoom/chrome_zoom_level_prefs.h" #include "components/zoom/zoom_event_manager.h"
diff --git a/chrome/test/chromedriver/test/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py index 318acd86..d064d79 100755 --- a/chrome/test/chromedriver/test/run_py_tests.py +++ b/chrome/test/chromedriver/test/run_py_tests.py
@@ -1235,7 +1235,7 @@ self.assertFalse(self._driver.capabilities['mobileEmulationEnabled']) def testChromeDriverSendLargeData(self): - script = 's = ""; for (i = 0; i < 10e6; i++) s += "0"; return s;' + script = 'var s = ""; for (var i = 0; i < 10e6; i++) s += "0"; return s;' lots_of_data = self._driver.ExecuteScript(script) self.assertEquals('0'.zfill(int(10e6)), lots_of_data)
diff --git a/chrome/test/data/extensions/audio_focus_web_app/main.html b/chrome/test/data/extensions/audio_focus_web_app/main.html new file mode 100644 index 0000000..6049d28 --- /dev/null +++ b/chrome/test/data/extensions/audio_focus_web_app/main.html
@@ -0,0 +1,33 @@ +<!-- + * 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. +--> +<!DOCTYPE html> +<html> +<body> + <video src="/media/bigbuck.webm"></video> + <script> + const video = document.getElementsByTagName('video')[0]; + + function startPlaying() { + video.play() + .then(() => window.domAutomationController.send(true)) + .catch(() => window.domAutomationController.send(false)); + } + + function waitForPause() { + if (video.paused) { + window.domAutomationController.send(true); + return; + } + + video.addEventListener('pause', () => window.domAutomationController.send(true), { once: true }); + } + + function isPaused() { + window.domAutomationController.send(video.paused); + } + </script> +</body> +</html>
diff --git a/chrome/test/data/webui/settings/sync_account_control_test.js b/chrome/test/data/webui/settings/sync_account_control_test.js index 7191fe3..af4ea08 100644 --- a/chrome/test/data/webui/settings/sync_account_control_test.js +++ b/chrome/test/data/webui/settings/sync_account_control_test.js
@@ -328,7 +328,7 @@ disabled: false, }; - assertVisible(testElement.$$('#turn-off'), false); + assertVisible(testElement.$$('#turn-off'), true); assertVisible(testElement.$$('#sync-error-button'), false); testElement.embeddedInSubpage = true; @@ -340,7 +340,7 @@ statusAction: settings.StatusAction.REAUTHENTICATE, disabled: false, }; - assertVisible(testElement.$$('#turn-off'), false); + assertVisible(testElement.$$('#turn-off'), true); assertVisible(testElement.$$('#sync-error-button'), true); testElement.embeddedInSubpage = true; @@ -352,7 +352,7 @@ statusAction: settings.StatusAction.REAUTHENTICATE, disabled: false, }; - assertVisible(testElement.$$('#turn-off'), false); + assertVisible(testElement.$$('#turn-off'), true); assertVisible(testElement.$$('#sync-error-button'), true); testElement.embeddedInSubpage = true; @@ -364,7 +364,7 @@ statusAction: settings.StatusAction.ENTER_PASSPHRASE, disabled: false, }; - assertVisible(testElement.$$('#turn-off'), false); + assertVisible(testElement.$$('#turn-off'), true); // Don't show passphrase error button on embedded page. assertVisible(testElement.$$('#sync-error-button'), false); @@ -377,7 +377,7 @@ statusAction: settings.StatusAction.NO_ACTION, disabled: false, }; - assertVisible(testElement.$$('#turn-off'), false); + assertVisible(testElement.$$('#turn-off'), true); assertVisible(testElement.$$('#sync-error-button'), false); });
diff --git a/chromeos/process_proxy/process_proxy_unittest.cc b/chromeos/process_proxy/process_proxy_unittest.cc index 6a368d1d..338925a 100644 --- a/chromeos/process_proxy/process_proxy_unittest.cc +++ b/chromeos/process_proxy/process_proxy_unittest.cc
@@ -206,8 +206,6 @@ } void EndRegistryTest(base::OnceClosure done_closure) { - base::ScopedAllowBaseSyncPrimitivesForTesting allow_sync_primitives; - registry_->CloseProcess(terminal_id_); int unused_exit_code = 0; @@ -215,6 +213,7 @@ base::GetTerminationStatus(terminal_id_, &unused_exit_code); EXPECT_NE(base::TERMINATION_STATUS_STILL_RUNNING, status); if (status == base::TERMINATION_STATUS_STILL_RUNNING) { + base::ScopedAllowBaseSyncPrimitivesForTesting allow_sync_primitives; base::Process process = base::Process::DeprecatedGetProcessFromHandle(terminal_id_); process.Terminate(0, true);
diff --git a/components/autofill/content/browser/content_autofill_driver_factory.cc b/components/autofill/content/browser/content_autofill_driver_factory.cc index 6825bcf..6c85d18 100644 --- a/components/autofill/content/browser/content_autofill_driver_factory.cc +++ b/components/autofill/content/browser/content_autofill_driver_factory.cc
@@ -57,8 +57,8 @@ if (FromWebContents(contents)) return; - auto new_factory = base::WrapUnique(new ContentAutofillDriverFactory( - contents, client, app_locale, enable_download_manager, provider)); + auto new_factory = std::make_unique<ContentAutofillDriverFactory>( + contents, client, app_locale, enable_download_manager, provider); const std::vector<content::RenderFrameHost*> frames = contents->GetAllFrames(); for (content::RenderFrameHost* frame : frames) {
diff --git a/components/autofill/content/browser/content_autofill_driver_factory.h b/components/autofill/content/browser/content_autofill_driver_factory.h index 2ff9b33..3d503f4 100644 --- a/components/autofill/content/browser/content_autofill_driver_factory.h +++ b/components/autofill/content/browser/content_autofill_driver_factory.h
@@ -28,6 +28,13 @@ public content::WebContentsObserver, public base::SupportsUserData::Data { public: + ContentAutofillDriverFactory( + content::WebContents* web_contents, + AutofillClient* client, + const std::string& app_locale, + AutofillManager::AutofillDownloadManagerState enable_download_manager, + AutofillProvider* provider); + ~ContentAutofillDriverFactory() override; static void CreateForWebContentsAndDelegate( @@ -63,13 +70,6 @@ static const char kContentAutofillDriverFactoryWebContentsUserDataKey[]; private: - ContentAutofillDriverFactory( - content::WebContents* web_contents, - AutofillClient* client, - const std::string& app_locale, - AutofillManager::AutofillDownloadManagerState enable_download_manager, - AutofillProvider* provider); - std::string app_locale_; AutofillManager::AutofillDownloadManagerState enable_download_manager_; AutofillProvider* provider_;
diff --git a/components/autofill/core/browser/address_field_unittest.cc b/components/autofill/core/browser/address_field_unittest.cc index 4791ab091..78549dfb 100644 --- a/components/autofill/core/browser/address_field_unittest.cc +++ b/components/autofill/core/browser/address_field_unittest.cc
@@ -32,7 +32,8 @@ // Downcast for tests. static std::unique_ptr<AddressField> Parse(AutofillScanner* scanner) { std::unique_ptr<FormField> field = AddressField::Parse(scanner); - return base::WrapUnique(static_cast<AddressField*>(field.release())); + return std::unique_ptr<AddressField>( + static_cast<AddressField*>(field.release())); } private:
diff --git a/components/autofill/core/browser/address_normalizer_impl.cc b/components/autofill/core/browser/address_normalizer_impl.cc index ca78af9..8c2e4f4 100644 --- a/components/autofill/core/browser/address_normalizer_impl.cc +++ b/components/autofill/core/browser/address_normalizer_impl.cc
@@ -77,9 +77,9 @@ std::unique_ptr<Source> source, DeleteOnTaskRunnerStorageUniquePtr storage, LoadRulesListener* load_rules_listener) { - return std::make_unique<AddressValidator>(std::move(source), - base::WrapUnique(storage.release()), - load_rules_listener); + return std::make_unique<AddressValidator>( + std::move(source), std::unique_ptr<Storage>(storage.release()), + load_rules_listener); } } // namespace
diff --git a/components/autofill/core/browser/autocomplete_history_manager.cc b/components/autofill/core/browser/autocomplete_history_manager.cc index 06bd1c7..5186636 100644 --- a/components/autofill/core/browser/autocomplete_history_manager.cc +++ b/components/autofill/core/browser/autocomplete_history_manager.cc
@@ -73,9 +73,11 @@ AutocompleteHistoryManager::QueryHandler::QueryHandler( int client_query_id, + bool autoselect_first_suggestion, base::string16 prefix, base::WeakPtr<SuggestionsHandler> handler) : client_query_id_(client_query_id), + autoselect_first_suggestion_(autoselect_first_suggestion), prefix_(prefix), handler_(std::move(handler)) {} @@ -106,6 +108,7 @@ void AutocompleteHistoryManager::OnGetAutocompleteSuggestions( int query_id, bool is_autocomplete_enabled, + bool autoselect_first_suggestion, const base::string16& name, const base::string16& prefix, const std::string& form_control_type, @@ -114,7 +117,8 @@ if (!is_autocomplete_enabled || form_control_type == "textarea" || IsInAutofillSuggestionsDisabledExperiment()) { - SendSuggestions({}, QueryHandler(query_id, prefix, handler)); + SendSuggestions({}, QueryHandler(query_id, autoselect_first_suggestion, + prefix, handler)); uma_recorder_.OnGetAutocompleteSuggestions(name, 0 /* pending_query_handle */); return; @@ -127,7 +131,8 @@ // We can simply insert, since |query_handle| is always unique. pending_queries_.insert( - {query_handle, QueryHandler(query_id, prefix, handler)}); + {query_handle, + QueryHandler(query_id, autoselect_first_suggestion, prefix, handler)}); } } @@ -207,8 +212,9 @@ [](const base::string16& result) { return Suggestion(result); }); } - query_handler.handler_->OnSuggestionsReturned(query_handler.client_query_id_, - suggestions); + query_handler.handler_->OnSuggestionsReturned( + query_handler.client_query_id_, + query_handler.autoselect_first_suggestion_, suggestions); } void AutocompleteHistoryManager::OnWebDataServiceRequestDone(
diff --git a/components/autofill/core/browser/autocomplete_history_manager.h b/components/autofill/core/browser/autocomplete_history_manager.h index 651d3bf..43f58bf 100644 --- a/components/autofill/core/browser/autocomplete_history_manager.h +++ b/components/autofill/core/browser/autocomplete_history_manager.h
@@ -39,6 +39,7 @@ // |suggestions| is the list of fetched autocomplete suggestions. virtual void OnSuggestionsReturned( int query_id, + bool autoselect_first_suggestion, const std::vector<Suggestion>& suggestions) = 0; }; @@ -70,6 +71,7 @@ virtual void OnGetAutocompleteSuggestions( int query_id, bool is_autocomplete_enabled, + bool autoselect_first_suggestion, const base::string16& name, const base::string16& prefix, const std::string& form_control_type, @@ -131,6 +133,7 @@ // with the appropriate response. struct QueryHandler { QueryHandler(int client_query_id, + bool autoselect_first_suggestion, base::string16 prefix, base::WeakPtr<SuggestionsHandler> handler); QueryHandler(const QueryHandler& original); @@ -140,6 +143,11 @@ // database query ID. This ID is unique per frame, but not per profile. int client_query_id_; + // Determines whether we should auto-select the first suggestion when + // returning. This value was given by the handler when requesting + // suggestions. + bool autoselect_first_suggestion_; + // Prefix used to search suggestions, submitted by the handler. base::string16 prefix_;
diff --git a/components/autofill/core/browser/autocomplete_history_manager_unittest.cc b/components/autofill/core/browser/autocomplete_history_manager_unittest.cc index 17b5a47..2c1fb1f 100644 --- a/components/autofill/core/browser/autocomplete_history_manager_unittest.cc +++ b/components/autofill/core/browser/autocomplete_history_manager_unittest.cc
@@ -73,8 +73,10 @@ public: MockSuggestionsHandler() : weak_ptr_factory_(this) {} - MOCK_METHOD2(OnSuggestionsReturned, - void(int query_id, const std::vector<Suggestion>& suggestions)); + MOCK_METHOD3(OnSuggestionsReturned, + void(int query_id, + bool autoselect_first_suggestion, + const std::vector<Suggestion>& suggestions)); base::WeakPtr<MockSuggestionsHandler> GetWeakPtr() { return weak_ptr_factory_.GetWeakPtr(); @@ -339,13 +341,15 @@ // Simulate request for suggestions. autocomplete_manager_->OnGetAutocompleteSuggestions( - test_query_id, /*is_autocomplete_enabled=*/true, test_name, test_prefix, + test_query_id, /*is_autocomplete_enabled=*/true, + /*autoselect_first_suggestion=*/false, test_name, test_prefix, "Some Type", suggestions_handler->GetWeakPtr()); // Setting up mock to verify that DB response triggers a call to the handler's // OnSuggestionsReturned EXPECT_CALL(*suggestions_handler.get(), OnSuggestionsReturned(test_query_id, + /*autoselect_first_suggestion=*/false, testing::Truly(IsEmptySuggestionVector))); // Simulate response from DB. @@ -375,14 +379,56 @@ // Simulate request for suggestions. autocomplete_manager_->OnGetAutocompleteSuggestions( - test_query_id, /*is_autocomplete_enabled=*/true, test_name, test_prefix, + test_query_id, /*is_autocomplete_enabled=*/true, + /*autoselect_first_suggestion=*/false, test_name, test_prefix, "Some Type", suggestions_handler->GetWeakPtr()); // Setting up mock to verify that DB response triggers a call to the handler's - EXPECT_CALL(*suggestions_handler.get(), - OnSuggestionsReturned( - test_query_id, UnorderedElementsAre(Field( - &Suggestion::value, expected_values[0])))); + EXPECT_CALL( + *suggestions_handler.get(), + OnSuggestionsReturned( + test_query_id, /*autoselect_first_suggestion=*/false, + UnorderedElementsAre(Field(&Suggestion::value, expected_values[0])))); + + // Simulate response from DB. + autocomplete_manager_->OnWebDataServiceRequestDone(mocked_db_query_id, + std::move(mocked_results)); +} + +// Tests that we are correctly forwarding the value of +// |autoselect_first_suggestion| back to the handler. +TEST_F(AutocompleteHistoryManagerTest, + SuggestionsReturned_InvokeHandler_PassesAutoSelect) { + int mocked_db_query_id = 100; + + auto suggestions_handler = std::make_unique<MockSuggestionsHandler>(); + int test_query_id = 2; + auto test_name = ASCIIToUTF16("Some Field Name"); + auto test_prefix = ASCIIToUTF16("SomePrefix"); + + std::vector<base::string16> expected_values = {ASCIIToUTF16("SomePrefixOne")}; + + std::unique_ptr<WDTypedResult> mocked_results = + std::make_unique<WDResult<std::vector<base::string16>>>( + AUTOFILL_VALUE_RESULT, expected_values); + + EXPECT_CALL(*web_data_service_, + GetFormValuesForElementName(test_name, test_prefix, _, + autocomplete_manager_.get())) + .WillOnce(Return(mocked_db_query_id)); + + // Simulate request for suggestions. + autocomplete_manager_->OnGetAutocompleteSuggestions( + test_query_id, /*is_autocomplete_enabled=*/true, + /*autoselect_first_suggestion=*/true, test_name, test_prefix, "Some Type", + suggestions_handler->GetWeakPtr()); + + // Setting up mock to verify that DB response triggers a call to the handler's + EXPECT_CALL( + *suggestions_handler.get(), + OnSuggestionsReturned( + test_query_id, /*autoselect_first_suggestion=*/true, + UnorderedElementsAre(Field(&Suggestion::value, expected_values[0])))); // Simulate response from DB. autocomplete_manager_->OnWebDataServiceRequestDone(mocked_db_query_id, @@ -413,12 +459,14 @@ // Simulate request for suggestions. autocomplete_manager_->OnGetAutocompleteSuggestions( - test_query_id, /*is_autocomplete_enabled=*/true, test_name, test_prefix, + test_query_id, /*is_autocomplete_enabled=*/true, + /*autoselect_first_suggestion=*/false, test_name, test_prefix, "Some Type", suggestions_handler->GetWeakPtr()); // Setting up mock to verify that DB response triggers a call to the handler's EXPECT_CALL(*suggestions_handler.get(), OnSuggestionsReturned(test_query_id, + /*autoselect_first_suggestion=*/false, testing::Truly(IsEmptySuggestionVector))); // Simulate response from DB. @@ -450,14 +498,16 @@ // Simulate request for suggestions. autocomplete_manager_->OnGetAutocompleteSuggestions( - test_query_id, /*is_autocomplete_enabled=*/true, test_name, test_prefix, + test_query_id, /*is_autocomplete_enabled=*/true, + /*autoselect_first_suggestion=*/false, test_name, test_prefix, "Some Type", suggestions_handler->GetWeakPtr()); // Setting up mock to verify that DB response triggers a call to the handler's - EXPECT_CALL(*suggestions_handler.get(), - OnSuggestionsReturned( - test_query_id, UnorderedElementsAre(Field( - &Suggestion::value, expected_values[0])))); + EXPECT_CALL( + *suggestions_handler.get(), + OnSuggestionsReturned( + test_query_id, /*autoselect_first_suggestion=*/false, + UnorderedElementsAre(Field(&Suggestion::value, expected_values[0])))); // Simulate response from DB. autocomplete_manager_->OnWebDataServiceRequestDone(mocked_db_query_id, @@ -497,21 +547,23 @@ // Simulate request for the first suggestions. autocomplete_manager_->OnGetAutocompleteSuggestions( - test_query_id_first, /*is_autocomplete_enabled=*/true, test_name, - test_prefix, "Some Type", suggestions_handler->GetWeakPtr()); + test_query_id_first, /*is_autocomplete_enabled=*/true, + /*autoselect_first_suggestion=*/false, test_name, test_prefix, + "Some Type", suggestions_handler->GetWeakPtr()); // Simulate request for the second suggestions (this will cancel the first // one). EXPECT_CALL(*web_data_service_, CancelRequest(mocked_db_query_id_first)) .Times(1); autocomplete_manager_->OnGetAutocompleteSuggestions( - test_query_id_second, /*is_autocomplete_enabled=*/true, test_name, - test_prefix, "Some Type", suggestions_handler->GetWeakPtr()); + test_query_id_second, /*is_autocomplete_enabled=*/true, + /*autoselect_first_suggestion=*/false, test_name, test_prefix, + "Some Type", suggestions_handler->GetWeakPtr()); // Setting up mock to verify that we can get the second response first. EXPECT_CALL(*suggestions_handler.get(), OnSuggestionsReturned( - test_query_id_second, + test_query_id_second, /*autoselect_first_suggestion=*/false, UnorderedElementsAre( Field(&Suggestion::value, expected_values_second[0])))); @@ -522,7 +574,8 @@ // Setting up mock to verify that the handler doesn't get called for the first // request, which was cancelled. EXPECT_CALL(*suggestions_handler.get(), - OnSuggestionsReturned(test_query_id_first, _)) + OnSuggestionsReturned(test_query_id_first, + /*autoselect_first_suggestion=*/false, _)) .Times(0); // Simulate response from DB, first request comes back after. @@ -564,18 +617,20 @@ // Simulate request for the first suggestions. autocomplete_manager_->OnGetAutocompleteSuggestions( - test_query_id_first, /*is_autocomplete_enabled=*/true, test_name, - test_prefix, "Some Type", suggestions_handler_first->GetWeakPtr()); + test_query_id_first, /*is_autocomplete_enabled=*/true, + /*autoselect_first_suggestion=*/false, test_name, test_prefix, + "Some Type", suggestions_handler_first->GetWeakPtr()); // Simulate request for the second suggestions. autocomplete_manager_->OnGetAutocompleteSuggestions( - test_query_id_second, /*is_autocomplete_enabled=*/true, test_name, - test_prefix, "Some Type", suggestions_handler_second->GetWeakPtr()); + test_query_id_second, /*is_autocomplete_enabled=*/true, + /*autoselect_first_suggestion=*/false, test_name, test_prefix, + "Some Type", suggestions_handler_second->GetWeakPtr()); // Setting up mock to verify that we get the second response first. EXPECT_CALL(*suggestions_handler_second.get(), OnSuggestionsReturned( - test_query_id_second, + test_query_id_second, /*autoselect_first_suggestion=*/false, UnorderedElementsAre( Field(&Suggestion::value, expected_values_second[0])))); @@ -586,7 +641,7 @@ // Setting up mock to verify that we get the first response second. EXPECT_CALL(*suggestions_handler_first.get(), OnSuggestionsReturned( - test_query_id_first, + test_query_id_first, /*autoselect_first_suggestion=*/false, UnorderedElementsAre( Field(&Suggestion::value, expected_values_first[0])))); @@ -629,13 +684,15 @@ .WillOnce(Return(mocked_db_query_id_two)); autocomplete_manager_->OnGetAutocompleteSuggestions( - test_query_id_one, /*is_autocomplete_enabled=*/true, test_name, - test_prefix, "Some Type", suggestions_handler_one->GetWeakPtr()); + test_query_id_one, /*is_autocomplete_enabled=*/true, + /*autoselect_first_suggestion=*/false, test_name, test_prefix, + "Some Type", suggestions_handler_one->GetWeakPtr()); // Simlate second handler request for autocomplete suggestions. autocomplete_manager_->OnGetAutocompleteSuggestions( - test_query_id_two, /*is_autocomplete_enabled=*/true, test_name, - test_prefix, "Some Type", suggestions_handler_two->GetWeakPtr()); + test_query_id_two, /*is_autocomplete_enabled=*/true, + /*autoselect_first_suggestion=*/false, test_name, test_prefix, + "Some Type", suggestions_handler_two->GetWeakPtr()); // Simlate first handler cancelling its request. EXPECT_CALL(*web_data_service_, CancelRequest(mocked_db_query_id_one)) @@ -643,17 +700,18 @@ autocomplete_manager_->CancelPendingQueries(suggestions_handler_one.get()); // Simulate second handler receiving the suggestions. - EXPECT_CALL( - *suggestions_handler_two.get(), - OnSuggestionsReturned(test_query_id_two, - UnorderedElementsAre(Field( - &Suggestion::value, expected_values_two[0])))); + EXPECT_CALL(*suggestions_handler_two.get(), + OnSuggestionsReturned( + test_query_id_two, /*autoselect_first_suggestion=*/false, + UnorderedElementsAre( + Field(&Suggestion::value, expected_values_two[0])))); autocomplete_manager_->OnWebDataServiceRequestDone( mocked_db_query_id_two, std::move(mocked_results_two)); // Make sure first handler is not called when the DB responds. EXPECT_CALL(*suggestions_handler_one.get(), - OnSuggestionsReturned(test_query_id_one, _)) + OnSuggestionsReturned(test_query_id_one, + /*autoselect_first_suggestion=*/false, _)) .Times(0); autocomplete_manager_->OnWebDataServiceRequestDone( mocked_db_query_id_one, std::move(mocked_results_one)); @@ -671,14 +729,15 @@ test::CreateTestFormField("Address", "address", "", "textarea", &field); auto suggestions_handler = std::make_unique<MockSuggestionsHandler>(); - EXPECT_CALL( - *suggestions_handler.get(), - OnSuggestionsReturned(0, testing::Truly(IsEmptySuggestionVector))); + EXPECT_CALL(*suggestions_handler.get(), + OnSuggestionsReturned(0, /*autoselect_first_suggestion=*/false, + testing::Truly(IsEmptySuggestionVector))); base::HistogramTester histogram_tester; autocomplete_manager_->OnGetAutocompleteSuggestions( - 0, /*is_autocomplete_enabled=*/true, field.name, field.value, + 0, /*is_autocomplete_enabled=*/true, + /*autoselect_first_suggestion=*/false, field.name, field.value, field.form_control_type, suggestions_handler->GetWeakPtr()); histogram_tester.ExpectBucketCount("Autofill.AutocompleteQuery", 0, 1); @@ -702,11 +761,12 @@ // Verify that the query has been created. base::HistogramTester histogram_tester; - EXPECT_CALL( - *suggestions_handler.get(), - OnSuggestionsReturned(0, testing::Truly(IsEmptySuggestionVector))); + EXPECT_CALL(*suggestions_handler.get(), + OnSuggestionsReturned(0, /*autoselect_first_suggestion=*/false, + testing::Truly(IsEmptySuggestionVector))); autocomplete_manager_->OnGetAutocompleteSuggestions( - 0, /*is_autocomplete_enabled=*/true, field.name, field.value, + 0, /*is_autocomplete_enabled=*/true, + /*autoselect_first_suggestion=*/false, field.name, field.value, field.form_control_type, suggestions_handler->GetWeakPtr()); histogram_tester.ExpectBucketCount("Autofill.AutocompleteQuery", 1, 1); histogram_tester.ExpectBucketCount("Autofill.AutocompleteQuery", 0, 0); @@ -731,11 +791,12 @@ autocomplete_manager_.get())) .WillOnce(Return(mock_handle)); - EXPECT_CALL( - *suggestions_handler.get(), - OnSuggestionsReturned(0, testing::Truly(NonEmptySuggestionVector))); + EXPECT_CALL(*suggestions_handler.get(), + OnSuggestionsReturned(0, /*autoselect_first_suggestion=*/false, + testing::Truly(NonEmptySuggestionVector))); autocomplete_manager_->OnGetAutocompleteSuggestions( - 0, /*is_autocomplete_enabled=*/true, field.name, field.value, + 0, /*is_autocomplete_enabled=*/true, + /*autoselect_first_suggestion=*/false, field.name, field.value, field.form_control_type, suggestions_handler->GetWeakPtr()); histogram_tester.ExpectBucketCount("Autofill.AutocompleteQuery", 1, 2); histogram_tester.ExpectBucketCount("Autofill.AutocompleteQuery", 0, 0); @@ -771,13 +832,15 @@ // Simulate request for the first suggestions. autocomplete_manager_->OnGetAutocompleteSuggestions( - test_query_id_first, /*is_autocomplete_enabled=*/true, test_name, - test_prefix, "Some Type", suggestions_handler_first->GetWeakPtr()); + test_query_id_first, /*is_autocomplete_enabled=*/true, + /*autoselect_first_suggestion=*/false, test_name, test_prefix, + "Some Type", suggestions_handler_first->GetWeakPtr()); // Simulate request for the second suggestions. autocomplete_manager_->OnGetAutocompleteSuggestions( - test_query_id_second, /*is_autocomplete_enabled=*/true, test_name, - test_prefix, "Some Type", suggestions_handler_second->GetWeakPtr()); + test_query_id_second, /*is_autocomplete_enabled=*/true, + /*autoselect_first_suggestion=*/false, test_name, test_prefix, + "Some Type", suggestions_handler_second->GetWeakPtr()); // Expect cancel calls for both requests. EXPECT_CALL(*web_data_service_, CancelRequest(mocked_db_query_id_first))
diff --git a/components/autofill/core/browser/autofill_address_util.cc b/components/autofill/core/browser/autofill_address_util.cc index 3a2dafd..34806bc 100644 --- a/components/autofill/core/browser/autofill_address_util.cc +++ b/components/autofill/core/browser/autofill_address_util.cc
@@ -103,7 +103,7 @@ components[i - 1].length_hint == AddressUiComponent::HINT_LONG || components[i].length_hint == AddressUiComponent::HINT_LONG) { line = new base::ListValue; - address_components->Append(base::WrapUnique(line)); + address_components->Append(std::unique_ptr<base::ListValue>(line)); // |line| is invalidated at this point, so it needs to be reset. address_components->GetList(address_components->GetSize() - 1, &line); }
diff --git a/components/autofill/core/browser/autofill_experiments.cc b/components/autofill/core/browser/autofill_experiments.cc index 76816b8..cc9418c9 100644 --- a/components/autofill/core/browser/autofill_experiments.cc +++ b/components/autofill/core/browser/autofill_experiments.cc
@@ -118,10 +118,13 @@ // If the "allow all email domains" flag is off, restrict credit card upload // only to Google Accounts with @googlemail, @gmail, @google, or @chromium // domains. + // example.com is on the list because ChromeOS tests rely on using this. That + // should be fine, since example.com is an IANA reserved domain. if (!base::FeatureList::IsEnabled( features::kAutofillUpstreamAllowAllEmailDomains) && !(domain == "googlemail.com" || domain == "gmail.com" || - domain == "google.com" || domain == "chromium.org")) { + domain == "google.com" || domain == "chromium.org" || + domain == "example.com")) { return false; }
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc index 9bcf98de..d4b3eb3f 100644 --- a/components/autofill/core/browser/autofill_manager.cc +++ b/components/autofill/core/browser/autofill_manager.cc
@@ -653,8 +653,9 @@ // Suggestions come back asynchronously, so the Autocomplete manager will // handle sending the results back to the renderer. autocomplete_history_manager_->OnGetAutocompleteSuggestions( - query_id, client_->IsAutocompleteEnabled(), field.name, field.value, - field.form_control_type, weak_ptr_factory_.GetWeakPtr()); + query_id, client_->IsAutocompleteEnabled(), autoselect_first_suggestion, + field.name, field.value, field.form_control_type, + weak_ptr_factory_.GetWeakPtr()); return; } @@ -1162,10 +1163,13 @@ form.ShouldBeUploaded(); } +// AutocompleteHistoryManager::SuggestionsHandler implementation void AutofillManager::OnSuggestionsReturned( int query_id, + bool autoselect_first_suggestion, const std::vector<Suggestion>& suggestions) { - external_delegate_->OnSuggestionsReturned(query_id, suggestions, false); + external_delegate_->OnSuggestionsReturned(query_id, suggestions, + autoselect_first_suggestion); } // Note that |submitted_form| is passed as a pointer rather than as a reference
diff --git a/components/autofill/core/browser/autofill_manager.h b/components/autofill/core/browser/autofill_manager.h index 4bfa00c6..5d22b2e 100644 --- a/components/autofill/core/browser/autofill_manager.h +++ b/components/autofill/core/browser/autofill_manager.h
@@ -203,6 +203,7 @@ // AutocompleteHistoryManager::SuggestionsHandler: void OnSuggestionsReturned( int query_id, + bool autoselect_first_suggestion, const std::vector<Suggestion>& suggestions) override; // Returns the value of AutofillEnabled pref.
diff --git a/components/autofill/core/browser/autofill_manager_unittest.cc b/components/autofill/core/browser/autofill_manager_unittest.cc index 678046b..5f43f7f 100644 --- a/components/autofill/core/browser/autofill_manager_unittest.cc +++ b/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -427,7 +427,8 @@ std::back_inserter(suggestions), [](auto result) { return Suggestion(result); }); - autofill_manager_->OnSuggestionsReturned(query_id, suggestions); + autofill_manager_->OnSuggestionsReturned( + query_id, /*autoselect_first_suggestion=*/false, suggestions); } void FormsSeen(const std::vector<FormData>& forms) { @@ -1124,9 +1125,21 @@ std::vector<Suggestion> suggestions = { Suggestion("Charles", "123 Apple St.", "", 1), Suggestion("Elvis", "3734 Elvis Presley Blvd.", "", 2)}; - autofill_manager_->OnSuggestionsReturned(kDefaultPageID, suggestions); - CheckSuggestions(kDefaultPageID, suggestions[0], suggestions[1]); + { + autofill_manager_->OnSuggestionsReturned( + kDefaultPageID, /*autoselect_first_suggestion=*/false, suggestions); + + EXPECT_FALSE(external_delegate_->autoselect_first_suggestion()); + CheckSuggestions(kDefaultPageID, suggestions[0], suggestions[1]); + } + { + autofill_manager_->OnSuggestionsReturned( + kDefaultPageID, /*autoselect_first_suggestion=*/true, suggestions); + + EXPECT_TRUE(external_delegate_->autoselect_first_suggestion()); + CheckSuggestions(kDefaultPageID, suggestions[0], suggestions[1]); + } } // Test that we return all credit card profile suggestions when all form fields @@ -4215,7 +4228,8 @@ // |form_structure| will be owned by |autofill_manager_|. TestFormStructure* form_structure = new TestFormStructure(form); form_structure->DetermineHeuristicTypes(); - autofill_manager_->AddSeenFormStructure(base::WrapUnique(form_structure)); + autofill_manager_->AddSeenFormStructure( + std::unique_ptr<TestFormStructure>(form_structure)); // Similarly, a second form. FormData form2; @@ -4235,7 +4249,8 @@ TestFormStructure* form_structure2 = new TestFormStructure(form2); form_structure2->DetermineHeuristicTypes(); - autofill_manager_->AddSeenFormStructure(base::WrapUnique(form_structure2)); + autofill_manager_->AddSeenFormStructure( + std::unique_ptr<TestFormStructure>(form_structure2)); AutofillQueryResponseContents response; response.add_field()->set_overall_type_prediction(3); @@ -4397,7 +4412,8 @@ // |form_structure| will be owned by |autofill_manager_|. TestFormStructure* form_structure = new TestFormStructure(form); form_structure->DetermineHeuristicTypes(); - autofill_manager_->AddSeenFormStructure(base::WrapUnique(form_structure)); + autofill_manager_->AddSeenFormStructure( + std::unique_ptr<TestFormStructure>(form_structure)); AutofillQueryResponseContents response; response.add_field()->set_overall_type_prediction(3); @@ -4451,7 +4467,8 @@ // |form_structure| will be owned by |autofill_manager_|. TestFormStructure* form_structure = new TestFormStructure(form); form_structure->DetermineHeuristicTypes(); - autofill_manager_->AddSeenFormStructure(base::WrapUnique(form_structure)); + autofill_manager_->AddSeenFormStructure( + std::unique_ptr<TestFormStructure>(form_structure)); AutofillQueryResponseContents response; response.add_field()->set_overall_type_prediction(CREDIT_CARD_NAME_FIRST); @@ -4526,7 +4543,8 @@ server_types.push_back(form_structure->field(i)->heuristic_type()); } form_structure->SetFieldTypes(heuristic_types, server_types); - autofill_manager_->AddSeenFormStructure(base::WrapUnique(form_structure)); + autofill_manager_->AddSeenFormStructure( + std::unique_ptr<TestFormStructure>(form_structure)); // Fill the form. const char guid[] = "00000000-0000-0000-0000-000000000001";
diff --git a/components/autofill/core/browser/credit_card_field.cc b/components/autofill/core/browser/credit_card_field.cc index a0c484b..fb1f8bf9 100644 --- a/components/autofill/core/browser/credit_card_field.cc +++ b/components/autofill/core/browser/credit_card_field.cc
@@ -85,8 +85,7 @@ if (scanner->IsEnd()) return nullptr; - // Using 'new' to access private constructor. - auto credit_card_field = base::WrapUnique(new CreditCardField()); + auto credit_card_field = std::make_unique<CreditCardField>(); size_t saved_cursor = scanner->SaveCursor(); int nb_unknown_fields = 0;
diff --git a/components/autofill/core/browser/credit_card_field.h b/components/autofill/core/browser/credit_card_field.h index 3d462507..b1bbbe02 100644 --- a/components/autofill/core/browser/credit_card_field.h +++ b/components/autofill/core/browser/credit_card_field.h
@@ -20,6 +20,7 @@ class CreditCardField : public FormField { public: + CreditCardField(); ~CreditCardField() override; static std::unique_ptr<FormField> Parse(AutofillScanner* scanner); @@ -48,8 +49,6 @@ // a credit card. static bool IsGiftCardField(AutofillScanner* scanner); - CreditCardField(); - // Parses the expiration month/year/date fields. Returns true if it finds // something new. bool ParseExpirationDate(AutofillScanner* scanner);
diff --git a/components/autofill/core/browser/credit_card_field_unittest.cc b/components/autofill/core/browser/credit_card_field_unittest.cc index 8cc3686..f701a39 100644 --- a/components/autofill/core/browser/credit_card_field_unittest.cc +++ b/components/autofill/core/browser/credit_card_field_unittest.cc
@@ -34,7 +34,8 @@ void Parse() { AutofillScanner scanner(list_); std::unique_ptr<FormField> field = CreditCardField::Parse(&scanner); - field_ = base::WrapUnique(static_cast<CreditCardField*>(field.release())); + field_ = std::unique_ptr<CreditCardField>( + static_cast<CreditCardField*>(field.release())); } void MultipleParses() { @@ -43,7 +44,8 @@ AutofillScanner scanner(list_); while (!scanner.IsEnd()) { field = CreditCardField::Parse(&scanner); - field_ = base::WrapUnique(static_cast<CreditCardField*>(field.release())); + field_ = std::unique_ptr<CreditCardField>( + static_cast<CreditCardField*>(field.release())); if (field_ == nullptr) { scanner.Advance(); } else {
diff --git a/components/autofill/core/browser/credit_card_save_manager.cc b/components/autofill/core/browser/credit_card_save_manager.cc index a1f2ddcf..9d62395 100644 --- a/components/autofill/core/browser/credit_card_save_manager.cc +++ b/components/autofill/core/browser/credit_card_save_manager.cc
@@ -257,12 +257,16 @@ } bool CreditCardSaveManager::IsCreditCardUploadEnabled() { +#if defined(OS_IOS) // If observer_for_testing_ is set, assume we are in a browsertest and // credit card upload should be enabled by default. - return observer_for_testing_ || - ::autofill::IsCreditCardUploadEnabled( - client_->GetPrefs(), client_->GetSyncService(), - personal_data_manager_->GetAccountInfoForPaymentsServer().email); + // TODO(crbug.com/859761): Remove dependency from iOS tests on this behavior. + if (observer_for_testing_) + return true; +#endif // defined(OS_IOS) + return ::autofill::IsCreditCardUploadEnabled( + client_->GetPrefs(), client_->GetSyncService(), + personal_data_manager_->GetAccountInfoForPaymentsServer().email); } bool CreditCardSaveManager::IsUploadEnabledForNetwork(
diff --git a/components/autofill/core/browser/email_field.cc b/components/autofill/core/browser/email_field.cc index 3f4a351d..86d507ed 100644 --- a/components/autofill/core/browser/email_field.cc +++ b/components/autofill/core/browser/email_field.cc
@@ -4,7 +4,6 @@ #include "components/autofill/core/browser/email_field.h" -#include "base/memory/ptr_util.h" #include "base/strings/utf_string_conversions.h" #include "components/autofill/core/browser/autofill_scanner.h" #include "components/autofill/core/common/autofill_regex_constants.h" @@ -16,7 +15,7 @@ AutofillField* field; if (ParseFieldSpecifics(scanner, base::UTF8ToUTF16(kEmailRe), MATCH_DEFAULT | MATCH_EMAIL, &field)) { - return base::WrapUnique(new EmailField(field)); + return std::make_unique<EmailField>(field); } return nullptr;
diff --git a/components/autofill/core/browser/email_field.h b/components/autofill/core/browser/email_field.h index c47eb44..ea79202 100644 --- a/components/autofill/core/browser/email_field.h +++ b/components/autofill/core/browser/email_field.h
@@ -16,13 +16,12 @@ class EmailField : public FormField { public: static std::unique_ptr<FormField> Parse(AutofillScanner* scanner); + explicit EmailField(const AutofillField* field); protected: void AddClassifications(FieldCandidatesMap* field_candidates) const override; private: - explicit EmailField(const AutofillField* field); - const AutofillField* field_; DISALLOW_COPY_AND_ASSIGN(EmailField);
diff --git a/components/autofill/core/browser/mock_autocomplete_history_manager.h b/components/autofill/core/browser/mock_autocomplete_history_manager.h index be4a8c0..52e251de 100644 --- a/components/autofill/core/browser/mock_autocomplete_history_manager.h +++ b/components/autofill/core/browser/mock_autocomplete_history_manager.h
@@ -17,10 +17,11 @@ ~MockAutocompleteHistoryManager(); MOCK_METHOD2(Init, void(scoped_refptr<AutofillWebDataService>, bool)); - MOCK_METHOD6( + MOCK_METHOD7( OnGetAutocompleteSuggestions, void(int query_id, bool is_autocomplete_enabled, + bool autoselect_first_suggestion, const base::string16& name, const base::string16& prefix, const std::string& form_control_type,
diff --git a/components/autofill/core/browser/name_field.cc b/components/autofill/core/browser/name_field.cc index 6bbe3c1..a6ea9e7 100644 --- a/components/autofill/core/browser/name_field.cc +++ b/components/autofill/core/browser/name_field.cc
@@ -7,7 +7,6 @@ #include <memory> #include "base/macros.h" -#include "base/memory/ptr_util.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "components/autofill/core/browser/autofill_scanner.h" @@ -23,13 +22,12 @@ class FullNameField : public NameField { public: static std::unique_ptr<FullNameField> Parse(AutofillScanner* scanner); + explicit FullNameField(AutofillField* field); protected: void AddClassifications(FieldCandidatesMap* field_candidates) const override; private: - explicit FullNameField(AutofillField* field); - AutofillField* field_; DISALLOW_COPY_AND_ASSIGN(FullNameField); @@ -91,7 +89,7 @@ // "Travel Profile Name". AutofillField* field = nullptr; if (ParseField(scanner, UTF8ToUTF16(kNameRe), &field)) - return base::WrapUnique(new FullNameField(field)); + return std::make_unique<FullNameField>(field); return nullptr; }
diff --git a/components/autofill/core/browser/name_field_unittest.cc b/components/autofill/core/browser/name_field_unittest.cc index b575d16..e6a3d226 100644 --- a/components/autofill/core/browser/name_field_unittest.cc +++ b/components/autofill/core/browser/name_field_unittest.cc
@@ -31,7 +31,7 @@ // Downcast for tests. static std::unique_ptr<NameField> Parse(AutofillScanner* scanner) { std::unique_ptr<FormField> field = NameField::Parse(scanner); - return base::WrapUnique(static_cast<NameField*>(field.release())); + return std::unique_ptr<NameField>(static_cast<NameField*>(field.release())); } private:
diff --git a/components/autofill/core/browser/personal_data_manager_unittest.cc b/components/autofill/core/browser/personal_data_manager_unittest.cc index cb9076a..bfc241d2 100644 --- a/components/autofill/core/browser/personal_data_manager_unittest.cc +++ b/components/autofill/core/browser/personal_data_manager_unittest.cc
@@ -3848,7 +3848,7 @@ // Create the |existing_profiles| vector. std::vector<std::unique_ptr<AutofillProfile>> existing_profiles; existing_profiles.push_back(std::move(profile1)); - existing_profiles.push_back(base::WrapUnique(profile2)); + existing_profiles.push_back(std::unique_ptr<AutofillProfile>(profile2)); // Create a new imported profile with no company name. AutofillProfile imported_profile(base::GenerateGUID(), test::kEmptyOrigin); @@ -3891,7 +3891,7 @@ // Create the |existing_profiles| vector. std::vector<std::unique_ptr<AutofillProfile>> existing_profiles; - existing_profiles.push_back(base::WrapUnique(profile)); + existing_profiles.push_back(std::unique_ptr<AutofillProfile>(profile)); // Change the current date. test_clock.SetNow(kSomeLaterTime); @@ -3971,11 +3971,11 @@ // Add the profiles. std::vector<std::unique_ptr<AutofillProfile>> existing_profiles; - existing_profiles.push_back(base::WrapUnique(profile1)); - existing_profiles.push_back(base::WrapUnique(profile2)); - existing_profiles.push_back(base::WrapUnique(profile3)); - existing_profiles.push_back(base::WrapUnique(profile4)); - existing_profiles.push_back(base::WrapUnique(profile5)); + existing_profiles.push_back(std::unique_ptr<AutofillProfile>(profile1)); + existing_profiles.push_back(std::unique_ptr<AutofillProfile>(profile2)); + existing_profiles.push_back(std::unique_ptr<AutofillProfile>(profile3)); + existing_profiles.push_back(std::unique_ptr<AutofillProfile>(profile4)); + existing_profiles.push_back(std::unique_ptr<AutofillProfile>(profile5)); // Enable the profile cleanup. EnableAutofillProfileCleanup(); @@ -4056,11 +4056,11 @@ // Add the profiles. std::vector<std::unique_ptr<AutofillProfile>> existing_profiles; - existing_profiles.push_back(base::WrapUnique(profile1)); - existing_profiles.push_back(base::WrapUnique(profile2)); - existing_profiles.push_back(base::WrapUnique(profile3)); - existing_profiles.push_back(base::WrapUnique(profile4)); - existing_profiles.push_back(base::WrapUnique(profile5)); + existing_profiles.push_back(std::unique_ptr<AutofillProfile>(profile1)); + existing_profiles.push_back(std::unique_ptr<AutofillProfile>(profile2)); + existing_profiles.push_back(std::unique_ptr<AutofillProfile>(profile3)); + existing_profiles.push_back(std::unique_ptr<AutofillProfile>(profile4)); + existing_profiles.push_back(std::unique_ptr<AutofillProfile>(profile5)); // Enable the profile cleanup. EnableAutofillProfileCleanup(); @@ -4115,12 +4115,14 @@ credit_card4->set_billing_address_id("F"); // Add the credit cards to the database. - personal_data_->local_credit_cards_.push_back(base::WrapUnique(credit_card1)); + personal_data_->local_credit_cards_.push_back( + std::unique_ptr<CreditCard>(credit_card1)); personal_data_->server_credit_cards_.push_back( - base::WrapUnique(credit_card2)); - personal_data_->local_credit_cards_.push_back(base::WrapUnique(credit_card3)); + std::unique_ptr<CreditCard>(credit_card2)); + personal_data_->local_credit_cards_.push_back( + std::unique_ptr<CreditCard>(credit_card3)); personal_data_->server_credit_cards_.push_back( - base::WrapUnique(credit_card4)); + std::unique_ptr<CreditCard>(credit_card4)); personal_data_->UpdateCardsBillingAddressReference(guids_merge_map);
diff --git a/components/autofill/core/browser/phone_field_unittest.cc b/components/autofill/core/browser/phone_field_unittest.cc index d8374d0..96ee9c8 100644 --- a/components/autofill/core/browser/phone_field_unittest.cc +++ b/components/autofill/core/browser/phone_field_unittest.cc
@@ -38,7 +38,8 @@ // Downcast for tests. static std::unique_ptr<PhoneField> Parse(AutofillScanner* scanner) { std::unique_ptr<FormField> field = PhoneField::Parse(scanner); - return base::WrapUnique(static_cast<PhoneField*>(field.release())); + return std::unique_ptr<PhoneField>( + static_cast<PhoneField*>(field.release())); } void Clear() {
diff --git a/components/autofill/core/browser/search_field_unittest.cc b/components/autofill/core/browser/search_field_unittest.cc index 4c65cb0..f242351 100644 --- a/components/autofill/core/browser/search_field_unittest.cc +++ b/components/autofill/core/browser/search_field_unittest.cc
@@ -32,7 +32,8 @@ // Downcast for tests. static std::unique_ptr<SearchField> Parse(AutofillScanner* scanner) { std::unique_ptr<FormField> field = SearchField::Parse(scanner); - return base::WrapUnique(static_cast<SearchField*>(field.release())); + return std::unique_ptr<SearchField>( + static_cast<SearchField*>(field.release())); } private:
diff --git a/components/autofill/core/browser/webdata/autofill_profile_syncable_service.cc b/components/autofill/core/browser/webdata/autofill_profile_syncable_service.cc index cd6d492..51d3cb7 100644 --- a/components/autofill/core/browser/webdata/autofill_profile_syncable_service.cc +++ b/components/autofill/core/browser/webdata/autofill_profile_syncable_service.cc
@@ -76,8 +76,8 @@ const std::string& app_locale) { web_data_service->GetDBUserData()->SetUserData( AutofillProfileSyncableServiceUserDataKey(), - base::WrapUnique( - new AutofillProfileSyncableService(webdata_backend, app_locale))); + std::make_unique<AutofillProfileSyncableService>(webdata_backend, + app_locale)); } // static
diff --git a/components/autofill/core/browser/webdata/autofill_profile_syncable_service.h b/components/autofill/core/browser/webdata/autofill_profile_syncable_service.h index ce6efa43..079ff91 100644 --- a/components/autofill/core/browser/webdata/autofill_profile_syncable_service.h +++ b/components/autofill/core/browser/webdata/autofill_profile_syncable_service.h
@@ -50,6 +50,9 @@ public syncer::SyncableService, public AutofillWebDataServiceObserverOnDBSequence { public: + AutofillProfileSyncableService(AutofillWebDataBackend* webdata_backend, + const std::string& app_locale); + ~AutofillProfileSyncableService() override; // Creates a new AutofillProfileSyncableService and hangs it off of @@ -87,9 +90,6 @@ const syncer::SyncableService::StartSyncFlare& flare); protected: - AutofillProfileSyncableService(AutofillWebDataBackend* webdata_backend, - const std::string& app_locale); - // A convenience wrapper of a bunch of state we pass around while // associating models, and send to the WebDatabase for persistence. // We do this so we hold the write lock for only a small period.
diff --git a/components/autofill/core/browser/webdata/autofill_profile_syncable_service_unittest.cc b/components/autofill/core/browser/webdata/autofill_profile_syncable_service_unittest.cc index 7e94e37d..b4dc3f5 100644 --- a/components/autofill/core/browser/webdata/autofill_profile_syncable_service_unittest.cc +++ b/components/autofill/core/browser/webdata/autofill_profile_syncable_service_unittest.cc
@@ -1604,7 +1604,7 @@ .WillOnce(Return(true)); autofill_syncable_service_.MergeDataAndStartSyncing( syncer::AUTOFILL_PROFILE, data_list, - base::WrapUnique(sync_change_processor), + std::unique_ptr<TestSyncChangeProcessor>(sync_change_processor), std::unique_ptr<syncer::SyncErrorFactory>( new syncer::SyncErrorFactoryMock())); @@ -1640,7 +1640,7 @@ .WillOnce(Return(true)); autofill_syncable_service_.MergeDataAndStartSyncing( syncer::AUTOFILL_PROFILE, syncer::SyncDataList(), - base::WrapUnique(new TestSyncChangeProcessor), + std::make_unique<TestSyncChangeProcessor>(), std::unique_ptr<syncer::SyncErrorFactory>( new syncer::SyncErrorFactoryMock())); AutofillProfile server_profile(AutofillProfile::SERVER_PROFILE, "server-id");
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc b/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc index 48911cd..86fd8a07 100644 --- a/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc +++ b/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc
@@ -611,8 +611,8 @@ const std::string& app_locale) { web_data_service->GetDBUserData()->SetUserData( AutofillWalletMetadataSyncableServiceUserDataKey(), - base::WrapUnique(new AutofillWalletMetadataSyncableService( - web_data_backend, app_locale))); + std::make_unique<AutofillWalletMetadataSyncableService>(web_data_backend, + app_locale)); } // static
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.h b/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.h index 4df82f0..0169b0de 100644 --- a/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.h +++ b/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.h
@@ -49,6 +49,10 @@ public syncer::SyncableService, public AutofillWebDataServiceObserverOnDBSequence { public: + AutofillWalletMetadataSyncableService( + AutofillWebDataBackend* web_data_backend, + const std::string& app_locale); + ~AutofillWalletMetadataSyncableService() override; // Determines whether this bridge should be monitoring the Wallet data. This @@ -91,10 +95,6 @@ AutofillWebDataService* web_data_service); protected: - AutofillWalletMetadataSyncableService( - AutofillWebDataBackend* web_data_backend, - const std::string& app_locale); - // Populates the provided |profiles| and |cards| with mappings from server ID // to server profiles and server cards read from disk. This data contains the // usage stats. Returns true on success.
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc b/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc index 68e210f80..3cc21a09 100644 --- a/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc +++ b/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc
@@ -252,8 +252,8 @@ const std::string& app_locale) { web_data_service->GetDBUserData()->SetUserData( AutofillWalletSyncableServiceUserDataKey(), - base::WrapUnique( - new AutofillWalletSyncableService(webdata_backend, app_locale))); + std::make_unique<AutofillWalletSyncableService>(webdata_backend, + app_locale)); } // static
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.h b/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.h index ff4f62d..e8c130d 100644 --- a/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.h +++ b/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.h
@@ -29,6 +29,9 @@ : public base::SupportsUserData::Data, public syncer::SyncableService { public: + AutofillWalletSyncableService(AutofillWebDataBackend* webdata_backend, + const std::string& app_locale); + ~AutofillWalletSyncableService() override; // syncer::SyncableService implementation. @@ -60,11 +63,6 @@ void InjectStartSyncFlare( const syncer::SyncableService::StartSyncFlare& flare); - protected: - AutofillWalletSyncableService( - AutofillWebDataBackend* webdata_backend, - const std::string& app_locale); - private: FRIEND_TEST_ALL_PREFIXES(AutofillWalletSyncableServiceTest, CopyRelevantMetadataFromDisk_KeepLocalAddresses);
diff --git a/components/autofill/core/browser/webdata/web_data_service_unittest.cc b/components/autofill/core/browser/webdata/web_data_service_unittest.cc index 97f8650..2f6fba9 100644 --- a/components/autofill/core/browser/webdata/web_data_service_unittest.cc +++ b/components/autofill/core/browser/webdata/web_data_service_unittest.cc
@@ -106,7 +106,7 @@ base::CreateSingleThreadTaskRunnerWithTraits({base::MayBlock()}); wdbs_ = new WebDatabaseService(path, base::ThreadTaskRunnerHandle::Get(), db_task_runner); - wdbs_->AddTable(base::WrapUnique(new AutofillTable)); + wdbs_->AddTable(std::make_unique<AutofillTable>()); wdbs_->LoadDatabase(); wds_ = new AutofillWebDataService(
diff --git a/components/autofill/core/common/autofill_l10n_util.cc b/components/autofill/core/common/autofill_l10n_util.cc index 9ab031f..f22057ab 100644 --- a/components/autofill/core/common/autofill_l10n_util.cc +++ b/components/autofill/core/common/autofill_l10n_util.cc
@@ -31,7 +31,7 @@ << locale_name; // Attempt to load the English locale. - collator = base::WrapUnique( + collator.reset( icu::Collator::createInstance(icu::Locale::getEnglish(), ignored)); if (!collator) { LOG(ERROR) << "Failed to initialize the ICU Collator with the English "
diff --git a/components/autofill/ios/browser/autofill_driver_ios_webframe.h b/components/autofill/ios/browser/autofill_driver_ios_webframe.h index 3990337..56a6630 100644 --- a/components/autofill/ios/browser/autofill_driver_ios_webframe.h +++ b/components/autofill/ios/browser/autofill_driver_ios_webframe.h
@@ -34,18 +34,19 @@ AutofillManager::AutofillDownloadManagerState enable_download_manager); ~AutofillDriverIOSWebFrameFactory() override; - // Returns a AutofillDriverIOSFromWebFrame for |web_frame|, creating it if - // needed. - AutofillDriverIOSWebFrame* AutofillDriverIOSFromWebFrame( - web::WebFrame* web_frame); - - private: AutofillDriverIOSWebFrameFactory( web::WebState* web_state, AutofillClient* client, id<AutofillDriverIOSBridge> bridge, const std::string& app_locale, AutofillManager::AutofillDownloadManagerState enable_download_manager); + + // Returns a AutofillDriverIOSFromWebFrame for |web_frame|, creating it if + // needed. + AutofillDriverIOSWebFrame* AutofillDriverIOSFromWebFrame( + web::WebFrame* web_frame); + + private: web::WebState* web_state_ = nullptr; AutofillClient* client_ = nullptr; id<AutofillDriverIOSBridge> bridge_ = nil; @@ -96,7 +97,6 @@ AutofillDriverIOS* driver() { return driver_.get(); } scoped_refptr<AutofillDriverIOSRefCountable> GetRetainableDriver(); - private: AutofillDriverIOSWebFrame( web::WebState* web_state, web::WebFrame* web_frame,
diff --git a/components/autofill/ios/browser/autofill_driver_ios_webframe.mm b/components/autofill/ios/browser/autofill_driver_ios_webframe.mm index c924b11..2c4988db 100644 --- a/components/autofill/ios/browser/autofill_driver_ios_webframe.mm +++ b/components/autofill/ios/browser/autofill_driver_ios_webframe.mm
@@ -20,8 +20,8 @@ web_state->SetUserData( UserDataKey(), - base::WrapUnique(new AutofillDriverIOSWebFrameFactory( - web_state, client, bridge, app_locale, enable_download_manager))); + std::make_unique<AutofillDriverIOSWebFrameFactory>( + web_state, client, bridge, app_locale, enable_download_manager)); } AutofillDriverIOSWebFrameFactory::AutofillDriverIOSWebFrameFactory( @@ -59,9 +59,9 @@ return; web_frame->SetUserData(UserDataKey(), - base::WrapUnique(new AutofillDriverIOSWebFrame( + std::make_unique<AutofillDriverIOSWebFrame>( web_state, web_frame, client, bridge, app_locale, - enable_download_manager))); + enable_download_manager)); } AutofillDriverIOSRefCountable::AutofillDriverIOSRefCountable(
diff --git a/components/autofill/ios/browser/autofill_driver_ios_webstate.h b/components/autofill/ios/browser/autofill_driver_ios_webstate.h index d6fc069..7e3dabd 100644 --- a/components/autofill/ios/browser/autofill_driver_ios_webstate.h +++ b/components/autofill/ios/browser/autofill_driver_ios_webstate.h
@@ -28,7 +28,6 @@ ~AutofillDriverIOSWebState() override; - protected: AutofillDriverIOSWebState( web::WebState* web_state, AutofillClient* client,
diff --git a/components/autofill/ios/browser/autofill_driver_ios_webstate.mm b/components/autofill/ios/browser/autofill_driver_ios_webstate.mm index d69d3b5..0237ae17 100644 --- a/components/autofill/ios/browser/autofill_driver_ios_webstate.mm +++ b/components/autofill/ios/browser/autofill_driver_ios_webstate.mm
@@ -24,8 +24,8 @@ web_state->SetUserData( UserDataKey(), - base::WrapUnique(new AutofillDriverIOSWebState( - web_state, client, bridge, app_locale, enable_download_manager))); + std::make_unique<AutofillDriverIOSWebState>( + web_state, client, bridge, app_locale, enable_download_manager)); } AutofillDriverIOSWebState::AutofillDriverIOSWebState(
diff --git a/components/autofill_assistant/browser/service.proto b/components/autofill_assistant/browser/service.proto index 1ae95f37..8418740d 100644 --- a/components/autofill_assistant/browser/service.proto +++ b/components/autofill_assistant/browser/service.proto
@@ -627,6 +627,10 @@ // Mid that comes from Knowledge Graph. Uniquely identify the object that this // proto describes. optional string m_id = 5; + + // Price label containing the total amount and the currency to pay, formatted + // in the client's locale (e.g., $123.00). + optional string total_price = 6; } // Show contextual information.
diff --git a/components/browser_sync/profile_sync_test_util.cc b/components/browser_sync/profile_sync_test_util.cc index 343def56..da6a872 100644 --- a/components/browser_sync/profile_sync_test_util.cc +++ b/components/browser_sync/profile_sync_test_util.cc
@@ -210,7 +210,7 @@ ProfileSyncServiceBundle::ProfileSyncServiceBundle() : db_thread_(base::SequencedTaskRunnerHandle::Get()), - identity_test_env_(true) { + identity_test_env_(&test_url_loader_factory_) { RegisterPrefsForProfileSyncService(pref_service_.registry()); identity_test_env_.SetAutomaticIssueOfAccessTokens(true); identity_provider_ = std::make_unique<invalidation::ProfileIdentityProvider>(
diff --git a/components/browser_sync/sync_auth_manager_unittest.cc b/components/browser_sync/sync_auth_manager_unittest.cc index 72d59a3..945f7c2 100644 --- a/components/browser_sync/sync_auth_manager_unittest.cc +++ b/components/browser_sync/sync_auth_manager_unittest.cc
@@ -31,8 +31,7 @@ using CredentialsChangedCallback = SyncAuthManager::CredentialsChangedCallback; - SyncAuthManagerTest() - : identity_env_(/*use_fake_url_loader_for_gaia_cookie_manager=*/true) { + SyncAuthManagerTest() : identity_env_(&test_url_loader_factory_) { syncer::SyncPrefs::RegisterProfilePrefs(pref_service_.registry()); sync_prefs_ = std::make_unique<syncer::SyncPrefs>(&pref_service_); } @@ -60,6 +59,7 @@ private: base::test::ScopedTaskEnvironment task_environment_; + network::TestURLLoaderFactory test_url_loader_factory_; identity::IdentityTestEnvironment identity_env_; sync_preferences::TestingPrefServiceSyncable pref_service_; std::unique_ptr<syncer::SyncPrefs> sync_prefs_;
diff --git a/components/browsing_data_strings.grdp b/components/browsing_data_strings.grdp index b1a53bbd..3e9c5ee 100644 --- a/components/browsing_data_strings.grdp +++ b/components/browsing_data_strings.grdp
@@ -125,12 +125,12 @@ =1 {1 item} other {# items}} </message> - <message name="IDS_DEL_HOSTED_APPS_COUNTER" desc="A counter showing how many hosted apps the user has. We show the number of apps, and in the cases where there is one or two apps, we will also give two example app names, denoted as placeholders $1 and $2. If there are more than two apps, we will give two examples and say 'and X more'. The 'and X more' string, denoted by the placeholder $3, will be supplied from another message."> + <message name="IDS_DEL_HOSTED_APPS_COUNTER" desc="A counter showing how many hosted apps the user has. We show the number of apps, and in the cases where there is one or two apps, we will also give two example app names, denoted as placeholders EXAMPLE_APP_1 and EXAMPLE_APP_2. If there are more than two apps, we will give two examples and say 'and X more'. The 'and X more' string, denoted by the placeholder AND_MORE, will be supplied from another message."> {COUNT, plural, =0 {None} - =1 {1 app ($1)} - =2 {2 apps ($1, $2)} - other {# apps ($1, $2, $3)}} + =1 {1 app (<ph name="EXAMPLE_APP_1">$1<ex>Gmail</ex></ph>)} + =2 {2 apps (<ph name="EXAMPLE_APP_1">$1<ex>Gmail</ex></ph>, <ph name="EXAMPLE_APP_2">$2<ex>Youtube</ex></ph>)} + other {# apps (<ph name="EXAMPLE_APP_1">$1<ex>Gmail</ex></ph>, <ph name="EXAMPLE_APP_2">$2<ex>Youtube</ex></ph>, <ph name="AND_MORE">$3<ex>and 9 more</ex></ph>)}} </message> <message name="IDS_DEL_HOSTED_APPS_COUNTER_AND_X_MORE" desc="This message stands at the end of a sentence enumerating hosted apps the user has installed, e.g.: 'App1, App2, and 5 more'"> {COUNT, plural,
diff --git a/components/content_settings/core/browser/BUILD.gn b/components/content_settings/core/browser/BUILD.gn index 6484333..8e6d992b 100644 --- a/components/content_settings/core/browser/BUILD.gn +++ b/components/content_settings/core/browser/BUILD.gn
@@ -62,6 +62,10 @@ "//url", ] + if (is_android) { + deps += [ "//media" ] + } + configs += [ "//build/config/compiler:no_size_t_to_int_warning", "//build/config/compiler:wexit_time_destructors",
diff --git a/components/content_settings/core/browser/DEPS b/components/content_settings/core/browser/DEPS index 1cd4d4e..747e920 100644 --- a/components/content_settings/core/browser/DEPS +++ b/components/content_settings/core/browser/DEPS
@@ -6,6 +6,7 @@ "+components/sync_preferences", "+components/url_formatter", "+extensions/buildflags", + "+media/base/android", "+net/base", "+net/cookies", "+services/preferences/public",
diff --git a/components/content_settings/core/browser/content_settings_registry.cc b/components/content_settings/core/browser/content_settings_registry.cc index f7caa647..4924d2c 100644 --- a/components/content_settings/core/browser/content_settings_registry.cc +++ b/components/content_settings/core/browser/content_settings_registry.cc
@@ -16,6 +16,10 @@ #include "components/content_settings/core/browser/website_settings_registry.h" #include "components/content_settings/core/common/content_settings.h" +#if defined(OS_ANDROID) +#include "media/base/android/media_drm_bridge.h" +#endif + namespace content_settings { namespace { @@ -68,6 +72,19 @@ return std::set<ContentSetting>(settings, settings + arraysize(settings)); } +ContentSetting GetInitialDefaultContentSettingForProtectedMediaIdentifier() { +// On Android, the default value is ALLOW or ASK depending on whether per-origin +// provisioning is used (https://crbug.com/854737 and https://crbug.com/904883). +// On ChromeOS the default value is always ASK. +#if defined(OS_ANDROID) + return media::MediaDrmBridge::IsPerOriginProvisioningSupported() + ? CONTENT_SETTING_ALLOW + : CONTENT_SETTING_ASK; +#else + return CONTENT_SETTING_ASK; +#endif // defined(OS_ANDROID) +} + } // namespace // static @@ -264,26 +281,19 @@ ContentSettingsInfo::PERSISTENT, ContentSettingsInfo::EXCEPTIONS_ON_SECURE_ORIGINS_ONLY); + const auto protected_media_identifier_setting = + GetInitialDefaultContentSettingForProtectedMediaIdentifier(); Register(CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER, - "protected-media-identifier", -// On Android, the default value is ALLOW. See https://crbug.com/854737 for -// details. On ChromeOS the default value is still ASK. -#if defined(OS_ANDROID) - CONTENT_SETTING_ALLOW, -#else - CONTENT_SETTING_ASK, -#endif // defined(OS_ANDROID) + "protected-media-identifier", protected_media_identifier_setting, WebsiteSettingsInfo::UNSYNCABLE, WhitelistedSchemes(), ValidSettings(CONTENT_SETTING_ALLOW, CONTENT_SETTING_BLOCK, CONTENT_SETTING_ASK), WebsiteSettingsInfo::REQUESTING_ORIGIN_AND_TOP_LEVEL_ORIGIN_SCOPE, WebsiteSettingsRegistry::PLATFORM_ANDROID | WebsiteSettingsRegistry::PLATFORM_CHROMEOS, -#if defined(OS_ANDROID) - ContentSettingsInfo::INHERIT_IN_INCOGNITO, -#else - ContentSettingsInfo::INHERIT_IF_LESS_PERMISSIVE, -#endif // defined(OS_ANDROID) + protected_media_identifier_setting == CONTENT_SETTING_ALLOW + ? ContentSettingsInfo::INHERIT_IN_INCOGNITO + : ContentSettingsInfo::INHERIT_IF_LESS_PERMISSIVE, ContentSettingsInfo::PERSISTENT, ContentSettingsInfo::EXCEPTIONS_ON_SECURE_ORIGINS_ONLY);
diff --git a/components/exo/BUILD.gn b/components/exo/BUILD.gn index 9c24e95..26bea2d 100644 --- a/components/exo/BUILD.gn +++ b/components/exo/BUILD.gn
@@ -163,7 +163,7 @@ "test/test_client_controlled_state_delegate.h", ] deps += [ - "//ash:test_support_without_content", + "//ash:test_support", "//ash/public/cpp", ] } @@ -227,7 +227,7 @@ deps += [ "//ash", - "//ash:test_support_without_content", + "//ash:test_support", "//ash/public/cpp", "//ui/keyboard", ] @@ -276,7 +276,7 @@ ] deps += [ - "//ash:test_support_without_content", + "//ash:test_support", "//ash/public/cpp", ]
diff --git a/components/exo/wayland/BUILD.gn b/components/exo/wayland/BUILD.gn index 5554b07..0423fa8 100644 --- a/components/exo/wayland/BUILD.gn +++ b/components/exo/wayland/BUILD.gn
@@ -4,9 +4,9 @@ import("//build/config/linux/pkg_config.gni") import("//build/config/ui.gni") +import("//testing/test.gni") import("//ui/base/ui_features.gni") import("//ui/ozone/ozone.gni") -import("//testing/test.gni") declare_args() { # Enable experimental vulkan wayland client. @@ -426,7 +426,7 @@ deps += [ "//ash", - "//ash:test_support_without_content", + "//ash:test_support", "//ash/public/cpp", ] }
diff --git a/components/exo/wayland/clients/test/wayland_client_test.cc b/components/exo/wayland/clients/test/wayland_client_test.cc index fe44c7d..22c9641 100644 --- a/components/exo/wayland/clients/test/wayland_client_test.cc +++ b/components/exo/wayland/clients/test/wayland_client_test.cc
@@ -10,7 +10,6 @@ #include "ash/session/session_controller.h" #include "ash/shell.h" -#include "ash/test/ash_test_environment.h" #include "ash/test/ash_test_helper.h" #include "ash/test/ash_test_views_delegate.h" #include "base/command_line.h" @@ -31,20 +30,6 @@ namespace exo { -class AshTestEnvironmentWayland : public ash::AshTestEnvironment { - public: - AshTestEnvironmentWayland() = default; - ~AshTestEnvironmentWayland() override = default; - - // Overriden from ash::AshTestEnvironment: - std::unique_ptr<ash::AshTestViewsDelegate> CreateViewsDelegate() override { - return std::make_unique<ash::AshTestViewsDelegate>(); - } - - private: - DISALLOW_COPY_AND_ASSIGN(AshTestEnvironmentWayland); -}; - // The ui message loop for running the wayland server. If it is not provided, we // will use external wayland server. scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner_ = nullptr; @@ -124,9 +109,7 @@ // Disable window animation when running tests. command_line->AppendSwitch(wm::switches::kWindowAnimationsDisabled); - ash_test_environment_ = std::make_unique<AshTestEnvironmentWayland>(); - ash_test_helper_ = - std::make_unique<ash::AshTestHelper>(ash_test_environment_.get()); + ash_test_helper_ = std::make_unique<ash::AshTestHelper>(); ash_test_helper_->SetUp(false /* start_session */, true /* provide_local_state */); @@ -164,7 +147,6 @@ ash::Shell::Get()->session_controller()->NotifyChromeTerminating(); ash_test_helper_->TearDown(); ash_test_helper_ = nullptr; - ash_test_environment_ = nullptr; xdg_temp_dir_ = nullptr; event->Signal(); }
diff --git a/components/exo/wayland/clients/test/wayland_client_test.h b/components/exo/wayland/clients/test/wayland_client_test.h index 16624b51..76436dc8 100644 --- a/components/exo/wayland/clients/test/wayland_client_test.h +++ b/components/exo/wayland/clients/test/wayland_client_test.h
@@ -13,7 +13,6 @@ #include "testing/gtest/include/gtest/gtest.h" namespace ash { -class AshTestEnvironment; class AshTestHelper; } // namespace ash @@ -39,7 +38,7 @@ scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner); protected: - // Overridden from AshTestBase: + // Overridden from testing::Test: void SetUp() override; void TearDown() override; @@ -51,7 +50,6 @@ // Below objects can only be accessed from UI thread. std::unique_ptr<base::ScopedTempDir> xdg_temp_dir_; - std::unique_ptr<ash::AshTestEnvironment> ash_test_environment_; std::unique_ptr<ash::AshTestHelper> ash_test_helper_; std::unique_ptr<WMHelper> wm_helper_; std::unique_ptr<Display> display_;
diff --git a/components/feedback/feedback_uploader.cc b/components/feedback/feedback_uploader.cc index 7b536c0..20e3caed 100644 --- a/components/feedback/feedback_uploader.cc +++ b/components/feedback/feedback_uploader.cc
@@ -104,7 +104,10 @@ retry_delay_ *= 2; report_being_dispatched_->set_upload_at(retry_delay_ + base::Time::Now()); reports_queue_.emplace(report_being_dispatched_); + VLOG(1) << "Report upload failed. Will retry again after " + << retry_delay_.InSeconds() << " seconds."; } else { + VLOG(1) << "Report upload failed. Will discard."; // The report won't be retried, hence explicitly delete its file on disk. report_being_dispatched_->DeleteReportOnDisk(); } @@ -128,6 +131,7 @@ network::ResourceRequest* resource_request) {} void FeedbackUploader::DispatchReport() { + VLOG(1) << "Uploading report."; net::NetworkTrafficAnnotationTag traffic_annotation = net::DefineNetworkTrafficAnnotation("chrome_feedback_report_app", R"( semantics { @@ -255,6 +259,7 @@ void FeedbackUploader::QueueReportWithDelay(std::unique_ptr<std::string> data, base::TimeDelta delay) { + VLOG(1) << "Queuing report with delay = " << delay.InSeconds() << " seconds."; reports_queue_.emplace(base::MakeRefCounted<FeedbackReport>( feedback_reports_path_, base::Time::Now() + delay, std::move(data), task_runner_));
diff --git a/components/gcm_driver/fake_gcm_client.cc b/components/gcm_driver/fake_gcm_client.cc index 1e7c21b..eb17380 100644 --- a/components/gcm_driver/fake_gcm_client.cc +++ b/components/gcm_driver/fake_gcm_client.cc
@@ -117,7 +117,7 @@ } void FakeGCMClient::Register( - const linked_ptr<RegistrationInfo>& registration_info) { + scoped_refptr<RegistrationInfo> registration_info) { DCHECK(io_thread_->RunsTasksInCurrentSequence()); std::string registration_id; @@ -140,17 +140,17 @@ base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(&FakeGCMClient::RegisterFinished, weak_ptr_factory_.GetWeakPtr(), - registration_info, registration_id)); + std::move(registration_info), registration_id)); } bool FakeGCMClient::ValidateRegistration( - const linked_ptr<RegistrationInfo>& registration_info, + scoped_refptr<RegistrationInfo> registration_info, const std::string& registration_id) { return true; } void FakeGCMClient::Unregister( - const linked_ptr<RegistrationInfo>& registration_info) { + scoped_refptr<RegistrationInfo> registration_info) { DCHECK(io_thread_->RunsTasksInCurrentSequence()); base::ThreadTaskRunnerHandle::Get()->PostTask( @@ -271,17 +271,16 @@ } void FakeGCMClient::RegisterFinished( - const linked_ptr<RegistrationInfo>& registration_info, + scoped_refptr<RegistrationInfo> registration_info, const std::string& registrion_id) { - delegate_->OnRegisterFinished( - registration_info, - registrion_id, - registrion_id.empty() ? SERVER_ERROR : SUCCESS); + delegate_->OnRegisterFinished(std::move(registration_info), registrion_id, + registrion_id.empty() ? SERVER_ERROR : SUCCESS); } void FakeGCMClient::UnregisterFinished( - const linked_ptr<RegistrationInfo>& registration_info) { - delegate_->OnUnregisterFinished(registration_info, GCMClient::SUCCESS); + scoped_refptr<RegistrationInfo> registration_info) { + delegate_->OnUnregisterFinished(std::move(registration_info), + GCMClient::SUCCESS); } void FakeGCMClient::SendFinished(const std::string& app_id,
diff --git a/components/gcm_driver/fake_gcm_client.h b/components/gcm_driver/fake_gcm_client.h index 726b0d5..d3bd6f6 100644 --- a/components/gcm_driver/fake_gcm_client.h +++ b/components/gcm_driver/fake_gcm_client.h
@@ -55,12 +55,10 @@ Delegate* delegate) override; void Start(StartMode start_mode) override; void Stop() override; - void Register(const linked_ptr<RegistrationInfo>& registration_info) override; - bool ValidateRegistration( - const linked_ptr<RegistrationInfo>& registration_info, - const std::string& registration_id) override; - void Unregister( - const linked_ptr<RegistrationInfo>& registration_info) override; + void Register(scoped_refptr<RegistrationInfo> registration_info) override; + bool ValidateRegistration(scoped_refptr<RegistrationInfo> registration_info, + const std::string& registration_id) override; + void Unregister(scoped_refptr<RegistrationInfo> registration_info) override; void Send(const std::string& app_id, const std::string& receiver_id, const OutgoingMessage& message) override; @@ -104,11 +102,9 @@ // Called on IO thread. void DoStart(); void Started(); - void RegisterFinished( - const linked_ptr<RegistrationInfo>& registration_info, - const std::string& registrion_id); - void UnregisterFinished( - const linked_ptr<RegistrationInfo>& registration_info); + void RegisterFinished(scoped_refptr<RegistrationInfo> registration_info, + const std::string& registrion_id); + void UnregisterFinished(scoped_refptr<RegistrationInfo> registration_info); void SendFinished(const std::string& app_id, const OutgoingMessage& message); void MessageReceived(const std::string& app_id, const IncomingMessage& message);
diff --git a/components/gcm_driver/gcm_client.h b/components/gcm_driver/gcm_client.h index 674995b..874cd360 100644 --- a/components/gcm_driver/gcm_client.h +++ b/components/gcm_driver/gcm_client.h
@@ -12,28 +12,26 @@ #include <string> #include <vector> -#include "base/memory/linked_ptr.h" +#include "base/memory/scoped_refptr.h" #include "components/gcm_driver/common/gcm_messages.h" #include "components/gcm_driver/gcm_activity.h" #include "components/gcm_driver/registration_info.h" #include "services/network/public/mojom/proxy_resolving_socket.mojom.h" -template <class T> class scoped_refptr; - namespace base { class FilePath; class RetainingOneShotTimer; class SequencedTaskRunner; -} +} // namespace base namespace net { class IPEndPoint; -} +} // namespace net namespace network { class NetworkConnectionTracker; class SharedURLLoaderFactory; -} +} // namespace network namespace gcm { @@ -159,7 +157,7 @@ // |registration_id|: non-empty if the registration completed successfully. // |result|: the type of the error if an error occured, success otherwise. virtual void OnRegisterFinished( - const linked_ptr<RegistrationInfo>& registration_info, + scoped_refptr<RegistrationInfo> registration_info, const std::string& registration_id, Result result) = 0; @@ -168,7 +166,7 @@ // registration. // |result|: result of the unregistration. virtual void OnUnregisterFinished( - const linked_ptr<RegistrationInfo>& registration_info, + scoped_refptr<RegistrationInfo> registration_info, GCMClient::Result result) = 0; // Called when the message is scheduled to send successfully or an error @@ -268,14 +266,13 @@ // registration. For GCM, it will contain app id and // sender IDs. For InstanceID, it will contain app_id, // authorized entity and scope. - virtual void Register( - const linked_ptr<RegistrationInfo>& registration_info) = 0; + virtual void Register(scoped_refptr<RegistrationInfo> registration_info) = 0; // Checks that the provided |registration_id| (aka token for Instance ID // registrations) matches the stored registration info. Also checks sender IDs // match for GCM registrations. virtual bool ValidateRegistration( - const linked_ptr<RegistrationInfo>& registration_info, + scoped_refptr<RegistrationInfo> registration_info, const std::string& registration_id) = 0; // Unregisters from the server to stop accessing the provided service. @@ -286,7 +283,7 @@ // IDs can be ingored). For InstanceID, it will contain // app id, authorized entity and scope. virtual void Unregister( - const linked_ptr<RegistrationInfo>& registration_info) = 0; + scoped_refptr<RegistrationInfo> registration_info) = 0; // Sends a message to a given receiver. Delegate::OnSendFinished will be // called asynchronously upon completion.
diff --git a/components/gcm_driver/gcm_client_impl.cc b/components/gcm_driver/gcm_client_impl.cc index 7e12cd5..a3e6564 100644 --- a/components/gcm_driver/gcm_client_impl.cc +++ b/components/gcm_driver/gcm_client_impl.cc
@@ -435,12 +435,12 @@ iter != result->registrations.end(); ++iter) { std::string registration_id; - std::unique_ptr<RegistrationInfo> registration = + scoped_refptr<RegistrationInfo> registration = RegistrationInfo::BuildFromString(iter->first, iter->second, ®istration_id); // TODO(jianli): Add UMA to track the error case. if (registration) - registrations_[make_linked_ptr(registration.release())] = registration_id; + registrations_.emplace(std::move(registration), registration_id); } for (auto iter = result->instance_id_data.begin(); @@ -863,7 +863,7 @@ } void GCMClientImpl::Register( - const linked_ptr<RegistrationInfo>& registration_info) { + scoped_refptr<RegistrationInfo> registration_info) { DCHECK_EQ(state_, READY); // Registrations should never pass as an app_id the special category used @@ -984,7 +984,7 @@ } void GCMClientImpl::OnRegisterCompleted( - const linked_ptr<RegistrationInfo>& registration_info, + scoped_refptr<RegistrationInfo> registration_info, RegistrationRequest::Status status, const std::string& registration_id) { DCHECK(delegate_); @@ -1032,7 +1032,7 @@ } bool GCMClientImpl::ValidateRegistration( - const linked_ptr<RegistrationInfo>& registration_info, + scoped_refptr<RegistrationInfo> registration_info, const std::string& registration_id) { DCHECK_EQ(state_, READY); @@ -1066,7 +1066,7 @@ } void GCMClientImpl::Unregister( - const linked_ptr<RegistrationInfo>& registration_info) { + scoped_refptr<RegistrationInfo> registration_info) { DCHECK_EQ(state_, READY); std::unique_ptr<UnregistrationRequest::CustomRequestHandler> request_handler; @@ -1169,7 +1169,7 @@ } void GCMClientImpl::OnUnregisterCompleted( - const linked_ptr<RegistrationInfo>& registration_info, + scoped_refptr<RegistrationInfo> registration_info, UnregistrationRequest::Status status) { DVLOG(1) << "Unregister completed for app: " << registration_info->app_id << " with " << (status ? "success." : "failure.");
diff --git a/components/gcm_driver/gcm_client_impl.h b/components/gcm_driver/gcm_client_impl.h index 1bf64b8..d58742d9 100644 --- a/components/gcm_driver/gcm_client_impl.h +++ b/components/gcm_driver/gcm_client_impl.h
@@ -121,12 +121,10 @@ GCMClient::Delegate* delegate) override; void Start(StartMode start_mode) override; void Stop() override; - void Register(const linked_ptr<RegistrationInfo>& registration_info) override; - bool ValidateRegistration( - const linked_ptr<RegistrationInfo>& registration_info, - const std::string& registration_id) override; - void Unregister( - const linked_ptr<RegistrationInfo>& registration_info) override; + void Register(scoped_refptr<RegistrationInfo> registration_info) override; + bool ValidateRegistration(scoped_refptr<RegistrationInfo> registration_info, + const std::string& registration_id) override; + void Unregister(scoped_refptr<RegistrationInfo> registration_info) override; void Send(const std::string& app_id, const std::string& receiver_id, const OutgoingMessage& message) override; @@ -198,7 +196,7 @@ // instance, while values are pending registration requests to obtain a // registration ID for requesting application. using PendingRegistrationRequests = - std::map<linked_ptr<RegistrationInfo>, + std::map<scoped_refptr<RegistrationInfo>, std::unique_ptr<RegistrationRequest>, RegistrationInfoComparer>; @@ -206,7 +204,7 @@ // instance, while values are pending unregistration requests to disable the // registration ID currently assigned to the application. using PendingUnregistrationRequests = - std::map<linked_ptr<RegistrationInfo>, + std::map<scoped_refptr<RegistrationInfo>, std::unique_ptr<UnregistrationRequest>, RegistrationInfoComparer>; @@ -285,15 +283,13 @@ void ResetStoreCallback(bool success); // Completes the registration request. - void OnRegisterCompleted( - const linked_ptr<RegistrationInfo>& registration_info, - RegistrationRequest::Status status, - const std::string& registration_id); + void OnRegisterCompleted(scoped_refptr<RegistrationInfo> registration_info, + RegistrationRequest::Status status, + const std::string& registration_id); // Completes the unregistration request. - void OnUnregisterCompleted( - const linked_ptr<RegistrationInfo>& registration_info, - UnregistrationRequest::Status status); + void OnUnregisterCompleted(scoped_refptr<RegistrationInfo> registration_info, + UnregistrationRequest::Status status); // Completes the GCM store destroy request. void OnGCMStoreDestroyed(bool success);
diff --git a/components/gcm_driver/gcm_client_impl_unittest.cc b/components/gcm_driver/gcm_client_impl_unittest.cc index a4bb30b..8d0f1e8 100644 --- a/components/gcm_driver/gcm_client_impl_unittest.cc +++ b/components/gcm_driver/gcm_client_impl_unittest.cc
@@ -318,12 +318,11 @@ const std::string& registration_id); // GCMClient::Delegate overrides (for verification). - void OnRegisterFinished(const linked_ptr<RegistrationInfo>& registration_info, + void OnRegisterFinished(scoped_refptr<RegistrationInfo> registration_info, const std::string& registration_id, GCMClient::Result result) override; - void OnUnregisterFinished( - const linked_ptr<RegistrationInfo>& registration_info, - GCMClient::Result result) override; + void OnUnregisterFinished(scoped_refptr<RegistrationInfo> registration_info, + GCMClient::Result result) override; void OnSendFinished(const std::string& app_id, const std::string& message_id, GCMClient::Result result) override {} @@ -611,10 +610,10 @@ const std::string& app_id, const std::vector<std::string>& sender_ids, const std::string& registration_id) { - linked_ptr<GCMRegistrationInfo> registration(new GCMRegistrationInfo); + auto registration = base::MakeRefCounted<GCMRegistrationInfo>(); registration->app_id = app_id; registration->sender_ids = sender_ids; - gcm_client_->registrations_[registration] = registration_id; + gcm_client_->registrations_.emplace(std::move(registration), registration_id); } void GCMClientImplTest::InitializeGCMClient() { @@ -641,17 +640,16 @@ void GCMClientImplTest::Register(const std::string& app_id, const std::vector<std::string>& senders) { - std::unique_ptr<GCMRegistrationInfo> gcm_info(new GCMRegistrationInfo); + auto gcm_info = base::MakeRefCounted<GCMRegistrationInfo>(); gcm_info->app_id = app_id; gcm_info->sender_ids = senders; - gcm_client()->Register(make_linked_ptr<RegistrationInfo>(gcm_info.release())); + gcm_client()->Register(std::move(gcm_info)); } void GCMClientImplTest::Unregister(const std::string& app_id) { - std::unique_ptr<GCMRegistrationInfo> gcm_info(new GCMRegistrationInfo); + auto gcm_info = base::MakeRefCounted<GCMRegistrationInfo>(); gcm_info->app_id = app_id; - gcm_client()->Unregister( - make_linked_ptr<RegistrationInfo>(gcm_info.release())); + gcm_client()->Unregister(std::move(gcm_info)); } void GCMClientImplTest::ReceiveMessageFromMCS(const MCSMessage& message) { @@ -683,7 +681,7 @@ } void GCMClientImplTest::OnRegisterFinished( - const linked_ptr<RegistrationInfo>& registration_info, + scoped_refptr<RegistrationInfo> registration_info, const std::string& registration_id, GCMClient::Result result) { last_event_ = REGISTRATION_COMPLETED; @@ -693,7 +691,7 @@ } void GCMClientImplTest::OnUnregisterFinished( - const linked_ptr<RegistrationInfo>& registration_info, + scoped_refptr<RegistrationInfo> registration_info, GCMClient::Result result) { last_event_ = UNREGISTRATION_COMPLETED; last_app_id_ = registration_info->app_id; @@ -831,12 +829,12 @@ TEST_F(GCMClientImplTest, SerializeAndDeserialize) { std::vector<std::string> senders{"sender"}; - auto gcm_info = std::make_unique<GCMRegistrationInfo>(); + auto gcm_info = base::MakeRefCounted<GCMRegistrationInfo>(); gcm_info->app_id = kExtensionAppId; gcm_info->sender_ids = senders; gcm_info->last_validated = clock()->Now(); - auto gcm_info_deserialized = std::make_unique<GCMRegistrationInfo>(); + auto gcm_info_deserialized = base::MakeRefCounted<GCMRegistrationInfo>(); std::string gcm_registration_id_deserialized; { std::string serialized_key = gcm_info->GetSerializedKey(); @@ -852,13 +850,14 @@ EXPECT_EQ(gcm_info->last_validated, gcm_info_deserialized->last_validated); EXPECT_EQ(kRegistrationId, gcm_registration_id_deserialized); - auto instance_id_info = std::make_unique<InstanceIDTokenInfo>(); + auto instance_id_info = base::MakeRefCounted<InstanceIDTokenInfo>(); instance_id_info->app_id = kExtensionAppId; instance_id_info->last_validated = clock()->Now(); instance_id_info->authorized_entity = "different_sender"; instance_id_info->scope = "scope"; - auto instance_id_info_deserialized = std::make_unique<InstanceIDTokenInfo>(); + auto instance_id_info_deserialized = + base::MakeRefCounted<InstanceIDTokenInfo>(); std::string instance_id_registration_id_deserialized; { std::string serialized_key = instance_id_info->GetSerializedKey(); @@ -1683,25 +1682,21 @@ void GCMClientInstanceIDTest::GetToken(const std::string& app_id, const std::string& authorized_entity, const std::string& scope) { - std::unique_ptr<InstanceIDTokenInfo> instance_id_info( - new InstanceIDTokenInfo); + auto instance_id_info = base::MakeRefCounted<InstanceIDTokenInfo>(); instance_id_info->app_id = app_id; instance_id_info->authorized_entity = authorized_entity; instance_id_info->scope = scope; - gcm_client()->Register( - make_linked_ptr<RegistrationInfo>(instance_id_info.release())); + gcm_client()->Register(std::move(instance_id_info)); } void GCMClientInstanceIDTest::DeleteToken(const std::string& app_id, const std::string& authorized_entity, const std::string& scope) { - std::unique_ptr<InstanceIDTokenInfo> instance_id_info( - new InstanceIDTokenInfo); + auto instance_id_info = base::MakeRefCounted<InstanceIDTokenInfo>(); instance_id_info->app_id = app_id; instance_id_info->authorized_entity = authorized_entity; instance_id_info->scope = scope; - gcm_client()->Unregister( - make_linked_ptr<RegistrationInfo>(instance_id_info.release())); + gcm_client()->Unregister(std::move(instance_id_info)); } void GCMClientInstanceIDTest::CompleteDeleteToken() { @@ -1718,13 +1713,11 @@ bool GCMClientInstanceIDTest::ExistsToken(const std::string& app_id, const std::string& authorized_entity, const std::string& scope) const { - std::unique_ptr<InstanceIDTokenInfo> instance_id_info( - new InstanceIDTokenInfo); + auto instance_id_info = base::MakeRefCounted<InstanceIDTokenInfo>(); instance_id_info->app_id = app_id; instance_id_info->authorized_entity = authorized_entity; instance_id_info->scope = scope; - return gcm_client()->registrations_.count( - make_linked_ptr<RegistrationInfo>(instance_id_info.release())) > 0; + return gcm_client()->registrations_.count(std::move(instance_id_info)) > 0; } TEST_F(GCMClientInstanceIDTest, GetToken) {
diff --git a/components/gcm_driver/gcm_driver_desktop.cc b/components/gcm_driver/gcm_driver_desktop.cc index 4095b833..804a367d 100644 --- a/components/gcm_driver/gcm_driver_desktop.cc +++ b/components/gcm_driver/gcm_driver_desktop.cc
@@ -43,12 +43,11 @@ // Overridden from GCMClient::Delegate: // Called on IO thread. - void OnRegisterFinished(const linked_ptr<RegistrationInfo>& registration_info, + void OnRegisterFinished(scoped_refptr<RegistrationInfo> registration_info, const std::string& registration_id, GCMClient::Result result) override; - void OnUnregisterFinished( - const linked_ptr<RegistrationInfo>& registration_info, - GCMClient::Result result) override; + void OnUnregisterFinished(scoped_refptr<RegistrationInfo> registration_info, + GCMClient::Result result) override; void OnSendFinished(const std::string& app_id, const std::string& message_id, GCMClient::Result result) override; @@ -108,7 +107,7 @@ const std::string& authorized_entity, const std::string& scope, const std::map<std::string, std::string>& options); - bool ValidateRegistration(std::unique_ptr<RegistrationInfo> registration_info, + bool ValidateRegistration(scoped_refptr<RegistrationInfo> registration_info, const std::string& registration_id); void DeleteToken(const std::string& app_id, const std::string& authorized_entity, @@ -167,7 +166,7 @@ } void GCMDriverDesktop::IOWorker::OnRegisterFinished( - const linked_ptr<RegistrationInfo>& registration_info, + scoped_refptr<RegistrationInfo> registration_info, const std::string& registration_id, GCMClient::Result result) { DCHECK(io_thread_->RunsTasksInCurrentSequence()); @@ -194,7 +193,7 @@ } void GCMDriverDesktop::IOWorker::OnUnregisterFinished( - const linked_ptr<RegistrationInfo>& registration_info, + scoped_refptr<RegistrationInfo> registration_info, GCMClient::Result result) { DCHECK(io_thread_->RunsTasksInCurrentSequence()); @@ -317,28 +316,27 @@ const std::vector<std::string>& sender_ids) { DCHECK(io_thread_->RunsTasksInCurrentSequence()); - auto gcm_info = std::make_unique<GCMRegistrationInfo>(); + auto gcm_info = base::MakeRefCounted<GCMRegistrationInfo>(); gcm_info->app_id = app_id; gcm_info->sender_ids = sender_ids; - gcm_client_->Register(make_linked_ptr<RegistrationInfo>(gcm_info.release())); + gcm_client_->Register(std::move(gcm_info)); } bool GCMDriverDesktop::IOWorker::ValidateRegistration( - std::unique_ptr<RegistrationInfo> registration_info, + scoped_refptr<RegistrationInfo> registration_info, const std::string& registration_id) { DCHECK(io_thread_->RunsTasksInCurrentSequence()); - return gcm_client_->ValidateRegistration( - make_linked_ptr(registration_info.release()), registration_id); + return gcm_client_->ValidateRegistration(std::move(registration_info), + registration_id); } void GCMDriverDesktop::IOWorker::Unregister(const std::string& app_id) { DCHECK(io_thread_->RunsTasksInCurrentSequence()); - auto gcm_info = std::make_unique<GCMRegistrationInfo>(); + auto gcm_info = base::MakeRefCounted<GCMRegistrationInfo>(); gcm_info->app_id = app_id; - gcm_client_->Unregister( - make_linked_ptr<RegistrationInfo>(gcm_info.release())); + gcm_client_->Unregister(std::move(gcm_info)); } void GCMDriverDesktop::IOWorker::Send(const std::string& app_id, @@ -450,25 +448,23 @@ const std::map<std::string, std::string>& options) { DCHECK(io_thread_->RunsTasksInCurrentSequence()); - auto instance_id_token_info = std::make_unique<InstanceIDTokenInfo>(); + auto instance_id_token_info = base::MakeRefCounted<InstanceIDTokenInfo>(); instance_id_token_info->app_id = app_id; instance_id_token_info->authorized_entity = authorized_entity; instance_id_token_info->scope = scope; instance_id_token_info->options = options; - gcm_client_->Register( - make_linked_ptr<RegistrationInfo>(instance_id_token_info.release())); + gcm_client_->Register(std::move(instance_id_token_info)); } void GCMDriverDesktop::IOWorker::DeleteToken( const std::string& app_id, const std::string& authorized_entity, const std::string& scope) { - auto instance_id_token_info = std::make_unique<InstanceIDTokenInfo>(); + auto instance_id_token_info = base::MakeRefCounted<InstanceIDTokenInfo>(); instance_id_token_info->app_id = app_id; instance_id_token_info->authorized_entity = authorized_entity; instance_id_token_info->scope = scope; - gcm_client_->Unregister( - make_linked_ptr<RegistrationInfo>(instance_id_token_info.release())); + gcm_client_->Unregister(std::move(instance_id_token_info)); } void GCMDriverDesktop::IOWorker::WakeFromSuspendForHeartbeat(bool wake) { @@ -579,17 +575,16 @@ // Only validating current state, so ignore pending register_callbacks_. - auto gcm_info = std::make_unique<GCMRegistrationInfo>(); + auto gcm_info = base::MakeRefCounted<GCMRegistrationInfo>(); gcm_info->app_id = app_id; gcm_info->sender_ids = sender_ids; // Normalize the sender IDs by making them sorted. std::sort(gcm_info->sender_ids.begin(), gcm_info->sender_ids.end()); if (!delayed_task_controller_->CanRunTaskWithoutDelay()) { - delayed_task_controller_->AddTask( - base::Bind(&GCMDriverDesktop::DoValidateRegistration, - weak_ptr_factory_.GetWeakPtr(), base::Passed(&gcm_info), - registration_id, callback)); + delayed_task_controller_->AddTask(base::Bind( + &GCMDriverDesktop::DoValidateRegistration, + weak_ptr_factory_.GetWeakPtr(), gcm_info, registration_id, callback)); return; } @@ -597,14 +592,14 @@ } void GCMDriverDesktop::DoValidateRegistration( - std::unique_ptr<RegistrationInfo> registration_info, + scoped_refptr<RegistrationInfo> registration_info, const std::string& registration_id, const ValidateRegistrationCallback& callback) { base::PostTaskAndReplyWithResult( io_thread_.get(), FROM_HERE, base::Bind(&GCMDriverDesktop::IOWorker::ValidateRegistration, base::Unretained(io_worker_.get()), - base::Passed(®istration_info), registration_id), + std::move(registration_info), registration_id), callback); } @@ -948,16 +943,15 @@ // Only validating current state, so ignore pending get_token_callbacks_. - auto instance_id_info = std::make_unique<InstanceIDTokenInfo>(); + auto instance_id_info = base::MakeRefCounted<InstanceIDTokenInfo>(); instance_id_info->app_id = app_id; instance_id_info->authorized_entity = authorized_entity; instance_id_info->scope = scope; if (!delayed_task_controller_->CanRunTaskWithoutDelay()) { - delayed_task_controller_->AddTask( - base::Bind(&GCMDriverDesktop::DoValidateRegistration, - weak_ptr_factory_.GetWeakPtr(), - base::Passed(&instance_id_info), token, callback)); + delayed_task_controller_->AddTask(base::Bind( + &GCMDriverDesktop::DoValidateRegistration, + weak_ptr_factory_.GetWeakPtr(), instance_id_info, token, callback)); return; }
diff --git a/components/gcm_driver/gcm_driver_desktop.h b/components/gcm_driver/gcm_driver_desktop.h index b3e562a..8a2ca3e 100644 --- a/components/gcm_driver/gcm_driver_desktop.h +++ b/components/gcm_driver/gcm_driver_desktop.h
@@ -147,10 +147,9 @@ bool operator()(const TokenTuple& a, const TokenTuple& b) const; }; - void DoValidateRegistration( - std::unique_ptr<RegistrationInfo> registration_info, - const std::string& registration_id, - const ValidateRegistrationCallback& callback); + void DoValidateRegistration(scoped_refptr<RegistrationInfo> registration_info, + const std::string& registration_id, + const ValidateRegistrationCallback& callback); // Stops the GCM service. It can be restarted by calling EnsureStarted again. void Stop();
diff --git a/components/gcm_driver/registration_info.cc b/components/gcm_driver/registration_info.cc index f08388f..f10e769 100644 --- a/components/gcm_driver/registration_info.cc +++ b/components/gcm_driver/registration_info.cc
@@ -15,25 +15,26 @@ namespace gcm { namespace { -const char kInstanceIDSerializationPrefix[] = "iid-"; -const char kSerializedValidationTimeSeparator = '#'; -const char kSerializedKeySeparator = ','; -const int kInstanceIDSerializationPrefixLength = +constexpr char kInstanceIDSerializationPrefix[] = "iid-"; +constexpr char kSerializedValidationTimeSeparator = '#'; +constexpr char kSerializedKeySeparator = ','; +constexpr int kInstanceIDSerializationPrefixLength = sizeof(kInstanceIDSerializationPrefix) / sizeof(char) - 1; } // namespace // static -std::unique_ptr<RegistrationInfo> RegistrationInfo::BuildFromString( +scoped_refptr<RegistrationInfo> RegistrationInfo::BuildFromString( const std::string& serialized_key, const std::string& serialized_value, std::string* registration_id) { - std::unique_ptr<RegistrationInfo> registration; + scoped_refptr<RegistrationInfo> registration; if (base::StartsWith(serialized_key, kInstanceIDSerializationPrefix, - base::CompareCase::SENSITIVE)) - registration.reset(new InstanceIDTokenInfo); - else - registration.reset(new GCMRegistrationInfo); + base::CompareCase::SENSITIVE)) { + registration = base::MakeRefCounted<InstanceIDTokenInfo>(); + } else { + registration = base::MakeRefCounted<GCMRegistrationInfo>(); + } if (!registration->Deserialize(serialized_key, serialized_value, registration_id)) { @@ -42,11 +43,9 @@ return registration; } -RegistrationInfo::RegistrationInfo() { -} +RegistrationInfo::RegistrationInfo() = default; -RegistrationInfo::~RegistrationInfo() { -} +RegistrationInfo::~RegistrationInfo() = default; // static const GCMRegistrationInfo* GCMRegistrationInfo::FromRegistrationInfo( @@ -64,11 +63,9 @@ return static_cast<GCMRegistrationInfo*>(registration_info); } -GCMRegistrationInfo::GCMRegistrationInfo() { -} +GCMRegistrationInfo::GCMRegistrationInfo() = default; -GCMRegistrationInfo::~GCMRegistrationInfo() { -} +GCMRegistrationInfo::~GCMRegistrationInfo() = default; RegistrationInfo::RegistrationType GCMRegistrationInfo::GetType() const { return GCM_REGISTRATION; @@ -167,11 +164,9 @@ return static_cast<InstanceIDTokenInfo*>(registration_info); } -InstanceIDTokenInfo::InstanceIDTokenInfo() { -} +InstanceIDTokenInfo::InstanceIDTokenInfo() = default; -InstanceIDTokenInfo::~InstanceIDTokenInfo() { -} +InstanceIDTokenInfo::~InstanceIDTokenInfo() = default; RegistrationInfo::RegistrationType InstanceIDTokenInfo::GetType() const { return INSTANCE_ID_TOKEN; @@ -246,8 +241,8 @@ } bool RegistrationInfoComparer::operator()( - const linked_ptr<RegistrationInfo>& a, - const linked_ptr<RegistrationInfo>& b) const { + const scoped_refptr<RegistrationInfo>& a, + const scoped_refptr<RegistrationInfo>& b) const { DCHECK(a.get() && b.get()); // For GCMRegistrationInfo, the comparison is based on app_id only. @@ -283,11 +278,10 @@ bool ExistsGCMRegistrationInMap(const RegistrationInfoMap& map, const std::string& app_id) { - std::unique_ptr<GCMRegistrationInfo> gcm_registration( - new GCMRegistrationInfo); + scoped_refptr<RegistrationInfo> gcm_registration = + base::MakeRefCounted<GCMRegistrationInfo>(); gcm_registration->app_id = app_id; - return map.count( - make_linked_ptr<RegistrationInfo>(gcm_registration.release())) > 0; + return map.find(gcm_registration) != map.end(); } } // namespace gcm
diff --git a/components/gcm_driver/registration_info.h b/components/gcm_driver/registration_info.h index 0e029f6c..039270f 100644 --- a/components/gcm_driver/registration_info.h +++ b/components/gcm_driver/registration_info.h
@@ -10,13 +10,13 @@ #include <string> #include <vector> -#include "base/memory/linked_ptr.h" +#include "base/memory/ref_counted.h" #include "base/time/time.h" namespace gcm { // Encapsulates the information needed to register with the server. -struct RegistrationInfo { +struct RegistrationInfo : public base::RefCounted<RegistrationInfo> { enum RegistrationType { GCM_REGISTRATION, INSTANCE_ID_TOKEN @@ -25,13 +25,12 @@ // Returns the appropriate RegistrationInfo instance based on the serialized // key and value. // |registration_id| can be NULL if no interest to it. - static std::unique_ptr<RegistrationInfo> BuildFromString( + static scoped_refptr<RegistrationInfo> BuildFromString( const std::string& serialized_key, const std::string& serialized_value, std::string* registration_id); RegistrationInfo(); - virtual ~RegistrationInfo(); // Returns the type of the registration info. virtual RegistrationType GetType() const = 0; @@ -50,12 +49,15 @@ // Every registration is associated with an application. std::string app_id; base::Time last_validated; + + protected: + friend class base::RefCounted<RegistrationInfo>; + virtual ~RegistrationInfo(); }; // For GCM registration. -struct GCMRegistrationInfo : public RegistrationInfo { +struct GCMRegistrationInfo final : public RegistrationInfo { GCMRegistrationInfo(); - ~GCMRegistrationInfo() override; // Converts from the base type; static const GCMRegistrationInfo* FromRegistrationInfo( @@ -75,12 +77,14 @@ // List of IDs of the servers that are allowed to send the messages to the // application. These IDs are assigned by the Google API Console. std::vector<std::string> sender_ids; + + private: + ~GCMRegistrationInfo() override; }; // For InstanceID token retrieval. -struct InstanceIDTokenInfo : public RegistrationInfo { +struct InstanceIDTokenInfo final : public RegistrationInfo { InstanceIDTokenInfo(); - ~InstanceIDTokenInfo() override; // Converts from the base type; static const InstanceIDTokenInfo* FromRegistrationInfo( @@ -110,18 +114,20 @@ // associated with the token and may be used in processing the request. These // are not serialized/deserialized. std::map<std::string, std::string> options; + + private: + ~InstanceIDTokenInfo() override; }; struct RegistrationInfoComparer { - bool operator()(const linked_ptr<RegistrationInfo>& a, - const linked_ptr<RegistrationInfo>& b) const; + bool operator()(const scoped_refptr<RegistrationInfo>& a, + const scoped_refptr<RegistrationInfo>& b) const; }; // Collection of registration info. // Map from RegistrationInfo instance to registration ID. -typedef std::map<linked_ptr<RegistrationInfo>, - std::string, - RegistrationInfoComparer> RegistrationInfoMap; +using RegistrationInfoMap = std:: + map<scoped_refptr<RegistrationInfo>, std::string, RegistrationInfoComparer>; // Returns true if a GCM registration for |app_id| exists in |map|. bool ExistsGCMRegistrationInMap(const RegistrationInfoMap& map,
diff --git a/components/invalidation/impl/fcm_network_handler.cc b/components/invalidation/impl/fcm_network_handler.cc index 4277def..a321791 100644 --- a/components/invalidation/impl/fcm_network_handler.cc +++ b/components/invalidation/impl/fcm_network_handler.cc
@@ -115,6 +115,7 @@ // validation. DeliverToken(subscription_token); token_ = subscription_token; + UpdateGcmChannelState(/* online */ true); break; case InstanceID::INVALID_PARAMETER: case InstanceID::DISABLED: @@ -124,7 +125,7 @@ case InstanceID::NETWORK_ERROR: DLOG(WARNING) << "Messaging subscription failed; InstanceID::Result = " << result; - UpdateGcmChannelState(false); + UpdateGcmChannelState(/* online */ false); break; } ScheduleNextTokenValidation(); @@ -194,8 +195,6 @@ message, &payload, &private_topic, &public_topic, &version); UMA_HISTOGRAM_ENUMERATION("FCMInvalidations.FCMMessageStatus", status); - UpdateGcmChannelState(true); - if (status == InvalidationParsingStatus::kSuccess) DeliverIncomingMessage(payload, private_topic, public_topic, version); }
diff --git a/components/neterror/resources/offline.js b/components/neterror/resources/offline.js index a678165c..d19f0cc6 100644 --- a/components/neterror/resources/offline.js +++ b/components/neterror/resources/offline.js
@@ -712,14 +712,14 @@ this.tRex.setDuck(true); } } - } else if (this.crashed && e.type == Runner.events.TOUCHSTART && + // iOS only triggers touchstart and no pointer events. + } else if (IS_IOS && this.crashed && e.type == Runner.events.TOUCHSTART && e.currentTarget == this.containerEl) { - this.restart(); + this.handleGameOverClicks(e); } } }, - /** * Process key up. * @param {Event} e @@ -743,7 +743,7 @@ (Runner.keycodes.RESTART[keyCode] || this.isLeftClickOnCanvas(e) || (deltaTime >= this.config.GAMEOVER_CLEAR_TIME && Runner.keycodes.JUMP[keyCode]))) { - this.restart(); + this.handleGameOverClicks(e); } } else if (this.paused && isjumpKey) { // Reset the jump state @@ -753,6 +753,28 @@ }, /** + * Handle interactions on the game over screen state. + * A user is able to tap the high score twice to reset it. + * @param {Event} e + */ + handleGameOverClicks: function(e) { + e.preventDefault(); + if (this.distanceMeter.hasClickedOnHighScore(e) && this.highestScore) { + if (this.distanceMeter.isHighScoreFlashing()) { + // Subsequent click, reset the high score. + this.saveHighScore(0, true); + this.distanceMeter.resetHighScore(); + } else { + // First click, flash the high score. + this.distanceMeter.startHighScoreFlashing(); + } + } else { + this.distanceMeter.cancelHighScoreFlashing(); + this.restart(); + } + }, + + /** * Returns whether the event was a left click on canvas. * On Windows right click is registered as a click. * @param {Event} e @@ -799,6 +821,25 @@ }, /** + * Sets the current high score and saves to the profile if available. + * @param {number} distanceRan Total distance ran. + * @param {boolean} opt_resetScore Whether to reset the score. + */ + saveHighScore: function(distanceRan, opt_resetScore) { + this.highestScore = Math.ceil(distanceRan); + this.distanceMeter.setHighScore(this.highestScore); + + // Store the new high score in the profile. + if (this.syncHighestScore && window.errorPageController) { + if (opt_resetScore) { + errorPageController.resetEasterEggHighScore(); + } else { + errorPageController.updateEasterEggHighScore(this.highestScore); + } + } + }, + + /** * Game over state. */ gameOver: function() { @@ -822,13 +863,7 @@ // Update the high score. if (this.distanceRan > this.highestScore) { - this.highestScore = Math.ceil(this.distanceRan); - this.distanceMeter.setHighScore(this.highestScore); - - // Store the new high score in the profile. - if (this.syncHighestScore && window.errorPageController) { - errorPageController.updateEasterEggHighScore(this.highestScore); - } + this.saveHighScore(this.distanceRan); } // Reset the time clock. @@ -1952,6 +1987,9 @@ this.flashTimer = 0; this.flashIterations = 0; this.invertTrigger = false; + this.flashingRafId = null; + this.highScoreBounds = {}; + this.highScoreFlashing = false; this.config = DistanceMeter.config; this.maxScoreUnits = this.config.MAX_DISTANCE_UNITS; @@ -1995,7 +2033,10 @@ FLASH_DURATION: 1000 / 4, // Flash iterations for achievement animation. - FLASH_ITERATIONS: 3 + FLASH_ITERATIONS: 3, + + // Padding around the high score hit area. + HIGH_SCORE_HIT_AREA_PADDING: 4 }; @@ -2175,6 +2216,133 @@ this.highScore = ['10', '11', ''].concat(highScoreStr.split('')); }, + + /** + * Whether a clicked is in the high score area. + * @param {TouchEvent|ClickEvent} e Event object. + * @return {boolean} Whether the click was in the high score bounds. + */ + hasClickedOnHighScore: function(e) { + var x = 0; + var y = 0; + + if (e.touches) { + // Bounds for touch differ from pointer. + var canvasBounds = this.canvas.getBoundingClientRect(); + x = e.touches[0].clientX - canvasBounds.left; + y = e.touches[0].clientY - canvasBounds.top; + } else { + x = e.offsetX; + y = e.offsetY; + } + + this.highScoreBounds = this.getHighScoreBounds(); + return x >= this.highScoreBounds.x && x <= + this.highScoreBounds.x + this.highScoreBounds.width && + y >= this.highScoreBounds.y && y <= + this.highScoreBounds.y + this.highScoreBounds.height; + }, + + /** + * Get the bounding box for the high score. + * @return {Object} Object with x, y, width and height properties. + */ + getHighScoreBounds: function() { + return { + x: (this.x - (this.maxScoreUnits * 2) * + DistanceMeter.dimensions.WIDTH) - + DistanceMeter.config.HIGH_SCORE_HIT_AREA_PADDING, + y: this.y, + width: DistanceMeter.dimensions.WIDTH * (this.highScore.length + 1) + + DistanceMeter.config.HIGH_SCORE_HIT_AREA_PADDING, + height: DistanceMeter.dimensions.HEIGHT + + (DistanceMeter.config.HIGH_SCORE_HIT_AREA_PADDING * 2) + }; + }, + + /** + * Animate flashing the high score to indicate ready for resetting. + * The flashing stops following this.config.FLASH_ITERATIONS x 2 flashes. + */ + flashHighScore: function() { + var now = getTimeStamp(); + var deltaTime = now - (this.frameTimeStamp || now); + var paint = true; + this.frameTimeStamp = now; + + // Reached the max number of flashes. + if (this.flashIterations > this.config.FLASH_ITERATIONS * 2) { + this.cancelHighScoreFlashing(); + return; + } + + this.flashTimer += deltaTime; + + if (this.flashTimer < this.config.FLASH_DURATION) { + paint = false; + } else if (this.flashTimer > this.config.FLASH_DURATION * 2) { + this.flashTimer = 0; + this.flashIterations++; + } + + if (paint) { + this.drawHighScore(); + } else { + this.clearHighScoreBounds(); + } + // Frame update. + this.flashingRafId = + requestAnimationFrame(this.flashHighScore.bind(this)); + }, + + /** + * Draw empty rectangle over high score. + */ + clearHighScoreBounds: function() { + this.canvasCtx.save(); + this.canvasCtx.fillStyle = '#fff'; + this.canvasCtx.rect(this.highScoreBounds.x, this.highScoreBounds.y, + this.highScoreBounds.width, this.highScoreBounds.height); + this.canvasCtx.fill(); + this.canvasCtx.restore(); + }, + + /** + * Starts the flashing of the high score. + */ + startHighScoreFlashing() { + this.highScoreFlashing = true; + this.flashHighScore(); + }, + + /** + * Whether high score is flashing. + * @return {boolean} + */ + isHighScoreFlashing() { + return this.highScoreFlashing; + }, + + /** + * Stop flashing the high score. + */ + cancelHighScoreFlashing: function() { + cancelAnimationFrame(this.flashingRafId); + this.flashIterations = 0; + this.flashTimer = 0; + this.highScoreFlashing = false; + this.clearHighScoreBounds(); + this.drawHighScore(); + }, + + /** + * Clear the high score. + */ + resetHighScore: function() { + this.setHighScore(0); + this.cancelHighScoreFlashing(); + }, + /** * Reset the distance meter back to '00000'. */
diff --git a/components/password_manager/core/browser/form_parsing/form_parser.cc b/components/password_manager/core/browser/form_parsing/form_parser.cc index 00113b5..962e07f 100644 --- a/components/password_manager/core/browser/form_parsing/form_parser.cc +++ b/components/password_manager/core/browser/form_parsing/form_parser.cc
@@ -131,6 +131,21 @@ StringMatchesCVC(field.field->id_attribute); } +// Returns true iff |field_type| is one of password types. +bool IsPasswordPrediction(const CredentialFieldType field_type) { + switch (field_type) { + case CredentialFieldType::kUsername: + case CredentialFieldType::kNone: + return false; + case CredentialFieldType::kCurrentPassword: + case CredentialFieldType::kNewPassword: + case CredentialFieldType::kConfirmationPassword: + return true; + } + NOTREACHED(); + return false; +} + // Returns true iff |processed_field| matches the |interactability_bar|. That is // when either: // (1) |processed_field.interactability| is not less than |interactability_bar|, @@ -204,12 +219,10 @@ // Tries to parse |processed_fields| based on server |predictions|. Uses |mode| // to decide which of two username hints are relevant, if present. -std::unique_ptr<SignificantFields> ParseUsingPredictions( - std::vector<ProcessedField>* processed_fields, - const FormPredictions& predictions, - FormDataParser::Mode mode) { - auto result = std::make_unique<SignificantFields>(); - +void ParseUsingPredictions(std::vector<ProcessedField>* processed_fields, + const FormPredictions& predictions, + FormDataParser::Mode mode, + SignificantFields* result) { // Following the design from https://goo.gl/Mc2KRe, this code will attempt to // understand the special case when there are two usernames hinted by the // server. In that case, they are considered the sign-in and sign-up @@ -224,7 +237,16 @@ const FormFieldData* second_username = nullptr; for (const auto& prediction : predictions) { ProcessedField* processed_field = nullptr; - switch (DeriveFromServerFieldType(prediction.second.type)) { + + CredentialFieldType field_type = + DeriveFromServerFieldType(prediction.second.type); + bool is_password_prediction = IsPasswordPrediction(field_type); + if (mode == FormDataParser::Mode::kSaving && is_password_prediction) { + // TODO(crbug.com/913965): Consider server predictions for password fields + // in SAVING mode when the server predictions become complete. + continue; + } + switch (field_type) { case CredentialFieldType::kUsername: if (!result->username) { processed_field = @@ -250,7 +272,7 @@ FindFieldWithUniqueRendererId(processed_fields, prediction.first); if (processed_field) { if (!processed_field->is_password) - return nullptr; + continue; result->password = processed_field->field; } } @@ -271,7 +293,7 @@ FindFieldWithUniqueRendererId(processed_fields, prediction.first); if (processed_field) { if (!processed_field->is_password) - return nullptr; + continue; result->new_password = processed_field->field; } } @@ -281,7 +303,7 @@ FindFieldWithUniqueRendererId(processed_fields, prediction.first); if (processed_field) { if (!processed_field->is_password) - return nullptr; + continue; result->confirmation_password = processed_field->field; } break; @@ -322,46 +344,44 @@ processed_field->server_hints_CVC = true; } } - - return result->HasPasswords() ? std::move(result) : nullptr; } -// Tries to parse |processed_fields| based on autocomplete attributes. -// Assumption on the usage autocomplete attributes: +// Looks for autocomplete attributes in |processed_fields| and saves predictions +// to |result|. Assumption on the usage autocomplete attributes: // 1. Not more than 1 field with autocomplete=username. // 2. Not more than 1 field with autocomplete=current-password. // 3. Not more than 2 fields with autocomplete=new-password. // 4. Only password fields have "*-password" attribute and only non-password // fields have the "username" attribute. -// Are these assumptions violated, or is there no password with an autocomplete -// attribute, parsing is unsuccessful. Returns nullptr if parsing is -// unsuccessful. -std::unique_ptr<SignificantFields> ParseUsingAutocomplete( - const std::vector<ProcessedField>& processed_fields) { - auto result = std::make_unique<SignificantFields>(); +// If any assumption is violated, the autocomplete attribute is ignored. +void ParseUsingAutocomplete(const std::vector<ProcessedField>& processed_fields, + SignificantFields* result) { + bool new_password_found_by_server = result->new_password; + const FormFieldData* field_marked_as_username = nullptr; + int username_fields_found = 0; for (const ProcessedField& processed_field : processed_fields) { switch (processed_field.autocomplete_flag) { case AutocompleteFlag::kUsername: if (processed_field.is_password || result->username) - return nullptr; - result->username = processed_field.field; + continue; + + username_fields_found++; + field_marked_as_username = processed_field.field; break; case AutocompleteFlag::kCurrentPassword: if (!processed_field.is_password || result->password) - return nullptr; + continue; result->password = processed_field.field; break; case AutocompleteFlag::kNewPassword: - if (!processed_field.is_password) - return nullptr; + if (!processed_field.is_password || new_password_found_by_server) + continue; // The first field with autocomplete=new-password is considered to be // new_password and the second is confirmation_password. if (!result->new_password) result->new_password = processed_field.field; else if (!result->confirmation_password) result->confirmation_password = processed_field.field; - else - return nullptr; break; case AutocompleteFlag::kCreditCard: NOTREACHED(); @@ -370,8 +390,8 @@ break; } } - - return result->HasPasswords() ? std::move(result) : nullptr; + if (!result->username && username_fields_found == 1) + result->username = field_marked_as_username; } // This computes the "likely" condition from the design https://goo.gl/ERvoEN . @@ -889,51 +909,46 @@ if (processed_fields.empty()) return nullptr; - std::unique_ptr<SignificantFields> significant_fields; + SignificantFields significant_fields; UsernameDetectionMethod username_detection_method = UsernameDetectionMethod::kNoUsernameDetected; // (1) First, try to parse with server predictions. if (predictions_) { - significant_fields = - ParseUsingPredictions(&processed_fields, *predictions_, mode); - if (significant_fields && significant_fields->username) { + ParseUsingPredictions(&processed_fields, *predictions_, mode, + &significant_fields); + if (significant_fields.username) { username_detection_method = UsernameDetectionMethod::kServerSidePrediction; } } // (2) If that failed, try to parse with autocomplete attributes. - if (!significant_fields) { - significant_fields = ParseUsingAutocomplete(processed_fields); - if (significant_fields && significant_fields->username) { - username_detection_method = - UsernameDetectionMethod::kAutocompleteAttribute; - } + ParseUsingAutocomplete(processed_fields, &significant_fields); + if (username_detection_method == + UsernameDetectionMethod::kNoUsernameDetected && + significant_fields.username) { + username_detection_method = UsernameDetectionMethod::kAutocompleteAttribute; } // Pass the "reliability" information to mark the new-password fields as // eligible for automatic password generation. This only makes sense when // forms are analysed for filling, because no passwords are generated when the // user saves the already entered one. - if (mode == Mode::kFilling && significant_fields && - significant_fields->new_password) { - significant_fields->is_new_password_reliable = true; + if (mode == Mode::kFilling && significant_fields.new_password) { + significant_fields.is_new_password_reliable = true; } // (3) Now try to fill the gaps. - if (!significant_fields) - significant_fields = std::make_unique<SignificantFields>(); - - const bool username_found_before_heuristic = significant_fields->username; + const bool username_found_before_heuristic = significant_fields.username; // Try to parse with base heuristic. Interactability username_max = Interactability::kUnlikely; - ParseUsingBaseHeuristics(processed_fields, mode, significant_fields.get(), + ParseUsingBaseHeuristics(processed_fields, mode, &significant_fields, &username_max, &readonly_status_); if (username_detection_method == UsernameDetectionMethod::kNoUsernameDetected && - significant_fields && significant_fields->username) { + significant_fields.username) { username_detection_method = UsernameDetectionMethod::kBaseHeuristic; } @@ -949,7 +964,7 @@ if (username_field_by_context && !(mode == FormDataParser::Mode::kSaving && username_field_by_context->value.empty())) { - significant_fields->username = username_field_by_context; + significant_fields.username = username_field_by_context; if (username_detection_method == UsernameDetectionMethod::kNoUsernameDetected || username_detection_method == @@ -964,7 +979,7 @@ username_detection_method, UsernameDetectionMethod::kCount); - return AssemblePasswordForm(form_data, *significant_fields, + return AssemblePasswordForm(form_data, significant_fields, std::move(all_possible_passwords), std::move(all_possible_usernames), predictions_); }
diff --git a/components/password_manager/core/browser/form_parsing/form_parser_unittest.cc b/components/password_manager/core/browser/form_parsing/form_parser_unittest.cc index 5178fac6..ee1c49c 100644 --- a/components/password_manager/core/browser/form_parsing/form_parser_unittest.cc +++ b/components/password_manager/core/browser/form_parsing/form_parser_unittest.cc
@@ -88,6 +88,10 @@ const autofill::ValueElementVector* all_possible_usernames = nullptr; bool username_may_use_prefilled_placeholder = false; base::Optional<FormDataParser::ReadonlyPasswordFields> readonly_status; + base::Optional<FormDataParser::ReadonlyPasswordFields> + readonly_status_for_saving; + base::Optional<FormDataParser::ReadonlyPasswordFields> + readonly_status_for_filling; // If the result should be marked as only useful for fallbacks. bool fallback_only = false; SubmissionIndicatorEvent submission_event = SubmissionIndicatorEvent::NONE; @@ -373,11 +377,21 @@ EXPECT_EQ(*test_case.all_possible_usernames, parsed_form->other_possible_usernames); } - EXPECT_EQ(test_case.fallback_only, - parsed_form->only_for_fallback_saving); + if (mode == FormDataParser::Mode::kSaving) { + EXPECT_EQ(test_case.fallback_only, + parsed_form->only_for_fallback_saving); + } } if (test_case.readonly_status) { EXPECT_EQ(*test_case.readonly_status, parser.readonly_status()); + } else { + const base::Optional<FormDataParser::ReadonlyPasswordFields>* + expected_readonly_status = + mode == FormDataParser::Mode::kSaving + ? &test_case.readonly_status_for_saving + : &test_case.readonly_status_for_filling; + if (expected_readonly_status->has_value()) + EXPECT_EQ(*expected_readonly_status, parser.readonly_status()); } } } @@ -782,13 +796,15 @@ }, }, { - "Partial autocomplete analysis fails if no passwords are found", - // The attribute 'username' is ignored, because there was no password + "Partial autocomplete analysis doesn't fail if no passwords are " + "found", + // The attribute 'username' is used even if there was no password // marked up. { - {.form_control_type = "text", + {.role = ElementRole::USERNAME, + .form_control_type = "text", .autocomplete_attribute = "username"}, - {.role = ElementRole::USERNAME, .form_control_type = "text"}, + {.form_control_type = "text"}, {.role = ElementRole::CURRENT_PASSWORD, .form_control_type = "password"}, }, @@ -799,12 +815,11 @@ { {.form_control_type = "text", .autocomplete_attribute = "username"}, - {.role = ElementRole::USERNAME, - .form_control_type = "text", + {.form_control_type = "text", .autocomplete_attribute = "username"}, + {.role = ElementRole::USERNAME, .form_control_type = "text"}, + {.form_control_type = "password"}, {.role = ElementRole::CURRENT_PASSWORD, - .form_control_type = "password"}, - {.role = ElementRole::NEW_PASSWORD, .form_control_type = "password", .autocomplete_attribute = "current-password"}, }, @@ -1024,12 +1039,12 @@ }, }, { - "Username-only predictions are ignored", + "Username-only predictions are not ignored", { - {.form_control_type = "text", - .prediction = {.type = autofill::USERNAME, - .may_use_prefilled_placeholder = true}}, - {.role = ElementRole::USERNAME, .form_control_type = "text"}, + {.role = ElementRole::USERNAME, + .form_control_type = "text", + .prediction = {.type = autofill::USERNAME}}, + {.form_control_type = "text"}, {.role = ElementRole::CURRENT_PASSWORD, .form_control_type = "password"}, }, @@ -1042,8 +1057,10 @@ .prediction = {.type = autofill::USERNAME_AND_EMAIL_ADDRESS, .may_use_prefilled_placeholder = true}}, {.form_control_type = "text"}, - {.form_control_type = "password"}, - {.role = ElementRole::CURRENT_PASSWORD, + {.role_saving = ElementRole::CURRENT_PASSWORD, + .form_control_type = "password"}, + {.role_filling = ElementRole::CURRENT_PASSWORD, + .role_saving = ElementRole::NEW_PASSWORD, .prediction = {.type = autofill::PASSWORD, .may_use_prefilled_placeholder = true}, .form_control_type = "password"}, @@ -1058,14 +1075,16 @@ .prediction = {.type = autofill::USERNAME}, .form_control_type = "text"}, {.form_control_type = "text"}, - {.form_control_type = "password"}, - {.role = ElementRole::NEW_PASSWORD, + {.role_saving = ElementRole::CURRENT_PASSWORD, + .form_control_type = "password"}, + {.role_filling = ElementRole::NEW_PASSWORD, + .prediction = {.type = autofill::ACCOUNT_CREATION_PASSWORD}, .form_control_type = "password"}, - {.role = ElementRole::CONFIRMATION_PASSWORD, + {.role_filling = ElementRole::CONFIRMATION_PASSWORD, .prediction = {.type = autofill::CONFIRMATION_PASSWORD}, .form_control_type = "password"}, - {.role = ElementRole::CURRENT_PASSWORD, + {.role_filling = ElementRole::CURRENT_PASSWORD, .prediction = {.type = autofill::PASSWORD}, .form_control_type = "password"}, }, @@ -1378,10 +1397,10 @@ "heuristics", { {.role = ElementRole::USERNAME, .form_control_type = "text"}, - {.role = ElementRole::CONFIRMATION_PASSWORD, + {.role_filling = ElementRole::CONFIRMATION_PASSWORD, + .role_saving = ElementRole::CURRENT_PASSWORD, .prediction = {.type = autofill::CONFIRMATION_PASSWORD}, .form_control_type = "password"}, - {.form_control_type = "text"}, {.role = ElementRole::NEW_PASSWORD, .prediction = {.type = autofill::NEW_PASSWORD}, .form_control_type = "password"}, @@ -1389,11 +1408,13 @@ .is_new_password_reliable = true, }, { - "No password from server still means that serve hints are ignored.", + "No password from server still means. Username hint from server is " + "used.", { - {.prediction = {.type = autofill::USERNAME_AND_EMAIL_ADDRESS}, + {.role = ElementRole::USERNAME, + .prediction = {.type = autofill::USERNAME_AND_EMAIL_ADDRESS}, .form_control_type = "text"}, - {.role = ElementRole::USERNAME, .form_control_type = "text"}, + {.form_control_type = "text"}, {.role = ElementRole::CURRENT_PASSWORD, .form_control_type = "password"}, }, @@ -1457,7 +1478,7 @@ TEST(FormParserTest, ReadonlyStatus) { CheckTestData({ { - "Server hints prevent heuristics from using readonly.", + "Server predictions are ignored in saving mode", { {.role = ElementRole::USERNAME, .form_control_type = "text"}, {.role = ElementRole::CURRENT_PASSWORD, @@ -1465,8 +1486,11 @@ .is_readonly = true, .form_control_type = "password"}, }, - .readonly_status = + .readonly_status_for_filling = FormDataParser::ReadonlyPasswordFields::kNoHeuristics, + .readonly_status_for_saving = + FormDataParser::ReadonlyPasswordFields::kAllIgnored, + .fallback_only = true, }, { "Autocomplete attributes prevent heuristics from using readonly.", @@ -1493,13 +1517,15 @@ "No readonly passwords ignored.", { {.role = ElementRole::USERNAME, .form_control_type = "text"}, - {.role = ElementRole::CURRENT_PASSWORD, + {.role_filling = ElementRole::CURRENT_PASSWORD, + .role_saving = ElementRole::CURRENT_PASSWORD, // While readonly, this field is not ignored because it was // autofilled before. .is_readonly = true, .properties_mask = FieldPropertiesFlags::AUTOFILLED_ON_PAGELOAD, .form_control_type = "password"}, - {.role = ElementRole::NEW_PASSWORD, + {.role_filling = ElementRole::NEW_PASSWORD, + .role_saving = ElementRole::NEW_PASSWORD, .is_readonly = false, .form_control_type = "password"}, }, @@ -1624,7 +1650,8 @@ .prediction = {.type = autofill::USERNAME}}, {.form_control_type = "text", .prediction = {.type = autofill::USERNAME}}, - {.role = ElementRole::NEW_PASSWORD, + {.role_filling = ElementRole::NEW_PASSWORD, + .role_saving = ElementRole::CURRENT_PASSWORD, .form_control_type = "password", .prediction = {.type = autofill::ACCOUNT_CREATION_PASSWORD}}, }, @@ -1640,7 +1667,8 @@ {.role = ElementRole::CURRENT_PASSWORD, .form_control_type = "password", .prediction = {.type = autofill::PASSWORD}}, - {.form_control_type = "password", + {.role_saving = ElementRole::NEW_PASSWORD, + .form_control_type = "password", .prediction = {.type = autofill::PASSWORD}}, }, }, @@ -1660,11 +1688,10 @@ { "Two usernames in sign-in, sign-up order.", { - {.role_filling = ElementRole::USERNAME, + {.role = ElementRole::USERNAME, .form_control_type = "text", .prediction = {.type = autofill::USERNAME}}, - {.role_saving = ElementRole::USERNAME, - .form_control_type = "text", + {.form_control_type = "text", .prediction = {.type = autofill::USERNAME}}, {.role = ElementRole::CURRENT_PASSWORD, .form_control_type = "password", @@ -1684,12 +1711,13 @@ {.role_filling = ElementRole::USERNAME, .form_control_type = "text", .prediction = {.type = autofill::USERNAME}}, - {.role = ElementRole::NEW_PASSWORD, + {.role_filling = ElementRole::NEW_PASSWORD, + .role_saving = ElementRole::CURRENT_PASSWORD, .form_control_type = "password", .prediction = {.type = autofill::ACCOUNT_CREATION_PASSWORD}}, {.form_control_type = "password", .prediction = {.type = autofill::ACCOUNT_CREATION_PASSWORD}}, - {.role = ElementRole::CURRENT_PASSWORD, + {.role_filling = ElementRole::CURRENT_PASSWORD, .form_control_type = "password", .prediction = {.type = autofill::PASSWORD}}, }, @@ -1697,12 +1725,11 @@ { "Two usernames in sign-in, sign-up order; sign-in is pre-filled.", { - {.role_filling = ElementRole::USERNAME, + {.role = ElementRole::USERNAME, .form_control_type = "text", .properties_mask = FieldPropertiesFlags::AUTOFILLED_ON_PAGELOAD, .prediction = {.type = autofill::USERNAME}}, - {.role_saving = ElementRole::USERNAME, - .form_control_type = "text", + {.form_control_type = "text", .prediction = {.type = autofill::USERNAME}}, {.role = ElementRole::CURRENT_PASSWORD, .form_control_type = "password", @@ -1728,10 +1755,12 @@ {.role = ElementRole::USERNAME, .form_control_type = "text", .prediction = {.type = autofill::USERNAME}}, - {.role = ElementRole::NEW_PASSWORD, + {.role_filling = ElementRole::NEW_PASSWORD, + .role_saving = ElementRole::CURRENT_PASSWORD, .form_control_type = "password", .prediction = {.type = autofill::ACCOUNT_CREATION_PASSWORD}}, - {.form_control_type = "password", + {.role_saving = ElementRole::NEW_PASSWORD, + .form_control_type = "password", .prediction = {.type = autofill::ACCOUNT_CREATION_PASSWORD}}, }, }, @@ -1741,12 +1770,13 @@ {.role = ElementRole::USERNAME, .form_control_type = "text", .prediction = {.type = autofill::USERNAME}}, - {.role = ElementRole::NEW_PASSWORD, + {.role_filling = ElementRole::NEW_PASSWORD, + .role_saving = ElementRole::CURRENT_PASSWORD, .form_control_type = "password", .prediction = {.type = autofill::ACCOUNT_CREATION_PASSWORD}}, {.form_control_type = "password", .prediction = {.type = autofill::ACCOUNT_CREATION_PASSWORD}}, - {.role = ElementRole::CONFIRMATION_PASSWORD, + {.role_filling = ElementRole::CONFIRMATION_PASSWORD, .form_control_type = "password", .prediction = {.type = autofill::CONFIRMATION_PASSWORD}}, },
diff --git a/components/policy/core/common/cloud/cloud_policy_core.cc b/components/policy/core/common/cloud/cloud_policy_core.cc index 1a9b5aa..8d563d1 100644 --- a/components/policy/core/common/cloud/cloud_policy_core.cc +++ b/components/policy/core/common/cloud/cloud_policy_core.cc
@@ -109,6 +109,15 @@ observers_.RemoveObserver(observer); } +void CloudPolicyCore::ConnectForTesting( + std::unique_ptr<CloudPolicyService> service, + std::unique_ptr<CloudPolicyClient> client) { + service_ = std::move(service); + client_ = std::move(client); + for (auto& observer : observers_) + observer.OnCoreConnected(this); +} + void CloudPolicyCore::UpdateRefreshDelayFromPref() { if (refresh_scheduler_ && refresh_delay_) refresh_scheduler_->SetDesiredRefreshDelay(refresh_delay_->GetValue());
diff --git a/components/policy/core/common/cloud/cloud_policy_core.h b/components/policy/core/common/cloud/cloud_policy_core.h index 5511d63..470abfb 100644 --- a/components/policy/core/common/cloud/cloud_policy_core.h +++ b/components/policy/core/common/cloud/cloud_policy_core.h
@@ -119,6 +119,10 @@ // Removes the specified observer. void RemoveObserver(Observer* observer); + // Initializes the cloud connection using injected |service| and |client|. + void ConnectForTesting(std::unique_ptr<CloudPolicyService> service, + std::unique_ptr<CloudPolicyClient> client); + private: // Updates the refresh scheduler on refresh delay changes. void UpdateRefreshDelayFromPref();
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index 6c457591..a643d48 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json
@@ -709,6 +709,7 @@ 'policies': [ 'AlternativeBrowserPath', 'AlternativeBrowserParameters', + 'BrowserSwitcherExternalSitelistUrl', 'BrowserSwitcherUrlList', 'BrowserSwitcherUrlGreylist', 'BrowserSwitcherUseIeSitelist',
diff --git a/components/search_provider_logos/logo_service_impl_unittest.cc b/components/search_provider_logos/logo_service_impl_unittest.cc index c582e08..2cf40aa 100644 --- a/components/search_provider_logos/logo_service_impl_unittest.cc +++ b/components/search_provider_logos/logo_service_impl_unittest.cc
@@ -297,7 +297,9 @@ &signin_client_, &test_url_loader_factory_), #if defined(OS_CHROMEOS) - signin_manager_(&signin_client_, &account_tracker_service_), + signin_manager_(&signin_client_, + &token_service_, + &account_tracker_service_), #else signin_manager_(&signin_client_, &token_service_,
diff --git a/components/signin/core/browser/BUILD.gn b/components/signin/core/browser/BUILD.gn index 829ed86..14f968cc 100644 --- a/components/signin/core/browser/BUILD.gn +++ b/components/signin/core/browser/BUILD.gn
@@ -207,6 +207,10 @@ "child_account_info_fetcher_impl.cc", "child_account_info_fetcher_impl.h", ] + sources += [ + "oauth2_token_service_delegate_android.cc", + "oauth2_token_service_delegate_android.h", + ] deps += [ "android:jni_headers" ] } }
diff --git a/components/signin/core/browser/account_reconcilor_unittest.cc b/components/signin/core/browser/account_reconcilor_unittest.cc index 48d102c..d42fbea 100644 --- a/components/signin/core/browser/account_reconcilor_unittest.cc +++ b/components/signin/core/browser/account_reconcilor_unittest.cc
@@ -353,7 +353,7 @@ &test_signin_client_, &test_url_loader_factory_), #if defined(OS_CHROMEOS) - signin_manager_(&test_signin_client_, &account_tracker_), + signin_manager_(&test_signin_client_, &token_service_, &account_tracker_), #else signin_manager_(&test_signin_client_, &token_service_,
diff --git a/components/signin/core/browser/android/BUILD.gn b/components/signin/core/browser/android/BUILD.gn index f3cc876..71bc6dee 100644 --- a/components/signin/core/browser/android/BUILD.gn +++ b/components/signin/core/browser/android/BUILD.gn
@@ -8,6 +8,7 @@ sources = [ "java/src/org/chromium/components/signin/AccountTrackerService.java", "java/src/org/chromium/components/signin/ChildAccountInfoFetcher.java", + "java/src/org/chromium/components/signin/OAuth2TokenService.java", ] jni_package = "components/signin" } @@ -37,6 +38,7 @@ "java/src/org/chromium/components/signin/GmsAvailabilityException.java", "java/src/org/chromium/components/signin/GmsJustUpdatedException.java", "java/src/org/chromium/components/signin/util/PatternMatcher.java", + "java/src/org/chromium/components/signin/OAuth2TokenService.java", "java/src/org/chromium/components/signin/ProfileDataSource.java", "java/src/org/chromium/components/signin/SystemAccountManagerDelegate.java", ]
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/OAuth2TokenService.java b/components/signin/core/browser/android/java/src/org/chromium/components/signin/OAuth2TokenService.java similarity index 87% rename from chrome/android/java/src/org/chromium/chrome/browser/signin/OAuth2TokenService.java rename to components/signin/core/browser/android/java/src/org/chromium/components/signin/OAuth2TokenService.java index b5f1b96..0b52d30 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/OAuth2TokenService.java +++ b/components/signin/core/browser/android/java/src/org/chromium/components/signin/OAuth2TokenService.java
@@ -2,23 +2,19 @@ // 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.signin; +package org.chromium.components.signin; import android.accounts.Account; import android.content.Context; import android.support.annotation.MainThread; -import android.util.Log; import org.chromium.base.ContextUtils; +import org.chromium.base.Log; import org.chromium.base.ObserverList; import org.chromium.base.StrictModeContext; import org.chromium.base.ThreadUtils; import org.chromium.base.VisibleForTesting; import org.chromium.base.annotations.CalledByNative; -import org.chromium.chrome.browser.profiles.Profile; -import org.chromium.components.signin.AccountManagerFacade; -import org.chromium.components.signin.AccountTrackerService; -import org.chromium.components.signin.ChromeSigninController; import java.util.Arrays; import java.util.HashSet; @@ -54,31 +50,26 @@ private static final String OAUTH2_SCOPE_PREFIX = "oauth2:"; + private final long mNativeOAuth2TokenServiceDelegate; + private final AccountTrackerService mAccountTrackerService; + private final ObserverList<OAuth2TokenServiceObserver> mObservers = new ObserverList<>(); + private boolean mPendingValidation; private boolean mPendingValidationForceNotifications; - private final long mNativeOAuth2TokenServiceDelegateAndroid; - private final ObserverList<OAuth2TokenServiceObserver> mObservers = new ObserverList<>(); - private final AccountTrackerService mAccountTrackerService; - private OAuth2TokenService( - long nativeOAuth2Service, AccountTrackerService accountTrackerService) { - mNativeOAuth2TokenServiceDelegateAndroid = nativeOAuth2Service; + long nativeOAuth2TokenServiceDelegate, AccountTrackerService accountTrackerService) { + mNativeOAuth2TokenServiceDelegate = nativeOAuth2TokenServiceDelegate; mAccountTrackerService = accountTrackerService; mAccountTrackerService.addSystemAccountsSeededListener(this); } - public static OAuth2TokenService getForProfile(Profile profile) { - ThreadUtils.assertOnUiThread(); - return (OAuth2TokenService) nativeGetForProfile(profile); - } - @CalledByNative private static OAuth2TokenService create( - long nativeOAuth2Service, AccountTrackerService accountTrackerService) { + long nativeOAuth2TokenServiceDelegate, AccountTrackerService accountTrackerService) { ThreadUtils.assertOnUiThread(); - return new OAuth2TokenService(nativeOAuth2Service, accountTrackerService); + return new OAuth2TokenService(nativeOAuth2TokenServiceDelegate, accountTrackerService); } @VisibleForTesting @@ -214,8 +205,7 @@ if (semaphore.tryAcquire(timeout, unit)) { return result.get(); } else { - Log.d(TAG, "Failed to retrieve auth token within timeout (" - + timeout + " + " + unit.name() + ")"); + Log.d(TAG, "Failed to retrieve auth token within timeout (%s %s)", timeout, unit); return null; } } catch (InterruptedException e) { @@ -242,8 +232,8 @@ } /** - * Called by native to invalidate an OAuth2 token. - */ + * Called by native to invalidate an OAuth2 token. + */ @CalledByNative public static void invalidateOAuth2AuthToken(String accessToken) { if (accessToken != null) { @@ -252,9 +242,9 @@ } /** - * Continue pending accounts validation after system accounts have been seeded into - * AccountTrackerService. - */ + * Continue pending accounts validation after system accounts have been seeded into + * AccountTrackerService. + */ @Override public void onSystemAccountsSeedingComplete() { if (mPendingValidation) { @@ -265,9 +255,9 @@ } /** - * Clear pending accounts validation when system accounts in AccountTrackerService were - * refreshed. - */ + * Clear pending accounts validation when system accounts in AccountTrackerService were + * refreshed. + */ @Override public void onSystemAccountsChanged() { mPendingValidationForceNotifications = false; @@ -297,8 +287,8 @@ // change (re-signin or sign out signed-in account). currentlySignedInAccount = null; } - nativeValidateAccounts(mNativeOAuth2TokenServiceDelegateAndroid, currentlySignedInAccount, - forceNotifications); + nativeValidateAccounts( + mNativeOAuth2TokenServiceDelegate, currentlySignedInAccount, forceNotifications); } private boolean isSignedInAccountChanged(String signedInAccountName) { @@ -337,17 +327,18 @@ private static String[] getStoredAccounts() { Set<String> accounts = ContextUtils.getAppSharedPreferences().getStringSet(STORED_ACCOUNTS_KEY, null); - return accounts == null ? new String[]{} : accounts.toArray(new String[accounts.size()]); + return accounts == null ? new String[] {} : accounts.toArray(new String[0]); } @CalledByNative private static void saveStoredAccounts(String[] accounts) { Set<String> set = new HashSet<>(Arrays.asList(accounts)); - ContextUtils.getAppSharedPreferences().edit() - .putStringSet(STORED_ACCOUNTS_KEY, set).apply(); + ContextUtils.getAppSharedPreferences() + .edit() + .putStringSet(STORED_ACCOUNTS_KEY, set) + .apply(); } - private static native Object nativeGetForProfile(Profile profile); private static native void nativeOAuth2TokenFetched( String authToken, boolean isTransientError, long nativeCallback); private native void nativeValidateAccounts(long nativeOAuth2TokenServiceDelegateAndroid,
diff --git a/components/signin/core/browser/fake_signin_manager.cc b/components/signin/core/browser/fake_signin_manager.cc index 8013a5e..5a19dca 100644 --- a/components/signin/core/browser/fake_signin_manager.cc +++ b/components/signin/core/browser/fake_signin_manager.cc
@@ -14,9 +14,11 @@ FakeSigninManagerBase::FakeSigninManagerBase( SigninClient* client, + ProfileOAuth2TokenService* token_service, AccountTrackerService* account_tracker_service, SigninErrorController* signin_error_controller) : SigninManagerBase(client, + token_service, account_tracker_service, signin_error_controller) {}
diff --git a/components/signin/core/browser/fake_signin_manager.h b/components/signin/core/browser/fake_signin_manager.h index 33a2af3..1196edd 100644 --- a/components/signin/core/browser/fake_signin_manager.h +++ b/components/signin/core/browser/fake_signin_manager.h
@@ -19,6 +19,7 @@ public: FakeSigninManagerBase( SigninClient* client, + ProfileOAuth2TokenService* token_service, AccountTrackerService* account_tracker_service, SigninErrorController* signin_error_controller = nullptr); ~FakeSigninManagerBase() override;
diff --git a/components/signin/core/browser/gaia_cookie_manager_service.cc b/components/signin/core/browser/gaia_cookie_manager_service.cc index b9020bde..3f67fbd6 100644 --- a/components/signin/core/browser/gaia_cookie_manager_service.cc +++ b/components/signin/core/browser/gaia_cookie_manager_service.cc
@@ -156,8 +156,7 @@ account_ids_(other.account_ids()), source_(other.source()) {} -GaiaCookieManagerService::GaiaCookieRequest::~GaiaCookieRequest() { -} +GaiaCookieManagerService::GaiaCookieRequest::~GaiaCookieRequest() {} const std::string GaiaCookieManagerService::GaiaCookieRequest::GetAccountID() { DCHECK_EQ(request_type_, GaiaCookieRequestType::ADD_ACCOUNT); @@ -429,8 +428,7 @@ cookie_listener_binding_(this), external_cc_result_fetched_(false), list_accounts_stale_(true), - weak_ptr_factory_(this) { -} + weak_ptr_factory_(this) {} GaiaCookieManagerService::~GaiaCookieManagerService() { CancelAll(); @@ -507,8 +505,8 @@ gaia::GaiaSource source) { DCHECK(!account_id.empty()); if (!signin_client_->AreSigninCookiesAllowed()) { - SignalComplete(account_id, - GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED)); + SignalComplete(account_id, GoogleServiceAuthError( + GoogleServiceAuthError::REQUEST_CANCELED)); return; } @@ -616,8 +614,8 @@ // Remove all but the executing request. Re-add all requests being kept. if (requests_.size() > 1) { requests_.erase(requests_.begin() + 1, requests_.end()); - requests_.insert( - requests_.end(), requests_to_keep.begin(), requests_to_keep.end()); + requests_.insert(requests_.end(), requests_to_keep.begin(), + requests_to_keep.end()); } } @@ -706,7 +704,7 @@ void GaiaCookieManagerService::OnUbertokenSuccess( const std::string& uber_token) { DCHECK(requests_.front().request_type() == - GaiaCookieRequestType::ADD_ACCOUNT); + GaiaCookieRequestType::ADD_ACCOUNT); VLOG(1) << "GaiaCookieManagerService::OnUbertokenSuccess" << " account=" << requests_.front().GetAccountID(); fetcher_retries_ = 0; @@ -805,8 +803,8 @@ if (++fetcher_retries_ < signin::kMaxFetcherRetries && error.IsTransientError()) { fetcher_backoff_.InformOfRequest(false); - UMA_HISTOGRAM_ENUMERATION("OAuth2Login.MergeSessionRetry", - error.state(), GoogleServiceAuthError::NUM_STATES); + UMA_HISTOGRAM_ENUMERATION("OAuth2Login.MergeSessionRetry", error.state(), + GoogleServiceAuthError::NUM_STATES); fetcher_timer_.Start( FROM_HERE, fetcher_backoff_.GetTimeUntilRelease(), base::BindOnce( @@ -818,8 +816,8 @@ uber_token_ = std::string(); - UMA_HISTOGRAM_ENUMERATION("OAuth2Login.MergeSessionFailure", - error.state(), GoogleServiceAuthError::NUM_STATES); + UMA_HISTOGRAM_ENUMERATION("OAuth2Login.MergeSessionFailure", error.state(), + GoogleServiceAuthError::NUM_STATES); HandleNextRequest(); SignalComplete(account_id, error); } @@ -876,8 +874,8 @@ GaiaCookieRequestType::LIST_ACCOUNTS); fetcher_backoff_.InformOfRequest(true); - if (!gaia::ParseListAccountsData( - data, &listed_accounts_, &signed_out_accounts_)) { + if (!gaia::ParseListAccountsData(data, &listed_accounts_, + &signed_out_accounts_)) { listed_accounts_.clear(); signed_out_accounts_.clear(); GoogleServiceAuthError error( @@ -920,8 +918,8 @@ if (++fetcher_retries_ < signin::kMaxFetcherRetries && error.IsTransientError()) { fetcher_backoff_.InformOfRequest(false); - UMA_HISTOGRAM_ENUMERATION("Signin.ListAccountsRetry", - error.state(), GoogleServiceAuthError::NUM_STATES); + UMA_HISTOGRAM_ENUMERATION("Signin.ListAccountsRetry", error.state(), + GoogleServiceAuthError::NUM_STATES); fetcher_timer_.Start( FROM_HERE, fetcher_backoff_.GetTimeUntilRelease(), base::BindOnce( @@ -1027,8 +1025,8 @@ gaia_auth_fetcher_ = signin_client_->CreateGaiaAuthFetcher( this, requests_.front().source(), GetURLLoaderFactory()); - gaia_auth_fetcher_->StartMergeSession(uber_token_, - external_cc_result_fetcher_.GetExternalCcResult()); + gaia_auth_fetcher_->StartMergeSession( + uber_token_, external_cc_result_fetcher_.GetExternalCcResult()); } void GaiaCookieManagerService::StartGaiaLogOut() { @@ -1113,7 +1111,7 @@ GaiaCookieRequestType::LIST_ACCOUNTS) { // This and any directly subsequent list accounts would return the same. while (!requests_.empty() && requests_.front().request_type() == - GaiaCookieRequestType::LIST_ACCOUNTS) { + GaiaCookieRequestType::LIST_ACCOUNTS) { requests_.pop_front(); } } else {
diff --git a/components/signin/core/browser/gaia_cookie_manager_service.h b/components/signin/core/browser/gaia_cookie_manager_service.h index c9305f70..8ef4864e 100644 --- a/components/signin/core/browser/gaia_cookie_manager_service.h +++ b/components/signin/core/browser/gaia_cookie_manager_service.h
@@ -35,7 +35,7 @@ namespace network { class SharedURLLoaderFactory; class SimpleURLLoader; -} +} // namespace network namespace signin { // The maximum number of retries for a fetcher used in this class. @@ -286,9 +286,7 @@ } // Returns a non-NULL pointer to its instance of net::BackoffEntry - const net::BackoffEntry* GetBackoffEntry() { - return &fetcher_backoff_; - } + const net::BackoffEntry* GetBackoffEntry() { return &fetcher_backoff_; } // Can be overridden by tests. virtual scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory();
diff --git a/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc b/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc index ef8d8e1..0bd8f5f 100644 --- a/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc +++ b/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc
@@ -47,6 +47,7 @@ void(const std::vector<gaia::ListedAccount>&, const std::vector<gaia::ListedAccount>&, const GoogleServiceAuthError&)); + private: GaiaCookieManagerService* helper_; @@ -90,11 +91,9 @@ class InstrumentedGaiaCookieManagerService : public GaiaCookieManagerService { public: - InstrumentedGaiaCookieManagerService( - OAuth2TokenService* token_service, - SigninClient* signin_client) - : GaiaCookieManagerService(token_service, - signin_client) { + InstrumentedGaiaCookieManagerService(OAuth2TokenService* token_service, + SigninClient* signin_client) + : GaiaCookieManagerService(token_service, signin_client) { total++; } @@ -249,8 +248,8 @@ MockObserver observer(&helper); EXPECT_CALL(helper, StartFetchingUbertoken()); - EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc1@gmail.com", - no_error())); + EXPECT_CALL(observer, + OnAddAccountToCookieCompleted("acc1@gmail.com", no_error())); helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome); SimulateMergeSessionSuccess(&helper, "token"); @@ -262,15 +261,15 @@ base::HistogramTester histograms; EXPECT_CALL(helper, StartFetchingUbertoken()); - EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc1@gmail.com", - error())); + EXPECT_CALL(observer, + OnAddAccountToCookieCompleted("acc1@gmail.com", error())); helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome); SimulateMergeSessionFailure(&helper, error()); // Persistent error incurs no further retries. DCHECK(!helper.is_running()); histograms.ExpectUniqueSample("OAuth2Login.MergeSessionFailure", - GoogleServiceAuthError::SERVICE_ERROR, 1); + GoogleServiceAuthError::SERVICE_ERROR, 1); } TEST_F(GaiaCookieManagerServiceTest, AddAccountCookiesDisabled) { @@ -278,8 +277,8 @@ MockObserver observer(&helper); signin_client()->set_are_signin_cookies_allowed(false); - EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc1@gmail.com", - canceled())); + EXPECT_CALL(observer, + OnAddAccountToCookieCompleted("acc1@gmail.com", canceled())); helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome); } @@ -294,8 +293,8 @@ EXPECT_CALL(helper, StartFetchingUbertoken()); EXPECT_CALL(helper, StartFetchingMergeSession()); - EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc1@gmail.com", - no_error())); + EXPECT_CALL(observer, + OnAddAccountToCookieCompleted("acc1@gmail.com", no_error())); helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome); SimulateMergeSessionFailure(&helper, canceled()); @@ -316,8 +315,8 @@ EXPECT_CALL(helper, StartFetchingUbertoken()); EXPECT_CALL(helper, StartFetchingMergeSession()).Times(2); - EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc1@gmail.com", - no_error())); + EXPECT_CALL(observer, + OnAddAccountToCookieCompleted("acc1@gmail.com", no_error())); helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome); SimulateMergeSessionFailure(&helper, canceled()); @@ -329,7 +328,7 @@ SimulateMergeSessionSuccess(&helper, "token"); DCHECK(!helper.is_running()); histograms.ExpectUniqueSample("OAuth2Login.MergeSessionRetry", - GoogleServiceAuthError::REQUEST_CANCELED, 2); + GoogleServiceAuthError::REQUEST_CANCELED, 2); } TEST_F(GaiaCookieManagerServiceTest, FailedUbertoken) { @@ -337,8 +336,8 @@ MockObserver observer(&helper); EXPECT_CALL(helper, StartFetchingUbertoken()); - EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc1@gmail.com", - error())); + EXPECT_CALL(observer, + OnAddAccountToCookieCompleted("acc1@gmail.com", error())); helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome); SimulateUbertokenFailure(&helper, error()); @@ -874,10 +873,10 @@ MockObserver observer(&helper); EXPECT_CALL(helper, StartFetchingUbertoken()).Times(2); - EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc1@gmail.com", - no_error())); - EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc2@gmail.com", - no_error())); + EXPECT_CALL(observer, + OnAddAccountToCookieCompleted("acc1@gmail.com", no_error())); + EXPECT_CALL(observer, + OnAddAccountToCookieCompleted("acc2@gmail.com", no_error())); helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome); helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome); @@ -890,10 +889,10 @@ MockObserver observer(&helper); EXPECT_CALL(helper, StartFetchingUbertoken()).Times(2); - EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc1@gmail.com", - error())); - EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc2@gmail.com", - no_error())); + EXPECT_CALL(observer, + OnAddAccountToCookieCompleted("acc1@gmail.com", error())); + EXPECT_CALL(observer, + OnAddAccountToCookieCompleted("acc2@gmail.com", no_error())); helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome); helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome); @@ -906,10 +905,10 @@ MockObserver observer(&helper); EXPECT_CALL(helper, StartFetchingUbertoken()).Times(2); - EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc1@gmail.com", - error())); - EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc2@gmail.com", - no_error())); + EXPECT_CALL(observer, + OnAddAccountToCookieCompleted("acc1@gmail.com", error())); + EXPECT_CALL(observer, + OnAddAccountToCookieCompleted("acc2@gmail.com", no_error())); helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome); helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome); @@ -944,8 +943,8 @@ MockObserver observer(&helper); EXPECT_CALL(helper, StartFetchingUbertoken()); - EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc2@gmail.com", - no_error())); + EXPECT_CALL(observer, + OnAddAccountToCookieCompleted("acc2@gmail.com", no_error())); EXPECT_CALL(helper, StartFetchingLogOut()); helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome); @@ -961,8 +960,8 @@ MockObserver observer(&helper); EXPECT_CALL(helper, StartFetchingUbertoken()); - EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc2@gmail.com", - no_error())); + EXPECT_CALL(observer, + OnAddAccountToCookieCompleted("acc2@gmail.com", no_error())); EXPECT_CALL(helper, StartFetchingLogOut()); helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome); @@ -979,8 +978,8 @@ MockObserver observer(&helper); EXPECT_CALL(helper, StartFetchingUbertoken()); - EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc2@gmail.com", - no_error())); + EXPECT_CALL(observer, + OnAddAccountToCookieCompleted("acc2@gmail.com", no_error())); EXPECT_CALL(helper, StartFetchingLogOut()); helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome); @@ -995,10 +994,10 @@ MockObserver observer(&helper); EXPECT_CALL(helper, StartFetchingUbertoken()); - EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc1@gmail.com", - no_error())); - EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc2@gmail.com", - canceled())); + EXPECT_CALL(observer, + OnAddAccountToCookieCompleted("acc1@gmail.com", no_error())); + EXPECT_CALL(observer, + OnAddAccountToCookieCompleted("acc2@gmail.com", canceled())); EXPECT_CALL(helper, StartFetchingLogOut()); helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome); @@ -1015,8 +1014,8 @@ MockObserver observer(&helper); EXPECT_CALL(helper, StartFetchingUbertoken()); - EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc2@gmail.com", - no_error())); + EXPECT_CALL(observer, + OnAddAccountToCookieCompleted("acc2@gmail.com", no_error())); EXPECT_CALL(helper, StartFetchingLogOut()); helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome); @@ -1033,11 +1032,11 @@ MockObserver observer(&helper); EXPECT_CALL(helper, StartFetchingUbertoken()).Times(2); - EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc2@gmail.com", - no_error())); + EXPECT_CALL(observer, + OnAddAccountToCookieCompleted("acc2@gmail.com", no_error())); EXPECT_CALL(helper, StartFetchingLogOut()); - EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc3@gmail.com", - no_error())); + EXPECT_CALL(observer, + OnAddAccountToCookieCompleted("acc3@gmail.com", no_error())); helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome); SimulateMergeSessionSuccess(&helper, "token1"); @@ -1053,13 +1052,12 @@ InstrumentedGaiaCookieManagerService helper(token_service(), signin_client()); MockObserver observer(&helper); - EXPECT_CALL(helper, StartFetchingUbertoken()).Times(2); - EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc2@gmail.com", - no_error())); + EXPECT_CALL(observer, + OnAddAccountToCookieCompleted("acc2@gmail.com", no_error())); EXPECT_CALL(helper, StartFetchingLogOut()); - EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc3@gmail.com", - no_error())); + EXPECT_CALL(observer, + OnAddAccountToCookieCompleted("acc3@gmail.com", no_error())); helper.AddAccountToCookie("acc2@gmail.com", gaia::GaiaSource::kChrome); SimulateMergeSessionSuccess(&helper, "token1"); @@ -1079,13 +1077,13 @@ MockObserver observer(&helper); // From the first Signin. - EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc1@gmail.com", - no_error())); + EXPECT_CALL(observer, + OnAddAccountToCookieCompleted("acc1@gmail.com", no_error())); // From the sign out and then re-sign in. EXPECT_CALL(helper, StartFetchingLogOut()); - EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc3@gmail.com", - no_error())); + EXPECT_CALL(observer, + OnAddAccountToCookieCompleted("acc3@gmail.com", no_error())); // Total sign in 2 times, not enforcing ordered sequences. EXPECT_CALL(helper, StartFetchingUbertoken()).Times(2); @@ -1105,10 +1103,10 @@ MockObserver observer(&helper); EXPECT_CALL(helper, StartFetchingUbertoken()); - EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc2@gmail.com", - canceled())); - EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc1@gmail.com", - no_error())); + EXPECT_CALL(observer, + OnAddAccountToCookieCompleted("acc2@gmail.com", canceled())); + EXPECT_CALL(observer, + OnAddAccountToCookieCompleted("acc1@gmail.com", no_error())); EXPECT_CALL(helper, StartFetchingLogOut()); helper.AddAccountToCookie("acc1@gmail.com", gaia::GaiaSource::kChrome); @@ -1156,7 +1154,8 @@ ASSERT_FALSE(helper.ListAccounts(&list_accounts, &signed_out_accounts)); - SimulateListAccountsSuccess(&helper, + SimulateListAccountsSuccess( + &helper, "[\"f\", [[\"b\", 0, \"n\", \"a@b.com\", \"p\", 0, 0, 0, 0, 1, \"8\"]]]"); } @@ -1189,11 +1188,12 @@ ASSERT_FALSE(helper.ListAccounts(&list_accounts, &signed_out_accounts)); - SimulateListAccountsSuccess(&helper, + SimulateListAccountsSuccess( + &helper, "[\"f\"," "[[\"b\", 0, \"n\", \"a@b.com\", \"p\", 0, 0, 0, 0, 1, \"8\"]," " [\"b\", 0, \"n\", \"c@d.com\", \"p\", 0, 0, 0, 0, 1, \"9\"," - "null,null,null,1]]]"); + "null,null,null,1]]]"); } TEST_F(GaiaCookieManagerServiceTest, ListAccountsAcceptsNull) { @@ -1202,11 +1202,12 @@ ASSERT_FALSE(helper.ListAccounts(nullptr, nullptr)); - SimulateListAccountsSuccess(&helper, + SimulateListAccountsSuccess( + &helper, "[\"f\"," "[[\"b\", 0, \"n\", \"a@b.com\", \"p\", 0, 0, 0, 0, 1, \"8\"]," " [\"b\", 0, \"n\", \"c@d.com\", \"p\", 0, 0, 0, 0, 1, \"9\"," - "null,null,null,1]]]"); + "null,null,null,1]]]"); std::vector<gaia::ListedAccount> signed_out_accounts; ASSERT_TRUE(helper.ListAccounts(nullptr, &signed_out_accounts));
diff --git a/chrome/browser/signin/oauth2_token_service_delegate_android.cc b/components/signin/core/browser/oauth2_token_service_delegate_android.cc similarity index 93% rename from chrome/browser/signin/oauth2_token_service_delegate_android.cc rename to components/signin/core/browser/oauth2_token_service_delegate_android.cc index 9f7ae868..dcc990b 100644 --- a/chrome/browser/signin/oauth2_token_service_delegate_android.cc +++ b/components/signin/core/browser/oauth2_token_service_delegate_android.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/signin/oauth2_token_service_delegate_android.h" +#include "components/signin/core/browser/oauth2_token_service_delegate_android.h" #include "base/android/jni_android.h" #include "base/android/jni_array.h" @@ -12,8 +12,6 @@ #include "base/macros.h" #include "base/metrics/histogram_macros.h" #include "base/stl_util.h" -#include "chrome/browser/profiles/profile_android.h" -#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" #include "components/signin/core/browser/account_info.h" #include "google_apis/gaia/gaia_auth_util.h" #include "google_apis/gaia/oauth2_access_token_fetcher.h" @@ -34,9 +32,9 @@ // - the OAuth2 access token. // - the expiry time of the token (may be null, indicating that the expiry // time is unknown. -typedef base::Callback<void(const GoogleServiceAuthError&, - const std::string&, - const base::Time&)> FetchOAuth2TokenCallback; +typedef base::Callback< + void(const GoogleServiceAuthError&, const std::string&, const base::Time&)> + FetchOAuth2TokenCallback; class AndroidAccessTokenFetcher : public OAuth2AccessTokenFetcher { public: @@ -71,11 +69,9 @@ : OAuth2AccessTokenFetcher(consumer), account_id_(account_id), request_was_cancelled_(false), - weak_factory_(this) { -} + weak_factory_(this) {} -AndroidAccessTokenFetcher::~AndroidAccessTokenFetcher() { -} +AndroidAccessTokenFetcher::~AndroidAccessTokenFetcher() {} void AndroidAccessTokenFetcher::Start(const std::string& client_id, const std::string& client_secret, @@ -168,26 +164,10 @@ } } -OAuth2TokenServiceDelegateAndroid::~OAuth2TokenServiceDelegateAndroid() { -} +OAuth2TokenServiceDelegateAndroid::~OAuth2TokenServiceDelegateAndroid() {} -// static -ScopedJavaLocalRef<jobject> OAuth2TokenServiceDelegateAndroid::GetForProfile( - JNIEnv* env, - const JavaRef<jobject>& j_profile_android) { - Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile_android); - ProfileOAuth2TokenService* service = - ProfileOAuth2TokenServiceFactory::GetForProfile(profile); - OAuth2TokenServiceDelegate* delegate = service->GetDelegate(); - return ScopedJavaLocalRef<jobject>( - static_cast<OAuth2TokenServiceDelegateAndroid*>(delegate)->java_ref_); -} - -static ScopedJavaLocalRef<jobject> JNI_OAuth2TokenService_GetForProfile( - JNIEnv* env, - const JavaParamRef<jobject>& j_profile_android) { - return OAuth2TokenServiceDelegateAndroid::GetForProfile(env, - j_profile_android); +ScopedJavaLocalRef<jobject> OAuth2TokenServiceDelegateAndroid::GetJavaObject() { + return ScopedJavaLocalRef<jobject>(java_ref_); } bool OAuth2TokenServiceDelegateAndroid::RefreshTokenIsAvailable( @@ -221,8 +201,7 @@ const std::string& account_id, const GoogleServiceAuthError& error) { DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::UpdateAuthError" - << " account=" << account_id - << " error=" << error.ToString(); + << " account=" << account_id << " error=" << error.ToString(); if (error.IsTransientError()) return;
diff --git a/chrome/browser/signin/oauth2_token_service_delegate_android.h b/components/signin/core/browser/oauth2_token_service_delegate_android.h similarity index 93% rename from chrome/browser/signin/oauth2_token_service_delegate_android.h rename to components/signin/core/browser/oauth2_token_service_delegate_android.h index 02d1baf54..9ecb1dbb 100644 --- a/chrome/browser/signin/oauth2_token_service_delegate_android.h +++ b/components/signin/core/browser/oauth2_token_service_delegate_android.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_SIGNIN_OAUTH2_TOKEN_SERVICE_DELEGATE_ANDROID_H_ -#define CHROME_BROWSER_SIGNIN_OAUTH2_TOKEN_SERVICE_DELEGATE_ANDROID_H_ +#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_OAUTH2_TOKEN_SERVICE_DELEGATE_ANDROID_H_ +#define COMPONENTS_SIGNIN_CORE_BROWSER_OAUTH2_TOKEN_SERVICE_DELEGATE_ANDROID_H_ #include <map> #include <memory> @@ -36,10 +36,8 @@ // Creates a new instance of the OAuth2TokenServiceDelegateAndroid. static OAuth2TokenServiceDelegateAndroid* Create(); - // Returns a reference to the Java instance of this service. - static base::android::ScopedJavaLocalRef<jobject> GetForProfile( - JNIEnv* env, - const base::android::JavaRef<jobject>& j_profile_android); + // Returns a reference to the corresponding Java OAuth2TokenService object. + base::android::ScopedJavaLocalRef<jobject> GetJavaObject(); // Called by the TestingProfile class to disable account validation in // tests. This prevents the token service from trying to look up system
diff --git a/components/signin/core/browser/signin_manager.cc b/components/signin/core/browser/signin_manager.cc index 2863a80..0602af4 100644 --- a/components/signin/core/browser/signin_manager.cc +++ b/components/signin/core/browser/signin_manager.cc
@@ -33,11 +33,10 @@ SigninErrorController* signin_error_controller, signin::AccountConsistencyMethod account_consistency) : SigninManagerBase(client, + token_service, account_tracker_service, signin_error_controller), type_(SIGNIN_TYPE_NONE), - client_(client), - token_service_(token_service), cookie_manager_service_(cookie_manager_service), account_consistency_(account_consistency), signin_manager_signed_in_(false), @@ -126,7 +125,7 @@ possibly_invalid_email_ = source.possibly_invalid_email_; temp_refresh_token_ = source.temp_refresh_token_; password_ = source.password_; - source.client_->AfterCredentialsCopied(); + source.signin_client()->AfterCredentialsCopied(); } void SigninManager::ClearTransientSigninData() { @@ -175,7 +174,7 @@ signin_metrics::ProfileSignout signout_source_metric, signin_metrics::SignoutDelete signout_delete_metric, RemoveAccountsOption remove_option) { - client_->PreSignOut( + signin_client()->PreSignOut( base::BindOnce(&SigninManager::OnSignoutDecisionReached, base::Unretained(this), signout_source_metric, signout_delete_metric, remove_option), @@ -219,13 +218,13 @@ const std::string account_id = GetAuthenticatedAccountId(); const std::string username = account_info.email; const base::Time signin_time = - base::Time::FromInternalValue( - client_->GetPrefs()->GetInt64(prefs::kSignedInTime)); + base::Time::FromDeltaSinceWindowsEpoch(base::TimeDelta::FromMicroseconds( + signin_client()->GetPrefs()->GetInt64(prefs::kSignedInTime))); ClearAuthenticatedAccountId(); - client_->GetPrefs()->ClearPref(prefs::kGoogleServicesHostedDomain); - client_->GetPrefs()->ClearPref(prefs::kGoogleServicesAccountId); - client_->GetPrefs()->ClearPref(prefs::kGoogleServicesUserAccountId); - client_->GetPrefs()->ClearPref(prefs::kSignedInTime); + signin_client()->GetPrefs()->ClearPref(prefs::kGoogleServicesHostedDomain); + signin_client()->GetPrefs()->ClearPref(prefs::kGoogleServicesAccountId); + signin_client()->GetPrefs()->ClearPref(prefs::kGoogleServicesUserAccountId); + signin_client()->GetPrefs()->ClearPref(prefs::kSignedInTime); // Determine the duration the user was logged in and log that to UMA. if (!signin_time.is_null()) { @@ -241,13 +240,13 @@ case RemoveAccountsOption::kRemoveAllAccounts: VLOG(0) << "Revoking all refresh tokens on server. Reason: sign out, " << "IsSigninAllowed: " << IsSigninAllowed(); - token_service_->RevokeAllCredentials( + token_service()->RevokeAllCredentials( signin_metrics::SourceForRefreshTokenOperation:: kSigninManager_ClearPrimaryAccount); break; case RemoveAccountsOption::kRemoveAuthenticatedAccountIfInError: - if (token_service_->RefreshTokenHasError(account_id)) - token_service_->RevokeCredentials( + if (token_service()->RefreshTokenHasError(account_id)) + token_service()->RevokeCredentials( account_id, signin_metrics::SourceForRefreshTokenOperation:: kSigninManager_ClearPrimaryAccount); break; @@ -259,9 +258,8 @@ FireGoogleSignedOut(account_info); } -void SigninManager::Initialize(PrefService* local_state) { - SigninManagerBase::Initialize(local_state); - +void SigninManager::FinalizeInitBeforeLoadingRefreshTokens( + PrefService* local_state) { // local_state can be null during unit tests. if (local_state) { local_state_pref_registrar_.Init(local_state); @@ -270,13 +268,12 @@ base::Bind(&SigninManager::OnGoogleServicesUsernamePatternChanged, weak_pointer_factory_.GetWeakPtr())); } - signin_allowed_.Init(prefs::kSigninAllowed, - client_->GetPrefs(), + signin_allowed_.Init(prefs::kSigninAllowed, signin_client()->GetPrefs(), base::Bind(&SigninManager::OnSigninAllowedPrefChanged, base::Unretained(this))); std::string account_id = - client_->GetPrefs()->GetString(prefs::kGoogleServicesAccountId); + signin_client()->GetPrefs()->GetString(prefs::kGoogleServicesAccountId); std::string user = account_id.empty() ? std::string() : account_tracker_service()->GetAccountInfo(account_id).email; if (!account_id.empty() && (!IsAllowedUsername(user) || !IsSigninAllowed())) { @@ -305,12 +302,11 @@ // It is important to only load credentials after starting to observe the // token service. - token_service_->AddObserver(this); - token_service_->LoadCredentials(GetAuthenticatedAccountId()); + token_service()->AddObserver(this); } void SigninManager::Shutdown() { - token_service_->RemoveObserver(this); + token_service()->RemoveObserver(this); account_tracker_service()->RemoveObserver(this); local_state_pref_registrar_.RemoveAll(); SigninManagerBase::Shutdown(); @@ -391,7 +387,7 @@ if (!temp_refresh_token_.empty()) { std::string account_id = GetAuthenticatedAccountId(); - token_service_->UpdateCredentials( + token_service()->UpdateCredentials( account_id, temp_refresh_token_, signin_metrics::SourceForRefreshTokenOperation:: kSigninManager_LegacyPreDiceSigninFlow); @@ -414,8 +410,9 @@ void SigninManager::OnSignedIn() { bool reauth_in_progress = IsAuthenticated(); - client_->GetPrefs()->SetInt64(prefs::kSignedInTime, - base::Time::Now().ToInternalValue()); + signin_client()->GetPrefs()->SetInt64( + prefs::kSignedInTime, + base::Time::Now().ToDeltaSinceWindowsEpoch().InMicroseconds()); SetAuthenticatedAccountInfo(possibly_invalid_gaia_id_, possibly_invalid_email_); @@ -429,8 +426,8 @@ if (!reauth_in_progress) FireGoogleSigninSucceeded(); - signin_metrics::LogSigninProfile(client_->IsFirstRun(), - client_->GetInstallDate()); + signin_metrics::LogSigninProfile(signin_client()->IsFirstRun(), + signin_client()->GetInstallDate()); PostSignedIn(); } @@ -453,8 +450,8 @@ if (!signin_manager_signed_in_ || !user_info_fetched_by_account_tracker_) return; - client_->PostSignedIn(GetAuthenticatedAccountId(), - GetAuthenticatedAccountInfo().email, password_); + signin_client()->PostSignedIn(GetAuthenticatedAccountId(), + GetAuthenticatedAccountInfo().email, password_); password_.clear(); } @@ -472,7 +469,7 @@ } void SigninManager::OnRefreshTokensLoaded() { - token_service_->RemoveObserver(this); + token_service()->RemoveObserver(this); if (account_tracker_service()->GetMigrationState() == AccountTrackerService::MIGRATION_IN_PROGRESS) { @@ -480,12 +477,12 @@ } // Remove account information from the account tracker service if needed. - if (token_service_->HasLoadCredentialsFinishedWithNoErrors()) { + if (token_service()->HasLoadCredentialsFinishedWithNoErrors()) { std::vector<AccountInfo> accounts_in_tracker_service = account_tracker_service()->GetAccounts(); for (const auto& account : accounts_in_tracker_service) { if (GetAuthenticatedAccountId() != account.account_id && - !token_service_->RefreshTokenIsAvailable(account.account_id)) { + !token_service()->RefreshTokenIsAvailable(account.account_id)) { DVLOG(0) << "Removed account from account tracker service: " << account.account_id; account_tracker_service()->RemoveAccount(account.account_id);
diff --git a/components/signin/core/browser/signin_manager.h b/components/signin/core/browser/signin_manager.h index 83682f78..d91d8b1 100644 --- a/components/signin/core/browser/signin_manager.h +++ b/components/signin/core/browser/signin_manager.h
@@ -48,8 +48,6 @@ class GaiaCookieManagerService; class GoogleServiceAuthError; class PrefService; -class ProfileOAuth2TokenService; -class SigninClient; class SigninErrorController; namespace identity { @@ -143,7 +141,9 @@ // On platforms where SigninManager is responsible for dealing with // invalid username policy updates, we need to check this during // initialization and sign the user out. - void Initialize(PrefService* local_state) override; + void FinalizeInitBeforeLoadingRefreshTokens( + PrefService* local_state) override; + void Shutdown() override; // If applicable, merge the signed in account into the cookie jar. @@ -268,14 +268,6 @@ // token service so that it does not need to mint new ones. std::string temp_refresh_token_; - // The SigninClient object associated with this object. Must outlive this - // object. - SigninClient* client_; - - // The ProfileOAuth2TokenService instance associated with this object. Must - // outlive this object. - ProfileOAuth2TokenService* token_service_; - // Object used to use the token to push a GAIA cookie into the cookie jar. GaiaCookieManagerService* cookie_manager_service_;
diff --git a/components/signin/core/browser/signin_manager_base.cc b/components/signin/core/browser/signin_manager_base.cc index 85fb881..6dde0dd 100644 --- a/components/signin/core/browser/signin_manager_base.cc +++ b/components/signin/core/browser/signin_manager_base.cc
@@ -16,6 +16,7 @@ #include "components/prefs/pref_service.h" #include "components/signin/core/browser/account_info.h" #include "components/signin/core/browser/account_tracker_service.h" +#include "components/signin/core/browser/profile_oauth2_token_service.h" #include "components/signin/core/browser/signin_client.h" #include "components/signin/core/browser/signin_error_controller.h" #include "components/signin/core/browser/signin_pref_names.h" @@ -26,9 +27,11 @@ SigninManagerBase::SigninManagerBase( SigninClient* client, + ProfileOAuth2TokenService* token_service, AccountTrackerService* account_tracker_service, SigninErrorController* signin_error_controller) : client_(client), + token_service_(token_service), account_tracker_service_(account_tracker_service), signin_error_controller_(signin_error_controller), initialized_(false), @@ -148,8 +151,13 @@ } SetAuthenticatedAccountId(account_id); } + FinalizeInitBeforeLoadingRefreshTokens(local_state); + token_service()->LoadCredentials(GetAuthenticatedAccountId()); } +void SigninManagerBase::FinalizeInitBeforeLoadingRefreshTokens( + PrefService* local_state) {} + bool SigninManagerBase::IsInitialized() const { return initialized_; } bool SigninManagerBase::IsSigninAllowed() const {
diff --git a/components/signin/core/browser/signin_manager_base.h b/components/signin/core/browser/signin_manager_base.h index 89365f6a..6dc0895 100644 --- a/components/signin/core/browser/signin_manager_base.h +++ b/components/signin/core/browser/signin_manager_base.h
@@ -41,6 +41,7 @@ class AccountTrackerService; class PrefRegistrySimple; class PrefService; +class ProfileOAuth2TokenService; class SigninClient; class SigninErrorController; @@ -95,6 +96,7 @@ private: #endif SigninManagerBase(SigninClient* client, + ProfileOAuth2TokenService* token_service, AccountTrackerService* account_tracker_service, SigninErrorController* signin_error_controller); #if !defined(OS_CHROMEOS) @@ -110,7 +112,7 @@ static void RegisterPrefs(PrefRegistrySimple* registry); // If user was signed in, load tokens from DB if available. - virtual void Initialize(PrefService* local_state); + void Initialize(PrefService* local_state); bool IsInitialized() const; // Returns true if a signin to Chrome is allowed (by policy or pref). @@ -157,6 +159,8 @@ // Gives access to the SigninClient instance associated with this instance. SigninClient* signin_client() const { return client_; } + ProfileOAuth2TokenService* token_service() const { return token_service_; } + // Adds a callback that will be called when this instance is shut down.Not // intended for general usage, but rather for usage only by the Identity // Service implementation during the time period of conversion of Chrome to @@ -171,6 +175,10 @@ return account_tracker_service_; } + // Invoked at the end of |Initialize| before the refresh token for the primary + // account is loaded. + virtual void FinalizeInitBeforeLoadingRefreshTokens(PrefService* local_state); + // Sets the authenticated user's account id. // If the user is already authenticated with the same account id, then this // method is a no-op. @@ -200,6 +208,11 @@ friend class SigninManager; SigninClient* client_; + + // The ProfileOAuth2TokenService instance associated with this object. Must + // outlive this object. + ProfileOAuth2TokenService* token_service_; + AccountTrackerService* account_tracker_service_; SigninErrorController* signin_error_controller_; bool initialized_;
diff --git a/components/signin/core/browser/signin_tracker_unittest.cc b/components/signin/core/browser/signin_tracker_unittest.cc index 87a6d5c8..e897771 100644 --- a/components/signin/core/browser/signin_tracker_unittest.cc +++ b/components/signin/core/browser/signin_tracker_unittest.cc
@@ -56,7 +56,9 @@ &signin_client_, &test_url_loader_factory_), #if defined(OS_CHROMEOS) - fake_signin_manager_(&signin_client_, &account_tracker_) { + fake_signin_manager_(&signin_client_, + &fake_oauth2_token_service_, + &account_tracker_) { #else fake_signin_manager_(&signin_client_, &fake_oauth2_token_service_,
diff --git a/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.cc b/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.cc index 446e72c..ffcb7a93 100644 --- a/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.cc +++ b/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.cc
@@ -127,10 +127,8 @@ navigation_handle()->GetWebContents()->UnsafeFindFrameByFrameTreeNodeId( navigation_handle()->GetFrameTreeNodeId()); if (!starting_rfh) { - // This should not happen. See https://crbug.com/904248. - DEBUG_ALIAS_FOR_GURL(previous_url, navigation_handle()->GetPreviousURL()); - DEBUG_ALIAS_FOR_GURL(new_url, navigation_handle()->GetURL()); - base::debug::DumpWithoutCrashing(); + // TODO(arthursonzogni): Remove this block, this must not happen. + // See https://crbug.com/904248. observer_manager->NotifySubframeNavigationEvaluated( navigation_handle(), load_policy_, false /* is_ad_subframe */); return;
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 6881901d..4fe3c57 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
@@ -423,6 +423,9 @@ entity = CreateEntity(storage_key, *data); } else if (entity->MatchesData(*data)) { // Ignore changes that don't actually change anything. + UMA_HISTOGRAM_ENUMERATION("Sync.ModelTypeRedundantPut", + ModelTypeToHistogramInt(type_), + static_cast<int>(MODEL_TYPE_COUNT)); return; }
diff --git a/components/test/BUILD.gn b/components/test/BUILD.gn index 2855473..870351a 100644 --- a/components/test/BUILD.gn +++ b/components/test/BUILD.gn
@@ -5,6 +5,7 @@ import("//printing/buildflags/buildflags.gni") import("//services/catalog/public/tools/catalog.gni") import("//services/service_manager/public/service_manifest.gni") +import("//ui/base/ui_features.gni") source_set("test_support") { testonly = true @@ -45,6 +46,10 @@ public_deps += [ "//content/test:test_support" ] } + + if (enable_mus) { + deps += [ "//ui/aura:test_support" ] + } } # Defines a main() function that uses components_test_suite.h
diff --git a/components/test/components_test_suite.cc b/components/test/components_test_suite.cc index f017860..2d4e426 100644 --- a/components/test/components_test_suite.cc +++ b/components/test/components_test_suite.cc
@@ -14,11 +14,13 @@ #include "base/test/launcher/unit_test_launcher.h" #include "base/test/test_suite.h" #include "build/build_config.h" +#include "build/buildflag.h" #include "components/content_settings/core/common/content_settings_pattern.h" #include "mojo/core/embedder/embedder.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/ui_base_paths.h" +#include "ui/base/ui_features.h" #include "url/url_util.h" #if defined(OS_IOS) @@ -35,6 +37,10 @@ #include "base/win/scoped_com_initializer.h" #endif +#if BUILDFLAG(ENABLE_MUS) +#include "ui/aura/test/aura_test_suite_setup.h" // nogncheck +#endif + namespace { // Not using kExtensionScheme and kChromeSearchScheme to avoid the dependency @@ -152,6 +158,10 @@ testing::TestEventListeners& listeners = testing::UnitTest::GetInstance()->listeners(); listeners.Append(new ComponentsUnitTestEventListener()); +#if BUILDFLAG(ENABLE_MUS) + // Components unit tests do not use mus window service client code. + aura::AuraTestSuiteSetup::DisableMusFeatures(); +#endif #if !defined(OS_IOS) return base::BindOnce(&content::UnitTestTestSuite::Run,
diff --git a/components/variations/service/variations_service.cc b/components/variations/service/variations_service.cc index 75fc26a..6c53f8b 100644 --- a/components/variations/service/variations_service.cc +++ b/components/variations/service/variations_service.cc
@@ -86,9 +86,8 @@ const uint32_t kServerPublicKeyVersion = 1; -// TODO(mad): To be removed when we stop updating the NetworkTimeTracker. // For the HTTP date headers, the resolution of the server time is 1 second. -const int64_t kServerTimeResolutionMs = 1000; +const base::TimeDelta kServerTimeResolution = base::TimeDelta::FromSeconds(1); // Whether the VariationsService should fetch the seed for testing. bool g_should_fetch_for_testing = false; @@ -721,15 +720,15 @@ response_code = headers->response_code(); } net_error = pending_seed_request_->NetError(); - is_success = headers && (net_error == net::OK); + is_success = headers && response_body && (net_error == net::OK); } pending_seed_request_.reset(); if (last_request_was_http_retry_) { - base::UmaHistogramSparse("Variations.SeedFetchResponseOrErrorCode", + base::UmaHistogramSparse("Variations.SeedFetchResponseOrErrorCode.HTTP", is_success ? response_code : net_error); } else { - base::UmaHistogramSparse("Variations.SeedFetchResponseOrErrorCode.HTTP", + base::UmaHistogramSparse("Variations.SeedFetchResponseOrErrorCode", is_success ? response_code : net_error); } if (!is_success) { @@ -752,39 +751,46 @@ } } - const base::TimeDelta latency = - base::TimeTicks::Now() - last_request_started_time_; - - base::Time response_date; - if (response_code == net::HTTP_OK || - response_code == net::HTTP_NOT_MODIFIED) { - bool success = headers->GetDateValue(&response_date); - DCHECK(success || response_date.is_null()); - - if (!response_date.is_null()) { - client_->GetNetworkTimeTracker()->UpdateNetworkTime( - response_date, - base::TimeDelta::FromMilliseconds(kServerTimeResolutionMs), latency, - base::TimeTicks::Now()); - } - } - - if (response_code != net::HTTP_OK) { - DVLOG(1) << "Variations server request returned non-HTTP_OK response code: " - << response_code; - if (response_code == net::HTTP_NOT_MODIFIED) { - RecordSuccessfulFetch(); - - // Update the seed date value in local state (used for expiry check on - // next start up), since 304 is a successful response. Note that the - // serial number included in the request is always that of the latest - // seed, even when running in safe mode, so it's appropriate to always - // modify the latest seed's date. - field_trial_creator_.seed_store()->UpdateSeedDateAndLogDayChange( - response_date); - } + // Return if there was a failure. Note that we check both |is_success| which + // is set above and the response code. There could be a case where there's a + // HTTP_OK response code but |is_success| is false, for example if the fetch + // download was interrupted after having been started. + if (!is_success || (response_code != net::HTTP_OK && + response_code != net::HTTP_NOT_MODIFIED)) { + DVLOG(1) << "Variations server request failed: is_success=" << is_success + << " response_code=" << response_code + << " net_error=" << net_error; return; } + // At this point, |headers| and |response_body| should exist. + DCHECK(headers); + DCHECK(response_body); + + base::Time response_date; + if (headers->GetDateValue(&response_date)) { + DCHECK(!response_date.is_null()); + + const base::TimeTicks now = base::TimeTicks::Now(); + const base::TimeDelta latency = now - last_request_started_time_; + client_->GetNetworkTimeTracker()->UpdateNetworkTime( + response_date, kServerTimeResolution, latency, now); + } + + if (response_code == net::HTTP_NOT_MODIFIED) { + RecordSuccessfulFetch(); + + // Update the seed date value in local state (used for expiry check on + // next start up), since 304 is a successful response. Note that the + // serial number included in the request is always that of the latest + // seed, even when running in safe mode, so it's appropriate to always + // modify the latest seed's date. + field_trial_creator_.seed_store()->UpdateSeedDateAndLogDayChange( + response_date); + return; + } + + // We're now handling the HTTP_OK success case. + DCHECK_EQ(response_code, net::HTTP_OK); bool is_delta_compressed; bool is_gzip_compressed;
diff --git a/components/variations/service/variations_service_unittest.cc b/components/variations/service/variations_service_unittest.cc index 626f900c..57eac53 100644 --- a/components/variations/service/variations_service_unittest.cc +++ b/components/variations/service/variations_service_unittest.cc
@@ -51,6 +51,18 @@ namespace variations { namespace { +// The below seed and signature pair were generated using the server's +// private key. +const char kBase64SeedData[] = + "CigxZDI5NDY0ZmIzZDc4ZmYxNTU2ZTViNTUxYzY0NDdjYmM3NGU1ZmQwEr0BCh9VTUEtVW5p" + "Zm9ybWl0eS1UcmlhbC0xMC1QZXJjZW50GICckqUFOAFCB2RlZmF1bHRKCwoHZGVmYXVsdBAB" + "SgwKCGdyb3VwXzAxEAFKDAoIZ3JvdXBfMDIQAUoMCghncm91cF8wMxABSgwKCGdyb3VwXzA0" + "EAFKDAoIZ3JvdXBfMDUQAUoMCghncm91cF8wNhABSgwKCGdyb3VwXzA3EAFKDAoIZ3JvdXBf" + "MDgQAUoMCghncm91cF8wORAB"; +const char kBase64SeedSignature[] = + "MEQCIDD1IVxjzWYncun+9IGzqYjZvqxxujQEayJULTlbTGA/AiAr0oVmEgVUQZBYq5VLOSvy" + "96JkMYgzTkHPwbv7K/CmgA=="; + // A stub for the metrics state manager. void StubStoreClientInfo(const metrics::ClientInfo& /* client_info */) {} @@ -830,22 +842,10 @@ &prefs_, GetMetricsStateManager(), true); service.set_intercepts_fetch(false); - // The below seed and signature pair were generated using the server's - // private key. - const std::string base64_seed_data = - "CigxZDI5NDY0ZmIzZDc4ZmYxNTU2ZTViNTUxYzY0NDdjYmM3NGU1ZmQwEr0BCh9VTUEtVW5p" - "Zm9ybWl0eS1UcmlhbC0xMC1QZXJjZW50GICckqUFOAFCB2RlZmF1bHRKCwoHZGVmYXVsdBAB" - "SgwKCGdyb3VwXzAxEAFKDAoIZ3JvdXBfMDIQAUoMCghncm91cF8wMxABSgwKCGdyb3VwXzA0" - "EAFKDAoIZ3JvdXBfMDUQAUoMCghncm91cF8wNhABSgwKCGdyb3VwXzA3EAFKDAoIZ3JvdXBf" - "MDgQAUoMCghncm91cF8wORAB"; - const std::string base64_seed_signature = - "MEQCIDD1IVxjzWYncun+9IGzqYjZvqxxujQEayJULTlbTGA/AiAr0oVmEgVUQZBYq5VLOSvy" - "96JkMYgzTkHPwbv7K/CmgA=="; - std::string response; - ASSERT_TRUE(base::Base64Decode(base64_seed_data, &response)); + ASSERT_TRUE(base::Base64Decode(kBase64SeedData, &response)); const std::string seed_signature_header = - "X-Seed-Signature:" + base64_seed_signature; + std::string("X-Seed-Signature:") + kBase64SeedSignature; std::string headers("HTTP/1.1 200 OK\n\n"); network::ResourceResponseHead head; @@ -912,8 +912,14 @@ service.set_intercepts_fetch(false); service.test_url_loader_factory()->AddResponse( service.interception_url().spec(), serialized_seed); - service.DoActualFetch(); + base::HistogramTester histogram_tester; + // Note: We call DoFetchFromURL() here instead of DoActualFetch() since the + // latter doesn't pass true to |http_retry|. + service.DoFetchFromURL(service.interception_url(), true); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(service.insecurely_fetched_seed()); + histogram_tester.ExpectUniqueSample( + "Variations.SeedFetchResponseOrErrorCode.HTTP", net::HTTP_OK, 1); } TEST_F(VariationsServiceTest, InsecurelyFetchedNotSetWhenHTTPS) { @@ -926,8 +932,11 @@ service.set_intercepts_fetch(false); service.test_url_loader_factory()->AddResponse( service.interception_url().spec(), serialized_seed); + base::HistogramTester histogram_tester; service.DoActualFetch(); EXPECT_FALSE(service.insecurely_fetched_seed()); + histogram_tester.ExpectUniqueSample("Variations.SeedFetchResponseOrErrorCode", + net::HTTP_OK, 1); } TEST_F(VariationsServiceTest, RetryOverHTTPIfURLisSet) { @@ -994,6 +1003,43 @@ EXPECT_FALSE(service.seed_stored()); } +TEST_F(VariationsServiceTest, NullResponseReceivedWithHTTPOk) { + VariationsService::EnableFetchForTesting(); + + TestVariationsService service( + std::make_unique<web_resource::TestRequestAllowedNotifier>( + &prefs_, network_tracker_), + &prefs_, GetMetricsStateManager(), true); + service.set_intercepts_fetch(false); + + std::string response; + ASSERT_TRUE(base::Base64Decode(kBase64SeedData, &response)); + const std::string seed_signature_header = + std::string("X-Seed-Signature:") + kBase64SeedSignature; + + std::string headers("HTTP/1.1 200 OK\n\n"); + network::ResourceResponseHead head; + head.headers = new net::HttpResponseHeaders( + net::HttpUtil::AssembleRawHeaders(headers.c_str(), headers.size())); + EXPECT_EQ(net::HTTP_OK, head.headers->response_code()); + head.headers->AddHeader(seed_signature_header); + // Set ERR_FAILED status code despite the 200 response code. + network::URLLoaderCompletionStatus status(net::ERR_FAILED); + status.decoded_body_length = response.size(); + service.test_url_loader_factory()->AddResponse( + service.interception_url(), head, response, status, + network::TestURLLoaderFactory::Redirects(), + // We pass the flag below to preserve the 200 code with an error response. + network::TestURLLoaderFactory::kSendHeadersOnNetworkError); + EXPECT_EQ(net::HTTP_OK, head.headers->response_code()); + + base::HistogramTester histogram_tester; + service.DoActualFetch(); + EXPECT_FALSE(service.seed_stored()); + histogram_tester.ExpectUniqueSample("Variations.SeedFetchResponseOrErrorCode", + net::ERR_FAILED, 1); +} + // TODO(isherman): Add an integration test for saving and loading a safe seed, // once the loading functionality is implemented on the seed store.
diff --git a/components/viz/common/features.cc b/components/viz/common/features.cc index 0ab71966..6fd15e5 100644 --- a/components/viz/common/features.cc +++ b/components/viz/common/features.cc
@@ -26,7 +26,7 @@ // Enables running the display compositor as part of the viz service in the GPU // process. This is also referred to as out-of-process display compositor // (OOP-D). -#if defined(OS_CHROMEOS) || defined(OS_MACOSX) || defined(OS_ANDROID) +#if defined(OS_CHROMEOS) || defined(OS_ANDROID) const base::Feature kVizDisplayCompositor{"VizDisplayCompositor", base::FEATURE_DISABLED_BY_DEFAULT}; #else
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn index 266c8ff7a..3ecb373d 100644 --- a/components/viz/service/BUILD.gn +++ b/components/viz/service/BUILD.gn
@@ -367,6 +367,7 @@ "display/texture_deleter_unittest.cc", "display_embedder/buffer_queue_unittest.cc", "display_embedder/server_shared_bitmap_manager_unittest.cc", + "display_embedder/skia_output_surface_impl_unittest.cc", "frame_sinks/compositor_frame_sink_support_unittest.cc", "frame_sinks/direct_layer_tree_frame_sink_unittest.cc", "frame_sinks/frame_sink_manager_unittest.cc",
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_unittest.cc b/components/viz/service/display_embedder/skia_output_surface_impl_unittest.cc new file mode 100644 index 0000000..6f073b3c5 --- /dev/null +++ b/components/viz/service/display_embedder/skia_output_surface_impl_unittest.cc
@@ -0,0 +1,224 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/viz/service/display_embedder/skia_output_surface_impl.h" + +#include "base/base64.h" +#include "base/test/scoped_feature_list.h" +#include "cc/test/fake_output_surface_client.h" +#include "cc/test/pixel_test_utils.h" +#include "components/viz/common/frame_sinks/copy_output_request.h" +#include "components/viz/common/frame_sinks/copy_output_result.h" +#include "components/viz/service/display_embedder/skia_output_surface_impl.h" +#include "components/viz/service/gl/gpu_service_impl.h" +#include "gpu/command_buffer/service/scheduler.h" +#include "gpu/ipc/gpu_in_process_thread_service.h" +#include "gpu/ipc/service/gpu_watchdog_thread.h" +#include "mojo/public/cpp/bindings/strong_binding.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/gl/init/gl_factory.h" + +namespace viz { + +static void ExpectEquals(SkBitmap actual, SkBitmap expected) { + EXPECT_EQ(actual.dimensions(), expected.dimensions()); + auto expected_url = cc::GetPNGDataUrl(expected); + auto actual_url = cc::GetPNGDataUrl(actual); + EXPECT_TRUE(actual_url == expected_url); +} + +class SkiaOutputSurfaceImplTest : public testing::Test { + public: + void CheckSyncTokenOnGpuThread(const gpu::SyncToken& sync_token); + void CopyRequestCallbackOnGpuThread(const SkColor output_color, + const gfx::Rect& output_rect, + const gfx::ColorSpace& color_space, + std::unique_ptr<CopyOutputResult> result); + + protected: + SkiaOutputSurfaceImplTest() + : output_surface_client_(std::make_unique<cc::FakeOutputSurfaceClient>()), + wait_(base::WaitableEvent::ResetPolicy::AUTOMATIC, + base::WaitableEvent::InitialState::NOT_SIGNALED) {} + inline void SetUp() override { SetUpSkiaOutputSurfaceImpl(); } + void TearDown() override; + void BlockMainThread(); + void UnblockMainThread(); + + std::unique_ptr<base::Thread> gpu_thread_; + std::unique_ptr<SkiaOutputSurfaceImpl> output_surface_; + std::unique_ptr<GpuServiceImpl> gpu_service_; + + private: + void SetUpSkiaOutputSurfaceImpl(); + void TearDownGpuServiceOnGpuThread(); + void SetUpGpuServiceOnGpuThread(); + + std::unique_ptr<base::Thread> io_thread_; + scoped_refptr<gpu::CommandBufferTaskExecutor> task_executor_; + std::unique_ptr<cc::FakeOutputSurfaceClient> output_surface_client_; + std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list_; + base::WaitableEvent wait_; +}; + +void SkiaOutputSurfaceImplTest::BlockMainThread() { + wait_.Wait(); +} + +void SkiaOutputSurfaceImplTest::UnblockMainThread() { + DCHECK(!wait_.IsSignaled()); + wait_.Signal(); +} + +void SkiaOutputSurfaceImplTest::SetUpGpuServiceOnGpuThread() { + ASSERT_TRUE(gpu_thread_->task_runner()->BelongsToCurrentThread()); + gpu_service_ = std::make_unique<GpuServiceImpl>( + gpu::GPUInfo(), nullptr /* watchdog_thread */, io_thread_->task_runner(), + gpu::GpuFeatureInfo(), gpu::GpuPreferences(), + gpu::GPUInfo() /* gpu_info_for_hardware_gpu */, + gpu::GpuFeatureInfo() /* gpu_feature_info_for_hardware_gpu */, + nullptr /* vulkan_implementation */, + base::DoNothing() /* exit_callback */); + + // Uses a null gpu_host here, because we don't want to receive any message. + std::unique_ptr<mojom::GpuHost> gpu_host; + mojom::GpuHostPtr gpu_host_proxy; + mojo::MakeStrongBinding(std::move(gpu_host), + mojo::MakeRequest(&gpu_host_proxy)); + gpu_service_->InitializeWithHost( + std::move(gpu_host_proxy), gpu::GpuProcessActivityFlags(), + gl::init::CreateOffscreenGLSurface(gfx::Size()), + nullptr /* sync_point_manager */, nullptr /* shutdown_event */); + task_executor_ = base::MakeRefCounted<gpu::GpuInProcessThreadService>( + gpu_thread_->task_runner(), gpu_service_->scheduler(), + gpu_service_->sync_point_manager(), gpu_service_->mailbox_manager(), + gpu_service_->share_group(), + gpu_service_->gpu_channel_manager() + ->default_offscreen_surface() + ->GetFormat(), + gpu_service_->gpu_feature_info(), + gpu_service_->gpu_channel_manager()->gpu_preferences()); + UnblockMainThread(); +} + +void SkiaOutputSurfaceImplTest::TearDownGpuServiceOnGpuThread() { + task_executor_ = nullptr; + gpu_service_ = nullptr; + UnblockMainThread(); +} + +void SkiaOutputSurfaceImplTest::TearDown() { + output_surface_ = nullptr; + + if (task_executor_) { + // Tear down the GPU service. + gpu_thread_->task_runner()->PostTask( + FROM_HERE, + base::BindOnce( + &SkiaOutputSurfaceImplTest::TearDownGpuServiceOnGpuThread, + base::Unretained(this))); + BlockMainThread(); + } + io_thread_ = nullptr; + gpu_thread_ = nullptr; + scoped_feature_list_ = nullptr; +} + +void SkiaOutputSurfaceImplTest::SetUpSkiaOutputSurfaceImpl() { + // SkiaOutputSurfaceImplOnGpu requires UseSkiaRenderer. + const char enable_features[] = "UseSkiaRenderer"; + const char disable_features[] = ""; + scoped_feature_list_ = std::make_unique<base::test::ScopedFeatureList>(); + scoped_feature_list_->InitFromCommandLine(enable_features, disable_features); + + // Set up the GPU service. + gpu_thread_ = std::make_unique<base::Thread>("GPUMainThread"); + ASSERT_TRUE(gpu_thread_->Start()); + io_thread_ = std::make_unique<base::Thread>("GPUIOThread"); + ASSERT_TRUE(io_thread_->Start()); + + gpu_thread_->task_runner()->PostTask( + FROM_HERE, + base::BindOnce(&SkiaOutputSurfaceImplTest::SetUpGpuServiceOnGpuThread, + base::Unretained(this))); + BlockMainThread(); + + // Set up the SkiaOutputSurfaceImpl. + output_surface_ = std::make_unique<SkiaOutputSurfaceImpl>( + gpu_service_.get(), gpu::kNullSurfaceHandle, + nullptr /* synthetic_begin_frame_source */, + false /*show_overdraw_feedback*/); + output_surface_->BindToClient(output_surface_client_.get()); +} + +void SkiaOutputSurfaceImplTest::CheckSyncTokenOnGpuThread( + const gpu::SyncToken& sync_token) { + EXPECT_TRUE( + gpu_service_->sync_point_manager()->IsSyncTokenReleased(sync_token)); + UnblockMainThread(); +} + +void SkiaOutputSurfaceImplTest::CopyRequestCallbackOnGpuThread( + const SkColor output_color, + const gfx::Rect& output_rect, + const gfx::ColorSpace& color_space, + std::unique_ptr<CopyOutputResult> result) { + std::unique_ptr<SkBitmap> result_bitmap; + result_bitmap = std::make_unique<SkBitmap>(result->AsSkBitmap()); + EXPECT_EQ(result_bitmap->width(), output_rect.width()); + EXPECT_EQ(result_bitmap->height(), output_rect.height()); + + std::vector<SkPMColor> expected_pixels( + output_rect.width() * output_rect.height(), + SkPreMultiplyColor(output_color)); + SkBitmap expected; + expected.installPixels( + SkImageInfo::MakeN32Premul(output_rect.width(), output_rect.height(), + color_space.ToSkColorSpace()), + expected_pixels.data(), output_rect.width() * sizeof(SkColor)); + ExpectEquals(*result_bitmap.get(), expected); + + UnblockMainThread(); +} + +TEST_F(SkiaOutputSurfaceImplTest, SubmitPaint) { + output_surface_->Reshape(gfx::Size(100.0, 100.0), 1, gfx::ColorSpace(), true, + false); + SkCanvas* root_canvas = output_surface_->BeginPaintCurrentFrame(); + SkPaint paint; + const SkColor output_color = SK_ColorRED; + const gfx::Rect output_rect(0, 0, 10, 10); + paint.setColor(output_color); + SkRect rect = SkRect::MakeWH(output_rect.width(), output_rect.height()); + root_canvas->drawRect(rect, paint); + + gpu::SyncToken sync_token = output_surface_->SubmitPaint(); + EXPECT_TRUE(sync_token.HasData()); + base::OnceClosure closure = + base::BindOnce(&SkiaOutputSurfaceImplTest::CheckSyncTokenOnGpuThread, + base::Unretained(this), sync_token); + + std::vector<gpu::SyncToken> resource_sync_tokens; + resource_sync_tokens.push_back(sync_token); + auto sequence_id = gpu_service_->skia_output_surface_sequence_id(); + gpu_service_->scheduler()->ScheduleTask(gpu::Scheduler::Task( + sequence_id, std::move(closure), std::move(resource_sync_tokens))); + BlockMainThread(); + + // Copy the output + const gfx::ColorSpace color_space = gfx::ColorSpace::CreateSRGB(); + auto request = std::make_unique<CopyOutputRequest>( + CopyOutputRequest::ResultFormat::RGBA_BITMAP, + base::BindOnce(&SkiaOutputSurfaceImplTest::CopyRequestCallbackOnGpuThread, + base::Unretained(this), output_color, output_rect, + color_space)); + request->set_result_task_runner(gpu_thread_->task_runner()); + gfx::Rect result_rect = output_rect; + output_surface_->CopyOutput(0, output_rect, color_space, result_rect, + std::move(request)); + BlockMainThread(); +} + +} // namespace viz
diff --git a/content/browser/accessibility/accessibility_tree_formatter_win.cc b/content/browser/accessibility/accessibility_tree_formatter_win.cc index 91706b9..abf05c8 100644 --- a/content/browser/accessibility/accessibility_tree_formatter_win.cc +++ b/content/browser/accessibility/accessibility_tree_formatter_win.cc
@@ -441,10 +441,7 @@ // If S_FALSE it means there is no name if (S_OK == node->get_accName(variant_self, temp_bstr.Receive())) { base::string16 name = base::string16(temp_bstr, temp_bstr.Length()); - - // Ignore a JAWS workaround where the name of a document is " ". - if (name != L" " || ia_role != ROLE_SYSTEM_DOCUMENT) - dict->SetString("name", name); + dict->SetString("name", name); } temp_bstr.Reset();
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index a43a30d..154b8398 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc
@@ -1019,17 +1019,6 @@ base::BindOnce( base::IgnoreResult(&base::ThreadRestrictions::SetIOAllowed), true)); - // Also allow waiting to join threads. - // TODO(https://crbug.com/800808): Ideally this (and the above SetIOAllowed() - // would be scoped allowances). That would be one of the first step to ensure - // no persistent work is being done after TaskScheduler::Shutdown() in order - // to move towards atomic shutdown. - base::ThreadRestrictions::SetWaitAllowed(true); - base::PostTaskWithTraits( - FROM_HERE, {BrowserThread::IO}, - base::BindOnce( - base::IgnoreResult(&base::ThreadRestrictions::SetWaitAllowed), true)); - #if defined(OS_ANDROID) g_browser_main_loop_shutting_down = true; #endif @@ -1107,13 +1096,16 @@ save_file_manager_->Shutdown(); { - TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:IOThread"); - ResetThread_IO(std::move(io_thread_)); - } + base::ScopedAllowBaseSyncPrimitives allow_wait_for_join; + { + TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:IOThread"); + ResetThread_IO(std::move(io_thread_)); + } - { - TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:TaskScheduler"); - base::TaskScheduler::GetInstance()->Shutdown(); + { + TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:TaskScheduler"); + base::TaskScheduler::GetInstance()->Shutdown(); + } } // Must happen after the IO thread is shutdown since this may be accessed from
diff --git a/content/browser/devtools/devtools_http_handler.cc b/content/browser/devtools/devtools_http_handler.cc index 2fab142..42134d8b 100644 --- a/content/browser/devtools/devtools_http_handler.cc +++ b/content/browser/devtools/devtools_http_handler.cc
@@ -223,8 +223,7 @@ thread->task_runner()->DeleteSoon(FROM_HERE, std::move(socket_factory)); if (thread) { base::PostTaskWithTraits( - FROM_HERE, - {base::WithBaseSyncPrimitives(), base::TaskPriority::BEST_EFFORT}, + FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT}, BindOnce([](std::unique_ptr<base::Thread>) {}, std::move(thread))); } }
diff --git a/content/browser/media/media_internals_unittest.cc b/content/browser/media/media_internals_unittest.cc index 0fa3497..75d0550 100644 --- a/content/browser/media/media_internals_unittest.cc +++ b/content/browser/media/media_internals_unittest.cc
@@ -498,7 +498,11 @@ // Abandon audio focus. RemoveAllPlayersForTest(media_session1); - WaitForCallbackCount(1); + + // TODO(https://crbug.com/916177): This should wait on a more precise + // condition than RunLoop idling, but it's not clear exactly what that should + // be. + base::RunLoop().RunUntilIdle(); // Check JSON is what we expect. {
diff --git a/content/browser/media/session/audio_focus_delegate_default.cc b/content/browser/media/session/audio_focus_delegate_default.cc index 9962a55..9d0c464 100644 --- a/content/browser/media/session/audio_focus_delegate_default.cc +++ b/content/browser/media/session/audio_focus_delegate_default.cc
@@ -6,6 +6,7 @@ #include "base/no_destructor.h" #include "base/unguessable_token.h" +#include "build/build_config.h" #include "content/browser/media/session/media_session_impl.h" #include "content/public/browser/browser_thread.h" #include "content/public/common/service_manager_connection.h" @@ -22,10 +23,20 @@ const char kAudioFocusSourceName[] = "web"; -static const base::UnguessableToken& GetBrowserGroupId() { +base::UnguessableToken GetAudioFocusGroupId(MediaSessionImpl* session) { + // Allow the media session to override the group id. + if (session->audio_focus_group_id() != base::UnguessableToken::Null()) + return session->audio_focus_group_id(); + + // If we are on Chrome OS, then use a shared audio focus group id for the + // whole browser. This will mean that tabs will share audio focus. +#if defined(OS_CHROMEOS) static const base::NoDestructor<base::UnguessableToken> token( base::UnguessableToken::Create()); return *token; +#else + return base::UnguessableToken::Create(); +#endif } // AudioFocusDelegateDefault is the default implementation of @@ -102,9 +113,7 @@ audio_focus_ptr_->RequestGroupedAudioFocus( mojo::MakeRequest(&request_client_ptr_), std::move(media_session), session_info_.Clone(), audio_focus_type, - media_session_->audio_focus_group_id() == base::UnguessableToken::Null() - ? GetBrowserGroupId() - : media_session_->audio_focus_group_id(), + GetAudioFocusGroupId(media_session_), base::BindOnce(&AudioFocusDelegateDefault::FinishAudioFocusRequest, base::Unretained(this), audio_focus_type)); }
diff --git a/content/browser/media/session/audio_focus_delegate_default_browsertest.cc b/content/browser/media/session/audio_focus_delegate_default_browsertest.cc index 45cdfc24..619b865 100644 --- a/content/browser/media/session/audio_focus_delegate_default_browsertest.cc +++ b/content/browser/media/session/audio_focus_delegate_default_browsertest.cc
@@ -4,6 +4,7 @@ #include "base/command_line.h" #include "base/unguessable_token.h" +#include "build/build_config.h" #include "content/browser/media/session/media_session_impl.h" #include "content/browser/media/session/mock_media_session_player_observer.h" #include "content/public/common/service_manager_connection.h" @@ -25,6 +26,14 @@ const char kExpectedSourceName[] = "web"; +bool IsBrowserAudioFocusGroupingEnabled() { +#if defined(OS_CHROMEOS) + return true; +#else + return false; +#endif +} + } // namespace class AudioFocusDelegateDefaultBrowserTest : public ContentBrowserTest { @@ -106,7 +115,7 @@ media_session::test::MockMediaSessionMojoObserver observer( *media_session); observer.WaitForState( - use_separate_group_id + use_separate_group_id || !IsBrowserAudioFocusGroupingEnabled() ? media_session::mojom::MediaSessionInfo::SessionState::kSuspended : media_session::mojom::MediaSessionInfo::SessionState::kActive); }
diff --git a/content/browser/media/session/media_session_impl_browsertest.cc b/content/browser/media/session/media_session_impl_browsertest.cc index 6923f9c..894ea08 100644 --- a/content/browser/media/session/media_session_impl_browsertest.cc +++ b/content/browser/media/session/media_session_impl_browsertest.cc
@@ -1768,7 +1768,7 @@ media_session::test::MockMediaSessionMojoObserver observer(*media_session_); StartNewPlayer(player_observer.get(), media::MediaContentType::Persistent); ResolveAudioFocusSuccess(); - EXPECT_EQ(metadata, *observer.WaitForMetadata()); + EXPECT_EQ(metadata, observer.WaitForNonEmptyMetadata()); } }
diff --git a/content/browser/media/session/media_session_impl_service_routing_unittest.cc b/content/browser/media/session/media_session_impl_service_routing_unittest.cc index e5aaeb4..d033481 100644 --- a/content/browser/media/session/media_session_impl_service_routing_unittest.cc +++ b/content/browser/media/session/media_session_impl_service_routing_unittest.cc
@@ -565,7 +565,7 @@ media_session::test::MockMediaSessionMojoObserver observer( *GetMediaSession()); services_[main_frame_]->SetMetadata(expected_metadata); - EXPECT_EQ(expected_metadata, *observer.WaitForMetadata()); + EXPECT_EQ(expected_metadata, observer.WaitForNonEmptyMetadata()); } }
diff --git a/content/browser/renderer_host/input/passthrough_touch_event_queue.cc b/content/browser/renderer_host/input/passthrough_touch_event_queue.cc index 9fa8b4df..1e48ae4 100644 --- a/content/browser/renderer_host/input/passthrough_touch_event_queue.cc +++ b/content/browser/renderer_host/input/passthrough_touch_event_queue.cc
@@ -83,15 +83,17 @@ const TouchEventWithLatencyInfo& event) { TRACE_EVENT0("input", "PassthroughTouchEventQueue::QueueEvent"); PreFilterResult filter_result = FilterBeforeForwarding(event.event); - if (filter_result != FORWARD_TO_RENDERER) { + bool should_forward_touch_event = + filter_result == PreFilterResult::kUnfiltered; + UMA_HISTOGRAM_ENUMERATION("Event.Touch.FilteredAtPassthroughQueue", + filter_result); + + if (!should_forward_touch_event) { client_->OnFilteringTouchEvent(event.event); - InputEventAckState ack_state = - filter_result == ACK_WITH_NO_CONSUMER_EXISTS - ? INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS - : INPUT_EVENT_ACK_STATE_NOT_CONSUMED; TouchEventWithLatencyInfoAndAckState event_with_ack_state = event; - event_with_ack_state.set_ack_info(InputEventAckSource::BROWSER, ack_state); + event_with_ack_state.set_ack_info(InputEventAckSource::BROWSER, + INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS); outstanding_touches_.insert(event_with_ack_state); AckCompletedEvents(); return; @@ -293,7 +295,7 @@ PassthroughTouchEventQueue::PreFilterResult PassthroughTouchEventQueue::FilterBeforeForwarding(const WebTouchEvent& event) { if (event.GetType() == WebInputEvent::kTouchScrollStarted) - return FORWARD_TO_RENDERER; + return PreFilterResult::kUnfiltered; if (WebTouchEventTraits::IsTouchSequenceStart(event)) { // We don't know if we have a handler until we get the ACK back so @@ -305,59 +307,61 @@ drop_remaining_touches_in_sequence_ = false; if (!has_handlers_) { drop_remaining_touches_in_sequence_ = true; - return ACK_WITH_NO_CONSUMER_EXISTS; + return PreFilterResult::kFilteredNoPageHandlers; } } if (timeout_handler_ && timeout_handler_->FilterEvent(event)) - return ACK_WITH_NO_CONSUMER_EXISTS; + return PreFilterResult::kFilteredTimeout; if (drop_remaining_touches_in_sequence_ && - event.GetType() != WebInputEvent::kTouchCancel) { - return ACK_WITH_NO_CONSUMER_EXISTS; - } + event.GetType() != WebInputEvent::kTouchCancel) + return PreFilterResult::kFilteredNoPageHandlers; if (event.GetType() == WebInputEvent::kTouchStart) { return (has_handlers_ || maybe_has_handler_for_current_sequence_) - ? FORWARD_TO_RENDERER - : ACK_WITH_NO_CONSUMER_EXISTS; + ? PreFilterResult::kUnfiltered + : PreFilterResult::kFilteredNoPageHandlers; } - if (maybe_has_handler_for_current_sequence_) { - // Only forward a touch if it has a non-stationary pointer that is active - // in the current touch sequence. - for (size_t i = 0; i < event.touches_length; ++i) { - const WebTouchPoint& point = event.touches[i]; - if (point.state == WebTouchPoint::kStateStationary) + // If none of the touch points active in the current sequence have handlers, + // don't forward the touch event. + if (!maybe_has_handler_for_current_sequence_) + return PreFilterResult::kFilteredNoHandlerForSequence; + + // Only forward a touch if it has a non-stationary pointer that is active + // in the current touch sequence. + for (size_t i = 0; i < event.touches_length; ++i) { + const WebTouchPoint& point = event.touches[i]; + if (point.state == WebTouchPoint::kStateStationary) + continue; + + // |last_sent_touchevent_| will be non-null as long as there is an + // active touch sequence being forwarded to the renderer. + if (!last_sent_touchevent_) + continue; + + for (size_t j = 0; j < last_sent_touchevent_->touches_length; ++j) { + if (point.id != last_sent_touchevent_->touches[j].id) continue; - // |last_sent_touchevent_| will be non-null as long as there is an - // active touch sequence being forwarded to the renderer. - if (!last_sent_touchevent_) - continue; + if (event.GetType() != WebInputEvent::kTouchMove) + return PreFilterResult::kUnfiltered; - for (size_t j = 0; j < last_sent_touchevent_->touches_length; ++j) { - if (point.id != last_sent_touchevent_->touches[j].id) - continue; + // All pointers in TouchMove events may have state as StateMoved, + // even though none of the pointers have not changed in real. + // Forward these events when at least one pointer has changed. + if (HasPointChanged(last_sent_touchevent_->touches[j], point)) + return PreFilterResult::kUnfiltered; - if (event.GetType() != WebInputEvent::kTouchMove) - return FORWARD_TO_RENDERER; - - // All pointers in TouchMove events may have state as StateMoved, - // even though none of the pointers have not changed in real. - // Forward these events when at least one pointer has changed. - if (HasPointChanged(last_sent_touchevent_->touches[j], point)) - return FORWARD_TO_RENDERER; - - // This is a TouchMove event for which we have yet to find a - // non-stationary pointer. Continue checking the next pointers - // in the |event|. - break; - } + // This is a TouchMove event for which we have yet to find a + // non-stationary pointer. Continue checking the next pointers + // in the |event|. + break; } } - return ACK_WITH_NO_CONSUMER_EXISTS; + return PreFilterResult::kFilteredNoNonstationaryPointers; } void PassthroughTouchEventQueue::UpdateTouchConsumerStates(
diff --git a/content/browser/renderer_host/input/passthrough_touch_event_queue.h b/content/browser/renderer_host/input/passthrough_touch_event_queue.h index 04088dd..7280e7b0 100644 --- a/content/browser/renderer_host/input/passthrough_touch_event_queue.h +++ b/content/browser/renderer_host/input/passthrough_touch_event_queue.h
@@ -7,6 +7,7 @@ #include <set> +#include "base/gtest_prod_util.h" #include "base/macros.h" #include "base/time/time.h" #include "content/browser/renderer_host/event_with_latency_info.h" @@ -112,6 +113,27 @@ private: friend class PassthroughTouchEventQueueTest; + FRIEND_TEST_ALL_PREFIXES(PassthroughTouchEventQueueTest, + TouchScrollStartedUnfiltered); + FRIEND_TEST_ALL_PREFIXES(PassthroughTouchEventQueueTest, + TouchStartWithoutPageHandlersFiltered); + FRIEND_TEST_ALL_PREFIXES(PassthroughTouchEventQueueTest, + TouchStartWithPageHandlersUnfiltered); + FRIEND_TEST_ALL_PREFIXES(PassthroughTouchEventQueueTest, + TouchMoveFilteredAfterTimeout); + FRIEND_TEST_ALL_PREFIXES(PassthroughTouchEventQueueTest, + TouchMoveWithoutPageHandlersFiltered); + FRIEND_TEST_ALL_PREFIXES(PassthroughTouchEventQueueTest, + StationaryTouchMoveFiltered); + FRIEND_TEST_ALL_PREFIXES(PassthroughTouchEventQueueTest, + StationaryTouchMoveWithActualTouchMoveUnfiltered); + FRIEND_TEST_ALL_PREFIXES(PassthroughTouchEventQueueTest, + NonTouchMoveUnfiltered); + FRIEND_TEST_ALL_PREFIXES(PassthroughTouchEventQueueTest, + TouchMoveWithNonTouchMoveUnfiltered); + FRIEND_TEST_ALL_PREFIXES(PassthroughTouchEventQueueTest, + TouchMoveWithoutSequenceHandlerFiltered); + friend class TouchTimeoutHandler; class TouchEventWithLatencyInfoAndAckState @@ -131,11 +153,19 @@ InputEventAckState ack_state_; }; - enum PreFilterResult { - ACK_WITH_NO_CONSUMER_EXISTS, - ACK_WITH_NOT_CONSUMED, - FORWARD_TO_RENDERER, + // These values are logged to UMA. Entries should not be renumbered and + // numeric values should never be reused. Please keep in sync with + // "EventPreFilterResult" in src/tools/metrics/histograms/enums.xml. + enum class PreFilterResult { + kUnfiltered = 0, + kFilteredNoPageHandlers = 1, + kFilteredTimeout = 2, + kFilteredNoNonstationaryPointers = 3, + kFilteredNoHandlerForSequence = 4, + kMaxValue = kFilteredNoHandlerForSequence, + }; + // Filter touches prior to forwarding to the renderer, e.g., if the renderer // has no touch handler. PreFilterResult FilterBeforeForwarding(const blink::WebTouchEvent& event);
diff --git a/content/browser/renderer_host/input/passthrough_touch_event_queue_unittest.cc b/content/browser/renderer_host/input/passthrough_touch_event_queue_unittest.cc index 2c869a0..5ef9bd59 100644 --- a/content/browser/renderer_host/input/passthrough_touch_event_queue_unittest.cc +++ b/content/browser/renderer_host/input/passthrough_touch_event_queue_unittest.cc
@@ -315,6 +315,11 @@ run_loop.Run(); } + PassthroughTouchEventQueue::PreFilterResult FilterBeforeForwarding( + const blink::WebTouchEvent& event) { + return queue_->FilterBeforeForwarding(event); + } + int GetUniqueTouchEventID() { return sent_events_ids_.back(); } private: @@ -1775,4 +1780,146 @@ EXPECT_FALSE(sent_event().touch_start_or_first_touch_move); } +TEST_F(PassthroughTouchEventQueueTest, TouchScrollStartedUnfiltered) { + SyntheticWebTouchEvent event; + event.SetType(WebInputEvent::kTouchScrollStarted); + EXPECT_EQ(PassthroughTouchEventQueue::PreFilterResult::kUnfiltered, + FilterBeforeForwarding(event)); +} + +TEST_F(PassthroughTouchEventQueueTest, TouchStartWithoutPageHandlersFiltered) { + OnHasTouchEventHandlers(false); + SyntheticWebTouchEvent event; + event.PressPoint(1, 1); + + EXPECT_EQ( + PassthroughTouchEventQueue::PreFilterResult::kFilteredNoPageHandlers, + FilterBeforeForwarding(event)); +} + +TEST_F(PassthroughTouchEventQueueTest, TouchStartWithPageHandlersUnfiltered) { + OnHasTouchEventHandlers(true); + SyntheticWebTouchEvent event; + event.PressPoint(1, 1); + + EXPECT_EQ(PassthroughTouchEventQueue::PreFilterResult::kUnfiltered, + FilterBeforeForwarding(event)); +} + +TEST_F(PassthroughTouchEventQueueTest, TouchMoveFilteredAfterTimeout) { + SetUpForTimeoutTesting(); + OnHasTouchEventHandlers(true); + PressTouchPoint(1, 1); + + // Allow the initial touch start event to time out. + RunTasksAndWait(DefaultTouchTimeoutDelay() * 2); + + // Any subsequent touch move events are filtered. + SyntheticWebTouchEvent event; + int id = event.PressPoint(1, 1); + event.MovePoint(id, 2, 2); + + EXPECT_EQ(PassthroughTouchEventQueue::PreFilterResult::kFilteredTimeout, + FilterBeforeForwarding(event)); +} + +TEST_F(PassthroughTouchEventQueueTest, TouchMoveWithoutPageHandlersFiltered) { + OnHasTouchEventHandlers(false); + // Start the touch sequence. + PressTouchPoint(1, 1); + + SyntheticWebTouchEvent event; + int id = event.PressPoint(1, 1); + event.ReleasePoint(id); + + EXPECT_EQ( + PassthroughTouchEventQueue::PreFilterResult::kFilteredNoPageHandlers, + FilterBeforeForwarding(event)); +} + +TEST_F(PassthroughTouchEventQueueTest, StationaryTouchMoveFiltered) { + OnHasTouchEventHandlers(true); + // Start the touch sequence. + PressTouchPoint(1, 1); + + // Touch move events with stationary pointers are filtered. + SyntheticWebTouchEvent event; + int id = event.PressPoint(1, 1); + event.MovePoint(id, 1, 1); + + EXPECT_EQ(PassthroughTouchEventQueue::PreFilterResult:: + kFilteredNoNonstationaryPointers, + FilterBeforeForwarding(event)); +} + +TEST_F(PassthroughTouchEventQueueTest, + StationaryTouchMoveWithActualTouchMoveUnfiltered) { + OnHasTouchEventHandlers(true); + // Start the touch sequence. + PressTouchPoint(1, 1); + PressTouchPoint(2, 2); + + // Touch move events with non stationary pointers are unfiltered, even if + // there's another touch with a stationary pointer. + SyntheticWebTouchEvent event; + int id1 = event.PressPoint(1, 1); + event.MovePoint(id1, 1, 1); + int id2 = event.PressPoint(2, 2); + event.MovePoint(id2, 3, 3); + + EXPECT_EQ(PassthroughTouchEventQueue::PreFilterResult::kUnfiltered, + FilterBeforeForwarding(event)); +} + +TEST_F(PassthroughTouchEventQueueTest, NonTouchMoveUnfiltered) { + OnHasTouchEventHandlers(true); + // Start the touch sequence. + PressTouchPoint(1, 1); + + // Non-touchmove events are never filtered. + SyntheticWebTouchEvent event; + int id = event.PressPoint(1, 1); + event.ReleasePoint(id); + + EXPECT_EQ(PassthroughTouchEventQueue::PreFilterResult::kUnfiltered, + FilterBeforeForwarding(event)); +} + +TEST_F(PassthroughTouchEventQueueTest, TouchMoveWithNonTouchMoveUnfiltered) { + OnHasTouchEventHandlers(true); + // Start the touch sequence. + PressTouchPoint(1, 1); + PressTouchPoint(1, 1); + + // Non-touchmove events are never filtered, even if they're paired with a + // touchmove event that would otherwise be filtered. + SyntheticWebTouchEvent event; + int id1 = event.PressPoint(1, 1); + event.MovePoint(id1, 1, 1); + int id2 = event.PressPoint(2, 2); + event.ReleasePoint(id2); + + EXPECT_EQ(PassthroughTouchEventQueue::PreFilterResult::kUnfiltered, + FilterBeforeForwarding(event)); +} + +TEST_F(PassthroughTouchEventQueueTest, + TouchMoveWithoutSequenceHandlerFiltered) { + OnHasTouchEventHandlers(true); + // Start the touch sequence. + PressTouchPoint(1, 1); + + // Send an ack indicating that there's no handler for the current sequence. + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS); + + // Any subsequent touches in the sequence should be filtered. + SyntheticWebTouchEvent event; + int id = event.PressPoint(1, 1); + event.MovePoint(id, 3, 3); + + EXPECT_EQ(PassthroughTouchEventQueue::PreFilterResult:: + kFilteredNoHandlerForSequence, + FilterBeforeForwarding(event)); +} + } // namespace content
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index 9832053..275faba 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -731,6 +731,8 @@ OnIntrinsicSizingInfoChanged) IPC_MESSAGE_HANDLER(WidgetHostMsg_AnimateDoubleTapZoomInMainFrame, OnAnimateDoubleTapZoomInMainFrame) + IPC_MESSAGE_HANDLER(WidgetHostMsg_ZoomToFindInPageRectInMainFrame, + OnZoomToFindInPageRectInMainFrame) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() @@ -3176,6 +3178,30 @@ return std::move(hosts); } +namespace { + +bool TransformPointAndRectToRootView(RenderWidgetHostViewBase* view, + RenderWidgetHostViewBase* root_view, + gfx::Point* transformed_point, + gfx::Rect* transformed_rect) { + gfx::Transform transform_to_main_frame; + if (!view->GetTransformToViewCoordSpace(root_view, &transform_to_main_frame)) + return false; + + if (transformed_point) + transform_to_main_frame.TransformPoint(transformed_point); + + if (transformed_rect) { + gfx::RectF transformed_rect_f(*transformed_rect); + transform_to_main_frame.TransformRect(&transformed_rect_f); + *transformed_rect = gfx::ToEnclosingRect(transformed_rect_f); + } + + return true; +} + +} // namespace + void RenderWidgetHostImpl::OnAnimateDoubleTapZoomInMainFrame( const gfx::Point& point, const gfx::Rect& rect_to_zoom) { @@ -3183,20 +3209,34 @@ return; auto* root_view = view_->GetRootView(); - gfx::Transform transform_to_main_frame; - if (!view_->GetTransformToViewCoordSpace(root_view, &transform_to_main_frame)) - return; gfx::Point transformed_point(point); - transform_to_main_frame.TransformPoint(&transformed_point); - gfx::RectF transformed_rect(rect_to_zoom); - transform_to_main_frame.TransformRect(&transformed_rect); - - // Transform the point & rect into the root-view's coordinates. - gfx::Rect transformed_rect_to_zoom = gfx::ToEnclosingRect(transformed_rect); + gfx::Rect transformed_rect_to_zoom(rect_to_zoom); + if (!TransformPointAndRectToRootView(view_.get(), root_view, + &transformed_point, + &transformed_rect_to_zoom)) { + return; + } auto* root_rvhi = RenderViewHostImpl::From(root_view->GetRenderWidgetHost()); root_rvhi->Send(new ViewMsg_AnimateDoubleTapZoom( root_rvhi->GetRoutingID(), transformed_point, transformed_rect_to_zoom)); } +void RenderWidgetHostImpl::OnZoomToFindInPageRectInMainFrame( + const gfx::Rect& rect_to_zoom) { + if (!view_) + return; + + auto* root_view = view_->GetRootView(); + gfx::Rect transformed_rect_to_zoom(rect_to_zoom); + if (!TransformPointAndRectToRootView(view_.get(), root_view, nullptr, + &transformed_rect_to_zoom)) { + return; + } + + auto* root_rvhi = RenderViewHostImpl::From(root_view->GetRenderWidgetHost()); + root_rvhi->Send(new ViewMsg_ZoomToFindInPageRect(root_rvhi->GetRoutingID(), + transformed_rect_to_zoom)); +} + } // namespace content
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h index 69f3b6a..4557cf72 100644 --- a/content/browser/renderer_host/render_widget_host_impl.h +++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -787,6 +787,8 @@ ConflictingAllocationsResolve); FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest, ResizeAndCrossProcessPostMessagePreserveOrder); + FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostInputEventRouterTest, + EnsureRendererDestroyedHandlesUnAckedTouchEvents); friend class MockRenderWidgetHost; friend class OverscrollNavigationOverlayTest; friend class RenderViewHostTester; @@ -849,6 +851,7 @@ void OnIntrinsicSizingInfoChanged(blink::WebIntrinsicSizingInfo info); void OnAnimateDoubleTapZoomInMainFrame(const gfx::Point& point, const gfx::Rect& rect_to_zoom); + void OnZoomToFindInPageRectInMainFrame(const gfx::Rect& rect_to_zoom); // Called when visual properties have changed in the renderer. void DidUpdateVisualProperties(const cc::RenderFrameMetadata& metadata);
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router.cc b/content/browser/renderer_host/render_widget_host_input_event_router.cc index ce574da..5c3f08a 100644 --- a/content/browser/renderer_host/render_widget_host_input_event_router.cc +++ b/content/browser/renderer_host/render_widget_host_input_event_router.cc
@@ -129,6 +129,8 @@ void UpdateQueueAfterTargetDestroyed(RenderWidgetHostViewBase* target_view); + size_t length_for_testing() { return ack_queue_.size(); } + private: void ProcessAckedTouchEvents(); void ReportTouchEventAckQueueUmaStats(); @@ -230,7 +232,7 @@ ack_queue_.end()); // Otherwise, mark its status accordingly. - for_each(ack_queue_.begin(), ack_queue_.end(), [target_view](AckData data) { + for_each(ack_queue_.begin(), ack_queue_.end(), [target_view](AckData& data) { if (data.target_view == target_view) { data.touch_event_ack_status = TouchEventAckStatus::TouchEventAcked; data.ack_result = INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS; @@ -240,6 +242,11 @@ ProcessAckedTouchEvents(); } +size_t RenderWidgetHostInputEventRouter::TouchEventAckQueueLengthForTesting() + const { + return touch_event_ack_queue_->length_for_testing(); +} + void RenderWidgetHostInputEventRouter::OnRenderWidgetHostViewBaseDestroyed( RenderWidgetHostViewBase* view) { // RenderWidgetHostViewBase::RemoveObserver() should only ever be called
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router.h b/content/browser/renderer_host/render_widget_host_input_event_router.h index 78eb7a7..89bb6ba 100644 --- a/content/browser/renderer_host/render_widget_host_input_event_router.h +++ b/content/browser/renderer_host/render_widget_host_input_event_router.h
@@ -162,6 +162,8 @@ void ShowContextMenuAtPoint(const gfx::Point& point, const ui::MenuSourceType source_type) override; + size_t TouchEventAckQueueLengthForTesting() const; + private: FRIEND_TEST_ALL_PREFIXES(BrowserSideFlingBrowserTest, InertialGSUBubblingStopsWhenParentCannotScroll);
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc b/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc index 5da50575..290bc19 100644 --- a/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc
@@ -395,6 +395,48 @@ view_root_->last_gesture_seen()); } +TEST_F(RenderWidgetHostInputEventRouterTest, + EnsureRendererDestroyedHandlesUnAckedTouchEvents) { + // Tell the child that it has event handlers, to prevent the touch event + // queue in the renderer host from acking the touch events immediately. + widget_host2_->OnHasTouchEventHandlers(true); + + // Make sure we route touch events to child. This will cause the RWH's + // InputRouter to IPC the event into the ether, from which it will never + // return, which is perfect for this test. + view_root_->SetHittestResult(view_other_.get(), false); + + // Send a TouchStart/End sequence. + blink::WebTouchEvent touch_start_event( + blink::WebInputEvent::kTouchStart, blink::WebInputEvent::kNoModifiers, + blink::WebInputEvent::GetStaticTimeStampForTests()); + touch_start_event.touches_length = 1; + touch_start_event.touches[0].state = blink::WebTouchPoint::kStatePressed; + touch_start_event.unique_touch_event_id = 1; + + rwhier_.RouteTouchEvent(view_root_.get(), &touch_start_event, + ui::LatencyInfo(ui::SourceEventType::TOUCH)); + + blink::WebTouchEvent touch_end_event( + blink::WebInputEvent::kTouchEnd, blink::WebInputEvent::kNoModifiers, + blink::WebInputEvent::GetStaticTimeStampForTests()); + touch_end_event.touches_length = 1; + touch_end_event.touches[0].state = blink::WebTouchPoint::kStateReleased; + touch_end_event.unique_touch_event_id = 2; + + rwhier_.RouteTouchEvent(view_root_.get(), &touch_end_event, + ui::LatencyInfo(ui::SourceEventType::TOUCH)); + + // Make sure both touch events were added to the TEAQ. + EXPECT_EQ(2u, rwhier_.TouchEventAckQueueLengthForTesting()); + + // Now, tell the router that the child view was destroyed, and verify the + // acks. + rwhier_.OnRenderWidgetHostViewBaseDestroyed(view_other_.get()); + EXPECT_EQ(view_root_->last_id_for_touch_ack(), 2lu); + EXPECT_EQ(0u, rwhier_.TouchEventAckQueueLengthForTesting()); +} + // Ensure that when RenderWidgetHostInputEventRouter receives an unexpected // touch event, it calls the root view's method to Ack the event before // dropping it.
diff --git a/content/browser/sandbox_host_linux.cc b/content/browser/sandbox_host_linux.cc index db3b884c..2f89027 100644 --- a/content/browser/sandbox_host_linux.cc +++ b/content/browser/sandbox_host_linux.cc
@@ -64,10 +64,6 @@ if (IGNORE_EINTR(close(child_socket_)) < 0) PLOG(ERROR) << "close"; - // TODO(gab): We might be able to just delete this destructor: - // https://chromium-review.googlesource.com/c/chromium/src/+/1378683 - base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope - allow_thread_join_on_shutdown; ipc_thread_->Join(); } }
diff --git a/content/browser/tracing/background_tracing_manager_impl.cc b/content/browser/tracing/background_tracing_manager_impl.cc index e2f6cf4..de18c9eb 100644 --- a/content/browser/tracing/background_tracing_manager_impl.cc +++ b/content/browser/tracing/background_tracing_manager_impl.cc
@@ -115,11 +115,9 @@ } void BackgroundTracingManagerImpl::AddMetadataGeneratorFunction() { - TracingControllerImpl::GetInstance() - ->GetTraceEventAgent() - ->AddMetadataGeneratorFunction(base::BindRepeating( - &BackgroundTracingManagerImpl::GenerateMetadataDict, - base::Unretained(this))); + tracing::TraceEventAgent::GetInstance()->AddMetadataGeneratorFunction( + base::BindRepeating(&BackgroundTracingManagerImpl::GenerateMetadataDict, + base::Unretained(this))); } void BackgroundTracingManagerImpl::WhenIdle( @@ -491,7 +489,7 @@ void BackgroundTracingManagerImpl::SetRuleTriggeredCallbackForTesting( const base::Closure& callback) { rule_triggered_callback_for_testing_ = callback; -}; +} void BackgroundTracingManagerImpl::FireTimerForTesting() { DCHECK(tracing_timer_);
diff --git a/content/browser/tracing/cast_tracing_agent.cc b/content/browser/tracing/cast_tracing_agent.cc index c98ad17..0c0588f 100644 --- a/content/browser/tracing/cast_tracing_agent.cc +++ b/content/browser/tracing/cast_tracing_agent.cc
@@ -274,9 +274,8 @@ } // namespace -CastTracingAgent::CastTracingAgent(service_manager::Connector* connector) - : BaseAgent(connector, - "systemTraceEvents", +CastTracingAgent::CastTracingAgent() + : BaseAgent("systemTraceEvents", tracing::mojom::TraceDataType::STRING, base::kNullProcessId), worker_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
diff --git a/content/browser/tracing/cast_tracing_agent.h b/content/browser/tracing/cast_tracing_agent.h index 0a45ac50..04492e9 100644 --- a/content/browser/tracing/cast_tracing_agent.h +++ b/content/browser/tracing/cast_tracing_agent.h
@@ -12,10 +12,6 @@ #include "services/tracing/public/cpp/base_agent.h" #include "services/tracing/public/mojom/tracing.mojom.h" -namespace service_manager { -class Connector; -} // namespace service_manager - namespace chromecast { class SystemTracer; } @@ -28,7 +24,7 @@ // service with perfetto. class CastTracingAgent : public tracing::BaseAgent { public: - explicit CastTracingAgent(service_manager::Connector* connector); + CastTracingAgent(); ~CastTracingAgent() override; private:
diff --git a/content/browser/tracing/cros_tracing_agent.cc b/content/browser/tracing/cros_tracing_agent.cc index 542b4d2..d9e25fe 100644 --- a/content/browser/tracing/cros_tracing_agent.cc +++ b/content/browser/tracing/cros_tracing_agent.cc
@@ -217,9 +217,8 @@ } // namespace -CrOSTracingAgent::CrOSTracingAgent(service_manager::Connector* connector) - : BaseAgent(connector, - tracing::mojom::kSystemTraceEventLabel, +CrOSTracingAgent::CrOSTracingAgent() + : BaseAgent(tracing::mojom::kSystemTraceEventLabel, tracing::mojom::TraceDataType::STRING, base::kNullProcessId) { tracing::ProducerClient::Get()->AddDataSource(CrOSDataSource::GetInstance());
diff --git a/content/browser/tracing/cros_tracing_agent.h b/content/browser/tracing/cros_tracing_agent.h index a9e0c24..289db7c 100644 --- a/content/browser/tracing/cros_tracing_agent.h +++ b/content/browser/tracing/cros_tracing_agent.h
@@ -15,10 +15,6 @@ class RefCountedString; } // namespace base -namespace service_manager { -class Connector; -} // namespace service_manager - namespace content { class CrOSSystemTracingSession; @@ -27,7 +23,7 @@ // service with perfetto. class CrOSTracingAgent : public tracing::BaseAgent { public: - explicit CrOSTracingAgent(service_manager::Connector* connector); + CrOSTracingAgent(); private: friend std::default_delete<CrOSTracingAgent>;
diff --git a/content/browser/tracing/tracing_controller_browsertest.cc b/content/browser/tracing/tracing_controller_browsertest.cc index 8e660c2..d59699d3 100644 --- a/content/browser/tracing/tracing_controller_browsertest.cc +++ b/content/browser/tracing/tracing_controller_browsertest.cc
@@ -253,8 +253,9 @@ base::Bind(&IsTraceEventArgsWhitelisted)); TracingControllerImpl* controller = TracingControllerImpl::GetInstance(); - controller->GetTraceEventAgent()->AddMetadataGeneratorFunction(base::Bind( - &TracingControllerTest::GenerateMetadataDict, base::Unretained(this))); + tracing::TraceEventAgent::GetInstance()->AddMetadataGeneratorFunction( + base::Bind(&TracingControllerTest::GenerateMetadataDict, + base::Unretained(this))); { base::RunLoop run_loop;
diff --git a/content/browser/tracing/tracing_controller_impl.cc b/content/browser/tracing/tracing_controller_impl.cc index 72ad7681..d530b9e 100644 --- a/content/browser/tracing/tracing_controller_impl.cc +++ b/content/browser/tracing/tracing_controller_impl.cc
@@ -132,13 +132,16 @@ connector->BindInterface(tracing::mojom::kServiceName, &coordinator_); #if defined(OS_CHROMEOS) - agents_.push_back(std::make_unique<CrOSTracingAgent>(connector)); + agents_.push_back(std::make_unique<CrOSTracingAgent>()); #elif defined(CAST_TRACING_AGENT) - agents_.push_back(std::make_unique<CastTracingAgent>(connector)); + agents_.push_back(std::make_unique<CastTracingAgent>()); #endif - auto trace_event_agent = tracing::TraceEventAgent::Create( - connector, true /* request_clock_sync_marker_on_android */); + for (auto& agent : agents_) + agent->Connect(connector); + + auto* trace_event_agent = tracing::TraceEventAgent::GetInstance(); + trace_event_agent->Connect(connector); // For adding general CPU, network, OS, and other system information to the // metadata. @@ -149,12 +152,6 @@ base::BindRepeating(&TracingDelegate::GenerateMetadataDict, base::Unretained(delegate_.get()))); } - trace_event_agent_ = std::move(trace_event_agent); -} - -tracing::TraceEventAgent* TracingControllerImpl::GetTraceEventAgent() const { - DCHECK(trace_event_agent_); - return trace_event_agent_.get(); } std::unique_ptr<base::DictionaryValue> @@ -355,6 +352,10 @@ return false; DCHECK_CURRENTLY_ON(BrowserThread::UI); +#if defined(OS_ANDROID) + base::trace_event::TraceLog::GetInstance()->AddClockSyncMetadataEvent(); +#endif + tracing::TraceStartupConfig::GetInstance()->SetDisabled(); trace_data_endpoint_ = std::move(trace_data_endpoint); is_data_complete_ = false; @@ -462,9 +463,9 @@ void TracingControllerImpl::SetTracingDelegateForTesting( std::unique_ptr<TracingDelegate> delegate) { - if (!delegate) + if (!delegate) { delegate_.reset(GetContentClient()->browser()->GetTracingDelegate()); - else { + } else { delegate_ = std::move(delegate); } }
diff --git a/content/browser/tracing/tracing_controller_impl.h b/content/browser/tracing/tracing_controller_impl.h index 13092d2..4d7434a 100644 --- a/content/browser/tracing/tracing_controller_impl.h +++ b/content/browser/tracing/tracing_controller_impl.h
@@ -8,6 +8,7 @@ #include <memory> #include <set> #include <string> +#include <vector> #include "base/callback_forward.h" #include "base/memory/ref_counted.h" @@ -27,7 +28,7 @@ } // namespace base namespace tracing { -class TraceEventAgent; +class BaseAgent; } // namespace tracing namespace content { @@ -65,8 +66,6 @@ void RegisterTracingUI(TracingUI* tracing_ui); void UnregisterTracingUI(TracingUI* tracing_ui); - CONTENT_EXPORT tracing::TraceEventAgent* GetTraceEventAgent() const; - // For unittests. CONTENT_EXPORT void SetTracingDelegateForTesting( std::unique_ptr<TracingDelegate> delegate); @@ -88,8 +87,7 @@ tracing::mojom::AgentRegistryPtr agent_registry_; tracing::mojom::CoordinatorPtr coordinator_; - std::vector<std::unique_ptr<tracing::mojom::Agent>> agents_; - std::unique_ptr<tracing::TraceEventAgent> trace_event_agent_; + std::vector<std::unique_ptr<tracing::BaseAgent>> agents_; std::unique_ptr<TracingDelegate> delegate_; std::unique_ptr<base::trace_event::TraceConfig> trace_config_; std::unique_ptr<mojo::DataPipeDrainer> drainer_;
diff --git a/content/child/child_thread_impl.cc b/content/child/child_thread_impl.cc index 08dc179..a0cd22fd 100644 --- a/content/child/child_thread_impl.cc +++ b/content/child/child_thread_impl.cc
@@ -71,6 +71,7 @@ #include "services/service_manager/public/cpp/interface_provider.h" #include "services/service_manager/runner/common/client_util.h" #include "services/service_manager/sandbox/sandbox_type.h" +#include "services/tracing/public/cpp/trace_event_agent.h" #if defined(OS_POSIX) #include "base/posix/global_descriptors.h" @@ -571,8 +572,7 @@ channel_->AddFilter(new tracing::ChildTraceMessageFilter( ChildProcess::current()->io_task_runner())); - trace_event_agent_ = tracing::TraceEventAgent::Create( - GetConnector(), false /* request_clock_sync_marker_on_android */); + tracing::TraceEventAgent::GetInstance()->Connect(GetConnector()); } ChildThreadImpl::~ChildThreadImpl() {
diff --git a/content/child/child_thread_impl.h b/content/child/child_thread_impl.h index 249b5b3..a4792c9 100644 --- a/content/child/child_thread_impl.h +++ b/content/child/child_thread_impl.h
@@ -30,7 +30,6 @@ #include "ipc/message_router.h" #include "mojo/public/cpp/bindings/associated_binding.h" #include "mojo/public/cpp/bindings/associated_binding_set.h" -#include "services/tracing/public/cpp/trace_event_agent.h" #include "third_party/blink/public/mojom/associated_interfaces/associated_interfaces.mojom.h" #if defined(OS_WIN) @@ -244,8 +243,6 @@ scoped_refptr<base::SingleThreadTaskRunner> browser_process_io_runner_; - std::unique_ptr<tracing::TraceEventAgent> trace_event_agent_; - std::unique_ptr<variations::ChildProcessFieldTrialSyncer> field_trial_syncer_; std::unique_ptr<base::WeakPtrFactory<ChildThreadImpl>>
diff --git a/content/common/view_messages.h b/content/common/view_messages.h index 3cef510..811dab2 100644 --- a/content/common/view_messages.h +++ b/content/common/view_messages.h
@@ -223,6 +223,10 @@ gfx::Point /* tap point */, gfx::Rect /* rect_to_zoom */) +// Sent to the main-frame's view to request performing a zoom-to-find-in-page +// based on the rect provided. +IPC_MESSAGE_ROUTED1(ViewMsg_ZoomToFindInPageRect, gfx::Rect /*rect_to_zoom */) + // ----------------------------------------------------------------------------- // Messages sent from the renderer to the browser.
diff --git a/content/common/widget_messages.h b/content/common/widget_messages.h index 6e80d660..48d584db 100644 --- a/content/common/widget_messages.h +++ b/content/common/widget_messages.h
@@ -342,4 +342,9 @@ gfx::Point /* tap point */, gfx::Rect /* rect_to_zoom */) +// Sent by a widget to the browser to request a page scale animation in the +// main-frame's widget for find-in-page zoom. +IPC_MESSAGE_ROUTED1(WidgetHostMsg_ZoomToFindInPageRectInMainFrame, + gfx::Rect /* rect_to_zoom */) + #endif // CONTENT_COMMON_WIDGET_MESSAGES_H_
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/MediaSessionTest.java b/content/public/android/javatests/src/org/chromium/content/browser/MediaSessionTest.java index 981c659..03aed05c 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/MediaSessionTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/MediaSessionTest.java
@@ -189,6 +189,7 @@ @Test @MediumTest @Feature({"MediaSession"}) + @DisabledTest(message = "crbug.com/916535") public void testShortAudioIsTransient() throws Exception { Assert.assertEquals( AudioManager.AUDIOFOCUS_LOSS, mAudioFocusChangeListener.getAudioFocusState());
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc index 0222c42..e8f77a30 100644 --- a/content/public/test/browser_test_utils.cc +++ b/content/public/test/browser_test_utils.cc
@@ -1800,18 +1800,18 @@ } void WaitForInterstitialDetach(content::WebContents* web_contents) { - RunTaskAndWaitForInterstitialDetach(web_contents, base::Closure()); + RunTaskAndWaitForInterstitialDetach(web_contents, base::OnceClosure()); } void RunTaskAndWaitForInterstitialDetach(content::WebContents* web_contents, - const base::Closure& task) { + base::OnceClosure task) { if (!web_contents || !web_contents->ShowingInterstitialPage()) return; base::RunLoop run_loop; InterstitialObserver observer(web_contents, base::OnceClosure(), run_loop.QuitClosure()); if (!task.is_null()) - task.Run(); + std::move(task).Run(); // At this point, web_contents may have been deleted. run_loop.Run(); }
diff --git a/content/public/test/browser_test_utils.h b/content/public/test/browser_test_utils.h index eda137c..3effe69 100644 --- a/content/public/test/browser_test_utils.h +++ b/content/public/test/browser_test_utils.h
@@ -818,7 +818,7 @@ // destroyed by the time WaitForInterstitialDetach is called (e.g. when waiting // for an interstitial detach after closing a tab). void RunTaskAndWaitForInterstitialDetach(content::WebContents* web_contents, - const base::Closure& task); + base::OnceClosure task); // Waits until all resources have loaded in the given RenderFrameHost. // When the load completes, this function sends a "pageLoadComplete" message
diff --git a/content/public/test/unittest_test_suite.cc b/content/public/test/unittest_test_suite.cc index 45fa013..5d1c4b9 100644 --- a/content/public/test/unittest_test_suite.cc +++ b/content/public/test/unittest_test_suite.cc
@@ -54,21 +54,18 @@ #if defined(USE_X11) XInitThreads(); #endif -#if defined(USE_AURA) - aura_test_suite_setup_ = std::make_unique<aura::AuraTestSuiteSetup>(); -#endif DCHECK(test_suite); blink_test_support_.reset(new TestBlinkWebUnitTestSupport); } -UnitTestTestSuite::~UnitTestTestSuite() { - blink_test_support_.reset(); -#if defined(USE_AURA) - aura_test_suite_setup_.reset(); -#endif -} +UnitTestTestSuite::~UnitTestTestSuite() = default; int UnitTestTestSuite::Run() { +#if defined(USE_AURA) + // Must be initialized after test suites manipulate feature flags. + aura::AuraTestSuiteSetup aura_setup; +#endif + return test_suite_->Run(); }
diff --git a/content/public/test/unittest_test_suite.h b/content/public/test/unittest_test_suite.h index c84dfe2..a6be2fa 100644 --- a/content/public/test/unittest_test_suite.h +++ b/content/public/test/unittest_test_suite.h
@@ -10,12 +10,6 @@ #include "base/macros.h" #include "build/build_config.h" -#if defined(USE_AURA) -namespace aura { -class AuraTestSuiteSetup; -} -#endif - namespace base { class TestSuite; } @@ -40,9 +34,6 @@ std::unique_ptr<base::TestSuite> test_suite_; std::unique_ptr<TestBlinkWebUnitTestSupport> blink_test_support_; -#if defined(USE_AURA) - std::unique_ptr<aura::AuraTestSuiteSetup> aura_test_suite_setup_; -#endif DISALLOW_COPY_AND_ASSIGN(UnitTestTestSuite); };
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index 8b7b27c..5cc21191 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc
@@ -1260,6 +1260,7 @@ IPC_MESSAGE_HANDLER(ViewMsg_PluginActionAt, OnPluginActionAt) IPC_MESSAGE_HANDLER(ViewMsg_AnimateDoubleTapZoom, OnAnimateDoubleTapZoomInMainFrame) + IPC_MESSAGE_HANDLER(ViewMsg_ZoomToFindInPageRect, OnZoomToFindInPageRect) // Page messages. IPC_MESSAGE_HANDLER(PageMsg_UpdateWindowScreenRect, @@ -2140,4 +2141,9 @@ webview()->AnimateDoubleTapZoom(point, bound); } +void RenderViewImpl::OnZoomToFindInPageRect( + const blink::WebRect& rect_to_zoom) { + webview()->ZoomToFindInPageRect(rect_to_zoom); +} + } // namespace content
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h index 723484c..c4b2e8c2 100644 --- a/content/renderer/render_view_impl.h +++ b/content/renderer/render_view_impl.h
@@ -299,8 +299,6 @@ return renderer_wide_named_frame_lookup_; } void UpdateZoomLevel(double zoom_level); - void OnAnimateDoubleTapZoomInMainFrame(const blink::WebPoint& point, - const blink::WebRect& rect_to_zoom); protected: RenderViewImpl(CompositorDependencies* compositor_deps, @@ -448,6 +446,9 @@ void OnEnablePreferredSizeChangedMode(); void OnPluginActionAt(const gfx::Point& location, const blink::WebPluginAction& action); + void OnAnimateDoubleTapZoomInMainFrame(const blink::WebPoint& point, + const blink::WebRect& rect_to_zoom); + void OnZoomToFindInPageRect(const blink::WebRect& rect_to_zoom); void OnMoveOrResizeStarted(); void OnExitFullscreen(); void OnSetHistoryOffsetAndLength(int history_offset, int history_length);
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index 4e9715c..97ca49f2 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -1384,33 +1384,32 @@ UpdateZoom(params.zoom_level); - if (params.auto_resize_enabled) - return; + if (!params.auto_resize_enabled) { + visible_viewport_size_ = params.visible_viewport_size; - visible_viewport_size_ = params.visible_viewport_size; + // NOTE: We may have entered fullscreen mode without changing our size. + bool fullscreen_change = + is_fullscreen_granted_ != params.is_fullscreen_granted; + is_fullscreen_granted_ = params.is_fullscreen_granted; + display_mode_ = params.display_mode; - // NOTE: We may have entered fullscreen mode without changing our size. - bool fullscreen_change = - is_fullscreen_granted_ != params.is_fullscreen_granted; - is_fullscreen_granted_ = params.is_fullscreen_granted; - display_mode_ = params.display_mode; + size_ = params.new_size; - size_ = params.new_size; + ResizeWebWidget(); - ResizeWebWidget(); + WebSize visual_viewport_size; + if (compositor_deps_->IsUseZoomForDSFEnabled()) { + visual_viewport_size = + gfx::ScaleToCeiledSize(params.visible_viewport_size, + GetOriginalScreenInfo().device_scale_factor); + } else { + visual_viewport_size = visible_viewport_size_; + } + GetWebWidget()->ResizeVisualViewport(visual_viewport_size); - WebSize visual_viewport_size; - if (compositor_deps_->IsUseZoomForDSFEnabled()) { - visual_viewport_size = - gfx::ScaleToCeiledSize(params.visible_viewport_size, - GetOriginalScreenInfo().device_scale_factor); - } else { - visual_viewport_size = visible_viewport_size_; + if (fullscreen_change) + DidToggleFullscreen(); } - GetWebWidget()->ResizeVisualViewport(visual_viewport_size); - - if (fullscreen_change) - DidToggleFullscreen(); if (!owner_delegate_) { // Make sure that page scale factor changes propagating down from the main @@ -3041,6 +3040,14 @@ rect_to_zoom)); } +void RenderWidget::ZoomToFindInPageRectInMainFrame( + const blink::WebRect& rect_to_zoom) { + // Only oopif subframes should be sending this message. + DCHECK(!owner_delegate_); + Send(new WidgetHostMsg_ZoomToFindInPageRectInMainFrame(routing_id(), + rect_to_zoom)); +} + void RenderWidget::RequestUnbufferedInputEvents() { if (input_event_queue_) input_event_queue_->RequestUnbufferedInputEvents();
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h index f97ad74..9466b02 100644 --- a/content/renderer/render_widget.h +++ b/content/renderer/render_widget.h
@@ -375,6 +375,8 @@ void SetNeedsLowLatencyInput(bool) override; void AnimateDoubleTapZoomInMainFrame(const blink::WebPoint& point, const blink::WebRect& bounds) override; + void ZoomToFindInPageRectInMainFrame( + const blink::WebRect& rect_to_zoom) override; // Override point to obtain that the current input method state and caret // position.
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index b4567a8..4718cfc 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -2178,7 +2178,8 @@ } } -if (enable_nocompile_tests) { +# Disabled on jumbo builds because of timeouts (crbug.com/882852). +if (enable_nocompile_tests && !use_jumbo_build) { nocompile_test("content_nocompile_tests") { sources = [ "../public/browser/browser_task_traits_unittest.nc",
diff --git a/extensions/BUILD.gn b/extensions/BUILD.gn index 52e1d9ca..2e1d8f7 100644 --- a/extensions/BUILD.gn +++ b/extensions/BUILD.gn
@@ -7,6 +7,7 @@ import("//testing/test.gni") import("//tools/grit/grit_rule.gni") import("//tools/grit/repack.gni") +import("//ui/base/ui_features.gni") assert(enable_extensions) @@ -233,6 +234,10 @@ data_deps = [ "//third_party/mesa_headers", ] + + if (enable_mus) { + deps += [ "//ui/aura:test_support" ] + } } test("extensions_browsertests") {
diff --git a/extensions/browser/DEPS b/extensions/browser/DEPS index a9224bf..fa7620e 100644 --- a/extensions/browser/DEPS +++ b/extensions/browser/DEPS
@@ -25,6 +25,7 @@ # This directory contains build flags and does not pull all of PPAPI in. "+ppapi/buildflags", "+services/data_decoder/public", + "+services/identity/public/cpp", "+services/network/public/cpp", "+services/network/public/mojom", "+services/network",
diff --git a/extensions/browser/api/feedback_private/feedback_private_api.cc b/extensions/browser/api/feedback_private/feedback_private_api.cc index 7f4b0ca..71f665f 100644 --- a/extensions/browser/api/feedback_private/feedback_private_api.cc +++ b/extensions/browser/api/feedback_private/feedback_private_api.cc
@@ -203,6 +203,7 @@ ExtensionFunction::ResponseAction FeedbackPrivateGetSystemInformationFunction::Run() { + VLOG(1) << "Fetching system logs started."; // Self-deleting object. system_logs::SystemLogsFetcher* fetcher = ExtensionsAPIClient::Get() @@ -216,6 +217,7 @@ void FeedbackPrivateGetSystemInformationFunction::OnCompleted( std::unique_ptr<system_logs::SystemLogsResponse> sys_info) { + VLOG(1) << "Received system logs."; SystemInformationList sys_info_list; if (sys_info) { sys_info_list.reserve(sys_info->size()); @@ -266,6 +268,7 @@ #endif // defined(OS_CHROMEOS) ExtensionFunction::ResponseAction FeedbackPrivateSendFeedbackFunction::Run() { + VLOG(1) << "Sending feedback report started."; std::unique_ptr<feedback_private::SendFeedback::Params> params( feedback_private::SendFeedback::Params::Create(*args_)); EXTENSION_FUNCTION_VALIDATE(params); @@ -333,6 +336,8 @@ bool send_histograms, bool send_bluetooth_logs, std::unique_ptr<system_logs::SystemLogsResponse> sys_logs) { + VLOG(1) << "All logs have been fetched. Proceeding with sending the report."; + feedback_data->SetAndCompressSystemInfo(std::move(sys_logs)); FeedbackService* service = FeedbackPrivateAPI::GetFactoryInstance()
diff --git a/extensions/browser/api/feedback_private/feedback_service.cc b/extensions/browser/api/feedback_private/feedback_service.cc index 7dcab18d..547ad79 100644 --- a/extensions/browser/api/feedback_private/feedback_service.cc +++ b/extensions/browser/api/feedback_private/feedback_service.cc
@@ -32,6 +32,7 @@ feedback_data->set_user_agent(ExtensionsBrowserClient::Get()->GetUserAgent()); if (!feedback_data->attached_file_uuid().empty()) { + VLOG(1) << "Attaching file to the report."; // Self-deleting object. BlobReader* attached_file_reader = new BlobReader(browser_context_, feedback_data->attached_file_uuid(), @@ -41,6 +42,7 @@ } if (!feedback_data->screenshot_uuid().empty()) { + VLOG(1) << "Attaching screenshot to the report."; // Self-deleting object. BlobReader* screenshot_reader = new BlobReader(browser_context_, feedback_data->screenshot_uuid(), @@ -91,6 +93,7 @@ const bool screenshot_completed = feedback_data->screenshot_uuid().empty(); if (screenshot_completed && attached_file_completed) { + VLOG(1) << "Attachments are ready."; // Signal the feedback object that the data from the feedback page has been // filled - the object will manage sending of the actual report. feedback_data->OnFeedbackPageDataComplete();
diff --git a/extensions/browser/api/messaging/message_service.cc b/extensions/browser/api/messaging/message_service.cc index 95e8cc9..4cf086d 100644 --- a/extensions/browser/api/messaging/message_service.cc +++ b/extensions/browser/api/messaging/message_service.cc
@@ -39,6 +39,7 @@ #include "extensions/browser/extensions_browser_client.h" #include "extensions/browser/guest_view/web_view/web_view_guest.h" #include "extensions/browser/lazy_background_task_queue.h" +#include "extensions/browser/lazy_context_id.h" #include "extensions/browser/process_manager.h" #include "extensions/common/extension.h" #include "extensions/common/manifest_constants.h" @@ -638,7 +639,7 @@ auto pending = pending_lazy_background_page_channels_.find(channel_id); if (pending != pending_lazy_background_page_channels_.end()) { lazy_background_task_queue_->AddPendingTask( - pending->second.first, pending->second.second, + LazyContextId(pending->second.first, pending->second.second), base::BindOnce(&MessageService::PendingLazyBackgroundPageClosePort, weak_factory_.GetWeakPtr(), port_id, process_id, routing_id, force_close, error_message)); @@ -738,7 +739,7 @@ auto pending = pending_lazy_background_page_channels_.find(channel_id); if (pending != pending_lazy_background_page_channels_.end()) { lazy_background_task_queue_->AddPendingTask( - pending->second.first, pending->second.second, + LazyContextId(pending->second.first, pending->second.second), base::BindOnce(&MessageService::PendingLazyBackgroundPagePostMessage, weak_factory_.GetWeakPtr(), source_port_id, message)); } @@ -780,7 +781,7 @@ PendingLazyBackgroundPageChannel(context, extension->id()); int source_id = (*params)->source_process_id; lazy_background_task_queue_->AddPendingTask( - context, extension->id(), + LazyContextId(context, extension->id()), base::BindOnce(&MessageService::PendingLazyBackgroundPageOpenChannel, weak_factory_.GetWeakPtr(), base::Passed(params), source_id));
diff --git a/extensions/browser/api/runtime/runtime_api.cc b/extensions/browser/api/runtime/runtime_api.cc index 7416632..50836799 100644 --- a/extensions/browser/api/runtime/runtime_api.cc +++ b/extensions/browser/api/runtime/runtime_api.cc
@@ -32,6 +32,7 @@ #include "extensions/browser/extension_util.h" #include "extensions/browser/extensions_browser_client.h" #include "extensions/browser/lazy_background_task_queue.h" +#include "extensions/browser/lazy_context_id.h" #include "extensions/browser/process_manager_factory.h" #include "extensions/common/api/runtime.h" #include "extensions/common/error_utils.h" @@ -130,7 +131,7 @@ LazyBackgroundTaskQueue::Get(browser_context) ->ShouldEnqueueTask(browser_context, extension)) { LazyBackgroundTaskQueue::Get(browser_context) - ->AddPendingTask(browser_context, extension_id, + ->AddPendingTask(LazyContextId(browser_context, extension_id), base::BindOnce(&DispatchOnStartupEventImpl, browser_context, extension_id, false)); return; @@ -599,7 +600,7 @@ ->ShouldEnqueueTask(browser_context(), extension())) { LazyBackgroundTaskQueue::Get(browser_context()) ->AddPendingTask( - browser_context(), extension_id(), + LazyContextId(browser_context(), extension_id()), base::BindOnce(&RuntimeGetBackgroundPageFunction::OnPageLoaded, this)); } else if (host) {
diff --git a/extensions/browser/api/web_request/web_request_api_helpers.cc b/extensions/browser/api/web_request/web_request_api_helpers.cc index 6288974..7af7e6c 100644 --- a/extensions/browser/api/web_request/web_request_api_helpers.cc +++ b/extensions/browser/api/web_request/web_request_api_helpers.cc
@@ -558,8 +558,7 @@ } } if (!cookie_with_same_name_found) { - cookies->push_back(std::make_pair(base::StringPiece(*new_name), - base::StringPiece(*new_value))); + cookies->emplace_back(*new_name, *new_value); modified = true; } }
diff --git a/extensions/browser/events/lazy_event_dispatcher.cc b/extensions/browser/events/lazy_event_dispatcher.cc index dba9fc1..887d171 100644 --- a/extensions/browser/events/lazy_event_dispatcher.cc +++ b/extensions/browser/events/lazy_event_dispatcher.cc
@@ -118,8 +118,8 @@ dispatched_event->will_dispatch_callback.Reset(); } - queue->AddPendingTaskToDispatchEvent( - dispatch_context, base::BindOnce(dispatch_function_, dispatched_event)); + queue->AddPendingTask(dispatch_context, + base::BindOnce(dispatch_function_, dispatched_event)); return true; }
diff --git a/extensions/browser/extension_registrar.cc b/extensions/browser/extension_registrar.cc index 55d68f7..e54628e 100644 --- a/extensions/browser/extension_registrar.cc +++ b/extensions/browser/extension_registrar.cc
@@ -17,6 +17,7 @@ #include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_system.h" #include "extensions/browser/lazy_background_task_queue.h" +#include "extensions/browser/lazy_context_id.h" #include "extensions/browser/notification_types.h" #include "extensions/browser/process_manager.h" #include "extensions/browser/renderer_startup_helper.h" @@ -522,7 +523,8 @@ // Wake up the event page by posting a dummy task. LazyBackgroundTaskQueue* queue = LazyBackgroundTaskQueue::Get(browser_context_); - queue->AddPendingTask(browser_context_, extension->id(), base::DoNothing()); + queue->AddPendingTask(LazyContextId(browser_context_, extension->id()), + base::DoNothing()); } } // namespace extensions
diff --git a/extensions/browser/guest_view/app_view/app_view_guest.cc b/extensions/browser/guest_view/app_view/app_view_guest.cc index 13f0910..f4596561 100644 --- a/extensions/browser/guest_view/app_view/app_view_guest.cc +++ b/extensions/browser/guest_view/app_view/app_view_guest.cc
@@ -20,6 +20,7 @@ #include "extensions/browser/extension_registry.h" #include "extensions/browser/guest_view/app_view/app_view_constants.h" #include "extensions/browser/lazy_background_task_queue.h" +#include "extensions/browser/lazy_context_id.h" #include "extensions/browser/process_manager.h" #include "extensions/browser/view_type_utils.h" #include "extensions/common/api/app_runtime.h" @@ -197,7 +198,7 @@ LazyBackgroundTaskQueue::Get(browser_context()); if (queue->ShouldEnqueueTask(browser_context(), guest_extension)) { queue->AddPendingTask( - browser_context(), guest_extension->id(), + LazyContextId(browser_context(), guest_extension->id()), base::BindOnce(&AppViewGuest::LaunchAppAndFireEvent, weak_ptr_factory_.GetWeakPtr(), data->CreateDeepCopy(), std::move(callback)));
diff --git a/extensions/browser/lazy_background_task_queue.cc b/extensions/browser/lazy_background_task_queue.cc index bfc6afc..69f0db3 100644 --- a/extensions/browser/lazy_background_task_queue.cc +++ b/extensions/browser/lazy_background_task_queue.cc
@@ -82,21 +82,14 @@ return false; } -void LazyBackgroundTaskQueue::AddPendingTaskToDispatchEvent( - const LazyContextId& context_id, - LazyContextTaskQueue::PendingTask task) { - AddPendingTask(context_id.browser_context(), context_id.extension_id(), - std::move(task)); -} - -void LazyBackgroundTaskQueue::AddPendingTask( - content::BrowserContext* browser_context, - const std::string& extension_id, - PendingTask task) { +void LazyBackgroundTaskQueue::AddPendingTask(const LazyContextId& context_id, + PendingTask task) { if (ExtensionsBrowserClient::Get()->IsShuttingDown()) { std::move(task).Run(nullptr); return; } + const ExtensionId& extension_id = context_id.extension_id(); + content::BrowserContext* const browser_context = context_id.browser_context(); PendingTasksList* tasks_list = nullptr; PendingTasksKey key(browser_context, extension_id); auto it = pending_tasks_.find(key);
diff --git a/extensions/browser/lazy_background_task_queue.h b/extensions/browser/lazy_background_task_queue.h index b9173320..6e0ddbf 100644 --- a/extensions/browser/lazy_background_task_queue.h +++ b/extensions/browser/lazy_background_task_queue.h
@@ -56,19 +56,14 @@ bool ShouldEnqueueTask(content::BrowserContext* context, const Extension* extension) override; - // TODO(lazyboy): Find a better way to use AddPendingTask instead of this. - void AddPendingTaskToDispatchEvent(const LazyContextId& context_id, - PendingTask task) override; - // Adds a task to the queue for a given extension. If this is the first // task added for the extension, its lazy background page will be loaded. // The task will be called either when the page is loaded, or when the // page fails to load for some reason (e.g. a crash or browser // shutdown). In the latter case, |task| will be called with an empty // std::unique_ptr<ContextItem> parameter. - void AddPendingTask(content::BrowserContext* context, - const std::string& extension_id, - PendingTask task); + void AddPendingTask(const LazyContextId& context_id, + PendingTask task) override; private: FRIEND_TEST_ALL_PREFIXES(LazyBackgroundTaskQueueTest, AddPendingTask);
diff --git a/extensions/browser/lazy_background_task_queue_unittest.cc b/extensions/browser/lazy_background_task_queue_unittest.cc index 740e115..926a3fc 100644 --- a/extensions/browser/lazy_background_task_queue_unittest.cc +++ b/extensions/browser/lazy_background_task_queue_unittest.cc
@@ -16,6 +16,7 @@ #include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_registry_factory.h" #include "extensions/browser/extensions_test.h" +#include "extensions/browser/lazy_context_id.h" #include "extensions/browser/process_manager.h" #include "extensions/browser/process_manager_factory.h" #include "extensions/browser/test_extensions_browser_client.h" @@ -148,8 +149,9 @@ // Adding a pending task increases the number of extensions with tasks, but // doesn't run the task. - queue.AddPendingTask(browser_context(), - no_background->id(), + const LazyContextId no_background_context_id(browser_context(), + no_background->id()); + queue.AddPendingTask(no_background_context_id, base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask, base::Unretained(this))); EXPECT_EQ(1u, queue.pending_tasks_.size()); @@ -157,8 +159,7 @@ // Another task on the same extension doesn't increase the number of // extensions that have tasks and doesn't run any tasks. - queue.AddPendingTask(browser_context(), - no_background->id(), + queue.AddPendingTask(no_background_context_id, base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask, base::Unretained(this))); EXPECT_EQ(1u, queue.pending_tasks_.size()); @@ -168,8 +169,9 @@ // a background host, and if that fails, runs the task immediately. scoped_refptr<const Extension> lazy_background = CreateLazyBackgroundExtension(); - queue.AddPendingTask(browser_context(), - lazy_background->id(), + const LazyContextId lazy_background_context_id(browser_context(), + lazy_background->id()); + queue.AddPendingTask(lazy_background_context_id, base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask, base::Unretained(this))); EXPECT_EQ(1u, queue.pending_tasks_.size()); @@ -189,8 +191,7 @@ EXPECT_EQ(0, task_run_count()); // Schedule a task to run. - queue.AddPendingTask(browser_context(), - extension->id(), + queue.AddPendingTask(LazyContextId(browser_context(), extension->id()), base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask, base::Unretained(this))); EXPECT_EQ(0, task_run_count()); @@ -225,7 +226,7 @@ // Did not try to create a background host because there are no queued tasks. EXPECT_EQ(0, process_manager()->create_count()); - queue.AddPendingTask(browser_context(), lazy_background->id(), + queue.AddPendingTask(LazyContextId(browser_context(), lazy_background->id()), base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask, base::Unretained(this))); EXPECT_EQ(1u, queue.pending_tasks_.size());
diff --git a/extensions/browser/lazy_context_task_queue.h b/extensions/browser/lazy_context_task_queue.h index f6ef47f..1d3d642 100644 --- a/extensions/browser/lazy_context_task_queue.h +++ b/extensions/browser/lazy_context_task_queue.h
@@ -65,15 +65,8 @@ // be loaded. The task will be called either when the page is loaded, // or when the page fails to load for some reason (e.g. a crash or browser // shutdown). In the latter case, the ContextInfo will be nullptr. - // - // TODO(lazyboy): Remove "ToDispatchEvent" suffix and simply call this - // AddPendingTask. Issues: - // 1. We already have LazyBackgroundTaskQueue::AddPendingTask. Moreover, that - // is heavily used thoughout the codebase. - // 2. LazyBackgroundTaskQueue::AddPendingTask is tied to ExtensionHost. This - // class should be ExtensionHost agnostic. - virtual void AddPendingTaskToDispatchEvent(const LazyContextId& context_id, - PendingTask task) = 0; + virtual void AddPendingTask(const LazyContextId& context_id, + PendingTask task) = 0; }; } // namespace extensions
diff --git a/extensions/browser/process_manager.cc b/extensions/browser/process_manager.cc index 882c7e7..67b3acf 100644 --- a/extensions/browser/process_manager.cc +++ b/extensions/browser/process_manager.cc
@@ -33,6 +33,7 @@ #include "extensions/browser/extension_system.h" #include "extensions/browser/extensions_browser_client.h" #include "extensions/browser/lazy_background_task_queue.h" +#include "extensions/browser/lazy_context_id.h" #include "extensions/browser/notification_types.h" #include "extensions/browser/process_manager_delegate.h" #include "extensions/browser/process_manager_factory.h" @@ -434,7 +435,7 @@ LazyBackgroundTaskQueue* queue = LazyBackgroundTaskQueue::Get(browser_context_); queue->AddPendingTask( - browser_context_, extension_id, + LazyContextId(browser_context_, extension_id), base::BindOnce(&PropagateExtensionWakeResult, std::move(callback))); return true; }
diff --git a/extensions/browser/service_worker_task_queue.cc b/extensions/browser/service_worker_task_queue.cc index 7f57446..6b1b9db9 100644 --- a/extensions/browser/service_worker_task_queue.cc +++ b/extensions/browser/service_worker_task_queue.cc
@@ -200,9 +200,8 @@ return true; } -void ServiceWorkerTaskQueue::AddPendingTaskToDispatchEvent( - const LazyContextId& context_id, - PendingTask task) { +void ServiceWorkerTaskQueue::AddPendingTask(const LazyContextId& context_id, + PendingTask task) { DCHECK(context_id.is_for_service_worker()); // TODO(lazyboy): Do we need to handle incognito context?
diff --git a/extensions/browser/service_worker_task_queue.h b/extensions/browser/service_worker_task_queue.h index 36d27e8..8594889 100644 --- a/extensions/browser/service_worker_task_queue.h +++ b/extensions/browser/service_worker_task_queue.h
@@ -37,8 +37,8 @@ bool ShouldEnqueueTask(content::BrowserContext* context, const Extension* extension) override; - void AddPendingTaskToDispatchEvent(const LazyContextId& context_id, - PendingTask task) override; + void AddPendingTask(const LazyContextId& context_id, + PendingTask task) override; // Performs Service Worker related tasks upon |extension| activation, // e.g. registering |extension|'s worker, executing any pending tasks.
diff --git a/extensions/browser/updater/extension_downloader.cc b/extensions/browser/updater/extension_downloader.cc index 87aac16..db2b25f 100644 --- a/extensions/browser/updater/extension_downloader.cc +++ b/extensions/browser/updater/extension_downloader.cc
@@ -43,6 +43,9 @@ #include "net/http/http_status_code.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "net/url_request/url_request_status.h" +#include "services/identity/public/cpp/access_token_info.h" +#include "services/identity/public/cpp/identity_manager.h" +#include "services/identity/public/cpp/primary_account_access_token_fetcher.h" #include "services/network/public/cpp/resource_request.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/cpp/simple_url_loader.h" @@ -209,8 +212,7 @@ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, service_manager::Connector* connector, const base::FilePath& profile_path) - : OAuth2TokenService::Consumer(kTokenServiceConsumerId), - delegate_(delegate), + : delegate_(delegate), url_loader_factory_(std::move(url_loader_factory)), profile_path_for_url_loader_factory_(profile_path), connector_(connector), @@ -223,7 +225,7 @@ base::BindRepeating(&ExtensionDownloader::CreateExtensionLoader, base::Unretained(this))), extension_cache_(nullptr), - token_service_(nullptr), + identity_manager_(nullptr), weak_ptr_factory_(this) { DCHECK(delegate_); DCHECK(url_loader_factory_); @@ -301,11 +303,9 @@ fetches_preparing_.clear(); } -void ExtensionDownloader::SetWebstoreAuthenticationCapabilities( - const GetWebstoreAccountCallback& webstore_account_callback, - OAuth2TokenService* token_service) { - webstore_account_callback_ = webstore_account_callback; - token_service_ = token_service; +void ExtensionDownloader::SetIdentityManager( + identity::IdentityManager* identity_manager) { + identity_manager_ = identity_manager; } // static @@ -928,12 +928,17 @@ // We should try OAuth2, but we have no token cached. This // ExtensionLoader will be started once the token fetch is complete, // in either OnTokenFetchSuccess or OnTokenFetchFailure. - DCHECK(token_service_); - DCHECK(!webstore_account_callback_.is_null()); - OAuth2TokenService::ScopeSet webstore_scopes; + DCHECK(identity_manager_); + identity::ScopeSet webstore_scopes; webstore_scopes.insert(kWebstoreOAuth2Scope); - access_token_request_ = token_service_->StartRequest( - webstore_account_callback_.Run(), webstore_scopes, this); + // It is safe to use Unretained(this) here given that the callback + // will not be invoked if this object is deleted. + access_token_fetcher_ = + std::make_unique<identity::PrimaryAccountAccessTokenFetcher>( + kTokenServiceConsumerId, identity_manager_, webstore_scopes, + base::BindOnce(&ExtensionDownloader::OnAccessTokenFetchComplete, + base::Unretained(this)), + identity::PrimaryAccountAccessTokenFetcher::Mode::kImmediate); return; } extension_loader_resource_request_->headers.SetHeader( @@ -1098,7 +1103,7 @@ // fetch. switch (fetch->credentials) { case ExtensionFetch::CREDENTIALS_NONE: - if (fetch->url.DomainIs(kGoogleDotCom) && token_service_) { + if (fetch->url.DomainIs(kGoogleDotCom) && identity_manager_) { fetch->credentials = ExtensionFetch::CREDENTIALS_OAUTH2_TOKEN; } else { fetch->credentials = ExtensionFetch::CREDENTIALS_COOKIES; @@ -1110,12 +1115,12 @@ // should invalidate the token and try again. if (response_code == net::HTTP_UNAUTHORIZED && fetch->oauth2_attempt_count <= kMaxOAuth2Attempts) { - DCHECK(token_service_); - DCHECK(!webstore_account_callback_.is_null()); - OAuth2TokenService::ScopeSet webstore_scopes; + DCHECK(identity_manager_); + identity::ScopeSet webstore_scopes; webstore_scopes.insert(kWebstoreOAuth2Scope); - token_service_->InvalidateAccessToken(webstore_account_callback_.Run(), - webstore_scopes, access_token_); + identity_manager_->RemoveAccessTokenFromCache( + identity_manager_->GetPrimaryAccountId(), webstore_scopes, + access_token_); access_token_.clear(); return true; } @@ -1142,24 +1147,25 @@ return false; } -void ExtensionDownloader::OnGetTokenSuccess( - const OAuth2TokenService::Request* request, - const OAuth2AccessTokenConsumer::TokenResponse& token_response) { - access_token_ = token_response.access_token; +void ExtensionDownloader::OnAccessTokenFetchComplete( + GoogleServiceAuthError error, + identity::AccessTokenInfo token_info) { + access_token_fetcher_.reset(); + + if (error.state() != GoogleServiceAuthError::NONE) { + // If we fail to get an access token, kick the pending fetch and let it fall + // back on cookies. + StartExtensionLoader(); + return; + } + + access_token_ = token_info.token; extension_loader_resource_request_->headers.SetHeader( net::HttpRequestHeaders::kAuthorization, base::StringPrintf("Bearer %s", access_token_.c_str())); StartExtensionLoader(); } -void ExtensionDownloader::OnGetTokenFailure( - const OAuth2TokenService::Request* request, - const GoogleServiceAuthError& error) { - // If we fail to get an access token, kick the pending fetch and let it fall - // back on cookies. - StartExtensionLoader(); -} - ManifestFetchData* ExtensionDownloader::CreateManifestFetchData( const GURL& update_url, int request_id,
diff --git a/extensions/browser/updater/extension_downloader.h b/extensions/browser/updater/extension_downloader.h index 6b1adea..c1203f5 100644 --- a/extensions/browser/updater/extension_downloader.h +++ b/extensions/browser/updater/extension_downloader.h
@@ -21,10 +21,16 @@ #include "extensions/browser/updater/request_queue.h" #include "extensions/browser/updater/safe_manifest_parser.h" #include "extensions/common/extension.h" -#include "google_apis/gaia/oauth2_token_service.h" +#include "google_apis/gaia/google_service_auth_error.h" #include "net/http/http_request_headers.h" #include "url/gurl.h" +namespace identity { +class PrimaryAccountAccessTokenFetcher; +class IdentityManager; +struct AccessTokenInfo; +} // namespace identity + namespace net { class URLRequestStatus; } @@ -60,18 +66,13 @@ // the crx file when updates are found. It uses a |ExtensionDownloaderDelegate| // that takes ownership of the downloaded crx files, and handles events during // the update check. -class ExtensionDownloader : public OAuth2TokenService::Consumer { +class ExtensionDownloader { public: // A closure which constructs a new ExtensionDownloader to be owned by the // caller. using Factory = base::RepeatingCallback<std::unique_ptr<ExtensionDownloader>( ExtensionDownloaderDelegate* delegate)>; - // A closure that returns the account to use for authentication to the - // webstore. - using GetWebstoreAccountCallback = - base::RepeatingCallback<const std::string&()>; - // |delegate| is stored as a raw pointer and must outlive the // ExtensionDownloader. ExtensionDownloader( @@ -79,7 +80,7 @@ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, service_manager::Connector* connector, const base::FilePath& profile_path = base::FilePath()); - ~ExtensionDownloader() override; + ~ExtensionDownloader(); // Adds |extension| to the list of extensions to check for updates. // Returns false if the |extension| can't be updated due to invalid details. @@ -114,12 +115,10 @@ // AddExtension() and AddPendingExtension(). void StartAllPending(ExtensionCache* cache); - // Sets GetWebstoreAccountCallback and TokenService instances to be used for - // OAuth2 authentication on protected Webstore downloads. Both objects must be - // valid to use for the lifetime of this object. - void SetWebstoreAuthenticationCapabilities( - const GetWebstoreAccountCallback& webstore_account_callback, - OAuth2TokenService* token_service); + // Sets the IdentityManager instance to be used for OAuth2 authentication on + // protected Webstore downloads. The IdentityManager instance must be valid to + // use for the lifetime of this object. + void SetIdentityManager(identity::IdentityManager* identity_manager); void set_brand_code(const std::string& brand_code) { brand_code_ = brand_code; @@ -312,12 +311,8 @@ const net::URLRequestStatus& status, int response_code); - // OAuth2TokenService::Consumer implementation. - void OnGetTokenSuccess( - const OAuth2TokenService::Request* request, - const OAuth2AccessTokenConsumer::TokenResponse& token_response) override; - void OnGetTokenFailure(const OAuth2TokenService::Request* request, - const GoogleServiceAuthError& error) override; + void OnAccessTokenFetchComplete(GoogleServiceAuthError error, + identity::AccessTokenInfo token_info); ManifestFetchData* CreateManifestFetchData( const GURL& update_url, @@ -377,20 +372,17 @@ // Cache for .crx files. ExtensionCache* extension_cache_; - // Gets the account to use for protected download requests. May be null. If - // non-null, valid to call for the lifetime of this object. - GetWebstoreAccountCallback webstore_account_callback_; - // May be used to fetch access tokens for protected download requests. May be // null. If non-null, guaranteed to outlive this object. - OAuth2TokenService* token_service_; + identity::IdentityManager* identity_manager_; // A Webstore download-scoped access token for the |identity_provider_|'s // active account, if any. std::string access_token_; - // A pending token fetch request. - std::unique_ptr<OAuth2TokenService::Request> access_token_request_; + // A pending access token fetcher. + std::unique_ptr<identity::PrimaryAccountAccessTokenFetcher> + access_token_fetcher_; // Brand code to include with manifest fetch queries if sending ping data. std::string brand_code_;
diff --git a/extensions/renderer/dispatcher.cc b/extensions/renderer/dispatcher.cc index cb5636d..bf256f67 100644 --- a/extensions/renderer/dispatcher.cc +++ b/extensions/renderer/dispatcher.cc
@@ -432,8 +432,10 @@ base::StringPiece script_resource = ui::ResourceBundle::GetSharedInstance().GetRawDataResource( IDR_SERVICE_WORKER_BINDINGS_JS); - v8::Local<v8::String> script = v8::String::NewExternal( - isolate, new StaticV8ExternalOneByteStringResource(script_resource)); + v8::Local<v8::String> script = + v8::String::NewExternalOneByte( + isolate, new StaticV8ExternalOneByteStringResource(script_resource)) + .ToLocalChecked(); // Run service_worker.js to get the main function. v8::Local<v8::Function> main_function;
diff --git a/extensions/renderer/resource_bundle_source_map.cc b/extensions/renderer/resource_bundle_source_map.cc index 2bd987be..9459f47e 100644 --- a/extensions/renderer/resource_bundle_source_map.cc +++ b/extensions/renderer/resource_bundle_source_map.cc
@@ -18,9 +18,10 @@ v8::Local<v8::String> ConvertString(v8::Isolate* isolate, const base::StringPiece& string) { // v8 takes ownership of the StaticV8ExternalOneByteStringResource (see - // v8::String::NewExternal()). - return v8::String::NewExternal( - isolate, new StaticV8ExternalOneByteStringResource(string)); + // v8::String::NewExternalOneByte()). + return v8::String::NewExternalOneByte( + isolate, new StaticV8ExternalOneByteStringResource(string)) + .FromMaybe(v8::Local<v8::String>()); } } // namespace
diff --git a/extensions/renderer/v8_schema_registry.cc b/extensions/renderer/v8_schema_registry.cc index 0f5d1eb1..7533a276 100644 --- a/extensions/renderer/v8_schema_registry.cc +++ b/extensions/renderer/v8_schema_registry.cc
@@ -30,9 +30,12 @@ v8::Maybe<bool> maybe = object->SetPrototype(context, v8::Null(context->GetIsolate())); CHECK(maybe.IsJust() && maybe.FromJust()); - v8::Local<v8::Array> property_names = object->GetOwnPropertyNames(); + v8::Local<v8::Array> property_names = + object->GetOwnPropertyNames(context).ToLocalChecked(); for (uint32_t i = 0; i < property_names->Length(); ++i) { - v8::Local<v8::Value> child = object->Get(property_names->Get(i)); + v8::Local<v8::Value> child = + object->Get(context, property_names->Get(context, i).ToLocalChecked()) + .ToLocalChecked(); if (child->IsObject()) DeepFreeze(v8::Local<v8::Object>::Cast(child), context); } @@ -106,12 +109,17 @@ const std::vector<std::string>& apis) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); v8::EscapableHandleScope handle_scope(isolate); - v8::Context::Scope context_scope(GetOrCreateContext(isolate)); + v8::Local<v8::Context> context = GetOrCreateContext(isolate); + v8::Context::Scope context_scope(context); v8::Local<v8::Array> v8_apis(v8::Array::New(isolate, apis.size())); size_t api_index = 0; for (auto i = apis.cbegin(); i != apis.cend(); ++i) { - v8_apis->Set(api_index++, GetSchema(*i)); + bool set_result = + v8_apis->Set(context, api_index++, GetSchema(*i)).ToChecked(); + // Set() should never return false without throwing an exception (which + // would be caught by the ToChecked() above). + DCHECK(set_result); } return handle_scope.Escape(v8_apis); } @@ -134,9 +142,8 @@ base::StringPiece schema_string = ExtensionAPI::GetSharedInstance()->GetSchemaStringPiece(api); CHECK(!schema_string.empty()); - v8::MaybeLocal<v8::String> v8_maybe_string = - v8::String::NewExternal( - isolate, new StaticV8ExternalOneByteStringResource(schema_string)); + v8::MaybeLocal<v8::String> v8_maybe_string = v8::String::NewExternalOneByte( + isolate, new StaticV8ExternalOneByteStringResource(schema_string)); v8::Local<v8::String> v8_schema_string; CHECK(v8_maybe_string.ToLocal(&v8_schema_string));
diff --git a/extensions/test/DEPS b/extensions/test/DEPS index 186feed..d70103cd 100644 --- a/extensions/test/DEPS +++ b/extensions/test/DEPS
@@ -1,4 +1,5 @@ include_rules = [ "+content/public", + "+ui/aura/test", "+ui/gl", ]
diff --git a/extensions/test/extensions_unittests_main.cc b/extensions/test/extensions_unittests_main.cc index ea040353..9b4a7ea4 100644 --- a/extensions/test/extensions_unittests_main.cc +++ b/extensions/test/extensions_unittests_main.cc
@@ -10,6 +10,7 @@ #include "base/path_service.h" #include "base/test/launcher/unit_test_launcher.h" #include "base/test/test_io_thread.h" +#include "build/buildflag.h" #include "content/public/common/content_client.h" #include "content/public/test/content_test_suite_base.h" #include "content/public/test/unittest_test_suite.h" @@ -17,9 +18,14 @@ #include "extensions/common/extension_paths.h" #include "extensions/test/test_extensions_client.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/base/ui_features.h" #include "ui/gl/test/gl_surface_test_support.h" #include "url/url_util.h" +#if BUILDFLAG(ENABLE_MUS) +#include "ui/aura/test/aura_test_suite_setup.h" // nogncheck +#endif + namespace { // Content client that exists only to register chrome-extension:// scheme with @@ -99,6 +105,12 @@ int main(int argc, char** argv) { content::UnitTestTestSuite test_suite(new ExtensionsTestSuite(argc, argv)); + +#if BUILDFLAG(ENABLE_MUS) + // Extensions unit tests do not use mus window service client code. + aura::AuraTestSuiteSetup::DisableMusFeatures(); +#endif + return base::LaunchUnitTests(argc, argv, base::Bind(&content::UnitTestTestSuite::Run,
diff --git a/infra/config/global/PRESUBMIT.py b/infra/config/global/PRESUBMIT.py index 4dcd129..81687a14 100644 --- a/infra/config/global/PRESUBMIT.py +++ b/infra/config/global/PRESUBMIT.py
@@ -25,7 +25,7 @@ input_api.Command( name='testing/buildbot config checks', cmd=[input_api.python_executable, input_api.os_path.join( - '..', '..', 'testing', 'buildbot', + '..', '..', '..', 'testing', 'buildbot', 'generate_buildbot_json.py',), '--check'], kwargs={}, message=output_api.PresubmitError)])
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd index 6fdc0e11..f0e6e5d 100644 --- a/ios/chrome/app/strings/ios_strings.grd +++ b/ios/chrome/app/strings/ios_strings.grd
@@ -1328,6 +1328,9 @@ <message name="IDS_IOS_SEARCH_COPIED" desc="The message displayed when the search is copied via long press (contextual search) [Length: 10em] [iOS only]"> Copied </message> + <message name="IDS_IOS_SEARCH_COPIED_TEXT" desc="Text in the search accelerator menu shown when long-pressing the omnibox with copied text. Enables pasting the current contents of the clipboard and searching the text. [iOS only]"> + Search Copied Text + </message> <message name="IDS_IOS_SEARCH_ENGINE_SETTING_TITLE" desc="The title for Search Engine selection setting [iOS only]"> Search Engine </message> @@ -1844,6 +1847,9 @@ <message name="IDS_IOS_UPGRADE_AVAILABLE_BUTTON" desc="Displayed on a button the user can use to upgrade the a more recent version of the application. [Length: 10em]"> Update </message> + <message name="IDS_IOS_VISIT_COPIED_LINK" desc="Text in the search accelerator menu shown when long-pressing the omnibox with a copied url. Enables pasting the current contents of the clipboard and navigating to the url. [iOS only]"> + Visit Copied Link + </message> <message name="IDS_IOS_VERSION" desc="The label for the Chrome version on which the application is based, displayed in the About Chrome settings page [Length: 30em] [iOS only]"> Version <ph name="PRODUCT_VERSION">$1<ex>31.0.1650.18</ex></ph> </message> @@ -1925,6 +1931,6 @@ <message name="IDS_IOS_PASTE_AND_GO" desc="Text in the editing menu shown when long-pressing the omnibox. Enables pasting the current contents of the clipboard and searching the text or navigating to the url. [iOS only]"> Paste and Go </message> - </messages> + </messages> </release> </grit>
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_SEARCH_COPIED_TEXT.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_SEARCH_COPIED_TEXT.png.sha1 new file mode 100644 index 0000000..724ec881 --- /dev/null +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_SEARCH_COPIED_TEXT.png.sha1
@@ -0,0 +1 @@ +d04775c6612f8f4f96f7925e66cc0d8453f85668 \ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_VISIT_COPIED_LINK.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_VISIT_COPIED_LINK.png.sha1 new file mode 100644 index 0000000..10d5ab9 --- /dev/null +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_VISIT_COPIED_LINK.png.sha1
@@ -0,0 +1 @@ +3394c2d0d4b3eaf30f6069acf89cceec6d7bc19d \ No newline at end of file
diff --git a/ios/chrome/browser/about_flags.mm b/ios/chrome/browser/about_flags.mm index e82958e72..a14130ce 100644 --- a/ios/chrome/browser/about_flags.mm +++ b/ios/chrome/browser/about_flags.mm
@@ -475,6 +475,11 @@ flag_descriptions::kSyncPseudoUSSPriorityPreferencesDescription, flags_ui::kOsIos, FEATURE_VALUE_TYPE(switches::kSyncPseudoUSSPriorityPreferences)}, + {"use-nsurlsession-for-signin", + flag_descriptions::kUseNSURLSessionForGaiaSigninRequestsName, + flag_descriptions::kUseNSURLSessionForGaiaSigninRequestsDescription, + flags_ui::kOsIos, + FEATURE_VALUE_TYPE(kUseNSURLSessionForGaiaSigninRequests)}, {"sync-pseudo-uss-supervised-users", flag_descriptions::kSyncPseudoUSSSupervisedUsersName, flag_descriptions::kSyncPseudoUSSSupervisedUsersDescription,
diff --git a/ios/chrome/browser/autofill/form_input_accessory_view_controller.mm b/ios/chrome/browser/autofill/form_input_accessory_view_controller.mm index c4652aa9..cfa0682 100644 --- a/ios/chrome/browser/autofill/form_input_accessory_view_controller.mm +++ b/ios/chrome/browser/autofill/form_input_accessory_view_controller.mm
@@ -188,6 +188,7 @@ if (!self.inputAccessoryView) { self.inputAccessoryView = [[FormInputAccessoryView alloc] init]; + self.inputAccessoryView.accessibilityViewIsModal = YES; if (IsIPadIdiom()) { [self.inputAccessoryView setUpWithLeadingView:self.formSuggestionView
diff --git a/ios/chrome/browser/infobars/BUILD.gn b/ios/chrome/browser/infobars/BUILD.gn index f53c9bd..1329252d 100644 --- a/ios/chrome/browser/infobars/BUILD.gn +++ b/ios/chrome/browser/infobars/BUILD.gn
@@ -24,7 +24,9 @@ deps = [ "//base", "//components/translate/core/browser", + "//ios/chrome/browser", "//ios/chrome/browser/ui/infobars:infobars_ui", + "//ios/chrome/browser/ui/infobars/confirm_infobar", "//ios/web", "//ui/base", "//ui/gfx",
diff --git a/ios/chrome/browser/infobars/infobar.h b/ios/chrome/browser/infobars/infobar.h index 529b390..7d8a146 100644 --- a/ios/chrome/browser/infobars/infobar.h +++ b/ios/chrome/browser/infobars/infobar.h
@@ -12,7 +12,7 @@ #include "components/infobars/core/infobar.h" #import "ios/chrome/browser/infobars/infobar_controller_delegate.h" -@class InfoBarController; +@protocol InfobarUIDelegate; namespace infobars { class InfoBarDelegate; } @@ -20,12 +20,15 @@ // The iOS version of infobars::InfoBar. class InfoBarIOS : public infobars::InfoBar, public InfoBarControllerDelegate { public: - InfoBarIOS(InfoBarController* controller, + InfoBarIOS(id<InfobarUIDelegate> controller, std::unique_ptr<infobars::InfoBarDelegate> delegate); ~InfoBarIOS() override; // Returns the infobar view holding contents of this infobar. - UIView* view(); + UIView* View(); + + // Returns the InfobarUIDelegate associated to this Infobar. + id<InfobarUIDelegate> InfobarUIDelegate(); // Remove the infobar view from infobar container view. void RemoveView(); @@ -35,7 +38,7 @@ bool IsOwned() override; void RemoveInfoBar() override; - InfoBarController* controller_; + id<InfobarUIDelegate> controller_; DISALLOW_COPY_AND_ASSIGN(InfoBarIOS); };
diff --git a/ios/chrome/browser/infobars/infobar.mm b/ios/chrome/browser/infobars/infobar.mm index d8807f9..1ab7807 100644 --- a/ios/chrome/browser/infobars/infobar.mm +++ b/ios/chrome/browser/infobars/infobar.mm
@@ -9,9 +9,9 @@ #include "base/logging.h" #include "components/infobars/core/confirm_infobar_delegate.h" #include "components/translate/core/browser/translate_infobar_delegate.h" -#import "ios/chrome/browser/infobars/confirm_infobar_controller.h" #include "ios/chrome/browser/infobars/infobar_controller.h" #include "ios/chrome/browser/translate/translate_infobar_tags.h" +#import "ios/chrome/browser/ui/infobars/infobar_ui_delegate.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -20,7 +20,7 @@ using infobars::InfoBar; using infobars::InfoBarDelegate; -InfoBarIOS::InfoBarIOS(InfoBarController* controller, +InfoBarIOS::InfoBarIOS(id<InfobarUIDelegate> controller, std::unique_ptr<InfoBarDelegate> delegate) : InfoBar(std::move(delegate)), controller_(controller) { DCHECK(controller_); @@ -33,11 +33,16 @@ controller_ = nil; } -UIView* InfoBarIOS::view() { +UIView* InfoBarIOS::View() { DCHECK(controller_); return [controller_ view]; } +id<InfobarUIDelegate> InfoBarIOS::InfobarUIDelegate() { + DCHECK(controller_); + return controller_; +} + void InfoBarIOS::RemoveView() { DCHECK(controller_); [controller_ removeView];
diff --git a/ios/chrome/browser/infobars/infobar_container_ios.mm b/ios/chrome/browser/infobars/infobar_container_ios.mm index 0b241629..2c1e66f 100644 --- a/ios/chrome/browser/infobars/infobar_container_ios.mm +++ b/ios/chrome/browser/infobars/infobar_container_ios.mm
@@ -21,7 +21,8 @@ void InfoBarContainerIOS::PlatformSpecificAddInfoBar(infobars::InfoBar* infobar, size_t position) { InfoBarIOS* infobar_ios = static_cast<InfoBarIOS*>(infobar); - [consumer_ addInfoBarView:infobar_ios->view() position:position]; + [consumer_ addInfoBarWithDelegate:infobar_ios->InfobarUIDelegate() + position:position]; } void InfoBarContainerIOS::PlatformSpecificRemoveInfoBar(
diff --git a/ios/chrome/browser/infobars/infobar_controller.h b/ios/chrome/browser/infobars/infobar_controller.h index abec3eb..387bdd9 100644 --- a/ios/chrome/browser/infobars/infobar_controller.h +++ b/ios/chrome/browser/infobars/infobar_controller.h
@@ -7,26 +7,14 @@ #import <UIKit/UIKit.h> +#import "ios/chrome/browser/ui/infobars/infobar_ui_delegate.h" + namespace infobars { class InfoBarDelegate; } // namespace infobars -class InfoBarControllerDelegate; - // InfoBar for iOS acts as a UIViewController for InfoBarView. -@interface InfoBarController : NSObject - -// Detaches view from its delegate. -// After this function is called, no user interaction can be handled. -- (void)detachView; - -// Removes the view. -- (void)removeView; - -// The view. -@property(nonatomic, readonly) UIView* view; - -@property(nonatomic, assign) InfoBarControllerDelegate* delegate; // weak +@interface InfoBarController : NSObject <InfobarUIDelegate> @property(nonatomic, readonly) infobars::InfoBarDelegate* infoBarDelegate; // weak
diff --git a/ios/chrome/browser/infobars/infobar_utils.mm b/ios/chrome/browser/infobars/infobar_utils.mm index 8b5955a..5ac2013 100644 --- a/ios/chrome/browser/infobars/infobar_utils.mm +++ b/ios/chrome/browser/infobars/infobar_utils.mm
@@ -8,8 +8,10 @@ #include <utility> #include "components/infobars/core/confirm_infobar_delegate.h" +#include "ios/chrome/browser/experimental_flags.h" #include "ios/chrome/browser/infobars/confirm_infobar_controller.h" #include "ios/chrome/browser/infobars/infobar.h" +#import "ios/chrome/browser/ui/infobars/confirm_infobar/confirm_infobar_view_controller.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -17,7 +19,14 @@ std::unique_ptr<infobars::InfoBar> CreateConfirmInfoBar( std::unique_ptr<ConfirmInfoBarDelegate> delegate) { - ConfirmInfoBarController* controller = - [[ConfirmInfoBarController alloc] initWithInfoBarDelegate:delegate.get()]; - return std::make_unique<InfoBarIOS>(controller, std::move(delegate)); + if (experimental_flags::IsInfobarUIRebootEnabled()) { + ConfirmInfobarViewController* controller = + [[ConfirmInfobarViewController alloc] + initWithInfoBarDelegate:delegate.get()]; + return std::make_unique<InfoBarIOS>(controller, std::move(delegate)); + } else { + ConfirmInfoBarController* controller = [[ConfirmInfoBarController alloc] + initWithInfoBarDelegate:delegate.get()]; + return std::make_unique<InfoBarIOS>(controller, std::move(delegate)); + } }
diff --git a/ios/chrome/browser/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/ios_chrome_flag_descriptions.cc index ceb7113..7bb1abbe 100644 --- a/ios/chrome/browser/ios_chrome_flag_descriptions.cc +++ b/ios/chrome/browser/ios_chrome_flag_descriptions.cc
@@ -365,6 +365,11 @@ const char kUseMultiloginEndpointDescription[] = "Use Gaia OAuth multilogin for identity consistency."; +const char kUseNSURLSessionForGaiaSigninRequestsName[] = + "Use NSURLSession for sign-in requests"; +const char kUseNSURLSessionForGaiaSigninRequestsDescription[] = + "Use NSURLSession to make sign-in requests to Gaia"; + const char kUsdzPreviewName[] = "Preview USDZ format 3D models"; const char kUsdzPreviewDescription[] = "Enables previewing USDZ format 3D models in AR Quick Look.";
diff --git a/ios/chrome/browser/ios_chrome_flag_descriptions.h b/ios/chrome/browser/ios_chrome_flag_descriptions.h index a0e3190..2429949 100644 --- a/ios/chrome/browser/ios_chrome_flag_descriptions.h +++ b/ios/chrome/browser/ios_chrome_flag_descriptions.h
@@ -299,6 +299,11 @@ extern const char kUseMultiloginEndpointName[]; extern const char kUseMultiloginEndpointDescription[]; +// Title and description for the flag to switch from WKWebView to NSURLSession +// to make sign-in requests to Gaia with attached cookies. +extern const char kUseNSURLSessionForGaiaSigninRequestsName[]; +extern const char kUseNSURLSessionForGaiaSigninRequestsDescription[]; + // Title and description for the flag to enable previewing USDZ 3 model files. extern const char kUsdzPreviewName[]; extern const char kUsdzPreviewDescription[];
diff --git a/ios/chrome/browser/passwords/password_controller.h b/ios/chrome/browser/passwords/password_controller.h index 389c6f0..ae43d17 100644 --- a/ios/chrome/browser/passwords/password_controller.h +++ b/ios/chrome/browser/passwords/password_controller.h
@@ -79,6 +79,11 @@ - (instancetype)init NS_UNAVAILABLE; +// Generates and offers a password to the user based on given |formName|. +// |completionHandler| called with YES if user accepted the generated password. +- (void)generatePasswordForForm:(NSString*)formName + completionHandler:(void (^)(BOOL))completionHandler; + @end #endif // IOS_CHROME_BROWSER_PASSWORDS_PASSWORD_CONTROLLER_H_
diff --git a/ios/chrome/browser/passwords/password_controller.mm b/ios/chrome/browser/passwords/password_controller.mm index b806efe..6d37f542 100644 --- a/ios/chrome/browser/passwords/password_controller.mm +++ b/ios/chrome/browser/passwords/password_controller.mm
@@ -425,18 +425,23 @@ frameID:(NSString*)frameID completionHandler:(SuggestionHandledCompletion)completion { switch (suggestion.identifier) { - case autofill::POPUP_ITEM_ID_ALL_SAVED_PASSWORDS_ENTRY: + case autofill::POPUP_ITEM_ID_ALL_SAVED_PASSWORDS_ENTRY: { // Navigate to the settings list. [self.delegate displaySavedPasswordList]; completion(); LogSuggestionClicked(PasswordSuggestionType::SHOW_ALL); return; - case autofill::POPUP_ITEM_ID_GENERATE_PASSWORD_ENTRY: + } + case autofill::POPUP_ITEM_ID_GENERATE_PASSWORD_ENTRY: { [self generatePasswordForForm:formName - fieldIdentifier:fieldIdentifier - completionHandler:completion]; + completionHandler:^(BOOL injected) { + if (injected) + completion(); + }]; + // TODO(crbug.com/886583): add metrics. return; - default: + } + default: { LogSuggestionClicked(PasswordSuggestionType::CREDENTIALS); DCHECK([suggestion.value hasSuffix:kSuggestionSuffix]); NSString* username = [suggestion.value @@ -454,6 +459,7 @@ completion(); }]; break; + } } } @@ -665,15 +671,13 @@ } - (void)generatePasswordForForm:(NSString*)formName - fieldIdentifier:(NSString*)fieldIdentifier - completionHandler:(SuggestionHandledCompletion)completion { + completionHandler:(void (^)(BOOL))completionHandler { // TODO(crbug.com/886583): form_signature, field_signature, max_length and // spec_priority in PGM::GeneratePassword are being refactored, passing 0 for // now to get a generic random password. base::string16 generatedPassword = - _passwordGenerationManager->GeneratePassword( - _passwordManager->client()->GetLastCommittedEntryURL(), 0, 0, 0, - nullptr); + _passwordGenerationManager->GeneratePassword([self lastCommittedURL], 0, + 0, 0, nullptr); NSString* displayPassword = base::SysUTF16ToNSString(generatedPassword); @@ -698,12 +702,17 @@ addItemWithTitle:l10n_util::GetNSString(IDS_IOS_SUGGEST_PASSWORD) action:^{ // TODO(crbug.com/886583): inject in password form + if (completionHandler) + completionHandler(YES); } style:UIAlertActionStyleDefault]; [self.actionSheetCoordinator addItemWithTitle:l10n_util::GetNSString(IDS_CANCEL) - action:nil + action:^{ + if (completionHandler) + completionHandler(NO); + } style:UIAlertActionStyleCancel]; [self.actionSheetCoordinator start];
diff --git a/ios/chrome/browser/passwords/password_tab_helper.h b/ios/chrome/browser/passwords/password_tab_helper.h index e10daff8..aed2224 100644 --- a/ios/chrome/browser/passwords/password_tab_helper.h +++ b/ios/chrome/browser/passwords/password_tab_helper.h
@@ -39,6 +39,9 @@ // Sets the PasswordController delegate. void SetPasswordControllerDelegate(id<PasswordControllerDelegate> delegate); + // Generate and offer to user a password for the given |formName|. + void GenerateAndOfferPassword(NSString* formName); + // Returns an object that can provide suggestions from the PasswordController. // May return nil. id<FormSuggestionProvider> GetSuggestionProvider();
diff --git a/ios/chrome/browser/passwords/password_tab_helper.mm b/ios/chrome/browser/passwords/password_tab_helper.mm index 23c4511b..fd2f9cd 100644 --- a/ios/chrome/browser/passwords/password_tab_helper.mm +++ b/ios/chrome/browser/passwords/password_tab_helper.mm
@@ -37,6 +37,10 @@ controller_.delegate = delegate; } +void PasswordTabHelper::GenerateAndOfferPassword(NSString* formName) { + [controller_ generatePasswordForForm:formName completionHandler:nil]; +} + id<FormSuggestionProvider> PasswordTabHelper::GetSuggestionProvider() { return controller_.suggestionProvider; }
diff --git a/ios/chrome/browser/passwords/update_password_infobar_controller.mm b/ios/chrome/browser/passwords/update_password_infobar_controller.mm index a2d40161..99a01a2 100644 --- a/ios/chrome/browser/passwords/update_password_infobar_controller.mm +++ b/ios/chrome/browser/passwords/update_password_infobar_controller.mm
@@ -48,11 +48,15 @@ if (self) { _baseViewController = baseViewController; _delegate = delegate; + [self updateInfobarLabel:self.view]; } return self; } - (void)updateInfobarLabel:(ConfirmInfoBarView*)view { + if (!_delegate) + return; + [super updateInfobarLabel:view]; // Get the message text with current links marked.
diff --git a/ios/chrome/browser/signin/BUILD.gn b/ios/chrome/browser/signin/BUILD.gn index 988daef..409b708 100644 --- a/ios/chrome/browser/signin/BUILD.gn +++ b/ios/chrome/browser/signin/BUILD.gn
@@ -28,6 +28,8 @@ "gaia_auth_fetcher_ios.mm", "gaia_auth_fetcher_ios_bridge.h", "gaia_auth_fetcher_ios_bridge.mm", + "gaia_auth_fetcher_ios_ns_url_session_bridge.h", + "gaia_auth_fetcher_ios_ns_url_session_bridge.mm", "gaia_auth_fetcher_ios_wk_webview_bridge.h", "gaia_auth_fetcher_ios_wk_webview_bridge.mm", "gaia_cookie_manager_service_factory.cc", @@ -82,6 +84,7 @@ "//ios/chrome/browser/reading_list:reading_list_remover", "//ios/chrome/browser/ui/commands", "//ios/chrome/common", + "//ios/net", "//ios/public/provider/chrome/browser", "//ios/public/provider/chrome/browser/signin", "//ios/web", @@ -142,10 +145,12 @@ sources = [ "authentication_service_unittest.mm", "chrome_identity_service_observer_bridge_unittest.mm", + "gaia_auth_fetcher_ios_ns_url_session_bridge_unittests.mm", "gaia_auth_fetcher_ios_unittest.mm", "signin_browser_state_info_updater_unittest.mm", ] deps = [ + ":feature_flags", ":signin", ":test_support", "//base", @@ -166,7 +171,9 @@ "//ios/chrome/browser/prefs:browser_prefs", "//ios/chrome/browser/sync", "//ios/chrome/browser/sync:test_support", + "//ios/chrome/browser/web:test_support", "//ios/chrome/test:test_support", + "//ios/net", "//ios/public/provider/chrome/browser", "//ios/public/provider/chrome/browser/signin", "//ios/public/provider/chrome/browser/signin:test_support",
diff --git a/ios/chrome/browser/signin/fake_gaia_cookie_manager_service_builder.cc b/ios/chrome/browser/signin/fake_gaia_cookie_manager_service_builder.cc index 15baf57..b60be54 100644 --- a/ios/chrome/browser/signin/fake_gaia_cookie_manager_service_builder.cc +++ b/ios/chrome/browser/signin/fake_gaia_cookie_manager_service_builder.cc
@@ -14,7 +14,7 @@ std::unique_ptr<KeyedService> BuildFakeGaiaCookieManagerService( web::BrowserState* browser_state) { return BuildFakeGaiaCookieManagerServiceWithOptions( - /*create_fake_url_loader_factory_for_cookie_requests=*/true, + /*create_fake_url_loader_factory_for_cookie_requests=*/false, browser_state); }
diff --git a/ios/chrome/browser/signin/feature_flags.h b/ios/chrome/browser/signin/feature_flags.h index 51a6d633..3d96312 100644 --- a/ios/chrome/browser/signin/feature_flags.h +++ b/ios/chrome/browser/signin/feature_flags.h
@@ -10,6 +10,9 @@ // Feature flag to enable WKWebView in SSO. extern const base::Feature kSSOWithWKWebView; +// Feature flag to enable NSURLSession for GAIAAuthFetcherIOS. +extern const base::Feature kUseNSURLSessionForGaiaSigninRequests; + // Returns true if the WKWebView should be enabled in SSO. bool ShouldEnableWKWebViewWithSSO();
diff --git a/ios/chrome/browser/signin/feature_flags.mm b/ios/chrome/browser/signin/feature_flags.mm index 3c6b4aaf2..e459a6e 100644 --- a/ios/chrome/browser/signin/feature_flags.mm +++ b/ios/chrome/browser/signin/feature_flags.mm
@@ -13,6 +13,9 @@ const base::Feature kSSOWithWKWebView{"SSOWithWKWebView", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kUseNSURLSessionForGaiaSigninRequests{ + "UseNSURLSessionForGaiaSigninRequests", base::FEATURE_ENABLED_BY_DEFAULT}; + bool ShouldEnableWKWebViewWithSSO() { if (!base::ios::IsRunningOnIOS12OrLater()) return false;
diff --git a/ios/chrome/browser/signin/gaia_auth_fetcher_ios.mm b/ios/chrome/browser/signin/gaia_auth_fetcher_ios.mm index 35ac343..9447cfc8 100644 --- a/ios/chrome/browser/signin/gaia_auth_fetcher_ios.mm +++ b/ios/chrome/browser/signin/gaia_auth_fetcher_ios.mm
@@ -8,8 +8,11 @@ #include "base/logging.h" #import "base/mac/foundation_util.h" +#include "ios/chrome/browser/signin/feature_flags.h" +#import "ios/chrome/browser/signin/gaia_auth_fetcher_ios_ns_url_session_bridge.h" #include "ios/chrome/browser/signin/gaia_auth_fetcher_ios_wk_webview_bridge.h" #include "ios/web/public/browser_state.h" +#include "ios/web/public/features.h" #include "net/base/load_flags.h" #include "services/network/public/cpp/shared_url_loader_factory.h" @@ -30,8 +33,18 @@ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, web::BrowserState* browser_state) : GaiaAuthFetcher(consumer, source, url_loader_factory), - bridge_(new GaiaAuthFetcherIOSWKWebViewBridge(this, browser_state)), - browser_state_(browser_state) {} + browser_state_(browser_state) { + if (base::FeatureList::IsEnabled(web::features::kWKHTTPSystemCookieStore) && + base::FeatureList::IsEnabled(kUseNSURLSessionForGaiaSigninRequests)) { + // GaiaAuthFetcherIOSNSURLSessionBridge can only work with + // kWKHTTPSystemCookieStore is enabled. + // See http://crbug.com/902584 + bridge_.reset( + new GaiaAuthFetcherIOSNSURLSessionBridge(this, browser_state)); + } else { + bridge_.reset(new GaiaAuthFetcherIOSWKWebViewBridge(this, browser_state)); + } +} GaiaAuthFetcherIOS::~GaiaAuthFetcherIOS() {}
diff --git a/ios/chrome/browser/signin/gaia_auth_fetcher_ios_ns_url_session_bridge.h b/ios/chrome/browser/signin/gaia_auth_fetcher_ios_ns_url_session_bridge.h new file mode 100644 index 0000000..cd87540 --- /dev/null +++ b/ios/chrome/browser/signin/gaia_auth_fetcher_ios_ns_url_session_bridge.h
@@ -0,0 +1,58 @@ +// 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_SIGNIN_GAIA_AUTH_FETCHER_IOS_NS_URL_SESSION_BRIDGE_H_ +#define IOS_CHROME_BROWSER_SIGNIN_GAIA_AUTH_FETCHER_IOS_NS_URL_SESSION_BRIDGE_H_ + +#import <Foundation/Foundation.h> + +#include "ios/chrome/browser/signin/gaia_auth_fetcher_ios_bridge.h" +#include "net/cookies/canonical_cookie.h" + +class GaiaAuthFetcherIOSNSURLSessionBridge; +@class GaiaAuthFetcherIOSURLSessionDelegate; +@class NSHTTPURLResponse; +@class NSURLSession; + +// Specialization of GaiaAuthFetcher on iOS, using NSURLSession to send +// requests. This class can only be used when those 2 flags are enabbled: +// + kUseNSURLSessionForGaiaSigninRequests +// + web::features::kWKHTTPSystemCookieStore +class GaiaAuthFetcherIOSNSURLSessionBridge : public GaiaAuthFetcherIOSBridge { + public: + GaiaAuthFetcherIOSNSURLSessionBridge( + GaiaAuthFetcherIOSBridge::GaiaAuthFetcherIOSBridgeDelegate* delegate, + web::BrowserState* browser_state); + ~GaiaAuthFetcherIOSNSURLSessionBridge() override; + + // GaiaAuthFetcherIOSBridge. + void Cancel() override; + + // Set cookies from |response| in SystemCookieStore asynchronously. + void SetCanonicalCookiesFromResponse(NSHTTPURLResponse* response); + + private: + friend class GaiaAuthFetcherIOSNSURLSessionBridgeTest; + + // GaiaAuthFetcherIOSBridge. + void FetchPendingRequest() override; + + // Starts the NSURLRequest with the cookie list. + void FetchPendingRequestWithCookies( + const std::vector<net::CanonicalCookie>& cookies); + // Creates a NSURLSession, and sets its delegate. + virtual NSURLSession* CreateNSURLSession( + id<NSURLSessionTaskDelegate> url_session_delegate); + + // Fetcher which makes requests to Gaia with NSURLSession. + GaiaAuthFetcherIOSURLSessionDelegate* url_session_delegate_; + // Session to send the NSURLRequest. + NSURLSession* url_session_; + // Task to send the NSURLRequest. + NSURLSessionDataTask* url_session_data_task_; + + DISALLOW_COPY_AND_ASSIGN(GaiaAuthFetcherIOSNSURLSessionBridge); +}; + +#endif // IOS_CHROME_BROWSER_SIGNIN_GAIA_AUTH_FETCHER_IOS_NS_URL_SESSION_BRIDGE_H_
diff --git a/ios/chrome/browser/signin/gaia_auth_fetcher_ios_ns_url_session_bridge.mm b/ios/chrome/browser/signin/gaia_auth_fetcher_ios_ns_url_session_bridge.mm new file mode 100644 index 0000000..0c3b14e --- /dev/null +++ b/ios/chrome/browser/signin/gaia_auth_fetcher_ios_ns_url_session_bridge.mm
@@ -0,0 +1,159 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/signin/gaia_auth_fetcher_ios_ns_url_session_bridge.h" + +#import <Foundation/Foundation.h> + +#include "base/mac/foundation_util.h" +#include "base/strings/sys_string_conversions.h" +#include "ios/chrome/browser/signin/feature_flags.h" +#include "ios/net/cookies/system_cookie_util.h" +#include "ios/web/public/browser_state.h" +#include "ios/web/public/features.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@interface GaiaAuthFetcherIOSURLSessionDelegate + : NSObject <NSURLSessionTaskDelegate> + +// Gaia auth fetcher bridge. +@property(nonatomic, assign) GaiaAuthFetcherIOSNSURLSessionBridge* bridge; +// Session for the multilogin request. +@property(nonatomic, strong) NSURLSession* requestSession; + +@end + +@implementation GaiaAuthFetcherIOSURLSessionDelegate + +@synthesize bridge = _bridge; +@synthesize requestSession = _requestSession; + +#pragma mark - NSURLSessionTaskDelegate + +- (void)URLSession:(NSURLSession*)session + task:(NSURLSessionTask*)task + willPerformHTTPRedirection:(NSHTTPURLResponse*)response + newRequest:(NSURLRequest*)request + completionHandler:(void (^)(NSURLRequest*))completionHandler { + // If there is a redirect, the cookies from the redirect need to be stored. + DCHECK(self.requestSession == session); + if (self.bridge) { + self.bridge->SetCanonicalCookiesFromResponse(response); + completionHandler(request); + } else { + // No need to continue the redirect if there is no more bridge instance. + completionHandler(NULL); + } +} + +#pragma mark - Private + +- (void)requestCompletedWithData:(NSData*)data + response:(NSURLResponse*)response + error:(NSError*)error { + if (!self.bridge) + return; + NSHTTPURLResponse* responseWithHeaders = + base::mac::ObjCCastStrict<NSHTTPURLResponse>(response); + if (error) { + self.bridge->OnURLFetchFailure(net::ERR_FAILED, + responseWithHeaders.statusCode); + } else { + self.bridge->SetCanonicalCookiesFromResponse(responseWithHeaders); + NSString* result = [[NSString alloc] initWithData:data + encoding:NSUTF8StringEncoding]; + self.bridge->OnURLFetchSuccess(base::SysNSStringToUTF8(result), + responseWithHeaders.statusCode); + } +} + +@end + +GaiaAuthFetcherIOSNSURLSessionBridge::GaiaAuthFetcherIOSNSURLSessionBridge( + GaiaAuthFetcherIOSBridge::GaiaAuthFetcherIOSBridgeDelegate* delegate, + web::BrowserState* browser_state) + : GaiaAuthFetcherIOSBridge(delegate, browser_state) { + DCHECK(base::FeatureList::IsEnabled(kUseNSURLSessionForGaiaSigninRequests)); + DCHECK(base::FeatureList::IsEnabled(web::features::kWKHTTPSystemCookieStore)); + url_session_delegate_ = [[GaiaAuthFetcherIOSURLSessionDelegate alloc] init]; + url_session_delegate_.bridge = this; +} + +GaiaAuthFetcherIOSNSURLSessionBridge::~GaiaAuthFetcherIOSNSURLSessionBridge() { + url_session_delegate_.bridge = nullptr; +} + +void GaiaAuthFetcherIOSNSURLSessionBridge::FetchPendingRequest() { + network::mojom::CookieManager* cookie_manager = + GetBrowserState()->GetCookieManager(); + net::CookieOptions options; + options.set_include_httponly(); + options.set_same_site_cookie_mode( + net::CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX); + cookie_manager->GetCookieList( + GetRequest().url, options, + base::BindOnce( + &GaiaAuthFetcherIOSNSURLSessionBridge::FetchPendingRequestWithCookies, + base::Unretained(this))); +} + +void GaiaAuthFetcherIOSNSURLSessionBridge::Cancel() { + [url_session_data_task_ cancel]; + OnURLFetchFailure(net::ERR_ABORTED, 0); +} + +void GaiaAuthFetcherIOSNSURLSessionBridge::SetCanonicalCookiesFromResponse( + NSHTTPURLResponse* response) { + NSArray* cookies = + [NSHTTPCookie cookiesWithResponseHeaderFields:response.allHeaderFields + forURL:response.URL]; + network::mojom::CookieManager* cookie_manager = + GetBrowserState()->GetCookieManager(); + for (NSHTTPCookie* cookie : cookies) { + cookie_manager->SetCanonicalCookie( + net::CanonicalCookieFromSystemCookie(cookie, base::Time::Now()), + /*secure_source=*/true, + /*modify_http_only=*/true, base::DoNothing()); + } +} + +void GaiaAuthFetcherIOSNSURLSessionBridge::FetchPendingRequestWithCookies( + const std::vector<net::CanonicalCookie>& cookies) { + DCHECK(!url_session_); + url_session_ = CreateNSURLSession(url_session_delegate_); + url_session_delegate_.requestSession = url_session_; + DCHECK(!url_session_data_task_); + __weak __typeof(url_session_delegate_) weakDelegate = url_session_delegate_; + url_session_data_task_ = + [url_session_ dataTaskWithRequest:GetNSURLRequest() + completionHandler:^(NSData* data, NSURLResponse* response, + NSError* error) { + [weakDelegate requestCompletedWithData:data + response:response + error:error]; + }]; + NSMutableArray* http_cookies = + [[NSMutableArray alloc] initWithCapacity:cookies.size()]; + for (const net::CanonicalCookie& cookie : cookies) { + [http_cookies addObject:net::SystemCookieFromCanonicalCookie(cookie)]; + } + [url_session_.configuration.HTTPCookieStorage + storeCookies:http_cookies + forTask:url_session_data_task_]; + + [url_session_data_task_ resume]; +} + +NSURLSession* GaiaAuthFetcherIOSNSURLSessionBridge::CreateNSURLSession( + id<NSURLSessionTaskDelegate> url_session_delegate) { + NSURLSessionConfiguration* session_configuration = + NSURLSessionConfiguration.ephemeralSessionConfiguration; + session_configuration.HTTPShouldSetCookies = YES; + return [NSURLSession sessionWithConfiguration:session_configuration + delegate:url_session_delegate + delegateQueue:NSOperationQueue.mainQueue]; +}
diff --git a/ios/chrome/browser/signin/gaia_auth_fetcher_ios_ns_url_session_bridge_unittests.mm b/ios/chrome/browser/signin/gaia_auth_fetcher_ios_ns_url_session_bridge_unittests.mm new file mode 100644 index 0000000..b945710 --- /dev/null +++ b/ios/chrome/browser/signin/gaia_auth_fetcher_ios_ns_url_session_bridge_unittests.mm
@@ -0,0 +1,433 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/signin/gaia_auth_fetcher_ios_ns_url_session_bridge.h" + +#import <Foundation/Foundation.h> + +#include "base/test/scoped_feature_list.h" +#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" +#include "ios/chrome/browser/signin/feature_flags.h" +#include "ios/chrome/browser/signin/gaia_auth_fetcher_ios_bridge.h" +#import "ios/chrome/browser/web/chrome_web_test.h" +#include "ios/net/cookies/system_cookie_util.h" +#include "ios/web/public/features.h" +#include "ios/web/public/test/test_web_thread_bundle.h" +#include "net/cookies/cookie_store.h" +#include "testing/platform_test.h" +#import "third_party/ocmock/OCMock/OCMock.h" +#include "third_party/ocmock/gtest_support.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +typedef void (^DataTaskWithRequestCompletionHandler)( + NSData* _Nullable data, + NSURLResponse* _Nullable response, + NSError* _Nullable error); + +class GaiaAuthFetcherIOSNSURLSessionBridgeTest; + +namespace { + +NSString* GetStringWithNSHTTPCookie(NSHTTPCookie* cookie) { + return [NSString stringWithFormat:@"%@=%@; path=%@; domain=%@", cookie.name, + cookie.value, cookie.path, cookie.domain]; +} + +NSString* GetStringWithCanonicalCookie(net::CanonicalCookie cookie) { + return [NSString + stringWithFormat:@"%s=%s; path=%s; domain=%s", cookie.Name().c_str(), + cookie.Value().c_str(), cookie.Path().c_str(), + cookie.Domain().c_str()]; +} + +// Delegate classe to test GaiaAuthFetcherIOSNSURLSessionBridge. +class FakeGaiaAuthFetcherIOSBridgeDelegate + : public GaiaAuthFetcherIOSBridge::GaiaAuthFetcherIOSBridgeDelegate { + public: + FakeGaiaAuthFetcherIOSBridgeDelegate() + : GaiaAuthFetcherIOSBridge::GaiaAuthFetcherIOSBridgeDelegate(), + fetch_complete_called_(false){}; + + ~FakeGaiaAuthFetcherIOSBridgeDelegate() override{}; + + // GaiaAuthFetcherIOSBridge::GaiaAuthFetcherIOSBridgeDelegate. + void OnFetchComplete(const GURL& url, + const std::string& data, + const net::URLRequestStatus& status, + int response_code) override { + EXPECT_FALSE(fetch_complete_called_); + fetch_complete_called_ = true; + url_ = url; + data_ = data; + status_ = status; + response_code_ = response_code; + }; + + // Returns true if has been called(). + bool GetFetchCompleteCalled() { return fetch_complete_called_; }; + + // Returns |url| from FetchComplete(). + const GURL& GetURL() { return url_; }; + + // Returns |data| from FetchComplete(). + const std::string& GetData() { return data_; }; + + // Returns |status| from FetchComplete(). + net::URLRequestStatus GetStatus() { return status_; }; + + // Returns |response_code| from FetchComplete(). + int GetResponseCode() { return response_code_; }; + + private: + // true if has been called(). + bool fetch_complete_called_; + // |url| from FetchComplete(). + GURL url_; + // |data| from FetchComplete(). + std::string data_; + // |status| from FetchComplete(). + net::URLRequestStatus status_; + // |response_code| from FetchComplete(). + int response_code_; +}; + +class TestGaiaAuthFetcherIOSNSURLSessionBridge + : public GaiaAuthFetcherIOSNSURLSessionBridge { + public: + TestGaiaAuthFetcherIOSNSURLSessionBridge( + GaiaAuthFetcherIOSBridge::GaiaAuthFetcherIOSBridgeDelegate* delegate, + web::BrowserState* browser_state, + GaiaAuthFetcherIOSNSURLSessionBridgeTest* test); + + // GaiaAuthFetcherIOSNSURLSessionBridge. + NSURLSession* CreateNSURLSession( + id<NSURLSessionTaskDelegate> url_session_delegate) override; + + protected: + GaiaAuthFetcherIOSNSURLSessionBridgeTest* test_; +}; + +} // namespace + +class GaiaAuthFetcherIOSNSURLSessionBridgeTest : public ChromeWebTest { + protected: + // ChromeWebTest. + void SetUp() override; + void TearDown() override; + + // Create a NSURLSession mock, and saves its delegate. + NSURLSession* CreateNSURLSession( + id<NSURLSessionTaskDelegate> url_session_delegate); + + void ExpectCookies(NSArray<NSHTTPCookie*>* cookies); + + void AllCookies(const std::vector<net::CanonicalCookie>& all_cookies); + + void AddCookiesToCookieManager(NSArray<NSHTTPCookie*>* cookies); + + std::string GetCookieDomain() { return std::string("example.com"); }; + GURL GetFetchGURL() { return GURL("http://www." + GetCookieDomain()); }; + + NSHTTPCookie* GetCookie1(); + + NSHTTPCookie* GetCookie2(); + + NSHTTPURLResponse* CreateHTTPURLResponse(int status_code, + NSArray<NSHTTPCookie*>* cookies); + + NSDictionary* GetHeaderFieldsWithCookies(NSArray<NSHTTPCookie*>* cookies); + + friend TestGaiaAuthFetcherIOSNSURLSessionBridge; + + // kWKHTTPSystemCookieStore and kUseNSURLSessionForGaiaSigninRequests should + // be enabled. + base::test::ScopedFeatureList scoped_feature_list; + // Browser state for the tests. + std::unique_ptr<ios::ChromeBrowserState> browser_state_; + // Instance used for the tests. + std::unique_ptr<TestGaiaAuthFetcherIOSNSURLSessionBridge> + ns_url_session_bridge_; + // Fake delegate for |ns_url_session_bridge_|. + std::unique_ptr<FakeGaiaAuthFetcherIOSBridgeDelegate> delegate_; + // Cookies returned by the cookie manager. + std::vector<net::CanonicalCookie> all_cookies_; + // Delegate for |url_session_mock_|, provided by |ns_url_session_bridge_|. + id<NSURLSessionTaskDelegate> url_session_delegate_; + + NSHTTPCookieStorage* http_cookie_storage_mock_; + NSURLSession* url_session_mock_; + NSURLSessionDataTask* url_session_data_task_mock_; + NSURLSessionConfiguration* url_session_configuration_mock_; + DataTaskWithRequestCompletionHandler completion_handler_; +}; + +#pragma mark - TestGaiaAuthFetcherIOSNSURLSessionBridge + +TestGaiaAuthFetcherIOSNSURLSessionBridge:: + TestGaiaAuthFetcherIOSNSURLSessionBridge( + GaiaAuthFetcherIOSBridge::GaiaAuthFetcherIOSBridgeDelegate* delegate, + web::BrowserState* browser_state, + GaiaAuthFetcherIOSNSURLSessionBridgeTest* test) + : GaiaAuthFetcherIOSNSURLSessionBridge(delegate, browser_state), + test_(test) {} + +NSURLSession* TestGaiaAuthFetcherIOSNSURLSessionBridge::CreateNSURLSession( + id<NSURLSessionTaskDelegate> url_session_delegate) { + return test_->CreateNSURLSession(url_session_delegate); +} + +#pragma mark - GaiaAuthFetcherIOSNSURLSessionBridgeTest + +void GaiaAuthFetcherIOSNSURLSessionBridgeTest::SetUp() { + std::vector<base::Feature> enabled_features; + std::vector<base::Feature> disabled_features; + enabled_features.push_back(web::features::kWKHTTPSystemCookieStore); + enabled_features.push_back(kUseNSURLSessionForGaiaSigninRequests); + scoped_feature_list.InitWithFeatures(enabled_features, disabled_features); + delegate_.reset(new FakeGaiaAuthFetcherIOSBridgeDelegate()); + browser_state_ = TestChromeBrowserState::Builder().Build(); + ns_url_session_bridge_.reset(new TestGaiaAuthFetcherIOSNSURLSessionBridge( + delegate_.get(), browser_state_.get(), this)); + http_cookie_storage_mock_ = OCMStrictClassMock([NSHTTPCookieStorage class]); + url_session_configuration_mock_ = + OCMStrictClassMock(NSClassFromString(@"__NSCFURLSessionConfiguration")); + OCMStub([url_session_configuration_mock_ HTTPCookieStorage]) + .andReturn(http_cookie_storage_mock_); + url_session_mock_ = OCMStrictClassMock([NSURLSession class]); + OCMStub([url_session_mock_ configuration]) + .andReturn(url_session_configuration_mock_); + url_session_data_task_mock_ = + OCMStrictClassMock([NSURLSessionDataTask class]); + OCMExpect([url_session_data_task_mock_ resume]); + completion_handler_ = nil; +} + +void GaiaAuthFetcherIOSNSURLSessionBridgeTest::TearDown() { + ASSERT_OCMOCK_VERIFY((id)http_cookie_storage_mock_); + ASSERT_OCMOCK_VERIFY((id)url_session_mock_); + ASSERT_OCMOCK_VERIFY((id)url_session_data_task_mock_); + ASSERT_OCMOCK_VERIFY((id)url_session_configuration_mock_); +} + +NSURLSession* GaiaAuthFetcherIOSNSURLSessionBridgeTest::CreateNSURLSession( + id<NSURLSessionTaskDelegate> url_session_delegate) { + url_session_delegate_ = url_session_delegate; + id completion_handler = [OCMArg checkWithBlock:^BOOL(id value) { + DCHECK(!completion_handler_); + completion_handler_ = [value copy]; + return YES; + }]; + OCMExpect([url_session_mock_ + dataTaskWithRequest:ns_url_session_bridge_->GetNSURLRequest() + completionHandler:completion_handler]) + .andReturn(url_session_data_task_mock_); + return url_session_mock_; +} + +void GaiaAuthFetcherIOSNSURLSessionBridgeTest::ExpectCookies( + NSArray<NSHTTPCookie*>* expected_cookies) { + network::mojom::CookieManager* cookie_manager = + browser_state_->GetCookieManager(); + cookie_manager->GetAllCookies( + base::BindOnce(&GaiaAuthFetcherIOSNSURLSessionBridgeTest::AllCookies, + base::Unretained(this))); + WaitForBackgroundTasks(); + NSMutableSet<NSString*>* expected_cookies_set = [NSMutableSet set]; + for (NSHTTPCookie* cookie in expected_cookies) { + [expected_cookies_set addObject:GetStringWithNSHTTPCookie(cookie)]; + } + NSMutableSet<NSString*>* cookies_set = [NSMutableSet set]; + for (net::CanonicalCookie cookie : all_cookies_) { + [cookies_set addObject:GetStringWithCanonicalCookie(cookie)]; + } + EXPECT_TRUE([expected_cookies_set isEqualToSet:cookies_set]); +} + +void GaiaAuthFetcherIOSNSURLSessionBridgeTest::AllCookies( + const std::vector<net::CanonicalCookie>& all_cookies) { + all_cookies_ = all_cookies; +} + +void GaiaAuthFetcherIOSNSURLSessionBridgeTest::AddCookiesToCookieManager( + NSArray<NSHTTPCookie*>* cookies) { + network::mojom::CookieManager* cookie_manager = + browser_state_->GetCookieManager(); + for (NSHTTPCookie* cookie in cookies) { + cookie_manager->SetCanonicalCookie( + net::CanonicalCookieFromSystemCookie(cookie, base::Time::Now()), + /*secure_source=*/true, + /*modify_http_only=*/true, base::DoNothing()); + } + WaitForBackgroundTasks(); +} + +NSHTTPCookie* GaiaAuthFetcherIOSNSURLSessionBridgeTest::GetCookie1() { + NSString* cookie_domain = + [NSString stringWithFormat:@".%s", GetCookieDomain().c_str()]; + return [NSHTTPCookie cookieWithProperties:@{ + NSHTTPCookiePath : @"/", + NSHTTPCookieName : @"COOKIE1", + NSHTTPCookieValue : @"VALUE1", + NSHTTPCookieDomain : cookie_domain, + }]; +} + +NSHTTPCookie* GaiaAuthFetcherIOSNSURLSessionBridgeTest::GetCookie2() { + NSString* cookie_domain = + [NSString stringWithFormat:@".%s", GetCookieDomain().c_str()]; + return [NSHTTPCookie cookieWithProperties:@{ + NSHTTPCookiePath : @"/", + NSHTTPCookieName : @"COOKIE2", + NSHTTPCookieValue : @"VALUE2", + NSHTTPCookieDomain : cookie_domain, + }]; +} + +NSHTTPURLResponse* +GaiaAuthFetcherIOSNSURLSessionBridgeTest::CreateHTTPURLResponse( + int status_code, + NSArray<NSHTTPCookie*>* cookies) { + NSString* url_string = + [NSString stringWithFormat:@"http://www.%s/", GetCookieDomain().c_str()]; + NSURL* url = [NSURL URLWithString:url_string]; + return [[NSHTTPURLResponse alloc] + initWithURL:url + statusCode:status_code + HTTPVersion:@"HTTP/1.1" + headerFields:GetHeaderFieldsWithCookies(cookies)]; +} + +NSDictionary* +GaiaAuthFetcherIOSNSURLSessionBridgeTest::GetHeaderFieldsWithCookies( + NSArray<NSHTTPCookie*>* cookies) { + NSMutableString* cookie_string = [NSMutableString string]; + for (NSHTTPCookie* cookie in cookies) { + if (cookie_string.length != 0) + [cookie_string appendString:@", "]; + [cookie_string appendString:GetStringWithNSHTTPCookie(cookie)]; + } + return @{@"Set-Cookie" : cookie_string}; +} + +#pragma mark - Tests + +// Tests to send a request with no cookies set in the cookie store and receive +// multiples cookies from the request. +TEST_F(GaiaAuthFetcherIOSNSURLSessionBridgeTest, FetchWithEmptyCookieStore) { + ns_url_session_bridge_->Fetch(GetFetchGURL(), "", "", false); + OCMExpect([http_cookie_storage_mock_ + storeCookies:@[] + forTask:url_session_data_task_mock_]); + WaitForBackgroundTasks(); + EXPECT_NE(nullptr, completion_handler_); + NSHTTPURLResponse* http_url_reponse = + CreateHTTPURLResponse(200, @[ GetCookie1(), GetCookie2() ]); + completion_handler_([@"Test" dataUsingEncoding:NSUTF8StringEncoding], + http_url_reponse, nil); + EXPECT_TRUE(delegate_->GetFetchCompleteCalled()); + EXPECT_EQ(delegate_->GetURL(), GetFetchGURL()); + EXPECT_EQ(delegate_->GetStatus().status(), net::URLRequestStatus::SUCCESS); + EXPECT_EQ(delegate_->GetResponseCode(), 200); + EXPECT_EQ(delegate_->GetData(), std::string("Test")); + ExpectCookies(@[ GetCookie1(), GetCookie2() ]); +} + +// Tests to send a request with one cookie set in the cookie store and receive +// another cookies from the request. +TEST_F(GaiaAuthFetcherIOSNSURLSessionBridgeTest, FetchWithCookieStore) { + NSArray* cookies_to_send = @[ GetCookie1() ]; + AddCookiesToCookieManager(cookies_to_send); + ns_url_session_bridge_->Fetch(GetFetchGURL(), "", "", false); + OCMExpect([http_cookie_storage_mock_ + storeCookies:cookies_to_send + forTask:url_session_data_task_mock_]); + WaitForBackgroundTasks(); + EXPECT_NE(nullptr, completion_handler_); + NSHTTPURLResponse* http_url_reponse = + CreateHTTPURLResponse(200, @[ GetCookie2() ]); + completion_handler_(nil, http_url_reponse, nil); + EXPECT_TRUE(delegate_->GetFetchCompleteCalled()); + EXPECT_EQ(delegate_->GetURL(), GetFetchGURL()); + EXPECT_EQ(delegate_->GetStatus().status(), net::URLRequestStatus::SUCCESS); + EXPECT_EQ(delegate_->GetResponseCode(), 200); + EXPECT_EQ(delegate_->GetData(), std::string()); + ExpectCookies(@[ GetCookie1(), GetCookie2() ]); +} + +// Tests to a request with a redirect. One cookie is received by the first +// request, and a second one by the redirected request. +TEST_F(GaiaAuthFetcherIOSNSURLSessionBridgeTest, FetchWithRedirect) { + ns_url_session_bridge_->Fetch(GetFetchGURL(), "", "", false); + OCMExpect([http_cookie_storage_mock_ + storeCookies:@[] + forTask:url_session_data_task_mock_]); + WaitForBackgroundTasks(); + EXPECT_NE(nullptr, completion_handler_); + NSURLRequest* redirected_url_request = + OCMStrictClassMock([NSURLRequest class]); + __block bool completion_handler_called = false; + void (^completion_handler)(NSURLRequest*) = ^(NSURLRequest* url_request) { + EXPECT_EQ(redirected_url_request, url_request); + completion_handler_called = true; + }; + NSHTTPURLResponse* redirected_url_response = + CreateHTTPURLResponse(301, @[ GetCookie1() ]); + [url_session_delegate_ URLSession:url_session_mock_ + task:url_session_data_task_mock_ + willPerformHTTPRedirection:redirected_url_response + newRequest:redirected_url_request + completionHandler:completion_handler]; + EXPECT_TRUE(completion_handler_called); + NSHTTPURLResponse* http_url_reponse = + CreateHTTPURLResponse(200, @[ GetCookie2() ]); + completion_handler_(nil, http_url_reponse, nil); + EXPECT_TRUE(delegate_->GetFetchCompleteCalled()); + EXPECT_EQ(delegate_->GetURL(), GetFetchGURL()); + EXPECT_EQ(delegate_->GetStatus().status(), net::URLRequestStatus::SUCCESS); + EXPECT_EQ(delegate_->GetResponseCode(), 200); + EXPECT_EQ(delegate_->GetData(), std::string()); + ExpectCookies(@[ GetCookie1(), GetCookie2() ]); + ASSERT_OCMOCK_VERIFY((id)redirected_url_request); +} + +// Tests to cancel the request. +TEST_F(GaiaAuthFetcherIOSNSURLSessionBridgeTest, FetchWithCancel) { + ns_url_session_bridge_->Fetch(GetFetchGURL(), "", "", false); + OCMExpect([http_cookie_storage_mock_ + storeCookies:@[] + forTask:url_session_data_task_mock_]); + WaitForBackgroundTasks(); + EXPECT_NE(nullptr, completion_handler_); + OCMExpect([url_session_data_task_mock_ cancel]); + ns_url_session_bridge_->Cancel(); + WaitForBackgroundTasks(); + EXPECT_TRUE(delegate_->GetFetchCompleteCalled()); + EXPECT_EQ(delegate_->GetURL(), GetFetchGURL()); + EXPECT_EQ(delegate_->GetStatus().status(), net::URLRequestStatus::CANCELED); + EXPECT_EQ(delegate_->GetResponseCode(), 0); + EXPECT_EQ(delegate_->GetData(), std::string()); +} + +// Tests a request with error. +TEST_F(GaiaAuthFetcherIOSNSURLSessionBridgeTest, FetchWithError) { + ns_url_session_bridge_->Fetch(GetFetchGURL(), "", "", false); + OCMExpect([http_cookie_storage_mock_ + storeCookies:@[] + forTask:url_session_data_task_mock_]); + WaitForBackgroundTasks(); + EXPECT_NE(nullptr, completion_handler_); + NSHTTPURLResponse* http_url_reponse = + CreateHTTPURLResponse(501, @[ GetCookie1(), GetCookie2() ]); + completion_handler_(nil, http_url_reponse, + [NSError errorWithDomain:@"test" code:1 userInfo:nil]); + EXPECT_TRUE(delegate_->GetFetchCompleteCalled()); + EXPECT_EQ(delegate_->GetURL(), GetFetchGURL()); + EXPECT_EQ(delegate_->GetStatus().status(), net::URLRequestStatus::FAILED); + EXPECT_EQ(delegate_->GetResponseCode(), 501); + EXPECT_EQ(delegate_->GetData(), std::string()); + ExpectCookies(@[]); +}
diff --git a/ios/chrome/browser/ui/authentication/re_signin_infobar_delegate.mm b/ios/chrome/browser/ui/authentication/re_signin_infobar_delegate.mm index 10062672..eac495d 100644 --- a/ios/chrome/browser/ui/authentication/re_signin_infobar_delegate.mm +++ b/ios/chrome/browser/ui/authentication/re_signin_infobar_delegate.mm
@@ -123,7 +123,7 @@ signin_metrics::RecordSigninUserActionForAccessPoint( signin_metrics::AccessPoint::ACCESS_POINT_RESIGNIN_INFOBAR, signin_metrics::PromoAction::PROMO_ACTION_NO_SIGNIN_PROMO); - DCHECK(static_cast<InfoBarIOS*>(infobar())->view()); + DCHECK(static_cast<InfoBarIOS*>(infobar())->View()); ShowSigninCommand* command = [[ShowSigninCommand alloc] initWithOperation:AUTHENTICATION_OPERATION_REAUTHENTICATE accessPoint:signin_metrics::AccessPoint::
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_address_cell.mm b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_address_cell.mm index aa807c6..8a14b65 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_address_cell.mm +++ b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_address_cell.mm
@@ -454,6 +454,10 @@ AppendHorizontalConstraintsForViews(staticConstraints, @[ self.emailAddressButton ], guide); + // Without this set, Voice Over will read the content vertically instead of + // horizontally. + self.contentView.shouldGroupAccessibilityChildren = YES; + [NSLayoutConstraint activateConstraints:staticConstraints]; }
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_card_cell.mm b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_card_cell.mm index d0fe1bb..7726b45e 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_card_cell.mm +++ b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_card_cell.mm
@@ -218,6 +218,10 @@ ], self.contentView); + // Without this set, Voice Over will read the content vertically instead of + // horizontally. + self.contentView.shouldGroupAccessibilityChildren = YES; + [NSLayoutConstraint activateConstraints:staticConstraints]; }
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_content_delegate.h b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_content_delegate.h index a990f01..d2a46dd 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_content_delegate.h +++ b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_content_delegate.h
@@ -33,6 +33,9 @@ passwordField:(BOOL)passwordField requiresHTTPS:(BOOL)requiresHTTPS; +// Generate and offer to user a password that matches current form. +- (void)generateAndOfferPassword; + @end #endif // IOS_CHROME_BROWSER_UI_AUTOFILL_MANUAL_FILL_MANUAL_FILL_CONTENT_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_injection_handler.mm b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_injection_handler.mm index 7928bc1..110c9f3 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_injection_handler.mm +++ b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_injection_handler.mm
@@ -18,6 +18,7 @@ #import "components/autofill/ios/form_util/form_activity_observer_bridge.h" #include "components/autofill/ios/form_util/form_activity_params.h" #import "ios/chrome/browser/autofill/form_input_accessory_view_handler.h" +#import "ios/chrome/browser/passwords/password_tab_helper.h" #import "ios/chrome/browser/ui/autofill/manual_fill/form_observer_helper.h" #import "ios/chrome/browser/web_state_list/web_state_list.h" #include "ios/chrome/grit/ios_strings.h" @@ -67,6 +68,9 @@ // The last seen focused element identifier. @property(nonatomic, assign) std::string lastFocusedElementIdentifier; +// The form name of the last seen focused element. +@property(nonatomic, assign) std::string lastFocusedFormName; + // The view controller this object was initialized with. @property(weak, nonatomic, nullable, readonly) UIViewController* baseViewController; @@ -120,6 +124,12 @@ } } +- (void)generateAndOfferPassword { + web::WebState* webState = self.webStateList->GetActiveWebState(); + PasswordTabHelper::FromWebState(webState)->GenerateAndOfferPassword( + base::SysUTF8ToNSString(self.lastFocusedFormName)); +} + #pragma mark - FormActivityObserver - (void)webState:(web::WebState*)webState @@ -132,6 +142,7 @@ autofill::IsContextSecureForWebState(webState); self.lastFocusedElementPasswordField = params.field_type == "password"; self.lastFocusedElementIdentifier = params.field_identifier; + self.lastFocusedFormName = params.form_name; if (autofill::switches::IsAutofillIFrameMessagingEnabled()) { DCHECK(frame); self.lastFocusedElementFrameIdentifier = frame->GetFrameId();
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/password_mediator.h b/ios/chrome/browser/ui/autofill/manual_fill/password_mediator.h index a414521..e52bc292 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/password_mediator.h +++ b/ios/chrome/browser/ui/autofill/manual_fill/password_mediator.h
@@ -23,6 +23,7 @@ extern NSString* const ManagePasswordsAccessibilityIdentifier; extern NSString* const OtherPasswordsAccessibilityIdentifier; +extern NSString* const SuggestPasswordAccessibilityIdentifier; } // namespace manual_fill
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/password_mediator.mm b/ios/chrome/browser/ui/autofill/manual_fill/password_mediator.mm index 3bdd6c1..ec91bdd 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/password_mediator.mm +++ b/ios/chrome/browser/ui/autofill/manual_fill/password_mediator.mm
@@ -10,6 +10,7 @@ #include "base/strings/sys_string_conversions.h" #include "components/password_manager/core/browser/password_store.h" #import "ios/chrome/browser/autofill/manual_fill/passwords_fetcher.h" +#include "ios/chrome/browser/experimental_flags.h" #import "ios/chrome/browser/ui/autofill/manual_fill/action_cell.h" #import "ios/chrome/browser/ui/autofill/manual_fill/credential.h" #import "ios/chrome/browser/ui/autofill/manual_fill/credential_password_form.h" @@ -36,6 +37,8 @@ @"kManualFillManagePasswordsAccessibilityIdentifier"; NSString* const OtherPasswordsAccessibilityIdentifier = @"kManualFillOtherPasswordsAccessibilityIdentifier"; +NSString* const SuggestPasswordAccessibilityIdentifier = + @"kManualFillSuggestPasswordAccessibilityIdentifier"; } // namespace manual_fill @@ -203,19 +206,42 @@ return; } if (self.isAllPasswordButtonEnabled) { - NSString* otherPasswordsTitleString = l10n_util::GetNSString( - IDS_IOS_MANUAL_FALLBACK_USE_OTHER_PASSWORD_WITH_DOTS); + NSMutableArray<ManualFillActionItem*>* actions = + [[NSMutableArray alloc] init]; __weak __typeof(self) weakSelf = self; - auto otherPasswordsItem = [[ManualFillActionItem alloc] - initWithTitle:otherPasswordsTitleString - action:^{ - base::RecordAction(base::UserMetricsAction( - "ManualFallback_Password_OpenOtherPassword")); - [weakSelf.navigationDelegate openAllPasswordsList]; - }]; - otherPasswordsItem.accessibilityIdentifier = - manual_fill::OtherPasswordsAccessibilityIdentifier; + if (experimental_flags::IsAutomaticPasswordGenerationEnabled() && + [self.contentDelegate canUserInjectInPasswordField:YES + requiresHTTPS:YES]) { + NSString* generatePasswordTitleString = + l10n_util::GetNSString(IDS_IOS_SUGGEST_PASSWORD); + auto generatePasswordItem = [[ManualFillActionItem alloc] + initWithTitle:generatePasswordTitleString + action:^{ + base::RecordAction(base::UserMetricsAction( + "ManualFallback_Password_OpenSuggestPassword")); + [self generateAndOfferPassword]; + }]; + generatePasswordItem.accessibilityIdentifier = + manual_fill::SuggestPasswordAccessibilityIdentifier; + [actions addObject:generatePasswordItem]; + } + + // TODO(crbug.com/908776): fix or wait until iOS 11.2- is deprecated. + if (@available(iOS 11.3, *)) { + NSString* otherPasswordsTitleString = l10n_util::GetNSString( + IDS_IOS_MANUAL_FALLBACK_USE_OTHER_PASSWORD_WITH_DOTS); + auto otherPasswordsItem = [[ManualFillActionItem alloc] + initWithTitle:otherPasswordsTitleString + action:^{ + base::RecordAction(base::UserMetricsAction( + "ManualFallback_Password_OpenOtherPassword")); + [weakSelf.navigationDelegate openAllPasswordsList]; + }]; + otherPasswordsItem.accessibilityIdentifier = + manual_fill::OtherPasswordsAccessibilityIdentifier; + [actions addObject:otherPasswordsItem]; + } NSString* managePasswordsTitle = l10n_util::GetNSString(IDS_IOS_MANUAL_FALLBACK_MANAGE_PASSWORDS); @@ -228,13 +254,9 @@ }]; managePasswordsItem.accessibilityIdentifier = manual_fill::ManagePasswordsAccessibilityIdentifier; - if (@available(iOS 11.3, *)) { - [self.consumer - presentActions:@[ otherPasswordsItem, managePasswordsItem ]]; - } else { - // TODO(crbug.com/908776): fix or wait until iOS 11.2- is deprecated. - [self.consumer presentActions:@[ managePasswordsItem ]]; - } + [actions addObject:managePasswordsItem]; + + [self.consumer presentActions:actions]; } else { [self.consumer presentActions:@[]]; } @@ -273,4 +295,8 @@ requiresHTTPS:requiresHTTPS]; } +- (void)generateAndOfferPassword { + [self.contentDelegate generateAndOfferPassword]; +} + @end
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm index f8fb2f4b7..1324596 100644 --- a/ios/chrome/browser/ui/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -4096,7 +4096,7 @@ return; [self.dispatcher openURLInNewTab:[OpenNewTabCommand command]]; - [self restoreTabWithSessionID:entry->id]; + RestoreTab(entry->id, WindowOpenDisposition::CURRENT_TAB, self.browserState); } #pragma mark - MainContentUI @@ -4275,17 +4275,6 @@ sessionTab->navigations)); } -- (void)restoreTabWithSessionID:(const SessionID)sessionID { - TabRestoreServiceDelegateImplIOS* delegate = - TabRestoreServiceDelegateImplIOSFactory::GetForBrowserState( - self.browserState); - sessions::TabRestoreService* restoreService = - IOSChromeTabRestoreServiceFactory::GetForBrowserState( - self.browserState->GetOriginalChromeBrowserState()); - restoreService->RestoreEntryById(delegate, sessionID, - WindowOpenDisposition::CURRENT_TAB); -} - #pragma mark - UrlLoader helpers // Opens a new tab in the current mode, following |command| parameters. The
diff --git a/ios/chrome/browser/ui/infobars/BUILD.gn b/ios/chrome/browser/ui/infobars/BUILD.gn index 4f1621e..118130c 100644 --- a/ios/chrome/browser/ui/infobars/BUILD.gn +++ b/ios/chrome/browser/ui/infobars/BUILD.gn
@@ -14,7 +14,7 @@ ":infobars_ui", ":public", "//base", - "//ios/chrome/browser/download", + "//ios/chrome/browser", "//ios/chrome/browser/infobars", "//ios/chrome/browser/tabs", "//ios/chrome/browser/translate", @@ -55,6 +55,9 @@ "infobar_constants.h", "infobar_constants.mm", "infobar_container_consumer.h", + "infobar_container_view_controller.h", + "infobar_container_view_controller.mm", + "infobar_ui_delegate.h", "legacy_infobar_container_view_controller.h", "legacy_infobar_container_view_controller.mm", ]
diff --git a/ios/chrome/browser/ui/infobars/confirm_infobar/BUILD.gn b/ios/chrome/browser/ui/infobars/confirm_infobar/BUILD.gn new file mode 100644 index 0000000..b349587 --- /dev/null +++ b/ios/chrome/browser/ui/infobars/confirm_infobar/BUILD.gn
@@ -0,0 +1,16 @@ +# 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. + +source_set("confirm_infobar") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ + "confirm_infobar_view_controller.h", + "confirm_infobar_view_controller.mm", + ] + deps = [ + "//base", + "//components/infobars/core", + "//ios/chrome/browser/ui/infobars:infobars_ui", + ] +}
diff --git a/ios/chrome/browser/ui/infobars/confirm_infobar/confirm_infobar_view_controller.h b/ios/chrome/browser/ui/infobars/confirm_infobar/confirm_infobar_view_controller.h new file mode 100644 index 0000000..001d5bc5 --- /dev/null +++ b/ios/chrome/browser/ui/infobars/confirm_infobar/confirm_infobar_view_controller.h
@@ -0,0 +1,28 @@ +// 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_INFOBARS_CONFIRM_INFOBAR_CONFIRM_INFOBAR_VIEW_CONTROLLER_H_ +#define IOS_CHROME_BROWSER_UI_INFOBARS_CONFIRM_INFOBAR_CONFIRM_INFOBAR_VIEW_CONTROLLER_H_ + +#import <UIKit/UIKit.h> + +#import "ios/chrome/browser/ui/infobars/infobar_ui_delegate.h" + +class ConfirmInfoBarDelegate; + +// TODO(crbug.com/911864): PLACEHOLDER Work in Progress class for the new +// InfobarUI. +@interface ConfirmInfobarViewController : UIViewController <InfobarUIDelegate> + +- (instancetype)initWithInfoBarDelegate:(ConfirmInfoBarDelegate*)infoBarDelegate + NS_DESIGNATED_INITIALIZER; + +- (instancetype)initWithNibName:(NSString*)nibNameOrNil + bundle:(NSBundle*)nibBundleOrNil NS_UNAVAILABLE; +- (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +@end + +#endif // IOS_CHROME_BROWSER_UI_INFOBARS_CONFIRM_INFOBAR_CONFIRM_INFOBAR_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/infobars/confirm_infobar/confirm_infobar_view_controller.mm b/ios/chrome/browser/ui/infobars/confirm_infobar/confirm_infobar_view_controller.mm new file mode 100644 index 0000000..c935b75c --- /dev/null +++ b/ios/chrome/browser/ui/infobars/confirm_infobar/confirm_infobar_view_controller.mm
@@ -0,0 +1,70 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/infobars/confirm_infobar/confirm_infobar_view_controller.h" + +#include "base/strings/sys_string_conversions.h" +#include "components/infobars/core/confirm_infobar_delegate.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@interface ConfirmInfobarViewController () + +@property(nonatomic, readonly) ConfirmInfoBarDelegate* infoBarDelegate; + +@end + +// TODO(crbug.com/1372916): PLACEHOLDER Work in Progress class for the new +// InfobarUI. +@implementation ConfirmInfobarViewController +@synthesize delegate = _delegate; + +- (instancetype)initWithInfoBarDelegate: + (ConfirmInfoBarDelegate*)infoBarDelegate { + self = [super initWithNibName:nil bundle:nil]; + if (self) { + _infoBarDelegate = infoBarDelegate; + } + return self; +} + +#pragma mark - View Lifecycle + +- (void)viewDidLoad { + [super viewDidLoad]; + base::string16 messageText = self.infoBarDelegate->GetMessageText(); + NSString* message = base::SysUTF16ToNSString(messageText); + + UILabel* messageLabel = [[UILabel alloc] init]; + messageLabel.text = message; + messageLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleTitle1]; + messageLabel.adjustsFontForContentSizeCategory = YES; + messageLabel.textColor = [UIColor blackColor]; + messageLabel.translatesAutoresizingMaskIntoConstraints = NO; + + [self.view addSubview:messageLabel]; + self.view.backgroundColor = [UIColor grayColor]; + + [NSLayoutConstraint activateConstraints:@[ + [messageLabel.leadingAnchor + constraintEqualToAnchor:self.view.leadingAnchor], + [messageLabel.topAnchor constraintEqualToAnchor:self.view.topAnchor], + [messageLabel.heightAnchor constraintEqualToConstant:30], + [messageLabel.widthAnchor constraintEqualToConstant:200], + ]]; +} + +#pragma mark - InfobarUIDelegate + +- (void)removeView { + // TO-DO +} + +- (void)detachView { + // TO-DO +} + +@end
diff --git a/ios/chrome/browser/ui/infobars/infobar_container_consumer.h b/ios/chrome/browser/ui/infobars/infobar_container_consumer.h index a044a9c..aabee06c 100644 --- a/ios/chrome/browser/ui/infobars/infobar_container_consumer.h +++ b/ios/chrome/browser/ui/infobars/infobar_container_consumer.h
@@ -7,11 +7,15 @@ #import <UIKit/UIKit.h> +@protocol InfobarUIDelegate; + // Protocol to communicate with the Infobar container. @protocol InfobarContainerConsumer -// Add a new infobar to the Infobar container view at position |position|. -- (void)addInfoBarView:(UIView*)infoBarView position:(NSInteger)position; +// Adds |infoBarDelegate|'s Infobar to the InfobarContainer at position +// |position|. +- (void)addInfoBarWithDelegate:(id<InfobarUIDelegate>)infoBarDelegate + position:(NSInteger)position; // Sets the Infobar container user interaction to |enabled|. - (void)setUserInteractionEnabled:(BOOL)enabled;
diff --git a/ios/chrome/browser/ui/infobars/infobar_container_coordinator.mm b/ios/chrome/browser/ui/infobars/infobar_container_coordinator.mm index cdf0bc4..799b86c 100644 --- a/ios/chrome/browser/ui/infobars/infobar_container_coordinator.mm +++ b/ios/chrome/browser/ui/infobars/infobar_container_coordinator.mm
@@ -6,9 +6,11 @@ #include <memory> +#include "ios/chrome/browser/experimental_flags.h" #include "ios/chrome/browser/infobars/infobar_manager_impl.h" #import "ios/chrome/browser/ui/commands/application_commands.h" #include "ios/chrome/browser/ui/infobars/infobar_container_mediator.h" +#include "ios/chrome/browser/ui/infobars/infobar_container_view_controller.h" #import "ios/chrome/browser/ui/infobars/infobar_positioner.h" #include "ios/chrome/browser/ui/infobars/legacy_infobar_container_view_controller.h" #import "ios/chrome/browser/ui/signin_interaction/public/signin_presenter.h" @@ -24,7 +26,7 @@ // UIViewController that contains Infobars. @property(nonatomic, strong) - LegacyInfobarContainerViewController* containerViewController; + UIViewController<InfobarContainerConsumer>* containerViewController; // The mediator for this Coordinator. @property(nonatomic, strong) InfobarContainerMediator* mediator; @@ -49,16 +51,26 @@ DCHECK(self.dispatcher); // Create and setup the ViewController. - self.containerViewController = - [[LegacyInfobarContainerViewController alloc] init]; - [self.baseViewController addChildViewController:self.containerViewController]; - // TODO(crbug.com/892376): We shouldn't modify the BaseVC hierarchy, BVC needs - // to handle this. - [self.baseViewController.view insertSubview:self.containerViewController.view - aboveSubview:self.positioner.parentView]; - [self.containerViewController - didMoveToParentViewController:self.baseViewController]; - self.containerViewController.positioner = self.positioner; + if (experimental_flags::IsInfobarUIRebootEnabled()) { + self.containerViewController = + [[InfobarContainerViewController alloc] init]; + [self.baseViewController + addChildViewController:self.containerViewController]; + [self.baseViewController.view addSubview:self.containerViewController.view]; + [self.containerViewController + didMoveToParentViewController:self.baseViewController]; + } else { + LegacyInfobarContainerViewController* legacyContainer = + [[LegacyInfobarContainerViewController alloc] init]; + [self.baseViewController addChildViewController:legacyContainer]; + // TODO(crbug.com/892376): We shouldn't modify the BaseVC hierarchy, BVC + // needs to handle this. + [self.baseViewController.view insertSubview:legacyContainer.view + aboveSubview:self.positioner.parentView]; + [legacyContainer didMoveToParentViewController:self.baseViewController]; + legacyContainer.positioner = self.positioner; + self.containerViewController = legacyContainer; + } // Create the mediator once the VC has been added to the View hierarchy. self.mediator = [[InfobarContainerMediator alloc]
diff --git a/ios/chrome/browser/ui/infobars/infobar_container_view_controller.h b/ios/chrome/browser/ui/infobars/infobar_container_view_controller.h new file mode 100644 index 0000000..e3a2bd774 --- /dev/null +++ b/ios/chrome/browser/ui/infobars/infobar_container_view_controller.h
@@ -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. + +#ifndef IOS_CHROME_BROWSER_UI_INFOBARS_INFOBAR_CONTAINER_VIEW_CONTROLLER_H_ +#define IOS_CHROME_BROWSER_UI_INFOBARS_INFOBAR_CONTAINER_VIEW_CONTROLLER_H_ + +#import <UIKit/UIKit.h> + +#import "ios/chrome/browser/ui/infobars/infobar_container_consumer.h" + +// TODO(crbug.com/1372916): PLACEHOLDER Work in Progress class for the new +// InfobarUI. ViewController that contains all Infobars. +@interface InfobarContainerViewController + : UIViewController <InfobarContainerConsumer> + +@end + +#endif // IOS_CHROME_BROWSER_UI_INFOBARS_INFOBAR_CONTAINER_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/infobars/infobar_container_view_controller.mm b/ios/chrome/browser/ui/infobars/infobar_container_view_controller.mm new file mode 100644 index 0000000..efb5197 --- /dev/null +++ b/ios/chrome/browser/ui/infobars/infobar_container_view_controller.mm
@@ -0,0 +1,56 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/infobars/infobar_container_view_controller.h" + +#include "base/ios/block_types.h" +#include "base/logging.h" +#import "ios/chrome/browser/ui/util/rtl_geometry.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +// TODO(crbug.com/1372916): PLACEHOLDER Work in Progress class for the new +// InfobarUI. +@implementation InfobarContainerViewController + +- (void)viewDidLoad { + self.view = [[UIView alloc] initWithFrame:CGRectMake(20, 100, 360, 75)]; +} + +#pragma mark - InfobarConsumer + +- (void)addInfoBarWithDelegate:(id<InfobarUIDelegate>)infoBarDelegate + position:(NSInteger)position { + UIViewController* infoBarViewController = + static_cast<UIViewController*>(infoBarDelegate); + + [self addChildViewController:infoBarViewController]; + [self.view addSubview:infoBarViewController.view]; + infoBarViewController.view.translatesAutoresizingMaskIntoConstraints = NO; + [infoBarViewController didMoveToParentViewController:self]; + + [NSLayoutConstraint activateConstraints:@[ + [infoBarViewController.view.leadingAnchor + constraintEqualToAnchor:self.view.leadingAnchor], + [infoBarViewController.view.trailingAnchor + constraintEqualToAnchor:self.view.trailingAnchor], + [infoBarViewController.view.topAnchor + constraintEqualToAnchor:self.view.topAnchor], + [infoBarViewController.view.bottomAnchor + constraintEqualToAnchor:self.view.bottomAnchor] + ]]; +} + +- (void)setUserInteractionEnabled:(BOOL)enabled { + [self.view setUserInteractionEnabled:enabled]; +} + +- (void)updateLayoutAnimated:(BOOL)animated { + // NO-OP - This shouldn't be need in the new UI since we use autolayout for + // the contained Infobars. +} + +@end
diff --git a/ios/chrome/browser/ui/infobars/infobar_ui_delegate.h b/ios/chrome/browser/ui/infobars/infobar_ui_delegate.h new file mode 100644 index 0000000..274c63c --- /dev/null +++ b/ios/chrome/browser/ui/infobars/infobar_ui_delegate.h
@@ -0,0 +1,32 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_INFOBARS_INFOBAR_UI_DELEGATE_H_ +#define IOS_CHROME_BROWSER_UI_INFOBARS_INFOBAR_UI_DELEGATE_H_ + +#import <UIKit/UIKit.h> + +class InfoBarControllerDelegate; + +// Protocol to communicate with the Infobar container. +@protocol InfobarUIDelegate + +// Removes the view from the View Hierarchy. +- (void)removeView; + +// Detaches view from its delegate. After this function is called, no user +// interaction can be handled. +// TODO(crbug.com/1372916): This nils the View's delegate, once we +// start using ViewControllers it might not be needed. +- (void)detachView; + +// The Infobar UIView. +@property(nonatomic, readonly) UIView* view; + +// The InfobarControllerDelegate. +@property(nonatomic, assign) InfoBarControllerDelegate* delegate; + +@end + +#endif // IOS_CHROME_BROWSER_UI_INFOBARS_INFOBAR_UI_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/infobars/legacy_infobar_container_view_controller.mm b/ios/chrome/browser/ui/infobars/legacy_infobar_container_view_controller.mm index 224ae32..04943d2 100644 --- a/ios/chrome/browser/ui/infobars/legacy_infobar_container_view_controller.mm +++ b/ios/chrome/browser/ui/infobars/legacy_infobar_container_view_controller.mm
@@ -7,6 +7,7 @@ #include "base/ios/block_types.h" #include "base/logging.h" #import "ios/chrome/browser/ui/infobars/infobar_positioner.h" +#import "ios/chrome/browser/ui/infobars/infobar_ui_delegate.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -46,8 +47,10 @@ #pragma mark - InfobarConsumer -- (void)addInfoBarView:(UIView*)infoBarView position:(NSInteger)position { +- (void)addInfoBarWithDelegate:(id<InfobarUIDelegate>)infoBarDelegate + position:(NSInteger)position { DCHECK_LE(static_cast<NSUInteger>(position), [[self.view subviews] count]); + UIView* infoBarView = infoBarDelegate.view; [self.view insertSubview:infoBarView atIndex:position]; infoBarView.translatesAutoresizingMaskIntoConstraints = NO; [NSLayoutConstraint activateConstraints:@[
diff --git a/ios/chrome/browser/ui/location_bar/BUILD.gn b/ios/chrome/browser/ui/location_bar/BUILD.gn index 81ee66d..5812c05 100644 --- a/ios/chrome/browser/ui/location_bar/BUILD.gn +++ b/ios/chrome/browser/ui/location_bar/BUILD.gn
@@ -41,6 +41,7 @@ "//ios/chrome/browser/search_engines", "//ios/chrome/browser/ssl", "//ios/chrome/browser/ui", + "//ios/chrome/browser/ui:feature_flags", "//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/fullscreen", "//ios/chrome/browser/ui/fullscreen:ui",
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_view_controller.mm b/ios/chrome/browser/ui/location_bar/location_bar_view_controller.mm index 2767d7a..f9e1824 100644 --- a/ios/chrome/browser/ui/location_bar/location_bar_view_controller.mm +++ b/ios/chrome/browser/ui/location_bar/location_bar_view_controller.mm
@@ -14,6 +14,7 @@ #import "ios/chrome/browser/ui/fullscreen/fullscreen_animator.h" #include "ios/chrome/browser/ui/location_bar/location_bar_steady_view.h" #import "ios/chrome/browser/ui/orchestrator/location_bar_offset_provider.h" +#include "ios/chrome/browser/ui/ui_feature_flags.h" #import "ios/chrome/browser/ui/util/named_guide.h" #import "ios/chrome/common/ui_util/constraints_ui_util.h" #import "ios/chrome/grit/ios_strings.h" @@ -428,10 +429,20 @@ // when it's the first time setting the first responder. dispatch_async(dispatch_get_main_queue(), ^{ UIMenuController* menu = [UIMenuController sharedMenuController]; - UIMenuItem* pasteAndGo = [[UIMenuItem alloc] - initWithTitle:l10n_util::GetNSString(IDS_IOS_PASTE_AND_GO) - action:@selector(pasteAndGo:)]; - [menu setMenuItems:@[ pasteAndGo ]]; + if (base::FeatureList::IsEnabled(kCopiedTextBehavior)) { + UIMenuItem* visitCopiedLink = [[UIMenuItem alloc] + initWithTitle:l10n_util::GetNSString(IDS_IOS_VISIT_COPIED_LINK) + action:@selector(visitCopiedLink:)]; + UIMenuItem* searchCopiedText = [[UIMenuItem alloc] + initWithTitle:l10n_util::GetNSString(IDS_IOS_SEARCH_COPIED_TEXT) + action:@selector(searchCopiedText:)]; + [menu setMenuItems:@[ visitCopiedLink, searchCopiedText ]]; + } else { + UIMenuItem* pasteAndGo = [[UIMenuItem alloc] + initWithTitle:l10n_util::GetNSString(IDS_IOS_PASTE_AND_GO) + action:@selector(pasteAndGo:)]; + [menu setMenuItems:@[ pasteAndGo ]]; + } [menu setTargetRect:self.locationBarSteadyView.frame inView:self.view]; [menu setMenuVisible:YES animated:YES]; @@ -440,18 +451,45 @@ } - (BOOL)canPerformAction:(SEL)action withSender:(id)sender { - return action == @selector(copy:) || - (action == @selector(pasteAndGo:) && - UIPasteboard.generalPasteboard.string.length > 0); + if (action == @selector(copy:)) { + return true; + } + + UIPasteboard* pasteboard = UIPasteboard.generalPasteboard; + // remove along with flag kCopiedTextBehavior + if (action == @selector(pasteAndGo:)) { + DCHECK(!base::FeatureList::IsEnabled(kCopiedTextBehavior)); + return UIPasteboard.generalPasteboard.string.length > 0; + } + if (action == @selector(visitCopiedLink:)) { + DCHECK(base::FeatureList::IsEnabled(kCopiedTextBehavior)); + return pasteboard.hasURLs; + } + if (action == @selector(searchCopiedText:)) { + DCHECK(base::FeatureList::IsEnabled(kCopiedTextBehavior)); + return !pasteboard.hasURLs && pasteboard.hasStrings; + } + return NO; } - (void)copy:(id)sender { [self.delegate locationBarCopyTapped]; } +- (void)visitCopiedLink:(id)sender { + [self pasteAndGo:sender]; +} + +- (void)searchCopiedText:(id)sender { + [self pasteAndGo:sender]; +} + +// Both actions are performed the same, but need to be enabled differently, +// so we need two different selectors. - (void)pasteAndGo:(id)sender { - [self.dispatcher loadQuery:UIPasteboard.generalPasteboard.string - immediately:YES]; + UIPasteboard* pasteboard = UIPasteboard.generalPasteboard; + NSString* query = pasteboard.URL.absoluteString ?: pasteboard.string; + [self.dispatcher loadQuery:query immediately:YES]; } @end
diff --git a/ios/chrome/browser/ui/omnibox/BUILD.gn b/ios/chrome/browser/ui/omnibox/BUILD.gn index eea46df..199dd7d3 100644 --- a/ios/chrome/browser/ui/omnibox/BUILD.gn +++ b/ios/chrome/browser/ui/omnibox/BUILD.gn
@@ -110,6 +110,7 @@ "//ios/chrome/browser/search_engines", "//ios/chrome/browser/sessions", "//ios/chrome/browser/ui", + "//ios/chrome/browser/ui:feature_flags", "//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/fullscreen", "//ios/chrome/browser/ui/location_bar:constants",
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_view_controller.mm b/ios/chrome/browser/ui/omnibox/omnibox_view_controller.mm index 64a282c..514d8a8 100644 --- a/ios/chrome/browser/ui/omnibox/omnibox_view_controller.mm +++ b/ios/chrome/browser/ui/omnibox/omnibox_view_controller.mm
@@ -9,6 +9,7 @@ #import "ios/chrome/browser/ui/omnibox/omnibox_container_view.h" #import "ios/chrome/browser/ui/toolbar/public/omnibox_focuser.h" #import "ios/chrome/browser/ui/toolbar/public/toolbar_constants.h" +#include "ios/chrome/browser/ui/ui_feature_flags.h" #include "ios/chrome/browser/ui/util/ui_util.h" #include "ios/chrome/browser/ui/util/uikit_ui_util.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" @@ -77,10 +78,20 @@ // Add Paste and Go option to the editing menu UIMenuController* menu = [UIMenuController sharedMenuController]; - UIMenuItem* pasteAndGo = [[UIMenuItem alloc] - initWithTitle:l10n_util::GetNSString(IDS_IOS_PASTE_AND_GO) - action:NSSelectorFromString(@"pasteAndGo:")]; - [menu setMenuItems:@[ pasteAndGo ]]; + if (base::FeatureList::IsEnabled(kCopiedTextBehavior)) { + UIMenuItem* visitCopiedLink = [[UIMenuItem alloc] + initWithTitle:l10n_util::GetNSString(IDS_IOS_VISIT_COPIED_LINK) + action:@selector(visitCopiedLink:)]; + UIMenuItem* searchCopiedText = [[UIMenuItem alloc] + initWithTitle:l10n_util::GetNSString(IDS_IOS_SEARCH_COPIED_TEXT) + action:@selector(searchCopiedText:)]; + [menu setMenuItems:@[ visitCopiedLink, searchCopiedText ]]; + } else { + UIMenuItem* pasteAndGo = [[UIMenuItem alloc] + initWithTitle:l10n_util::GetNSString(IDS_IOS_PASTE_AND_GO) + action:NSSelectorFromString(@"pasteAndGo:")]; + [menu setMenuItems:@[ pasteAndGo ]]; + } self.textField.placeholderTextColor = [self placeholderAndClearButtonColor]; self.textField.placeholder = l10n_util::GetNSString(IDS_OMNIBOX_EMPTY_HINT); @@ -229,17 +240,37 @@ #pragma mark - UIMenuItem - (BOOL)canPerformAction:(SEL)action withSender:(id)sender { - if (UIPasteboard.generalPasteboard.string.length > 0 && action == @selector - (pasteAndGo:)) { - return YES; + UIPasteboard* pasteboard = UIPasteboard.generalPasteboard; + // remove with flag kCopiedTextBehavior + if (action == @selector(pasteAndGo:)) { + DCHECK(!base::FeatureList::IsEnabled(kCopiedTextBehavior)); + return UIPasteboard.generalPasteboard.string.length > 0; } - + if (action == @selector(visitCopiedLink:)) { + DCHECK(base::FeatureList::IsEnabled(kCopiedTextBehavior)); + return pasteboard.hasURLs; + } + if (action == @selector(searchCopiedText:)) { + DCHECK(base::FeatureList::IsEnabled(kCopiedTextBehavior)); + return !pasteboard.hasURLs && pasteboard.hasStrings; + } return NO; } +- (void)visitCopiedLink:(id)sender { + [self pasteAndGo:sender]; +} + +- (void)searchCopiedText:(id)sender { + [self pasteAndGo:sender]; +} + +// Both actions are performed the same, but need to be enabled differently, +// so we need two different selectors. - (void)pasteAndGo:(id)sender { - [self.dispatcher loadQuery:UIPasteboard.generalPasteboard.string - immediately:YES]; + UIPasteboard* pasteboard = UIPasteboard.generalPasteboard; + NSString* query = pasteboard.URL.absoluteString ?: pasteboard.string; + [self.dispatcher loadQuery:query immediately:YES]; [self.dispatcher cancelOmniboxEdit]; }
diff --git a/ios/chrome/browser/ui/recent_tabs/BUILD.gn b/ios/chrome/browser/ui/recent_tabs/BUILD.gn index a39a334..c980782 100644 --- a/ios/chrome/browser/ui/recent_tabs/BUILD.gn +++ b/ios/chrome/browser/ui/recent_tabs/BUILD.gn
@@ -76,6 +76,7 @@ "//ios/chrome/browser/ui/table_view", "//ios/chrome/browser/ui/table_view:presentation", "//ios/chrome/browser/ui/util", + "//ios/chrome/browser/url_loading", "//ios/chrome/common/favicon", "//ui/base", ]
diff --git a/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.h b/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.h index 0e8f2c8..7c502cc 100644 --- a/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.h +++ b/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.h
@@ -7,6 +7,7 @@ #import "ios/chrome/browser/ui/recent_tabs/recent_tabs_consumer.h" #import "ios/chrome/browser/ui/table_view/chrome_table_view_controller.h" +#include "ui/base/window_open_disposition.h" namespace ios { class ChromeBrowserState; @@ -26,7 +27,8 @@ @property(nonatomic, weak) id<ApplicationCommands> dispatcher; // UrlLoader used by this ViewController. @property(nonatomic, weak) id<UrlLoader> loader; - +// Disposition for tabs restored by this object. Defaults to CURRENT_TAB. +@property(nonatomic, assign) WindowOpenDisposition restoredTabDisposition; // RecentTabsTableViewControllerDelegate delegate. @property(nonatomic, weak) id<RecentTabsTableViewControllerDelegate> delegate;
diff --git a/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm b/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm index 2f98b56..6bb3629 100644 --- a/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm +++ b/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm
@@ -46,6 +46,7 @@ #import "ios/chrome/browser/ui/url_loader.h" #import "ios/chrome/browser/ui/util/top_view_controller.h" #include "ios/chrome/browser/ui/util/ui_util.h" +#import "ios/chrome/browser/url_loading/url_loading_util.h" #import "ios/chrome/common/favicon/favicon_attributes.h" #import "ios/chrome/common/favicon/favicon_view.h" #include "ios/chrome/grit/ios_chromium_strings.h" @@ -118,17 +119,6 @@ @end @implementation RecentTabsTableViewController : ChromeTableViewController -@synthesize browserState = _browserState; -@synthesize contextMenuCoordinator = _contextMenuCoordinator; -@synthesize delegate = delegate_; -@synthesize dispatcher = _dispatcher; -@synthesize presentationDelegate = _presentationDelegate; -@synthesize imageDataSource = _imageDataSource; -@synthesize loader = _loader; -@synthesize sessionState = _sessionState; -@synthesize signinPromoViewMediator = _signinPromoViewMediator; -@synthesize updatesTableView = _updatesTableView; -@synthesize tabRestoreService = _tabRestoreService; #pragma mark - Public Interface @@ -138,6 +128,7 @@ if (self) { _sessionState = SessionsSyncUserState::USER_SIGNED_OUT; _syncedSessions.reset(new synced_sessions::SyncedSessions()); + _restoredTabDisposition = WindowOpenDisposition::CURRENT_TAB; } return self; } @@ -882,7 +873,7 @@ base::UserMetricsAction("MobileRecentTabManagerRecentTabOpened")); new_tab_page_uma::RecordAction( self.browserState, new_tab_page_uma::ACTION_OPENED_RECENTLY_CLOSED_ENTRY); - [self.loader restoreTabWithSessionID:entry->id]; + RestoreTab(entry->id, self.restoredTabDisposition, self.browserState); [self.presentationDelegate showActiveRegularTabFromRecentTabs]; }
diff --git a/ios/chrome/browser/ui/settings/BUILD.gn b/ios/chrome/browser/ui/settings/BUILD.gn index b5c2578..f725018 100644 --- a/ios/chrome/browser/ui/settings/BUILD.gn +++ b/ios/chrome/browser/ui/settings/BUILD.gn
@@ -88,10 +88,10 @@ "settings_root_view_controlling.h", "settings_utils.h", "settings_utils.mm", - "sync_create_passphrase_collection_view_controller.h", - "sync_create_passphrase_collection_view_controller.mm", - "sync_encryption_passphrase_collection_view_controller.h", - "sync_encryption_passphrase_collection_view_controller.mm", + "sync_create_passphrase_table_view_controller.h", + "sync_create_passphrase_table_view_controller.mm", + "sync_encryption_passphrase_table_view_controller.h", + "sync_encryption_passphrase_table_view_controller.mm", "sync_encryption_table_view_controller.h", "sync_encryption_table_view_controller.mm", "sync_settings_collection_view_controller.h", @@ -230,8 +230,8 @@ configs += [ "//build/config/compiler:enable_arc" ] testonly = true sources = [ - "passphrase_collection_view_controller_test.h", - "passphrase_collection_view_controller_test.mm", + "passphrase_table_view_controller_test.h", + "passphrase_table_view_controller_test.mm", "password_details_table_view_controller+testing.h", "password_exporter_for_testing.h", "personal_data_manager_data_changed_observer.cc", @@ -257,7 +257,7 @@ "//ios/chrome/browser/signin:test_support", "//ios/chrome/browser/sync", "//ios/chrome/browser/sync:test_support", - "//ios/chrome/browser/ui/collection_view:test_support", + "//ios/chrome/browser/ui/table_view:test_support", "//ios/public/provider/chrome/browser/signin:test_support", "//ios/web/public/test", "//testing/gtest", @@ -288,8 +288,8 @@ "settings_navigation_controller_unittest.mm", "settings_root_collection_view_controller_unittest.mm", "settings_root_table_view_controller_unittest.mm", - "sync_create_passphrase_collection_view_controller_unittest.mm", - "sync_encryption_passphrase_collection_view_controller_unittest.mm", + "sync_create_passphrase_table_view_controller_unittest.mm", + "sync_encryption_passphrase_table_view_controller_unittest.mm", "sync_encryption_table_view_controller_unittest.mm", "sync_settings_collection_view_controller_unittest.mm", "time_range_selector_collection_view_controller_unittest.mm",
diff --git a/ios/chrome/browser/ui/settings/cells/byo_textfield_item.h b/ios/chrome/browser/ui/settings/cells/byo_textfield_item.h index bb8ad89..e3261dd 100644 --- a/ios/chrome/browser/ui/settings/cells/byo_textfield_item.h +++ b/ios/chrome/browser/ui/settings/cells/byo_textfield_item.h
@@ -7,17 +7,16 @@ #import <UIKit/UIKit.h> -#import "ios/chrome/browser/ui/collection_view/cells/collection_view_item.h" -#import "ios/third_party/material_components_ios/src/components/CollectionCells/src/MaterialCollectionCells.h" +#import "ios/chrome/browser/ui/table_view/cells/table_view_item.h" // Bring-your-own-text-field: Item that hosts a text field provided by the user // of this class. -// Useful for adding a text field to a collection view, where the view may -// be scrolled out of view and back in. By using this object, even if the -// collection view cell containing the text field is cleared and reused, the -// user-entered content remains unchanged by using the same text field. -// Not recommended for large models, as the text field is not reused. -@interface BYOTextFieldItem : CollectionViewItem +// Useful for adding a text field to a table view, where the view may be +// scrolled out of view and back in. By using this object, even if the table +// view cell containing the text field is cleared and reused, the user-entered +// content remains unchanged by using the same text field. Not recommended for +// large models, as the text field is not reused. +@interface BYOTextFieldItem : TableViewItem // The text field that will be installed in the cell during -configureCell:. @property(nonatomic, strong) UITextField* textField; @@ -25,7 +24,7 @@ @end // Cell class associated to BYOTextFieldItem. -@interface BYOTextFieldCell : MDCCollectionViewCell +@interface BYOTextFieldCell : UITableViewCell @end #endif // IOS_CHROME_BROWSER_UI_SETTINGS_CELLS_BYO_TEXTFIELD_ITEM_H_
diff --git a/ios/chrome/browser/ui/settings/cells/byo_textfield_item.mm b/ios/chrome/browser/ui/settings/cells/byo_textfield_item.mm index bdf9824..fb56404 100644 --- a/ios/chrome/browser/ui/settings/cells/byo_textfield_item.mm +++ b/ios/chrome/browser/ui/settings/cells/byo_textfield_item.mm
@@ -13,6 +13,8 @@ namespace { // Padding used on the leading and trailing edges of the cell. const CGFloat kHorizontalPadding = 16; +// Padding used on the top and bottom edges of the cell. +const CGFloat kVerticalPadding = 14; } // namespace @interface BYOTextFieldCell () @@ -40,8 +42,9 @@ return self; } -- (void)configureCell:(BYOTextFieldCell*)cell { - [super configureCell:cell]; +- (void)configureCell:(BYOTextFieldCell*)cell + withStyler:(ChromeTableViewStyler*)styler { + [super configureCell:cell withStyler:styler]; [cell installTextField:self.textField]; } @@ -71,8 +74,10 @@ // Store the constraints. self.textFieldConstraints = @[ - [textField.topAnchor constraintEqualToAnchor:contentView.topAnchor], - [textField.bottomAnchor constraintEqualToAnchor:contentView.bottomAnchor], + [textField.topAnchor constraintEqualToAnchor:contentView.topAnchor + constant:kVerticalPadding], + [textField.bottomAnchor constraintEqualToAnchor:contentView.bottomAnchor + constant:-kVerticalPadding], [textField.leadingAnchor constraintEqualToAnchor:contentView.leadingAnchor constant:kHorizontalPadding], [textField.trailingAnchor constraintEqualToAnchor:contentView.trailingAnchor
diff --git a/ios/chrome/browser/ui/settings/cells/byo_textfield_item_unittest.mm b/ios/chrome/browser/ui/settings/cells/byo_textfield_item_unittest.mm index ea858f9..adffd925 100644 --- a/ios/chrome/browser/ui/settings/cells/byo_textfield_item_unittest.mm +++ b/ios/chrome/browser/ui/settings/cells/byo_textfield_item_unittest.mm
@@ -4,6 +4,7 @@ #import "ios/chrome/browser/ui/settings/cells/byo_textfield_item.h" +#import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h" #include "testing/gtest/include/gtest/gtest.h" #import "testing/gtest_mac.h" #include "testing/platform_test.h" @@ -25,9 +26,8 @@ UITextField* textField = [[UITextField alloc] init]; EXPECT_NSEQ(nil, [textField superview]); item.textField = textField; - [item configureCell:cell]; + [item configureCell:cell withStyler:[[ChromeTableViewStyler alloc] init]]; EXPECT_NSEQ(cell.contentView, [textField superview]); - EXPECT_TRUE(CGRectEqualToRect(cell.contentView.bounds, textField.frame)); } } // namespace
diff --git a/ios/chrome/browser/ui/settings/cells/card_multiline_item.h b/ios/chrome/browser/ui/settings/cells/card_multiline_item.h index 746fc20..2dd1d4c 100644 --- a/ios/chrome/browser/ui/settings/cells/card_multiline_item.h +++ b/ios/chrome/browser/ui/settings/cells/card_multiline_item.h
@@ -7,18 +7,17 @@ #import <UIKit/UIKit.h> -#import "ios/chrome/browser/ui/collection_view/cells/collection_view_item.h" -#import "ios/third_party/material_components_ios/src/components/CollectionCells/src/MaterialCollectionCells.h" +#import "ios/chrome/browser/ui/table_view/cells/table_view_item.h" // Item to display a multiline text, presented in the card style. -@interface CardMultilineItem : CollectionViewItem +@interface CardMultilineItem : TableViewItem // The text to display. @property(nonatomic, copy) NSString* text; @end -@interface CardMultilineCell : MDCCollectionViewCell +@interface CardMultilineCell : UITableViewCell // UILabel corresponding to |text| from the item. @property(nonatomic, readonly, strong) UILabel* textLabel;
diff --git a/ios/chrome/browser/ui/settings/cells/card_multiline_item.mm b/ios/chrome/browser/ui/settings/cells/card_multiline_item.mm index 7e35474..31ccb4e 100644 --- a/ios/chrome/browser/ui/settings/cells/card_multiline_item.mm +++ b/ios/chrome/browser/ui/settings/cells/card_multiline_item.mm
@@ -4,11 +4,8 @@ #import "ios/chrome/browser/ui/settings/cells/card_multiline_item.h" -#include "ios/chrome/browser/ui/collection_view/cells/collection_view_cell_constants.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" #import "ios/chrome/common/ui_util/constraints_ui_util.h" -#import "ios/third_party/material_components_ios/src/components/Palettes/src/MaterialPalettes.h" -#import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -34,10 +31,12 @@ return self; } -#pragma mark CollectionViewItem +#pragma mark TableViewItem -- (void)configureCell:(CardMultilineCell*)cell { - [super configureCell:cell]; +- (void)configureCell:(CardMultilineCell*)cell + withStyler:(ChromeTableViewStyler*)styler { + [super configureCell:cell withStyler:styler]; + cell.selectionStyle = UITableViewCellSelectionStyleNone; cell.textLabel.text = self.text; } @@ -47,16 +46,17 @@ @synthesize textLabel = _textLabel; -- (instancetype)initWithFrame:(CGRect)frame { - self = [super initWithFrame:frame]; +- (instancetype)initWithStyle:(UITableViewCellStyle)style + reuseIdentifier:(NSString*)reuseIdentifier { + self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { UIView* contentView = self.contentView; _textLabel = [[UILabel alloc] init]; _textLabel.translatesAutoresizingMaskIntoConstraints = NO; _textLabel.numberOfLines = 0; - _textLabel.font = [UIFont systemFontOfSize:kUIKitMainFontSize]; - _textLabel.textColor = UIColorFromRGB(kUIKitMainTextColor); + _textLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; + _textLabel.adjustsFontForContentSizeCategory = YES; [contentView addSubview:_textLabel]; // Set up the constraints.
diff --git a/ios/chrome/browser/ui/settings/cells/card_multiline_item_unittest.mm b/ios/chrome/browser/ui/settings/cells/card_multiline_item_unittest.mm index 9cef450b..2514f83c 100644 --- a/ios/chrome/browser/ui/settings/cells/card_multiline_item_unittest.mm +++ b/ios/chrome/browser/ui/settings/cells/card_multiline_item_unittest.mm
@@ -4,6 +4,7 @@ #import "ios/chrome/browser/ui/settings/cells/card_multiline_item.h" +#import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h" #include "testing/gtest/include/gtest/gtest.h" #import "testing/gtest_mac.h" #include "testing/platform_test.h" @@ -29,7 +30,7 @@ CardMultilineCell* disclaimerCell = static_cast<CardMultilineCell*>(cell); EXPECT_FALSE(disclaimerCell.textLabel.text); - [item configureCell:cell]; + [item configureCell:cell withStyler:[[ChromeTableViewStyler alloc] init]]; EXPECT_NSEQ(text, disclaimerCell.textLabel.text); }
diff --git a/ios/chrome/browser/ui/settings/cells/passphrase_error_item.h b/ios/chrome/browser/ui/settings/cells/passphrase_error_item.h index cace876..cf1806941 100644 --- a/ios/chrome/browser/ui/settings/cells/passphrase_error_item.h +++ b/ios/chrome/browser/ui/settings/cells/passphrase_error_item.h
@@ -5,11 +5,10 @@ #ifndef IOS_CHROME_BROWSER_UI_SETTINGS_CELLS_PASSPHRASE_ERROR_ITEM_H_ #define IOS_CHROME_BROWSER_UI_SETTINGS_CELLS_PASSPHRASE_ERROR_ITEM_H_ -#import "ios/chrome/browser/ui/collection_view/cells/collection_view_item.h" -#import "ios/third_party/material_components_ios/src/components/CollectionCells/src/MaterialCollectionCells.h" +#import "ios/chrome/browser/ui/table_view/cells/table_view_item.h" // Item to display an error when the passphrase is incorrect. -@interface PassphraseErrorItem : CollectionViewItem +@interface PassphraseErrorItem : TableViewItem // The error text. It appears in red. @property(nonatomic, copy) NSString* text; @@ -17,7 +16,7 @@ @end // Cell class associated to PassphraseErrorItem. -@interface PassphraseErrorCell : MDCCollectionViewCell +@interface PassphraseErrorCell : UITableViewCell // Label for the error text. @property(nonatomic, readonly, strong) UILabel* textLabel;
diff --git a/ios/chrome/browser/ui/settings/cells/passphrase_error_item.mm b/ios/chrome/browser/ui/settings/cells/passphrase_error_item.mm index b96a5ae..e164184 100644 --- a/ios/chrome/browser/ui/settings/cells/passphrase_error_item.mm +++ b/ios/chrome/browser/ui/settings/cells/passphrase_error_item.mm
@@ -4,13 +4,6 @@ #import "ios/chrome/browser/ui/settings/cells/passphrase_error_item.h" -#import <UIKit/UIKit.h> - -#include "ios/chrome/browser/ui/collection_view/cells/collection_view_cell_constants.h" -#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" -#import "ios/third_party/material_components_ios/src/components/Palettes/src/MaterialPalettes.h" -#import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h" - #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif @@ -32,9 +25,11 @@ return self; } -- (void)configureCell:(PassphraseErrorCell*)cell { - [super configureCell:cell]; +- (void)configureCell:(UITableViewCell*)cell + withStyler:(ChromeTableViewStyler*)styler { + [super configureCell:cell withStyler:styler]; cell.textLabel.text = self.text; + cell.selectionStyle = UITableViewCellSelectionStyleNone; } @end @@ -48,15 +43,17 @@ @synthesize textLabel = _textLabel; @synthesize errorImageView = _errorImageView; -- (instancetype)initWithFrame:(CGRect)frame { - self = [super initWithFrame:frame]; +- (instancetype)initWithStyle:(UITableViewCellStyle)style + reuseIdentifier:(NSString*)reuseIdentifier { + self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { UIView* contentView = self.contentView; _textLabel = [[UILabel alloc] init]; _textLabel.translatesAutoresizingMaskIntoConstraints = NO; - _textLabel.font = [UIFont systemFontOfSize:kUIKitMainFontSize]; - _textLabel.textColor = [[MDCPalette cr_redPalette] tint500]; + _textLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; + _textLabel.adjustsFontForContentSizeCategory = YES; + _textLabel.textColor = UIColor.redColor; [contentView addSubview:_textLabel]; _errorImageView = [[UIImageView alloc] init];
diff --git a/ios/chrome/browser/ui/settings/cells/passphrase_error_item_unittest.mm b/ios/chrome/browser/ui/settings/cells/passphrase_error_item_unittest.mm index 6fc21d7..af56d539 100644 --- a/ios/chrome/browser/ui/settings/cells/passphrase_error_item_unittest.mm +++ b/ios/chrome/browser/ui/settings/cells/passphrase_error_item_unittest.mm
@@ -4,6 +4,7 @@ #import "ios/chrome/browser/ui/settings/cells/passphrase_error_item.h" +#import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h" #include "testing/gtest/include/gtest/gtest.h" #import "testing/gtest_mac.h" #include "testing/platform_test.h" @@ -25,7 +26,7 @@ NSString* text = @"This is an error"; item.text = text; - [item configureCell:cell]; + [item configureCell:cell withStyler:[[ChromeTableViewStyler alloc] init]]; EXPECT_NSEQ(text, cell.textLabel.text); }
diff --git a/ios/chrome/browser/ui/settings/google_services_settings_coordinator.mm b/ios/chrome/browser/ui/settings/google_services_settings_coordinator.mm index 5994b3a..9675484 100644 --- a/ios/chrome/browser/ui/settings/google_services_settings_coordinator.mm +++ b/ios/chrome/browser/ui/settings/google_services_settings_coordinator.mm
@@ -24,7 +24,7 @@ #import "ios/chrome/browser/ui/settings/google_services_settings_local_commands.h" #import "ios/chrome/browser/ui/settings/google_services_settings_mediator.h" #import "ios/chrome/browser/ui/settings/google_services_settings_view_controller.h" -#import "ios/chrome/browser/ui/settings/sync_encryption_passphrase_collection_view_controller.h" +#import "ios/chrome/browser/ui/settings/sync_encryption_passphrase_table_view_controller.h" #import "ios/chrome/browser/ui/settings/sync_encryption_table_view_controller.h" #include "ios/chrome/browser/unified_consent/unified_consent_service_factory.h" #include "ios/public/provider/chrome/browser/chrome_browser_provider.h" @@ -172,7 +172,7 @@ // If there was a sync error, prompt the user to enter the passphrase. // Otherwise, show the full encryption options. if (syncService->IsPassphraseRequired()) { - controllerToPush = [[SyncEncryptionPassphraseCollectionViewController alloc] + controllerToPush = [[SyncEncryptionPassphraseTableViewController alloc] initWithBrowserState:self.browserState]; } else { controllerToPush = [[SyncEncryptionTableViewController alloc]
diff --git a/ios/chrome/browser/ui/settings/passphrase_collection_view_controller_test.h b/ios/chrome/browser/ui/settings/passphrase_table_view_controller_test.h similarity index 73% rename from ios/chrome/browser/ui/settings/passphrase_collection_view_controller_test.h rename to ios/chrome/browser/ui/settings/passphrase_table_view_controller_test.h index 9d99406..88262da 100644 --- a/ios/chrome/browser/ui/settings/passphrase_collection_view_controller_test.h +++ b/ios/chrome/browser/ui/settings/passphrase_table_view_controller_test.h
@@ -2,16 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_PASSPHRASE_COLLECTION_VIEW_CONTROLLER_TEST_H_ -#define IOS_CHROME_BROWSER_UI_SETTINGS_PASSPHRASE_COLLECTION_VIEW_CONTROLLER_TEST_H_ +#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_PASSPHRASE_TABLE_VIEW_CONTROLLER_TEST_H_ +#define IOS_CHROME_BROWSER_UI_SETTINGS_PASSPHRASE_TABLE_VIEW_CONTROLLER_TEST_H_ -#include <memory> +#include "ios/chrome/browser/ui/table_view/chrome_table_view_controller_test.h" #include "base/compiler_specific.h" #include "components/keyed_service/core/keyed_service.h" #include "components/sync/engine/cycle/sync_cycle_snapshot.h" #include "google_apis/gaia/google_service_auth_error.h" -#import "ios/chrome/browser/ui/collection_view/collection_view_controller_test.h" #include "ios/web/public/test/test_web_thread_bundle.h" #include "testing/platform_test.h" @@ -27,17 +26,16 @@ @class UINavigationController; @class UIViewController; -// Base class for PassphraseCollectionViewController tests. +// Base class for PassphraseTableViewController tests. // Sets up a testing profile and a mock profile sync service, along with the // supporting structure they require. -class PassphraseCollectionViewControllerTest - : public CollectionViewControllerTest { +class PassphraseTableViewControllerTest : public ChromeTableViewControllerTest { public: static std::unique_ptr<KeyedService> CreateNiceProfileSyncServiceMock( web::BrowserState* context); - PassphraseCollectionViewControllerTest(); - ~PassphraseCollectionViewControllerTest() override; + PassphraseTableViewControllerTest(); + ~PassphraseTableViewControllerTest() override; protected: void SetUp() override; @@ -60,4 +58,4 @@ UINavigationController* nav_controller_; }; -#endif // IOS_CHROME_BROWSER_UI_SETTINGS_PASSPHRASE_COLLECTION_VIEW_CONTROLLER_TEST_H_ +#endif // IOS_CHROME_BROWSER_UI_SETTINGS_PASSPHRASE_TABLE_VIEW_CONTROLLER_TEST_H_
diff --git a/ios/chrome/browser/ui/settings/passphrase_collection_view_controller_test.mm b/ios/chrome/browser/ui/settings/passphrase_table_view_controller_test.mm similarity index 88% rename from ios/chrome/browser/ui/settings/passphrase_collection_view_controller_test.mm rename to ios/chrome/browser/ui/settings/passphrase_table_view_controller_test.mm index 123e9a06..5981349 100644 --- a/ios/chrome/browser/ui/settings/passphrase_collection_view_controller_test.mm +++ b/ios/chrome/browser/ui/settings/passphrase_table_view_controller_test.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/ui/settings/passphrase_collection_view_controller_test.h" +#import "ios/chrome/browser/ui/settings/passphrase_table_view_controller_test.h" #import <UIKit/UIKit.h> @@ -46,7 +46,7 @@ } std::unique_ptr<KeyedService> -PassphraseCollectionViewControllerTest::CreateNiceProfileSyncServiceMock( +PassphraseTableViewControllerTest::CreateNiceProfileSyncServiceMock( web::BrowserState* context) { browser_sync::ProfileSyncService::InitParams init_params = CreateProfileSyncServiceParamsForTest( @@ -55,16 +55,15 @@ std::move(init_params)); } -PassphraseCollectionViewControllerTest::PassphraseCollectionViewControllerTest() - : CollectionViewControllerTest(), +PassphraseTableViewControllerTest::PassphraseTableViewControllerTest() + : ChromeTableViewControllerTest(), fake_sync_service_(NULL), default_auth_error_(GoogleServiceAuthError::NONE) {} -PassphraseCollectionViewControllerTest:: - ~PassphraseCollectionViewControllerTest() {} +PassphraseTableViewControllerTest::~PassphraseTableViewControllerTest() {} -void PassphraseCollectionViewControllerTest::SetUp() { - CollectionViewControllerTest::SetUp(); +void PassphraseTableViewControllerTest::SetUp() { + ChromeTableViewControllerTest::SetUp(); // Set up the default return values for non-trivial return types. DefaultValue<const GoogleServiceAuthError&>::Set(default_auth_error_); @@ -101,7 +100,7 @@ ->SignIn(identity, ""); } -void PassphraseCollectionViewControllerTest::SetUpNavigationController( +void PassphraseTableViewControllerTest::SetUpNavigationController( UIViewController* test_controller) { dummy_controller_ = [[UIViewController alloc] init]; nav_controller_ = [[SettingsNavigationController alloc]
diff --git a/ios/chrome/browser/ui/settings/settings_navigation_controller.mm b/ios/chrome/browser/ui/settings/settings_navigation_controller.mm index c3fc3fa..e7a656b 100644 --- a/ios/chrome/browser/ui/settings/settings_navigation_controller.mm +++ b/ios/chrome/browser/ui/settings/settings_navigation_controller.mm
@@ -23,7 +23,7 @@ #import "ios/chrome/browser/ui/settings/settings_collection_view_controller.h" #import "ios/chrome/browser/ui/settings/settings_root_collection_view_controller.h" #import "ios/chrome/browser/ui/settings/settings_utils.h" -#import "ios/chrome/browser/ui/settings/sync_encryption_passphrase_collection_view_controller.h" +#import "ios/chrome/browser/ui/settings/sync_encryption_passphrase_table_view_controller.h" #import "ios/chrome/browser/ui/settings/sync_settings_collection_view_controller.h" #include "ios/chrome/browser/ui/util/ui_util.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" @@ -182,8 +182,8 @@ newSyncEncryptionPassphraseController:(ios::ChromeBrowserState*)browserState delegate:(id<SettingsNavigationControllerDelegate>) delegate { - SyncEncryptionPassphraseCollectionViewController* controller = - [[SyncEncryptionPassphraseCollectionViewController alloc] + SyncEncryptionPassphraseTableViewController* controller = + [[SyncEncryptionPassphraseTableViewController alloc] initWithBrowserState:browserState]; controller.dispatcher = [delegate dispatcherForSettings]; SettingsNavigationController* nc = [[SettingsNavigationController alloc] @@ -540,8 +540,8 @@ // TODO(crbug.com/779791) : Do not pass |baseViewController| through dispatcher. - (void)showSyncPassphraseSettingsFromViewController: (UIViewController*)baseViewController { - SyncEncryptionPassphraseCollectionViewController* controller = - [[SyncEncryptionPassphraseCollectionViewController alloc] + SyncEncryptionPassphraseTableViewController* controller = + [[SyncEncryptionPassphraseTableViewController alloc] initWithBrowserState:mainBrowserState_]; controller.dispatcher = [delegate_ dispatcherForSettings]; [self pushViewController:controller animated:YES];
diff --git a/ios/chrome/browser/ui/settings/sync_create_passphrase_collection_view_controller.h b/ios/chrome/browser/ui/settings/sync_create_passphrase_collection_view_controller.h deleted file mode 100644 index afbbc7ae..0000000 --- a/ios/chrome/browser/ui/settings/sync_create_passphrase_collection_view_controller.h +++ /dev/null
@@ -1,21 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_SYNC_CREATE_PASSPHRASE_COLLECTION_VIEW_CONTROLLER_H_ -#define IOS_CHROME_BROWSER_UI_SETTINGS_SYNC_CREATE_PASSPHRASE_COLLECTION_VIEW_CONTROLLER_H_ - -#import "ios/chrome/browser/ui/settings/sync_encryption_passphrase_collection_view_controller.h" - -@class UITextField; - -// Controller to allow user to specify encryption passphrase for Sync. -@interface SyncCreatePassphraseCollectionViewController - : SyncEncryptionPassphraseCollectionViewController -@end - -@interface SyncCreatePassphraseCollectionViewController (UsedForTesting) -@property(nonatomic, readonly) UITextField* confirmPassphrase; -@end - -#endif // IOS_CHROME_BROWSER_UI_SETTINGS_SYNC_CREATE_PASSPHRASE_COLLECTION_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/settings/sync_create_passphrase_table_view_controller.h b/ios/chrome/browser/ui/settings/sync_create_passphrase_table_view_controller.h new file mode 100644 index 0000000..ae42f73 --- /dev/null +++ b/ios/chrome/browser/ui/settings/sync_create_passphrase_table_view_controller.h
@@ -0,0 +1,19 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_SYNC_CREATE_PASSPHRASE_TABLE_VIEW_CONTROLLER_H_ +#define IOS_CHROME_BROWSER_UI_SETTINGS_SYNC_CREATE_PASSPHRASE_TABLE_VIEW_CONTROLLER_H_ + +#import "ios/chrome/browser/ui/settings/sync_encryption_passphrase_table_view_controller.h" + +// Controller to allow user to specify encryption passphrase for Sync. +@interface SyncCreatePassphraseTableViewController + : SyncEncryptionPassphraseTableViewController +@end + +@interface SyncCreatePassphraseTableViewController (UsedForTesting) +@property(nonatomic, readonly) UITextField* confirmPassphrase; +@end + +#endif // IOS_CHROME_BROWSER_UI_SETTINGS_SYNC_CREATE_PASSPHRASE_TABLE_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/settings/sync_create_passphrase_collection_view_controller.mm b/ios/chrome/browser/ui/settings/sync_create_passphrase_table_view_controller.mm similarity index 72% rename from ios/chrome/browser/ui/settings/sync_create_passphrase_collection_view_controller.mm rename to ios/chrome/browser/ui/settings/sync_create_passphrase_table_view_controller.mm index 7295678d..2e76c426 100644 --- a/ios/chrome/browser/ui/settings/sync_create_passphrase_collection_view_controller.mm +++ b/ios/chrome/browser/ui/settings/sync_create_passphrase_table_view_controller.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/ui/settings/sync_create_passphrase_collection_view_controller.h" +#import "ios/chrome/browser/ui/settings/sync_create_passphrase_table_view_controller.h" #import <UIKit/UIKit.h> @@ -10,11 +10,8 @@ #import "base/mac/foundation_util.h" #include "base/strings/sys_string_conversions.h" #include "components/strings/grit/components_strings.h" -#import "ios/chrome/browser/ui/collection_view/cells/collection_view_item.h" -#import "ios/chrome/browser/ui/collection_view/collection_view_model.h" #import "ios/chrome/browser/ui/settings/cells/byo_textfield_item.h" #include "ios/chrome/grit/ios_strings.h" -#import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h" #include "ui/base/l10n/l10n_util_mac.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -23,14 +20,14 @@ using namespace sync_encryption_passphrase; -@interface SyncCreatePassphraseCollectionViewController () { +@interface SyncCreatePassphraseTableViewController () { UITextField* confirmPassphrase_; } // Returns a confirm passphrase item. -- (CollectionViewItem*)confirmPassphraseItem; +- (TableViewItem*)confirmPassphraseItem; @end -@implementation SyncCreatePassphraseCollectionViewController +@implementation SyncCreatePassphraseTableViewController - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState { self = [super initWithBrowserState:browserState]; @@ -50,7 +47,7 @@ return self; } -#pragma mark - View lifecycle +#pragma mark - UIViewController - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; @@ -66,11 +63,11 @@ } } -#pragma mark - SettingsRootCollectionViewController +#pragma mark - SettingsRootTableViewController - (void)loadModel { [super loadModel]; - CollectionViewModel* model = self.collectionViewModel; + TableViewModel* model = self.tableViewModel; NSInteger enterPassphraseIndex = [model indexPathForItemType:ItemTypeEnterPassphrase @@ -83,16 +80,17 @@ #pragma mark - Items -- (CollectionViewItem*)confirmPassphraseItem { +- (TableViewItem*)confirmPassphraseItem { if (!confirmPassphrase_) { confirmPassphrase_ = [[UITextField alloc] init]; - [confirmPassphrase_ setSecureTextEntry:YES]; - [confirmPassphrase_ setBackgroundColor:[UIColor clearColor]]; - [confirmPassphrase_ setAutoresizingMask:UIViewAutoresizingFlexibleWidth]; - [confirmPassphrase_ setAutocorrectionType:UITextAutocorrectionTypeNo]; - [confirmPassphrase_ - setPlaceholder:l10n_util::GetNSString( - IDS_IOS_SYNC_CONFIRM_PASSPHRASE_LABEL)]; + confirmPassphrase_.secureTextEntry = YES; + confirmPassphrase_.backgroundColor = UIColor.clearColor; + confirmPassphrase_.autocorrectionType = UITextAutocorrectionTypeNo; + confirmPassphrase_.font = + [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; + confirmPassphrase_.adjustsFontForContentSizeCategory = YES; + confirmPassphrase_.placeholder = + l10n_util::GetNSString(IDS_IOS_SYNC_CONFIRM_PASSPHRASE_LABEL); [self registerTextField:confirmPassphrase_]; } @@ -102,19 +100,18 @@ return item; } -#pragma mark UICollectionViewDelegate +#pragma mark UITableViewDelegate -- (void)collectionView:(UICollectionView*)collectionView - didSelectItemAtIndexPath:(NSIndexPath*)indexPath { - [super collectionView:collectionView didSelectItemAtIndexPath:indexPath]; - NSInteger itemType = - [self.collectionViewModel itemTypeForIndexPath:indexPath]; +- (void)tableView:(UITableView*)tableView + didSelectRowAtIndexPath:(NSIndexPath*)indexPath { + [super tableView:tableView didSelectRowAtIndexPath:indexPath]; + NSInteger itemType = [self.tableViewModel itemTypeForIndexPath:indexPath]; if (itemType == ItemTypeConfirmPassphrase) { [confirmPassphrase_ becomeFirstResponder]; } } -#pragma mark SyncEncryptionPassphraseCollectionViewController +#pragma mark SyncEncryptionPassphraseTableViewController - (BOOL)forDecryption { return NO; @@ -168,7 +165,7 @@ @end -@implementation SyncCreatePassphraseCollectionViewController (UsedForTesting) +@implementation SyncCreatePassphraseTableViewController (UsedForTesting) - (UITextField*)confirmPassphrase { return confirmPassphrase_;
diff --git a/ios/chrome/browser/ui/settings/sync_create_passphrase_collection_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/sync_create_passphrase_table_view_controller_unittest.mm similarity index 72% rename from ios/chrome/browser/ui/settings/sync_create_passphrase_collection_view_controller_unittest.mm rename to ios/chrome/browser/ui/settings/sync_create_passphrase_table_view_controller_unittest.mm index 58d3fb5..ce38029 100644 --- a/ios/chrome/browser/ui/settings/sync_create_passphrase_collection_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/settings/sync_create_passphrase_table_view_controller_unittest.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/ui/settings/sync_create_passphrase_collection_view_controller.h" +#import "ios/chrome/browser/ui/settings/sync_create_passphrase_table_view_controller.h" #import <UIKit/UIKit.h> @@ -13,7 +13,7 @@ #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" #import "ios/chrome/browser/ui/settings/cells/byo_textfield_item.h" #import "ios/chrome/browser/ui/settings/cells/passphrase_error_item.h" -#import "ios/chrome/browser/ui/settings/passphrase_collection_view_controller_test.h" +#import "ios/chrome/browser/ui/settings/passphrase_table_view_controller_test.h" #include "ios/chrome/grit/ios_strings.h" #include "testing/gmock/include/gmock/gmock.h" #import "testing/gtest_mac.h" @@ -31,30 +31,28 @@ using testing::AtLeast; using testing::Return; -class SyncCreatePassphraseCollectionViewControllerTest - : public PassphraseCollectionViewControllerTest { +class SyncCreatePassphraseTableViewControllerTest + : public PassphraseTableViewControllerTest { public: - SyncCreatePassphraseCollectionViewControllerTest() {} + SyncCreatePassphraseTableViewControllerTest() {} protected: void TearDown() override { [SyncController() stopObserving]; - PassphraseCollectionViewControllerTest::TearDown(); + PassphraseTableViewControllerTest::TearDown(); } - CollectionViewController* InstantiateController() override { - return [[SyncCreatePassphraseCollectionViewController alloc] + ChromeTableViewController* InstantiateController() override { + return [[SyncCreatePassphraseTableViewController alloc] initWithBrowserState:chrome_browser_state_.get()]; } - SyncCreatePassphraseCollectionViewController* SyncController() { - return static_cast<SyncCreatePassphraseCollectionViewController*>( - controller()); + SyncCreatePassphraseTableViewController* SyncController() { + return static_cast<SyncCreatePassphraseTableViewController*>(controller()); } }; -TEST_F(SyncCreatePassphraseCollectionViewControllerTest, - TestConstructorDestructor) { +TEST_F(SyncCreatePassphraseTableViewControllerTest, TestConstructorDestructor) { CreateController(); CheckController(); EXPECT_CALL(*fake_sync_service_->GetUserSettingsMock(), @@ -64,25 +62,24 @@ [controller() viewDidAppear:YES]; } -TEST_F(SyncCreatePassphraseCollectionViewControllerTest, TestModel) { - SyncCreatePassphraseCollectionViewController* controller = SyncController(); - EXPECT_EQ(2, NumberOfSections()); +TEST_F(SyncCreatePassphraseTableViewControllerTest, TestModel) { + SyncCreatePassphraseTableViewController* controller = SyncController(); + EXPECT_EQ(1, NumberOfSections()); NSInteger const kSection = 0; EXPECT_EQ(2, NumberOfItemsInSection(kSection)); NSString* expectedTitle = l10n_util::GetNSString(IDS_IOS_SYNC_ENCRYPTION_CREATE_PASSPHRASE); CheckTitle(expectedTitle); // Passphrase item. - BYOTextFieldItem* passphraseItem = GetCollectionViewItem(kSection, 0); + BYOTextFieldItem* passphraseItem = GetTableViewItem(kSection, 0); EXPECT_NSEQ(controller.passphrase, passphraseItem.textField); // Confirm passphrase item. - BYOTextFieldItem* confirmPassphraseItem = GetCollectionViewItem(kSection, 1); + BYOTextFieldItem* confirmPassphraseItem = GetTableViewItem(kSection, 1); EXPECT_NSEQ(controller.confirmPassphrase, confirmPassphraseItem.textField); } -TEST_F(SyncCreatePassphraseCollectionViewControllerTest, TestAllFieldsFilled) { - SyncCreatePassphraseCollectionViewController* sync_controller = - SyncController(); +TEST_F(SyncCreatePassphraseTableViewControllerTest, TestAllFieldsFilled) { + SyncCreatePassphraseTableViewController* sync_controller = SyncController(); // Both text fields empty should return false. EXPECT_FALSE([sync_controller areAllFieldsFilled]); // One text field empty should return false. @@ -96,10 +93,8 @@ EXPECT_TRUE([sync_controller areAllFieldsFilled]); } -TEST_F(SyncCreatePassphraseCollectionViewControllerTest, - TestCredentialsOkPressed) { - SyncCreatePassphraseCollectionViewController* sync_controller = - SyncController(); +TEST_F(SyncCreatePassphraseTableViewControllerTest, TestCredentialsOkPressed) { + SyncCreatePassphraseTableViewController* sync_controller = SyncController(); EXPECT_CALL(*fake_sync_service_->GetUserSettingsMock(), SetEncryptionPassphrase(_)) .Times(0); @@ -107,9 +102,8 @@ [sync_controller signInPressed]; } -TEST_F(SyncCreatePassphraseCollectionViewControllerTest, TestNextTextField) { - SyncCreatePassphraseCollectionViewController* sync_controller = - SyncController(); +TEST_F(SyncCreatePassphraseTableViewControllerTest, TestNextTextField) { + SyncCreatePassphraseTableViewController* sync_controller = SyncController(); // The second call to -nextTextField is the same as hitting 'ok'. // With matching text, this should cause an attempt to set the passphrase. EXPECT_CALL(*fake_sync_service_, AddObserver(_)).Times(AtLeast(1)); @@ -124,10 +118,8 @@ [sync_controller textFieldDidEndEditing:[sync_controller confirmPassphrase]]; } -TEST_F(SyncCreatePassphraseCollectionViewControllerTest, - TestOneTextFieldEmpty) { - SyncCreatePassphraseCollectionViewController* sync_controller = - SyncController(); +TEST_F(SyncCreatePassphraseTableViewControllerTest, TestOneTextFieldEmpty) { + SyncCreatePassphraseTableViewController* sync_controller = SyncController(); EXPECT_CALL(*fake_sync_service_->GetUserSettingsMock(), SetEncryptionPassphrase(_)) .Times(0); @@ -139,10 +131,10 @@ EXPECT_FALSE([[sync_controller navigationItem].rightBarButtonItem isEnabled]); } -TEST_F(SyncCreatePassphraseCollectionViewControllerTest, - TestTextFieldsDoNotMatch) { - SyncCreatePassphraseCollectionViewController* sync_controller = - SyncController(); +// Tests that if user inputs incompatible passwords, an error message will be +// shown. If the user types again, the error messasge will be cleared. +TEST_F(SyncCreatePassphraseTableViewControllerTest, TestTextFieldsDoNotMatch) { + SyncCreatePassphraseTableViewController* sync_controller = SyncController(); // Mismatching text fields should not get to the point of trying to set the // passphrase and adding the sync observer. EXPECT_CALL(*fake_sync_service_, AddObserver(_)).Times(0); @@ -157,14 +149,23 @@ // Check the error cell. NSInteger const kSection = 0; EXPECT_EQ(3, NumberOfItemsInSection(kSection)); - PassphraseErrorItem* item = GetCollectionViewItem(kSection, 2); + PassphraseErrorItem* item = GetTableViewItem(kSection, 2); EXPECT_NSEQ(l10n_util::GetNSString(IDS_SYNC_PASSPHRASE_MISMATCH_ERROR), item.text); + + // User types again. + [sync_controller textFieldDidBeginEditing:sync_controller.confirmPassphrase]; + + // Check that error message is cleared. + EXPECT_EQ(2, NumberOfItemsInSection(kSection)); + EXPECT_FALSE([sync_controller.tableViewModel + hasItemForItemType:sync_encryption_passphrase::ItemTypeError + sectionIdentifier:sync_encryption_passphrase:: + SectionIdentifierPassphrase]); } -TEST_F(SyncCreatePassphraseCollectionViewControllerTest, TestTextFieldsMatch) { - SyncCreatePassphraseCollectionViewController* sync_controller = - SyncController(); +TEST_F(SyncCreatePassphraseTableViewControllerTest, TestTextFieldsMatch) { + SyncCreatePassphraseTableViewController* sync_controller = SyncController(); // Matching text should cause an attempt to set it and add a sync observer. EXPECT_CALL(*fake_sync_service_, AddObserver(_)).Times(AtLeast(1)); EXPECT_CALL(*fake_sync_service_, RemoveObserver(_)).Times(AtLeast(1)); @@ -176,9 +177,8 @@ [sync_controller signInPressed]; } -TEST_F(SyncCreatePassphraseCollectionViewControllerTest, TestOnStateChanged) { - SyncCreatePassphraseCollectionViewController* sync_controller = - SyncController(); +TEST_F(SyncCreatePassphraseTableViewControllerTest, TestOnStateChanged) { + SyncCreatePassphraseTableViewController* sync_controller = SyncController(); SetUpNavigationController(sync_controller); EXPECT_EQ([nav_controller_ topViewController], sync_controller); @@ -200,10 +200,9 @@ // TODO(crbug.com/658269): Re-enable test once it's been deflaked. // Verifies that sync errors don't make the navigation item disappear. // Regression test for http://crbug.com/501784. -TEST_F(SyncCreatePassphraseCollectionViewControllerTest, +TEST_F(SyncCreatePassphraseTableViewControllerTest, DISABLED_TestOnStateChangedError) { - SyncCreatePassphraseCollectionViewController* sync_controller = - SyncController(); + SyncCreatePassphraseTableViewController* sync_controller = SyncController(); SetUpNavigationController(sync_controller); EXPECT_EQ([nav_controller_ topViewController], sync_controller); EXPECT_NE(nil, sync_controller.title);
diff --git a/ios/chrome/browser/ui/settings/sync_encryption_passphrase_collection_view_controller.h b/ios/chrome/browser/ui/settings/sync_encryption_passphrase_table_view_controller.h similarity index 80% rename from ios/chrome/browser/ui/settings/sync_encryption_passphrase_collection_view_controller.h rename to ios/chrome/browser/ui/settings/sync_encryption_passphrase_table_view_controller.h index 0acdc49a..fc5e13b 100644 --- a/ios/chrome/browser/ui/settings/sync_encryption_passphrase_collection_view_controller.h +++ b/ios/chrome/browser/ui/settings/sync_encryption_passphrase_table_view_controller.h
@@ -2,14 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_SYNC_ENCRYPTION_PASSPHRASE_COLLECTION_VIEW_CONTROLLER_H_ -#define IOS_CHROME_BROWSER_UI_SETTINGS_SYNC_ENCRYPTION_PASSPHRASE_COLLECTION_VIEW_CONTROLLER_H_ +#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_SYNC_ENCRYPTION_PASSPHRASE_TABLE_VIEW_CONTROLLER_H_ +#define IOS_CHROME_BROWSER_UI_SETTINGS_SYNC_ENCRYPTION_PASSPHRASE_TABLE_VIEW_CONTROLLER_H_ #import <UIKit/UIKit.h> #import "ios/chrome/browser/sync/sync_observer_bridge.h" -#import "ios/chrome/browser/ui/collection_view/collection_view_model.h" -#import "ios/chrome/browser/ui/settings/settings_root_collection_view_controller.h" +#import "ios/chrome/browser/ui/settings/settings_root_table_view_controller.h" namespace ios { class ChromeBrowserState; @@ -18,7 +17,6 @@ namespace sync_encryption_passphrase { typedef NS_ENUM(NSInteger, SectionIdentifier) { SectionIdentifierPassphrase = kSectionIdentifierEnumZero, - SectionIdentifierFooter, }; typedef NS_ENUM(NSInteger, ItemType) { ItemTypeMessage = kItemTypeEnumZero, @@ -30,8 +28,8 @@ } // namespace sync_encryption_passphrase // Controller to allow user to specify encryption passphrase for Sync. -@interface SyncEncryptionPassphraseCollectionViewController - : SettingsRootCollectionViewController<SyncObserverModelBridge> +@interface SyncEncryptionPassphraseTableViewController + : SettingsRootTableViewController <SyncObserverModelBridge> @property(weak, nonatomic, readonly) UITextField* passphrase; @property(nonatomic, copy) NSString* headerMessage; @@ -42,14 +40,15 @@ // |browserState| must not be nil. - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState NS_DESIGNATED_INITIALIZER; -- (instancetype)initWithLayout:(UICollectionViewLayout*)layout - style:(CollectionViewControllerStyle)style +- (instancetype)initWithTableViewStyle:(UITableViewStyle)style + appBarStyle: + (ChromeTableViewControllerStyle)appBarStyle NS_UNAVAILABLE; @end -@interface SyncEncryptionPassphraseCollectionViewController ( - Subclassing)<UITextFieldDelegate> +@interface SyncEncryptionPassphraseTableViewController (Subclassing) < + UITextFieldDelegate> // Whether this controller is for encryption or decryption. Returns |YES|, if // the used for the user to enter an existing passphrase that is not yet @@ -87,4 +86,4 @@ @end -#endif // IOS_CHROME_BROWSER_UI_SETTINGS_SYNC_ENCRYPTION_PASSPHRASE_COLLECTION_VIEW_CONTROLLER_H_ +#endif // IOS_CHROME_BROWSER_UI_SETTINGS_SYNC_ENCRYPTION_PASSPHRASE_TABLE_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/settings/sync_encryption_passphrase_collection_view_controller.mm b/ios/chrome/browser/ui/settings/sync_encryption_passphrase_table_view_controller.mm similarity index 71% rename from ios/chrome/browser/ui/settings/sync_encryption_passphrase_collection_view_controller.mm rename to ios/chrome/browser/ui/settings/sync_encryption_passphrase_table_view_controller.mm index 3ac6686..5b3d4343 100644 --- a/ios/chrome/browser/ui/settings/sync_encryption_passphrase_collection_view_controller.mm +++ b/ios/chrome/browser/ui/settings/sync_encryption_passphrase_table_view_controller.mm
@@ -2,13 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/ui/settings/sync_encryption_passphrase_collection_view_controller.h" - -#include <memory> +#import "ios/chrome/browser/ui/settings/sync_encryption_passphrase_table_view_controller.h" #include "base/i18n/time_formatting.h" #include "base/mac/foundation_util.h" - #include "base/strings/sys_string_conversions.h" #include "components/browser_sync/profile_sync_service.h" #include "components/google/core/common/google_util.h" @@ -24,22 +21,16 @@ #include "ios/chrome/browser/sync/profile_sync_service_factory.h" #include "ios/chrome/browser/sync/sync_setup_service.h" #include "ios/chrome/browser/sync/sync_setup_service_factory.h" -#import "ios/chrome/browser/ui/collection_view/cells/MDCCollectionViewCell+Chrome.h" -#import "ios/chrome/browser/ui/collection_view/cells/collection_view_cell_constants.h" -#import "ios/chrome/browser/ui/collection_view/cells/collection_view_footer_item.h" -#import "ios/chrome/browser/ui/collection_view/cells/collection_view_item.h" -#import "ios/chrome/browser/ui/collection_view/collection_view_model.h" -#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" #import "ios/chrome/browser/ui/settings/cells/byo_textfield_item.h" #import "ios/chrome/browser/ui/settings/cells/card_multiline_item.h" #import "ios/chrome/browser/ui/settings/cells/passphrase_error_item.h" #import "ios/chrome/browser/ui/settings/settings_navigation_controller.h" #import "ios/chrome/browser/ui/settings/settings_utils.h" #import "ios/chrome/browser/ui/settings/sync_utils/sync_util.h" +#import "ios/chrome/browser/ui/table_view/cells/table_view_link_header_footer_item.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" #include "ios/chrome/grit/ios_strings.h" #import "ios/public/provider/chrome/browser/signin/chrome_identity.h" -#import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util_mac.h" #include "url/gurl.h" @@ -57,7 +48,7 @@ } // namespace -@interface SyncEncryptionPassphraseCollectionViewController ()< +@interface SyncEncryptionPassphraseTableViewController () < OAuth2TokenServiceObserverBridgeDelegate, SettingsControllerProtocol> { ios::ChromeBrowserState* browserState_; @@ -70,46 +61,15 @@ UITextField* passphrase_; } -// Sets up the navigation bar's right button. The button will be enabled iff -// |-areAllFieldsFilled| returns YES. -- (void)setRightNavBarItem; - -// Returns a passphrase message item. -- (CollectionViewItem*)passphraseMessageItem; - -// Returns a passphrase item. -- (CollectionViewItem*)passphraseItem; - -// Returns a passphrase error item having |errorMessage| as title. -- (CollectionViewItem*)passphraseErrorItemWithMessage:(NSString*)errorMessage; - -// Shows the UI to indicate the decryption is being attempted. -- (void)showDecryptionProgress; - -// Hides the UI to indicate decryption is in process. -- (void)hideDecryptionProgress; - -// Returns a transparent content view object to be used as a footer, or nil -// for no footer. -- (CollectionViewItem*)footerItem; - -// Creates a new UIBarButtonItem with a spinner. -- (UIBarButtonItem*)spinnerButton; - @end -@implementation SyncEncryptionPassphraseCollectionViewController - -@synthesize headerMessage = headerMessage_; -@synthesize footerMessage = footerMessage_; -@synthesize processingMessage = processingMessage_; -@synthesize syncErrorMessage = syncErrorMessage_; +@implementation SyncEncryptionPassphraseTableViewController - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState { DCHECK(browserState); - UICollectionViewLayout* layout = [[MDCCollectionViewFlowLayout alloc] init]; self = - [super initWithLayout:layout style:CollectionViewControllerStyleAppBar]; + [super initWithTableViewStyle:UITableViewStyleGrouped + appBarStyle:ChromeTableViewControllerStyleWithAppBar]; if (self) { self.title = l10n_util::GetNSString(IDS_IOS_SYNC_ENTER_PASSPHRASE_TITLE); self.shouldHideDoneButton = YES; @@ -126,28 +86,24 @@ if (!passphrase_time.is_null()) { base::string16 passphrase_time_str = base::TimeFormatShortDate(passphrase_time); - self.headerMessage = l10n_util::GetNSStringF( + _headerMessage = l10n_util::GetNSStringF( IDS_IOS_SYNC_ENTER_PASSPHRASE_BODY_WITH_EMAIL_AND_DATE, base::SysNSStringToUTF16(userEmail), passphrase_time_str); } else { - self.headerMessage = l10n_util::GetNSStringF( + _headerMessage = l10n_util::GetNSStringF( IDS_IOS_SYNC_ENTER_PASSPHRASE_BODY_WITH_EMAIL, base::SysNSStringToUTF16(userEmail)); } } else { - self.headerMessage = + _headerMessage = l10n_util::GetNSString(IDS_SYNC_ENTER_GOOGLE_PASSPHRASE_BODY); } - self.processingMessage = l10n_util::GetNSString(IDS_SYNC_LOGIN_SETTING_UP); - footerMessage_ = l10n_util::GetNSString(IDS_IOS_SYNC_PASSPHRASE_RECOVER); + _processingMessage = l10n_util::GetNSString(IDS_SYNC_LOGIN_SETTING_UP); + _footerMessage = l10n_util::GetNSString(IDS_IOS_SYNC_PASSPHRASE_RECOVER); tokenServiceObserver_.reset(new OAuth2TokenServiceObserverBridge( ProfileOAuth2TokenServiceFactory::GetForBrowserState(browserState_), self)); - - // TODO(crbug.com/764578): -loadModel should not be called from - // initializer. A possible fix is to move this call to -viewDidLoad. - [self loadModel]; } return self; } @@ -157,15 +113,15 @@ } - (NSString*)syncErrorMessage { - if (syncErrorMessage_) - return syncErrorMessage_; + if (_syncErrorMessage) + return _syncErrorMessage; SyncSetupService* service = SyncSetupServiceFactory::GetForBrowserState(browserState_); DCHECK(service); SyncSetupService::SyncServiceState syncServiceState = service->GetSyncServiceState(); - // Passphrase error directly set |syncErrorMessage_|. + // Passphrase error directly set |_syncErrorMessage|. if (syncServiceState == SyncSetupService::kSyncServiceNeedsPassphrase) return nil; @@ -176,6 +132,7 @@ - (void)viewDidLoad { [super viewDidLoad]; + [self loadModel]; [self setRightNavBarItem]; } @@ -198,11 +155,11 @@ } } -#pragma mark - SettingsRootCollectionViewController +#pragma mark - SettingsRootTableViewController - (void)loadModel { [super loadModel]; - CollectionViewModel* model = self.collectionViewModel; + TableViewModel* model = self.tableViewModel; [model addSectionWithIdentifier:SectionIdentifierPassphrase]; if (self.headerMessage) { @@ -217,33 +174,32 @@ [model addItem:[self passphraseErrorItemWithMessage:errorMessage] toSectionWithIdentifier:SectionIdentifierPassphrase]; } - // TODO(crbug.com/650424): Footer items must currently go into a separate - // section, to work around a drawing bug in MDC. - [model addSectionWithIdentifier:SectionIdentifierFooter]; - [model addItem:[self footerItem] - toSectionWithIdentifier:SectionIdentifierFooter]; + [model setFooter:[self footerItem] + forSectionWithIdentifier:SectionIdentifierPassphrase]; } #pragma mark - Items -- (CollectionViewItem*)passphraseMessageItem { +// Returns a passphrase message item. +- (TableViewItem*)passphraseMessageItem { CardMultilineItem* item = [[CardMultilineItem alloc] initWithType:ItemTypeMessage]; - item.text = headerMessage_; + item.text = self.headerMessage; return item; } -- (CollectionViewItem*)passphraseItem { +// Returns a passphrase item. +- (TableViewItem*)passphraseItem { if (passphrase_) { [self unregisterTextField:passphrase_]; } passphrase_ = [[UITextField alloc] init]; - [passphrase_ setSecureTextEntry:YES]; - [passphrase_ setBackgroundColor:[UIColor clearColor]]; - [passphrase_ setAutoresizingMask:UIViewAutoresizingFlexibleWidth]; - [passphrase_ setAutocorrectionType:UITextAutocorrectionTypeNo]; - [passphrase_ - setPlaceholder:l10n_util::GetNSString(IDS_SYNC_PASSPHRASE_LABEL)]; + passphrase_.secureTextEntry = YES; + passphrase_.backgroundColor = UIColor.clearColor; + passphrase_.autocorrectionType = UITextAutocorrectionTypeNo; + passphrase_.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; + passphrase_.adjustsFontForContentSizeCategory = YES; + passphrase_.placeholder = l10n_util::GetNSString(IDS_SYNC_PASSPHRASE_LABEL); [self registerTextField:passphrase_]; BYOTextFieldItem* item = @@ -252,77 +208,47 @@ return item; } -- (CollectionViewItem*)passphraseErrorItemWithMessage:(NSString*)errorMessage { +// Returns a passphrase error item having |errorMessage| as title. +- (TableViewItem*)passphraseErrorItemWithMessage:(NSString*)errorMessage { PassphraseErrorItem* item = [[PassphraseErrorItem alloc] initWithType:ItemTypeError]; item.text = errorMessage; return item; } -- (CollectionViewItem*)footerItem { - CollectionViewFooterItem* footerItem = - [[CollectionViewFooterItem alloc] initWithType:ItemTypeFooter]; - footerItem.cellStyle = CollectionViewCellStyle::kUIKit; +// Returns the footer item for passphrase section. +- (TableViewHeaderFooterItem*)footerItem { + TableViewLinkHeaderFooterItem* footerItem = + [[TableViewLinkHeaderFooterItem alloc] initWithType:ItemTypeFooter]; footerItem.text = self.footerMessage; footerItem.linkURL = google_util::AppendGoogleLocaleParam( GURL(kSyncGoogleDashboardURL), GetApplicationContext()->GetApplicationLocale()); - footerItem.linkDelegate = self; return footerItem; } -#pragma mark - MDCCollectionViewStylingDelegate +#pragma mark - UITableViewDelegate -- (MDCCollectionViewCellStyle)collectionView:(UICollectionView*)collectionView - cellStyleForSection:(NSInteger)section { - NSInteger sectionIdentifier = - [self.collectionViewModel sectionIdentifierForSection:section]; - switch (sectionIdentifier) { - case SectionIdentifierFooter: - // Display the Learn More footer in the default style with no "card" UI - // and no section padding. - return MDCCollectionViewCellStyleDefault; - default: - return self.styler.cellStyle; - } -} - -- (BOOL)collectionView:(UICollectionView*)collectionView - shouldHideItemBackgroundAtIndexPath:(NSIndexPath*)indexPath { - NSInteger sectionIdentifier = - [self.collectionViewModel sectionIdentifierForSection:indexPath.section]; - switch (sectionIdentifier) { - case SectionIdentifierFooter: - // Display the Learn More footer without any background image or - // shadowing. - return YES; - default: - return NO; - } -} - -- (CGFloat)collectionView:(UICollectionView*)collectionView - cellHeightAtIndexPath:(NSIndexPath*)indexPath { - CollectionViewItem* item = - [self.collectionViewModel itemAtIndexPath:indexPath]; - if (item.type == ItemTypeMessage || item.type == ItemTypeFooter) { - return [MDCCollectionViewCell - cr_preferredHeightForWidth:CGRectGetWidth(collectionView.bounds) - forItem:item]; - } - return MDCCellDefaultOneLineHeight; -} - -#pragma mark - UICollectionViewDelegate - -- (void)collectionView:(UICollectionView*)collectionView - didSelectItemAtIndexPath:(NSIndexPath*)indexPath { - [super collectionView:collectionView didSelectItemAtIndexPath:indexPath]; - NSInteger itemType = - [self.collectionViewModel itemTypeForIndexPath:indexPath]; +- (void)tableView:(UITableView*)tableView + didSelectRowAtIndexPath:(NSIndexPath*)indexPath { + [super tableView:tableView didSelectRowAtIndexPath:indexPath]; + NSInteger itemType = [self.tableViewModel itemTypeForIndexPath:indexPath]; if (itemType == ItemTypeEnterPassphrase) { [passphrase_ becomeFirstResponder]; } + [tableView deselectRowAtIndexPath:indexPath animated:YES]; +} + +- (UIView*)tableView:(UITableView*)tableView + viewForFooterInSection:(NSInteger)section { + UIView* view = [super tableView:tableView viewForFooterInSection:section]; + if (SectionIdentifierPassphrase == + [self.tableViewModel sectionIdentifierForSection:section]) { + TableViewLinkHeaderFooterView* linkView = + base::mac::ObjCCastStrict<TableViewLinkHeaderFooterView>(view); + linkView.delegate = self; + } + return view; } #pragma mark - Behavior @@ -370,6 +296,8 @@ [self reloadData]; } +// Sets up the navigation bar's right button. The button will be enabled iff +// |-areAllFieldsFilled| returns YES. - (void)setRightNavBarItem { UIBarButtonItem* submitButtonItem = self.navigationItem.rightBarButtonItem; if (!submitButtonItem) { @@ -395,6 +323,7 @@ [self.passphrase setText:@""]; } +// Shows the UI to indicate the decryption is being attempted. - (void)showDecryptionProgress { if (isDecryptionProgressShown_) return; @@ -409,9 +338,10 @@ savedLeftButton_ = self.navigationItem.leftBarButtonItem; self.navigationItem.leftBarButtonItem = [self spinnerButton]; savedTitle_ = [self.title copy]; - self.title = processingMessage_; + self.title = self.processingMessage; } +// Hides the UI to indicate decryption is in process. - (void)hideDecryptionProgress { if (!isDecryptionProgressShown_) return; @@ -448,6 +378,7 @@ forControlEvents:UIControlEventEditingDidEndOnExit]; } +// Creates a new UIBarButtonItem with a spinner. - (UIBarButtonItem*)spinnerButton { CGRect customViewFrame = CGRectMake(0, 0, kSpinnerButtonCustomViewSize, kSpinnerButtonCustomViewSize); @@ -483,17 +414,17 @@ - (void)textFieldDidBeginEditing:(id)sender { // Remove the error cell if there is one. - CollectionViewModel* model = self.collectionViewModel; - NSInteger section = - [model sectionForSectionIdentifier:SectionIdentifierPassphrase]; - NSIndexPath* errorIndexPath = - [NSIndexPath indexPathForItem:ItemTypeError inSection:section]; - if ([model hasItemAtIndexPath:errorIndexPath] && - [model itemTypeForIndexPath:errorIndexPath] == ItemTypeError) { + TableViewModel* model = self.tableViewModel; + if ([model hasItemForItemType:ItemTypeError + sectionIdentifier:SectionIdentifierPassphrase]) { DCHECK(self.syncErrorMessage); + NSIndexPath* path = + [model indexPathForItemType:ItemTypeError + sectionIdentifier:SectionIdentifierPassphrase]; [model removeItemWithType:ItemTypeError fromSectionWithIdentifier:SectionIdentifierPassphrase]; - [self.collectionView deleteItemsAtIndexPaths:@[ errorIndexPath ]]; + [self.tableView deleteRowsAtIndexPaths:@[ path ] + withRowAnimation:UITableViewRowAnimationAutomatic]; self.syncErrorMessage = nil; } }
diff --git a/ios/chrome/browser/ui/settings/sync_encryption_passphrase_collection_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/sync_encryption_passphrase_table_view_controller_unittest.mm similarity index 80% rename from ios/chrome/browser/ui/settings/sync_encryption_passphrase_collection_view_controller_unittest.mm rename to ios/chrome/browser/ui/settings/sync_encryption_passphrase_table_view_controller_unittest.mm index c2e1cc2..b2de154 100644 --- a/ios/chrome/browser/ui/settings/sync_encryption_passphrase_collection_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/settings/sync_encryption_passphrase_table_view_controller_unittest.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/ui/settings/sync_encryption_passphrase_collection_view_controller.h" +#import "ios/chrome/browser/ui/settings/sync_encryption_passphrase_table_view_controller.h" #import <UIKit/UIKit.h> @@ -20,7 +20,7 @@ #include "ios/chrome/browser/sync/sync_setup_service_mock.h" #import "ios/chrome/browser/ui/settings/cells/byo_textfield_item.h" #import "ios/chrome/browser/ui/settings/cells/card_multiline_item.h" -#import "ios/chrome/browser/ui/settings/passphrase_collection_view_controller_test.h" +#import "ios/chrome/browser/ui/settings/passphrase_table_view_controller_test.h" #import "ios/chrome/browser/ui/settings/sync_utils/sync_util.h" #import "testing/gtest_mac.h" #include "testing/platform_test.h" @@ -38,10 +38,10 @@ using testing::NiceMock; using testing::Return; -class SyncEncryptionPassphraseCollectionViewControllerTest - : public PassphraseCollectionViewControllerTest { +class SyncEncryptionPassphraseTableViewControllerTest + : public PassphraseTableViewControllerTest { public: - SyncEncryptionPassphraseCollectionViewControllerTest() {} + SyncEncryptionPassphraseTableViewControllerTest() {} static std::unique_ptr<KeyedService> CreateSyncSetupService( web::BrowserState* context) { @@ -69,7 +69,7 @@ protected: void SetUp() override { - PassphraseCollectionViewControllerTest::SetUp(); + PassphraseTableViewControllerTest::SetUp(); mock_sync_setup_service_ = static_cast<NiceMock<SyncSetupServiceMock>*>( SyncSetupServiceFactory::GetInstance()->SetTestingFactoryAndUse( chrome_browser_state_.get(), @@ -82,16 +82,16 @@ void TearDown() override { [SyncController() stopObserving]; - PassphraseCollectionViewControllerTest::TearDown(); + PassphraseTableViewControllerTest::TearDown(); } - CollectionViewController* InstantiateController() override { - return [[SyncEncryptionPassphraseCollectionViewController alloc] + ChromeTableViewController* InstantiateController() override { + return [[SyncEncryptionPassphraseTableViewController alloc] initWithBrowserState:chrome_browser_state_.get()]; } - SyncEncryptionPassphraseCollectionViewController* SyncController() { - return static_cast<SyncEncryptionPassphraseCollectionViewController*>( + SyncEncryptionPassphraseTableViewController* SyncController() { + return static_cast<SyncEncryptionPassphraseTableViewController*>( controller()); } @@ -99,21 +99,20 @@ NiceMock<SyncSetupServiceMock>* mock_sync_setup_service_; }; -TEST_F(SyncEncryptionPassphraseCollectionViewControllerTest, TestModel) { - SyncEncryptionPassphraseCollectionViewController* controller = - SyncController(); - EXPECT_EQ(2, NumberOfSections()); +TEST_F(SyncEncryptionPassphraseTableViewControllerTest, TestModel) { + SyncEncryptionPassphraseTableViewController* controller = SyncController(); + EXPECT_EQ(1, NumberOfSections()); EXPECT_EQ(2, NumberOfItemsInSection(0)); // Passphrase message item. - CardMultilineItem* item = GetCollectionViewItem(0, 0); + CardMultilineItem* item = GetTableViewItem(0, 0); EXPECT_NSEQ(l10n_util::GetNSString(IDS_SYNC_ENTER_GOOGLE_PASSPHRASE_BODY), item.text); // Passphrase items. - BYOTextFieldItem* passphraseItem = GetCollectionViewItem(0, 1); + BYOTextFieldItem* passphraseItem = GetTableViewItem(0, 1); EXPECT_NSEQ(controller.passphrase, passphraseItem.textField); } -TEST_F(SyncEncryptionPassphraseCollectionViewControllerTest, +TEST_F(SyncEncryptionPassphraseTableViewControllerTest, TestConstructorDestructor) { CreateController(); CheckController(); @@ -125,9 +124,8 @@ [controller() viewDidAppear:YES]; } -TEST_F(SyncEncryptionPassphraseCollectionViewControllerTest, - TestDecryptButton) { - SyncEncryptionPassphraseCollectionViewController* sync_controller = +TEST_F(SyncEncryptionPassphraseTableViewControllerTest, TestDecryptButton) { + SyncEncryptionPassphraseTableViewController* sync_controller = SyncController(); [sync_controller textFieldDidChange:[sync_controller passphrase]]; EXPECT_FALSE([[sync_controller navigationItem].rightBarButtonItem isEnabled]); @@ -136,9 +134,9 @@ EXPECT_TRUE([[sync_controller navigationItem].rightBarButtonItem isEnabled]); } -TEST_F(SyncEncryptionPassphraseCollectionViewControllerTest, +TEST_F(SyncEncryptionPassphraseTableViewControllerTest, TestDecryptWrongPassphrase) { - SyncEncryptionPassphraseCollectionViewController* sync_controller = + SyncEncryptionPassphraseTableViewController* sync_controller = SyncController(); EXPECT_CALL(*fake_sync_service_, AddObserver(_)).Times(AtLeast(1)); EXPECT_CALL(*fake_sync_service_, RemoveObserver(_)).Times(AtLeast(1)); @@ -152,9 +150,9 @@ [sync_controller signInPressed]; } -TEST_F(SyncEncryptionPassphraseCollectionViewControllerTest, +TEST_F(SyncEncryptionPassphraseTableViewControllerTest, TestDecryptCorrectPassphrase) { - SyncEncryptionPassphraseCollectionViewController* sync_controller = + SyncEncryptionPassphraseTableViewController* sync_controller = SyncController(); EXPECT_CALL(*fake_sync_service_, AddObserver(_)).Times(AtLeast(1)); EXPECT_CALL(*fake_sync_service_, RemoveObserver(_)).Times(AtLeast(1)); @@ -168,9 +166,9 @@ [sync_controller signInPressed]; } -TEST_F(SyncEncryptionPassphraseCollectionViewControllerTest, +TEST_F(SyncEncryptionPassphraseTableViewControllerTest, TestOnStateChangedWrongPassphrase) { - SyncEncryptionPassphraseCollectionViewController* sync_controller = + SyncEncryptionPassphraseTableViewController* sync_controller = SyncController(); // Sets up a UINavigationController that has |controller_| as the second view // controller on the navigation stack. @@ -186,9 +184,9 @@ EXPECT_EQ([nav_controller_ topViewController], sync_controller); } -TEST_F(SyncEncryptionPassphraseCollectionViewControllerTest, +TEST_F(SyncEncryptionPassphraseTableViewControllerTest, TestOnStateChangedCorrectPassphrase) { - SyncEncryptionPassphraseCollectionViewController* sync_controller = + SyncEncryptionPassphraseTableViewController* sync_controller = SyncController(); // Sets up a UINavigationController that has |controller_| as the second view // controller on the navigation stack. @@ -210,8 +208,8 @@ })); } -TEST_F(SyncEncryptionPassphraseCollectionViewControllerTest, TestMessage) { - SyncEncryptionPassphraseCollectionViewController* sync_controller = +TEST_F(SyncEncryptionPassphraseTableViewControllerTest, TestMessage) { + SyncEncryptionPassphraseTableViewController* sync_controller = SyncController(); // Default. EXPECT_FALSE([sync_controller syncErrorMessage]);
diff --git a/ios/chrome/browser/ui/settings/sync_encryption_table_view_controller.mm b/ios/chrome/browser/ui/settings/sync_encryption_table_view_controller.mm index b9f62eb..c6170c6b 100644 --- a/ios/chrome/browser/ui/settings/sync_encryption_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/sync_encryption_table_view_controller.mm
@@ -19,8 +19,8 @@ #import "ios/chrome/browser/sync/sync_observer_bridge.h" #import "ios/chrome/browser/ui/settings/cells/encryption_item.h" #import "ios/chrome/browser/ui/settings/settings_utils.h" -#import "ios/chrome/browser/ui/settings/sync_create_passphrase_collection_view_controller.h" -#import "ios/chrome/browser/ui/settings/sync_encryption_passphrase_collection_view_controller.h" +#import "ios/chrome/browser/ui/settings/sync_create_passphrase_table_view_controller.h" +#import "ios/chrome/browser/ui/settings/sync_encryption_passphrase_table_view_controller.h" #import "ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h" #import "ios/chrome/browser/ui/table_view/cells/table_view_item.h" #import "ios/chrome/browser/ui/table_view/cells/table_view_link_header_footer_item.h" @@ -180,10 +180,14 @@ ProfileSyncServiceFactory::GetForBrowserState(_browserState); if (service->IsEngineInitialized() && !service->IsUsingSecondaryPassphrase()) { - SyncCreatePassphraseCollectionViewController* controller = - [[SyncCreatePassphraseCollectionViewController alloc] + SyncCreatePassphraseTableViewController* controller = + [[SyncCreatePassphraseTableViewController alloc] initWithBrowserState:_browserState]; - [self.navigationController pushViewController:controller animated:YES]; + if (controller) { + controller.dispatcher = self.dispatcher; + [self.navigationController pushViewController:controller + animated:YES]; + } } break; }
diff --git a/ios/chrome/browser/ui/settings/sync_settings_collection_view_controller.mm b/ios/chrome/browser/ui/settings/sync_settings_collection_view_controller.mm index d030a2e..eab0fb2 100644 --- a/ios/chrome/browser/ui/settings/sync_settings_collection_view_controller.mm +++ b/ios/chrome/browser/ui/settings/sync_settings_collection_view_controller.mm
@@ -43,7 +43,7 @@ #import "ios/chrome/browser/ui/settings/cells/sync_switch_item.h" #import "ios/chrome/browser/ui/settings/cells/text_and_error_item.h" #import "ios/chrome/browser/ui/settings/settings_navigation_controller.h" -#import "ios/chrome/browser/ui/settings/sync_encryption_passphrase_collection_view_controller.h" +#import "ios/chrome/browser/ui/settings/sync_encryption_passphrase_table_view_controller.h" #import "ios/chrome/browser/ui/settings/sync_encryption_table_view_controller.h" #import "ios/chrome/browser/ui/settings/sync_utils/sync_util.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" @@ -766,7 +766,7 @@ // If there was a sync error, prompt the user to enter the passphrase. // Otherwise, show the full encryption options. if (syncService->IsPassphraseRequired()) { - controllerToPush = [[SyncEncryptionPassphraseCollectionViewController alloc] + controllerToPush = [[SyncEncryptionPassphraseTableViewController alloc] initWithBrowserState:_browserState]; } else { controllerToPush = [[SyncEncryptionTableViewController alloc]
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm index f1e635c3..2d4ff0ba 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
@@ -208,6 +208,8 @@ incognitoBrowserState:self.incognitoTabModel.browserState]; self.adaptor.loader = self.URLLoader; baseViewController.remoteTabsViewController.loader = self.URLLoader; + baseViewController.remoteTabsViewController.restoredTabDisposition = + WindowOpenDisposition::NEW_FOREGROUND_TAB; baseViewController.remoteTabsViewController.presentationDelegate = self; // Insert the launch screen view in front of this view to hide it until after
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_url_loader.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_url_loader.mm index 3200257..8f0891b 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_url_loader.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_url_loader.mm
@@ -5,12 +5,8 @@ #import "ios/chrome/browser/ui/tab_grid/tab_grid_url_loader.h" #include "components/sessions/core/session_types.h" -#include "components/sessions/core/tab_restore_service.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" -#include "ios/chrome/browser/sessions/ios_chrome_tab_restore_service_factory.h" #include "ios/chrome/browser/sessions/session_util.h" -#include "ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios.h" -#include "ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios_factory.h" #include "ios/chrome/browser/ui/commands/open_new_tab_command.h" #import "ios/chrome/browser/web_state_list/web_state_list.h" #include "ios/chrome/browser/web_state_list/web_state_opener.h" @@ -105,17 +101,4 @@ AppendAndActivateWebState(self.regularWebStateList, std::move(webState)); } -// Restores |sessionID| in a new foreground tab, instead of replacing the active -// tab. -- (void)restoreTabWithSessionID:(const SessionID)sessionID { - TabRestoreServiceDelegateImplIOS* delegate = - TabRestoreServiceDelegateImplIOSFactory::GetForBrowserState( - self.regularBrowserState); - sessions::TabRestoreService* restoreService = - IOSChromeTabRestoreServiceFactory::GetForBrowserState( - self.regularBrowserState); - restoreService->RestoreEntryById(delegate, sessionID, - WindowOpenDisposition::NEW_FOREGROUND_TAB); -} - @end
diff --git a/ios/chrome/browser/ui/url_loader.h b/ios/chrome/browser/ui/url_loader.h index 17392626..3d9310e 100644 --- a/ios/chrome/browser/ui/url_loader.h +++ b/ios/chrome/browser/ui/url_loader.h
@@ -5,10 +5,8 @@ #ifndef IOS_CHROME_BROWSER_UI_URL_LOADER_H_ #define IOS_CHROME_BROWSER_UI_URL_LOADER_H_ -#import <UIKit/UIKit.h> +#import <Foundation/Foundation.h> -#include "base/strings/string16.h" -#include "components/sessions/core/session_id.h" #import "ios/chrome/browser/ui/chrome_load_params.h" @class OpenNewTabCommand; @@ -17,7 +15,7 @@ struct SessionTab; } -@protocol UrlLoader<NSObject> +@protocol UrlLoader // Load a new request. // TODO(crbug.com/907527): Check if it is possible to merge with the other way @@ -35,9 +33,6 @@ // Load a tab with the given session. - (void)loadSessionTab:(const sessions::SessionTab*)sessionTab; -// Restores a closed tab with |sessionID|. -- (void)restoreTabWithSessionID:(const SessionID)sessionID; - @end #endif // IOS_CHROME_BROWSER_UI_URL_LOADER_H_
diff --git a/ios/chrome/browser/url_loading/BUILD.gn b/ios/chrome/browser/url_loading/BUILD.gn index 5418c47..7361530 100644 --- a/ios/chrome/browser/url_loading/BUILD.gn +++ b/ios/chrome/browser/url_loading/BUILD.gn
@@ -10,8 +10,12 @@ ] deps = [ "//base", + "//components/sessions", + "//ios/chrome/browser/browser_state", "//ios/chrome/browser/prerender", + "//ios/chrome/browser/sessions", "//ios/web/public", + "//ui/base", "//url", ] }
diff --git a/ios/chrome/browser/url_loading/url_loading_util.h b/ios/chrome/browser/url_loading/url_loading_util.h index cc9f752..c2cc58e 100644 --- a/ios/chrome/browser/url_loading/url_loading_util.h +++ b/ios/chrome/browser/url_loading/url_loading_util.h
@@ -7,6 +7,9 @@ #import <Foundation/Foundation.h> +#include "components/sessions/core/session_id.h" +#include "ui/base/window_open_disposition.h" + class GURL; namespace ios { class ChromeBrowserState; @@ -22,4 +25,8 @@ ios::ChromeBrowserState* browserState, web::WebState* webState); +void RestoreTab(const SessionID sessionID, + WindowOpenDisposition disposition, + ios::ChromeBrowserState* browserState); + #endif // IOS_CHROME_BROWSER_URL_LOADING_URL_LOADING_UTIL_H_
diff --git a/ios/chrome/browser/url_loading/url_loading_util.mm b/ios/chrome/browser/url_loading/url_loading_util.mm index 40a864f..1d277d4 100644 --- a/ios/chrome/browser/url_loading/url_loading_util.mm +++ b/ios/chrome/browser/url_loading/url_loading_util.mm
@@ -5,8 +5,13 @@ #import "ios/chrome/browser/url_loading/url_loading_util.h" #include "base/strings/sys_string_conversions.h" +#include "components/sessions/core/tab_restore_service_helper.h" +#include "ios/chrome/browser/browser_state/chrome_browser_state.h" #import "ios/chrome/browser/prerender/prerender_service.h" #import "ios/chrome/browser/prerender/prerender_service_factory.h" +#include "ios/chrome/browser/sessions/ios_chrome_tab_restore_service_factory.h" +#include "ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios.h" +#include "ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios_factory.h" #import "ios/web/public/web_state/web_state.h" #include "url/gurl.h" @@ -29,3 +34,14 @@ if (webState) webState->ExecuteUserJavaScript(jsToEval); } + +void RestoreTab(const SessionID sessionID, + WindowOpenDisposition disposition, + ios::ChromeBrowserState* browserState) { + TabRestoreServiceDelegateImplIOS* delegate = + TabRestoreServiceDelegateImplIOSFactory::GetForBrowserState(browserState); + sessions::TabRestoreService* restoreService = + IOSChromeTabRestoreServiceFactory::GetForBrowserState( + browserState->GetOriginalChromeBrowserState()); + restoreService->RestoreEntryById(delegate, sessionID, disposition); +}
diff --git a/ios/chrome/test/fakes/fake_url_loader.mm b/ios/chrome/test/fakes/fake_url_loader.mm index eeafceb..b30beb1 100644 --- a/ios/chrome/test/fakes/fake_url_loader.mm +++ b/ios/chrome/test/fakes/fake_url_loader.mm
@@ -48,9 +48,6 @@ - (void)loadSessionTab:(const sessions::SessionTab*)sessionTab { } -- (void)restoreTabWithSessionID:(const SessionID)sessionID { -} - - (const GURL&)url { return _url; }
diff --git a/media/base/android/media_drm_bridge.cc b/media/base/android/media_drm_bridge.cc index c576edf8..efcde6a6 100644 --- a/media/base/android/media_drm_bridge.cc +++ b/media/base/android/media_drm_bridge.cc
@@ -264,14 +264,6 @@ return true; } -bool IsPersistentLicenseTypeSupportedByMediaDrm() { - return MediaDrmBridge::IsAvailable() && - // In development. See http://crbug.com/493521 - base::FeatureList::IsEnabled(kMediaDrmPersistentLicense) && - base::android::BuildInfo::GetInstance()->sdk_int() >= - base::android::SDK_VERSION_MARSHMALLOW; -} - } // namespace // MediaDrm is not generally usable without MediaCodec. Thus, both the MediaDrm @@ -290,11 +282,20 @@ } // static +bool MediaDrmBridge::IsPerOriginProvisioningSupported() { + return base::android::BuildInfo::GetInstance()->sdk_int() >= + base::android::SDK_VERSION_MARSHMALLOW; +} + +// static bool MediaDrmBridge::IsPersistentLicenseTypeSupported( - const std::string& key_system) { + const std::string& /* key_system */) { // TODO(yucliu): Check |key_system| if persistent license is supported by // MediaDrm. - return IsPersistentLicenseTypeSupportedByMediaDrm(); + return MediaDrmBridge::IsAvailable() && + // In development. See http://crbug.com/493521 + base::FeatureList::IsEnabled(kMediaDrmPersistentLicense) && + IsPerOriginProvisioningSupported(); } // static @@ -455,7 +456,8 @@ DCHECK(task_runner_->BelongsToCurrentThread()); DVLOG(2) << __func__; - DCHECK(IsPersistentLicenseTypeSupportedByMediaDrm()); + // Key system is not used, so just pass an empty string here. + DCHECK(IsPersistentLicenseTypeSupported("")); if (session_type != CdmSessionType::kPersistentLicense) { promise->reject( @@ -828,9 +830,8 @@ // TODO(yucliu): Remove the check once persistent storage is fully // supported and check if origin is valid. base::FeatureList::IsEnabled(kMediaDrmPersistentLicense) && - // MediaDrm implements origin isolated storage on Marshmallow. - base::android::BuildInfo::GetInstance()->sdk_int() >= - base::android::SDK_VERSION_MARSHMALLOW && + // Per-origin provisioning must be supported for origin isolated storage. + IsPerOriginProvisioningSupported() && // origin id can be empty when MediaDrmBridge is created by // CreateWithoutSessionSupport, which is used for unprovisioning. !origin_id.empty();
diff --git a/media/base/android/media_drm_bridge.h b/media/base/android/media_drm_bridge.h index 6ee3b98..fd9aff8 100644 --- a/media/base/android/media_drm_bridge.h +++ b/media/base/android/media_drm_bridge.h
@@ -74,6 +74,10 @@ const std::string& key_system, const std::string& container_mime_type); + // Whether per-origin provisioning (setting "origin" property on MediaDrm) is + // supported or not. If false, per-device provisioning is used. + static bool IsPerOriginProvisioningSupported(); + static bool IsPersistentLicenseTypeSupported(const std::string& key_system); // Returns the list of the platform-supported key system names that
diff --git a/media/gpu/vaapi/vaapi_video_decode_accelerator.cc b/media/gpu/vaapi/vaapi_video_decode_accelerator.cc index 5433fb1..1441727d 100644 --- a/media/gpu/vaapi/vaapi_video_decode_accelerator.cc +++ b/media/gpu/vaapi/vaapi_video_decode_accelerator.cc
@@ -169,6 +169,7 @@ : state_(kUninitialized), input_ready_(&lock_), vaapi_picture_factory_(new VaapiPictureFactory()), + profile_(VIDEO_CODEC_PROFILE_UNKNOWN), surfaces_available_(&lock_), decode_using_client_picture_buffers_(false), task_runner_(base::ThreadTaskRunnerHandle::Get()), @@ -178,7 +179,6 @@ requested_num_pics_(0), requested_num_reference_frames_(0), previously_requested_num_reference_frames_(0), - profile_(VIDEO_CODEC_PROFILE_UNKNOWN), make_context_current_cb_(make_context_current_cb), bind_image_cb_(bind_image_cb), weak_this_factory_(this) { @@ -291,9 +291,12 @@ PLATFORM_FAILURE, ); } - TRACE_COUNTER_ID2("media,gpu", "Vaapi frames at client", this, "used", - pictures_.size() - available_picture_buffers_.size(), - "available", available_picture_buffers_.size()); + { + base::AutoLock auto_lock(lock_); + TRACE_COUNTER_ID2("media,gpu", "Vaapi frames at client", this, "used", + pictures_.size() - available_picture_buffers_.size(), + "available", available_picture_buffers_.size()); + } DVLOGF(4) << "Notifying output picture id " << output_id << " for input " << input_id @@ -314,8 +317,11 @@ if (!client_) return; - if (pending_output_cbs_.empty() || available_picture_buffers_.empty()) - return; + { + base::AutoLock auto_lock(lock_); + if (pending_output_cbs_.empty() || available_picture_buffers_.empty()) + return; + } auto output_cb = std::move(pending_output_cbs_.front()); pending_output_cbs_.pop(); @@ -547,6 +553,7 @@ if (!awaiting_va_surfaces_recycle_) return; + base::AutoLock auto_lock(lock_); const size_t kExpectedMaxAvailableVASurfaces = decode_using_client_picture_buffers_ ? pictures_.size() @@ -586,7 +593,7 @@ VLOGF(2) << "Requesting " << requested_num_pics_ << " pictures of size: " << requested_pic_size_.ToString(); - VideoPixelFormat format = GfxBufferFormatToVideoPixelFormat( + const VideoPixelFormat format = GfxBufferFormatToVideoPixelFormat( vaapi_picture_factory_->GetBufferFormat()); task_runner_->PostTask( FROM_HERE, @@ -713,6 +720,7 @@ return; } + base::AutoLock auto_lock(lock_); if (!pictures_.count(picture_buffer_id)) { CloseGpuMemoryBufferHandle(gpu_memory_buffer_handle); @@ -747,24 +755,24 @@ TRACE_EVENT1("media,gpu", "VAVDA::ReusePictureBuffer", "Picture id", picture_buffer_id); - if (!pictures_.count(picture_buffer_id)) { - // It's possible that we've already posted a DismissPictureBuffer for this - // picture, but it has not yet executed when this ReusePictureBuffer - // was posted to us by the client. In that case just ignore this (we've - // already dismissed it and accounted for that). - DVLOGF(3) << "got picture id=" << picture_buffer_id - << " not in use (anymore?)."; - return; - } - { base::AutoLock auto_lock(lock_); - available_picture_buffers_.push_back(picture_buffer_id); - } - TRACE_COUNTER_ID2("media,gpu", "Vaapi frames at client", this, "used", - pictures_.size() - available_picture_buffers_.size(), - "available", available_picture_buffers_.size()); + if (!pictures_.count(picture_buffer_id)) { + // It's possible that we've already posted a DismissPictureBuffer for this + // picture, but it has not yet executed when this ReusePictureBuffer + // was posted to us by the client. In that case just ignore this (we've + // already dismissed it and accounted for that). + DVLOGF(3) << "got picture id=" << picture_buffer_id + << " not in use (anymore?)."; + return; + } + + available_picture_buffers_.push_back(picture_buffer_id); + TRACE_COUNTER_ID2("media,gpu", "Vaapi frames at client", this, "used", + pictures_.size() - available_picture_buffers_.size(), + "available", available_picture_buffers_.size()); + } TryOutputPicture(); } @@ -977,10 +985,10 @@ if (state_ == kResetting || state_ == kDestroying) return; } - pending_output_cbs_.push( base::BindOnce(&VaapiVideoDecodeAccelerator::OutputPicture, weak_this_, dec_surface, bitstream_id, visible_rect, color_space)); + TryOutputPicture(); } @@ -1029,15 +1037,17 @@ void VaapiVideoDecodeAccelerator::RecycleVASurfaceID( VASurfaceID va_surface_id) { DCHECK(task_runner_->BelongsToCurrentThread()); - base::AutoLock auto_lock(lock_); - available_va_surfaces_.push_back(va_surface_id); - if (!decode_using_client_picture_buffers_) { - TRACE_COUNTER_ID2( - "media,gpu", "Vaapi VASurfaceIDs", this, "used", - requested_num_reference_frames_ - available_va_surfaces_.size(), - "available", available_va_surfaces_.size()); + { + base::AutoLock auto_lock(lock_); + available_va_surfaces_.push_back(va_surface_id); + if (!decode_using_client_picture_buffers_) { + TRACE_COUNTER_ID2( + "media,gpu", "Vaapi VASurfaceIDs", this, "used", + requested_num_reference_frames_ - available_va_surfaces_.size(), + "available", available_va_surfaces_.size()); + } + surfaces_available_.Signal(); } - surfaces_available_.Signal(); TryOutputPicture(); }
diff --git a/media/gpu/vaapi/vaapi_video_decode_accelerator.h b/media/gpu/vaapi/vaapi_video_decode_accelerator.h index d1026778..4906cb7f 100644 --- a/media/gpu/vaapi/vaapi_video_decode_accelerator.h +++ b/media/gpu/vaapi/vaapi_video_decode_accelerator.h
@@ -25,6 +25,7 @@ #include "base/single_thread_task_runner.h" #include "base/synchronization/condition_variable.h" #include "base/synchronization/lock.h" +#include "base/thread_annotations.h" #include "base/threading/thread.h" #include "base/trace_event/memory_dump_provider.h" #include "media/base/bitstream_buffer.h" @@ -115,16 +116,16 @@ // |decoder_|. This method will sleep if no |input_buffers_| are available. // Returns true if a new buffer has been set up, false if an early exit has // been requested (due to initiated reset/flush/destroy). - bool GetCurrInputBuffer_Locked(); + bool GetCurrInputBuffer_Locked() EXCLUSIVE_LOCKS_REQUIRED(lock_); // Signals the client that |curr_input_buffer_| has been read and can be // returned. Will also release the mapping. - void ReturnCurrInputBuffer_Locked(); + void ReturnCurrInputBuffer_Locked() EXCLUSIVE_LOCKS_REQUIRED(lock_); // Waits for more surfaces to become available. Returns true once they do or // false if an early exit has been requested (due to an initiated // reset/flush/destroy). - bool WaitForSurfaces_Locked(); + bool WaitForSurfaces_Locked() EXCLUSIVE_LOCKS_REQUIRED(lock_); // Continue decoding given input buffers and sleep waiting for input/output // as needed. Will exit if a new set of surfaces or reset/flush/destroy @@ -201,38 +202,42 @@ kDestroying, }; - // |lock_| protects |input_buffers_|, |curr_input_buffer_|, |state_| and - // |available_picture_buffers_|. base::Lock lock_; - State state_; + State state_ GUARDED_BY(lock_); + // Only used on |task_runner_|. Config::OutputMode output_mode_; // Queue of available InputBuffers. - base::queue<std::unique_ptr<InputBuffer>> input_buffers_; + base::queue<std::unique_ptr<InputBuffer>> input_buffers_ GUARDED_BY(lock_); // Signalled when input buffers are queued onto |input_buffers_| queue. base::ConditionVariable input_ready_; - // Current input buffer at decoder. + // Current input buffer at decoder. Only used on |decoder_thread_task_runner_| std::unique_ptr<InputBuffer> curr_input_buffer_; + // Only used on |task_runner_|. std::unique_ptr<VaapiPictureFactory> vaapi_picture_factory_; - // Constructed in Initialize() when the codec information is received. + // The following variables are constructed/initialized in Initialize() when + // the codec information is received. |vaapi_wrapper_| is thread safe. scoped_refptr<VaapiWrapper> vaapi_wrapper_; + // Only used on |decoder_thread_task_runner_|. std::unique_ptr<AcceleratedVideoDecoder> decoder_; + VideoCodecProfile profile_; // All allocated VaapiPictures, regardless of their current state. Pictures // are allocated at AssignPictureBuffers() and are kept until dtor or // TryFinishSurfaceSetChange(). Comes after |vaapi_wrapper_| to ensure all // pictures are destroyed before this is destroyed. - base::small_map<std::map<int32_t, std::unique_ptr<VaapiPicture>>> pictures_; + base::small_map<std::map<int32_t, std::unique_ptr<VaapiPicture>>> pictures_ + GUARDED_BY(lock_); // List of PictureBuffer ids available to be sent to |client_| via // OutputPicture() (|client_| returns them via ReusePictureBuffer()). - std::list<int32_t> available_picture_buffers_; + std::list<int32_t> available_picture_buffers_ GUARDED_BY(lock_); // VASurfaceIDs no longer in use that can be passed back to |decoder_| for // reuse, once it requests them. - std::list<VASurfaceID> available_va_surfaces_; + std::list<VASurfaceID> available_va_surfaces_ GUARDED_BY(lock_); // Signalled when output surfaces are queued into |available_va_surfaces_|. base::ConditionVariable surfaces_available_; @@ -244,15 +249,13 @@ // If we don't have any available |pictures_| at the time when the decoder // requests output, we'll store the request in this queue for later and run it // once the client gives us more textures via ReusePictureBuffer(). + // Only used on |task_runner_|. base::queue<base::OnceClosure> pending_output_cbs_; // Under some circumstances, we can pass to libva our own VASurfaceIDs to - // decode onto, which skips one copy. + // decode onto, which skips one copy. Only used on |task_runner_|. bool decode_using_client_picture_buffers_; - // ChildThread's task runner. - const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - // WeakPtr<> pointing to |this| for use in posting tasks from the decoder // thread back to the ChildThread. Because the decoder thread is a member of // this class, any task running on the decoder thread is guaranteed that this @@ -261,26 +264,29 @@ // decoder thread to the ChildThread should use |weak_this_|. base::WeakPtr<VaapiVideoDecodeAccelerator> weak_this_; - // Callback used when creating VASurface objects. + // Callback used when creating VASurface objects. Only used on |task_runner_|. VASurface::ReleaseCB va_surface_release_cb_; - // To expose client callbacks from VideoDecodeAccelerator. - // NOTE: all calls to these objects *MUST* be executed on task_runner_. + // To expose client callbacks from VideoDecodeAccelerator. Used only on + // |task_runner_|. std::unique_ptr<base::WeakPtrFactory<Client>> client_ptr_factory_; base::WeakPtr<Client> client_; + // ChildThread's task runner. + const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + base::Thread decoder_thread_; // Use this to post tasks to |decoder_thread_| instead of // |decoder_thread_.task_runner()| because the latter will be NULL once // |decoder_thread_.Stop()| returns. scoped_refptr<base::SingleThreadTaskRunner> decoder_thread_task_runner_; - // Whether we are waiting for any pending_output_cbs_ to be run before - // NotifyingFlushDone. + // Whether we are waiting for any |pending_output_cbs_| to be run before + // NotifyingFlushDone. Only used on |task_runner_|. bool finish_flush_pending_; // Decoder requested a new surface set and we are waiting for all the surfaces - // to be returned before we can free them. + // to be returned before we can free them. Only used on |task_runner_|. bool awaiting_va_surfaces_recycle_; // Last requested number/resolution of output PictureBuffers. @@ -290,8 +296,6 @@ size_t requested_num_reference_frames_; size_t previously_requested_num_reference_frames_; - VideoCodecProfile profile_; - // Callback to make GL context current. MakeGLContextCurrentCallback make_context_current_cb_;
diff --git a/media/gpu/vaapi/vaapi_video_decode_accelerator_unittest.cc b/media/gpu/vaapi/vaapi_video_decode_accelerator_unittest.cc index 1f5309aa..b9819cd 100644 --- a/media/gpu/vaapi/vaapi_video_decode_accelerator_unittest.cc +++ b/media/gpu/vaapi/vaapi_video_decode_accelerator_unittest.cc
@@ -164,6 +164,7 @@ } void SetVdaStateToUnitialized() { + base::AutoLock auto_lock(vda_.lock_); vda_.state_ = VaapiVideoDecodeAccelerator::kUninitialized; }
diff --git a/net/base/network_config_watcher_mac.cc b/net/base/network_config_watcher_mac.cc index f324969a..4e3f5e83 100644 --- a/net/base/network_config_watcher_mac.cc +++ b/net/base/network_config_watcher_mac.cc
@@ -115,8 +115,6 @@ } #endif // !defined(OS_IOS) -} // namespace - class NetworkConfigWatcherMacThread : public base::Thread { public: NetworkConfigWatcherMacThread(NetworkConfigWatcherMac::Delegate* delegate); @@ -156,8 +154,10 @@ } NetworkConfigWatcherMacThread::~NetworkConfigWatcherMacThread() { - // This is expected to be invoked during shutdown. - base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope allow_thread_join; + // Allow IO because Stop() calls PlatformThread::Join(), which is a blocking + // operation. This is expected during shutdown. + base::ThreadRestrictions::ScopedAllowIO allow_io; + Stop(); } @@ -259,6 +259,8 @@ return true; } +} // namespace + NetworkConfigWatcherMac::NetworkConfigWatcherMac(Delegate* delegate) : notifier_thread_(new NetworkConfigWatcherMacThread(delegate)) { // We create this notifier thread because the notification implementation
diff --git a/net/cookies/cookie_util.cc b/net/cookies/cookie_util.cc index ab24456..72fbf5d 100644 --- a/net/cookies/cookie_util.cc +++ b/net/cookies/cookie_util.cc
@@ -9,6 +9,7 @@ #include "base/logging.h" #include "base/stl_util.h" +#include "base/strings/string_piece.h" #include "base/strings/string_tokenizer.h" #include "base/strings/string_util.h" #include "build/build_config.h" @@ -346,7 +347,8 @@ // i points to ';' or end of string. } } - parsed_cookies->push_back(std::make_pair(cookie_name, cookie_value)); + parsed_cookies->emplace_back(cookie_name.as_string(), + cookie_value.as_string()); // Eat ';'. if (i != header_value.end()) ++i; }
diff --git a/net/cookies/cookie_util.h b/net/cookies/cookie_util.h index 669457b..2c9ed99d 100644 --- a/net/cookies/cookie_util.h +++ b/net/cookies/cookie_util.h
@@ -9,7 +9,6 @@ #include <utility> #include <vector> -#include "base/strings/string_piece.h" #include "base/time/time.h" #include "net/base/net_export.h" @@ -59,8 +58,8 @@ const std::string& host); // A ParsedRequestCookie consists of the key and value of the cookie. -typedef std::pair<base::StringPiece, base::StringPiece> ParsedRequestCookie; -typedef std::vector<ParsedRequestCookie> ParsedRequestCookies; +using ParsedRequestCookie = std::pair<std::string, std::string>; +using ParsedRequestCookies = std::vector<ParsedRequestCookie>; // Assumes that |header_value| is the cookie header value of a HTTP Request // following the cookie-string schema of RFC 6265, section 4.2.1, and returns
diff --git a/net/cookies/cookie_util_unittest.cc b/net/cookies/cookie_util_unittest.cc index 00298cc0..7812e05 100644 --- a/net/cookies/cookie_util_unittest.cc +++ b/net/cookies/cookie_util_unittest.cc
@@ -18,27 +18,16 @@ base::StringPairs parsed; }; -cookie_util::ParsedRequestCookies MakeParsedRequestCookies( - const base::StringPairs& data) { - cookie_util::ParsedRequestCookies parsed; - for (size_t i = 0; i < data.size(); i++) { - parsed.push_back(std::make_pair(base::StringPiece(data[i].first), - base::StringPiece(data[i].second))); - } - return parsed; -} - void CheckParse(const std::string& str, const base::StringPairs& parsed_expected) { cookie_util::ParsedRequestCookies parsed; cookie_util::ParseRequestCookieLine(str, &parsed); - EXPECT_EQ(MakeParsedRequestCookies(parsed_expected), parsed); + EXPECT_EQ(parsed_expected, parsed); } void CheckSerialize(const base::StringPairs& parsed, const std::string& str_expected) { - cookie_util::ParsedRequestCookies prc = MakeParsedRequestCookies(parsed); - EXPECT_EQ(str_expected, cookie_util::SerializeRequestCookieLine(prc)); + EXPECT_EQ(str_expected, cookie_util::SerializeRequestCookieLine(parsed)); } TEST(CookieUtilTest, TestDomainIsHostOnly) {
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index 7331be7..f636610 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc
@@ -5827,6 +5827,149 @@ // TODO(juliatuttle): Anything else to check here? } +// Test the case where a proxied H2 session doesn't exist when an auth challenge +// is observed, but does exist by the time auth credentials are provided. +// Proxy-Connection: Close is used so that there's a second DNS lookup, which is +// what causes the existing H2 session to be noticed and reused. +TEST_F(HttpNetworkTransactionTest, ProxiedH2SessionAppearsDuringAuth) { + ProxyConfig proxy_config; + proxy_config.set_auto_detect(true); + proxy_config.set_pac_url(GURL("http://fooproxyurl")); + + CapturingProxyResolver capturing_proxy_resolver; + capturing_proxy_resolver.set_proxy_server( + ProxyServer(ProxyServer::SCHEME_HTTP, HostPortPair("myproxy", 70))); + session_deps_.proxy_resolution_service = + std::make_unique<ProxyResolutionService>( + std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation( + proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)), + std::make_unique<CapturingProxyResolverFactory>( + &capturing_proxy_resolver), + nullptr); + + std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); + + const char kMyUrl[] = "https://www.example.org/"; + spdy::SpdySerializedFrame get(spdy_util_.ConstructSpdyGet(kMyUrl, 1, LOWEST)); + spdy::SpdySerializedFrame get_resp( + spdy_util_.ConstructSpdyGetReply(NULL, 0, 1)); + spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); + + spdy_util_.UpdateWithStreamDestruction(1); + spdy::SpdySerializedFrame get2( + spdy_util_.ConstructSpdyGet(kMyUrl, 3, LOWEST)); + spdy::SpdySerializedFrame get_resp2( + spdy_util_.ConstructSpdyGetReply(NULL, 0, 3)); + spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true)); + + MockWrite auth_challenge_writes[] = { + MockWrite(ASYNC, 0, + "CONNECT www.example.org:443 HTTP/1.1\r\n" + "Host: www.example.org:443\r\n" + "Proxy-Connection: keep-alive\r\n\r\n"), + }; + + MockRead auth_challenge_reads[] = { + MockRead(ASYNC, 1, + "HTTP/1.1 407 Authentication Required\r\n" + "Content-Length: 0\r\n" + "Proxy-Connection: close\r\n" + "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"), + }; + + MockWrite spdy_writes[] = { + MockWrite(ASYNC, 0, + "CONNECT www.example.org:443 HTTP/1.1\r\n" + "Host: www.example.org:443\r\n" + "Proxy-Connection: keep-alive\r\n" + "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), + CreateMockWrite(get, 2), + CreateMockWrite(get2, 5), + }; + + MockRead spdy_reads[] = { + MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"), + CreateMockRead(get_resp, 3, ASYNC), + CreateMockRead(body, 4, ASYNC), + CreateMockRead(get_resp2, 6, ASYNC), + CreateMockRead(body2, 7, ASYNC), + + MockRead(SYNCHRONOUS, ERR_IO_PENDING, 8), + }; + + SequencedSocketData auth_challenge1(auth_challenge_reads, + auth_challenge_writes); + session_deps_.socket_factory->AddSocketDataProvider(&auth_challenge1); + + SequencedSocketData auth_challenge2(auth_challenge_reads, + auth_challenge_writes); + session_deps_.socket_factory->AddSocketDataProvider(&auth_challenge2); + + SequencedSocketData spdy_data(spdy_reads, spdy_writes); + session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); + + SSLSocketDataProvider ssl(ASYNC, OK); + ssl.next_proto = kProtoHTTP2; + session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); + + TestCompletionCallback callback; + std::string response_data; + + // Run first request until an auth challenge is observed. + HttpRequestInfo request1; + request1.method = "GET"; + request1.url = GURL(kMyUrl); + request1.traffic_annotation = + net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); + HttpNetworkTransaction trans1(LOWEST, session.get()); + int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource()); + EXPECT_THAT(callback.GetResult(rv), IsOk()); + const HttpResponseInfo* response = trans1.GetResponseInfo(); + ASSERT_TRUE(response); + ASSERT_TRUE(response->headers); + EXPECT_EQ(407, response->headers->response_code()); + EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); + EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get())); + + // Run second request until an auth challenge is observed. + HttpRequestInfo request2; + request2.method = "GET"; + request2.url = GURL(kMyUrl); + request2.traffic_annotation = + net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); + HttpNetworkTransaction trans2(LOWEST, session.get()); + rv = trans2.Start(&request2, callback.callback(), NetLogWithSource()); + EXPECT_THAT(callback.GetResult(rv), IsOk()); + response = trans2.GetResponseInfo(); + ASSERT_TRUE(response); + ASSERT_TRUE(response->headers); + EXPECT_EQ(407, response->headers->response_code()); + EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); + EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get())); + + // Now provide credentials for the first request, and wait for it to complete. + rv = trans1.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback()); + rv = callback.GetResult(rv); + EXPECT_THAT(rv, IsOk()); + response = trans1.GetResponseInfo(); + ASSERT_TRUE(response); + ASSERT_TRUE(response->headers); + EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine()); + ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk()); + EXPECT_EQ(kUploadData, response_data); + + // Now provide credentials for the second request. It should notice the + // existing session, and reuse it. + rv = trans2.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback()); + EXPECT_THAT(callback.GetResult(rv), IsOk()); + response = trans2.GetResponseInfo(); + ASSERT_TRUE(response); + ASSERT_TRUE(response->headers); + EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine()); + ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk()); + EXPECT_EQ(kUploadData, response_data); +} + // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY // HTTPS Proxy to different servers. TEST_F(HttpNetworkTransactionTest,
diff --git a/net/http/http_proxy_client_socket_wrapper.cc b/net/http/http_proxy_client_socket_wrapper.cc index f200e5f3..22f2e3f2 100644 --- a/net/http/http_proxy_client_socket_wrapper.cc +++ b/net/http/http_proxy_client_socket_wrapper.cc
@@ -483,6 +483,12 @@ if (result != OK) { UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpProxy.ConnectLatency.Insecure.Error", base::TimeTicks::Now() - connect_start_time_); + // This is a special error code meaning to reuse an existing SPDY session + // rather than use a fresh socket. Overriding it with a proxy error message + // would cause the request to fail, instead of switching to using the SPDY + // session. + if (result == ERR_SPDY_SESSION_ALREADY_EXISTS) + return result; return ERR_PROXY_CONNECTION_FAILED; }
diff --git a/net/http/http_stream_factory_job.cc b/net/http/http_stream_factory_job.cc index e20a9bd5..67b31b2b 100644 --- a/net/http/http_stream_factory_job.cc +++ b/net/http/http_stream_factory_job.cc
@@ -1325,13 +1325,16 @@ if (result == ERR_PROXY_AUTH_REQUESTED) return result; - if (result == OK) { + if (result == OK || result == ERR_SPDY_SESSION_ALREADY_EXISTS) { // Now that we've got the HttpProxyClientSocket connected. We have // to release it as an idle socket into the pool and start the connection // process from the beginning. Trying to pass it in with the // SSLSocketParams might cause a deadlock since params are dispatched // interchangeably. This request won't necessarily get this http proxy // socket, but there will be forward progress. + // + // Alernatively, if there's an existing H2 session that can be reused, + // also go back to the init connection state to reuse it. establishing_tunnel_ = false; ReturnToStateInitConnection(false /* do not close connection */); return OK;
diff --git a/net/proxy_resolution/multi_threaded_proxy_resolver.cc b/net/proxy_resolution/multi_threaded_proxy_resolver.cc index ae41f4f..c05969df 100644 --- a/net/proxy_resolution/multi_threaded_proxy_resolver.cc +++ b/net/proxy_resolution/multi_threaded_proxy_resolver.cc
@@ -28,11 +28,6 @@ #include "net/proxy_resolution/proxy_resolver.h" namespace net { - -// http://crbug.com/69710 -class MultiThreadedProxyResolverScopedAllowJoinOnIO - : public base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope {}; - namespace { class Job; @@ -375,9 +370,8 @@ DCHECK(coordinator_); { - // TODO(http://crbug.com/69710): Use TaskScheduler instead of creating a - // base::Thread. - MultiThreadedProxyResolverScopedAllowJoinOnIO allow_thread_join; + // See http://crbug.com/69710. + base::ThreadRestrictions::ScopedAllowIO allow_io; // Join the worker thread. thread_.reset();
diff --git a/net/test/embedded_test_server/embedded_test_server.cc b/net/test/embedded_test_server/embedded_test_server.cc index 6578877c..371e73ab0 100644 --- a/net/test/embedded_test_server/embedded_test_server.cc +++ b/net/test/embedded_test_server/embedded_test_server.cc
@@ -67,7 +67,9 @@ } { - base::ScopedAllowBaseSyncPrimitivesForTesting allow_wait_for_thread_join; + // Thread::Join induced by test code should cause an assert. + base::ScopedAllowBlockingForTesting allow_blocking; + io_thread_.reset(); } }
diff --git a/net/test/spawned_test_server/local_test_server_win.cc b/net/test/spawned_test_server/local_test_server_win.cc index bc78e77c..5addf0be 100644 --- a/net/test/spawned_test_server/local_test_server_win.cc +++ b/net/test/spawned_test_server/local_test_server_win.cc
@@ -72,7 +72,7 @@ bytes_read += num_bytes; } - base::ScopedAllowBaseSyncPrimitivesForTesting allow_thread_join; + base::ScopedAllowBlockingForTesting allow_thread_join; thread.Stop(); // If the timeout kicked in, abort.
diff --git a/services/identity/identity_manager_impl_unittest.cc b/services/identity/identity_manager_impl_unittest.cc index 9d2c6bcf..6f947f59 100644 --- a/services/identity/identity_manager_impl_unittest.cc +++ b/services/identity/identity_manager_impl_unittest.cc
@@ -42,7 +42,7 @@ : signin_client_(&pref_service_), token_service_(&pref_service_), #if defined(OS_CHROMEOS) - signin_manager_(&signin_client_, &account_tracker_), + signin_manager_(&signin_client_, &token_service_, &account_tracker_), #else signin_manager_(&signin_client_, &token_service_,
diff --git a/services/identity/public/cpp/accounts_mutator.cc b/services/identity/public/cpp/accounts_mutator.cc index a80285a1..6fce82d9 100644 --- a/services/identity/public/cpp/accounts_mutator.cc +++ b/services/identity/public/cpp/accounts_mutator.cc
@@ -4,18 +4,10 @@ #include "services/identity/public/cpp/accounts_mutator.h" -#include "components/signin/core/browser/profile_oauth2_token_service.h" - namespace identity { -AccountsMutator::AccountsMutator(ProfileOAuth2TokenService* token_service) - : token_service_(token_service) {} +AccountsMutator::AccountsMutator(ProfileOAuth2TokenService* token_service) {} AccountsMutator::~AccountsMutator() {} -void AccountsMutator::LoadAccountsFromDisk( - const std::string& primary_account_id) { - token_service_->LoadCredentials(primary_account_id); -} - } // namespace identity
diff --git a/services/identity/public/cpp/accounts_mutator.h b/services/identity/public/cpp/accounts_mutator.h index 471be5b3..08d0dbc 100644 --- a/services/identity/public/cpp/accounts_mutator.h +++ b/services/identity/public/cpp/accounts_mutator.h
@@ -20,22 +20,7 @@ explicit AccountsMutator(ProfileOAuth2TokenService* token_service); ~AccountsMutator(); - // Loads credentials from a backing persistent store to make them available - // after service is used between profile restarts. - // - // The primary account is specified with the |primary_account_id| argument. - // For a regular profile, the primary account id comes from IdentityManager. - // For a supervised user, the id comes from SupervisedUserService. - // NOTE: In normal usage this method SHOULD NOT be called as the loading of - // accounts from disk occurs as part of the internal startup flow. The method - // is only used in production for a very small number of corner case startup - // flows. - // TODO(https://crbug.com/740117): Eliminate the need to expose this. - void LoadAccountsFromDisk(const std::string& primary_account_id); - private: - ProfileOAuth2TokenService* token_service_; - DISALLOW_COPY_AND_ASSIGN(AccountsMutator); };
diff --git a/services/identity/public/cpp/accounts_mutator_unittest.cc b/services/identity/public/cpp/accounts_mutator_unittest.cc index 36e7ffc8..0b71e1d 100644 --- a/services/identity/public/cpp/accounts_mutator_unittest.cc +++ b/services/identity/public/cpp/accounts_mutator_unittest.cc
@@ -66,17 +66,8 @@ DISALLOW_COPY_AND_ASSIGN(AccountsMutatorTest); }; -// Tests that requesting a load of accounts results in the notification -// firing that tokens were loaded. -TEST_F(AccountsMutatorTest, LoadAccountsFromDisk) { - base::RunLoop run_loop; - token_service_observer()->set_on_refresh_tokens_loaded_callback( - run_loop.QuitClosure()); - - // Load the accounts and ensure that we see the resulting notification that - // they were loaded. - accounts_mutator()->LoadAccountsFromDisk(""); - run_loop.Run(); +TEST_F(AccountsMutatorTest, Basic) { + // Should not crash. } } // namespace identity
diff --git a/services/identity/public/cpp/identity_manager.h b/services/identity/public/cpp/identity_manager.h index 3f6ee7c..d4c5e23 100644 --- a/services/identity/public/cpp/identity_manager.h +++ b/services/identity/public/cpp/identity_manager.h
@@ -33,18 +33,12 @@ class UserSessionManager; } -// Necessary to declare this class as a friend. -namespace file_manager { -class MultiProfileFilesAppBrowserTest; -} - namespace network { class SharedURLLoaderFactory; } // Necessary to declare these classes as friends. class ArcSupportHostTest; -class MultiProfileDownloadNotificationTest; namespace identity { @@ -323,9 +317,6 @@ const std::string& account_id, const GoogleServiceAuthError& auth_error); - friend MultiProfileDownloadNotificationTest; - friend file_manager::MultiProfileFilesAppBrowserTest; - // These clients needs to call SetPrimaryAccountSynchronously(). friend ArcSupportHostTest; friend arc::ArcTermsOfServiceDefaultNegotiatorTest;
diff --git a/services/identity/public/cpp/identity_manager_unittest.cc b/services/identity/public/cpp/identity_manager_unittest.cc index aa3f169..8c8e31b 100644 --- a/services/identity/public/cpp/identity_manager_unittest.cc +++ b/services/identity/public/cpp/identity_manager_unittest.cc
@@ -466,7 +466,7 @@ DCHECK_EQ(account_consistency, signin::AccountConsistencyMethod::kDisabled) << "AccountConsistency is not used by SigninManagerBase"; signin_manager_ = std::make_unique<FakeSigninManagerBase>( - &signin_client_, &account_tracker_); + &signin_client_, &token_service_, &account_tracker_); #else signin_manager_ = std::make_unique<FakeSigninManager>( &signin_client_, &token_service_, &account_tracker_,
diff --git a/services/identity/public/cpp/identity_test_environment.cc b/services/identity/public/cpp/identity_test_environment.cc index db79410..76f8b57 100644 --- a/services/identity/public/cpp/identity_test_environment.cc +++ b/services/identity/public/cpp/identity_test_environment.cc
@@ -23,7 +23,7 @@ class IdentityManagerDependenciesOwner { public: IdentityManagerDependenciesOwner( - bool use_fake_url_loader_for_gaia_cookie_manager, + network::TestURLLoaderFactory* test_url_loader_factory, sync_preferences::TestingPrefServiceSyncable* pref_service, signin::AccountConsistencyMethod account_consistency); ~IdentityManagerDependenciesOwner(); @@ -49,13 +49,13 @@ TestSigninClient signin_client_; FakeProfileOAuth2TokenService token_service_; SigninManagerForTest signin_manager_; - FakeGaiaCookieManagerService gaia_cookie_manager_service_; + std::unique_ptr<FakeGaiaCookieManagerService> gaia_cookie_manager_service_; DISALLOW_COPY_AND_ASSIGN(IdentityManagerDependenciesOwner); }; IdentityManagerDependenciesOwner::IdentityManagerDependenciesOwner( - bool use_fake_url_loader_for_gaia_cookie_manager, + network::TestURLLoaderFactory* test_url_loader_factory, sync_preferences::TestingPrefServiceSyncable* pref_service_param, signin::AccountConsistencyMethod account_consistency) : owned_pref_service_( @@ -67,28 +67,24 @@ signin_client_(pref_service()), token_service_(pref_service()), #if defined(OS_CHROMEOS) - signin_manager_(&signin_client_, &account_tracker_), + signin_manager_(&signin_client_, &token_service_, &account_tracker_) { #else signin_manager_(&signin_client_, &token_service_, &account_tracker_, nullptr, nullptr, - account_consistency), + account_consistency) { #endif - // NOTE: Some unittests set up their own TestURLFetcherFactory. In these - // contexts FakeGaiaCookieManagerService can't set up its own - // FakeURLFetcherFactory, as {Test, Fake}URLFetcherFactory allow only one - // instance to be alive at a time. If some users require that - // GaiaCookieManagerService have a FakeURLFetcherFactory while *also* - // having their own FakeURLFetcherFactory, we'll need to pass the actual - // object in and have GaiaCookieManagerService have a reference to the - // object (or figure out the sharing some other way). Contact - // blundell@chromium.org if you come up against this issue. - gaia_cookie_manager_service_( - &token_service_, - &signin_client_, - use_fake_url_loader_for_gaia_cookie_manager) { + if (test_url_loader_factory != nullptr) { + gaia_cookie_manager_service_ = + std::make_unique<FakeGaiaCookieManagerService>( + &token_service_, &signin_client_, test_url_loader_factory); + } else { + gaia_cookie_manager_service_ = + std::make_unique<FakeGaiaCookieManagerService>(&token_service_, + &signin_client_); + } AccountTrackerService::RegisterPrefs(pref_service()->registry()); ProfileOAuth2TokenService::RegisterProfilePrefs(pref_service()->registry()); SigninManagerBase::RegisterProfilePrefs(pref_service()->registry()); @@ -116,7 +112,7 @@ FakeGaiaCookieManagerService* IdentityManagerDependenciesOwner::gaia_cookie_manager_service() { - return &gaia_cookie_manager_service_; + return gaia_cookie_manager_service_.get(); } sync_preferences::TestingPrefServiceSyncable* @@ -128,7 +124,7 @@ } IdentityTestEnvironment::IdentityTestEnvironment( - bool use_fake_url_loader_for_gaia_cookie_manager, + network::TestURLLoaderFactory* test_url_loader_factory, sync_preferences::TestingPrefServiceSyncable* pref_service, signin::AccountConsistencyMethod account_consistency) : IdentityTestEnvironment( @@ -137,7 +133,7 @@ /*signin_manager=*/nullptr, /*gaia_cookie_manager_service=*/nullptr, std::make_unique<IdentityManagerDependenciesOwner>( - use_fake_url_loader_for_gaia_cookie_manager, + test_url_loader_factory, pref_service, account_consistency), /*identity_manager=*/nullptr) {}
diff --git a/services/identity/public/cpp/identity_test_environment.h b/services/identity/public/cpp/identity_test_environment.h index c9f628f..ccd4f52 100644 --- a/services/identity/public/cpp/identity_test_environment.h +++ b/services/identity/public/cpp/identity_test_environment.h
@@ -29,7 +29,7 @@ #else using SigninManagerForTest = FakeSigninManager; #endif // OS_CHROMEOS -} +} // namespace // Internal class that creates and owns dependencies of IdentityManager // when those dependencies are not passed in externally. @@ -52,6 +52,9 @@ // a test). In that case, use the below constructor and switch to this // constructor once the conversion is complete. // + // This constructor takes an optional parameter |test_url_loader_factory| to + // use for cookie-related network requests. + // // This constructor also takes an optional PrefService instance as parameter, // which allows tests to move away from referencing IdentityManager's // dependencies directly (namely AccountTrackerService, PO2TS, SigninManager @@ -61,7 +64,7 @@ // Last, this constructor can take an optional parameter |account_consistency| // as parameter, to specify the account consistency policy that will be used. IdentityTestEnvironment( - bool use_fake_url_loader_for_gaia_cookie_manager = false, + network::TestURLLoaderFactory* test_url_loader_factory = nullptr, sync_preferences::TestingPrefServiceSyncable* pref_service = nullptr, signin::AccountConsistencyMethod account_consistency = signin::AccountConsistencyMethod::kDisabled);
diff --git a/services/identity/public/cpp/primary_account_mutator_unittest.cc b/services/identity/public/cpp/primary_account_mutator_unittest.cc index 58cedb0..e2e6b96 100644 --- a/services/identity/public/cpp/primary_account_mutator_unittest.cc +++ b/services/identity/public/cpp/primary_account_mutator_unittest.cc
@@ -115,8 +115,8 @@ AuthExpectation auth_expection = AuthExpectation::kAuthNormal) { base::test::ScopedTaskEnvironment task_environment; identity::IdentityTestEnvironment environment( - /*use_fake_url_loader_for_gaia_cookie_manager=*/false, - /*pref_service=*/nullptr, account_consistency_method); + /*test_url_loader_factory=*/nullptr, /*pref_service=*/nullptr, + account_consistency_method); identity::IdentityManager* identity_manager = environment.identity_manager(); identity::PrimaryAccountMutator* primary_account_mutator =
diff --git a/services/media_session/audio_focus_manager_unittest.cc b/services/media_session/audio_focus_manager_unittest.cc index 33e783cb..1ea3fc4 100644 --- a/services/media_session/audio_focus_manager_unittest.cc +++ b/services/media_session/audio_focus_manager_unittest.cc
@@ -1033,6 +1033,11 @@ std::unique_ptr<test::TestAudioFocusObserver> observer = CreateObserver(); media_session_1.AbandonAudioFocusFromClient(); + // TODO(https://crbug.com/916177): This should wait on a more precise + // condition than RunLoop idling, but it's not clear exactly what that + // should be. + base::RunLoop().RunUntilIdle(); + EXPECT_EQ( test::TestAudioFocusObserver::NotificationType::kActiveSessionChanged, observer->notifications().back());
diff --git a/services/media_session/media_controller_unittest.cc b/services/media_session/media_controller_unittest.cc index cea09f76..e9e810b 100644 --- a/services/media_session/media_controller_unittest.cc +++ b/services/media_session/media_controller_unittest.cc
@@ -553,7 +553,7 @@ { test::MockMediaSessionMojoObserver observer(controller()); media_session.SimulateMetadataChanged(test_metadata); - EXPECT_EQ(metadata, *observer.WaitForMetadata()); + EXPECT_EQ(metadata, observer.WaitForNonEmptyMetadata()); } }
diff --git a/services/media_session/public/cpp/test/mock_media_session.cc b/services/media_session/public/cpp/test/mock_media_session.cc index 095bf865..0f3d166 100644 --- a/services/media_session/public/cpp/test/mock_media_session.cc +++ b/services/media_session/public/cpp/test/mock_media_session.cc
@@ -46,6 +46,9 @@ if (waiting_for_metadata_) { run_loop_.Quit(); waiting_for_metadata_ = false; + } else if (waiting_for_non_empty_metadata_ && metadata.has_value()) { + run_loop_.Quit(); + waiting_for_non_empty_metadata_ = false; } } @@ -77,6 +80,15 @@ return session_metadata_.value(); } +const MediaMetadata& MockMediaSessionMojoObserver::WaitForNonEmptyMetadata() { + if (!session_metadata_.has_value() || !session_metadata_->has_value()) { + waiting_for_non_empty_metadata_ = true; + run_loop_.Run(); + } + + return session_metadata_->value(); +} + MockMediaSession::MockMediaSession() = default; MockMediaSession::MockMediaSession(bool force_duck) : force_duck_(force_duck) {}
diff --git a/services/media_session/public/cpp/test/mock_media_session.h b/services/media_session/public/cpp/test/mock_media_session.h index 5cba5df1..a66ad3b 100644 --- a/services/media_session/public/cpp/test/mock_media_session.h +++ b/services/media_session/public/cpp/test/mock_media_session.h
@@ -42,6 +42,7 @@ void WaitForState(mojom::MediaSessionInfo::SessionState wanted_state); void WaitForPlaybackState(mojom::MediaPlaybackState wanted_state); const base::Optional<MediaMetadata>& WaitForMetadata(); + const MediaMetadata& WaitForNonEmptyMetadata(); const mojom::MediaSessionInfoPtr& session_info() const { return session_info_; @@ -57,6 +58,7 @@ base::Optional<base::Optional<MediaMetadata>> session_metadata_; bool waiting_for_metadata_ = false; + bool waiting_for_non_empty_metadata_ = false; base::Optional<mojom::MediaSessionInfo::SessionState> wanted_state_; base::Optional<mojom::MediaPlaybackState> wanted_playback_state_; base::RunLoop run_loop_;
diff --git a/services/network/public/cpp/simple_url_loader.h b/services/network/public/cpp/simple_url_loader.h index d1446ac..dd9c8e0 100644 --- a/services/network/public/cpp/simple_url_loader.h +++ b/services/network/public/cpp/simple_url_loader.h
@@ -86,8 +86,11 @@ static const size_t kMaxUploadStringSizeToCopy; // Callback used when downloading the response body as a std::string. - // |response_body| is the body of the response, or nullptr on failure. It is - // safe to delete the SimpleURLLoader during the callback. + // |response_body| is the body of the response, or nullptr on failure. Note + // that |response_body| may be nullptr even if there's a valid response code + // like HTTP_OK, which could happen if there's an interruption before the + // full response body is received. It is safe to delete the SimpleURLLoader + // during the callback. using BodyAsStringCallback = base::OnceCallback<void(std::unique_ptr<std::string> response_body)>;
diff --git a/services/network/test/test_url_loader_factory.cc b/services/network/test/test_url_loader_factory.cc index 627738b..fab3064 100644 --- a/services/network/test/test_url_loader_factory.cc +++ b/services/network/test/test_url_loader_factory.cc
@@ -237,8 +237,12 @@ if (response_flags & kResponseOnlyRedirectsNoDestination) return; - if (status.error_code == net::OK) { + if ((response_flags & kSendHeadersOnNetworkError) || + status.error_code == net::OK) { client->OnReceiveResponse(head); + } + + if (status.error_code == net::OK) { mojo::DataPipe data_pipe(content.size()); uint32_t bytes_written = content.size(); CHECK_EQ(MOJO_RESULT_OK, data_pipe.producer_handle->WriteData(
diff --git a/services/network/test/test_url_loader_factory.h b/services/network/test/test_url_loader_factory.h index 4942418..55104966 100644 --- a/services/network/test/test_url_loader_factory.h +++ b/services/network/test/test_url_loader_factory.h
@@ -46,6 +46,7 @@ enum ResponseProduceFlags : uint32_t { kResponseDefault = 0, kResponseOnlyRedirectsNoDestination = 0x1, + kSendHeadersOnNetworkError = 0x2, }; TestURLLoaderFactory();
diff --git a/services/tracing/public/cpp/base_agent.cc b/services/tracing/public/cpp/base_agent.cc index 5ebd7f7..ccb31f6 100644 --- a/services/tracing/public/cpp/base_agent.cc +++ b/services/tracing/public/cpp/base_agent.cc
@@ -11,24 +11,23 @@ namespace tracing { -BaseAgent::BaseAgent(service_manager::Connector* connector, - const std::string& label, +BaseAgent::BaseAgent(const std::string& label, mojom::TraceDataType type, base::ProcessId pid) - : binding_(this) { - // |connector| can be null in tests. - if (!connector) - return; + : binding_(this), label_(label), type_(type), pid_(pid) {} + +BaseAgent::~BaseAgent() = default; + +void BaseAgent::Connect(service_manager::Connector* connector) { + DCHECK(!binding_ || !binding_.is_bound()); tracing::mojom::AgentRegistryPtr agent_registry; connector->BindInterface(tracing::mojom::kServiceName, &agent_registry); tracing::mojom::AgentPtr agent; binding_.Bind(mojo::MakeRequest(&agent)); - agent_registry->RegisterAgent(std::move(agent), label, type, pid); + agent_registry->RegisterAgent(std::move(agent), label_, type_, pid_); } -BaseAgent::~BaseAgent() = default; - void BaseAgent::StartTracing(const std::string& config, base::TimeTicks coordinator_time, Agent::StartTracingCallback callback) {
diff --git a/services/tracing/public/cpp/base_agent.h b/services/tracing/public/cpp/base_agent.h index f58e35d5..678c4ce 100644 --- a/services/tracing/public/cpp/base_agent.h +++ b/services/tracing/public/cpp/base_agent.h
@@ -21,12 +21,15 @@ // and StopAndFlush. namespace tracing { class COMPONENT_EXPORT(TRACING_CPP) BaseAgent : public mojom::Agent { + public: + ~BaseAgent() override; + + virtual void Connect(service_manager::Connector* connector); + protected: - BaseAgent(service_manager::Connector* connector, - const std::string& label, + BaseAgent(const std::string& label, mojom::TraceDataType type, base::ProcessId pid); - ~BaseAgent() override; private: // tracing::mojom::Agent: @@ -40,6 +43,10 @@ mojo::Binding<tracing::mojom::Agent> binding_; + const std::string label_; + const mojom::TraceDataType type_; + const base::ProcessId pid_; + DISALLOW_COPY_AND_ASSIGN(BaseAgent); };
diff --git a/services/tracing/public/cpp/perfetto/producer_client.cc b/services/tracing/public/cpp/perfetto/producer_client.cc index b7b6ac33..cafe3517 100644 --- a/services/tracing/public/cpp/perfetto/producer_client.cc +++ b/services/tracing/public/cpp/perfetto/producer_client.cc
@@ -8,7 +8,9 @@ #include "base/no_destructor.h" #include "base/task/post_task.h" +#include "services/service_manager/public/cpp/connector.h" #include "services/tracing/public/cpp/perfetto/shared_memory.h" +#include "services/tracing/public/mojom/constants.mojom.h" #include "third_party/perfetto/include/perfetto/tracing/core/commit_data_request.h" #include "third_party/perfetto/include/perfetto/tracing/core/shared_memory_arbiter.h" #include "third_party/perfetto/include/perfetto/tracing/core/trace_writer.h" @@ -79,6 +81,20 @@ GetPerfettoTaskRunner()->ResetTaskRunnerForTesting(CreateTaskRunner()); } +void ProducerClient::Connect(service_manager::Connector* connector) { + mojom::PerfettoServicePtr perfetto_service; + connector->BindInterface(mojom::kServiceName, &perfetto_service); + + CreateMojoMessagepipes(base::BindOnce( + [](mojom::PerfettoServicePtr perfetto_service, + mojom::ProducerClientPtr producer_client_pipe, + mojom::ProducerHostRequest producer_host_pipe) { + perfetto_service->ConnectToProducerHost(std::move(producer_client_pipe), + std::move(producer_host_pipe)); + }, + std::move(perfetto_service))); +} + void ProducerClient::CreateMojoMessagepipes( MessagepipesReadyCallback callback) { auto origin_task_runner = base::SequencedTaskRunnerHandle::Get(); @@ -100,6 +116,7 @@ mojom::ProducerClientRequest producer_client_request, mojom::ProducerClientPtr producer_client) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(!binding_ || !binding_->is_bound()); binding_ = std::make_unique<mojo::Binding<mojom::ProducerClient>>( this, std::move(producer_client_request));
diff --git a/services/tracing/public/cpp/perfetto/producer_client.h b/services/tracing/public/cpp/perfetto/producer_client.h index 82fba91..1473236 100644 --- a/services/tracing/public/cpp/perfetto/producer_client.h +++ b/services/tracing/public/cpp/perfetto/producer_client.h
@@ -25,6 +25,10 @@ class SharedMemoryArbiter; } // namespace perfetto +namespace service_manager { +class Connector; +} // namespace service_manager + namespace tracing { class MojoSharedMemory; @@ -80,6 +84,8 @@ // Returns the taskrunner used by Perfetto. static base::SequencedTaskRunner* GetTaskRunner(); + void Connect(service_manager::Connector* connector); + // Create the messagepipes that'll be used to connect // to the service-side ProducerHost, on the correct // sequence. The callback will be called on same sequence
diff --git a/services/tracing/public/cpp/trace_event_agent.cc b/services/tracing/public/cpp/trace_event_agent.cc index aa863cdb..4ee48d75 100644 --- a/services/tracing/public/cpp/trace_event_agent.cc +++ b/services/tracing/public/cpp/trace_event_agent.cc
@@ -18,98 +18,54 @@ #include "base/trace_event/trace_log.h" #include "base/values.h" #include "build/build_config.h" -#include "services/service_manager/public/cpp/connector.h" #include "services/tracing/public/cpp/tracing_features.h" -#include "services/tracing/public/mojom/constants.mojom.h" #if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_MACOSX) || \ defined(OS_WIN) #define PERFETTO_AVAILABLE #include "services/tracing/public/cpp/perfetto/producer_client.h" #include "services/tracing/public/cpp/perfetto/trace_event_data_source.h" -#include "third_party/perfetto/include/perfetto/tracing/core/trace_writer.h" -#include "third_party/perfetto/protos/perfetto/trace/chrome/chrome_trace_event.pbzero.h" -#include "third_party/perfetto/protos/perfetto/trace/trace_packet.pbzero.h" #endif namespace { const char kTraceEventLabel[] = "traceEvents"; -tracing::TraceEventAgent* g_trace_event_agent; - } // namespace namespace tracing { -#if defined(PERFETTO_AVAILABLE) - -namespace { - -void InitializeProducerClient(service_manager::Connector* connector) { - mojom::PerfettoServicePtr perfetto_service; - connector->BindInterface(mojom::kServiceName, &perfetto_service); - - ProducerClient* client = ProducerClient::Get(); - client->CreateMojoMessagepipes(base::BindOnce( - [](mojom::PerfettoServicePtr perfetto_service, - mojom::ProducerClientPtr producer_client_pipe, - mojom::ProducerHostRequest producer_host_pipe) { - perfetto_service->ConnectToProducerHost(std::move(producer_client_pipe), - std::move(producer_host_pipe)); - }, - std::move(perfetto_service))); - - client->AddDataSource(TraceEventDataSource::GetInstance()); -} - -void AddPerfettoMetadataGeneratorFunction( - TraceEventAgent::MetadataGeneratorFunction generator) { - // Instantiate and register the metadata data source on the first - // call. - static TraceEventMetadataSource* metadata_source = []() { - static base::NoDestructor<TraceEventMetadataSource> instance; - ProducerClient::Get()->AddDataSource(instance.get()); - return instance.get(); - }(); - - metadata_source->AddGeneratorFunction(generator); -} - -} // namespace - -#endif - // static -std::unique_ptr<TraceEventAgent> TraceEventAgent::Create( - service_manager::Connector* connector, - bool request_clock_sync_marker_on_android) { -#if defined(PERFETTO_AVAILABLE) - InitializeProducerClient(connector); -#endif - - return std::make_unique<TraceEventAgent>( - connector, request_clock_sync_marker_on_android); +TraceEventAgent* TraceEventAgent::GetInstance() { + static base::NoDestructor<TraceEventAgent> instance; + return instance.get(); } -TraceEventAgent::TraceEventAgent(service_manager::Connector* connector, - bool request_clock_sync_marker_on_android) - : BaseAgent(connector, - kTraceEventLabel, +void TraceEventAgent::Connect(service_manager::Connector* connector) { + // |connector| can be null in tests. + if (!connector) { + return; + } + + BaseAgent::Connect(connector); + +#if defined(PERFETTO_AVAILABLE) + ProducerClient::Get()->Connect(connector); +#endif +} + +TraceEventAgent::TraceEventAgent() + : BaseAgent(kTraceEventLabel, mojom::TraceDataType::ARRAY, base::trace_event::TraceLog::GetInstance()->process_id()), - enabled_tracing_modes_(0), - request_clock_sync_marker_on_android_( - request_clock_sync_marker_on_android) { + enabled_tracing_modes_(0) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(!g_trace_event_agent); - g_trace_event_agent = this; +#if defined(PERFETTO_AVAILABLE) + ProducerClient::Get()->AddDataSource(TraceEventDataSource::GetInstance()); +#endif } -TraceEventAgent::~TraceEventAgent() { - g_trace_event_agent = nullptr; - DCHECK(!trace_log_needs_me_); -} +TraceEventAgent::~TraceEventAgent() = default; void TraceEventAgent::GetCategories(GetCategoriesCallback callback) { std::vector<std::string> category_vector; @@ -122,8 +78,17 @@ MetadataGeneratorFunction generator) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); metadata_generator_functions_.push_back(generator); + #if defined(PERFETTO_AVAILABLE) - AddPerfettoMetadataGeneratorFunction(generator); + // Instantiate and register the metadata data source on the first + // call. + static TraceEventMetadataSource* metadata_source = []() { + static base::NoDestructor<TraceEventMetadataSource> instance; + ProducerClient::Get()->AddDataSource(instance.get()); + return instance.get(); + }(); + + metadata_source->AddGeneratorFunction(generator); #endif } @@ -150,10 +115,6 @@ void TraceEventAgent::StopAndFlush(mojom::RecorderPtr recorder) { DCHECK(!recorder_); -#if defined(OS_ANDROID) - if (request_clock_sync_marker_on_android_) - base::trace_event::TraceLog::GetInstance()->AddClockSyncMetadataEvent(); -#endif recorder_ = std::move(recorder); base::trace_event::TraceLog::GetInstance()->SetDisabled( enabled_tracing_modes_); @@ -163,7 +124,7 @@ if (metadata) recorder_->AddMetadata(std::move(*metadata)); } - trace_log_needs_me_ = true; + base::trace_event::TraceLog::GetInstance()->Flush( base::Bind(&TraceEventAgent::OnTraceLogFlush, base::Unretained(this))); } @@ -181,7 +142,6 @@ if (!events_str->data().empty()) recorder_->AddChunk(events_str->data()); if (!has_more_events) { - trace_log_needs_me_ = false; recorder_.reset(); } }
diff --git a/services/tracing/public/cpp/trace_event_agent.h b/services/tracing/public/cpp/trace_event_agent.h index 8ba14839f..b5615e5 100644 --- a/services/tracing/public/cpp/trace_event_agent.h +++ b/services/tracing/public/cpp/trace_event_agent.h
@@ -34,22 +34,20 @@ // interface instead. class COMPONENT_EXPORT(TRACING_CPP) TraceEventAgent : public BaseAgent { public: + static TraceEventAgent* GetInstance(); + + void Connect(service_manager::Connector* connector) override; + using MetadataGeneratorFunction = base::RepeatingCallback<std::unique_ptr<base::DictionaryValue>()>; - - static std::unique_ptr<TraceEventAgent> Create( - service_manager::Connector* connector, - bool request_clock_sync_marker_on_android); - - TraceEventAgent(service_manager::Connector* connector, - bool request_clock_sync_marker_on_android); - void AddMetadataGeneratorFunction(MetadataGeneratorFunction generator); private: + friend base::NoDestructor<tracing::TraceEventAgent>; friend std::default_delete<TraceEventAgent>; // For Testing friend class TraceEventAgentTest; // For Testing + TraceEventAgent(); ~TraceEventAgent() override; // mojom::Agent @@ -66,10 +64,8 @@ bool has_more_events); uint8_t enabled_tracing_modes_; - bool request_clock_sync_marker_on_android_; mojom::RecorderPtr recorder_; std::vector<MetadataGeneratorFunction> metadata_generator_functions_; - bool trace_log_needs_me_ = false; THREAD_CHECKER(thread_checker_);
diff --git a/services/tracing/public/cpp/trace_event_agent_unittest.cc b/services/tracing/public/cpp/trace_event_agent_unittest.cc index d385fd67..7fe1d40 100644 --- a/services/tracing/public/cpp/trace_event_agent_unittest.cc +++ b/services/tracing/public/cpp/trace_event_agent_unittest.cc
@@ -82,16 +82,13 @@ class TraceEventAgentTest : public testing::Test { public: - void SetUp() override { agent_.reset(new TraceEventAgent(nullptr, false)); } - void TearDown() override { base::trace_event::TraceLog::GetInstance()->SetDisabled(); recorder_.reset(); - agent_.reset(); } void StartTracing(const std::string& categories) { - agent_->StartTracing( + TraceEventAgent::GetInstance()->StartTracing( base::trace_event::TraceConfig(categories, "").ToString(), base::TimeTicks::Now(), base::BindRepeating([](bool success) { EXPECT_TRUE(success); })); @@ -101,17 +98,17 @@ mojom::RecorderPtr recorder_ptr; recorder_.reset(new MockRecorder(MakeRequest(&recorder_ptr))); recorder_->set_quit_closure(quit_closure); - agent_->StopAndFlush(std::move(recorder_ptr)); + TraceEventAgent::GetInstance()->StopAndFlush(std::move(recorder_ptr)); } void AddMetadataGeneratorFunction( TraceEventAgent::MetadataGeneratorFunction generator) { - agent_->AddMetadataGeneratorFunction(generator); + TraceEventAgent::GetInstance()->AddMetadataGeneratorFunction(generator); } void GetCategories(const std::string& expected_category, base::Closure quit_closure) { - agent_->GetCategories(base::BindRepeating( + TraceEventAgent::GetInstance()->GetCategories(base::BindRepeating( &TraceEventAgentTest::OnGetCategoriesReply, base::Unretained(this), expected_category, quit_closure)); } @@ -127,7 +124,6 @@ private: base::test::ScopedTaskEnvironment scoped_task_environment_; - std::unique_ptr<TraceEventAgent> agent_; std::unique_ptr<MockRecorder> recorder_; };
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json index e2707e5..424d0099 100644 --- a/testing/buildbot/chromium.chromiumos.json +++ b/testing/buildbot/chromium.chromiumos.json
@@ -1042,8 +1042,7 @@ }, { "args": [ - "--enable-features=SingleProcessMash", - "--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.single_process_mash.unit_tests.filter" + "--enable-features=SingleProcessMash" ], "name": "single_process_mash_unit_tests", "swarming": { @@ -1748,8 +1747,7 @@ }, { "args": [ - "--enable-features=SingleProcessMash", - "--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.single_process_mash.unit_tests.filter" + "--enable-features=SingleProcessMash" ], "name": "single_process_mash_unit_tests", "swarming": {
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json index f3bfb87..d6324176 100644 --- a/testing/buildbot/chromium.memory.json +++ b/testing/buildbot/chromium.memory.json
@@ -5011,7 +5011,6 @@ { "args": [ "--enable-features=SingleProcessMash", - "--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.single_process_mash.unit_tests.filter", "--test-launcher-print-test-stdio=always" ], "name": "single_process_mash_unit_tests", @@ -6536,7 +6535,6 @@ { "args": [ "--enable-features=SingleProcessMash", - "--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.single_process_mash.unit_tests.filter", "--test-launcher-print-test-stdio=always" ], "name": "single_process_mash_unit_tests",
diff --git a/testing/buildbot/filters/BUILD.gn b/testing/buildbot/filters/BUILD.gn index 487d5e6..c229657 100644 --- a/testing/buildbot/filters/BUILD.gn +++ b/testing/buildbot/filters/BUILD.gn
@@ -82,14 +82,6 @@ ] } -source_set("unit_tests_filters") { - testonly = true - - data = [ - "//testing/buildbot/filters/chromeos.single_process_mash.unit_tests.filter", - ] -} - source_set("webview_instrumentation_test_apk_filters") { testonly = true
diff --git a/testing/buildbot/filters/chromeos.single_process_mash.unit_tests.filter b/testing/buildbot/filters/chromeos.single_process_mash.unit_tests.filter deleted file mode 100644 index aba3829..0000000 --- a/testing/buildbot/filters/chromeos.single_process_mash.unit_tests.filter +++ /dev/null
@@ -1,14 +0,0 @@ -# Multi profile: https://crbug.com/910241 --BrowserFinderChromeOSTest.FindBrowserOwnedByAnotherProfile - -# Immersive mode: https://crbug.com/910249 --ImmersiveModeControllerAshTest.LockedFullscreenDisablesImmersive --ImmersiveModeControllerAshTest.RegularToLockedFullscreenDisablesImmersive --ImmersiveModeControllerAshTest.TabAndBrowserFullscreen - -# https://crbug.com/910240 --ArcInputMethodManagerServiceTest.DisableFallbackVirtualKeyboard - -# Fails because a MusClient is needed. Blocked on folding views_mus_test_suite -# into views_test_suite. --OmniboxViewViewsSteadyStateElisionsTest.GestureTaps
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index 967dec9..fdababe 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -3550,8 +3550,7 @@ 'single_process_mash_unit_tests': { 'test': 'unit_tests', 'args': [ - '--enable-features=SingleProcessMash', - '--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.single_process_mash.unit_tests.filter', + '--enable-features=SingleProcessMash' ], }, 'ui_chromeos_unittests': {},
diff --git a/third_party/blink/public/platform/web_feature.mojom b/third_party/blink/public/platform/web_feature.mojom index 99f7eb9..5924d1d6 100644 --- a/third_party/blink/public/platform/web_feature.mojom +++ b/third_party/blink/public/platform/web_feature.mojom
@@ -2092,6 +2092,16 @@ kV8RegExpMatchIsFalseishOnJSRegExp = 2651, kDownloadInAdFrameWithUserGesture = 2652, kDownloadInAdFrameWithoutUserGesture = 2653, + kNavigatorAppVersion = 2654, + kNavigatorDoNotTrack = 2655, + kNavigatorHardwareConcurrency = 2656, + kNavigatorLanguage = 2657, + kNavigatorLanguages = 2658, + kNavigatorMaxTouchPoints = 2659, + kNavigatorMimeTypes = 2660, + kNavigatorPlatform = 2661, + kNavigatorPlugins = 2662, + kNavigatorUserAgent = 2663, // Add new features immediately above this line. Don't change assigned // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/public/web/web_view.h b/third_party/blink/public/web/web_view.h index be4c27c3..7d14bb6 100644 --- a/third_party/blink/public/web/web_view.h +++ b/third_party/blink/public/web/web_view.h
@@ -259,6 +259,9 @@ // Requests a page-scale animation based on the specified point/rect. virtual void AnimateDoubleTapZoom(const gfx::Point&, const WebRect&) = 0; + // Requests a page-scale animation based on the specified rect. + virtual void ZoomToFindInPageRect(const WebRect&) = 0; + // Sets the display mode of the web app. virtual void SetDisplayMode(WebDisplayMode) = 0;
diff --git a/third_party/blink/public/web/web_widget_client.h b/third_party/blink/public/web/web_widget_client.h index b0abc6bc..fdac6cd 100644 --- a/third_party/blink/public/web/web_widget_client.h +++ b/third_party/blink/public/web/web_widget_client.h
@@ -182,6 +182,9 @@ // Double tap zooms a rect in the main-frame renderer. virtual void AnimateDoubleTapZoomInMainFrame(const blink::WebPoint& point, const blink::WebRect& bounds) {} + + // Find in page zooms a rect in the main-frame renderer. + virtual void ZoomToFindInPageRectInMainFrame(const blink::WebRect& rect) {} }; } // namespace blink
diff --git a/third_party/blink/renderer/bindings/IDLExtendedAttributes.md b/third_party/blink/renderer/bindings/IDLExtendedAttributes.md index 29c3d757..108fc38 100644 --- a/third_party/blink/renderer/bindings/IDLExtendedAttributes.md +++ b/third_party/blink/renderer/bindings/IDLExtendedAttributes.md
@@ -932,6 +932,22 @@ Usage: `[CustomElementCallbacks]` takes no arguments. +### [HighEntropy] _(m, a, c)_ + +Summary: Denotes an API that exposes data that folks on the internet find useful for fingerprinting. + +Attributes and methods marked as `[HighEntropy]` are known to be practically useful for [identifying particular clients](https://dev.chromium.org/Home/chromium-security/client-identification-mechanisms) on the web today. +Both methods and attribute/constant getters annotated with this attribute are wired up to [`Dactyloscoper::Record`](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/blink/renderer/core/frame/use_counter.cc&q=Dactyloscoper::Record) for additional processing. + +This attribute must be accompanied by either `[Measure]` or `[MeasureAs]`. + +```webidl +[HighEntropy, Measure] attribute Node interestingAttribute; +[HighEntropy, MeasureAs=InterestingNamedAttribute] attribute Node interestingNamedAttribute; +[HighEntropy, Measure] Node getInterestingNode(); +[HighEntropy, Measure] const INTERESTING_CONSTANT = 1; +``` + ### [Default] _(p)_ Summary: `[Default]` allows one to specify the default values for optional arguments. This removes the need to have C++ overloads in the Blink implementation.
diff --git a/third_party/blink/renderer/bindings/IDLExtendedAttributes.txt b/third_party/blink/renderer/bindings/IDLExtendedAttributes.txt index 9a36e75..4b929ed3 100644 --- a/third_party/blink/renderer/bindings/IDLExtendedAttributes.txt +++ b/third_party/blink/renderer/bindings/IDLExtendedAttributes.txt
@@ -58,6 +58,7 @@ FeaturePolicy=* FlexibleArrayBufferView Global=* +HighEntropy HTMLConstructor ImmutablePrototype ImplementedAs=*
diff --git a/third_party/blink/renderer/bindings/scripts/v8_attributes.py b/third_party/blink/renderer/bindings/scripts/v8_attributes.py index f06d6df..17c791f1 100644 --- a/third_party/blink/renderer/bindings/scripts/v8_attributes.py +++ b/third_party/blink/renderer/bindings/scripts/v8_attributes.py
@@ -129,6 +129,9 @@ deprecate_as = v8_utilities.deprecate_as(attribute) measure_as = v8_utilities.measure_as(attribute, interface) + # [HighEntropy] + high_entropy = v8_utilities.high_entropy(attribute) + is_lazy_data_attribute = \ (constructor_type and not (measure_as or deprecate_as)) or \ (str(idl_type) == 'Window' and attribute.name in ('frames', 'self', 'window')) @@ -144,6 +147,7 @@ 'cpp_name': cpp_name(attribute), 'cpp_type': idl_type.cpp_type, 'cpp_type_initializer': idl_type.cpp_type_initializer, + 'high_entropy': high_entropy, 'deprecate_as': deprecate_as, 'enum_type': idl_type.enum_type, 'enum_values': idl_type.enum_values,
diff --git a/third_party/blink/renderer/bindings/scripts/v8_interface.py b/third_party/blink/renderer/bindings/scripts/v8_interface.py index 3468250..343b168be 100644 --- a/third_party/blink/renderer/bindings/scripts/v8_interface.py +++ b/third_party/blink/renderer/bindings/scripts/v8_interface.py
@@ -841,6 +841,7 @@ 'deprecate_as': v8_utilities.deprecate_as(constant), # [DeprecateAs] 'idl_type': constant.idl_type.name, 'measure_as': v8_utilities.measure_as(constant, interface), # [MeasureAs] + 'high_entropy': v8_utilities.high_entropy(constant), # [HighEntropy] 'name': constant.name, 'origin_trial_feature_name': v8_utilities.origin_trial_feature_name(constant), # [OriginTrialEnabled] # FIXME: use 'reflected_name' as correct 'name'
diff --git a/third_party/blink/renderer/bindings/scripts/v8_methods.py b/third_party/blink/renderer/bindings/scripts/v8_methods.py index 11dbd99..cbd6848c 100644 --- a/third_party/blink/renderer/bindings/scripts/v8_methods.py +++ b/third_party/blink/renderer/bindings/scripts/v8_methods.py
@@ -195,6 +195,7 @@ if idl_type.is_explicit_nullable else idl_type.cpp_type), 'cpp_value': this_cpp_value, 'cpp_type_initializer': idl_type.cpp_type_initializer, + 'high_entropy': v8_utilities.high_entropy(method), # [HighEntropy] 'deprecate_as': v8_utilities.deprecate_as(method), # [DeprecateAs] 'do_not_test_new_object': 'DoNotTestNewObject' in extended_attributes, 'exposed_test': v8_utilities.exposed(method, interface), # [Exposed]
diff --git a/third_party/blink/renderer/bindings/scripts/v8_utilities.py b/third_party/blink/renderer/bindings/scripts/v8_utilities.py index 0d523207..29e9c52 100644 --- a/third_party/blink/renderer/bindings/scripts/v8_utilities.py +++ b/third_party/blink/renderer/bindings/scripts/v8_utilities.py
@@ -402,6 +402,19 @@ return None +# [HighEntropy] +def high_entropy(definition_or_member): + extended_attributes = definition_or_member.extended_attributes + if 'HighEntropy' in extended_attributes: + includes.add('core/frame/dactyloscoper.h') + if not ('Measure' in extended_attributes or 'MeasureAs' in extended_attributes): + raise Exception('%s specified [HighEntropy], but does not include ' + 'either [Measure] or [MeasureAs]' + % definition_or_member.name) + return True + return False + + # [OriginTrialEnabled] def origin_trial_feature_name(definition_or_member): """Returns the name of the feature for the OriginTrialEnabled attribute.
diff --git a/third_party/blink/renderer/bindings/templates/attributes.cc.tmpl b/third_party/blink/renderer/bindings/templates/attributes.cc.tmpl index 1d37cc0..202786f4 100644 --- a/third_party/blink/renderer/bindings/templates/attributes.cc.tmpl +++ b/third_party/blink/renderer/bindings/templates/attributes.cc.tmpl
@@ -252,7 +252,11 @@ {% endif %} {% if attribute.measure_as %} - UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{attribute.measure_as('AttributeGetter')}}); + ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate()); + UseCounter::Count(execution_context_for_measurement, WebFeature::k{{attribute.measure_as('AttributeGetter')}}); + {% if attribute.high_entropy %} + Dactyloscoper::Record(execution_context_for_measurement, WebFeature::k{{attribute.measure_as('AttributeGetter')}}); + {% endif %} {% endif %} {% if world_suffix in attribute.activity_logging_world_list_for_getter %} @@ -290,7 +294,11 @@ {% endif %} {% if attribute.measure_as %} - UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{attribute.measure_as('ConstructorGetter')}}); + ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate()); + UseCounter::Count(execution_context_for_measurement, WebFeature::k{{attribute.measure_as('ConstructorGetter')}}); + {% if attribute.high_entropy %} + Dactyloscoper::Record(execution_context_for_measurement, WebFeature::k{{attribute.measure_as('ConstructorGetter')}}); + {% endif %} {% endif %} {% if attribute.is_named_constructor %}
diff --git a/third_party/blink/renderer/bindings/templates/constants.cc.tmpl b/third_party/blink/renderer/bindings/templates/constants.cc.tmpl index a9fba5a4..2ba625e 100644 --- a/third_party/blink/renderer/bindings/templates/constants.cc.tmpl +++ b/third_party/blink/renderer/bindings/templates/constants.cc.tmpl
@@ -8,7 +8,11 @@ Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{constant.deprecate_as}}); {% endif %} {% if constant.measure_as %} - UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{constant.measure_as('ConstantGetter')}}); + ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate()); + UseCounter::Count(execution_context_for_measurement, WebFeature::k{{constant.measure_as('ConstantGetter')}}); + {% if constant.high_entropy %} + Dactyloscoper::Record(execution_context_for_measurement, WebFeature::k{{constant.measure_as('ConstantGetter')}}); + {% endif %} {% endif %} {% if constant.idl_type in ('Double', 'Float') %} V8SetReturnValue(info, {{constant.value}});
diff --git a/third_party/blink/renderer/bindings/templates/interface.cc.tmpl b/third_party/blink/renderer/bindings/templates/interface.cc.tmpl index e3e1dd2..8765554 100644 --- a/third_party/blink/renderer/bindings/templates/interface.cc.tmpl +++ b/third_party/blink/renderer/bindings/templates/interface.cc.tmpl
@@ -915,7 +915,11 @@ {{exported}}void ConstructorCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { {{ runtime_timer_scope_disabled_by_default(runtime_call_stats.constructor_counter) }} {% if measure_as %} - UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{measure_as('Constructor')}}); + ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate()); + UseCounter::Count(execution_context_for_measurement, WebFeature::k{{measure_as('Constructor')}}); + {% if high_entropy %} + Dactyloscoper::Record(execution_context_for_measurement, WebFeature::k{{measure_as('Constructor')}}); + {% endif %} {% endif %} if (!info.IsConstructCall()) { V8ThrowException::ThrowTypeError(
diff --git a/third_party/blink/renderer/bindings/templates/methods.cc.tmpl b/third_party/blink/renderer/bindings/templates/methods.cc.tmpl index 6de09d31..3cecdf7 100644 --- a/third_party/blink/renderer/bindings/templates/methods.cc.tmpl +++ b/third_party/blink/renderer/bindings/templates/methods.cc.tmpl
@@ -472,7 +472,11 @@ {% macro test_and_call_overloaded_method(test, method, overloads, world_suffix) %} if ({{test}}) { {% if method.measure_as and not overloads.measure_all_as %} - UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{method.measure_as('Method')}}); + ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate()); + UseCounter::Count(execution_context_for_measurement, WebFeature::k{{method.measure_as('Method')}}); + {% if method.high_entropy %} + Dactyloscoper::Record(execution_context_for_measurement, WebFeature::k{{method.measure_as('Method')}}); + {% endif %} {% endif %} {% if method.deprecate_as and not overloads.deprecate_all_as %} Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{method.deprecate_as}}); @@ -494,7 +498,11 @@ {% endif %} {% if not method.overloads %}{# Overloaded methods are measured in overload_resolution_method() #} {% if method.measure_as %} - UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{method.measure_as('Method')}}); + ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate()); + UseCounter::Count(execution_context_for_measurement, WebFeature::k{{method.measure_as('Method')}}); + {% if method.high_entropy %} + Dactyloscoper::Record(execution_context_for_measurement, WebFeature::k{{method.measure_as('Method')}}); + {% endif %} {% endif %} {% if method.deprecate_as %} Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), WebFeature::k{{method.deprecate_as}});
diff --git a/third_party/blink/renderer/bindings/tests/idls/core/test_object.idl b/third_party/blink/renderer/bindings/tests/idls/core/test_object.idl index d583b3c..9b712d2 100644 --- a/third_party/blink/renderer/bindings/tests/idls/core/test_object.idl +++ b/third_party/blink/renderer/bindings/tests/idls/core/test_object.idl
@@ -486,6 +486,16 @@ [MeasureAs=TestFeature] void measureAsSameValueOverloadedMethod(); [MeasureAs=TestFeature] void measureAsSameValueOverloadedMethod(long arg); + // [HighEntropy] + [HighEntropy,Measure] const DOMString highEntropyConstant = 1; + [HighEntropy,MeasureAs=TestFeatureHighEntropyConstant] const DOMString highEntropyConstant = 1; + [HighEntropy,Measure] void highEntropyMethodWithMeasure(); + [HighEntropy,MeasureAs=TestFeatureHighEntropy] void highEntropyMethodWithMeasureAs(); + [HighEntropy,Measure] attribute DOMString highEntropyAttributeWithMeasure; + [HighEntropy,Measure] readonly attribute DOMString highEntropyReadonlyAttributeWithMeasure; + [HighEntropy,MeasureAs=TestAttributeHighEntropy] attribute DOMString highEntropyAttributeWithMeasureAs; + [HighEntropy,MeasureAs=TestAttributeHighEntropy] readonly attribute DOMString highEntropyReadonlyAttributeWithMeasureAs; + // with [CEReactions] for not overloaded method [CEReactions] void ceReactionsNotOverloadedMethod(boolean arg); // with and without [CEReactions] for overloaded method
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_constants.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_constants.cc index c62971b..334c642 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_constants.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_constants.cc
@@ -78,7 +78,8 @@ void V8TestConstants::MEASUREDCONSTANTConstantGetterCallback(v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value>& info) { RUNTIME_CALL_TIMER_SCOPE_DISABLED_BY_DEFAULT(info.GetIsolate(), "Blink_TestConstants_MEASURED_CONSTANT_ConstantGetter"); - UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kConstant); + ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate()); + UseCounter::Count(execution_context_for_measurement, WebFeature::kConstant); V8SetReturnValueInt(info, 1); }
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface.cc index c4b8ddf..572193e 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface.cc
@@ -2607,7 +2607,8 @@ void V8TestInterface::TestInterfaceAttributeAttributeGetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { RUNTIME_CALL_TIMER_SCOPE_DISABLED_BY_DEFAULT(info.GetIsolate(), "Blink_TestInterfaceImplementation_testInterfaceAttribute_Getter"); - UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kV8TestInterface_TestInterfaceAttribute_AttributeGetter); + ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate()); + UseCounter::Count(execution_context_for_measurement, WebFeature::kV8TestInterface_TestInterfaceAttribute_AttributeGetter); test_interface_implementation_v8_internal::TestInterfaceAttributeAttributeGetter(info); }
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_constructor.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_constructor.cc index 2eb54fa7..79e8a8f 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_constructor.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_constructor.cc
@@ -342,7 +342,8 @@ CORE_EXPORT void ConstructorCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { RUNTIME_CALL_TIMER_SCOPE_DISABLED_BY_DEFAULT(info.GetIsolate(), "Blink_TestInterfaceConstructor_Constructor"); - UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestFeature); + ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate()); + UseCounter::Count(execution_context_for_measurement, WebFeature::kTestFeature); if (!info.IsConstructCall()) { V8ThrowException::ThrowTypeError( info.GetIsolate(),
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_object.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_object.cc index 945ae8d..d304445 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_object.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_object.cc
@@ -50,6 +50,7 @@ #include "third_party/blink/renderer/core/dom/class_collection.h" #include "third_party/blink/renderer/core/dom/tag_collection.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" +#include "third_party/blink/renderer/core/frame/dactyloscoper.h" #include "third_party/blink/renderer/core/frame/deprecation.h" #include "third_party/blink/renderer/core/frame/use_counter.h" #include "third_party/blink/renderer/core/html/custom/ce_reactions_scope.h" @@ -4360,6 +4361,74 @@ impl->setUnscopableRuntimeEnabledLongAttribute(cpp_value); } +static void HighEntropyAttributeWithMeasureAttributeGetter(const v8::FunctionCallbackInfo<v8::Value>& info) { + v8::Local<v8::Object> holder = info.Holder(); + + TestObject* impl = V8TestObject::ToImpl(holder); + + V8SetReturnValueString(info, impl->highEntropyAttributeWithMeasure(), info.GetIsolate()); +} + +static void HighEntropyAttributeWithMeasureAttributeSetter( + v8::Local<v8::Value> v8_value, const v8::FunctionCallbackInfo<v8::Value>& info) { + v8::Isolate* isolate = info.GetIsolate(); + ALLOW_UNUSED_LOCAL(isolate); + + v8::Local<v8::Object> holder = info.Holder(); + ALLOW_UNUSED_LOCAL(holder); + + TestObject* impl = V8TestObject::ToImpl(holder); + + // Prepare the value to be set. + V8StringResource<> cpp_value = v8_value; + if (!cpp_value.Prepare()) + return; + + impl->setHighEntropyAttributeWithMeasure(cpp_value); +} + +static void HighEntropyReadonlyAttributeWithMeasureAttributeGetter(const v8::FunctionCallbackInfo<v8::Value>& info) { + v8::Local<v8::Object> holder = info.Holder(); + + TestObject* impl = V8TestObject::ToImpl(holder); + + V8SetReturnValueString(info, impl->highEntropyReadonlyAttributeWithMeasure(), info.GetIsolate()); +} + +static void HighEntropyAttributeWithMeasureAsAttributeGetter(const v8::FunctionCallbackInfo<v8::Value>& info) { + v8::Local<v8::Object> holder = info.Holder(); + + TestObject* impl = V8TestObject::ToImpl(holder); + + V8SetReturnValueString(info, impl->highEntropyAttributeWithMeasureAs(), info.GetIsolate()); +} + +static void HighEntropyAttributeWithMeasureAsAttributeSetter( + v8::Local<v8::Value> v8_value, const v8::FunctionCallbackInfo<v8::Value>& info) { + v8::Isolate* isolate = info.GetIsolate(); + ALLOW_UNUSED_LOCAL(isolate); + + v8::Local<v8::Object> holder = info.Holder(); + ALLOW_UNUSED_LOCAL(holder); + + TestObject* impl = V8TestObject::ToImpl(holder); + + // Prepare the value to be set. + V8StringResource<> cpp_value = v8_value; + if (!cpp_value.Prepare()) + return; + + impl->setHighEntropyAttributeWithMeasureAs(cpp_value); +} + +static void HighEntropyReadonlyAttributeWithMeasureAsAttributeGetter(const v8::FunctionCallbackInfo<v8::Value>& info) { + v8::Local<v8::Object> holder = info.Holder(); + + TestObject* impl = V8TestObject::ToImpl(holder); + + V8SetReturnValueString(info, impl->highEntropyReadonlyAttributeWithMeasureAs(), info.GetIsolate()); +} + static void TestInterfaceAttributeAttributeGetter(const v8::FunctionCallbackInfo<v8::Value>& info) { v8::Local<v8::Object> holder = info.Holder(); @@ -8047,14 +8116,16 @@ switch (std::min(1, info.Length())) { case 0: if (true) { - UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kV8TestObject_MeasureOverloadedMethod_Method); + ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate()); + UseCounter::Count(execution_context_for_measurement, WebFeature::kV8TestObject_MeasureOverloadedMethod_Method); MeasureOverloadedMethod1Method(info); return; } break; case 1: if (true) { - UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kV8TestObject_MeasureOverloadedMethod_Method); + ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate()); + UseCounter::Count(execution_context_for_measurement, WebFeature::kV8TestObject_MeasureOverloadedMethod_Method); MeasureOverloadedMethod2Method(info); return; } @@ -8188,14 +8259,16 @@ switch (std::min(1, info.Length())) { case 0: if (true) { - UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestFeatureA); + ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate()); + UseCounter::Count(execution_context_for_measurement, WebFeature::kTestFeatureA); MeasureAsOverloadedMethod1Method(info); return; } break; case 1: if (true) { - UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestFeatureB); + ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate()); + UseCounter::Count(execution_context_for_measurement, WebFeature::kTestFeatureB); MeasureAsOverloadedMethod2Method(info); return; } @@ -8235,14 +8308,16 @@ switch (std::min(1, info.Length())) { case 0: if (true) { - UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestFeature); + ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate()); + UseCounter::Count(execution_context_for_measurement, WebFeature::kTestFeature); MeasureAsSameValueOverloadedMethod1Method(info); return; } break; case 1: if (true) { - UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestFeature); + ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate()); + UseCounter::Count(execution_context_for_measurement, WebFeature::kTestFeature); MeasureAsSameValueOverloadedMethod2Method(info); return; } @@ -8257,6 +8332,18 @@ exception_state.ThrowTypeError("No function was found that matched the signature provided."); } +static void HighEntropyMethodWithMeasureMethod(const v8::FunctionCallbackInfo<v8::Value>& info) { + TestObject* impl = V8TestObject::ToImpl(info.Holder()); + + impl->highEntropyMethodWithMeasure(); +} + +static void HighEntropyMethodWithMeasureAsMethod(const v8::FunctionCallbackInfo<v8::Value>& info) { + TestObject* impl = V8TestObject::ToImpl(info.Holder()); + + impl->highEntropyMethodWithMeasureAs(); +} + static void CeReactionsNotOverloadedMethodMethod(const v8::FunctionCallbackInfo<v8::Value>& info) { ExceptionState exception_state(info.GetIsolate(), ExceptionState::kExecutionContext, "TestObject", "ceReactionsNotOverloadedMethod"); CEReactionsScope ce_reactions_scope; @@ -8347,7 +8434,8 @@ switch (std::min(1, info.Length())) { case 0: if (true) { - UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestFeature); + ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate()); + UseCounter::Count(execution_context_for_measurement, WebFeature::kTestFeature); Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestFeatureA); DeprecateAsMeasureAsSameValueOverloadedMethod1Method(info); return; @@ -8355,7 +8443,8 @@ break; case 1: if (true) { - UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestFeature); + ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate()); + UseCounter::Count(execution_context_for_measurement, WebFeature::kTestFeature); Deprecation::CountDeprecation(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestFeatureB); DeprecateAsMeasureAsSameValueOverloadedMethod2Method(info); return; @@ -8398,14 +8487,16 @@ switch (std::min(1, info.Length())) { case 0: if (true) { - UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestFeatureA); + ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate()); + UseCounter::Count(execution_context_for_measurement, WebFeature::kTestFeatureA); DeprecateAsSameValueMeasureAsOverloadedMethod1Method(info); return; } break; case 1: if (true) { - UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestFeatureB); + ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate()); + UseCounter::Count(execution_context_for_measurement, WebFeature::kTestFeatureB); DeprecateAsSameValueMeasureAsOverloadedMethod2Method(info); return; } @@ -8447,14 +8538,16 @@ switch (std::min(1, info.Length())) { case 0: if (true) { - UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestFeatureB); + ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate()); + UseCounter::Count(execution_context_for_measurement, WebFeature::kTestFeatureB); DeprecateAsSameValueMeasureAsSameValueOverloadedMethod1Method(info); return; } break; case 1: if (true) { - UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestFeatureB); + ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate()); + UseCounter::Count(execution_context_for_measurement, WebFeature::kTestFeatureB); DeprecateAsSameValueMeasureAsSameValueOverloadedMethod2Method(info); return; } @@ -9423,6 +9516,24 @@ } // namespace test_object_v8_internal +void V8TestObject::HighEntropyConstantConstantGetterCallback(v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value>& info) { + RUNTIME_CALL_TIMER_SCOPE_DISABLED_BY_DEFAULT(info.GetIsolate(), "Blink_TestObject_highEntropyConstant_ConstantGetter"); + + ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate()); + UseCounter::Count(execution_context_for_measurement, WebFeature::kV8TestObject_HighEntropyConstant_ConstantGetter); + Dactyloscoper::Record(execution_context_for_measurement, WebFeature::kV8TestObject_HighEntropyConstant_ConstantGetter); + V8SetReturnValueString(info, "1"); +} + +void V8TestObject::HighEntropyConstantConstantGetterCallback(v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value>& info) { + RUNTIME_CALL_TIMER_SCOPE_DISABLED_BY_DEFAULT(info.GetIsolate(), "Blink_TestObject_highEntropyConstant_ConstantGetter"); + + ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate()); + UseCounter::Count(execution_context_for_measurement, WebFeature::kTestFeatureHighEntropyConstant); + Dactyloscoper::Record(execution_context_for_measurement, WebFeature::kTestFeatureHighEntropyConstant); + V8SetReturnValueString(info, "1"); +} + void V8TestObject::StringifierAttributeAttributeGetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { RUNTIME_CALL_TIMER_SCOPE_DISABLED_BY_DEFAULT(info.GetIsolate(), "Blink_TestObject_stringifierAttribute_Getter"); @@ -10508,7 +10619,8 @@ v8::Local<v8::Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) { RUNTIME_CALL_TIMER_SCOPE_DISABLED_BY_DEFAULT(info.GetIsolate(), "Blink_TestObject_measureAsFeatureNameTestInterfaceEmptyConstructorAttribute_ConstructorGetterCallback"); - UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kFeatureName); + ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate()); + UseCounter::Count(execution_context_for_measurement, WebFeature::kFeatureName); V8ConstructorAttributeGetter(property, info, V8TestInterfaceEmpty::GetWrapperTypeInfo()); } @@ -10661,7 +10773,8 @@ void V8TestObject::MeasureAsLongAttributeAttributeGetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { RUNTIME_CALL_TIMER_SCOPE_DISABLED_BY_DEFAULT(info.GetIsolate(), "Blink_TestObject_measureAsLongAttribute_Getter"); - UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestFeature); + ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate()); + UseCounter::Count(execution_context_for_measurement, WebFeature::kTestFeature); test_object_v8_internal::MeasureAsLongAttributeAttributeGetter(info); } @@ -11544,7 +11657,8 @@ void V8TestObject::MeasuredLongAttributeAttributeGetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { RUNTIME_CALL_TIMER_SCOPE_DISABLED_BY_DEFAULT(info.GetIsolate(), "Blink_TestObject_measuredLongAttribute_Getter"); - UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kV8TestObject_MeasuredLongAttribute_AttributeGetter); + ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate()); + UseCounter::Count(execution_context_for_measurement, WebFeature::kV8TestObject_MeasuredLongAttribute_AttributeGetter); test_object_v8_internal::MeasuredLongAttributeAttributeGetter(info); } @@ -11623,6 +11737,68 @@ test_object_v8_internal::UnscopableRuntimeEnabledLongAttributeAttributeSetter(v8_value, info); } +void V8TestObject::HighEntropyAttributeWithMeasureAttributeGetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { + RUNTIME_CALL_TIMER_SCOPE_DISABLED_BY_DEFAULT(info.GetIsolate(), "Blink_TestObject_highEntropyAttributeWithMeasure_Getter"); + + ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate()); + UseCounter::Count(execution_context_for_measurement, WebFeature::kV8TestObject_HighEntropyAttributeWithMeasure_AttributeGetter); + Dactyloscoper::Record(execution_context_for_measurement, WebFeature::kV8TestObject_HighEntropyAttributeWithMeasure_AttributeGetter); + + test_object_v8_internal::HighEntropyAttributeWithMeasureAttributeGetter(info); +} + +void V8TestObject::HighEntropyAttributeWithMeasureAttributeSetterCallback( + const v8::FunctionCallbackInfo<v8::Value>& info) { + RUNTIME_CALL_TIMER_SCOPE_DISABLED_BY_DEFAULT(info.GetIsolate(), "Blink_TestObject_highEntropyAttributeWithMeasure_Setter"); + + v8::Local<v8::Value> v8_value = info[0]; + + UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kV8TestObject_HighEntropyAttributeWithMeasure_AttributeSetter); + + test_object_v8_internal::HighEntropyAttributeWithMeasureAttributeSetter(v8_value, info); +} + +void V8TestObject::HighEntropyReadonlyAttributeWithMeasureAttributeGetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { + RUNTIME_CALL_TIMER_SCOPE_DISABLED_BY_DEFAULT(info.GetIsolate(), "Blink_TestObject_highEntropyReadonlyAttributeWithMeasure_Getter"); + + ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate()); + UseCounter::Count(execution_context_for_measurement, WebFeature::kV8TestObject_HighEntropyReadonlyAttributeWithMeasure_AttributeGetter); + Dactyloscoper::Record(execution_context_for_measurement, WebFeature::kV8TestObject_HighEntropyReadonlyAttributeWithMeasure_AttributeGetter); + + test_object_v8_internal::HighEntropyReadonlyAttributeWithMeasureAttributeGetter(info); +} + +void V8TestObject::HighEntropyAttributeWithMeasureAsAttributeGetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { + RUNTIME_CALL_TIMER_SCOPE_DISABLED_BY_DEFAULT(info.GetIsolate(), "Blink_TestObject_highEntropyAttributeWithMeasureAs_Getter"); + + ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate()); + UseCounter::Count(execution_context_for_measurement, WebFeature::kTestAttributeHighEntropy); + Dactyloscoper::Record(execution_context_for_measurement, WebFeature::kTestAttributeHighEntropy); + + test_object_v8_internal::HighEntropyAttributeWithMeasureAsAttributeGetter(info); +} + +void V8TestObject::HighEntropyAttributeWithMeasureAsAttributeSetterCallback( + const v8::FunctionCallbackInfo<v8::Value>& info) { + RUNTIME_CALL_TIMER_SCOPE_DISABLED_BY_DEFAULT(info.GetIsolate(), "Blink_TestObject_highEntropyAttributeWithMeasureAs_Setter"); + + v8::Local<v8::Value> v8_value = info[0]; + + UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestAttributeHighEntropy); + + test_object_v8_internal::HighEntropyAttributeWithMeasureAsAttributeSetter(v8_value, info); +} + +void V8TestObject::HighEntropyReadonlyAttributeWithMeasureAsAttributeGetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { + RUNTIME_CALL_TIMER_SCOPE_DISABLED_BY_DEFAULT(info.GetIsolate(), "Blink_TestObject_highEntropyReadonlyAttributeWithMeasureAs_Getter"); + + ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate()); + UseCounter::Count(execution_context_for_measurement, WebFeature::kTestAttributeHighEntropy); + Dactyloscoper::Record(execution_context_for_measurement, WebFeature::kTestAttributeHighEntropy); + + test_object_v8_internal::HighEntropyReadonlyAttributeWithMeasureAsAttributeGetter(info); +} + void V8TestObject::TestInterfaceAttributeAttributeGetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { RUNTIME_CALL_TIMER_SCOPE_DISABLED_BY_DEFAULT(info.GetIsolate(), "Blink_TestObject_testInterfaceAttribute_Getter"); @@ -12751,14 +12927,16 @@ void V8TestObject::MeasureAsVoidMethodMethodCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { RUNTIME_CALL_TIMER_SCOPE_DISABLED_BY_DEFAULT(info.GetIsolate(), "Blink_TestObject_measureAsVoidMethod"); - UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kTestFeature); + ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate()); + UseCounter::Count(execution_context_for_measurement, WebFeature::kTestFeature); test_object_v8_internal::MeasureAsVoidMethodMethod(info); } void V8TestObject::MeasureMethodMethodCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { RUNTIME_CALL_TIMER_SCOPE_DISABLED_BY_DEFAULT(info.GetIsolate(), "Blink_TestObject_measureMethod"); - UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kV8TestObject_MeasureMethod_Method); + ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate()); + UseCounter::Count(execution_context_for_measurement, WebFeature::kV8TestObject_MeasureMethod_Method); test_object_v8_internal::MeasureMethodMethod(info); } @@ -12792,6 +12970,24 @@ test_object_v8_internal::MeasureAsSameValueOverloadedMethodMethod(info); } +void V8TestObject::HighEntropyMethodWithMeasureMethodCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { + RUNTIME_CALL_TIMER_SCOPE_DISABLED_BY_DEFAULT(info.GetIsolate(), "Blink_TestObject_highEntropyMethodWithMeasure"); + + ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate()); + UseCounter::Count(execution_context_for_measurement, WebFeature::kV8TestObject_HighEntropyMethodWithMeasure_Method); + Dactyloscoper::Record(execution_context_for_measurement, WebFeature::kV8TestObject_HighEntropyMethodWithMeasure_Method); + test_object_v8_internal::HighEntropyMethodWithMeasureMethod(info); +} + +void V8TestObject::HighEntropyMethodWithMeasureAsMethodCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { + RUNTIME_CALL_TIMER_SCOPE_DISABLED_BY_DEFAULT(info.GetIsolate(), "Blink_TestObject_highEntropyMethodWithMeasureAs"); + + ExecutionContext* execution_context_for_measurement = CurrentExecutionContext(info.GetIsolate()); + UseCounter::Count(execution_context_for_measurement, WebFeature::kTestFeatureHighEntropy); + Dactyloscoper::Record(execution_context_for_measurement, WebFeature::kTestFeatureHighEntropy); + test_object_v8_internal::HighEntropyMethodWithMeasureAsMethod(info); +} + void V8TestObject::CeReactionsNotOverloadedMethodMethodCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { RUNTIME_CALL_TIMER_SCOPE_DISABLED_BY_DEFAULT(info.GetIsolate(), "Blink_TestObject_ceReactionsNotOverloadedMethod"); @@ -13364,6 +13560,10 @@ { "saveSameObjectAttribute", V8TestObject::SaveSameObjectAttributeAttributeGetterCallback, nullptr, V8PrivateProperty::kNoCachedAccessor, static_cast<v8::PropertyAttribute>(v8::ReadOnly), V8DOMConfiguration::kOnPrototype, V8DOMConfiguration::kCheckHolder, V8DOMConfiguration::kHasSideEffect, V8DOMConfiguration::kAlwaysCallGetter, V8DOMConfiguration::kAllWorlds }, { "staticSaveSameObjectAttribute", V8TestObject::StaticSaveSameObjectAttributeAttributeGetterCallback, nullptr, V8PrivateProperty::kNoCachedAccessor, static_cast<v8::PropertyAttribute>(v8::ReadOnly), V8DOMConfiguration::kOnInterface, V8DOMConfiguration::kCheckHolder, V8DOMConfiguration::kHasSideEffect, V8DOMConfiguration::kAlwaysCallGetter, V8DOMConfiguration::kAllWorlds }, { "unscopableLongAttribute", V8TestObject::UnscopableLongAttributeAttributeGetterCallback, V8TestObject::UnscopableLongAttributeAttributeSetterCallback, V8PrivateProperty::kNoCachedAccessor, static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::kOnPrototype, V8DOMConfiguration::kCheckHolder, V8DOMConfiguration::kHasSideEffect, V8DOMConfiguration::kAlwaysCallGetter, V8DOMConfiguration::kAllWorlds }, + { "highEntropyAttributeWithMeasure", V8TestObject::HighEntropyAttributeWithMeasureAttributeGetterCallback, V8TestObject::HighEntropyAttributeWithMeasureAttributeSetterCallback, V8PrivateProperty::kNoCachedAccessor, static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::kOnPrototype, V8DOMConfiguration::kCheckHolder, V8DOMConfiguration::kHasSideEffect, V8DOMConfiguration::kAlwaysCallGetter, V8DOMConfiguration::kAllWorlds }, + { "highEntropyReadonlyAttributeWithMeasure", V8TestObject::HighEntropyReadonlyAttributeWithMeasureAttributeGetterCallback, nullptr, V8PrivateProperty::kNoCachedAccessor, static_cast<v8::PropertyAttribute>(v8::ReadOnly), V8DOMConfiguration::kOnPrototype, V8DOMConfiguration::kCheckHolder, V8DOMConfiguration::kHasSideEffect, V8DOMConfiguration::kAlwaysCallGetter, V8DOMConfiguration::kAllWorlds }, + { "highEntropyAttributeWithMeasureAs", V8TestObject::HighEntropyAttributeWithMeasureAsAttributeGetterCallback, V8TestObject::HighEntropyAttributeWithMeasureAsAttributeSetterCallback, V8PrivateProperty::kNoCachedAccessor, static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::kOnPrototype, V8DOMConfiguration::kCheckHolder, V8DOMConfiguration::kHasSideEffect, V8DOMConfiguration::kAlwaysCallGetter, V8DOMConfiguration::kAllWorlds }, + { "highEntropyReadonlyAttributeWithMeasureAs", V8TestObject::HighEntropyReadonlyAttributeWithMeasureAsAttributeGetterCallback, nullptr, V8PrivateProperty::kNoCachedAccessor, static_cast<v8::PropertyAttribute>(v8::ReadOnly), V8DOMConfiguration::kOnPrototype, V8DOMConfiguration::kCheckHolder, V8DOMConfiguration::kHasSideEffect, V8DOMConfiguration::kAlwaysCallGetter, V8DOMConfiguration::kAllWorlds }, { "testInterfaceAttribute", V8TestObject::TestInterfaceAttributeAttributeGetterCallback, V8TestObject::TestInterfaceAttributeAttributeSetterCallback, V8PrivateProperty::kNoCachedAccessor, static_cast<v8::PropertyAttribute>(v8::None), V8DOMConfiguration::kOnPrototype, V8DOMConfiguration::kCheckHolder, V8DOMConfiguration::kHasSideEffect, V8DOMConfiguration::kAlwaysCallGetter, V8DOMConfiguration::kAllWorlds }, { "size", V8TestObject::SizeAttributeGetterCallback, nullptr, V8PrivateProperty::kNoCachedAccessor, static_cast<v8::PropertyAttribute>(v8::DontEnum | v8::ReadOnly), V8DOMConfiguration::kOnPrototype, V8DOMConfiguration::kCheckHolder, V8DOMConfiguration::kHasSideEffect, V8DOMConfiguration::kAlwaysCallGetter, V8DOMConfiguration::kAllWorlds }, }; @@ -13558,6 +13758,8 @@ {"DeprecateAsSameValueOverloadedMethod", V8TestObject::DeprecateAsSameValueOverloadedMethodMethodCallback, 0, v8::None, V8DOMConfiguration::kOnPrototype, V8DOMConfiguration::kCheckHolder, V8DOMConfiguration::kDoNotCheckAccess, V8DOMConfiguration::kHasSideEffect, V8DOMConfiguration::kAllWorlds}, {"measureAsOverloadedMethod", V8TestObject::MeasureAsOverloadedMethodMethodCallback, 0, v8::None, V8DOMConfiguration::kOnPrototype, V8DOMConfiguration::kCheckHolder, V8DOMConfiguration::kDoNotCheckAccess, V8DOMConfiguration::kHasSideEffect, V8DOMConfiguration::kAllWorlds}, {"measureAsSameValueOverloadedMethod", V8TestObject::MeasureAsSameValueOverloadedMethodMethodCallback, 0, v8::None, V8DOMConfiguration::kOnPrototype, V8DOMConfiguration::kCheckHolder, V8DOMConfiguration::kDoNotCheckAccess, V8DOMConfiguration::kHasSideEffect, V8DOMConfiguration::kAllWorlds}, + {"highEntropyMethodWithMeasure", V8TestObject::HighEntropyMethodWithMeasureMethodCallback, 0, v8::None, V8DOMConfiguration::kOnPrototype, V8DOMConfiguration::kCheckHolder, V8DOMConfiguration::kDoNotCheckAccess, V8DOMConfiguration::kHasSideEffect, V8DOMConfiguration::kAllWorlds}, + {"highEntropyMethodWithMeasureAs", V8TestObject::HighEntropyMethodWithMeasureAsMethodCallback, 0, v8::None, V8DOMConfiguration::kOnPrototype, V8DOMConfiguration::kCheckHolder, V8DOMConfiguration::kDoNotCheckAccess, V8DOMConfiguration::kHasSideEffect, V8DOMConfiguration::kAllWorlds}, {"ceReactionsNotOverloadedMethod", V8TestObject::CeReactionsNotOverloadedMethodMethodCallback, 1, v8::None, V8DOMConfiguration::kOnPrototype, V8DOMConfiguration::kCheckHolder, V8DOMConfiguration::kDoNotCheckAccess, V8DOMConfiguration::kHasSideEffect, V8DOMConfiguration::kAllWorlds}, {"ceReactionsOverloadedMethod", V8TestObject::CeReactionsOverloadedMethodMethodCallback, 0, v8::None, V8DOMConfiguration::kOnPrototype, V8DOMConfiguration::kCheckHolder, V8DOMConfiguration::kDoNotCheckAccess, V8DOMConfiguration::kHasSideEffect, V8DOMConfiguration::kAllWorlds}, {"deprecateAsMeasureAsSameValueOverloadedMethod", V8TestObject::DeprecateAsMeasureAsSameValueOverloadedMethodMethodCallback, 0, v8::None, V8DOMConfiguration::kOnPrototype, V8DOMConfiguration::kCheckHolder, V8DOMConfiguration::kDoNotCheckAccess, V8DOMConfiguration::kHasSideEffect, V8DOMConfiguration::kAllWorlds}, @@ -13615,6 +13817,12 @@ ALLOW_UNUSED_LOCAL(prototype_template); // Register IDL constants, attributes and operations. + V8DOMConfiguration::InstallConstantWithGetter( + isolate, interface_template, prototype_template, + "highEntropyConstant", V8TestObject::HighEntropyConstantConstantGetterCallback); + V8DOMConfiguration::InstallConstantWithGetter( + isolate, interface_template, prototype_template, + "highEntropyConstant", V8TestObject::HighEntropyConstantConstantGetterCallback); V8DOMConfiguration::InstallAttributes( isolate, world, instance_template, prototype_template, kV8TestObjectAttributes, base::size(kV8TestObjectAttributes));
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_object.h b/third_party/blink/renderer/bindings/tests/results/core/v8_test_object.h index c4c5caf3..7ced251 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_object.h +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_object.h
@@ -83,6 +83,8 @@ static void InstallFeatureName(ScriptState*); // Callback functions + CORE_EXPORT static void HighEntropyConstantConstantGetterCallback(v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value>&); + CORE_EXPORT static void HighEntropyConstantConstantGetterCallback(v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value>&); CORE_EXPORT static void StringifierAttributeAttributeGetterCallback(const v8::FunctionCallbackInfo<v8::Value>&); CORE_EXPORT static void StringifierAttributeAttributeSetterCallback(const v8::FunctionCallbackInfo<v8::Value>&); @@ -369,6 +371,12 @@ CORE_EXPORT static void UnscopableOriginTrialEnabledLongAttributeAttributeSetterCallback(const v8::FunctionCallbackInfo<v8::Value>&); CORE_EXPORT static void UnscopableRuntimeEnabledLongAttributeAttributeGetterCallback(const v8::FunctionCallbackInfo<v8::Value>&); CORE_EXPORT static void UnscopableRuntimeEnabledLongAttributeAttributeSetterCallback(const v8::FunctionCallbackInfo<v8::Value>&); + CORE_EXPORT static void HighEntropyAttributeWithMeasureAttributeGetterCallback(const v8::FunctionCallbackInfo<v8::Value>&); + CORE_EXPORT static void HighEntropyAttributeWithMeasureAttributeSetterCallback(const v8::FunctionCallbackInfo<v8::Value>&); + CORE_EXPORT static void HighEntropyReadonlyAttributeWithMeasureAttributeGetterCallback(const v8::FunctionCallbackInfo<v8::Value>&); + CORE_EXPORT static void HighEntropyAttributeWithMeasureAsAttributeGetterCallback(const v8::FunctionCallbackInfo<v8::Value>&); + CORE_EXPORT static void HighEntropyAttributeWithMeasureAsAttributeSetterCallback(const v8::FunctionCallbackInfo<v8::Value>&); + CORE_EXPORT static void HighEntropyReadonlyAttributeWithMeasureAsAttributeGetterCallback(const v8::FunctionCallbackInfo<v8::Value>&); CORE_EXPORT static void TestInterfaceAttributeAttributeGetterCallback(const v8::FunctionCallbackInfo<v8::Value>&); CORE_EXPORT static void TestInterfaceAttributeAttributeSetterCallback(const v8::FunctionCallbackInfo<v8::Value>&); CORE_EXPORT static void SizeAttributeGetterCallback(const v8::FunctionCallbackInfo<v8::Value>&); @@ -563,6 +571,8 @@ CORE_EXPORT static void DeprecateAsSameValueOverloadedMethodMethodCallback(const v8::FunctionCallbackInfo<v8::Value>&); CORE_EXPORT static void MeasureAsOverloadedMethodMethodCallback(const v8::FunctionCallbackInfo<v8::Value>&); CORE_EXPORT static void MeasureAsSameValueOverloadedMethodMethodCallback(const v8::FunctionCallbackInfo<v8::Value>&); + CORE_EXPORT static void HighEntropyMethodWithMeasureMethodCallback(const v8::FunctionCallbackInfo<v8::Value>&); + CORE_EXPORT static void HighEntropyMethodWithMeasureAsMethodCallback(const v8::FunctionCallbackInfo<v8::Value>&); CORE_EXPORT static void CeReactionsNotOverloadedMethodMethodCallback(const v8::FunctionCallbackInfo<v8::Value>&); CORE_EXPORT static void CeReactionsOverloadedMethodMethodCallback(const v8::FunctionCallbackInfo<v8::Value>&); CORE_EXPORT static void DeprecateAsMeasureAsSameValueOverloadedMethodMethodCallback(const v8::FunctionCallbackInfo<v8::Value>&);
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn index 406486b..e722610 100644 --- a/third_party/blink/renderer/core/BUILD.gn +++ b/third_party/blink/renderer/core/BUILD.gn
@@ -1751,6 +1751,7 @@ "css/cssom/css_style_image_value_test.cc", "css/cssom/css_unit_value_test.cc", "css/cssom/css_unparsed_value_test.cc", + "css/cssom/paint_worklet_style_property_map_test.cc", "css/cssom/prepopulated_computed_style_property_map_test.cc", "css/drag_update_test.cc", "css/font_face_cache_test.cc", @@ -2109,6 +2110,7 @@ "page/focus_controller_test.cc", "page/page_popup_client_test.cc", "page/print_context_test.cc", + "page/scrolling/main_thread_scrolling_reasons_test.cc", "page/scrolling/root_scroller_test.cc", "page/scrolling/scroll_into_view_test.cc", "page/scrolling/scroll_metrics_test.cc",
diff --git a/third_party/blink/renderer/core/DEPS b/third_party/blink/renderer/core/DEPS index 3fa0d9eb7..c621de51 100644 --- a/third_party/blink/renderer/core/DEPS +++ b/third_party/blink/renderer/core/DEPS
@@ -28,6 +28,7 @@ "+cc/paint/display_item_list.h", "+cc/paint/paint_canvas.h", "+cc/paint/paint_flags.h", + "+cc/paint/paint_worklet_input.h", "+gpu/config/gpu_feature_info.h", "-inspector/v8", "+inspector/v8/public",
diff --git a/third_party/blink/renderer/core/css/BUILD.gn b/third_party/blink/renderer/core/css/BUILD.gn index 6137551..8b5a6ca7 100644 --- a/third_party/blink/renderer/core/css/BUILD.gn +++ b/third_party/blink/renderer/core/css/BUILD.gn
@@ -259,6 +259,10 @@ "cssom/element_computed_style_map.h", "cssom/inline_style_property_map.cc", "cssom/inline_style_property_map.h", + "cssom/paint_worklet_input.cc", + "cssom/paint_worklet_input.h", + "cssom/paint_worklet_style_property_map.cc", + "cssom/paint_worklet_style_property_map.h", "cssom/prepopulated_computed_style_property_map.cc", "cssom/prepopulated_computed_style_property_map.h", "cssom/style_property_map.cc",
diff --git a/third_party/blink/renderer/core/css/cssom/css_unsupported_style_value.h b/third_party/blink/renderer/core/css/cssom/css_unsupported_style_value.h index b206419..3eb73ef 100644 --- a/third_party/blink/renderer/core/css/cssom/css_unsupported_style_value.h +++ b/third_party/blink/renderer/core/css/cssom/css_unsupported_style_value.h
@@ -28,6 +28,9 @@ static CSSUnsupportedStyleValue* Create(const CSSValue& value) { return MakeGarbageCollected<CSSUnsupportedStyleValue>(value.CssText()); } + static CSSUnsupportedStyleValue* Create(const String& css_text) { + return MakeGarbageCollected<CSSUnsupportedStyleValue>(css_text); + } static CSSUnsupportedStyleValue* Create(const CSSPropertyName& name, const String& css_text) { return MakeGarbageCollected<CSSUnsupportedStyleValue>(name, css_text);
diff --git a/third_party/blink/renderer/core/css/cssom/paint_worklet_input.cc b/third_party/blink/renderer/core/css/cssom/paint_worklet_input.cc new file mode 100644 index 0000000..6b3386f --- /dev/null +++ b/third_party/blink/renderer/core/css/cssom/paint_worklet_input.cc
@@ -0,0 +1,25 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/css/cssom/paint_worklet_input.h" + +namespace blink { + +PaintWorkletInput::PaintWorkletInput( + const std::string& name, + const FloatSize& container_size, + float effective_zoom, + const Document& document, + const ComputedStyle& style, + Node* styled_node, + const Vector<CSSPropertyID>& native_properties, + const Vector<AtomicString>& custom_properties) + : name_(name), + container_size_(container_size), + effective_zoom_(effective_zoom) { + style_map_ = MakeGarbageCollected<PaintWorkletStylePropertyMap>( + document, style, styled_node, native_properties, custom_properties); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/css/cssom/paint_worklet_input.h b/third_party/blink/renderer/core/css/cssom/paint_worklet_input.h new file mode 100644 index 0000000..1eb8452 --- /dev/null +++ b/third_party/blink/renderer/core/css/cssom/paint_worklet_input.h
@@ -0,0 +1,51 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_PAINT_WORKLET_INPUT_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_PAINT_WORKLET_INPUT_H_ + +#include <memory> +#include "cc/paint/paint_worklet_input.h" +#include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.h" +#include "third_party/blink/renderer/platform/geometry/float_size.h" +#include "third_party/blink/renderer/platform/heap/persistent.h" + +namespace blink { + +class CORE_EXPORT PaintWorkletInput : public cc::PaintWorkletInput { + public: + PaintWorkletInput(const std::string& name, + const FloatSize& container_size, + float effective_zoom, + const Document&, + const ComputedStyle&, + Node* styled_node, + const Vector<CSSPropertyID>& native_properties, + const Vector<AtomicString>& custom_properties); + + ~PaintWorkletInput() override = default; + + // PaintWorkletInput implementation + gfx::SizeF GetSize() const override { + return gfx::SizeF(container_size_.Width(), container_size_.Height()); + } + + const std::string& Name() const { return name_; } + const FloatSize& ContainerSize() const { return container_size_; } + float EffectiveZoom() const { return effective_zoom_; } + PaintWorkletStylePropertyMap* StyleMap() { return style_map_.Get(); } + + private: + // TODO(xidachen): these members should be const as they are immutable once + // created. + std::string name_; + FloatSize container_size_; + float effective_zoom_; + CrossThreadPersistent<PaintWorkletStylePropertyMap> style_map_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_PAINT_WORKLET_INPUT_H_
diff --git a/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.cc b/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.cc new file mode 100644 index 0000000..72fd28f --- /dev/null +++ b/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.cc
@@ -0,0 +1,178 @@ +// Copyright 2018 the Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.h" + +#include "third_party/blink/renderer/core/css/css_custom_property_declaration.h" +#include "third_party/blink/renderer/core/css/css_variable_data.h" +#include "third_party/blink/renderer/core/css/cssom/computed_style_property_map.h" +#include "third_party/blink/renderer/core/css/cssom/css_unparsed_value.h" +#include "third_party/blink/renderer/core/css/cssom/css_unsupported_style_value.h" +#include "third_party/blink/renderer/core/css/properties/css_property_ref.h" +#include "third_party/blink/renderer/core/dom/document.h" +#include "third_party/blink/renderer/core/style/computed_style.h" + +namespace blink { + +namespace { + +class PaintWorkletStylePropertyMapIterationSource final + : public PairIterable<String, CSSStyleValueVector>::IterationSource { + public: + explicit PaintWorkletStylePropertyMapIterationSource( + HeapVector<PaintWorkletStylePropertyMap::StylePropertyMapEntry> values) + : index_(0), values_(values) {} + + bool Next(ScriptState*, + String& key, + CSSStyleValueVector& value, + ExceptionState&) override { + if (index_ >= values_.size()) + return false; + + const PaintWorkletStylePropertyMap::StylePropertyMapEntry& pair = + values_.at(index_++); + key = pair.first; + value = pair.second; + return true; + } + + void Trace(blink::Visitor* visitor) override { + visitor->Trace(values_); + PairIterable<String, CSSStyleValueVector>::IterationSource::Trace(visitor); + } + + private: + wtf_size_t index_; + const HeapVector<PaintWorkletStylePropertyMap::StylePropertyMapEntry> values_; +}; + +} // namespace + +PaintWorkletStylePropertyMap::PaintWorkletStylePropertyMap( + const Document& document, + const ComputedStyle& style, + Node* styled_node, + const Vector<CSSPropertyID>& native_properties, + const Vector<AtomicString>& custom_properties) + : StylePropertyMapReadOnly() { + DCHECK(IsMainThread()); + native_values_.ReserveCapacityForSize(native_properties.size()); + custom_values_.ReserveCapacityForSize(custom_properties.size()); + BuildNativeValues(style, styled_node, native_properties); + BuildCustomValues(document, style, styled_node, custom_properties); +} + +void PaintWorkletStylePropertyMap::BuildNativeValues( + const ComputedStyle& style, + Node* styled_node, + const Vector<CSSPropertyID>& native_properties) { + DCHECK(IsMainThread()); + for (const auto& property_id : native_properties) { + // Silently drop shorthand properties. + DCHECK_NE(property_id, CSSPropertyInvalid); + DCHECK_NE(property_id, CSSPropertyVariable); + if (CSSProperty::Get(property_id).IsShorthand()) + continue; + const CSSValue* css_value = + CSSProperty::Get(property_id) + .CSSValueFromComputedStyle(style, /* layout_object */ nullptr, + styled_node, + /* allow_visited_style */ false); + // Ensure that the String can be safely passed cross threads. + String value = css_value->CssText(); + if (!value.IsSafeToSendToAnotherThread()) + value = value.IsolatedCopy(); + native_values_.Set(property_id, value); + } +} + +void PaintWorkletStylePropertyMap::BuildCustomValues( + const Document& document, + const ComputedStyle& style, + Node* styled_node, + const Vector<AtomicString>& custom_properties) { + DCHECK(IsMainThread()); + for (const auto& property_name : custom_properties) { + CSSPropertyRef ref(property_name, document); + const CSSValue* css_value = ref.GetProperty().CSSValueFromComputedStyle( + style, /* layout_object */ nullptr, styled_node, + /* allow_visited_style */ false); + if (!css_value) + css_value = CSSUnparsedValue::Create()->ToCSSValue(); + // Ensure that the String can be safely passed cross threads. + String key = property_name.GetString(); + if (!key.IsSafeToSendToAnotherThread()) + key = key.IsolatedCopy(); + String value = css_value->CssText(); + if (!value.IsSafeToSendToAnotherThread()) + value = value.IsolatedCopy(); + custom_values_.Set(key, value); + } +} + +CSSStyleValue* PaintWorkletStylePropertyMap::get( + const ExecutionContext* execution_context, + const String& property_name, + ExceptionState& exception_state) { + CSSStyleValueVector all_values = + getAll(execution_context, property_name, exception_state); + return all_values.IsEmpty() ? nullptr : all_values[0]; +} + +CSSStyleValueVector PaintWorkletStylePropertyMap::getAll( + const ExecutionContext* execution_context, + const String& property_name, + ExceptionState& exception_state) { + CSSPropertyID property_id = cssPropertyID(property_name); + if (property_id == CSSPropertyInvalid) { + exception_state.ThrowTypeError("Invalid propertyName: " + property_name); + return CSSStyleValueVector(); + } + + DCHECK(isValidCSSPropertyID(property_id)); + + CSSStyleValueVector values; + // Custom property + if (property_id == CSSPropertyVariable) { + auto value = custom_values_.find(property_name); + if (value == custom_values_.end()) + return CSSStyleValueVector(); + values.push_back(CSSUnsupportedStyleValue::Create(value->value)); + } else { + auto value = native_values_.find(property_id); + if (value == native_values_.end()) + return CSSStyleValueVector(); + values.push_back(CSSUnsupportedStyleValue::Create(value->value)); + } + return values; +} + +bool PaintWorkletStylePropertyMap::has( + const ExecutionContext* execution_context, + const String& property_name, + ExceptionState& exception_state) { + return !getAll(execution_context, property_name, exception_state).IsEmpty(); +} + +unsigned PaintWorkletStylePropertyMap::size() { + return native_values_.size() + custom_values_.size(); +} + +PaintWorkletStylePropertyMap::IterationSource* +PaintWorkletStylePropertyMap::StartIteration(ScriptState* script_state, + ExceptionState& exception_state) { + // TODO(xidachen): implement this function. Note that the output should be + // sorted. + NOTREACHED(); + HeapVector<PaintWorkletStylePropertyMap::StylePropertyMapEntry> result; + return MakeGarbageCollected<PaintWorkletStylePropertyMapIterationSource>( + result); +} + +void PaintWorkletStylePropertyMap::Trace(blink::Visitor* visitor) { + StylePropertyMapReadOnly::Trace(visitor); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.h b/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.h new file mode 100644 index 0000000..e5b8463 --- /dev/null +++ b/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.h
@@ -0,0 +1,78 @@ +// Copyright 2018 the Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_PAINT_WORKLET_STYLE_PROPERTY_MAP_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_PAINT_WORKLET_STYLE_PROPERTY_MAP_H_ + +#include "base/macros.h" +#include "third_party/blink/renderer/core/css/cssom/style_property_map_read_only.h" +#include "third_party/blink/renderer/platform/wtf/vector.h" + +namespace blink { + +// This class is designed for CSS Paint such that it can be safely passed cross +// threads. +// +// Here is a typical usage. +// At CSSPaintValue::GetImage which is on the main thread, build an instance +// of Blink::PaintWorkletInput which calls the constructor of this class. The +// ownership of this style map belongs to the Blink::PaintWorkletInput, which +// will eventually be passed to the worklet thread and used in the JS callback. +class CORE_EXPORT PaintWorkletStylePropertyMap + : public StylePropertyMapReadOnly { + public: + using StylePropertyMapEntry = std::pair<String, CSSStyleValueVector>; + // This constructor should be called on main-thread only. + PaintWorkletStylePropertyMap(const Document&, + const ComputedStyle&, + Node* styled_node, + const Vector<CSSPropertyID>& native_properties, + const Vector<AtomicString>& custom_properties); + + CSSStyleValue* get(const ExecutionContext*, + const String& property_name, + ExceptionState&) override; + + CSSStyleValueVector getAll(const ExecutionContext*, + const String& property_name, + ExceptionState&) override; + + bool has(const ExecutionContext*, + const String& property_name, + ExceptionState&) override; + + unsigned int size() override; + + void Trace(blink::Visitor*) override; + + const HashMap<CSSPropertyID, String>& NativeValuesForTest() { + return native_values_; + } + const HashMap<String, String>& CustomValuesForTest() { + return custom_values_; + } + + private: + IterationSource* StartIteration(ScriptState*, ExceptionState&) override; + + void BuildNativeValues(const ComputedStyle&, + Node* styled_node, + const Vector<CSSPropertyID>& native_properties); + void BuildCustomValues(const Document&, + const ComputedStyle&, + Node* styled_node, + const Vector<AtomicString>& custom_properties); + + // TODO(xidachen): we could merge the following two hash maps, because the get + // and getAll both take a String as input, and we convert it to CSSPropertyID + // to look up. + HashMap<CSSPropertyID, String> native_values_; + HashMap<String, String> custom_values_; + + DISALLOW_COPY_AND_ASSIGN(PaintWorkletStylePropertyMap); +}; + +} // namespace blink + +#endif
diff --git a/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map_test.cc b/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map_test.cc new file mode 100644 index 0000000..92d28d1 --- /dev/null +++ b/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map_test.cc
@@ -0,0 +1,184 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.h" + +#include <memory> +#include "base/single_thread_task_runner.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/renderer/core/css/css_computed_style_declaration.h" +#include "third_party/blink/renderer/core/css/cssom/paint_worklet_input.h" +#include "third_party/blink/renderer/core/dom/element.h" +#include "third_party/blink/renderer/core/dom/node_computed_style.h" +#include "third_party/blink/renderer/core/testing/page_test_base.h" +#include "third_party/blink/renderer/platform/cross_thread_functional.h" +#include "third_party/blink/renderer/platform/heap/handle.h" +#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" +#include "third_party/blink/renderer/platform/waitable_event.h" +#include "third_party/blink/renderer/platform/web_thread_supporting_gc.h" + +namespace blink { + +class PaintWorkletStylePropertyMapTest : public PageTestBase { + public: + PaintWorkletStylePropertyMapTest() = default; + + void SetUp() override { PageTestBase::SetUp(IntSize()); } + + Node* PageNode() { return GetDocument().documentElement(); } + + static void CheckCustomProperties( + PaintWorkletStylePropertyMap* map, + DummyExceptionStateForTesting& exception_state) { + const CSSStyleValue* foo = map->get(nullptr, "--foo", exception_state); + ASSERT_NE(nullptr, foo); + ASSERT_EQ(CSSStyleValue::kUnknownType, foo->GetType()); + EXPECT_FALSE(exception_state.HadException()); + + EXPECT_EQ(true, map->has(nullptr, "--foo", exception_state)); + EXPECT_FALSE(exception_state.HadException()); + + CSSStyleValueVector fooAll = map->getAll(nullptr, "--foo", exception_state); + EXPECT_EQ(1U, fooAll.size()); + ASSERT_NE(nullptr, fooAll[0]); + ASSERT_EQ(CSSStyleValue::kUnknownType, fooAll[0]->GetType()); + EXPECT_FALSE(exception_state.HadException()); + + EXPECT_EQ(nullptr, map->get(nullptr, "--quix", exception_state)); + EXPECT_FALSE(exception_state.HadException()); + + EXPECT_EQ(false, map->has(nullptr, "--quix", exception_state)); + EXPECT_FALSE(exception_state.HadException()); + + EXPECT_EQ(CSSStyleValueVector(), + map->getAll(nullptr, "--quix", exception_state)); + EXPECT_FALSE(exception_state.HadException()); + } + + static void CheckNativeProperties( + PaintWorkletStylePropertyMap* map, + DummyExceptionStateForTesting& exception_state) { + map->get(nullptr, "color", exception_state); + EXPECT_FALSE(exception_state.HadException()); + + map->has(nullptr, "color", exception_state); + EXPECT_FALSE(exception_state.HadException()); + + map->getAll(nullptr, "color", exception_state); + EXPECT_FALSE(exception_state.HadException()); + + map->get(nullptr, "align-contents", exception_state); + EXPECT_TRUE(exception_state.HadException()); + exception_state.ClearException(); + + map->has(nullptr, "align-contents", exception_state); + EXPECT_TRUE(exception_state.HadException()); + exception_state.ClearException(); + + map->getAll(nullptr, "align-contents", exception_state); + EXPECT_TRUE(exception_state.HadException()); + exception_state.ClearException(); + } + + static void CheckStyleMap(WaitableEvent* waitable_event, + scoped_refptr<PaintWorkletInput> input) { + DCHECK(!IsMainThread()); + + PaintWorkletStylePropertyMap* map = input->StyleMap(); + DCHECK(map); + + HashMap<CSSPropertyID, String> native_values = map->NativeValuesForTest(); + EXPECT_EQ(native_values.size(), 2u); + EXPECT_EQ(native_values.at(CSSPropertyColor), "rgb(0, 255, 0)"); + EXPECT_EQ(native_values.at(CSSPropertyAlignItems), "normal"); + + HashMap<String, String> custom_values = map->CustomValuesForTest(); + EXPECT_EQ(custom_values.size(), 2u); + EXPECT_EQ(custom_values.at("--foo"), "PaintWorklet"); + EXPECT_EQ(custom_values.at("--bar"), ""); + + waitable_event->Signal(); + } +}; + +TEST_F(PaintWorkletStylePropertyMapTest, NativePropertyAccessors) { + Vector<CSSPropertyID> native_properties( + {CSSPropertyColor, CSSPropertyAlignItems, CSSPropertyBackground}); + Vector<AtomicString> empty_custom_properties; + GetDocument().documentElement()->style()->setProperty( + &GetDocument(), "color", "rgb(0, 255, 0)", "", ASSERT_NO_EXCEPTION); + + UpdateAllLifecyclePhasesForTest(); + Node* node = PageNode(); + + PaintWorkletStylePropertyMap* map = + MakeGarbageCollected<PaintWorkletStylePropertyMap>( + GetDocument(), node->ComputedStyleRef(), node, native_properties, + empty_custom_properties); + + HashMap<CSSPropertyID, String> native_values = map->NativeValuesForTest(); + EXPECT_EQ(native_values.size(), 2u); + EXPECT_EQ(native_values.at(CSSPropertyColor), "rgb(0, 255, 0)"); + EXPECT_EQ(native_values.at(CSSPropertyAlignItems), "normal"); + + DummyExceptionStateForTesting exception_state; + CheckNativeProperties(map, exception_state); +} + +TEST_F(PaintWorkletStylePropertyMapTest, CustomPropertyAccessors) { + Vector<CSSPropertyID> empty_native_properties; + Vector<AtomicString> custom_properties({"--foo", "--bar"}); + GetDocument().documentElement()->style()->setProperty( + &GetDocument(), "--foo", "PaintWorklet", "", ASSERT_NO_EXCEPTION); + + UpdateAllLifecyclePhasesForTest(); + Node* node = PageNode(); + + PaintWorkletStylePropertyMap* map = + MakeGarbageCollected<PaintWorkletStylePropertyMap>( + GetDocument(), node->ComputedStyleRef(), node, + empty_native_properties, custom_properties); + + HashMap<String, String> custom_values = map->CustomValuesForTest(); + EXPECT_EQ(custom_values.size(), 2u); + EXPECT_EQ(custom_values.at("--foo"), "PaintWorklet"); + EXPECT_EQ(custom_values.at("--bar"), ""); + + DummyExceptionStateForTesting exception_state; + CheckCustomProperties(map, exception_state); +} + +// This test ensures that Blink::PaintWorkletInput can be safely passed cross +// threads and no information is lost. +TEST_F(PaintWorkletStylePropertyMapTest, PassValuesCrossThreads) { + Vector<CSSPropertyID> native_properties( + {CSSPropertyColor, CSSPropertyAlignItems}); + GetDocument().documentElement()->style()->setProperty( + &GetDocument(), "color", "rgb(0, 255, 0)", "", ASSERT_NO_EXCEPTION); + Vector<AtomicString> custom_properties({"--foo", "--bar"}); + GetDocument().documentElement()->style()->setProperty( + &GetDocument(), "--foo", "PaintWorklet", "", ASSERT_NO_EXCEPTION); + + UpdateAllLifecyclePhasesForTest(); + Node* node = PageNode(); + + scoped_refptr<PaintWorkletInput> input = + base::MakeRefCounted<PaintWorkletInput>( + "test", FloatSize(100, 100), 1.0f, GetDocument(), + node->ComputedStyleRef(), node, native_properties, custom_properties); + DCHECK(input); + + // TODO(xidachen): this isn't enough, find a right thread such that we can do + // CheckNative/CustomProperties on that thread. + std::unique_ptr<WebThreadSupportingGC> thread = WebThreadSupportingGC::Create( + ThreadCreationParams(WebThreadType::kTestThread)); + WaitableEvent waitable_event; + thread->PostTask( + FROM_HERE, CrossThreadBind( + &PaintWorkletStylePropertyMapTest::CheckStyleMap, + CrossThreadUnretained(&waitable_event), std::move(input))); + waitable_event.Wait(); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/events/navigator_events.idl b/third_party/blink/renderer/core/events/navigator_events.idl index 0bc89e28..da8d0e7a 100644 --- a/third_party/blink/renderer/core/events/navigator_events.idl +++ b/third_party/blink/renderer/core/events/navigator_events.idl
@@ -33,5 +33,5 @@ [ ImplementedAs=NavigatorEvents ] partial interface Navigator { - readonly attribute long maxTouchPoints; + [HighEntropy, MeasureAs=NavigatorMaxTouchPoints] readonly attribute long maxTouchPoints; };
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.h b/third_party/blink/renderer/core/exported/web_view_impl.h index f2863c7..91bbab2c 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.h +++ b/third_party/blink/renderer/core/exported/web_view_impl.h
@@ -134,7 +134,6 @@ void SetInitialFocus(bool reverse) override; void ClearFocusedElement() override; void SmoothScroll(int target_x, int target_y, long duration_ms) override; - void ZoomToFindInPageRect(const WebRect&); void AdvanceFocus(bool reverse) override; void AdvanceFocusAcrossFrames(WebFocusType, WebRemoteFrame* from, @@ -161,6 +160,7 @@ void SetDisplayMode(WebDisplayMode) override; void AnimateDoubleTapZoom(const gfx::Point&, const WebRect& block_bounds) override; + void ZoomToFindInPageRect(const WebRect&) override; void SetDeviceScaleFactor(float) override; void SetZoomFactorForDeviceScaleFactor(float) override;
diff --git a/third_party/blink/renderer/core/frame/BUILD.gn b/third_party/blink/renderer/core/frame/BUILD.gn index 098496b1..50cfc93 100644 --- a/third_party/blink/renderer/core/frame/BUILD.gn +++ b/third_party/blink/renderer/core/frame/BUILD.gn
@@ -27,6 +27,8 @@ "csp/source_list_directive.h", "csp/string_list_directive.cc", "csp/string_list_directive.h", + "dactyloscoper.cc", + "dactyloscoper.h", "deprecated_schedule_style_recalc_during_layout.cc", "deprecated_schedule_style_recalc_during_layout.h", "deprecation.cc",
diff --git a/third_party/blink/renderer/core/frame/dactyloscoper.cc b/third_party/blink/renderer/core/frame/dactyloscoper.cc new file mode 100644 index 0000000..c384ff49 --- /dev/null +++ b/third_party/blink/renderer/core/frame/dactyloscoper.cc
@@ -0,0 +1,30 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/frame/dactyloscoper.h" + +#include "third_party/blink/renderer/core/dom/document.h" +#include "third_party/blink/renderer/core/loader/document_loader.h" + +namespace blink { + +Dactyloscoper::Dactyloscoper() = default; + +void Dactyloscoper::Record(WebFeature feature) { + // TODO(mkwst): This is a stub. We'll pull in more interesting functionality + // here over time. +} + +// static +void Dactyloscoper::Record(ExecutionContext* context, WebFeature feature) { + // TODO: Workers. + if (!context) + return; + if (auto* document = DynamicTo<Document>(context)) { + if (DocumentLoader* loader = document->Loader()) + loader->GetDactyloscoper().Record(feature); + } +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/frame/dactyloscoper.h b/third_party/blink/renderer/core/frame/dactyloscoper.h new file mode 100644 index 0000000..d0796ca --- /dev/null +++ b/third_party/blink/renderer/core/frame/dactyloscoper.h
@@ -0,0 +1,33 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_DACTYLOSCOPER_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_DACTYLOSCOPER_H_ + +#include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/core/frame/web_feature.h" +#include "third_party/blink/renderer/platform/wtf/allocator.h" +#include "third_party/blink/renderer/platform/wtf/forward.h" + +namespace blink { + +class ExecutionContext; + +class CORE_EXPORT Dactyloscoper { + DISALLOW_NEW(); + + public: + Dactyloscoper(); + + void Record(WebFeature); + + static void Record(ExecutionContext*, WebFeature); + + private: + DISALLOW_COPY_AND_ASSIGN(Dactyloscoper); +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_DACTYLOSCOPER_H_
diff --git a/third_party/blink/renderer/core/frame/dom_timer.cc b/third_party/blink/renderer/core/frame/dom_timer.cc index 92c91b4..7373a276 100644 --- a/third_party/blink/renderer/core/frame/dom_timer.cc +++ b/third_party/blink/renderer/core/frame/dom_timer.cc
@@ -80,7 +80,8 @@ TimeDelta interval, bool single_shot, int timeout_id) - : PausableTimer(context, TaskType::kJavascriptTimer), + : ContextLifecycleObserver(context), + TimerBase(context->GetTaskRunner(TaskType::kJavascriptTimer)), timeout_id_(timeout_id), nesting_level_(context->Timers()->TimerNestingLevel() + 1), action_(action) { @@ -101,7 +102,6 @@ else StartRepeating(interval_milliseconds, FROM_HERE); - PauseIfNeeded(); TRACE_EVENT_INSTANT1("devtools.timeline", "TimerInstall", TRACE_EVENT_SCOPE_THREAD, "data", inspector_timer_install_event::Data( @@ -128,7 +128,7 @@ if (action_) action_->Dispose(); action_ = nullptr; - PausableTimer::Stop(); + TimerBase::Stop(); } void DOMTimer::ContextDestroyed(ExecutionContext*) { @@ -192,7 +192,7 @@ void DOMTimer::Trace(blink::Visitor* visitor) { visitor->Trace(action_); - PausableTimer::Trace(visitor); + ContextLifecycleObserver::Trace(visitor); } } // namespace blink
diff --git a/third_party/blink/renderer/core/frame/dom_timer.h b/third_party/blink/renderer/core/frame/dom_timer.h index fee0571..5636c07d 100644 --- a/third_party/blink/renderer/core/frame/dom_timer.h +++ b/third_party/blink/renderer/core/frame/dom_timer.h
@@ -30,16 +30,18 @@ #include "base/memory/scoped_refptr.h" #include "third_party/blink/renderer/bindings/core/v8/scheduled_action.h" #include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h" #include "third_party/blink/renderer/core/dom/user_gesture_indicator.h" -#include "third_party/blink/renderer/core/frame/pausable_timer.h" #include "third_party/blink/renderer/platform/heap/handle.h" +#include "third_party/blink/renderer/platform/timer.h" namespace blink { class ExecutionContext; class CORE_EXPORT DOMTimer final : public GarbageCollectedFinalized<DOMTimer>, - public PausableTimer { + public ContextLifecycleObserver, + public TimerBase { USING_GARBAGE_COLLECTED_MIXIN(DOMTimer); public: @@ -58,7 +60,7 @@ int timeout_id); ~DOMTimer() override; - // PausableObject + // ContextLifecycleObserver void ContextDestroyed(ExecutionContext*) override; // Eager finalization is needed to promptly stop this Timer object.
diff --git a/third_party/blink/renderer/core/frame/frame.h b/third_party/blink/renderer/core/frame/frame.h index 45802a6..d6b924b7f 100644 --- a/third_party/blink/renderer/core/frame/frame.h +++ b/third_party/blink/renderer/core/frame/frame.h
@@ -41,7 +41,6 @@ #include "third_party/blink/renderer/core/frame/frame_view.h" #include "third_party/blink/renderer/core/frame/navigation_rate_limiter.h" #include "third_party/blink/renderer/core/loader/frame_loader_types.h" -#include "third_party/blink/renderer/core/loader/navigation_policy.h" #include "third_party/blink/renderer/core/page/frame_tree.h" #include "third_party/blink/renderer/platform/graphics/touch_action.h" #include "third_party/blink/renderer/platform/heap/handle.h" @@ -101,9 +100,7 @@ WebFrameLoadType, UserGestureStatus) = 0; // Synchronously begins a navigation. - virtual void Navigate(const FrameLoadRequest&, - WebFrameLoadType, - NavigationPolicy = kNavigationPolicyCurrentTab) = 0; + virtual void Navigate(const FrameLoadRequest&, WebFrameLoadType) = 0; void Detach(FrameDetachType); void DisconnectOwnerElement();
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc index 13f425a..99178cbc5 100644 --- a/third_party/blink/renderer/core/frame/local_frame.cc +++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -340,11 +340,10 @@ } void LocalFrame::Navigate(const FrameLoadRequest& request, - WebFrameLoadType frame_load_type, - NavigationPolicy policy) { + WebFrameLoadType frame_load_type) { if (!navigation_rate_limiter().CanProceed()) return; - loader_.StartNavigation(request, frame_load_type, policy); + loader_.StartNavigation(request, frame_load_type); } void LocalFrame::DetachImpl(FrameDetachType type) {
diff --git a/third_party/blink/renderer/core/frame/local_frame.h b/third_party/blink/renderer/core/frame/local_frame.h index 3ba83df9..cdfe168 100644 --- a/third_party/blink/renderer/core/frame/local_frame.h +++ b/third_party/blink/renderer/core/frame/local_frame.h
@@ -132,9 +132,7 @@ const KURL&, WebFrameLoadType, UserGestureStatus) override; - void Navigate(const FrameLoadRequest&, - WebFrameLoadType, - NavigationPolicy = kNavigationPolicyCurrentTab) override; + void Navigate(const FrameLoadRequest&, WebFrameLoadType) override; bool ShouldClose() override; SecurityContext* GetSecurityContext() const override; void PrintNavigationErrorMessage(const Frame&, const char* reason);
diff --git a/third_party/blink/renderer/core/frame/navigator.idl b/third_party/blink/renderer/core/frame/navigator.idl index 7126b21..4738819 100644 --- a/third_party/blink/renderer/core/frame/navigator.idl +++ b/third_party/blink/renderer/core/frame/navigator.idl
@@ -23,13 +23,13 @@ // objects implementing this interface also implement the interfaces given below // TODO(foolip): vendorSub should be on NavigatorID. - [MeasureAs=NavigatorVendorSub] readonly attribute DOMString vendorSub; + [HighEntropy, MeasureAs=NavigatorVendorSub] readonly attribute DOMString vendorSub; // TODO(foolip): productSub and vendor are not yet in the spec: // https://www.w3.org/Bugs/Public/show_bug.cgi?id=27954 - [MeasureAs=NavigatorProductSub] readonly attribute DOMString productSub; + [HighEntropy, MeasureAs=NavigatorProductSub] readonly attribute DOMString productSub; // https://www.w3.org/Bugs/Public/show_bug.cgi?id=27786 - [MeasureAs=NavigatorVendor] readonly attribute DOMString vendor; + [HighEntropy, MeasureAs=NavigatorVendor] readonly attribute DOMString vendor; }; Navigator implements NavigatorConcurrentHardware;
diff --git a/third_party/blink/renderer/core/frame/navigator_concurrent_hardware.idl b/third_party/blink/renderer/core/frame/navigator_concurrent_hardware.idl index b6f63bb..af79103 100644 --- a/third_party/blink/renderer/core/frame/navigator_concurrent_hardware.idl +++ b/third_party/blink/renderer/core/frame/navigator_concurrent_hardware.idl
@@ -8,5 +8,5 @@ NoInterfaceObject, Exposed=(Window,Worker) ] interface NavigatorConcurrentHardware { - readonly attribute unsigned long long hardwareConcurrency; + [HighEntropy, MeasureAs=NavigatorHardwareConcurrency] readonly attribute unsigned long long hardwareConcurrency; };
diff --git a/third_party/blink/renderer/core/frame/navigator_device_memory.idl b/third_party/blink/renderer/core/frame/navigator_device_memory.idl index a0c717c..03e558c8 100644 --- a/third_party/blink/renderer/core/frame/navigator_device_memory.idl +++ b/third_party/blink/renderer/core/frame/navigator_device_memory.idl
@@ -8,6 +8,6 @@ NoInterfaceObject, Exposed=(Window,Worker) ] interface NavigatorDeviceMemory { - [MeasureAs=NavigatorDeviceMemory,RuntimeEnabled=NavigatorDeviceMemory,SecureContext] + [HighEntropy,MeasureAs=NavigatorDeviceMemory,RuntimeEnabled=NavigatorDeviceMemory,SecureContext] readonly attribute float deviceMemory; };
diff --git a/third_party/blink/renderer/core/frame/navigator_id.idl b/third_party/blink/renderer/core/frame/navigator_id.idl index 3f8bf7b..9e60756 100644 --- a/third_party/blink/renderer/core/frame/navigator_id.idl +++ b/third_party/blink/renderer/core/frame/navigator_id.idl
@@ -36,10 +36,10 @@ ] interface NavigatorID { readonly attribute DOMString appCodeName; // constant "Mozilla" readonly attribute DOMString appName; // constant "Netscape" - readonly attribute DOMString appVersion; - readonly attribute DOMString platform; + [HighEntropy, MeasureAs=NavigatorAppVersion] readonly attribute DOMString appVersion; + [HighEntropy, MeasureAs=NavigatorPlatform] readonly attribute DOMString platform; readonly attribute DOMString product; // constant "Gecko" // https://www.w3.org/Bugs/Public/show_bug.cgi?id=22555 // boolean taintEnabled(); // constant false - [Affects=Nothing] readonly attribute DOMString userAgent; + [Affects=Nothing, HighEntropy, MeasureAs=NavigatorUserAgent] readonly attribute DOMString userAgent; };
diff --git a/third_party/blink/renderer/core/frame/navigator_language.idl b/third_party/blink/renderer/core/frame/navigator_language.idl index a1cc95de..f587304 100644 --- a/third_party/blink/renderer/core/frame/navigator_language.idl +++ b/third_party/blink/renderer/core/frame/navigator_language.idl
@@ -8,6 +8,6 @@ NoInterfaceObject, Exposed=(Window,Worker) ] interface NavigatorLanguage { - readonly attribute DOMString language; - [CachedAttribute=IsLanguagesDirty] readonly attribute FrozenArray<DOMString> languages; + [HighEntropy, MeasureAs=NavigatorLanguage] readonly attribute DOMString language; + [CachedAttribute=IsLanguagesDirty, HighEntropy, MeasureAs=NavigatorLanguages] readonly attribute FrozenArray<DOMString> languages; };
diff --git a/third_party/blink/renderer/core/frame/remote_frame.cc b/third_party/blink/renderer/core/frame/remote_frame.cc index 1a40e6da..1db7ea1 100644 --- a/third_party/blink/renderer/core/frame/remote_frame.cc +++ b/third_party/blink/renderer/core/frame/remote_frame.cc
@@ -78,8 +78,7 @@ } void RemoteFrame::Navigate(const FrameLoadRequest& passed_request, - WebFrameLoadType frame_load_type, - NavigationPolicy) { + WebFrameLoadType frame_load_type) { if (!navigation_rate_limiter().CanProceed()) return;
diff --git a/third_party/blink/renderer/core/frame/remote_frame.h b/third_party/blink/renderer/core/frame/remote_frame.h index 457c94d..a2d54a2 100644 --- a/third_party/blink/renderer/core/frame/remote_frame.h +++ b/third_party/blink/renderer/core/frame/remote_frame.h
@@ -34,9 +34,7 @@ const KURL&, WebFrameLoadType, UserGestureStatus) override; - void Navigate(const FrameLoadRequest&, - WebFrameLoadType, - NavigationPolicy = kNavigationPolicyCurrentTab) override; + void Navigate(const FrameLoadRequest&, WebFrameLoadType) override; RemoteSecurityContext* GetSecurityContext() const override; bool PrepareForCommit() override; void CheckCompleted() override;
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc index f38750d..1b06b355 100644 --- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc +++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
@@ -1157,9 +1157,7 @@ void WebFrameWidgetImpl::ZoomToFindInPageRect( const WebRect& rect_in_root_frame) { - // TODO(wjmaclean): add plumbing to send IPC to browser to request - // this zoom operation on the main frame's renderer. - // https://crbug.com/734209: Add OOPIF support. + Client()->ZoomToFindInPageRectInMainFrame(rect_in_root_frame); } HitTestResult WebFrameWidgetImpl::HitTestResultForRootFramePos(
diff --git a/third_party/blink/renderer/core/html/forms/file_chooser.cc b/third_party/blink/renderer/core/html/forms/file_chooser.cc index 2cd55b41..834ba4e 100644 --- a/third_party/blink/renderer/core/html/forms/file_chooser.cc +++ b/third_party/blink/renderer/core/html/forms/file_chooser.cc
@@ -73,7 +73,8 @@ if (!frame) return false; chrome_client_impl_ = chrome_client_impl; - frame->GetInterfaceProvider().GetInterface(&file_chooser_); + frame->GetInterfaceProvider().GetInterface( + &file_chooser_, frame->GetTaskRunner(TaskType::kInternalDefault)); file_chooser_.set_connection_error_handler( WTF::Bind(&FileChooser::DidCloseChooser, WTF::Unretained(this))); file_chooser_->OpenFileChooser( @@ -92,7 +93,8 @@ if (!frame) return; DCHECK(!chrome_client_impl_); - frame->GetInterfaceProvider().GetInterface(&file_chooser_); + frame->GetInterfaceProvider().GetInterface( + &file_chooser_, frame->GetTaskRunner(TaskType::kInternalDefault)); file_chooser_.set_connection_error_handler( WTF::Bind(&FileChooser::DidCloseChooser, WTF::Unretained(this))); file_chooser_->EnumerateChosenDirectory(
diff --git a/third_party/blink/renderer/core/html/forms/html_form_element.cc b/third_party/blink/renderer/core/html/forms/html_form_element.cc index 7b44712..10acde0 100644 --- a/third_party/blink/renderer/core/html/forms/html_form_element.cc +++ b/third_party/blink/renderer/core/html/forms/html_form_element.cc
@@ -38,7 +38,6 @@ #include "third_party/blink/renderer/core/dom/events/scoped_event_queue.h" #include "third_party/blink/renderer/core/dom/node_lists_node_data.h" #include "third_party/blink/renderer/core/dom/user_gesture_indicator.h" -#include "third_party/blink/renderer/core/events/current_input_event.h" #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/local_frame.h" @@ -63,7 +62,6 @@ #include "third_party/blink/renderer/core/loader/form_submission.h" #include "third_party/blink/renderer/core/loader/mixed_content_checker.h" #include "third_party/blink/renderer/core/loader/navigation_scheduler.h" -#include "third_party/blink/renderer/core/probe/core_probes.h" #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h" namespace blink { @@ -498,32 +496,23 @@ WebFeature::kFormDisabledAttributePresentAndSubmit); } - FrameLoadRequest frame_load_request = - submission->CreateFrameLoadRequest(&GetDocument()); - frame_load_request.GetResourceRequest().SetHasUserGesture( - LocalFrame::HasTransientUserActivation(GetDocument().GetFrame())); - if (const WebInputEvent* input_event = CurrentInputEvent::Get()) - frame_load_request.SetInputStartTime(input_event->TimeStamp()); - - WebFrameLoadType frame_load_type = WebFrameLoadType::kStandard; - if (target_frame->IsLocalFrame() && - NavigationScheduler::MustReplaceCurrentItem(ToLocalFrame(target_frame))) { - frame_load_type = WebFrameLoadType::kReplaceCurrentItem; - } - - ClientNavigationReason reason = - submission->Method() == FormSubmission::kGetMethod - ? ClientNavigationReason::kFormSubmissionGet - : ClientNavigationReason::kFormSubmissionPost; + // TODO(lukasza): Investigate if the code below can uniformly handle remote + // and local frames (i.e. by calling virtual Frame::navigate from a timer). + // See also https://goo.gl/95d2KA. if (target_frame->IsLocalFrame()) { - probe::frameScheduledNavigation( - ToLocalFrame(target_frame), - frame_load_request.GetResourceRequest().Url(), 0.0, reason); - probe::frameClearedScheduledNavigation(ToLocalFrame(target_frame)); + ToLocalFrame(target_frame) + ->GetNavigationScheduler() + .ScheduleFormSubmission(&GetDocument(), submission); + } else { + FrameLoadRequest frame_load_request = + submission->CreateFrameLoadRequest(&GetDocument()); + frame_load_request.GetResourceRequest().SetHasUserGesture( + LocalFrame::HasTransientUserActivation(GetDocument().GetFrame())); + // TODO(dgozman): we lose information about triggering event and desired + // navigation policy here. + ToRemoteFrame(target_frame) + ->Navigate(frame_load_request, WebFrameLoadType::kStandard); } - - target_frame->Navigate(frame_load_request, frame_load_type, - submission->GetNavigationPolicy()); } void HTMLFormElement::reset() {
diff --git a/third_party/blink/renderer/core/inspector/worker_thread_debugger.cc b/third_party/blink/renderer/core/inspector/worker_thread_debugger.cc index 32c028f..5e8d128 100644 --- a/third_party/blink/renderer/core/inspector/worker_thread_debugger.cc +++ b/third_party/blink/renderer/core/inspector/worker_thread_debugger.cc
@@ -172,6 +172,7 @@ DCHECK(!thread->GlobalScope()->IsClosing()); thread->GetWorkerInspectorController()->FlushProtocolNotifications(); thread->GlobalScope()->PauseScheduledTasks(); + auto pause_handle = thread->GetScheduler()->Pause(); if (!nested_runner_) nested_runner_ = Platform::Current()->CreateNestedMessageLoopRunner(); nested_runner_->Run();
diff --git a/third_party/blink/renderer/core/layout/grid.cc b/third_party/blink/renderer/core/layout/grid.cc index 0b37f2a..324ba58 100644 --- a/third_party/blink/renderer/core/layout/grid.cc +++ b/third_party/blink/renderer/core/layout/grid.cc
@@ -452,17 +452,14 @@ auto& varying_index = is_row_axis ? row_index_ : column_index_; const size_t fixed_index = is_row_axis ? column_index_ : row_index_; const size_t end_fixed_span = fixed_index + fixed_track_span - 1; - size_t last_varying_index = grid_.NumTracks(orthogonal_axis); auto* track_node = tracks.Head(); while (track_node && track_node->Index() < varying_index) track_node = track_node->Next(); - do { - if (!track_node) { - if (last_varying_index - varying_index >= varying_track_span) - return CreateUniqueGridArea(); - return nullptr; - } + for (; track_node; track_node = track_node->Next()) { + if (!track_node) + return CreateUniqueGridArea(); + if (track_node->Index() - varying_index >= varying_track_span) return CreateUniqueGridArea(); @@ -473,10 +470,9 @@ varying_index = track_node->Index() + 1; else if (track_node->Index() - varying_index >= varying_track_span) return CreateUniqueGridArea(); - track_node = track_node->Next(); - } while (true); // track_node will eventually be nullptr + } - return nullptr; + return CreateUniqueGridArea(); } } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_grid.cc b/third_party/blink/renderer/core/layout/layout_grid.cc index 7b734e3..71b72542 100644 --- a/third_party/blink/renderer/core/layout/layout_grid.cc +++ b/third_party/blink/renderer/core/layout/layout_grid.cc
@@ -997,11 +997,7 @@ : minor_axis_cursors.at(major_axis_initial_position)); std::unique_ptr<GridArea> empty_grid_area = iterator->NextEmptyGridArea( major_axis_positions.IntegerSpan(), minor_axis_span_size); - if (!empty_grid_area) { - empty_grid_area = CreateEmptyGridAreaAtSpecifiedPositionsOutsideGrid( - grid, *auto_grid_item, AutoPlacementMajorAxisDirection(), - major_axis_positions); - } + DCHECK(empty_grid_area); grid.Insert(*auto_grid_item, *empty_grid_area); @@ -1085,25 +1081,24 @@ minor_axis_auto_placement_cursor); empty_grid_area = iterator->NextEmptyGridArea(major_axis_span_size, minor_axis_span_size); + DCHECK(empty_grid_area); - if (empty_grid_area) { - // Check that it fits in the minor axis direction, as we shouldn't grow - // in that direction here (it was already managed in - // populateExplicitGridAndOrderIterator()). - size_t minor_axis_final_position_index = - AutoPlacementMinorAxisDirection() == kForColumns - ? empty_grid_area->columns.EndLine() - : empty_grid_area->rows.EndLine(); - const size_t end_of_minor_axis = - grid.NumTracks(AutoPlacementMinorAxisDirection()); - if (minor_axis_final_position_index <= end_of_minor_axis) - break; + // Check that it fits in the minor axis direction, as we shouldn't grow + // in that direction here (it was already managed in + // populateExplicitGridAndOrderIterator()). + size_t minor_axis_final_position_index = + AutoPlacementMinorAxisDirection() == kForColumns + ? empty_grid_area->columns.EndLine() + : empty_grid_area->rows.EndLine(); + const size_t end_of_minor_axis = + grid.NumTracks(AutoPlacementMinorAxisDirection()); + if (minor_axis_final_position_index <= end_of_minor_axis) + break; - // Discard empty grid area as it does not fit in the minor axis - // direction. We don't need to create a new empty grid area yet as we - // might find a valid one in the next iteration. - empty_grid_area = nullptr; - } + // Discard empty grid area as it does not fit in the minor axis + // direction. We don't need to create a new empty grid area yet as we + // might find a valid one in the next iteration. + empty_grid_area.reset(); // As we're moving to the next track in the major axis we should reset the // auto-placement cursor in the minor axis.
diff --git a/third_party/blink/renderer/core/loader/document_loader.h b/third_party/blink/renderer/core/loader/document_loader.h index 02b4d7f..db9eb80 100644 --- a/third_party/blink/renderer/core/loader/document_loader.h +++ b/third_party/blink/renderer/core/loader/document_loader.h
@@ -42,6 +42,7 @@ #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/dom/weak_identifier_map.h" #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h" +#include "third_party/blink/renderer/core/frame/dactyloscoper.h" #include "third_party/blink/renderer/core/frame/frame_types.h" #include "third_party/blink/renderer/core/frame/use_counter.h" #include "third_party/blink/renderer/core/html/parser/parser_synchronization_policy.h" @@ -260,6 +261,7 @@ bool IsListingFtpDirectory() const { return listing_ftp_directory_; } UseCounter& GetUseCounter() { return use_counter_; } + Dactyloscoper& GetDactyloscoper() { return dactyloscoper_; } protected: static bool ShouldClearWindowName( @@ -425,6 +427,8 @@ // metrics that aggregates usage from frames to one page load and report // feature usage to UMA histograms per page load. UseCounter use_counter_; + + Dactyloscoper dactyloscoper_; }; DECLARE_WEAK_IDENTIFIER_MAP(DocumentLoader);
diff --git a/third_party/blink/renderer/core/loader/navigation_scheduler.cc b/third_party/blink/renderer/core/loader/navigation_scheduler.cc index 89bf15b..ff55612 100644 --- a/third_party/blink/renderer/core/loader/navigation_scheduler.cc +++ b/third_party/blink/renderer/core/loader/navigation_scheduler.cc
@@ -235,6 +235,55 @@ int reason_; }; +class ScheduledFormSubmission final : public ScheduledNavigation { + public: + static ScheduledFormSubmission* Create(Document* document, + FormSubmission* submission, + WebFrameLoadType frame_load_type, + base::TimeTicks input_timestamp) { + return MakeGarbageCollected<ScheduledFormSubmission>( + document, submission, frame_load_type, input_timestamp); + } + + ScheduledFormSubmission(Document* document, + FormSubmission* submission, + WebFrameLoadType frame_load_type, + base::TimeTicks input_timestamp) + : ScheduledNavigation(submission->Method() == FormSubmission::kGetMethod + ? ClientNavigationReason::kFormSubmissionGet + : ClientNavigationReason::kFormSubmissionPost, + 0, + document, + true, + input_timestamp), + submission_(submission), + frame_load_type_(frame_load_type) { + DCHECK_NE(submission->Method(), FormSubmission::kDialogMethod); + DCHECK(submission_->Form()); + } + + void Fire(LocalFrame* frame) override { + std::unique_ptr<UserGestureIndicator> gesture_indicator = + CreateUserGestureIndicator(); + FrameLoadRequest frame_request = + submission_->CreateFrameLoadRequest(OriginDocument()); + frame_request.SetInputStartTime(InputTimestamp()); + frame->Loader().StartNavigation(frame_request, frame_load_type_, + submission_->GetNavigationPolicy()); + } + + KURL Url() const override { return submission_->RequestURL(); } + + void Trace(blink::Visitor* visitor) override { + visitor->Trace(submission_); + ScheduledNavigation::Trace(visitor); + } + + private: + Member<FormSubmission> submission_; + WebFrameLoadType frame_load_type_; +}; + NavigationScheduler::NavigationScheduler(LocalFrame* frame) : frame_(frame) {} NavigationScheduler::~NavigationScheduler() { @@ -340,6 +389,16 @@ Schedule(ScheduledPageBlock::Create(origin_document, reason)); } +void NavigationScheduler::ScheduleFormSubmission(Document* document, + FormSubmission* submission) { + DCHECK(frame_->GetPage()); + WebFrameLoadType frame_load_type = WebFrameLoadType::kStandard; + if (MustReplaceCurrentItem(frame_)) + frame_load_type = WebFrameLoadType::kReplaceCurrentItem; + Schedule(ScheduledFormSubmission::Create(document, submission, + frame_load_type, InputTimestamp())); +} + void NavigationScheduler::NavigateTask() { if (!frame_->GetPage()) return;
diff --git a/third_party/blink/renderer/core/loader/navigation_scheduler.h b/third_party/blink/renderer/core/loader/navigation_scheduler.h index 46522db..d9769b2 100644 --- a/third_party/blink/renderer/core/loader/navigation_scheduler.h +++ b/third_party/blink/renderer/core/loader/navigation_scheduler.h
@@ -49,6 +49,7 @@ namespace blink { +class FormSubmission; class LocalFrame; class ScheduledNavigation; @@ -68,12 +69,11 @@ void ScheduleRedirect(double delay, const KURL&, Document::HttpRefreshType); void ScheduleFrameNavigation(Document*, const KURL&, WebFrameLoadType); void SchedulePageBlock(Document*, int reason); + void ScheduleFormSubmission(Document*, FormSubmission*); void StartTimer(); void Cancel(); - static bool MustReplaceCurrentItem(LocalFrame* target_frame); - void Trace(blink::Visitor*); private: @@ -82,6 +82,7 @@ void NavigateTask(); void Schedule(ScheduledNavigation*); + static bool MustReplaceCurrentItem(LocalFrame* target_frame); base::TimeTicks InputTimestamp(); Member<LocalFrame> frame_;
diff --git a/third_party/blink/renderer/core/page/scrolling/main_thread_scrolling_reasons_test.cc b/third_party/blink/renderer/core/page/scrolling/main_thread_scrolling_reasons_test.cc new file mode 100644 index 0000000..2ac22bf --- /dev/null +++ b/third_party/blink/renderer/core/page/scrolling/main_thread_scrolling_reasons_test.cc
@@ -0,0 +1,581 @@ +// 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 "cc/layers/picture_layer.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/platform/web_url_loader_mock_factory.h" +#include "third_party/blink/renderer/core/frame/frame_test_helpers.h" +#include "third_party/blink/renderer/core/frame/local_frame_view.h" +#include "third_party/blink/renderer/core/frame/visual_viewport.h" +#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h" +#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h" +#include "third_party/blink/renderer/core/html/html_iframe_element.h" +#include "third_party/blink/renderer/core/layout/layout_embedded_content.h" +#include "third_party/blink/renderer/core/layout/layout_view.h" +#include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h" +#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h" +#include "third_party/blink/renderer/platform/graphics/graphics_layer.h" +#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h" +#include "third_party/blink/renderer/platform/testing/url_test_helpers.h" + +namespace blink { + +class MainThreadScrollingReasonsTest + : public testing::Test, + public testing::WithParamInterface<bool>, + private ScopedBlinkGenPropertyTreesForTest { + public: + MainThreadScrollingReasonsTest() + : ScopedBlinkGenPropertyTreesForTest(GetParam()), + base_url_("http://www.test.com/") { + helper_.Initialize(nullptr, nullptr, &ConfigureSettings); + GetWebView()->MainFrameWidget()->Resize(IntSize(320, 240)); + + // macOS attaches main frame scrollbars to the VisualViewport so the + // VisualViewport layers need to be initialized. + GetWebView()->MainFrameWidget()->UpdateAllLifecyclePhases( + WebWidget::LifecycleUpdateReason::kTest); + WebFrameWidgetBase* main_frame_widget = + GetWebView()->MainFrameImpl()->FrameWidgetImpl(); + main_frame_widget->SetRootGraphicsLayer(GetWebView() + ->MainFrameImpl() + ->GetFrame() + ->View() + ->GetLayoutView() + ->Compositor() + ->RootGraphicsLayer()); + } + + ~MainThreadScrollingReasonsTest() override { + Platform::Current() + ->GetURLLoaderMockFactory() + ->UnregisterAllURLsAndClearMemoryCache(); + } + + void NavigateTo(const std::string& url) { + frame_test_helpers::LoadFrame(GetWebView()->MainFrameImpl(), url); + } + + void LoadHTML(const std::string& html) { + frame_test_helpers::LoadHTMLString(GetWebView()->MainFrameImpl(), html, + url_test_helpers::ToKURL("about:blank")); + } + + void ForceFullCompositingUpdate() { + GetWebView()->MainFrameWidget()->UpdateAllLifecyclePhases( + WebWidget::LifecycleUpdateReason::kTest); + } + + void RegisterMockedHttpURLLoad(const std::string& file_name) { + url_test_helpers::RegisterMockedURLLoadFromBase( + WebString::FromUTF8(base_url_), test::CoreTestDataPath(), + WebString::FromUTF8(file_name)); + } + + uint32_t GetViewMainThreadScrollingReasons() const { + // Pre-BlinkGenPropertyTrees, main thread scrolling reasons are set on + // cc::Layer in ScrollingCoordinator. + if (!RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) { + auto* layer = GetFrame()->View()->LayoutViewport()->LayerForScrolling(); + return layer->CcLayer()->GetMainThreadScrollingReasons(); + } + // With BlinkGenPropertyTrees, main thread scrolling reasons are calculated + // in the blink property tree builder and set on set on scroll nodes. + const auto* scroll = GetFrame() + ->View() + ->GetLayoutView() + ->FirstFragment() + .PaintProperties() + ->Scroll(); + return scroll->GetMainThreadScrollingReasons(); + } + + WebViewImpl* GetWebView() const { return helper_.GetWebView(); } + LocalFrame* GetFrame() const { return helper_.LocalMainFrame()->GetFrame(); } + + protected: + std::string base_url_; + + private: + static void ConfigureSettings(WebSettings* settings) { + settings->SetPreferCompositingToLCDTextEnabled(true); + } + + frame_test_helpers::WebViewHelper helper_; +}; + +INSTANTIATE_TEST_CASE_P(All, MainThreadScrollingReasonsTest, testing::Bool()); + +TEST_P(MainThreadScrollingReasonsTest, + FixedPositionLosingBackingShouldTriggerMainThreadScroll) { + GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(false); + RegisterMockedHttpURLLoad("fixed-position-losing-backing.html"); + NavigateTo(base_url_ + "fixed-position-losing-backing.html"); + ForceFullCompositingUpdate(); + + EXPECT_FALSE(GetViewMainThreadScrollingReasons()); + + Element* fixed_pos = GetFrame()->GetDocument()->getElementById("fixed"); + fixed_pos->SetInlineStyleProperty(CSSPropertyTransform, CSSValueNone); + ForceFullCompositingUpdate(); + + EXPECT_TRUE(GetViewMainThreadScrollingReasons()); +} + +TEST_P(MainThreadScrollingReasonsTest, + CustomScrollbarShouldTriggerMainThreadScroll) { + GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(true); + GetWebView()->SetDeviceScaleFactor(2.f); + RegisterMockedHttpURLLoad("custom_scrollbar.html"); + NavigateTo(base_url_ + "custom_scrollbar.html"); + ForceFullCompositingUpdate(); + + Document* document = GetFrame()->GetDocument(); + Element* container = document->getElementById("container"); + Element* content = document->getElementById("content"); + DCHECK_EQ(container->getAttribute(html_names::kClassAttr), + "custom_scrollbar"); + DCHECK(container); + DCHECK(content); + + LayoutObject* layout_object = container->GetLayoutObject(); + ASSERT_TRUE(layout_object->IsBox()); + LayoutBox* box = ToLayoutBox(layout_object); + ASSERT_TRUE(box->UsesCompositedScrolling()); + CompositedLayerMapping* composited_layer_mapping = + box->Layer()->GetCompositedLayerMapping(); + // When Blink generates property trees, the main thread reasons are stored in + // scroll nodes instead of being set on the custom scrollbar layer, so we use + // the scrolling contents layer to access the main thread scrolling reasons. + GraphicsLayer* layer = + RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled() + ? composited_layer_mapping->ScrollingContentsLayer() + : composited_layer_mapping->LayerForVerticalScrollbar(); + ASSERT_TRUE(layer); + EXPECT_TRUE(layer->CcLayer()->GetMainThreadScrollingReasons()); + EXPECT_TRUE(layer->CcLayer()->GetMainThreadScrollingReasons() & + MainThreadScrollingReason::kCustomScrollbarScrolling); + + // remove custom scrollbar class, the scrollbar is expected to scroll on + // impl thread as it is an overlay scrollbar. + container->removeAttribute("class"); + ForceFullCompositingUpdate(); + layer = RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled() + ? composited_layer_mapping->ScrollingContentsLayer() + : composited_layer_mapping->LayerForVerticalScrollbar(); + EXPECT_FALSE(layer->CcLayer()->GetMainThreadScrollingReasons()); + EXPECT_FALSE(layer->CcLayer()->GetMainThreadScrollingReasons() & + MainThreadScrollingReason::kCustomScrollbarScrolling); +} + +TEST_P(MainThreadScrollingReasonsTest, + BackgroundAttachmentFixedShouldTriggerMainThreadScroll) { + RegisterMockedHttpURLLoad("iframe-background-attachment-fixed.html"); + RegisterMockedHttpURLLoad("iframe-background-attachment-fixed-inner.html"); + RegisterMockedHttpURLLoad("white-1x1.png"); + NavigateTo(base_url_ + "iframe-background-attachment-fixed.html"); + ForceFullCompositingUpdate(); + + Element* iframe = GetFrame()->GetDocument()->getElementById("iframe"); + ASSERT_TRUE(iframe); + + LayoutObject* layout_object = iframe->GetLayoutObject(); + ASSERT_TRUE(layout_object); + ASSERT_TRUE(layout_object->IsLayoutEmbeddedContent()); + + LayoutEmbeddedContent* layout_embedded_content = + ToLayoutEmbeddedContent(layout_object); + ASSERT_TRUE(layout_embedded_content); + + LocalFrameView* inner_frame_view = + ToLocalFrameView(layout_embedded_content->ChildFrameView()); + ASSERT_TRUE(inner_frame_view); + + auto* inner_layout_view = inner_frame_view->GetLayoutView(); + ASSERT_TRUE(inner_layout_view); + + PaintLayerCompositor* inner_compositor = inner_layout_view->Compositor(); + ASSERT_TRUE(inner_compositor->InCompositingMode()); + + GraphicsLayer* scroll_layer = + inner_frame_view->LayoutViewport()->LayerForScrolling(); + ASSERT_TRUE(scroll_layer); + + cc::Layer* cc_scroll_layer = scroll_layer->CcLayer(); + ASSERT_TRUE(cc_scroll_layer->scrollable()); + ASSERT_TRUE(cc_scroll_layer->GetMainThreadScrollingReasons() & + MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects); + + // Remove fixed background-attachment should make the iframe + // scroll on cc. + auto* iframe_doc = ToHTMLIFrameElement(iframe)->contentDocument(); + iframe = iframe_doc->getElementById("scrollable"); + ASSERT_TRUE(iframe); + + iframe->removeAttribute("class"); + ForceFullCompositingUpdate(); + + layout_object = iframe->GetLayoutObject(); + ASSERT_TRUE(layout_object); + + scroll_layer = + layout_object->GetFrameView()->LayoutViewport()->LayerForScrolling(); + ASSERT_TRUE(scroll_layer); + + cc_scroll_layer = scroll_layer->CcLayer(); + ASSERT_TRUE(cc_scroll_layer->scrollable()); + ASSERT_FALSE(cc_scroll_layer->GetMainThreadScrollingReasons() & + MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects); + + // Force main frame to scroll on main thread. All its descendants + // should scroll on main thread as well. + Element* element = GetFrame()->GetDocument()->getElementById("scrollable"); + element->setAttribute( + "style", + "background-image: url('white-1x1.png'); background-attachment: fixed;", + ASSERT_NO_EXCEPTION); + + ForceFullCompositingUpdate(); + + layout_object = iframe->GetLayoutObject(); + ASSERT_TRUE(layout_object); + + scroll_layer = + layout_object->GetFrameView()->LayoutViewport()->LayerForScrolling(); + ASSERT_TRUE(scroll_layer); + + cc_scroll_layer = scroll_layer->CcLayer(); + ASSERT_TRUE(cc_scroll_layer->scrollable()); + ASSERT_TRUE(cc_scroll_layer->GetMainThreadScrollingReasons() & + MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects); +} + +// Upon resizing the content size, the main thread scrolling reason +// kHasNonLayerViewportConstrainedObject should be updated on all frames +TEST_P(MainThreadScrollingReasonsTest, + RecalculateMainThreadScrollingReasonsUponResize) { + GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(false); + RegisterMockedHttpURLLoad("has-non-layer-viewport-constrained-objects.html"); + NavigateTo(base_url_ + "has-non-layer-viewport-constrained-objects.html"); + ForceFullCompositingUpdate(); + + // When the main document is not scrollable, there should be no reasons. + EXPECT_FALSE(GetViewMainThreadScrollingReasons()); + + // When the div forces the document to be scrollable, it should scroll on main + // thread. + Element* element = GetFrame()->GetDocument()->getElementById("scrollable"); + element->setAttribute("style", + "overflow:scroll;height:2000px;will-change:transform;", + ASSERT_NO_EXCEPTION); + ForceFullCompositingUpdate(); + + EXPECT_TRUE( + GetViewMainThreadScrollingReasons() & + MainThreadScrollingReason::kHasNonLayerViewportConstrainedObjects); + + // The main thread scrolling reason should be reset upon the following change. + element->setAttribute("style", + "overflow:scroll;height:200px;will-change:transform;", + ASSERT_NO_EXCEPTION); + ForceFullCompositingUpdate(); + + EXPECT_FALSE(GetViewMainThreadScrollingReasons()); +} + +TEST_P(MainThreadScrollingReasonsTest, StickyTriggersMainThreadScroll) { + GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(false); + LoadHTML( + "<body style='height: 1200px'>" + "<div style='position: sticky; top: 0'>sticky</div>"); + ForceFullCompositingUpdate(); + EXPECT_EQ(MainThreadScrollingReason::kHasNonLayerViewportConstrainedObjects, + GetViewMainThreadScrollingReasons()); +} + +TEST_P(MainThreadScrollingReasonsTest, FastScrollingCanBeDisabledWithSetting) { + GetWebView()->MainFrameWidget()->Resize(WebSize(800, 600)); + LoadHTML("<div id='spacer' style='height: 1000px'></div>"); + GetWebView()->GetSettings()->SetThreadedScrollingEnabled(false); + GetFrame()->View()->SetNeedsPaintPropertyUpdate(); + ForceFullCompositingUpdate(); + + // Main scrolling should be enabled with the setting override. + EXPECT_TRUE(GetViewMainThreadScrollingReasons()); + + // Main scrolling should also propagate to inner viewport layer. + cc::Layer* inner_viewport_scroll_layer = + GetFrame()->GetPage()->GetVisualViewport().ScrollLayer()->CcLayer(); + ASSERT_TRUE(inner_viewport_scroll_layer->scrollable()); + EXPECT_TRUE(inner_viewport_scroll_layer->GetMainThreadScrollingReasons()); +} + +TEST_P(MainThreadScrollingReasonsTest, FastScrollingForFixedPosition) { + RegisterMockedHttpURLLoad("fixed-position.html"); + NavigateTo(base_url_ + "fixed-position.html"); + ForceFullCompositingUpdate(); + + // Fixed position should not fall back to main thread scrolling. + EXPECT_FALSE(GetViewMainThreadScrollingReasons()); +} + +TEST_P(MainThreadScrollingReasonsTest, FastScrollingForStickyPosition) { + RegisterMockedHttpURLLoad("sticky-position.html"); + NavigateTo(base_url_ + "sticky-position.html"); + ForceFullCompositingUpdate(); + + // Sticky position should not fall back to main thread scrolling. + EXPECT_FALSE(GetViewMainThreadScrollingReasons()); +} + +TEST_P(MainThreadScrollingReasonsTest, FastScrollingByDefault) { + GetWebView()->MainFrameWidget()->Resize(WebSize(800, 600)); + LoadHTML("<div id='spacer' style='height: 1000px'></div>"); + ForceFullCompositingUpdate(); + + // Fast scrolling should be enabled by default. + EXPECT_FALSE(GetViewMainThreadScrollingReasons()); + + cc::Layer* inner_viewport_scroll_layer = + GetFrame()->GetPage()->GetVisualViewport().ScrollLayer()->CcLayer(); + ASSERT_TRUE(inner_viewport_scroll_layer->scrollable()); + EXPECT_FALSE(inner_viewport_scroll_layer->GetMainThreadScrollingReasons()); +} + +TEST_P(MainThreadScrollingReasonsTest, + ScrollbarsForceMainThreadOrHaveCompositorScrollbarLayer) { + RegisterMockedHttpURLLoad("trivial-scroller.html"); + NavigateTo(base_url_ + "trivial-scroller.html"); + ForceFullCompositingUpdate(); + + Document* document = GetFrame()->GetDocument(); + Element* scrollable_element = document->getElementById("scroller"); + DCHECK(scrollable_element); + + LayoutObject* layout_object = scrollable_element->GetLayoutObject(); + ASSERT_TRUE(layout_object->IsBox()); + LayoutBox* box = ToLayoutBox(layout_object); + ASSERT_TRUE(box->UsesCompositedScrolling()); + CompositedLayerMapping* composited_layer_mapping = + box->Layer()->GetCompositedLayerMapping(); + GraphicsLayer* scrollbar_graphics_layer = + composited_layer_mapping->LayerForVerticalScrollbar(); + ASSERT_TRUE(scrollbar_graphics_layer); + + bool has_cc_scrollbar_layer = !scrollbar_graphics_layer->DrawsContent(); + EXPECT_TRUE( + has_cc_scrollbar_layer || + scrollbar_graphics_layer->CcLayer()->GetMainThreadScrollingReasons()); +} + +class NonCompositedMainThreadScrollingReasonsTest + : public MainThreadScrollingReasonsTest { + static const uint32_t kLCDTextRelatedReasons = + MainThreadScrollingReason::kHasOpacityAndLCDText | + MainThreadScrollingReason::kHasTransformAndLCDText | + MainThreadScrollingReason::kBackgroundNotOpaqueInRectAndLCDText | + MainThreadScrollingReason::kIsNotStackingContextAndLCDText; + + protected: + NonCompositedMainThreadScrollingReasonsTest() { + RegisterMockedHttpURLLoad("two_scrollable_area.html"); + NavigateTo(base_url_ + "two_scrollable_area.html"); + } + void TestNonCompositedReasons(const std::string& target, + const uint32_t reason) { + GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(false); + Document* document = GetFrame()->GetDocument(); + Element* container = document->getElementById("scroller1"); + container->setAttribute("class", target.c_str(), ASSERT_NO_EXCEPTION); + ForceFullCompositingUpdate(); + + PaintLayerScrollableArea* scrollable_area = + ToLayoutBoxModelObject(container->GetLayoutObject()) + ->GetScrollableArea(); + ASSERT_TRUE(scrollable_area); + EXPECT_TRUE(scrollable_area->GetNonCompositedMainThreadScrollingReasons() & + reason); + + Element* container2 = document->getElementById("scroller2"); + PaintLayerScrollableArea* scrollable_area2 = + ToLayoutBoxModelObject(container2->GetLayoutObject()) + ->GetScrollableArea(); + ASSERT_TRUE(scrollable_area2); + // Different scrollable area should remain unaffected. + EXPECT_FALSE( + scrollable_area2->GetNonCompositedMainThreadScrollingReasons() & + reason); + + LocalFrameView* frame_view = GetFrame()->View(); + ASSERT_TRUE(frame_view); + EXPECT_FALSE(frame_view->GetMainThreadScrollingReasons() & reason); + + // Remove attribute from the scroller 1 would lead to scroll on impl. + container->removeAttribute("class"); + ForceFullCompositingUpdate(); + + EXPECT_FALSE(scrollable_area->GetNonCompositedMainThreadScrollingReasons() & + reason); + EXPECT_FALSE(frame_view->GetMainThreadScrollingReasons() & reason); + + // Add target attribute would again lead to scroll on main thread + container->setAttribute("class", target.c_str(), ASSERT_NO_EXCEPTION); + ForceFullCompositingUpdate(); + + EXPECT_TRUE(scrollable_area->GetNonCompositedMainThreadScrollingReasons() & + reason); + EXPECT_FALSE(frame_view->GetMainThreadScrollingReasons() & reason); + + if ((reason & kLCDTextRelatedReasons) && + !(reason & ~kLCDTextRelatedReasons)) { + GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(true); + ForceFullCompositingUpdate(); + EXPECT_FALSE( + scrollable_area->GetNonCompositedMainThreadScrollingReasons()); + EXPECT_FALSE(frame_view->GetMainThreadScrollingReasons()); + } + } +}; + +INSTANTIATE_TEST_CASE_P(All, + NonCompositedMainThreadScrollingReasonsTest, + testing::Bool()); + +TEST_P(NonCompositedMainThreadScrollingReasonsTest, TransparentTest) { + TestNonCompositedReasons("transparent", + MainThreadScrollingReason::kHasOpacityAndLCDText); +} + +TEST_P(NonCompositedMainThreadScrollingReasonsTest, TransformTest) { + TestNonCompositedReasons("transform", + MainThreadScrollingReason::kHasTransformAndLCDText); +} + +TEST_P(NonCompositedMainThreadScrollingReasonsTest, BackgroundNotOpaqueTest) { + TestNonCompositedReasons( + "background-not-opaque", + MainThreadScrollingReason::kBackgroundNotOpaqueInRectAndLCDText); +} + +TEST_P(NonCompositedMainThreadScrollingReasonsTest, ClipTest) { + TestNonCompositedReasons("clip", + MainThreadScrollingReason::kHasClipRelatedProperty); +} + +TEST_P(NonCompositedMainThreadScrollingReasonsTest, ClipPathTest) { + uint32_t clip_reason = MainThreadScrollingReason::kHasClipRelatedProperty; + GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(false); + Document* document = GetFrame()->GetDocument(); + // Test ancestor with ClipPath + Element* element = document->body(); + element->setAttribute(html_names::kStyleAttr, + "clip-path:circle(115px at 20px 20px);"); + Element* container = document->getElementById("scroller1"); + ASSERT_TRUE(container); + ForceFullCompositingUpdate(); + + PaintLayerScrollableArea* scrollable_area = + ToLayoutBoxModelObject(container->GetLayoutObject())->GetScrollableArea(); + EXPECT_TRUE(scrollable_area->GetNonCompositedMainThreadScrollingReasons() & + clip_reason); + + EXPECT_FALSE(GetViewMainThreadScrollingReasons() & clip_reason); + + // Remove clip path from ancestor. + element->removeAttribute(html_names::kStyleAttr); + ForceFullCompositingUpdate(); + + EXPECT_FALSE(scrollable_area->GetNonCompositedMainThreadScrollingReasons() & + clip_reason); + EXPECT_FALSE(GetViewMainThreadScrollingReasons() & clip_reason); + + // Test descendant with ClipPath + element = document->getElementById("content1"); + ASSERT_TRUE(element); + element->setAttribute(html_names::kStyleAttr, + "clip-path:circle(115px at 20px 20px);"); + ForceFullCompositingUpdate(); + EXPECT_TRUE(scrollable_area->GetNonCompositedMainThreadScrollingReasons() & + clip_reason); + EXPECT_FALSE(GetViewMainThreadScrollingReasons() & clip_reason); + + // Remove clip path from descendant. + element->removeAttribute(html_names::kStyleAttr); + ForceFullCompositingUpdate(); + EXPECT_FALSE(scrollable_area->GetNonCompositedMainThreadScrollingReasons() & + clip_reason); + EXPECT_FALSE(GetViewMainThreadScrollingReasons() & clip_reason); +} + +TEST_P(NonCompositedMainThreadScrollingReasonsTest, LCDTextEnabledTest) { + TestNonCompositedReasons("transparent", + MainThreadScrollingReason::kHasOpacityAndLCDText); +} + +TEST_P(NonCompositedMainThreadScrollingReasonsTest, BoxShadowTest) { + TestNonCompositedReasons( + "box-shadow", MainThreadScrollingReason::kHasBoxShadowFromNonRootLayer); +} + +TEST_P(NonCompositedMainThreadScrollingReasonsTest, StackingContextTest) { + GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(false); + + Document* document = GetFrame()->GetDocument(); + Element* container = document->getElementById("scroller1"); + ASSERT_TRUE(container); + + ForceFullCompositingUpdate(); + + // If a scroller contains all its children, it's not a stacking context. + PaintLayerScrollableArea* scrollable_area = + ToLayoutBoxModelObject(container->GetLayoutObject())->GetScrollableArea(); + ASSERT_TRUE(scrollable_area); + EXPECT_TRUE(scrollable_area->GetNonCompositedMainThreadScrollingReasons() & + MainThreadScrollingReason::kIsNotStackingContextAndLCDText); + + GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(true); + ForceFullCompositingUpdate(); + EXPECT_FALSE(scrollable_area->GetNonCompositedMainThreadScrollingReasons() & + MainThreadScrollingReason::kIsNotStackingContextAndLCDText); + GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(false); + + // Adding "contain: paint" to force a stacking context leads to promotion. + container->setAttribute("style", "contain: paint", ASSERT_NO_EXCEPTION); + ForceFullCompositingUpdate(); + + EXPECT_FALSE(scrollable_area->GetNonCompositedMainThreadScrollingReasons()); +} + +TEST_P(NonCompositedMainThreadScrollingReasonsTest, + CompositedWithLCDTextRelatedReasonsTest) { + // With "will-change:transform" we composite elements with + // LCDTextRelatedReasons only. For elements with other + // NonCompositedReasons, we don't create scrollingLayer for their + // CompositedLayerMapping therefore they don't get composited. + GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(false); + Document* document = GetFrame()->GetDocument(); + Element* container = document->getElementById("scroller1"); + ASSERT_TRUE(container); + container->setAttribute("class", "composited transparent", + ASSERT_NO_EXCEPTION); + ForceFullCompositingUpdate(); + + PaintLayerScrollableArea* scrollable_area = + ToLayoutBoxModelObject(container->GetLayoutObject())->GetScrollableArea(); + ASSERT_TRUE(scrollable_area); + EXPECT_FALSE(scrollable_area->GetNonCompositedMainThreadScrollingReasons()); + + Element* container2 = document->getElementById("scroller2"); + ASSERT_TRUE(container2); + container2->setAttribute("class", "composited border-radius", + ASSERT_NO_EXCEPTION); + ForceFullCompositingUpdate(); + PaintLayerScrollableArea* scrollable_area2 = + ToLayoutBoxModelObject(container2->GetLayoutObject()) + ->GetScrollableArea(); + ASSERT_TRUE(scrollable_area2); + ASSERT_TRUE(scrollable_area2->UsesCompositedScrolling()); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc b/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc index eeeb190..9473160 100644 --- a/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc +++ b/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc
@@ -196,33 +196,6 @@ ASSERT_FALSE(inner_viewport_scroll_layer->GetMainThreadScrollingReasons()); } -TEST_P(ScrollingCoordinatorTest, fastScrollingCanBeDisabledWithSetting) { - GetWebView()->MainFrameWidget()->Resize(WebSize(800, 600)); - LoadHTML("<div id='spacer' style='height: 1000px'></div>"); - GetWebView()->GetSettings()->SetThreadedScrollingEnabled(false); - GetFrame()->View()->SetNeedsPaintPropertyUpdate(); - ForceFullCompositingUpdate(); - - // Make sure the scrolling coordinator is active. - LocalFrameView* frame_view = GetFrame()->View(); - Page* page = GetFrame()->GetPage(); - ASSERT_TRUE(page->GetScrollingCoordinator()); - ASSERT_TRUE(page->GetScrollingCoordinator()->CoordinatesScrollingForFrameView( - frame_view)); - - // Main scrolling should be enabled with the setting override. - cc::Layer* root_scroll_layer = GetRootScrollLayer(); - ASSERT_TRUE(root_scroll_layer); - ASSERT_TRUE(root_scroll_layer->scrollable()); - ASSERT_TRUE(root_scroll_layer->GetMainThreadScrollingReasons()); - - // Main scrolling should also propagate to inner viewport layer. - cc::Layer* inner_viewport_scroll_layer = - page->GetVisualViewport().ScrollLayer()->CcLayer(); - ASSERT_TRUE(inner_viewport_scroll_layer->scrollable()); - ASSERT_TRUE(inner_viewport_scroll_layer->GetMainThreadScrollingReasons()); -} - TEST_P(ScrollingCoordinatorTest, fastFractionalScrollingDiv) { ScopedFractionalScrollOffsetsForTest fractional_scroll_offsets(true); @@ -1325,32 +1298,6 @@ // an empty document by javascript. } -TEST_P(ScrollingCoordinatorTest, - ScrollbarsForceMainThreadOrHaveCompositorScrollbarLayer) { - RegisterMockedHttpURLLoad("trivial-scroller.html"); - NavigateTo(base_url_ + "trivial-scroller.html"); - ForceFullCompositingUpdate(); - - Document* document = GetFrame()->GetDocument(); - Element* scrollable_element = document->getElementById("scroller"); - DCHECK(scrollable_element); - - LayoutObject* layout_object = scrollable_element->GetLayoutObject(); - ASSERT_TRUE(layout_object->IsBox()); - LayoutBox* box = ToLayoutBox(layout_object); - ASSERT_TRUE(box->UsesCompositedScrolling()); - CompositedLayerMapping* composited_layer_mapping = - box->Layer()->GetCompositedLayerMapping(); - GraphicsLayer* scrollbar_graphics_layer = - composited_layer_mapping->LayerForVerticalScrollbar(); - ASSERT_TRUE(scrollbar_graphics_layer); - - bool has_cc_scrollbar_layer = !scrollbar_graphics_layer->DrawsContent(); - ASSERT_TRUE( - has_cc_scrollbar_layer || - scrollbar_graphics_layer->CcLayer()->GetMainThreadScrollingReasons()); -} - #if defined(OS_MACOSX) || defined(OS_ANDROID) TEST_P(ScrollingCoordinatorTest, DISABLED_setupScrollbarLayerShouldSetScrollLayerOpaque) @@ -1382,219 +1329,6 @@ contents_layer->contents_opaque()); } -// TODO(pdr): Main thread scrolling reason tests should be moved out of -// scrolling_coordinator_test.cc because the reasons are calculated in -// paint_property_tree_builder.cc for BlinkGeneratedPropertyTrees. -TEST_P(ScrollingCoordinatorTest, - FixedPositionLosingBackingShouldTriggerMainThreadScroll) { - GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(false); - RegisterMockedHttpURLLoad("fixed-position-losing-backing.html"); - NavigateTo(base_url_ + "fixed-position-losing-backing.html"); - ForceFullCompositingUpdate(); - - cc::Layer* scroll_layer = GetRootScrollLayer(); - ASSERT_TRUE(scroll_layer); - - Document* document = GetFrame()->GetDocument(); - Element* fixed_pos = document->getElementById("fixed"); - - EXPECT_TRUE(static_cast<LayoutBoxModelObject*>(fixed_pos->GetLayoutObject()) - ->Layer() - ->HasCompositedLayerMapping()); - EXPECT_FALSE(scroll_layer->GetMainThreadScrollingReasons()); - - fixed_pos->SetInlineStyleProperty(CSSPropertyTransform, CSSValueNone); - ForceFullCompositingUpdate(); - - EXPECT_FALSE(static_cast<LayoutBoxModelObject*>(fixed_pos->GetLayoutObject()) - ->Layer() - ->HasCompositedLayerMapping()); - EXPECT_TRUE(scroll_layer->GetMainThreadScrollingReasons()); -} - -TEST_P(ScrollingCoordinatorTest, CustomScrollbarShouldTriggerMainThreadScroll) { - GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(true); - GetWebView()->SetDeviceScaleFactor(2.f); - RegisterMockedHttpURLLoad("custom_scrollbar.html"); - NavigateTo(base_url_ + "custom_scrollbar.html"); - ForceFullCompositingUpdate(); - - Document* document = GetFrame()->GetDocument(); - Element* container = document->getElementById("container"); - Element* content = document->getElementById("content"); - DCHECK_EQ(container->getAttribute(html_names::kClassAttr), - "custom_scrollbar"); - DCHECK(container); - DCHECK(content); - - LayoutObject* layout_object = container->GetLayoutObject(); - ASSERT_TRUE(layout_object->IsBox()); - LayoutBox* box = ToLayoutBox(layout_object); - ASSERT_TRUE(box->UsesCompositedScrolling()); - CompositedLayerMapping* composited_layer_mapping = - box->Layer()->GetCompositedLayerMapping(); - // When Blink generates property trees, the main thread reasons are stored in - // scroll nodes instead of being set on the custom scrollbar layer, so we use - // the scrolling contents layer to access the main thread scrolling reasons. - GraphicsLayer* layer = - RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled() - ? composited_layer_mapping->ScrollingContentsLayer() - : composited_layer_mapping->LayerForVerticalScrollbar(); - ASSERT_TRUE(layer); - EXPECT_TRUE(layer->CcLayer()->GetMainThreadScrollingReasons()); - EXPECT_TRUE(layer->CcLayer()->GetMainThreadScrollingReasons() & - MainThreadScrollingReason::kCustomScrollbarScrolling); - - // remove custom scrollbar class, the scrollbar is expected to scroll on - // impl thread as it is an overlay scrollbar. - container->removeAttribute("class"); - ForceFullCompositingUpdate(); - layer = RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled() - ? composited_layer_mapping->ScrollingContentsLayer() - : composited_layer_mapping->LayerForVerticalScrollbar(); - EXPECT_FALSE(layer->CcLayer()->GetMainThreadScrollingReasons()); - EXPECT_FALSE(layer->CcLayer()->GetMainThreadScrollingReasons() & - MainThreadScrollingReason::kCustomScrollbarScrolling); -} - -TEST_P(ScrollingCoordinatorTest, - BackgroundAttachmentFixedShouldTriggerMainThreadScroll) { - RegisterMockedHttpURLLoad("iframe-background-attachment-fixed.html"); - RegisterMockedHttpURLLoad("iframe-background-attachment-fixed-inner.html"); - RegisterMockedHttpURLLoad("white-1x1.png"); - NavigateTo(base_url_ + "iframe-background-attachment-fixed.html"); - ForceFullCompositingUpdate(); - - Element* iframe = GetFrame()->GetDocument()->getElementById("iframe"); - ASSERT_TRUE(iframe); - - LayoutObject* layout_object = iframe->GetLayoutObject(); - ASSERT_TRUE(layout_object); - ASSERT_TRUE(layout_object->IsLayoutEmbeddedContent()); - - LayoutEmbeddedContent* layout_embedded_content = - ToLayoutEmbeddedContent(layout_object); - ASSERT_TRUE(layout_embedded_content); - - LocalFrameView* inner_frame_view = - ToLocalFrameView(layout_embedded_content->ChildFrameView()); - ASSERT_TRUE(inner_frame_view); - - auto* inner_layout_view = inner_frame_view->GetLayoutView(); - ASSERT_TRUE(inner_layout_view); - - PaintLayerCompositor* inner_compositor = inner_layout_view->Compositor(); - ASSERT_TRUE(inner_compositor->InCompositingMode()); - - GraphicsLayer* scroll_layer = - inner_frame_view->LayoutViewport()->LayerForScrolling(); - ASSERT_TRUE(scroll_layer); - - cc::Layer* cc_scroll_layer = scroll_layer->CcLayer(); - ASSERT_TRUE(cc_scroll_layer->scrollable()); - ASSERT_TRUE(cc_scroll_layer->GetMainThreadScrollingReasons() & - MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects); - - // Remove fixed background-attachment should make the iframe - // scroll on cc. - auto* iframe_doc = ToHTMLIFrameElement(iframe)->contentDocument(); - iframe = iframe_doc->getElementById("scrollable"); - ASSERT_TRUE(iframe); - - iframe->removeAttribute("class"); - ForceFullCompositingUpdate(); - - layout_object = iframe->GetLayoutObject(); - ASSERT_TRUE(layout_object); - - scroll_layer = - layout_object->GetFrameView()->LayoutViewport()->LayerForScrolling(); - ASSERT_TRUE(scroll_layer); - - cc_scroll_layer = scroll_layer->CcLayer(); - ASSERT_TRUE(cc_scroll_layer->scrollable()); - ASSERT_FALSE(cc_scroll_layer->GetMainThreadScrollingReasons() & - MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects); - - // Force main frame to scroll on main thread. All its descendants - // should scroll on main thread as well. - Element* element = GetFrame()->GetDocument()->getElementById("scrollable"); - element->setAttribute( - "style", - "background-image: url('white-1x1.png'); background-attachment: fixed;", - ASSERT_NO_EXCEPTION); - - ForceFullCompositingUpdate(); - - layout_object = iframe->GetLayoutObject(); - ASSERT_TRUE(layout_object); - - scroll_layer = - layout_object->GetFrameView()->LayoutViewport()->LayerForScrolling(); - ASSERT_TRUE(scroll_layer); - - cc_scroll_layer = scroll_layer->CcLayer(); - ASSERT_TRUE(cc_scroll_layer->scrollable()); - ASSERT_TRUE(cc_scroll_layer->GetMainThreadScrollingReasons() & - MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects); -} - -// Upon resizing the content size, the main thread scrolling reason -// kHasNonLayerViewportConstrainedObject should be updated on all frames -TEST_P(ScrollingCoordinatorTest, - RecalculateMainThreadScrollingReasonsUponResize) { - GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(false); - RegisterMockedHttpURLLoad("has-non-layer-viewport-constrained-objects.html"); - NavigateTo(base_url_ + "has-non-layer-viewport-constrained-objects.html"); - ForceFullCompositingUpdate(); - - Element* element = GetFrame()->GetDocument()->getElementById("scrollable"); - ASSERT_TRUE(element); - - LayoutObject* layout_object = element->GetLayoutObject(); - ASSERT_TRUE(layout_object); - - // When the div becomes to scrollable it should scroll on main thread - element->setAttribute("style", - "overflow:scroll;height:2000px;will-change:transform;", - ASSERT_NO_EXCEPTION); - ForceFullCompositingUpdate(); - - layout_object = element->GetLayoutObject(); - ASSERT_TRUE(layout_object); - - GraphicsLayer* scroll_layer = - layout_object->GetFrameView()->LayoutViewport()->LayerForScrolling(); - ASSERT_TRUE(scroll_layer); - - cc::Layer* cc_scroll_layer = scroll_layer->CcLayer(); - ASSERT_TRUE(cc_scroll_layer->scrollable()); - ASSERT_TRUE( - cc_scroll_layer->GetMainThreadScrollingReasons() & - MainThreadScrollingReason::kHasNonLayerViewportConstrainedObjects); - - // The main thread scrolling reason should be reset upon the following change - element->setAttribute("style", - "overflow:scroll;height:200px;will-change:transform;", - ASSERT_NO_EXCEPTION); - ForceFullCompositingUpdate(); - - layout_object = element->GetLayoutObject(); - ASSERT_TRUE(layout_object); -} - -TEST_P(ScrollingCoordinatorTest, StickyTriggersMainThreadScroll) { - GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(false); - LoadHTML( - "<body style='height: 1200px'>" - "<div style='position: sticky; top: 0'>sticky</div>"); - ForceFullCompositingUpdate(); - ScrollableArea* viewport = GetFrame()->View()->LayoutViewport(); - cc::Layer* scroll_layer = viewport->LayerForScrolling()->CcLayer(); - ASSERT_EQ(MainThreadScrollingReason::kHasNonLayerViewportConstrainedObjects, - scroll_layer->GetMainThreadScrollingReasons()); -} - // LocalFrameView::FrameIsScrollableDidChange is used as a dirty bit and is // set to clean in ScrollingCoordinator::UpdateAfterPaint. This test ensures // that the dirty bit is set and unset properly. @@ -1659,227 +1393,6 @@ histogram_tester.ExpectTotalCount("Blink.ScrollingCoordinator.UpdateTime", 2); } -// TODO(pdr): Main thread scrolling reason tests should be moved out of -// scrolling_coordinator_test.cc because the reasons are calculated in -// paint_property_tree_builder.cc for BlinkGeneratedPropertyTrees. -class NonCompositedMainThreadScrollingReasonTest - : public ScrollingCoordinatorTest { - static const uint32_t kLCDTextRelatedReasons = - MainThreadScrollingReason::kHasOpacityAndLCDText | - MainThreadScrollingReason::kHasTransformAndLCDText | - MainThreadScrollingReason::kBackgroundNotOpaqueInRectAndLCDText | - MainThreadScrollingReason::kIsNotStackingContextAndLCDText; - - protected: - NonCompositedMainThreadScrollingReasonTest() { - RegisterMockedHttpURLLoad("two_scrollable_area.html"); - NavigateTo(base_url_ + "two_scrollable_area.html"); - } - void TestNonCompositedReasons(const std::string& target, - const uint32_t reason) { - GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(false); - Document* document = GetFrame()->GetDocument(); - Element* container = document->getElementById("scroller1"); - container->setAttribute("class", target.c_str(), ASSERT_NO_EXCEPTION); - ForceFullCompositingUpdate(); - - PaintLayerScrollableArea* scrollable_area = - ToLayoutBoxModelObject(container->GetLayoutObject()) - ->GetScrollableArea(); - ASSERT_TRUE(scrollable_area); - EXPECT_TRUE(scrollable_area->GetNonCompositedMainThreadScrollingReasons() & - reason); - - Element* container2 = document->getElementById("scroller2"); - PaintLayerScrollableArea* scrollable_area2 = - ToLayoutBoxModelObject(container2->GetLayoutObject()) - ->GetScrollableArea(); - ASSERT_TRUE(scrollable_area2); - // Different scrollable area should remain unaffected. - EXPECT_FALSE( - scrollable_area2->GetNonCompositedMainThreadScrollingReasons() & - reason); - - LocalFrameView* frame_view = GetFrame()->View(); - ASSERT_TRUE(frame_view); - EXPECT_FALSE(frame_view->GetMainThreadScrollingReasons() & reason); - - // Remove attribute from the scroller 1 would lead to scroll on impl. - container->removeAttribute("class"); - ForceFullCompositingUpdate(); - - EXPECT_FALSE(scrollable_area->GetNonCompositedMainThreadScrollingReasons() & - reason); - EXPECT_FALSE(frame_view->GetMainThreadScrollingReasons() & reason); - - // Add target attribute would again lead to scroll on main thread - container->setAttribute("class", target.c_str(), ASSERT_NO_EXCEPTION); - ForceFullCompositingUpdate(); - - EXPECT_TRUE(scrollable_area->GetNonCompositedMainThreadScrollingReasons() & - reason); - EXPECT_FALSE(frame_view->GetMainThreadScrollingReasons() & reason); - - if ((reason & kLCDTextRelatedReasons) && - !(reason & ~kLCDTextRelatedReasons)) { - GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(true); - ForceFullCompositingUpdate(); - EXPECT_FALSE( - scrollable_area->GetNonCompositedMainThreadScrollingReasons()); - EXPECT_FALSE(frame_view->GetMainThreadScrollingReasons()); - } - } -}; - -INSTANTIATE_TEST_CASE_P( - All, - NonCompositedMainThreadScrollingReasonTest, - ::testing::Values(kScrollingCoordinatorTestNoFlags, - kScrollingCoordinatorTestBlinkGenPropertyTrees, - kScrollingCoordinatorTestPaintTouchActionRects, - (kScrollingCoordinatorTestBlinkGenPropertyTrees | - kScrollingCoordinatorTestPaintTouchActionRects))); - -TEST_P(NonCompositedMainThreadScrollingReasonTest, TransparentTest) { - TestNonCompositedReasons("transparent", - MainThreadScrollingReason::kHasOpacityAndLCDText); -} - -TEST_P(NonCompositedMainThreadScrollingReasonTest, TransformTest) { - TestNonCompositedReasons("transform", - MainThreadScrollingReason::kHasTransformAndLCDText); -} - -TEST_P(NonCompositedMainThreadScrollingReasonTest, BackgroundNotOpaqueTest) { - TestNonCompositedReasons( - "background-not-opaque", - MainThreadScrollingReason::kBackgroundNotOpaqueInRectAndLCDText); -} - -TEST_P(NonCompositedMainThreadScrollingReasonTest, ClipTest) { - TestNonCompositedReasons("clip", - MainThreadScrollingReason::kHasClipRelatedProperty); -} - -TEST_P(NonCompositedMainThreadScrollingReasonTest, ClipPathTest) { - uint32_t clip_reason = MainThreadScrollingReason::kHasClipRelatedProperty; - GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(false); - Document* document = GetFrame()->GetDocument(); - // Test ancestor with ClipPath - Element* element = document->body(); - ASSERT_TRUE(element); - element->setAttribute(html_names::kStyleAttr, - "clip-path:circle(115px at 20px 20px);"); - Element* container = document->getElementById("scroller1"); - ASSERT_TRUE(container); - ForceFullCompositingUpdate(); - - PaintLayerScrollableArea* scrollable_area = - ToLayoutBoxModelObject(container->GetLayoutObject())->GetScrollableArea(); - ASSERT_TRUE(scrollable_area); - EXPECT_TRUE(scrollable_area->GetNonCompositedMainThreadScrollingReasons() & - clip_reason); - - LocalFrameView* frame_view = GetFrame()->View(); - ASSERT_TRUE(frame_view); - EXPECT_FALSE(frame_view->GetMainThreadScrollingReasons() & clip_reason); - - // Remove clip path from ancestor. - element->removeAttribute(html_names::kStyleAttr); - ForceFullCompositingUpdate(); - - EXPECT_FALSE(scrollable_area->GetNonCompositedMainThreadScrollingReasons() & - clip_reason); - EXPECT_FALSE(frame_view->GetMainThreadScrollingReasons() & clip_reason); - - // Test descendant with ClipPath - element = document->getElementById("content1"); - ASSERT_TRUE(element); - element->setAttribute(html_names::kStyleAttr, - "clip-path:circle(115px at 20px 20px);"); - ForceFullCompositingUpdate(); - EXPECT_TRUE(scrollable_area->GetNonCompositedMainThreadScrollingReasons() & - clip_reason); - EXPECT_FALSE(frame_view->GetMainThreadScrollingReasons() & clip_reason); - - // Remove clip path from descendant. - element->removeAttribute(html_names::kStyleAttr); - ForceFullCompositingUpdate(); - EXPECT_FALSE(scrollable_area->GetNonCompositedMainThreadScrollingReasons() & - clip_reason); - EXPECT_FALSE(frame_view->GetMainThreadScrollingReasons() & clip_reason); -} - -TEST_P(NonCompositedMainThreadScrollingReasonTest, LCDTextEnabledTest) { - TestNonCompositedReasons("transparent", - MainThreadScrollingReason::kHasOpacityAndLCDText); -} - -TEST_P(NonCompositedMainThreadScrollingReasonTest, BoxShadowTest) { - TestNonCompositedReasons( - "box-shadow", MainThreadScrollingReason::kHasBoxShadowFromNonRootLayer); -} - -TEST_P(NonCompositedMainThreadScrollingReasonTest, StackingContextTest) { - GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(false); - - Document* document = GetFrame()->GetDocument(); - Element* container = document->getElementById("scroller1"); - ASSERT_TRUE(container); - - ForceFullCompositingUpdate(); - - // If a scroller contains all its children, it's not a stacking context. - PaintLayerScrollableArea* scrollable_area = - ToLayoutBoxModelObject(container->GetLayoutObject())->GetScrollableArea(); - ASSERT_TRUE(scrollable_area); - EXPECT_TRUE(scrollable_area->GetNonCompositedMainThreadScrollingReasons() & - MainThreadScrollingReason::kIsNotStackingContextAndLCDText); - - GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(true); - ForceFullCompositingUpdate(); - EXPECT_FALSE(scrollable_area->GetNonCompositedMainThreadScrollingReasons() & - MainThreadScrollingReason::kIsNotStackingContextAndLCDText); - GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(false); - - // Adding "contain: paint" to force a stacking context leads to promotion. - container->setAttribute("style", "contain: paint", ASSERT_NO_EXCEPTION); - ForceFullCompositingUpdate(); - - EXPECT_FALSE(scrollable_area->GetNonCompositedMainThreadScrollingReasons()); -} - -TEST_P(NonCompositedMainThreadScrollingReasonTest, - CompositedWithLCDTextRelatedReasonsTest) { - // With "will-change:transform" we composite elements with - // LCDTextRelatedReasons only. For elements with other - // NonCompositedReasons, we don't create scrollingLayer for their - // CompositedLayerMapping therefore they don't get composited. - GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(false); - Document* document = GetFrame()->GetDocument(); - Element* container = document->getElementById("scroller1"); - ASSERT_TRUE(container); - container->setAttribute("class", "composited transparent", - ASSERT_NO_EXCEPTION); - ForceFullCompositingUpdate(); - - PaintLayerScrollableArea* scrollable_area = - ToLayoutBoxModelObject(container->GetLayoutObject())->GetScrollableArea(); - ASSERT_TRUE(scrollable_area); - EXPECT_FALSE(scrollable_area->GetNonCompositedMainThreadScrollingReasons()); - - Element* container2 = document->getElementById("scroller2"); - ASSERT_TRUE(container2); - container2->setAttribute("class", "composited border-radius", - ASSERT_NO_EXCEPTION); - ForceFullCompositingUpdate(); - PaintLayerScrollableArea* scrollable_area2 = - ToLayoutBoxModelObject(container2->GetLayoutObject()) - ->GetScrollableArea(); - ASSERT_TRUE(scrollable_area2); - ASSERT_TRUE(scrollable_area2->UsesCompositedScrolling()); -} - class ScrollingCoordinatorTestWithAcceleratedContext : public ScrollingCoordinatorTest { public:
diff --git a/third_party/blink/renderer/core/paint/box_painter_base.cc b/third_party/blink/renderer/core/paint/box_painter_base.cc index 4f5c3e5..37dc1aa 100644 --- a/third_party/blink/renderer/core/paint/box_painter_base.cc +++ b/third_party/blink/renderer/core/paint/box_painter_base.cc
@@ -580,6 +580,12 @@ return adjusted; } +bool ShouldApplyBlendOperation(const BoxPainterBase::FillLayerInfo& info, + const FillLayer& layer) { + // For a mask layer, don't use the operator if this is the bottom layer. + return !info.is_bottom_layer || layer.GetType() != EFillLayerType::kMask; +} + } // anonymous namespace LayoutRectOutsets BoxPainterBase::AdjustedBorderOutsets( @@ -612,7 +618,7 @@ const auto did_adjust_paint_rect = scrolled_paint_rect != rect; scoped_refptr<Image> image; - SkBlendMode composite_op = op; + SkBlendMode composite_op = SkBlendMode::kSrcOver; base::Optional<ScopedInterpolationQuality> interpolation_quality_context; if (info.should_paint_image) { geometry.Calculate(paint_info.PaintContainer(), paint_info.phase, @@ -627,10 +633,10 @@ if (bg_layer.MaskSourceType() == EMaskSourceType::kLuminance) context.SetColorFilter(kColorFilterLuminanceToAlpha); - // If op != SkBlendMode::kSrcOver, a mask is being painted. - SkBlendMode bg_op = WebCoreCompositeToSkiaComposite( - bg_layer.Composite(), bg_layer.GetBlendMode()); - composite_op = (op == SkBlendMode::kSrcOver) ? bg_op : op; + if (ShouldApplyBlendOperation(info, bg_layer)) { + composite_op = WebCoreCompositeToSkiaComposite(bg_layer.Composite(), + bg_layer.GetBlendMode()); + } } LayoutRectOutsets border = ComputeBorders();
diff --git a/third_party/blink/renderer/core/testing/internals.cc b/third_party/blink/renderer/core/testing/internals.cc index 59d5b156..b81df811 100644 --- a/third_party/blink/renderer/core/testing/internals.cc +++ b/third_party/blink/renderer/core/testing/internals.cc
@@ -363,6 +363,9 @@ return 0; } + if (!doc->GetLayoutView()) + return 0; + return doc->GetLayoutView()->HitTestCount(); } @@ -374,6 +377,9 @@ return 0; } + if (!doc->GetLayoutView()) + return 0; + return doc->GetLayoutView()->HitTestCacheHits(); }
diff --git a/third_party/blink/renderer/core/workers/worker_thread.cc b/third_party/blink/renderer/core/workers/worker_thread.cc index cde92a7..b4cf4bf 100644 --- a/third_party/blink/renderer/core/workers/worker_thread.cc +++ b/third_party/blink/renderer/core/workers/worker_thread.cc
@@ -160,7 +160,7 @@ const v8_inspector::V8StackTraceId& stack_id) { DCHECK_CALLED_ON_VALID_THREAD(parent_thread_checker_); PostCrossThreadTask( - *GetTaskRunner(TaskType::kInternalWorker), FROM_HERE, + *GetTaskRunner(TaskType::kDOMManipulation), FROM_HERE, CrossThreadBind(&WorkerThread::EvaluateClassicScriptOnWorkerThread, CrossThreadUnretained(this), script_url, source_code, WTF::Passed(std::move(cached_meta_data)), stack_id)); @@ -172,7 +172,7 @@ const v8_inspector::V8StackTraceId& stack_id) { DCHECK_CALLED_ON_VALID_THREAD(parent_thread_checker_); PostCrossThreadTask( - *GetTaskRunner(TaskType::kInternalWorker), FROM_HERE, + *GetTaskRunner(TaskType::kDOMManipulation), FROM_HERE, CrossThreadBind(&WorkerThread::ImportClassicScriptOnWorkerThread, CrossThreadUnretained(this), script_url, WTF::Passed(outside_settings_object->CopyData()), @@ -185,7 +185,7 @@ network::mojom::FetchCredentialsMode credentials_mode) { DCHECK_CALLED_ON_VALID_THREAD(parent_thread_checker_); PostCrossThreadTask( - *GetTaskRunner(TaskType::kInternalWorker), FROM_HERE, + *GetTaskRunner(TaskType::kDOMManipulation), FROM_HERE, CrossThreadBind(&WorkerThread::ImportModuleScriptOnWorkerThread, CrossThreadUnretained(this), script_url, WTF::Passed(outside_settings_object->CopyData()),
diff --git a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc index 28f5fa4d..f6778b5e 100644 --- a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc +++ b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc
@@ -262,24 +262,18 @@ DOMWrapperWorld& world = script_state->World(); v8::Isolate* isolate = script_state->GetIsolate(); - XMLHttpRequest* xml_http_request = - world.IsIsolatedWorld() - ? MakeGarbageCollected<XMLHttpRequest>( - context, isolate, true, world.IsolatedWorldSecurityOrigin()) - : MakeGarbageCollected<XMLHttpRequest>(context, isolate, false, - nullptr); - xml_http_request->PauseIfNeeded(); - return xml_http_request; + return world.IsIsolatedWorld() + ? MakeGarbageCollected<XMLHttpRequest>( + context, isolate, true, world.IsolatedWorldSecurityOrigin()) + : MakeGarbageCollected<XMLHttpRequest>(context, isolate, false, + nullptr); } XMLHttpRequest* XMLHttpRequest::Create(ExecutionContext* context) { v8::Isolate* isolate = context->GetIsolate(); CHECK(isolate); - XMLHttpRequest* xml_http_request = - MakeGarbageCollected<XMLHttpRequest>(context, isolate, false, nullptr); - xml_http_request->PauseIfNeeded(); - return xml_http_request; + return MakeGarbageCollected<XMLHttpRequest>(context, isolate, false, nullptr); } XMLHttpRequest::XMLHttpRequest( @@ -287,7 +281,7 @@ v8::Isolate* isolate, bool is_isolated_world, scoped_refptr<SecurityOrigin> isolated_world_security_origin) - : PausableObject(context), + : ContextLifecycleObserver(context), progress_event_throttle_( XMLHttpRequestProgressEventThrottle::Create(this)), isolate_(isolate), @@ -1965,14 +1959,6 @@ expected_length); } -void XMLHttpRequest::Pause() { - progress_event_throttle_->Pause(); -} - -void XMLHttpRequest::Unpause() { - progress_event_throttle_->Unpause(); -} - void XMLHttpRequest::ContextDestroyed(ExecutionContext*) { Dispose(); @@ -1998,7 +1984,7 @@ } ExecutionContext* XMLHttpRequest::GetExecutionContext() const { - return PausableObject::GetExecutionContext(); + return ContextLifecycleObserver::GetExecutionContext(); } void XMLHttpRequest::ReportMemoryUsageToV8() { @@ -2031,7 +2017,7 @@ XMLHttpRequestEventTarget::Trace(visitor); ThreadableLoaderClient::Trace(visitor); DocumentParserClient::Trace(visitor); - PausableObject::Trace(visitor); + ContextLifecycleObserver::Trace(visitor); } std::ostream& operator<<(std::ostream& ostream, const XMLHttpRequest* xhr) {
diff --git a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.h b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.h index 813044e..ccdcff2 100644 --- a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.h +++ b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.h
@@ -28,8 +28,8 @@ #include "base/memory/scoped_refptr.h" #include "services/network/public/mojom/url_loader_factory.mojom-blink.h" #include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h" +#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h" #include "third_party/blink/renderer/core/dom/document_parser_client.h" -#include "third_party/blink/renderer/core/dom/pausable_object.h" #include "third_party/blink/renderer/core/loader/threadable_loader_client.h" #include "third_party/blink/renderer/core/xmlhttprequest/xml_http_request_event_target.h" #include "third_party/blink/renderer/core/xmlhttprequest/xml_http_request_progress_event_throttle.h" @@ -73,7 +73,7 @@ public ThreadableLoaderClient, public DocumentParserClient, public ActiveScriptWrappable<XMLHttpRequest>, - public PausableObject { + public ContextLifecycleObserver { DEFINE_WRAPPERTYPEINFO(); USING_GARBAGE_COLLECTED_MIXIN(XMLHttpRequest); @@ -105,11 +105,9 @@ kResponseTypeArrayBuffer, }; - // PausableObject + // ContextLifecycleObserver void ContextDestroyed(ExecutionContext*) override; ExecutionContext* GetExecutionContext() const override; - void Pause() override; - void Unpause() override; // ScriptWrappable bool HasPendingActivity() const final;
diff --git a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request_progress_event_throttle.cc b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request_progress_event_throttle.cc index ca7c69f..6655c12 100644 --- a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request_progress_event_throttle.cc +++ b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request_progress_event_throttle.cc
@@ -172,20 +172,6 @@ StartOneShot(kMinimumProgressEventDispatchingInterval, FROM_HERE); } -void XMLHttpRequestProgressEventThrottle::Pause() { - Stop(); -} - -void XMLHttpRequestProgressEventThrottle::Unpause() { - if (!deferred_.IsSet()) - return; - - // Do not dispatch events inline here, since ExecutionContext is iterating - // over the list of PausableObjects to resume them, and any activated JS - // event-handler could insert new PausableObjects to the list. - StartOneShot(TimeDelta(), FROM_HERE); -} - void XMLHttpRequestProgressEventThrottle::Trace(blink::Visitor* visitor) { visitor->Trace(target_); }
diff --git a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request_progress_event_throttle.h b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request_progress_event_throttle.h index d96f805..d3c13af 100644 --- a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request_progress_event_throttle.h +++ b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request_progress_event_throttle.h
@@ -85,9 +85,6 @@ // depending on the value of the ProgressEventAction argument. void DispatchReadyStateChangeEvent(Event*, DeferredEventAction); - void Pause(); - void Unpause(); - // Need to promptly stop this timer when it is deemed finalizable. EAGERLY_FINALIZE(); void Trace(blink::Visitor*);
diff --git a/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineProfileTree.js b/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineProfileTree.js index 47af9d6..fa6e010d9 100644 --- a/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineProfileTree.js +++ b/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineProfileTree.js
@@ -345,7 +345,7 @@ const id = TimelineModel.TimelineProfileTree._eventId(e); let node = nodeById.get(id); if (!node) { - node = new TimelineModel.TimelineProfileTree.BottomUpNode(root, id, e, true, root); + node = new TimelineModel.TimelineProfileTree.BottomUpNode(root, id, e, false, root); nodeById.set(id, node); } node.selfTime += selfTimeStack.pop(); @@ -353,6 +353,8 @@ node.totalTime += totalTimeById.get(id); totalTimeById.delete(id); } + if (firstNodeStack.length) + node.setHasChildren(); } this.selfTime = selfTimeStack.pop(); @@ -447,6 +449,10 @@ this._hasChildren = hasChildren; } + setHasChildren() { + this._hasChildren = true; + } + /** * @override * @return {boolean}
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth.cc b/third_party/blink/renderer/modules/bluetooth/bluetooth.cc index 37e6ce8..566c3f6 100644 --- a/third_party/blink/renderer/modules/bluetooth/bluetooth.cc +++ b/third_party/blink/renderer/modules/bluetooth/bluetooth.cc
@@ -182,7 +182,9 @@ if (!service_) { LocalFrame* frame = doc.GetFrame(); if (frame) { - frame->GetInterfaceProvider().GetInterface(mojo::MakeRequest(&service_)); + // See https://bit.ly/2S0zRAS for task types. + frame->GetInterfaceProvider().GetInterface(mojo::MakeRequest( + &service_, context->GetTaskRunner(TaskType::kMiscPlatformAPI))); } }
diff --git a/third_party/blink/renderer/modules/donottrack/navigator_do_not_track.idl b/third_party/blink/renderer/modules/donottrack/navigator_do_not_track.idl index ef59beb..d5e33be 100644 --- a/third_party/blink/renderer/modules/donottrack/navigator_do_not_track.idl +++ b/third_party/blink/renderer/modules/donottrack/navigator_do_not_track.idl
@@ -31,5 +31,5 @@ [ ImplementedAs=NavigatorDoNotTrack ] partial interface Navigator { - readonly attribute DOMString? doNotTrack; + [HighEntropy, MeasureAs=NavigatorDoNotTrack] readonly attribute DOMString? doNotTrack; };
diff --git a/third_party/blink/renderer/modules/geolocation/geolocation.cc b/third_party/blink/renderer/modules/geolocation/geolocation.cc index dff776ce..cdc7edc 100644 --- a/third_party/blink/renderer/modules/geolocation/geolocation.cc +++ b/third_party/blink/renderer/modules/geolocation/geolocation.cc
@@ -457,10 +457,13 @@ if (geolocation_) return; + // See https://bit.ly/2S0zRAS for task types. + scoped_refptr<base::SingleThreadTaskRunner> task_runner = + GetExecutionContext()->GetTaskRunner(TaskType::kMiscPlatformAPI); InterfaceInvalidator* invalidator = GetExecutionContext()->GetInterfaceInvalidator(); GetFrame()->GetInterfaceProvider().GetInterface(&geolocation_service_, - invalidator); + invalidator, task_runner); geolocation_service_->CreateGeolocation( MakeRequest(&geolocation_, invalidator), LocalFrame::HasTransientUserActivation(GetFrame()));
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_factory_impl.cc b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_factory_impl.cc index 035cd23d..45baf4c 100644 --- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_factory_impl.cc +++ b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_factory_impl.cc
@@ -13,6 +13,11 @@ namespace { +// QUIC's default is 100. Setting this value to 10000 allows room for QUIC to +// not refuse new incoming streams in the case that an application wants to send +// a small chunk of data per stream (and immediately close) unreliably. +uint32_t kMaxIncomingDynamicStreams = 10000; + // The P2PQuicPacketWriter is a private helper class that implements the // QuicPacketWriter using a P2PQuicPacketTransport. This allows us to // connect our own packet transport for writing into the QuicConnection. @@ -190,6 +195,7 @@ // QUIC configurations for the session are specified here. quic::QuicConfig quic_config; + quic_config.SetMaxIncomingDynamicStreamsToSend(kMaxIncomingDynamicStreams); return std::make_unique<P2PQuicTransportImpl>( delegate, packet_transport, std::move(config), std::move(helper), std::move(quic_connection), quic_config, clock_);
diff --git a/third_party/blink/renderer/modules/plugins/navigator_plugins.idl b/third_party/blink/renderer/modules/plugins/navigator_plugins.idl index 8c2ee1d..767905e 100644 --- a/third_party/blink/renderer/modules/plugins/navigator_plugins.idl +++ b/third_party/blink/renderer/modules/plugins/navigator_plugins.idl
@@ -6,7 +6,7 @@ [ ImplementedAs=NavigatorPlugins ] partial interface Navigator { - readonly attribute PluginArray plugins; - readonly attribute MimeTypeArray mimeTypes; + [HighEntropy, MeasureAs=NavigatorPlugins] readonly attribute PluginArray plugins; + [HighEntropy, MeasureAs=NavigatorMimeTypes] readonly attribute MimeTypeArray mimeTypes; boolean javaEnabled(); };
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn index a14d15f0..54fdfea 100644 --- a/third_party/blink/renderer/platform/BUILD.gn +++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -1091,7 +1091,6 @@ "graphics/picture_snapshot.h", "graphics/placeholder_image.cc", "graphics/placeholder_image.h", - "graphics/platform_paint_worklet_input.h", "graphics/profiling_canvas.cc", "graphics/profiling_canvas.h", "graphics/replaying_canvas.cc",
diff --git a/third_party/blink/renderer/platform/graphics/paint/README.md b/third_party/blink/renderer/platform/graphics/paint/README.md index 1cc5921..2f2163bc 100644 --- a/third_party/blink/renderer/platform/graphics/paint/README.md +++ b/third_party/blink/renderer/platform/graphics/paint/README.md
@@ -10,10 +10,10 @@ CompositeAfterPaint represents its paint artifact not as a flat display list, but as a list of drawings, and a list of paint chunks, stored together. -This document explains the CAP world as it develops, not the SPv1 world it -replaces. +This document explains the CompositeAfterPaint (CAP) world as it develops, not +the SPv1 world it replaces. -[paint-team-site]: https://www.chromium.org/developers/paint-team +[paint-team-site]: https://www.chromium.org/teams/paint-team ## Paint artifact @@ -142,7 +142,7 @@ *** note It is illegal for there to be two display items with the same ID in a display item list, except for display items that are marked uncacheable -(see [DisplayItemCacheSkipper](DisplayItemCacheSkipper.h)). +(see [DisplayItemCacheSkipper](display_item_cache_skipper.h)). *** Generally, clients of this code should use stack-allocated recorder classes to @@ -150,19 +150,19 @@ ### Standalone display items -#### [DrawingDisplayItem](DrawingDisplayItem.h) +#### [DrawingDisplayItem](drawing_display_item.h) Holds a `PaintRecord` which contains the paint operations required to draw some atom of content. -#### [ForeignLayerDisplayItem](ForeignLayerDisplayItem.h) +#### [ForeignLayerDisplayItem](foreign_layer_display_item.h) Draws an atom of content, but using a `cc::Layer` produced by some agent outside of the normal Blink paint system (for example, a plugin). Since they always map to a `cc::Layer`, they are always the only display item in their paint chunk, and are ineligible for squashing with other layers. -#### [ScrollHitTestDisplayItem](ScrollHitTestDisplayItem.h) +#### [ScrollHitTestDisplayItem](scroll_hit_test_display_item.h) Placeholder for creating a cc::Layer for scrolling in paint order. Hit testing in the compositor requires both property trees (scroll nodes) and a scrollable @@ -199,9 +199,9 @@ ## Paint artifact compositor -The [`PaintArtifactCompositor`](paint_artifact_compositor.h) is responsible for -consuming the `PaintArtifact` produced by the `PaintController`, and converting -it into a form suitable for the compositor to consume. +[`PaintArtifactCompositor`](../compositing/paint_artifact_compositor.h) is +responsible for consuming the `PaintArtifact` produced by the `PaintController`, +and converting it into a form suitable for the compositor to consume. At present, `PaintArtifactCompositor` creates a cc layer tree, with one layer for each paint chunk. In the future, it is expected that we will use heuristics
diff --git a/third_party/blink/renderer/platform/graphics/platform_paint_worklet_input.h b/third_party/blink/renderer/platform/graphics/platform_paint_worklet_input.h deleted file mode 100644 index 05d0c4d..0000000 --- a/third_party/blink/renderer/platform/graphics/platform_paint_worklet_input.h +++ /dev/null
@@ -1,41 +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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PLATFORM_PAINT_WORKLET_INPUT_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PLATFORM_PAINT_WORKLET_INPUT_H_ - -#include "cc/paint/paint_worklet_input.h" - -namespace blink { - -class PLATFORM_EXPORT PlatformPaintWorkletInput : public cc::PaintWorkletInput { - public: - PlatformPaintWorkletInput(const std::string& name, - const FloatSize& container_size, - float effective_zoom) - : name_(name), - container_size_(container_size), - effective_zoom_(effective_zoom) {} - - ~PlatformPaintWorkletInput() override = default; - - // PaintWorkletInput implementation - gfx::SizeF GetSize() const override { - return gfx::SizeF(container_size_.Width(), container_size_.Height()); - } - - const std::string& Name() const { return name_; } - const FloatSize& ContainerSize() const { return container_size_; } - float EffectiveZoom() const { return effective_zoom_; } - - private: - std::string name_; - FloatSize container_size_; - float effective_zoom_; - // TODO(crbug.com/895579): add a cross thread style map. -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHIC_PLATFORM_PAINT_WORKLET_INPUT_H_
diff --git a/third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h b/third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h index a644fbe..28a4284 100644 --- a/third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h +++ b/third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h
@@ -73,34 +73,6 @@ // the top level frame, i.e. a main frame. virtual FrameType GetFrameType() const = 0; - // The tasks runners below are listed in increasing QoS order. - // - throttleable task queue. Designed for custom user-provided javascript - // tasks. Lowest guarantees. Can be paused, blocked during user gesture, - // throttled when backgrounded or stopped completely after some time in - // background. - // - deferrable task queue. These tasks can be deferred for a small period - // (several seconds) when high-priority work is anticipated. These tasks - // can be paused. - // - pausable task queue. Default queue for high-priority javascript tasks. - // They can be paused according to the spec during javascript alert - // dialogs, printing windows and devtools debugging. Otherwise scheduler - // does not tamper with their execution. - // - unpausable task queue. Should be used for control tasks which should - // run when the context is paused. Usage should be extremely rare. - // Please consult scheduler-dev@ before using it. Running javascript - // on it is strictly verboten and can lead to hard-to-diagnose errors. - // - // - // These queues below are separate due to special handling for their - // priorities. - // - loading task queue. Similar to deferrable task queue. Throttling might - // be considered in the future. - // - loading control task queue. Loading task queue with increased priority - // to run small loading tasks which schedule other loading tasks. - - // Note: old-style timer task runner corresponds to throttleable task runner - // and unthrottled task runner corresponds to pausable task runner. - // Returns a task runner that is suitable with the given task type. virtual scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner( TaskType) = 0;
diff --git a/third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h b/third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h index 528963ce..738f21d8 100644 --- a/third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h +++ b/third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h
@@ -28,6 +28,19 @@ WorkerSchedulerProxy* proxy); ~WorkerScheduler() override; + class PLATFORM_EXPORT PauseHandle { + public: + PauseHandle(base::WeakPtr<WorkerScheduler>); + ~PauseHandle(); + + private: + base::WeakPtr<WorkerScheduler> scheduler_; + + DISALLOW_COPY_AND_ASSIGN(PauseHandle); + }; + + std::unique_ptr<PauseHandle> Pause() WARN_UNUSED_RESULT; + std::unique_ptr<ActiveConnectionHandle> OnActiveConnectionCreated() override; // Unregisters the task queues and cancels tasks in them. @@ -49,25 +62,39 @@ protected: scoped_refptr<NonMainThreadTaskQueue> ThrottleableTaskQueue(); - scoped_refptr<NonMainThreadTaskQueue> UnthrottleableTaskQueue(); + scoped_refptr<NonMainThreadTaskQueue> UnpausableTaskQueue(); + scoped_refptr<NonMainThreadTaskQueue> PausableTaskQueue(); private: void SetUpThrottling(); + void PauseImpl(); + void ResumeImpl(); base::WeakPtr<WorkerScheduler> GetWeakPtr(); + // The tasks runners below are listed in increasing QoS order. + // - throttleable task queue. Designed for custom user-provided javascript + // tasks. Lowest guarantees. Can be paused, blocked during user gesture, + // throttled when backgrounded or stopped completely after some time in + // background. + // - pausable task queue. Default queue for high-priority javascript tasks. + // They can be paused according to the spec during devtools debugging. + // Otherwise scheduler does not tamper with their execution. + // - unpausable task queue. Should be used for control tasks which should + // run when the context is paused. Usage should be extremely rare. + // Please consult scheduler-dev@ before using it. Running javascript + // on it is strictly verboten and can lead to hard-to-diagnose errors. scoped_refptr<NonMainThreadTaskQueue> throttleable_task_queue_; - scoped_refptr<NonMainThreadTaskQueue> unthrottleable_task_queue_; + scoped_refptr<NonMainThreadTaskQueue> pausable_task_queue_; + scoped_refptr<NonMainThreadTaskQueue> unpausable_task_queue_; SchedulingLifecycleState lifecycle_state_ = SchedulingLifecycleState::kNotThrottled; WorkerThreadScheduler* thread_scheduler_; // NOT OWNED -#if DCHECK_IS_ON() bool is_disposed_ = false; -#endif - + uint32_t paused_count_ = 0; base::WeakPtrFactory<WorkerScheduler> weak_factory_; };
diff --git a/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.cc b/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.cc index 2ba5085..ef5a635 100644 --- a/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.cc +++ b/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.cc
@@ -35,5 +35,11 @@ } } +void NonMainThreadTaskQueue::SetPaused(bool paused) { + if (!task_queue_voter_) + task_queue_voter_ = CreateQueueEnabledVoter(); + task_queue_voter_->SetQueueEnabled(!paused); +} + } // namespace scheduler } // namespace blink
diff --git a/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.h b/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.h index e801ecd6f..93cf85f 100644 --- a/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.h +++ b/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.h
@@ -33,7 +33,11 @@ return TaskQueue::CreateTaskRunner(static_cast<int>(task_type)); } + void SetPaused(bool paused); + private: + std::unique_ptr<QueueEnabledVoter> task_queue_voter_; + // Not owned. NonMainThreadSchedulerImpl* non_main_thread_scheduler_; };
diff --git a/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc b/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc index 2200c07..b4dfcaa 100644 --- a/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc +++ b/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc
@@ -12,12 +12,25 @@ namespace blink { namespace scheduler { +WorkerScheduler::PauseHandle::PauseHandle( + base::WeakPtr<WorkerScheduler> scheduler) + : scheduler_(scheduler) { + scheduler_->PauseImpl(); +} + +WorkerScheduler::PauseHandle::~PauseHandle() { + if (scheduler_) + scheduler_->ResumeImpl(); +} + WorkerScheduler::WorkerScheduler(WorkerThreadScheduler* worker_thread_scheduler, WorkerSchedulerProxy* proxy) : throttleable_task_queue_( worker_thread_scheduler->CreateTaskQueue("worker_throttleable_tq")), - unthrottleable_task_queue_( - worker_thread_scheduler->CreateTaskQueue("worker_unthrottleable_tq")), + pausable_task_queue_( + worker_thread_scheduler->CreateTaskQueue("worker_pausable_tq")), + unpausable_task_queue_( + worker_thread_scheduler->CreateTaskQueue("worker_unpausable_tq")), thread_scheduler_(worker_thread_scheduler), weak_factory_(this) { thread_scheduler_->RegisterWorkerScheduler(this); @@ -34,9 +47,33 @@ } WorkerScheduler::~WorkerScheduler() { -#if DCHECK_IS_ON() DCHECK(is_disposed_); -#endif + DCHECK_EQ(0u, paused_count_); +} + +std::unique_ptr<WorkerScheduler::PauseHandle> WorkerScheduler::Pause() { + thread_scheduler_->helper()->CheckOnValidThread(); + if (is_disposed_) + return nullptr; + return std::make_unique<PauseHandle>(GetWeakPtr()); +} + +void WorkerScheduler::PauseImpl() { + thread_scheduler_->helper()->CheckOnValidThread(); + paused_count_++; + if (paused_count_ == 1) { + throttleable_task_queue_->SetPaused(true); + pausable_task_queue_->SetPaused(true); + } +} + +void WorkerScheduler::ResumeImpl() { + thread_scheduler_->helper()->CheckOnValidThread(); + paused_count_--; + if (paused_count_ == 0 && !is_disposed_) { + throttleable_task_queue_->SetPaused(false); + pausable_task_queue_->SetPaused(false); + } } void WorkerScheduler::SetUpThrottling() { @@ -78,12 +115,11 @@ thread_scheduler_->UnregisterWorkerScheduler(this); - unthrottleable_task_queue_->ShutdownTaskQueue(); + unpausable_task_queue_->ShutdownTaskQueue(); + pausable_task_queue_->ShutdownTaskQueue(); throttleable_task_queue_->ShutdownTaskQueue(); -#if DCHECK_IS_ON() is_disposed_ = true; -#endif } scoped_refptr<base::SingleThreadTaskRunner> WorkerScheduler::GetTaskRunner( @@ -93,7 +129,6 @@ case TaskType::kPostedMessage: case TaskType::kWorkerAnimation: return throttleable_task_queue_->CreateTaskRunner(type); - case TaskType::kDeprecatedNone: case TaskType::kDOMManipulation: case TaskType::kUserInteraction: case TaskType::kNetworking: @@ -121,21 +156,27 @@ case TaskType::kPermission: case TaskType::kInternalDefault: case TaskType::kInternalLoading: - case TaskType::kInternalTest: case TaskType::kInternalWebCrypto: case TaskType::kInternalIndexedDB: case TaskType::kInternalMedia: case TaskType::kInternalMediaRealTime: - case TaskType::kInternalIPC: case TaskType::kInternalUserInteraction: - case TaskType::kInternalInspector: - case TaskType::kInternalWorker: case TaskType::kInternalIntersectionObserver: // UnthrottledTaskRunner is generally discouraged in future. // TODO(nhiroki): Identify which tasks can be throttled / suspendable and // move them into other task runners. See also comments in // Get(LocalFrame). (https://crbug.com/670534) - return unthrottleable_task_queue_->CreateTaskRunner(type); + return pausable_task_queue_->CreateTaskRunner(type); + case TaskType::kDeprecatedNone: + case TaskType::kInternalIPC: + case TaskType::kInternalInspector: + case TaskType::kInternalWorker: + case TaskType::kInternalTest: + // UnthrottledTaskRunner is generally discouraged in future. + // TODO(nhiroki): Identify which tasks can be throttled / suspendable and + // move them into other task runners. See also comments in + // Get(LocalFrame). (https://crbug.com/670534) + return unpausable_task_queue_->CreateTaskRunner(type); case TaskType::kMainThreadTaskQueueV8: case TaskType::kMainThreadTaskQueueCompositor: case TaskType::kMainThreadTaskQueueDefault: @@ -178,9 +219,12 @@ NotifyLifecycleObservers(); } -scoped_refptr<NonMainThreadTaskQueue> -WorkerScheduler::UnthrottleableTaskQueue() { - return unthrottleable_task_queue_.get(); +scoped_refptr<NonMainThreadTaskQueue> WorkerScheduler::UnpausableTaskQueue() { + return unpausable_task_queue_.get(); +} + +scoped_refptr<NonMainThreadTaskQueue> WorkerScheduler::PausableTaskQueue() { + return pausable_task_queue_.get(); } scoped_refptr<NonMainThreadTaskQueue> WorkerScheduler::ThrottleableTaskQueue() {
diff --git a/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_unittest.cc b/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_unittest.cc index 0f12381b..5b65ecb 100644 --- a/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_unittest.cc +++ b/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_unittest.cc
@@ -71,8 +71,8 @@ WorkerThreadSchedulerForTest* thread_scheduler) : WorkerScheduler(thread_scheduler, nullptr) {} - using WorkerScheduler::UnthrottleableTaskQueue; using WorkerScheduler::ThrottleableTaskQueue; + using WorkerScheduler::UnpausableTaskQueue; }; class WorkerSchedulerTest : public testing::Test { @@ -113,10 +113,10 @@ // Helper for posting a task. void PostTestTask(std::vector<std::string>* run_order, - const std::string& task_descriptor) { - worker_scheduler_->GetTaskRunner(TaskType::kInternalTest) - ->PostTask(FROM_HERE, - WTF::Bind(&AppendToVectorTestTask, + const std::string& task_descriptor, + TaskType task_type) { + worker_scheduler_->GetTaskRunner(task_type)->PostTask( + FROM_HERE, WTF::Bind(&AppendToVectorTestTask, WTF::Unretained(run_order), task_descriptor)); } @@ -131,18 +131,18 @@ TEST_F(WorkerSchedulerTest, TestPostTasks) { std::vector<std::string> run_order; - PostTestTask(&run_order, "T1"); - PostTestTask(&run_order, "T2"); + PostTestTask(&run_order, "T1", TaskType::kInternalTest); + PostTestTask(&run_order, "T2", TaskType::kInternalTest); RunUntilIdle(); - PostTestTask(&run_order, "T3"); + PostTestTask(&run_order, "T3", TaskType::kInternalTest); RunUntilIdle(); EXPECT_THAT(run_order, testing::ElementsAre("T1", "T2", "T3")); // Tasks should not run after the scheduler is disposed of. worker_scheduler_->Dispose(); run_order.clear(); - PostTestTask(&run_order, "T4"); - PostTestTask(&run_order, "T5"); + PostTestTask(&run_order, "T4", TaskType::kInternalTest); + PostTestTask(&run_order, "T5", TaskType::kInternalTest); RunUntilIdle(); EXPECT_TRUE(run_order.empty()); @@ -268,6 +268,40 @@ base::TimeTicks() + base::TimeDelta::FromSeconds(41))); } +TEST_F(WorkerSchedulerTest, PausableTasks) { + std::vector<std::string> run_order; + auto pause_handle = worker_scheduler_->Pause(); + // Tests interlacing pausable, throttable and unpausable tasks and + // ensures that the pausable & throttable tasks don't run when paused. + // Throttable + PostTestTask(&run_order, "T1", TaskType::kJavascriptTimer); + // Pausable + PostTestTask(&run_order, "T2", TaskType::kNetworking); + // Unpausable + PostTestTask(&run_order, "T3", TaskType::kInternalTest); + RunUntilIdle(); + EXPECT_THAT(run_order, testing::ElementsAre("T3")); + pause_handle.reset(); + RunUntilIdle(); + + EXPECT_THAT(run_order, testing::ElementsAre("T3", "T1", "T2")); +} + +TEST_F(WorkerSchedulerTest, NestedPauseHandlesTasks) { + std::vector<std::string> run_order; + auto pause_handle = worker_scheduler_->Pause(); + { + auto pause_handle2 = worker_scheduler_->Pause(); + PostTestTask(&run_order, "T1", TaskType::kJavascriptTimer); + PostTestTask(&run_order, "T2", TaskType::kNetworking); + } + RunUntilIdle(); + EXPECT_EQ(0u, run_order.size()); + pause_handle.reset(); + RunUntilIdle(); + EXPECT_THAT(run_order, testing::ElementsAre("T1", "T2")); +} + } // namespace worker_scheduler_unittest } // namespace scheduler } // namespace blink
diff --git a/third_party/blink/tools/blinkpy/common/net/web.py b/third_party/blink/tools/blinkpy/common/net/web.py index cd722893..c357305 100644 --- a/third_party/blink/tools/blinkpy/common/net/web.py +++ b/third_party/blink/tools/blinkpy/common/net/web.py
@@ -33,20 +33,20 @@ class Web(object): - class HTTPRedirectHandler2(urllib2.HTTPRedirectHandler): # pylint:disable=no-init + class _HTTPRedirectHandler2(urllib2.HTTPRedirectHandler): # pylint:disable=no-init """A subclass of HTTPRedirectHandler to support 308 Permanent Redirect.""" def http_error_308(self, req, fp, code, msg, headers): # pylint:disable=unused-argument # We have to override the code to 301 (Moved Permanently); # otherwise, HTTPRedirectHandler will throw a HTTPError. - self.http_error_301(req, fp, 301, msg, headers) + return self.http_error_301(req, fp, 301, msg, headers) def get_binary(self, url, return_none_on_404=False): return NetworkTransaction(return_none_on_404=return_none_on_404).run( lambda: self.request('GET', url).read()) def request(self, method, url, data=None, headers=None): - opener = urllib2.build_opener(Web.HTTPRedirectHandler2) + opener = urllib2.build_opener(Web._HTTPRedirectHandler2) request = urllib2.Request(url=url, data=data) request.get_method = lambda: method
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG index 5dacb6e..cec20655 100644 --- a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG +++ b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG
@@ -301,7 +301,7 @@ crbug.com/591099 virtual/android/rootscroller/set-root-scroller.html [ Pass ] crbug.com/591099 virtual/android/rootscroller/set-rootscroller-before-load.html [ Pass ] crbug.com/591099 virtual/android/url-bar/bottom-and-top-fixed-sticks-to-top.html [ Failure ] -crbug.com/591099 virtual/composite-after-paint/paint/background/scrolling-background-with-negative-z-child.html [ Failure ] +crbug.com/916511 virtual/composite-after-paint/paint/background/scrolling-background-with-negative-z-child.html [ Failure ] crbug.com/591099 virtual/composite-after-paint/paint/invalidation/box/margin.html [ Failure Pass ] crbug.com/591099 virtual/display-lock/display-lock/lock-before-append/measure-and-remove.html [ Failure ] crbug.com/591099 virtual/display-lock/display-lock/lock-before-append/measure-forced-layout.html [ Failure ]
diff --git a/third_party/blink/web_tests/SlowTests b/third_party/blink/web_tests/SlowTests index 92e466b..6c2e7f7 100644 --- a/third_party/blink/web_tests/SlowTests +++ b/third_party/blink/web_tests/SlowTests
@@ -1575,3 +1575,8 @@ crbug.com/893015 [ Linux ] virtual/streaming-preload/http/tests/fetch/chromium/response-text-gc-crash.html [ Slow ] crbug.com/912364 [ Mac ] virtual/user-activation-v2/fast/events/no-fake-mousemove.html [ Slow ] +crbug.com/914981 [ Mac ] media/controls/overflow-menu-pointer-selection.html [ Slow ] +crbug.com/914981 [ Mac ] virtual/fractional_scrolling/fast/scrolling/overflow-scrollability.html [ Slow ] +crbug.com/914981 [ Mac ] virtual/mouseevent_fractional/fast/events/no-fake-mousemove.html [ Slow ] +crbug.com/914981 [ Mac ] virtual/new-remote-playback-pipeline/media/controls/overflow-menu-pointer-selection.html [ Slow ] +crbug.com/914981 [ Mac ] virtual/video-surface-layer/media/controls/overflow-menu-pointer-selection.html [ Slow ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 337d026..a273619 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -4885,6 +4885,7 @@ # Does not work on Mac crbug.com/793771 [ Mac ] media/controls/modern/scrubbing.html [ Skip ] crbug.com/793771 [ Mac ] virtual/new-remote-playback-pipeline/media/controls/modern/scrubbing.html [ Skip ] +crbug.com/914981 [ Mac ] virtual/video-surface-layer/media/controls/modern/scrubbing.html [ Skip ] # Different paths may have different anti-aliasing pixels 2018-02-21 skbug.com/7641 external/wpt/css/css-paint-api/paint2d-paths.https.html [ Failure Pass ]
diff --git a/third_party/blink/web_tests/css3/masking/mask-composite-source-in-single-layer-expected.html b/third_party/blink/web_tests/css3/masking/mask-composite-source-in-single-layer-expected.html new file mode 100644 index 0000000..f718ea6 --- /dev/null +++ b/third_party/blink/web_tests/css3/masking/mask-composite-source-in-single-layer-expected.html
@@ -0,0 +1,2 @@ +<!DOCTYPE html> +<div style="width: 100px; height: 100px; background-color: green"></div>
diff --git a/third_party/blink/web_tests/css3/masking/mask-composite-source-in-single-layer.html b/third_party/blink/web_tests/css3/masking/mask-composite-source-in-single-layer.html new file mode 100644 index 0000000..b856650 --- /dev/null +++ b/third_party/blink/web_tests/css3/masking/mask-composite-source-in-single-layer.html
@@ -0,0 +1,11 @@ +<!DOCTYPE html> +<style> +#target { + width: 100px; + height: 100px; + background-color: green; + -webkit-mask-image: linear-gradient(white, white); + -webkit-mask-composite: source-in; +} +</style> +<div id="target"></div>
diff --git a/third_party/blink/web_tests/dom/legacy_dom_conformance/xhtml/level2/html/HTMLFormElement10.js b/third_party/blink/web_tests/dom/legacy_dom_conformance/xhtml/level2/html/HTMLFormElement10.js index b5f0fca..dd6ab120 100644 --- a/third_party/blink/web_tests/dom/legacy_dom_conformance/xhtml/level2/html/HTMLFormElement10.js +++ b/third_party/blink/web_tests/dom/legacy_dom_conformance/xhtml/level2/html/HTMLFormElement10.js
@@ -90,7 +90,7 @@ assertSize("Asize",1,nodeList); testNode = nodeList.item(0); testNode.submit(); - window.stop(); + } function runTest() {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/placement/grid-auto-placement-implicit-tracks-001.html b/third_party/blink/web_tests/external/wpt/css/css-grid/placement/grid-auto-placement-implicit-tracks-001.html new file mode 100644 index 0000000..546336a6 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/placement/grid-auto-placement-implicit-tracks-001.html
@@ -0,0 +1,124 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Grid items auto-placement implicit tracks</title> +<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-grid-1/#auto-placement-algo"> +<meta name="assert" content="This test checks that auto-placement works properly even when implicit tracks have been created during the first steps of the placement algorithm."> +<style> +.grid { + display: grid; + position: relative; + grid-auto-columns: 100px; + grid-auto-rows: 50px; + margin: 10px; +} +.gridAutoFlowColumn { grid-auto-flow: column; } +.gridAutoFlowColumnDense { grid-auto-flow: column dense; } +.gridAutoFlowRowDense { grid-auto-flow: row dense; } +.grid > div { border: solid; } +</style> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/check-layout-th.js"></script> + +<body onload="checkLayout('.grid')"> +<div id="log"></div> + +<div class="grid"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="100" data-expected-height="50">i1</div> + <div style="grid-column: span 2; grid-row: span 2;" + data-offset-x="0" data-offset-y="50" data-expected-width="200" data-expected-height="100">i2</div> + <div data-offset-x="0" data-offset-y="150" data-expected-width="100" data-expected-height="50">i3</div> + <div data-offset-x="100" data-offset-y="150" data-expected-width="100" data-expected-height="50">i4</div> +</div> + +<div class="grid"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="100" data-expected-height="50">i1</div> + <div style="grid-column: 1; grid-row: span 2;" + data-offset-x="0" data-offset-y="50" data-expected-width="100" data-expected-height="100">i2</div> + <div data-offset-x="0" data-offset-y="150" data-expected-width="100" data-expected-height="50">i3</div> + <div data-offset-x="0" data-offset-y="200" data-expected-width="100" data-expected-height="50">i4</div> +</div> + +<div class="grid"> + <div data-offset-x="0" data-offset-y="50" data-expected-width="100" data-expected-height="50">i1</div> + <div style="grid-column: span 2; grid-row: 1;" + data-offset-x="0" data-offset-y="0" data-expected-width="200" data-expected-height="50">i2</div> + <div data-offset-x="100" data-offset-y="50" data-expected-width="100" data-expected-height="50">i3</div> + <div data-offset-x="0" data-offset-y="100" data-expected-width="100" data-expected-height="50">i4</div> +</div> + +<div class="grid gridAutoFlowRowDense"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="100" data-expected-height="50">i1</div> + <div style="grid-column: span 2; grid-row: span 2;" + data-offset-x="0" data-offset-y="50" data-expected-width="200" data-expected-height="100">i2</div> + <div data-offset-x="100" data-offset-y="0" data-expected-width="100" data-expected-height="50">i3</div> + <div data-offset-x="0" data-offset-y="150" data-expected-width="100" data-expected-height="50">i4</div> +</div> + +<div class="grid gridAutoFlowRowDense"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="100" data-expected-height="50">i1</div> + <div style="grid-column: 1; grid-row: span 2;" + data-offset-x="0" data-offset-y="50" data-expected-width="100" data-expected-height="100">i2</div> + <div data-offset-x="0" data-offset-y="150" data-expected-width="100" data-expected-height="50">i3</div> + <div data-offset-x="0" data-offset-y="200" data-expected-width="100" data-expected-height="50">i4</div> +</div> + +<div class="grid gridAutoFlowRowDense"> + <div data-offset-x="0" data-offset-y="50" data-expected-width="100" data-expected-height="50">i1</div> + <div style="grid-column: span 2; grid-row: 1;" + data-offset-x="0" data-offset-y="0" data-expected-width="200" data-expected-height="50">i2</div> + <div data-offset-x="100" data-offset-y="50" data-expected-width="100" data-expected-height="50">i3</div> + <div data-offset-x="0" data-offset-y="100" data-expected-width="100" data-expected-height="50">i4</div> +</div> + +<div class="grid gridAutoFlowColumn"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="100" data-expected-height="50">i1</div> + <div style="grid-column: span 2; grid-row: span 2;" + data-offset-x="100" data-offset-y="0" data-expected-width="200" data-expected-height="100">i2</div> + <div data-offset-x="300" data-offset-y="0" data-expected-width="100" data-expected-height="50">i3</div> + <div data-offset-x="300" data-offset-y="50" data-expected-width="100" data-expected-height="50">i4</div> +</div> + +<div class="grid gridAutoFlowColumn"> + <div data-offset-x="100" data-offset-y="0" data-expected-width="100" data-expected-height="50">i1</div> + <div style="grid-column: 1; grid-row: span 2;" + data-offset-x="0" data-offset-y="0" data-expected-width="100" data-expected-height="100">i2</div> + <div data-offset-x="100" data-offset-y="50" data-expected-width="100" data-expected-height="50">i3</div> + <div data-offset-x="200" data-offset-y="0" data-expected-width="100" data-expected-height="50">i4</div> +</div> + +<div class="grid gridAutoFlowColumn"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="100" data-expected-height="50">i1</div> + <div style="grid-column: span 2; grid-row: 1;" + data-offset-x="100" data-offset-y="0" data-expected-width="200" data-expected-height="50">i2</div> + <div data-offset-x="300" data-offset-y="0" data-expected-width="100" data-expected-height="50">i3</div> + <div data-offset-x="400" data-offset-y="0" data-expected-width="100" data-expected-height="50">i4</div> +</div> + +<div class="grid gridAutoFlowColumnDense"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="100" data-expected-height="50">i1</div> + <div style="grid-column: span 2; grid-row: span 2;" + data-offset-x="100" data-offset-y="0" data-expected-width="200" data-expected-height="100">i2</div> + <div data-offset-x="0" data-offset-y="50" data-expected-width="100" data-expected-height="50">i3</div> + <div data-offset-x="300" data-offset-y="0" data-expected-width="100" data-expected-height="50">i4</div> +</div> + +<div class="grid gridAutoFlowColumnDense"> + <div data-offset-x="100" data-offset-y="0" data-expected-width="100" data-expected-height="50">i1</div> + <div style="grid-column: 1; grid-row: span 2;" + data-offset-x="0" data-offset-y="0" data-expected-width="100" data-expected-height="100">i2</div> + <div data-offset-x="100" data-offset-y="50" data-expected-width="100" data-expected-height="50">i3</div> + <div data-offset-x="200" data-offset-y="0" data-expected-width="100" data-expected-height="50">i4</div> +</div> + +<div class="grid gridAutoFlowColumnDense"> + <div data-offset-x="0" data-offset-y="0" data-expected-width="100" data-expected-height="50">i1</div> + <div style="grid-column: span 2; grid-row: 1;" + data-offset-x="100" data-offset-y="0" data-expected-width="200" data-expected-height="50">i2</div> + <div data-offset-x="300" data-offset-y="0" data-expected-width="100" data-expected-height="50">i3</div> + <div data-offset-x="400" data-offset-y="0" data-expected-width="100" data-expected-height="50">i4</div> +</div> + +</body>
diff --git a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_gotpointercapture_before_first_pointerevent-manual-automation.js b/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_gotpointercapture_before_first_pointerevent-manual-automation.js deleted file mode 100644 index 0284b99f..0000000 --- a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_gotpointercapture_before_first_pointerevent-manual-automation.js +++ /dev/null
@@ -1,6 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - return mouseClickInTarget('#target0'); -} -
diff --git a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerdown-manual-automation.js b/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerdown-manual-automation.js deleted file mode 100644 index 0284b99f..0000000 --- a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerdown-manual-automation.js +++ /dev/null
@@ -1,6 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - return mouseClickInTarget('#target0'); -} -
diff --git a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerenter-manual-automation.js b/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerenter-manual-automation.js deleted file mode 100644 index 0bc0732..0000000 --- a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerenter-manual-automation.js +++ /dev/null
@@ -1,6 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - return mouseMoveIntoTarget('#target0'); -} -
diff --git a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerenter_nohover-manual-automation.js b/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerenter_nohover-manual-automation.js deleted file mode 100644 index fbe48a5d..0000000 --- a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerenter_nohover-manual-automation.js +++ /dev/null
@@ -1,6 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - return touchTapInTarget('#target0'); -} -
diff --git a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerleave_after_pointerup_nohover-manual-automation.js b/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerleave_after_pointerup_nohover-manual-automation.js deleted file mode 100644 index fbe48a5d..0000000 --- a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerleave_after_pointerup_nohover-manual-automation.js +++ /dev/null
@@ -1,6 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - return touchTapInTarget('#target0'); -} -
diff --git a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerleave_mouse-manual-automation.js b/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerleave_mouse-manual-automation.js deleted file mode 100644 index 3bfc1d9..0000000 --- a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerleave_mouse-manual-automation.js +++ /dev/null
@@ -1,8 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - return mouseMoveIntoTarget('#target0').then(function() { - return mouseMoveToDocument(); - }); -} -
diff --git a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerleave_touch-manual-automation.js b/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerleave_touch-manual-automation.js deleted file mode 100644 index fbe48a5d..0000000 --- a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerleave_touch-manual-automation.js +++ /dev/null
@@ -1,6 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - return touchTapInTarget('#target0'); -} -
diff --git a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointermove_pointertype-manual-automation.js b/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointermove_pointertype-manual-automation.js deleted file mode 100644 index 1ec294d..0000000 --- a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointermove_pointertype-manual-automation.js +++ /dev/null
@@ -1,8 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - return mouseClickInTarget('#target0').then(function() { - mouseMoveIntoTarget('#target0'); - }); -} -
diff --git a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerout-manual-automation.js b/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerout-manual-automation.js deleted file mode 100644 index 7bdc7b3..0000000 --- a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerout-manual-automation.js +++ /dev/null
@@ -1,8 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - return mouseMoveIntoTarget('#target0').then(function() { - mouseMoveToDocument(); - }); -} -
diff --git a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerout_after_pointerup_nohover-manual-automation.js b/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerout_after_pointerup_nohover-manual-automation.js deleted file mode 100644 index fbe48a5d..0000000 --- a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerout_after_pointerup_nohover-manual-automation.js +++ /dev/null
@@ -1,6 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - return touchTapInTarget('#target0'); -} -
diff --git a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerover-manual-automation.js b/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerover-manual-automation.js deleted file mode 100644 index 0bc0732..0000000 --- a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerover-manual-automation.js +++ /dev/null
@@ -1,6 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - return mouseMoveIntoTarget('#target0'); -} -
diff --git a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointertype_mouse-manual-automation.js b/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointertype_mouse-manual-automation.js deleted file mode 100644 index 0284b99f..0000000 --- a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointertype_mouse-manual-automation.js +++ /dev/null
@@ -1,6 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - return mouseClickInTarget('#target0'); -} -
diff --git a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointertype_pen-manual-automation.js b/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointertype_pen-manual-automation.js deleted file mode 100644 index f1becec7..0000000 --- a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointertype_pen-manual-automation.js +++ /dev/null
@@ -1,6 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - return penClickIntoTarget('#target0'); -} -
diff --git a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointertype_touch-manual-automation.js b/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointertype_touch-manual-automation.js deleted file mode 100644 index fbe48a5d..0000000 --- a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointertype_touch-manual-automation.js +++ /dev/null
@@ -1,6 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - return touchTapInTarget('#target0'); -} -
diff --git a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerup-manual-automation.js b/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerup-manual-automation.js deleted file mode 100644 index 0284b99f..0000000 --- a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerup-manual-automation.js +++ /dev/null
@@ -1,6 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - return mouseClickInTarget('#target0'); -} -
diff --git a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerup_isprimary_same_as_pointerdown-manual-automation.js b/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerup_isprimary_same_as_pointerdown-manual-automation.js deleted file mode 100644 index 0284b99f..0000000 --- a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerup_isprimary_same_as_pointerdown-manual-automation.js +++ /dev/null
@@ -1,6 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - return mouseClickInTarget('#target0'); -} -
diff --git a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerup_pointertype-manual-automation.js b/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerup_pointertype-manual-automation.js deleted file mode 100644 index 0284b99f..0000000 --- a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerup_pointertype-manual-automation.js +++ /dev/null
@@ -1,6 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - return mouseClickInTarget('#target0'); -} -
diff --git a/third_party/blink/web_tests/fast/events/popup-blocked-to-post-blank-expected.txt b/third_party/blink/web_tests/fast/events/popup-blocked-to-post-blank-expected.txt index 1c6ee54..7f4325c 100644 --- a/third_party/blink/web_tests/fast/events/popup-blocked-to-post-blank-expected.txt +++ b/third_party/blink/web_tests/fast/events/popup-blocked-to-post-blank-expected.txt
@@ -1,2 +1,2 @@ -CONSOLE ERROR: line 15: Not allowed to navigate top frame to data URL: data:text/html,<script>alert(window)</script>? +CONSOLE ERROR: Not allowed to navigate top frame to data URL: data:text/html,<script>alert(window)</script>? If the POST pop-up was not blocked then there will be an ALERT containing a Window object. Otherwise, the test passes.
diff --git a/third_party/blink/web_tests/fast/forms/form-submission-create-crash.xhtml b/third_party/blink/web_tests/fast/forms/form-submission-create-crash.xhtml index ac56ca4c..c0d6b8d 100644 --- a/third_party/blink/web_tests/fast/forms/form-submission-create-crash.xhtml +++ b/third_party/blink/web_tests/fast/forms/form-submission-create-crash.xhtml
@@ -18,7 +18,6 @@ textNode.dispatchEvent(event); if (window.testRunner) testRunner.notifyDone(); - window.stop(); } setTimeout(runTest, 0);
diff --git a/third_party/blink/web_tests/fast/forms/select/select-empty-optgroup-crash.html b/third_party/blink/web_tests/fast/forms/select/select-empty-optgroup-crash.html index c90e4e0..81c35cdf 100644 --- a/third_party/blink/web_tests/fast/forms/select/select-empty-optgroup-crash.html +++ b/third_party/blink/web_tests/fast/forms/select/select-empty-optgroup-crash.html
@@ -4,9 +4,6 @@ { if (window.testRunner) testRunner.dumpAsText(); - if (sessionStorage.submitted) - return; - sessionStorage.submitted = true; document.getElementById("submitform").submit(); } </script>
diff --git a/third_party/blink/web_tests/fast/forms/submit-add-remove-element.html b/third_party/blink/web_tests/fast/forms/submit-add-remove-element.html index 0f16523..c54f4a33 100644 --- a/third_party/blink/web_tests/fast/forms/submit-add-remove-element.html +++ b/third_party/blink/web_tests/fast/forms/submit-add-remove-element.html
@@ -38,8 +38,7 @@ } window.onload = function() { - if (location.search == "") - document.getElementById('submitButton').click(); + document.getElementById('submitButton').click(); } if (window.testRunner)
diff --git a/third_party/blink/web_tests/http/tests/loading/307-after-303-after-post-expected.txt b/third_party/blink/web_tests/http/tests/loading/307-after-303-after-post-expected.txt index 80447924..7b513fe 100644 --- a/third_party/blink/web_tests/http/tests/loading/307-after-303-after-post-expected.txt +++ b/third_party/blink/web_tests/http/tests/loading/307-after-303-after-post-expected.txt
@@ -2,10 +2,10 @@ main frame - didCommitLoadForFrame main frame - didReceiveTitle: main frame - didFinishDocumentLoadForFrame +main frame - didHandleOnloadEventsForFrame main frame - didFinishLoadForFrame http://127.0.0.1:8000/loading/resources/post-to-303-target.php - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/post-to-303-target.php, main document URL http://127.0.0.1:8000/loading/resources/post-to-303-target.php, http method POST> main frame - didStartProvisionalLoadForFrame -main frame - didHandleOnloadEventsForFrame http://127.0.0.1:8000/loading/resources/303-to-307-target.php - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/303-to-307-target.php, main document URL http://127.0.0.1:8000/loading/resources/303-to-307-target.php, http method GET> http://127.0.0.1:8000/loading/resources/307-post-output-target.php - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/307-post-output-target.php, main document URL http://127.0.0.1:8000/loading/resources/307-post-output-target.php, http method GET> http://127.0.0.1:8000/loading/resources/307-post-output-target.php - didReceiveResponse <NSURLResponse http://127.0.0.1:8000/loading/resources/307-post-output-target.php, http status code 200>
diff --git a/third_party/blink/web_tests/http/tests/loading/redirect-methods-expected.txt b/third_party/blink/web_tests/http/tests/loading/redirect-methods-expected.txt index 75cae043..9bef8ff 100644 --- a/third_party/blink/web_tests/http/tests/loading/redirect-methods-expected.txt +++ b/third_party/blink/web_tests/http/tests/loading/redirect-methods-expected.txt
@@ -17,10 +17,10 @@ frame "0" - didCommitLoadForFrame frame "0" - didReceiveTitle: frame "0" - didFinishDocumentLoadForFrame +frame "0" - didHandleOnloadEventsForFrame frame "0" - didFinishLoadForFrame http://127.0.0.1:8000/loading/resources/redirect-methods-result.php - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/redirect-methods-result.php, main document URL http://127.0.0.1:8000/loading/redirect-methods.html, http method POST> frame "0" - didStartProvisionalLoadForFrame -frame "0" - didHandleOnloadEventsForFrame http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true, main document URL http://127.0.0.1:8000/loading/redirect-methods.html, http method GET> http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true - didReceiveResponse <NSURLResponse http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true, http status code 200> frame "0" - didCommitLoadForFrame @@ -41,10 +41,10 @@ frame "1" - didCommitLoadForFrame frame "1" - didReceiveTitle: frame "1" - didFinishDocumentLoadForFrame +frame "1" - didHandleOnloadEventsForFrame frame "1" - didFinishLoadForFrame http://127.0.0.1:8000/loading/resources/redirect-methods-result.php - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/redirect-methods-result.php, main document URL http://127.0.0.1:8000/loading/redirect-methods.html, http method POST> frame "1" - didStartProvisionalLoadForFrame -frame "1" - didHandleOnloadEventsForFrame http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true, main document URL http://127.0.0.1:8000/loading/redirect-methods.html, http method GET> http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true - didReceiveResponse <NSURLResponse http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true, http status code 200> frame "1" - didCommitLoadForFrame @@ -65,10 +65,10 @@ frame "2" - didCommitLoadForFrame frame "2" - didReceiveTitle: frame "2" - didFinishDocumentLoadForFrame +frame "2" - didHandleOnloadEventsForFrame frame "2" - didFinishLoadForFrame http://127.0.0.1:8000/loading/resources/redirect-methods-result.php - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/redirect-methods-result.php, main document URL http://127.0.0.1:8000/loading/redirect-methods.html, http method POST> frame "2" - didStartProvisionalLoadForFrame -frame "2" - didHandleOnloadEventsForFrame http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true, main document URL http://127.0.0.1:8000/loading/redirect-methods.html, http method GET> http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true - didReceiveResponse <NSURLResponse http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true, http status code 200> frame "2" - didCommitLoadForFrame @@ -89,10 +89,10 @@ frame "3" - didCommitLoadForFrame frame "3" - didReceiveTitle: frame "3" - didFinishDocumentLoadForFrame +frame "3" - didHandleOnloadEventsForFrame frame "3" - didFinishLoadForFrame http://127.0.0.1:8000/loading/resources/redirect-methods-result.php - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/redirect-methods-result.php, main document URL http://127.0.0.1:8000/loading/redirect-methods.html, http method POST> frame "3" - didStartProvisionalLoadForFrame -frame "3" - didHandleOnloadEventsForFrame http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true, main document URL http://127.0.0.1:8000/loading/redirect-methods.html, http method POST> http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true - didReceiveResponse <NSURLResponse http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true, http status code 200> frame "3" - didCommitLoadForFrame
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-get-blocked-with-redirect-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-get-blocked-with-redirect-expected.txt index d15e0f5..a37a9d3 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-get-blocked-with-redirect-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-get-blocked-with-redirect-expected.txt
@@ -1,4 +1,4 @@ -CONSOLE ERROR: line 16: Refused to send form data to 'http://localhost:8000/' because it violates the following Content Security Policy directive: "form-action 127.0.0.1:8000". +CONSOLE ERROR: Refused to send form data to 'http://localhost:8000/' because it violates the following Content Security Policy directive: "form-action 127.0.0.1:8000".
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-redirect-blocked-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-redirect-blocked-expected.txt index 2df5e203..e12c940 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-redirect-blocked-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-redirect-blocked-expected.txt
@@ -1,4 +1,4 @@ -CONSOLE ERROR: line 14: Refused to send form data to 'http://localhost:8000/' because it violates the following Content Security Policy directive: "form-action 127.0.0.1:8000". +CONSOLE ERROR: Refused to send form data to 'http://localhost:8000/' because it violates the following Content Security Policy directive: "form-action 127.0.0.1:8000".
diff --git a/third_party/blink/web_tests/virtual/mouseevent_fractional/fast/events/popup-blocked-to-post-blank-expected.txt b/third_party/blink/web_tests/virtual/mouseevent_fractional/fast/events/popup-blocked-to-post-blank-expected.txt index 1c6ee54..7f4325c 100644 --- a/third_party/blink/web_tests/virtual/mouseevent_fractional/fast/events/popup-blocked-to-post-blank-expected.txt +++ b/third_party/blink/web_tests/virtual/mouseevent_fractional/fast/events/popup-blocked-to-post-blank-expected.txt
@@ -1,2 +1,2 @@ -CONSOLE ERROR: line 15: Not allowed to navigate top frame to data URL: data:text/html,<script>alert(window)</script>? +CONSOLE ERROR: Not allowed to navigate top frame to data URL: data:text/html,<script>alert(window)</script>? If the POST pop-up was not blocked then there will be an ALERT containing a Window object. Otherwise, the test passes.
diff --git a/third_party/blink/web_tests/virtual/user-activation-v2/fast/events/popup-blocked-to-post-blank-expected.txt b/third_party/blink/web_tests/virtual/user-activation-v2/fast/events/popup-blocked-to-post-blank-expected.txt index 1c6ee54..7f4325c 100644 --- a/third_party/blink/web_tests/virtual/user-activation-v2/fast/events/popup-blocked-to-post-blank-expected.txt +++ b/third_party/blink/web_tests/virtual/user-activation-v2/fast/events/popup-blocked-to-post-blank-expected.txt
@@ -1,2 +1,2 @@ -CONSOLE ERROR: line 15: Not allowed to navigate top frame to data URL: data:text/html,<script>alert(window)</script>? +CONSOLE ERROR: Not allowed to navigate top frame to data URL: data:text/html,<script>alert(window)</script>? If the POST pop-up was not blocked then there will be an ALERT containing a Window object. Otherwise, the test passes.
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 26aa087..a993bbd6 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -15488,6 +15488,14 @@ <int value="128" label="Request type matched."/> </enum> +<enum name="EventPreFilterResult"> + <int value="0" label="Unfiltered"/> + <int value="1" label="Filtered due to no page handlers"/> + <int value="2" label="Filtered due to timeout"/> + <int value="3" label="Filtered due to no nonstationary pointers"/> + <int value="4" label="Filtered due to no handler for sequence"/> +</enum> + <enum name="EventResultType"> <int value="0" label="Passive"/> <int value="1" label="Uncancelable"/> @@ -21054,6 +21062,16 @@ <int value="2651" label="V8RegExpMatchIsFalseishOnJSRegExp"/> <int value="2652" label="DownloadInAdFrameWithUserGesture"/> <int value="2653" label="DownloadInAdFrameWithoutUserGesture"/> + <int value="2654" label="NavigatorAppVersion"/> + <int value="2655" label="NavigatorDoNotTrack"/> + <int value="2656" label="NavigatorHardwareConcurrency"/> + <int value="2657" label="NavigatorLanguage"/> + <int value="2658" label="NavigatorLanguages"/> + <int value="2659" label="NavigatorMaxTouchPoints"/> + <int value="2660" label="NavigatorMimeTypes"/> + <int value="2661" label="NavigatorPlatform"/> + <int value="2662" label="NavigatorPlugins"/> + <int value="2663" label="NavigatorUserAgent"/> </enum> <enum name="FeaturePolicyFeature">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 8c3dad5..c16efb1 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -29671,6 +29671,20 @@ </summary> </histogram> +<histogram name="Event.Touch.FilteredAtPassthroughQueue" + enum="EventPreFilterResult" expires_after="2020-01-01"> + <owner>charliea@chromium.org</owner> + <owner>nzolghadr@chromium.org</owner> + <summary> + Whether a given touch event is filtered by the passthrough touch event queue + or not. If the event was filtered, a reason is given. Potential reasons for + filtering include the page not having any registered touch handlers and the + renderer process not responding to previous touch events. + + Team: input-dev@chromium.org + </summary> +</histogram> + <histogram name="Event.Touch.GestureTarget" enum="BrowserGestureActionType"> <owner>kuscher@google.com</owner> <owner>rbyers@chromium.org</owner> @@ -112070,7 +112084,8 @@ <histogram base="true" name="Sync.ModelTypeMemoryKB" units="KB" expires_after="2020-02-01"> - <owner>pavely@chromium.org</owner> + <owner>mastiz@chromium.org</owner> + <owner>jkrcal@chromium.org</owner> <summary> Estimated memory usage by sync datatype in kilobytes. Recorded after sync configuration. This metric is used for monitoring general health of sync @@ -112089,6 +112104,16 @@ </summary> </histogram> +<histogram name="Sync.ModelTypeRedundantPut" enum="SyncModelTypes" + expires_after="2019-03-01"> + <owner>mastiz@chromium.org</owner> + <owner>jkrcal@chromium.org</owner> + <summary> + Records the model type when a local change is made and sync optimized it + away because nothing actually changed. + </summary> +</histogram> + <histogram name="Sync.ModelTypeStoreCommitCount" enum="SyncModelTypes" expires_after="2019-03-01"> <owner>mastiz@chromium.org</owner> @@ -128914,10 +128939,21 @@ label="Signed in and sync transport enabled for Wallet data types"/> <suffix name="SignedOut" label="Signed out"/> <suffix name="Unknown" label="Unknown"/> - <affected-histogram name="Autofill.FormEvents.Address"/> - <affected-histogram name="Autofill.FormEvents.CreditCard"/> + <affected-histogram + name="Autofill.FormEvents.Address.WithBothServerAndLocalData"/> + <affected-histogram name="Autofill.FormEvents.Address.WithNoData"/> + <affected-histogram name="Autofill.FormEvents.Address.WithOnlyLocalData"/> + <affected-histogram name="Autofill.FormEvents.Address.WithOnlyServerData"/> + <affected-histogram + name="Autofill.FormEvents.CreditCard.WithBothServerAndLocalData"/> + <affected-histogram name="Autofill.FormEvents.CreditCard.WithNoData"/> + <affected-histogram name="Autofill.FormEvents.CreditCard.WithOnlyLocalData"/> + <affected-histogram name="Autofill.FormEvents.CreditCard.WithOnlyServerData"/> <affected-histogram name="Autofill.IsEnabled.PageLoad"/> - <affected-histogram name="Autofill.SaveCreditCardPrompt"/> + <affected-histogram name="Autofill.SaveCreditCardPrompt.Local.FirstShow"/> + <affected-histogram name="Autofill.SaveCreditCardPrompt.Local.Reshows"/> + <affected-histogram name="Autofill.SaveCreditCardPrompt.Upload.FirstShow"/> + <affected-histogram name="Autofill.SaveCreditCardPrompt.Upload.Reshows"/> </histogram_suffixes> <histogram_suffixes name="AutofillUnmaskPromptCloseReasonEvents" separator=".">
diff --git a/ui/accessibility/platform/ax_platform_node_win.cc b/ui/accessibility/platform/ax_platform_node_win.cc index 1bf0e730..212abd0 100644 --- a/ui/accessibility/platform/ax_platform_node_win.cc +++ b/ui/accessibility/platform/ax_platform_node_win.cc
@@ -831,19 +831,8 @@ observer.OnAccNameCalled(); } - HRESULT result = - target->GetStringAttributeAsBstr(ax::mojom::StringAttribute::kName, name); - if (FAILED(result) && MSAARole() == ROLE_SYSTEM_DOCUMENT && GetParent()) { - // Hack: Some versions of JAWS crash if they get an empty name on - // a document that's the child of an iframe, so always return a - // nonempty string for this role. https://crbug.com/583057 - base::string16 str = L" "; - - *name = SysAllocString(str.c_str()); - DCHECK(*name); - } - - return result; + return target->GetStringAttributeAsBstr(ax::mojom::StringAttribute::kName, + name); } IFACEMETHODIMP AXPlatformNodeWin::get_accParent(IDispatch** disp_parent) {
diff --git a/ui/aura/test/aura_test_suite_setup.cc b/ui/aura/test/aura_test_suite_setup.cc index 36ae0cf8..c1d8270 100644 --- a/ui/aura/test/aura_test_suite_setup.cc +++ b/ui/aura/test/aura_test_suite_setup.cc
@@ -16,10 +16,22 @@ #endif namespace aura { +namespace { + +#if BUILDFLAG(ENABLE_MUS) +bool g_disable_mus_features = false; +#endif + +} // namespace AuraTestSuiteSetup::AuraTestSuiteSetup() { DCHECK(!Env::HasInstance()); #if BUILDFLAG(ENABLE_MUS) + if (g_disable_mus_features) { + scoped_feature_list_.InitWithFeatures( + {} /* enabled */, + {features::kMash, features::kSingleProcessMash} /* disabled */); + } const Env::Mode env_mode = features::IsUsingWindowService() ? Env::Mode::MUS : Env::Mode::LOCAL; env_ = Env::CreateInstance(env_mode); @@ -33,6 +45,13 @@ AuraTestSuiteSetup::~AuraTestSuiteSetup() = default; #if BUILDFLAG(ENABLE_MUS) +// static +void AuraTestSuiteSetup::DisableMusFeatures() { + g_disable_mus_features = true; +} +#endif + +#if BUILDFLAG(ENABLE_MUS) void AuraTestSuiteSetup::ConfigureMus() { // Configure the WindowTreeClient in a mode similar to that of connecting via // a WindowTreeFactory. This gives WindowTreeClient a mock WindowTree.
diff --git a/ui/aura/test/aura_test_suite_setup.h b/ui/aura/test/aura_test_suite_setup.h index 08e2802..65253e69 100644 --- a/ui/aura/test/aura_test_suite_setup.h +++ b/ui/aura/test/aura_test_suite_setup.h
@@ -8,6 +8,8 @@ #include <memory> #include "base/macros.h" +#include "base/test/scoped_feature_list.h" +#include "build/buildflag.h" #include "ui/base/ui_features.h" namespace ui { @@ -30,6 +32,12 @@ AuraTestSuiteSetup(); ~AuraTestSuiteSetup(); +#if BUILDFLAG(ENABLE_MUS) + // Disables window service feature flags for test suites that do not exercise + // mus client code. Must be called before this object is constructed. + static void DisableMusFeatures(); +#endif + private: #if BUILDFLAG(ENABLE_MUS) void ConfigureMus(); @@ -38,6 +46,7 @@ std::unique_ptr<aura::Env> env_; #if BUILDFLAG(ENABLE_MUS) + base::test::ScopedFeatureList scoped_feature_list_; std::unique_ptr<ui::ContextFactory> context_factory_; std::unique_ptr<TestWindowTreeClientDelegate> test_window_tree_client_delegate_;
diff --git a/ui/message_center/views/notification_view_md.cc b/ui/message_center/views/notification_view_md.cc index 4f60cc5..5898cd8 100644 --- a/ui/message_center/views/notification_view_md.cc +++ b/ui/message_center/views/notification_view_md.cc
@@ -967,14 +967,17 @@ void NotificationViewMD::CreateOrUpdateSmallIconView( const Notification& notification) { - if (!notification.vector_small_image().is_empty()) { - header_row_->SetAppIcon( - gfx::CreateVectorIcon(notification.vector_small_image(), - kSmallImageSizeMD, notification.accent_color())); - } else if (!notification.small_image().IsEmpty()) { - header_row_->SetAppIcon(notification.small_image().AsImageSkia()); - } else { + // TODO(knollr): figure out if this has a performance impact and + // cache images if so. (crbug.com/768748) + gfx::Image masked_small_icon = notification.GenerateMaskedSmallIcon( + kSmallImageSizeMD, notification.accent_color() == SK_ColorTRANSPARENT + ? message_center::kNotificationDefaultAccentColor + : notification.accent_color()); + + if (masked_small_icon.IsEmpty()) { header_row_->ClearAppIcon(); + } else { + header_row_->SetAppIcon(masked_small_icon.AsImageSkia()); } }
diff --git a/ui/views/cocoa/bridged_native_widget_unittest.mm b/ui/views/cocoa/bridged_native_widget_unittest.mm index 5c729fcd..055bfff 100644 --- a/ui/views/cocoa/bridged_native_widget_unittest.mm +++ b/ui/views/cocoa/bridged_native_widget_unittest.mm
@@ -320,7 +320,7 @@ // Usually the bridge gets initialized here. It is skipped to run extra // checks in tests, and so that a second window isn't created. - delegate()->OnNativeWidgetCreated(true); + delegate()->OnNativeWidgetCreated(); // To allow events to dispatch to a view, it needs a way to get focus. bridge_host()->SetFocusManager(GetWidget()->GetFocusManager());
diff --git a/ui/views/controls/focus_ring.cc b/ui/views/controls/focus_ring.cc index b9c01bc..e18f3bf 100644 --- a/ui/views/controls/focus_ring.cc +++ b/ui/views/controls/focus_ring.cc
@@ -54,6 +54,11 @@ SchedulePaint(); } +void FocusRing::SetColor(base::Optional<SkColor> color) { + color_ = color; + SchedulePaint(); +} + const char* FocusRing::GetClassName() const { return kViewClassName; } @@ -70,12 +75,10 @@ if (!has_focus_predicate_(parent())) return; - SkColor base_color = - GetNativeTheme()->GetSystemColor(ColorIdForValidity(!invalid_)); - cc::PaintFlags paint; paint.setAntiAlias(true); - paint.setColor(is_opaque_ ? base_color : SkColorSetA(base_color, 0x66)); + paint.setColor(color_.value_or(SkColorSetA( + GetNativeTheme()->GetSystemColor(ColorIdForValidity(!invalid_)), 0x66))); paint.setStyle(cc::PaintFlags::kStroke_Style); paint.setStrokeWidth(PlatformStyle::kFocusHaloThickness);
diff --git a/ui/views/controls/focus_ring.h b/ui/views/controls/focus_ring.h index 8bf3b05e..fec760e 100644 --- a/ui/views/controls/focus_ring.h +++ b/ui/views/controls/focus_ring.h
@@ -74,7 +74,7 @@ // focus, but the FocusRing sits on the parent instead of the inner view. void SetHasFocusPredicate(const ViewPredicate& predicate); - void set_is_opaque() { is_opaque_ = true; } + void SetColor(base::Optional<SkColor> color); // View: const char* GetClassName() const override; @@ -107,8 +107,8 @@ // the focus ring shows an invalid appearance (usually a different color). bool invalid_ = false; - // Whether the focus ring is painted with full opacity. - bool is_opaque_ = false; + // Overriding color for the focus ring. + base::Optional<SkColor> color_; // The predicate used to determine whether the parent has focus. ViewPredicate has_focus_predicate_;
diff --git a/ui/views/focus/focus_manager_factory.cc b/ui/views/focus/focus_manager_factory.cc index 5ebe513..9a63c41 100644 --- a/ui/views/focus/focus_manager_factory.cc +++ b/ui/views/focus/focus_manager_factory.cc
@@ -13,13 +13,11 @@ class DefaultFocusManagerFactory : public FocusManagerFactory { public: - DefaultFocusManagerFactory() : FocusManagerFactory() {} - ~DefaultFocusManagerFactory() override {} + DefaultFocusManagerFactory() = default; + ~DefaultFocusManagerFactory() override = default; protected: - std::unique_ptr<FocusManager> CreateFocusManager( - Widget* widget, - bool desktop_widget) override { + std::unique_ptr<FocusManager> CreateFocusManager(Widget* widget) override { return std::make_unique<FocusManager>(widget, nullptr /* delegate */); } @@ -31,18 +29,15 @@ } // namespace -FocusManagerFactory::FocusManagerFactory() { -} +FocusManagerFactory::FocusManagerFactory() = default; -FocusManagerFactory::~FocusManagerFactory() { -} +FocusManagerFactory::~FocusManagerFactory() = default; // static -std::unique_ptr<FocusManager> FocusManagerFactory::Create(Widget* widget, - bool desktop_widget) { +std::unique_ptr<FocusManager> FocusManagerFactory::Create(Widget* widget) { if (!g_focus_manager_factory) g_focus_manager_factory = new DefaultFocusManagerFactory(); - return g_focus_manager_factory->CreateFocusManager(widget, desktop_widget); + return g_focus_manager_factory->CreateFocusManager(widget); } // static
diff --git a/ui/views/focus/focus_manager_factory.h b/ui/views/focus/focus_manager_factory.h index 9b17a8cb..1a91b9e 100644 --- a/ui/views/focus/focus_manager_factory.h +++ b/ui/views/focus/focus_manager_factory.h
@@ -20,8 +20,7 @@ class VIEWS_EXPORT FocusManagerFactory { public: // Create a FocusManager for the given |widget| using the installed Factory. - static std::unique_ptr<FocusManager> Create(Widget* widget, - bool desktop_widget); + static std::unique_ptr<FocusManager> Create(Widget* widget); // Installs FocusManagerFactory. If |factory| is NULL, it resets // to the default factory which creates plain FocusManager. @@ -32,11 +31,7 @@ virtual ~FocusManagerFactory(); // Create a FocusManager for the given |widget|. - // The |desktop_widget| bool is true for widgets created in the desktop and - // false for widgets created in the shell. - virtual std::unique_ptr<FocusManager> CreateFocusManager( - Widget* widget, - bool desktop_widget) = 0; + virtual std::unique_ptr<FocusManager> CreateFocusManager(Widget* widget) = 0; private: DISALLOW_COPY_AND_ASSIGN(FocusManagerFactory);
diff --git a/ui/views/focus/focus_manager_unittest.cc b/ui/views/focus/focus_manager_unittest.cc index cffe97c..a46b9eb 100644 --- a/ui/views/focus/focus_manager_unittest.cc +++ b/ui/views/focus/focus_manager_unittest.cc
@@ -437,9 +437,7 @@ : dtor_tracker_(dtor_tracker) {} ~TestFocusManagerFactory() override {} - std::unique_ptr<FocusManager> CreateFocusManager( - Widget* widget, - bool desktop_widget) override { + std::unique_ptr<FocusManager> CreateFocusManager(Widget* widget) override { return std::make_unique<FocusManagerDtorTracked>(widget, dtor_tracker_); }
diff --git a/ui/views/mus/desktop_window_tree_host_mus.cc b/ui/views/mus/desktop_window_tree_host_mus.cc index 6449ce5..ccdb09c 100644 --- a/ui/views/mus/desktop_window_tree_host_mus.cc +++ b/ui/views/mus/desktop_window_tree_host_mus.cc
@@ -518,7 +518,7 @@ parent_ = static_cast<DesktopWindowTreeHostMus*>(params.parent->GetHost()); parent_->children_.insert(this); } - native_widget_delegate_->OnNativeWidgetCreated(true); + native_widget_delegate_->OnNativeWidgetCreated(); } void DesktopWindowTreeHostMus::OnActiveWindowChanged(bool active) {
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc index 72d04d0..f615231 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc
@@ -95,7 +95,7 @@ void DesktopWindowTreeHostPlatform::OnNativeWidgetCreated( const Widget::InitParams& params) { - native_widget_delegate_->OnNativeWidgetCreated(true); + native_widget_delegate_->OnNativeWidgetCreated(); #if defined(OS_LINUX) // Setup a non_client_window_event_filter, which handles resize/move, double
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc index f13a775..b2936d8f 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
@@ -805,7 +805,7 @@ } void DesktopWindowTreeHostWin::HandleCreate() { - native_widget_delegate_->OnNativeWidgetCreated(true); + native_widget_delegate_->OnNativeWidgetCreated(); } void DesktopWindowTreeHostWin::HandleDestroying() {
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc index 5e46a4f6..7f11f39 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
@@ -429,7 +429,7 @@ SetWindowTransparency(); - native_widget_delegate_->OnNativeWidgetCreated(true); + native_widget_delegate_->OnNativeWidgetCreated(); } void DesktopWindowTreeHostX11::OnWidgetInitDone() {}
diff --git a/ui/views/widget/native_widget_aura.cc b/ui/views/widget/native_widget_aura.cc index 63ef7767..390768b 100644 --- a/ui/views/widget/native_widget_aura.cc +++ b/ui/views/widget/native_widget_aura.cc
@@ -179,7 +179,7 @@ if (params.type == Widget::InitParams::TYPE_CONTROL) window_->Show(); - delegate_->OnNativeWidgetCreated(false); + delegate_->OnNativeWidgetCreated(); gfx::Rect window_bounds = params.bounds; gfx::NativeView parent = params.parent;
diff --git a/ui/views/widget/native_widget_delegate.h b/ui/views/widget/native_widget_delegate.h index fca8600..1b27833 100644 --- a/ui/views/widget/native_widget_delegate.h +++ b/ui/views/widget/native_widget_delegate.h
@@ -73,9 +73,7 @@ virtual void OnNativeWidgetVisibilityChanged(bool visible) = 0; // Called when the native widget is created. - // The |desktop_widget| bool is true for widgets created in the desktop and - // false for widgets created in the shell. - virtual void OnNativeWidgetCreated(bool desktop_widget) = 0; + virtual void OnNativeWidgetCreated() = 0; // Called just before the native widget is destroyed. This is the delegate's // last chance to do anything with the native widget handle.
diff --git a/ui/views/widget/native_widget_mac.mm b/ui/views/widget/native_widget_mac.mm index a5fdd67..e6d16c37 100644 --- a/ui/views/widget/native_widget_mac.mm +++ b/ui/views/widget/native_widget_mac.mm
@@ -158,7 +158,7 @@ if (params.keep_on_top) SetAlwaysOnTop(true); - delegate_->OnNativeWidgetCreated(true); + delegate_->OnNativeWidgetCreated(); DCHECK(GetWidget()->GetRootView()); bridge_host_->SetRootView(GetWidget()->GetRootView());
diff --git a/ui/views/widget/widget.cc b/ui/views/widget/widget.cc index eee5638..c7df0fb2 100644 --- a/ui/views/widget/widget.cc +++ b/ui/views/widget/widget.cc
@@ -1094,9 +1094,9 @@ root->layer()->SetVisible(visible); } -void Widget::OnNativeWidgetCreated(bool desktop_widget) { +void Widget::OnNativeWidgetCreated() { if (is_top_level()) - focus_manager_ = FocusManagerFactory::Create(this, desktop_widget); + focus_manager_ = FocusManagerFactory::Create(this); native_widget_->InitModalType(widget_delegate_->GetModalType());
diff --git a/ui/views/widget/widget.h b/ui/views/widget/widget.h index 106db03..9346796 100644 --- a/ui/views/widget/widget.h +++ b/ui/views/widget/widget.h
@@ -813,7 +813,7 @@ void OnNativeBlur() override; void OnNativeWidgetVisibilityChanging(bool visible) override; void OnNativeWidgetVisibilityChanged(bool visible) override; - void OnNativeWidgetCreated(bool desktop_widget) override; + void OnNativeWidgetCreated() override; void OnNativeWidgetDestroying() override; void OnNativeWidgetDestroyed() override; gfx::Size GetMinimumSize() const override;