events: replaces EventGenerator::delegate with a factory function

I need the ability for the delegate to have some additional context, and not
be long lived. By creating a unique delegate for each EventGenerator there can
be context per EventGenerator.

BUG=615033
TEST=this is a test only change

Change-Id: I9d8e099b940426b19d11071a427186573caf6b06
Reviewed-on: https://chromium-review.googlesource.com/1192124
Reviewed-by: Sadrul Chowdhury <[email protected]>
Commit-Queue: Scott Violet <[email protected]>
Cr-Commit-Position: refs/heads/master@{#586840}
diff --git a/ash/test/ash_test_base.cc b/ash/test/ash_test_base.cc
index 36302b7c..67bb074 100644
--- a/ash/test/ash_test_base.cc
+++ b/ash/test/ash_test_base.cc
@@ -77,11 +77,10 @@
   ~AshEventGeneratorDelegate() override = default;
 
   // aura::test::EventGeneratorDelegateAura overrides:
-  aura::WindowTreeHost* GetHostAt(
-      const gfx::Point& point_in_screen) const override {
+  ui::EventTarget* GetTargetAt(const gfx::Point& point_in_screen) override {
     display::Screen* screen = display::Screen::GetScreen();
     display::Display display = screen->GetDisplayNearestPoint(point_in_screen);
-    return Shell::GetRootWindowForDisplayId(display.id())->GetHost();
+    return Shell::GetRootWindowForDisplayId(display.id())->GetHost()->window();
   }
 
   aura::client::ScreenPositionClient* GetScreenPositionClient(
@@ -214,8 +213,8 @@
 
 ui::test::EventGenerator* AshTestBase::GetEventGenerator() {
   if (!event_generator_) {
-    event_generator_.reset(
-        new ui::test::EventGenerator(new AshEventGeneratorDelegate()));
+    event_generator_ = std::make_unique<ui::test::EventGenerator>(
+        std::make_unique<AshEventGeneratorDelegate>());
   }
   return event_generator_.get();
 }
diff --git a/ash/test/ash_test_helper.cc b/ash/test/ash_test_helper.cc
index aacfe7e..afdb144 100644
--- a/ash/test/ash_test_helper.cc
+++ b/ash/test/ash_test_helper.cc
@@ -157,7 +157,6 @@
     : ash_test_environment_(ash_test_environment),
       command_line_(std::make_unique<base::test::ScopedCommandLine>()) {
   ui::test::EnableTestConfigForPlatformWindows();
-  aura::test::InitializeAuraEventGeneratorDelegate();
 }
 
 AshTestHelper::~AshTestHelper() {
@@ -195,6 +194,9 @@
         switches::kAshDisableSmoothScreenRotation);
   }
 
+  ui::test::EventGeneratorDelegate::SetFactoryFunction(
+      base::BindRepeating(&aura::test::EventGeneratorDelegateAura::Create));
+
   display::ResetDisplayIdForTest();
   wm_state_ = std::make_unique<::wm::WMState>();
   test_views_delegate_ = ash_test_environment_->CreateViewsDelegate();
@@ -334,6 +336,9 @@
 #if !defined(NDEBUG)
   aura::Window::SetEnvArgRequired(nullptr);
 #endif
+
+  ui::test::EventGeneratorDelegate::SetFactoryFunction(
+      ui::test::EventGeneratorDelegate::FactoryFunction());
 }
 
 void AshTestHelper::SetRunningOutsideAsh() {
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
index 485b1d7..d50397f3 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
@@ -273,8 +273,8 @@
   ~ScreenEventGeneratorDelegate() override {}
 
   // EventGeneratorDelegateAura overrides:
-  aura::WindowTreeHost* GetHostAt(const gfx::Point& point) const override {
-    return root_window_->GetHost();
+  ui::EventTarget* GetTargetAt(const gfx::Point& point) override {
+    return root_window_->GetHost()->window();
   }
 
   aura::client::ScreenPositionClient* GetScreenPositionClient(
@@ -426,8 +426,9 @@
     if (input_source() == INPUT_SOURCE_MOUSE)
       return;
 #if defined(OS_CHROMEOS)
-    event_generator_.reset(new ui::test::EventGenerator(
-        new ScreenEventGeneratorDelegate(ash::wm::GetRootWindowAt(point))));
+    event_generator_ = std::make_unique<ui::test::EventGenerator>(
+        std::make_unique<ScreenEventGeneratorDelegate>(
+            ash::wm::GetRootWindowAt(point)));
 #endif
   }
 
diff --git a/chrome/test/base/default_ash_event_generator_delegate.cc b/chrome/test/base/default_ash_event_generator_delegate.cc
index 7038982..897a828 100644
--- a/chrome/test/base/default_ash_event_generator_delegate.cc
+++ b/chrome/test/base/default_ash_event_generator_delegate.cc
@@ -4,21 +4,40 @@
 
 #include "chrome/test/base/default_ash_event_generator_delegate.h"
 
-DefaultAshEventGeneratorDelegate*
-DefaultAshEventGeneratorDelegate::GetInstance() {
-  return base::Singleton<DefaultAshEventGeneratorDelegate>::get();
-}
+#include "ash/shell.h"
+#include "base/macros.h"
+#include "ui/aura/test/event_generator_delegate_aura.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_tree_host.h"
 
-void DefaultAshEventGeneratorDelegate::SetContext(
-    ui::test::EventGenerator* owner,
-    gfx::NativeWindow root_window,
-    gfx::NativeWindow window) {
-  root_window_ = root_window;
-}
+namespace {
 
-aura::WindowTreeHost* DefaultAshEventGeneratorDelegate::GetHostAt(
-    const gfx::Point& point) const {
-  return root_window_->GetHost();
+class DefaultAshEventGeneratorDelegate
+    : public aura::test::EventGeneratorDelegateAura {
+ public:
+  explicit DefaultAshEventGeneratorDelegate(aura::Window* root_window);
+  ~DefaultAshEventGeneratorDelegate() override = default;
+
+  // aura::test::EventGeneratorDelegateAura:
+  ui::EventTarget* GetTargetAt(const gfx::Point& location) override;
+  aura::client::ScreenPositionClient* GetScreenPositionClient(
+      const aura::Window* window) const override;
+  ui::EventDispatchDetails DispatchKeyEventToIME(ui::EventTarget* target,
+                                                 ui::KeyEvent* event) override;
+
+ private:
+  aura::Window* root_window_;
+
+  DISALLOW_COPY_AND_ASSIGN(DefaultAshEventGeneratorDelegate);
+};
+
+DefaultAshEventGeneratorDelegate::DefaultAshEventGeneratorDelegate(
+    aura::Window* root_window)
+    : root_window_(root_window) {}
+
+ui::EventTarget* DefaultAshEventGeneratorDelegate::GetTargetAt(
+    const gfx::Point& location) {
+  return root_window_->GetHost()->window();
 }
 
 aura::client::ScreenPositionClient*
@@ -33,13 +52,11 @@
   return ui::EventDispatchDetails();
 }
 
-DefaultAshEventGeneratorDelegate::DefaultAshEventGeneratorDelegate()
-    : root_window_(nullptr) {
-  DCHECK(!ui::test::EventGenerator::default_delegate);
-  ui::test::EventGenerator::default_delegate = this;
-}
+}  // namespace
 
-DefaultAshEventGeneratorDelegate::~DefaultAshEventGeneratorDelegate() {
-  DCHECK_EQ(this, ui::test::EventGenerator::default_delegate);
-  ui::test::EventGenerator::default_delegate = nullptr;
+std::unique_ptr<ui::test::EventGeneratorDelegate>
+CreateAshEventGeneratorDelegate(ui::test::EventGenerator* owner,
+                                gfx::NativeWindow root_window,
+                                gfx::NativeWindow window) {
+  return std::make_unique<DefaultAshEventGeneratorDelegate>(root_window);
 }
diff --git a/chrome/test/base/default_ash_event_generator_delegate.h b/chrome/test/base/default_ash_event_generator_delegate.h
index 9327ed7..2d93a89 100644
--- a/chrome/test/base/default_ash_event_generator_delegate.h
+++ b/chrome/test/base/default_ash_event_generator_delegate.h
@@ -5,40 +5,20 @@
 #ifndef CHROME_TEST_BASE_DEFAULT_ASH_EVENT_GENERATOR_DELEGATE_H_
 #define CHROME_TEST_BASE_DEFAULT_ASH_EVENT_GENERATOR_DELEGATE_H_
 
-#include "ash/shell.h"
-#include "base/macros.h"
-#include "base/memory/singleton.h"
-#include "ui/aura/test/event_generator_delegate_aura.h"
-#include "ui/aura/window.h"
+#include <memory>
 
-class DefaultAshEventGeneratorDelegate
-    : public aura::test::EventGeneratorDelegateAura {
- public:
-  static DefaultAshEventGeneratorDelegate* GetInstance();
+#include "ui/gfx/native_widget_types.h"
 
-  // EventGeneratorDelegate:
-  void SetContext(ui::test::EventGenerator* owner,
-                  gfx::NativeWindow root_window,
-                  gfx::NativeWindow window) override;
+namespace ui {
+namespace test {
+class EventGenerator;
+class EventGeneratorDelegate;
+}  // namespace test
+}  // namespace ui
 
-  aura::WindowTreeHost* GetHostAt(const gfx::Point& point) const override;
-
-  aura::client::ScreenPositionClient* GetScreenPositionClient(
-      const aura::Window* window) const override;
-
-  ui::EventDispatchDetails DispatchKeyEventToIME(ui::EventTarget* target,
-                                                 ui::KeyEvent* event) override;
-
- private:
-  friend struct base::DefaultSingletonTraits<DefaultAshEventGeneratorDelegate>;
-
-  DefaultAshEventGeneratorDelegate();
-
-  ~DefaultAshEventGeneratorDelegate() override;
-
-  aura::Window* root_window_;
-
-  DISALLOW_COPY_AND_ASSIGN(DefaultAshEventGeneratorDelegate);
-};
+std::unique_ptr<ui::test::EventGeneratorDelegate>
+CreateAshEventGeneratorDelegate(ui::test::EventGenerator* owner,
+                                gfx::NativeWindow root_window,
+                                gfx::NativeWindow window);
 
 #endif  // CHROME_TEST_BASE_DEFAULT_ASH_EVENT_GENERATOR_DELEGATE_H_
diff --git a/chrome/test/base/in_process_browser_test.cc b/chrome/test/base/in_process_browser_test.cc
index 466f44c1..02ded52 100644
--- a/chrome/test/base/in_process_browser_test.cc
+++ b/chrome/test/base/in_process_browser_test.cc
@@ -89,6 +89,7 @@
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/input_method/input_method_configuration.h"
 #include "chrome/test/base/default_ash_event_generator_delegate.h"
+#include "ui/events/test/event_generator.h"
 #endif  // defined(OS_CHROMEOS)
 
 #if !defined(OS_CHROMEOS) && defined(OS_LINUX)
@@ -153,7 +154,8 @@
 #endif
 
 #if defined(OS_CHROMEOS)
-  DefaultAshEventGeneratorDelegate::GetInstance();
+  ui::test::EventGeneratorDelegate::SetFactoryFunction(
+      base::BindRepeating(&CreateAshEventGeneratorDelegate));
 #endif
 
 #if defined(TOOLKIT_VIEWS)
diff --git a/chromecast/graphics/accessibility/partial_magnification_controller_unittest.cc b/chromecast/graphics/accessibility/partial_magnification_controller_unittest.cc
index f82c21f5..fbdf65ee 100644
--- a/chromecast/graphics/accessibility/partial_magnification_controller_unittest.cc
+++ b/chromecast/graphics/accessibility/partial_magnification_controller_unittest.cc
@@ -40,8 +40,8 @@
   ~TestEventGeneratorDelegate() override = default;
 
   // EventGeneratorDelegateAura overrides:
-  aura::WindowTreeHost* GetHostAt(const gfx::Point& point) const override {
-    return root_window_->GetHost();
+  ui::EventTarget* GetTargetAt(const gfx::Point& point) override {
+    return root_window_->GetHost()->window();
   }
 
   aura::client::ScreenPositionClient* GetScreenPositionClient(
@@ -113,8 +113,8 @@
 
   ui::test::EventGenerator& GetEventGenerator() {
     if (!event_generator_) {
-      event_generator_.reset(new ui::test::EventGenerator(
-          new TestEventGeneratorDelegate(root_window())));
+      event_generator_ = std::make_unique<ui::test::EventGenerator>(
+          std::make_unique<TestEventGeneratorDelegate>(root_window()));
     }
     return *event_generator_.get();
   }
diff --git a/chromecast/graphics/gestures/side_swipe_detector_test.cc b/chromecast/graphics/gestures/side_swipe_detector_test.cc
index 71760dba..dc041d8 100644
--- a/chromecast/graphics/gestures/side_swipe_detector_test.cc
+++ b/chromecast/graphics/gestures/side_swipe_detector_test.cc
@@ -43,8 +43,8 @@
   ~TestEventGeneratorDelegate() override = default;
 
   // EventGeneratorDelegateAura overrides:
-  aura::WindowTreeHost* GetHostAt(const gfx::Point& point) const override {
-    return root_window_->GetHost();
+  ui::EventTarget* GetTargetAt(const gfx::Point& point) override {
+    return root_window_->GetHost()->window();
   }
 
   aura::client::ScreenPositionClient* GetScreenPositionClient(
@@ -154,8 +154,8 @@
 
   ui::test::EventGenerator& GetEventGenerator() {
     if (!event_generator_) {
-      event_generator_.reset(new ui::test::EventGenerator(
-          new TestEventGeneratorDelegate(root_window())));
+      event_generator_ = std::make_unique<ui::test::EventGenerator>(
+          std::make_unique<TestEventGeneratorDelegate>(root_window()));
     }
     return *event_generator_.get();
   }
diff --git a/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc b/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc
index d8350f38..86f8645c 100644
--- a/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc
+++ b/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc
@@ -682,8 +682,6 @@
             rwhva->selection_controller()->active_status());
   EXPECT_FALSE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
 
-  ui::test::EventGeneratorDelegate* generator_delegate =
-      ui::test::EventGenerator::default_delegate;
   gfx::NativeView native_view = rwhva->GetNativeView();
   ui::test::EventGenerator generator(native_view->GetRootWindow());
 
@@ -694,7 +692,7 @@
   gfx::PointF point_f;
   ASSERT_TRUE(GetPointInsideTextfield(&point_f));
   gfx::Point point = gfx::ToRoundedPoint(point_f);
-  generator_delegate->ConvertPointFromTarget(native_view, &point);
+  generator.delegate()->ConvertPointFromTarget(native_view, &point);
   generator.GestureTapAt(point);
 
   selection_controller_client()->Wait();
@@ -707,7 +705,7 @@
   // Tap on the insertion handle; the quick menu should appear.
   gfx::Point handle_center = gfx::ToRoundedPoint(
       rwhva->selection_controller()->GetStartHandleRect().CenterPoint());
-  generator_delegate->ConvertPointFromTarget(native_view, &handle_center);
+  generator.delegate()->ConvertPointFromTarget(native_view, &handle_center);
   generator.GestureTapAt(handle_center);
   EXPECT_TRUE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
 
diff --git a/content/public/test/browser_test_base.cc b/content/public/test/browser_test_base.cc
index cb5fcf4c..d0cc5562 100644
--- a/content/public/test/browser_test_base.cc
+++ b/content/public/test/browser_test_base.cc
@@ -141,6 +141,11 @@
   base::i18n::AllowMultipleInitializeCallsForTesting();
 
   embedded_test_server_ = std::make_unique<net::EmbeddedTestServer>();
+
+#if defined(USE_AURA)
+  ui::test::EventGeneratorDelegate::SetFactoryFunction(
+      base::BindRepeating(&aura::test::EventGeneratorDelegateAura::Create));
+#endif
 }
 
 BrowserTestBase::~BrowserTestBase() {
@@ -205,8 +210,6 @@
   // us to, or it's requested on the command line.
   if (!enable_pixel_output_ && !use_software_compositing_)
     command_line->AppendSwitch(switches::kDisableGLDrawingForTests);
-
-  aura::test::InitializeAuraEventGeneratorDelegate();
 #endif
 
   bool use_software_gl = true;
@@ -327,6 +330,10 @@
 }
 
 void BrowserTestBase::TearDown() {
+#if defined(USE_AURA)
+  ui::test::EventGeneratorDelegate::SetFactoryFunction(
+      ui::test::EventGeneratorDelegate::FactoryFunction());
+#endif
 }
 
 bool BrowserTestBase::AllowFileAccessFromFiles() const {
diff --git a/ui/aura/test/aura_test_helper.cc b/ui/aura/test/aura_test_helper.cc
index 38fa90f..e13a577 100644
--- a/ui/aura/test/aura_test_helper.cc
+++ b/ui/aura/test/aura_test_helper.cc
@@ -53,7 +53,6 @@
   zero_duration_mode_.reset(new ui::ScopedAnimationDurationScaleMode(
       ui::ScopedAnimationDurationScaleMode::ZERO_DURATION));
   ui::test::EnableTestConfigForPlatformWindows();
-  InitializeAuraEventGeneratorDelegate();
 }
 
 AuraTestHelper::~AuraTestHelper() {
@@ -91,6 +90,8 @@
 
 void AuraTestHelper::SetUp(ui::ContextFactory* context_factory,
                            ui::ContextFactoryPrivate* context_factory_private) {
+  ui::test::EventGeneratorDelegate::SetFactoryFunction(
+      base::BindRepeating(&EventGeneratorDelegateAura::Create));
   // If Env has been configured with MUS, but |mode_| is still |LOCAL|, switch
   // to MUS. This is used for tests suites that setup Env globally.
   if (Env::HasInstance() && Env::GetInstance()->mode() == Env::Mode::MUS &&
@@ -203,6 +204,9 @@
     EnvTestHelper().SetMode(env_mode_to_restore_);
   }
   wm_state_.reset();
+
+  ui::test::EventGeneratorDelegate::SetFactoryFunction(
+      ui::test::EventGeneratorDelegate::FactoryFunction());
 }
 
 void AuraTestHelper::RunAllPendingInMessageLoop() {
diff --git a/ui/aura/test/event_generator_delegate_aura.cc b/ui/aura/test/event_generator_delegate_aura.cc
index abe5dfc..ff633db 100644
--- a/ui/aura/test/event_generator_delegate_aura.cc
+++ b/ui/aura/test/event_generator_delegate_aura.cc
@@ -5,7 +5,6 @@
 #include "ui/aura/test/event_generator_delegate_aura.h"
 
 #include "base/macros.h"
-#include "base/memory/singleton.h"
 #include "ui/aura/client/screen_position_client.h"
 #include "ui/aura/env.h"
 #include "ui/aura/test/env_test_helper.h"
@@ -20,40 +19,22 @@
 
 class DefaultEventGeneratorDelegate : public EventGeneratorDelegateAura {
  public:
-  static DefaultEventGeneratorDelegate* GetInstance() {
-    return base::Singleton<DefaultEventGeneratorDelegate>::get();
-  }
+  explicit DefaultEventGeneratorDelegate(gfx::NativeWindow root_window)
+      : root_window_(root_window) {}
 
-  // EventGeneratorDelegate:
-  void SetContext(ui::test::EventGenerator* owner,
-                  gfx::NativeWindow root_window,
-                  gfx::NativeWindow window) override {
-    root_window_ = root_window;
-  }
+  ~DefaultEventGeneratorDelegate() override = default;
 
   // EventGeneratorDelegateAura:
-  WindowTreeHost* GetHostAt(const gfx::Point& point) const override {
-    return root_window_->GetHost();
+  ui::EventTarget* GetTargetAt(const gfx::Point& location) override {
+    return root_window_->GetHost()->window();
   }
 
   client::ScreenPositionClient* GetScreenPositionClient(
       const aura::Window* window) const override {
-    return NULL;
+    return nullptr;
   }
 
  private:
-  friend struct base::DefaultSingletonTraits<DefaultEventGeneratorDelegate>;
-
-  DefaultEventGeneratorDelegate() : root_window_(NULL) {
-    DCHECK(!ui::test::EventGenerator::default_delegate);
-    ui::test::EventGenerator::default_delegate = this;
-  }
-
-  ~DefaultEventGeneratorDelegate() override {
-    DCHECK_EQ(this, ui::test::EventGenerator::default_delegate);
-    ui::test::EventGenerator::default_delegate = NULL;
-  }
-
   Window* root_window_;
 
   DISALLOW_COPY_AND_ASSIGN(DefaultEventGeneratorDelegate);
@@ -65,23 +46,17 @@
 
 }  // namespace
 
-void InitializeAuraEventGeneratorDelegate() {
-  if (!ui::test::EventGenerator::default_delegate)
-    DefaultEventGeneratorDelegate::GetInstance();
+// static
+std::unique_ptr<ui::test::EventGeneratorDelegate>
+EventGeneratorDelegateAura::Create(ui::test::EventGenerator* owner,
+                                   gfx::NativeWindow root_window,
+                                   gfx::NativeWindow window) {
+  return std::make_unique<DefaultEventGeneratorDelegate>(root_window);
 }
 
-EventGeneratorDelegateAura::EventGeneratorDelegateAura() {
-}
+EventGeneratorDelegateAura::EventGeneratorDelegateAura() = default;
 
-EventGeneratorDelegateAura::~EventGeneratorDelegateAura() {
-}
-
-ui::EventTarget* EventGeneratorDelegateAura::GetTargetAt(
-    const gfx::Point& location) {
-  // TODO(andresantoso): Add support for EventGenerator::targeting_application()
-  // if needed for Ash.
-  return GetHostAt(location)->window();
-}
+EventGeneratorDelegateAura::~EventGeneratorDelegateAura() = default;
 
 ui::EventSource* EventGeneratorDelegateAura::GetEventSource(
     ui::EventTarget* target) {
diff --git a/ui/aura/test/event_generator_delegate_aura.h b/ui/aura/test/event_generator_delegate_aura.h
index c856e8a..c72bf89f 100644
--- a/ui/aura/test/event_generator_delegate_aura.h
+++ b/ui/aura/test/event_generator_delegate_aura.h
@@ -8,9 +8,10 @@
 #include "base/macros.h"
 #include "ui/events/test/event_generator.h"
 
+#include <memory>
+
 namespace aura {
 class Window;
-class WindowTreeHost;
 
 namespace client {
 class ScreenPositionClient;
@@ -18,16 +19,16 @@
 
 namespace test {
 
-void InitializeAuraEventGeneratorDelegate();
-
 // Implementation of ui::test::EventGeneratorDelegate for Aura.
 class EventGeneratorDelegateAura : public ui::test::EventGeneratorDelegate {
  public:
   EventGeneratorDelegateAura();
   ~EventGeneratorDelegateAura() override;
 
-  // Returns the host for given point.
-  virtual WindowTreeHost* GetHostAt(const gfx::Point& point) const = 0;
+  static std::unique_ptr<ui::test::EventGeneratorDelegate> Create(
+      ui::test::EventGenerator* owner,
+      gfx::NativeWindow root_window,
+      gfx::NativeWindow window);
 
   // Returns the screen position client that determines the
   // coordinates used in EventGenerator. EventGenerator uses
@@ -36,7 +37,6 @@
       const aura::Window* window) const = 0;
 
   // Overridden from ui::test::EventGeneratorDelegate:
-  ui::EventTarget* GetTargetAt(const gfx::Point& location) override;
   ui::EventSource* GetEventSource(ui::EventTarget* target) override;
   gfx::Point CenterOfTarget(const ui::EventTarget* target) const override;
   gfx::Point CenterOfWindow(gfx::NativeWindow window) const override;
diff --git a/ui/events/test/event_generator.cc b/ui/events/test/event_generator.cc
index c602b542..23216d3 100644
--- a/ui/events/test/event_generator.cc
+++ b/ui/events/test/event_generator.cc
@@ -83,18 +83,32 @@
 
 const int kAllButtonMask = ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON;
 
+EventGeneratorDelegate::FactoryFunction g_event_generator_delegate_factory;
+
 }  // namespace
 
-EventGeneratorDelegate* EventGenerator::default_delegate = NULL;
+// static
+void EventGeneratorDelegate::SetFactoryFunction(FactoryFunction factory) {
+  g_event_generator_delegate_factory = std::move(factory);
+}
+
+// static
+std::unique_ptr<EventGeneratorDelegate> EventGeneratorDelegate::Create(
+    EventGenerator* owner,
+    gfx::NativeWindow root_window,
+    gfx::NativeWindow window) {
+  DCHECK(g_event_generator_delegate_factory);
+  return g_event_generator_delegate_factory.Run(owner, root_window, window);
+}
 
 EventGenerator::EventGenerator(gfx::NativeWindow root_window) {
-  Init(root_window, NULL);
+  Init(root_window, nullptr);
 }
 
 EventGenerator::EventGenerator(gfx::NativeWindow root_window,
                                const gfx::Point& point)
     : current_location_(point) {
-  Init(root_window, NULL);
+  Init(root_window, nullptr);
 }
 
 EventGenerator::EventGenerator(gfx::NativeWindow root_window,
@@ -102,14 +116,13 @@
   Init(root_window, window);
 }
 
-EventGenerator::EventGenerator(EventGeneratorDelegate* delegate)
-    : delegate_(delegate) {
-  Init(NULL, NULL);
+EventGenerator::EventGenerator(std::unique_ptr<EventGeneratorDelegate> delegate)
+    : delegate_(std::move(delegate)) {
+  Init(nullptr, nullptr);
 }
 
 EventGenerator::~EventGenerator() {
   pending_events_.clear();
-  delegate()->SetContext(NULL, NULL, NULL);
   ui::SetEventTickClockForTesting(nullptr);
 }
 
@@ -165,15 +178,9 @@
   Dispatch(&mouseev);
 }
 
+#if defined(OS_CHROMEOS)
 void EventGenerator::MoveMouseToWithNative(const gfx::Point& point_in_host,
                                            const gfx::Point& point_for_native) {
-#if defined(USE_X11)
-  ui::ScopedXI2Event xevent;
-  xevent.InitMotionEvent(point_in_host, point_for_native, flags_);
-  static_cast<XEvent*>(xevent)->xmotion.time =
-      (ui::EventTimeForNow() - base::TimeTicks()).InMilliseconds() & UINT32_MAX;
-  ui::MouseEvent mouseev(xevent);
-#elif defined(USE_OZONE)
   // Ozone uses the location in native event as a system location.
   // Create a fake event with the point in host, which will be passed
   // to the non native event, then update the native event with the native
@@ -183,17 +190,12 @@
                          ui::EventTimeForNow(), flags_, 0));
   ui::MouseEvent mouseev(native_event.get());
   native_event->set_location(point_for_native);
-#else
-  ui::MouseEvent mouseev(ui::ET_MOUSE_MOVED, point_in_host, point_for_native,
-                         ui::EventTimeForNow(), flags_, 0);
-  LOG(FATAL)
-      << "Generating a native motion event is not supported on this platform";
-#endif
   Dispatch(&mouseev);
 
   current_location_ = point_in_host;
   delegate()->ConvertPointFromHost(current_target_, &current_location_);
 }
+#endif
 
 void EventGenerator::MoveMouseToInHost(const gfx::Point& point_in_host) {
   const ui::EventType event_type = (flags_ & ui::EF_LEFT_MOUSE_BUTTON) ?
@@ -633,7 +635,11 @@
                           gfx::NativeWindow window_context) {
   tick_clock_ = std::make_unique<TestTickClock>();
   ui::SetEventTickClockForTesting(tick_clock_.get());
-  delegate()->SetContext(this, root_window, window_context);
+  if (!delegate_) {
+    DCHECK(g_event_generator_delegate_factory);
+    delegate_ = g_event_generator_delegate_factory.Run(this, root_window,
+                                                       window_context);
+  }
   if (window_context)
     current_location_ = delegate()->CenterOfWindow(window_context);
   current_target_ = delegate()->GetTargetAt(current_location_);
@@ -778,18 +784,5 @@
   }
 }
 
-const EventGeneratorDelegate* EventGenerator::delegate() const {
-  if (delegate_)
-    return delegate_.get();
-
-  DCHECK(default_delegate);
-  return default_delegate;
-}
-
-EventGeneratorDelegate* EventGenerator::delegate() {
-  return const_cast<EventGeneratorDelegate*>(
-      const_cast<const EventGenerator*>(this)->delegate());
-}
-
 }  // namespace test
 }  // namespace ui
diff --git a/ui/events/test/event_generator.h b/ui/events/test/event_generator.h
index 79ec888..35f71e6 100644
--- a/ui/events/test/event_generator.h
+++ b/ui/events/test/event_generator.h
@@ -40,11 +40,21 @@
  public:
   virtual ~EventGeneratorDelegate() {}
 
-  // Set the context of the delegate, whilst it is being used by an active
-  // EventGenerator.
-  virtual void SetContext(EventGenerator* owner,
-                          gfx::NativeWindow root_window,
-                          gfx::NativeWindow window) {}
+  // This factory function is used by EventGenerator to create a delegate if an
+  // EventGeneratorDelegate was not supplied to the constructor.
+  using FactoryFunction =
+      base::RepeatingCallback<std::unique_ptr<EventGeneratorDelegate>(
+          EventGenerator* owner,
+          gfx::NativeWindow root_window,
+          gfx::NativeWindow window)>;
+  static void SetFactoryFunction(FactoryFunction factory);
+
+  // Creates an EventGeneratorDelegate using the factory set by way of
+  // SetFactoryFunction().
+  static std::unique_ptr<EventGeneratorDelegate> Create(
+      EventGenerator* owner,
+      gfx::NativeWindow root_window,
+      gfx::NativeWindow window);
 
   // The ui::EventTarget at the given |location|.
   virtual EventTarget* GetTargetAt(const gfx::Point& location) = 0;
@@ -112,7 +122,7 @@
   // Create an EventGenerator with EventGeneratorDelegate,
   // which uses the coordinates conversions and targeting provided by
   // |delegate|.
-  explicit EventGenerator(EventGeneratorDelegate* delegate);
+  explicit EventGenerator(std::unique_ptr<EventGeneratorDelegate> delegate);
 
   // Creates an EventGenerator with the mouse/touch location
   // at |initial_location|, which uses the |root_window|'s coordinates.
@@ -206,10 +216,12 @@
     MoveMouseToInHost(gfx::Point(x, y));
   }
 
+#if defined(OS_CHROMEOS)
   // Generates a mouse move event at the point given in the host
   // coordinates, with a native event with |point_for_natve|.
   void MoveMouseToWithNative(const gfx::Point& point_in_host,
                              const gfx::Point& point_for_native);
+#endif
 
   // Generates events to move mouse to be the given |point| in screen
   // coordinates.
@@ -439,8 +451,8 @@
     current_target_ = target;
   }
 
-  // Default delegate set by a platform-specific GeneratorDelegate singleton.
-  static EventGeneratorDelegate* default_delegate;
+  const EventGeneratorDelegate* delegate() const { return delegate_.get(); }
+  EventGeneratorDelegate* delegate() { return delegate_.get(); }
 
  private:
   // Set up the test context using the delegate.
@@ -463,9 +475,6 @@
   // touch event.
   void MaybeDispatchToPointerWatchers(const Event& event);
 
-  const EventGeneratorDelegate* delegate() const;
-  EventGeneratorDelegate* delegate();
-
   std::unique_ptr<EventGeneratorDelegate> delegate_;
   gfx::Point current_location_;
   EventTarget* current_target_ = nullptr;
diff --git a/ui/views/test/event_generator_delegate_mac.h b/ui/views/test/event_generator_delegate_mac.h
index 86239ba..1e866c0 100644
--- a/ui/views/test/event_generator_delegate_mac.h
+++ b/ui/views/test/event_generator_delegate_mac.h
@@ -5,10 +5,24 @@
 #ifndef UI_VIEWS_TEST_EVENT_GENERATOR_DELEGATE_MAC_H_
 #define UI_VIEWS_TEST_EVENT_GENERATOR_DELEGATE_MAC_H_
 
+#include <memory>
+
+#include "ui/gfx/native_widget_types.h"
+
+namespace ui {
+namespace test {
+class EventGenerator;
+class EventGeneratorDelegate;
+}  // namespace test
+}  // namespace ui
+
 namespace views {
 namespace test {
 
-void InitializeMacEventGeneratorDelegate();
+std::unique_ptr<ui::test::EventGeneratorDelegate>
+CreateEventGeneratorDelegateMac(ui::test::EventGenerator* owner,
+                                gfx::NativeWindow root_window,
+                                gfx::NativeWindow window);
 
 }  // namespace test
 }  // namespace views
diff --git a/ui/views/test/event_generator_delegate_mac.mm b/ui/views/test/event_generator_delegate_mac.mm
index af8c4001..6b76d6d 100644
--- a/ui/views/test/event_generator_delegate_mac.mm
+++ b/ui/views/test/event_generator_delegate_mac.mm
@@ -245,9 +245,12 @@
                                   public ui::EventTargeter,
                                   public ui::test::EventGeneratorDelegate {
  public:
-  static EventGeneratorDelegateMac* GetInstance() {
-    return base::Singleton<EventGeneratorDelegateMac>::get();
-  }
+  EventGeneratorDelegateMac(ui::test::EventGenerator* owner,
+                            gfx::NativeWindow root_window,
+                            gfx::NativeWindow window);
+  ~EventGeneratorDelegateMac() override;
+
+  static EventGeneratorDelegateMac* instance() { return instance_; }
 
   IMP CurrentEventMethod() {
     return swizzle_current_event_->GetOriginalImplementation();
@@ -294,9 +297,6 @@
   }
 
   // Overridden from ui::test::EventGeneratorDelegate:
-  void SetContext(ui::test::EventGenerator* owner,
-                  gfx::NativeWindow root_window,
-                  gfx::NativeWindow window) override;
   ui::EventTarget* GetTargetAt(const gfx::Point& location) override {
     return this;
   }
@@ -321,10 +321,7 @@
   }
 
  private:
-  friend struct base::DefaultSingletonTraits<EventGeneratorDelegateMac>;
-
-  EventGeneratorDelegateMac();
-  ~EventGeneratorDelegateMac() override;
+  static EventGeneratorDelegateMac* instance_;
 
   ui::test::EventGenerator* owner_;
   base::scoped_nsobject<NSWindow> window_;
@@ -344,9 +341,16 @@
   DISALLOW_COPY_AND_ASSIGN(EventGeneratorDelegateMac);
 };
 
-EventGeneratorDelegateMac::EventGeneratorDelegateMac() : owner_(nullptr) {
-  DCHECK(!ui::test::EventGenerator::default_delegate);
-  ui::test::EventGenerator::default_delegate = this;
+// static
+EventGeneratorDelegateMac* EventGeneratorDelegateMac::instance_ = nullptr;
+
+EventGeneratorDelegateMac::EventGeneratorDelegateMac(
+    ui::test::EventGenerator* owner,
+    gfx::NativeWindow root_window,
+    gfx::NativeWindow window)
+    : owner_(owner) {
+  DCHECK(!instance_);
+  instance_ = this;
   SetTargetHandler(this);
   // Install a fake "edit" menu. This is normally provided by Chrome's
   // MainMenu.xib, but src/ui shouldn't depend on that.
@@ -369,11 +373,43 @@
                       keyEquivalent:fake_menu_item[i].key_equivalent
                             atIndex:i];
   }
+
+  // Mac doesn't use a |root_window|. Assume that if a single-argument
+  // constructor was used, it should be the actual |window|.
+  if (!window)
+    window = root_window;
+
+  swizzle_pressed_.reset();
+  swizzle_location_.reset();
+  swizzle_current_event_.reset();
+
+  // Retain the NSWindow (note it can be nil). This matches Cocoa's tendency to
+  // have autoreleased objects, or objects still in the event queue, that
+  // reference the NSWindow.
+  window_.reset([window retain]);
+
+  // Normally, edit menu items have a `nil` target. This results in -[NSMenu
+  // performKeyEquivalent:] relying on -[NSApplication targetForAction:to:from:]
+  // to find a target starting at the first responder of the key window. Since
+  // non-interactive tests have no key window, that won't work. So set (or
+  // clear) the target explicitly on all menu items.
+  [[fake_menu_ itemArray] makeObjectsPerformSelector:@selector(setTarget:)
+                                          withObject:[window firstResponder]];
+
+  if (owner_) {
+    swizzle_pressed_.reset(new base::mac::ScopedObjCClassSwizzler(
+        [NSEvent class], [NSEventDonor class], @selector(pressedMouseButtons)));
+    swizzle_location_.reset(new base::mac::ScopedObjCClassSwizzler(
+        [NSEvent class], [NSEventDonor class], @selector(mouseLocation)));
+    swizzle_current_event_.reset(new base::mac::ScopedObjCClassSwizzler(
+        [NSApplication class], [NSApplicationDonor class],
+        @selector(currentEvent)));
+  }
 }
 
 EventGeneratorDelegateMac::~EventGeneratorDelegateMac() {
-  DCHECK_EQ(this, ui::test::EventGenerator::default_delegate);
-  ui::test::EventGenerator::default_delegate = nullptr;
+  DCHECK_EQ(instance_, this);
+  instance_ = nullptr;
 }
 
 std::unique_ptr<ui::EventTargetIterator>
@@ -518,46 +554,6 @@
   last_scroll_timestamp_ = event->time_stamp();
 }
 
-void EventGeneratorDelegateMac::SetContext(ui::test::EventGenerator* owner,
-                                           gfx::NativeWindow root_window,
-                                           gfx::NativeWindow window) {
-  // Mac doesn't use a |root_window|. Assume that if a single-argument
-  // constructor was used, it should be the actual |window|.
-  if (!window)
-    window = root_window;
-
-  swizzle_pressed_.reset();
-  swizzle_location_.reset();
-  swizzle_current_event_.reset();
-  owner_ = owner;
-
-  // Retain the NSWindow (note it can be nil). This matches Cocoa's tendency to
-  // have autoreleased objects, or objects still in the event queue, that
-  // reference the NSWindow.
-  window_.reset([window retain]);
-
-  // Normally, edit menu items have a `nil` target. This results in -[NSMenu
-  // performKeyEquivalent:] relying on -[NSApplication targetForAction:to:from:]
-  // to find a target starting at the first responder of the key window. Since
-  // non-interactive tests have no key window, that won't work. So set (or
-  // clear) the target explicitly on all menu items.
-  [[fake_menu_ itemArray] makeObjectsPerformSelector:@selector(setTarget:)
-                                          withObject:[window firstResponder]];
-
-  if (owner_) {
-    swizzle_pressed_.reset(new base::mac::ScopedObjCClassSwizzler(
-        [NSEvent class],
-        [NSEventDonor class],
-        @selector(pressedMouseButtons)));
-    swizzle_location_.reset(new base::mac::ScopedObjCClassSwizzler(
-        [NSEvent class], [NSEventDonor class], @selector(mouseLocation)));
-    swizzle_current_event_.reset(new base::mac::ScopedObjCClassSwizzler(
-        [NSApplication class],
-        [NSApplicationDonor class],
-        @selector(currentEvent)));
-  }
-}
-
 gfx::Point EventGeneratorDelegateMac::CenterOfTarget(
     const ui::EventTarget* target) const {
   DCHECK_EQ(target, this);
@@ -573,7 +569,9 @@
 }
 
 ui::test::EventGenerator* GetActiveGenerator() {
-  return EventGeneratorDelegateMac::GetInstance()->owner();
+  return EventGeneratorDelegateMac::instance()
+             ? EventGeneratorDelegateMac::instance()->owner()
+             : nullptr;
 }
 
 }  // namespace
@@ -581,10 +579,13 @@
 namespace views {
 namespace test {
 
-void InitializeMacEventGeneratorDelegate() {
-  EventGeneratorDelegateMac::GetInstance();
+std::unique_ptr<ui::test::EventGeneratorDelegate>
+CreateEventGeneratorDelegateMac(ui::test::EventGenerator* owner,
+                                gfx::NativeWindow root_window,
+                                gfx::NativeWindow window) {
+  return std::make_unique<EventGeneratorDelegateMac>(owner, root_window,
+                                                     window);
 }
-
 }  // namespace test
 }  // namespace views
 
@@ -617,7 +618,7 @@
   // The location is the point in the root window which, for desktop widgets, is
   // the widget itself.
   gfx::Point point_in_root = generator->current_location();
-  NSWindow* window = EventGeneratorDelegateMac::GetInstance()->window();
+  NSWindow* window = EventGeneratorDelegateMac::instance()->window();
   NSPoint point_in_window = ConvertRootPointToTarget(window, point_in_root);
   return ui::ConvertPointFromWindowToScreen(window, point_in_window);
 }
@@ -631,7 +632,7 @@
     return g_current_event;
 
   // Find the original implementation and invoke it.
-  IMP original = EventGeneratorDelegateMac::GetInstance()->CurrentEventMethod();
+  IMP original = EventGeneratorDelegateMac::instance()->CurrentEventMethod();
   return original(self, _cmd);
 }
 
diff --git a/ui/views/test/views_test_helper_mac.mm b/ui/views/test/views_test_helper_mac.mm
index 8ddf8611..8146f9b 100644
--- a/ui/views/test/views_test_helper_mac.mm
+++ b/ui/views/test/views_test_helper_mac.mm
@@ -6,12 +6,14 @@
 
 #import <Cocoa/Cocoa.h>
 
+#include "base/bind.h"
 #import "base/mac/scoped_nsautorelease_pool.h"
 #include "ui/base/test/scoped_fake_full_keyboard_access.h"
 #include "ui/base/test/scoped_fake_nswindow_focus.h"
 #include "ui/base/test/scoped_fake_nswindow_fullscreen.h"
 #include "ui/base/test/ui_controls.h"
 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
+#include "ui/events/test/event_generator.h"
 #include "ui/views/test/event_generator_delegate_mac.h"
 #include "ui/views/widget/widget.h"
 
@@ -27,8 +29,6 @@
 ViewsTestHelperMac::ViewsTestHelperMac()
     : zero_duration_mode_(new ui::ScopedAnimationDurationScaleMode(
           ui::ScopedAnimationDurationScaleMode::ZERO_DURATION)) {
-  test::InitializeMacEventGeneratorDelegate();
-
   // Unbundled applications (those without Info.plist) default to
   // NSApplicationActivationPolicyProhibited, which prohibits the application
   // obtaining key status or activating windows without user interaction.
@@ -39,6 +39,9 @@
 }
 
 void ViewsTestHelperMac::SetUp() {
+  ui::test::EventGeneratorDelegate::SetFactoryFunction(
+      base::BindRepeating(&test::CreateEventGeneratorDelegateMac));
+
   ViewsTestHelper::SetUp();
   // Assume that if the methods in the ui_controls.h test header are enabled
   // then the test runner is in a non-sharded mode, and will use "real"
@@ -62,6 +65,9 @@
   NSArray* native_windows = [NSApp windows];
   for (NSWindow* window : native_windows)
     DCHECK(!Widget::GetWidgetForNativeWindow(window)) << "Widget not closed.";
+
+  ui::test::EventGeneratorDelegate::SetFactoryFunction(
+      ui::test::EventGeneratorDelegate::FactoryFunction());
 }
 
 }  // namespace views