Reland "aura: makes each Window be associated with an Env"

This reverts commit c179496f2b0ebc20360350c65aff0c4941c57e26.

Reason for revert: The test failure was fixed at https://chromium-review.googlesource.com/c/chromium/src/+/1168466 . The failure was a lingering issue and not caused by patch (but triggered by my patch), so reverting the revert.

Original change's description:
> Revert "aura: makes each Window be associated with an Env"
> 
> This reverts commit 99df3b2694dd3dab4860e9f20ee5a6235d9746c4.
> 
> Reason for revert: Caused failures on msan bot.
> 
> Original change's description:
> > aura: makes each Window be associated with an Env
> > 
> > This is to avoid using Env::GetInstance(), so that there can be multiple
> > Envs created at once.
> > 
> > BUG=847992
> > TEST=covered by tests
> > 
> > Change-Id: I2e2604c8f8a356ca9cc6771ed050ef8431e7b840
> > Reviewed-on: https://chromium-review.googlesource.com/1165861
> > Commit-Queue: Scott Violet <sky@chromium.org>
> > Reviewed-by: Michael Wasserman <msw@chromium.org>
> > Cr-Commit-Position: refs/heads/master@{#581568}
> 
> TBR=sky@chromium.org,msw@chromium.org
> 
> Change-Id: I50fb5f0d27011219ed2569b1035a78e01b9b3de9
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: 847992
> Reviewed-on: https://chromium-review.googlesource.com/1168323
> Reviewed-by: Scott Violet <sky@chromium.org>
> Commit-Queue: Scott Violet <sky@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#581718}

TBR=sky@chromium.org,msw@chromium.org

Change-Id: I83e61d6ca9de8dcd023757f03bb18f0abf09790e
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: 847992
Reviewed-on: https://chromium-review.googlesource.com/1168565
Reviewed-by: Scott Violet <sky@chromium.org>
Commit-Queue: Scott Violet <sky@chromium.org>
Cr-Commit-Position: refs/heads/master@{#581796}
diff --git a/ui/aura/env.cc b/ui/aura/env.cc
index 6f009fa..b8c4f9a 100644
--- a/ui/aura/env.cc
+++ b/ui/aura/env.cc
@@ -187,7 +187,7 @@
 
 Env::Env(Mode mode)
     : mode_(mode),
-      env_controller_(new EnvInputStateController),
+      env_controller_(std::make_unique<EnvInputStateController>(this)),
       mouse_button_flags_(0),
       is_touch_down_(false),
       get_last_mouse_location_from_mus_(mode_ == Mode::MUS),
diff --git a/ui/aura/env_input_state_controller.cc b/ui/aura/env_input_state_controller.cc
index 59fe1ca..e547287 100644
--- a/ui/aura/env_input_state_controller.cc
+++ b/ui/aura/env_input_state_controller.cc
@@ -11,16 +11,20 @@
 
 namespace aura {
 
+EnvInputStateController::EnvInputStateController(Env* env) : env_(env) {}
+
+EnvInputStateController::~EnvInputStateController() = default;
+
 void EnvInputStateController::UpdateStateForMouseEvent(
     const Window* window,
     const ui::MouseEvent& event) {
   switch (event.type()) {
     case ui::ET_MOUSE_PRESSED:
-      Env::GetInstance()->set_mouse_button_flags(event.button_flags());
+      env_->set_mouse_button_flags(event.button_flags());
       break;
     case ui::ET_MOUSE_RELEASED:
-      Env::GetInstance()->set_mouse_button_flags(
-          event.button_flags() & ~event.changed_button_flags());
+      env_->set_mouse_button_flags(event.button_flags() &
+                                   ~event.changed_button_flags());
       break;
     default:
       break;
@@ -40,7 +44,7 @@
   switch (event.type()) {
     case ui::ET_TOUCH_PRESSED:
       touch_ids_down_ |= (1 << event.pointer_details().id);
-      Env::GetInstance()->set_touch_down(touch_ids_down_ != 0);
+      env_->set_touch_down(touch_ids_down_ != 0);
       break;
 
     // Handle ET_TOUCH_CANCELLED only if it has a native event.
@@ -51,7 +55,7 @@
     case ui::ET_TOUCH_RELEASED:
       touch_ids_down_ = (touch_ids_down_ | (1 << event.pointer_details().id)) ^
                         (1 << event.pointer_details().id);
-      Env::GetInstance()->set_touch_down(touch_ids_down_ != 0);
+      env_->set_touch_down(touch_ids_down_ != 0);
       break;
 
     case ui::ET_TOUCH_MOVED:
@@ -68,7 +72,7 @@
     const gfx::Point& location_in_root) const {
   // If |root_window| is null, we are only using the event to update event
   // states, so we shouldn't update mouse location.
-  if (!root_window && Env::GetInstance()->mode() == aura::Env::Mode::MUS)
+  if (!root_window && env_->mode() == aura::Env::Mode::MUS)
     return;
 
   client::ScreenPositionClient* client =
@@ -76,9 +80,9 @@
   if (client) {
     gfx::Point location_in_screen = location_in_root;
     client->ConvertPointToScreen(root_window, &location_in_screen);
-    Env::GetInstance()->SetLastMouseLocation(location_in_screen);
+    env_->SetLastMouseLocation(location_in_screen);
   } else {
-    Env::GetInstance()->SetLastMouseLocation(location_in_root);
+    env_->SetLastMouseLocation(location_in_root);
   }
 }
 
diff --git a/ui/aura/env_input_state_controller.h b/ui/aura/env_input_state_controller.h
index 4ceb29e4..1d36764 100644
--- a/ui/aura/env_input_state_controller.h
+++ b/ui/aura/env_input_state_controller.h
@@ -24,12 +24,13 @@
 class EnvTestHelper;
 }
 
+class Env;
 class Window;
 
 class AURA_EXPORT EnvInputStateController {
  public:
-  EnvInputStateController() : touch_ids_down_(0) {}
-  ~EnvInputStateController() {}
+  explicit EnvInputStateController(Env* env);
+  ~EnvInputStateController();
 
   void UpdateStateForMouseEvent(const Window* window,
                                 const ui::MouseEvent& event);
@@ -39,8 +40,10 @@
 
  private:
   friend class test::EnvTestHelper;
+
+  Env* env_;
   // Touch ids that are currently down.
-  uint32_t touch_ids_down_;
+  uint32_t touch_ids_down_ = 0;
 
   DISALLOW_COPY_AND_ASSIGN(EnvInputStateController);
 };
diff --git a/ui/aura/event_injector.cc b/ui/aura/event_injector.cc
index 103c2b4..86153a3 100644
--- a/ui/aura/event_injector.cc
+++ b/ui/aura/event_injector.cc
@@ -8,6 +8,7 @@
 #include "services/ui/public/interfaces/constants.mojom.h"
 #include "ui/aura/env.h"
 #include "ui/aura/mus/window_tree_client.h"
+#include "ui/aura/window.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/events/event.h"
 #include "ui/events/event_sink.h"
@@ -38,9 +39,9 @@
 
 ui::EventDispatchDetails EventInjector::Inject(WindowTreeHost* host,
                                                ui::Event* event) {
-  Env* env = Env::GetInstance();
-  DCHECK(env);
   DCHECK(host);
+  Env* env = host->window()->env();
+  DCHECK(env);
   DCHECK(event);
 
   if (env->mode() == Env::Mode::LOCAL)
diff --git a/ui/aura/local/window_port_local.cc b/ui/aura/local/window_port_local.cc
index 7444e0b..50d6b04 100644
--- a/ui/aura/local/window_port_local.cc
+++ b/ui/aura/local/window_port_local.cc
@@ -28,7 +28,7 @@
     if (!window_->IsRootWindow())
       return;
     const bool cursor_is_in_bounds = window_->GetBoundsInScreen().Contains(
-        Env::GetInstance()->last_mouse_location());
+        window->env()->last_mouse_location());
     client::CursorClient* cursor_client = client::GetCursorClient(window_);
     if (cursor_is_in_bounds && cursor_client &&
         cursor_client->IsCursorVisible()) {
@@ -133,8 +133,7 @@
 std::unique_ptr<cc::LayerTreeFrameSink>
 WindowPortLocal::CreateLayerTreeFrameSink() {
   DCHECK(!frame_sink_id_.is_valid());
-  auto* context_factory_private =
-      aura::Env::GetInstance()->context_factory_private();
+  auto* context_factory_private = window_->env()->context_factory_private();
   auto* host_frame_sink_manager =
       context_factory_private->GetHostFrameSinkManager();
   frame_sink_id_ = context_factory_private->AllocateFrameSinkId();
@@ -154,7 +153,7 @@
 
   cc::mojo_embedder::AsyncLayerTreeFrameSink::InitParams params;
   params.gpu_memory_buffer_manager =
-      aura::Env::GetInstance()->context_factory()->GetGpuMemoryBufferManager();
+      window_->env()->context_factory()->GetGpuMemoryBufferManager();
   params.pipes.compositor_frame_sink_info = std::move(sink_info);
   params.pipes.client_request = std::move(client_request);
   params.enable_surface_synchronization = true;
diff --git a/ui/aura/mus/window_tree_host_mus.cc b/ui/aura/mus/window_tree_host_mus.cc
index 4cfedd6..7d6e017 100644
--- a/ui/aura/mus/window_tree_host_mus.cc
+++ b/ui/aura/mus/window_tree_host_mus.cc
@@ -38,13 +38,15 @@
 // WindowTreeHostMus, public:
 
 WindowTreeHostMus::WindowTreeHostMus(WindowTreeHostMusInitParams init_params)
-    : WindowTreeHostPlatform(std::move(init_params.window_port)),
+    : WindowTreeHostPlatform(
+          std::make_unique<Window>(nullptr,
+                                   std::move(init_params.window_port))),
       display_id_(init_params.display_id),
       delegate_(init_params.window_tree_client) {
   gfx::Rect bounds_in_pixels;
   window()->SetProperty(kWindowTreeHostMusKey, this);
-  // TODO(sky): find a cleaner way to set this! Better solution is to likely
-  // have constructor take aura::Window.
+  // TODO(sky): find a cleaner way to set this! Revisit this now that
+  // constructor takes a Window.
   WindowPortMus* window_mus = WindowPortMus::Get(window());
   window_mus->window_ = window();
   // Apply the properties before initializing the window, that way the server
diff --git a/ui/aura/test/event_generator_delegate_aura.cc b/ui/aura/test/event_generator_delegate_aura.cc
index 0fbdee8..abe5dfc 100644
--- a/ui/aura/test/event_generator_delegate_aura.cc
+++ b/ui/aura/test/event_generator_delegate_aura.cc
@@ -66,9 +66,8 @@
 }  // namespace
 
 void InitializeAuraEventGeneratorDelegate() {
-  if (!ui::test::EventGenerator::default_delegate) {
+  if (!ui::test::EventGenerator::default_delegate)
     DefaultEventGeneratorDelegate::GetInstance();
-  }
 }
 
 EventGeneratorDelegateAura::EventGeneratorDelegateAura() {
diff --git a/ui/aura/test/test_screen.cc b/ui/aura/test/test_screen.cc
index cb0b962..17bd578e 100644
--- a/ui/aura/test/test_screen.cc
+++ b/ui/aura/test/test_screen.cc
@@ -161,7 +161,10 @@
 }
 
 gfx::Point TestScreen::GetCursorScreenPoint() {
-  return Env::GetInstance()->last_mouse_location();
+  // This may be hit during shutdown, after |host_| has been destroyed.
+  return host_ && host_->window()
+             ? host_->window()->env()->last_mouse_location()
+             : gfx::Point();
 }
 
 bool TestScreen::IsWindowUnderCursor(gfx::NativeWindow window) {
diff --git a/ui/aura/test/test_windows.cc b/ui/aura/test/test_windows.cc
index 69430295..07328d8 100644
--- a/ui/aura/test/test_windows.cc
+++ b/ui/aura/test/test_windows.cc
@@ -8,12 +8,22 @@
 
 #include "base/strings/string_number_conversions.h"
 #include "ui/aura/client/aura_constants.h"
+#include "ui/aura/env.h"
 #include "ui/aura/window.h"
 #include "ui/compositor/layer.h"
 #include "ui/gfx/geometry/rect.h"
 
 namespace aura {
 namespace test {
+namespace {
+
+static Env* g_env = nullptr;
+
+}  // namespace
+
+void SetEnvForTestWindows(Env* env) {
+  g_env = env;
+}
 
 Window* CreateTestWindowWithId(int id, Window* parent) {
   return CreateTestWindowWithDelegate(NULL, id, gfx::Rect(), parent);
@@ -45,9 +55,8 @@
                                             const gfx::Rect& bounds,
                                             Window* parent,
                                             bool show_on_creation) {
-  Window* window = new Window(delegate);
+  Window* window = new Window(delegate, type, g_env);
   window->set_id(id);
-  window->SetType(type);
   window->Init(ui::LAYER_TEXTURED);
   window->SetProperty(aura::client::kResizeBehaviorKey,
                       ui::mojom::kResizeBehaviorCanResize |
diff --git a/ui/aura/test/test_windows.h b/ui/aura/test/test_windows.h
index 6d37931..6379ff1 100644
--- a/ui/aura/test/test_windows.h
+++ b/ui/aura/test/test_windows.h
@@ -14,8 +14,14 @@
 #include "ui/aura/test/test_window_delegate.h"
 
 namespace aura {
+class Env;
+
 namespace test {
 
+// Sets the Env to use for creation of new Windows. If null, Env::GetInstance()
+// is used.
+void SetEnvForTestWindows(Env* env);
+
 Window* CreateTestWindowWithId(int id, Window* parent);
 Window* CreateTestWindowWithBounds(const gfx::Rect& bounds, Window* parent);
 Window* CreateTestWindow(SkColor color,
diff --git a/ui/aura/test/ui_controls_factory_aurax11.cc b/ui/aura/test/ui_controls_factory_aurax11.cc
index 1763f8c..63d1998 100644
--- a/ui/aura/test/ui_controls_factory_aurax11.cc
+++ b/ui/aura/test/ui_controls_factory_aurax11.cc
@@ -144,7 +144,7 @@
                                      int accelerator_state) override {
     XEvent xevent = {0};
     XButtonEvent* xbutton = &xevent.xbutton;
-    gfx::Point mouse_loc = aura::Env::GetInstance()->last_mouse_location();
+    gfx::Point mouse_loc = host_->window()->env()->last_mouse_location();
     aura::client::ScreenPositionClient* screen_position_client =
           aura::client::GetScreenPositionClient(host_->window());
     if (screen_position_client) {
diff --git a/ui/aura/test/ui_controls_factory_ozone.cc b/ui/aura/test/ui_controls_factory_ozone.cc
index a503e9a..934d828 100644
--- a/ui/aura/test/ui_controls_factory_ozone.cc
+++ b/ui/aura/test/ui_controls_factory_ozone.cc
@@ -155,7 +155,7 @@
                                      int button_state,
                                      base::OnceClosure closure,
                                      int accelerator_state) override {
-    gfx::Point root_location = aura::Env::GetInstance()->last_mouse_location();
+    gfx::Point root_location = host_->window()->env()->last_mouse_location();
     aura::client::ScreenPositionClient* screen_position_client =
         aura::client::GetScreenPositionClient(host_->window());
     if (screen_position_client) {
@@ -218,7 +218,7 @@
 
  private:
   void SendEventToSink(ui::Event* event, base::OnceClosure closure) {
-    if (aura::Env::GetInstance()->mode() == aura::Env::Mode::MUS) {
+    if (host_->window()->env()->mode() == aura::Env::Mode::MUS) {
       std::unique_ptr<ui::Event> event_to_send;
       if (event->IsMouseEvent()) {
         // WindowService expects MouseEvents as PointerEvents.
@@ -297,7 +297,7 @@
   // Returns the ui::mojom::EventInjector, which is used to send events
   // to the Window Service for dispatch.
   ui::mojom::EventInjector* GetEventInjector() {
-    DCHECK_EQ(aura::Env::Mode::MUS, aura::Env::GetInstance()->mode());
+    DCHECK_EQ(aura::Env::Mode::MUS, host_->window()->env()->mode());
     if (!event_injector_) {
       DCHECK(aura::test::EnvTestHelper().GetWindowTreeClient());
       aura::test::EnvTestHelper()
diff --git a/ui/aura/window.cc b/ui/aura/window.cc
index 110eac9c..ff65b9e1 100644
--- a/ui/aura/window.cc
+++ b/ui/aura/window.cc
@@ -52,13 +52,15 @@
 
 namespace aura {
 
-Window::Window(WindowDelegate* delegate, client::WindowType type)
-    : Window(delegate, nullptr, type) {}
+Window::Window(WindowDelegate* delegate, client::WindowType type, Env* env)
+    : Window(delegate, nullptr, type, env) {}
 
 Window::Window(WindowDelegate* delegate,
                std::unique_ptr<WindowPort> port,
-               client::WindowType type)
-    : port_owner_(std::move(port)),
+               client::WindowType type,
+               Env* env)
+    : env_(env ? env : Env::GetInstance()),
+      port_owner_(std::move(port)),
       port_(port_owner_.get()),
       host_(nullptr),
       type_(type),
@@ -148,7 +150,7 @@
   WindowOcclusionTracker::ScopedPauseOcclusionTracking pause_occlusion_tracking;
 
   if (!port_owner_) {
-    port_owner_ = Env::GetInstance()->CreateWindowPort(this);
+    port_owner_ = env_->CreateWindowPort(this);
     port_ = port_owner_.get();
   }
   SetLayer(std::make_unique<ui::Layer>(layer_type));
@@ -157,7 +159,7 @@
   layer()->set_delegate(this);
   UpdateLayerName();
   layer()->SetFillsBoundsOpaquely(!transparent_);
-  Env::GetInstance()->NotifyWindowInitialized(this);
+  env_->NotifyWindowInitialized(this);
 }
 
 void Window::SetType(client::WindowType type) {
@@ -358,6 +360,8 @@
 
   DCHECK(layer()) << "Parent has not been Init()ed yet.";
   DCHECK(child->layer()) << "Child has not been Init()ed yt.";
+  DCHECK_EQ(env_, child->env_) << "All windows in a hierarchy must share the "
+                                  " same Env.";
   WindowObserver::HierarchyChangeParams params;
   params.target = child;
   params.new_parent = this;
@@ -1211,9 +1215,9 @@
 
 ui::EventTarget* Window::GetParentTarget() {
   if (IsRootWindow()) {
-    return client::GetEventClient(this) ?
-        client::GetEventClient(this)->GetToplevelEventTarget() :
-            Env::GetInstance();
+    return client::GetEventClient(this)
+               ? client::GetEventClient(this)->GetToplevelEventTarget()
+               : env_;
   }
   return parent_;
 }
diff --git a/ui/aura/window.h b/ui/aura/window.h
index 4e21096b..b6308ee9 100644
--- a/ui/aura/window.h
+++ b/ui/aura/window.h
@@ -57,6 +57,7 @@
 
 namespace aura {
 
+class Env;
 class LayoutManager;
 class ScopedKeyboardHook;
 class WindowDelegate;
@@ -118,10 +119,12 @@
   typedef std::vector<Window*> Windows;
 
   explicit Window(WindowDelegate* delegate,
-                  client::WindowType type = client::WINDOW_TYPE_UNKNOWN);
+                  client::WindowType type = client::WINDOW_TYPE_UNKNOWN,
+                  Env* env = nullptr);
   Window(WindowDelegate* delegate,
          std::unique_ptr<WindowPort> port,
-         client::WindowType type = client::WINDOW_TYPE_UNKNOWN);
+         client::WindowType type = client::WINDOW_TYPE_UNKNOWN,
+         Env* env = nullptr);
   ~Window() override;
 
   // Initializes the window. This creates the window's layer.
@@ -422,6 +425,8 @@
   // Returns whether this window is embedding another client.
   bool IsEmbeddingClient() const;
 
+  Env* env() { return env_; }
+
   // ui::GestureConsumer:
   bool RequiresDoubleTapGestureEvents() const override;
 
@@ -554,6 +559,11 @@
 
   void RegisterFrameSinkId();
   void UnregisterFrameSinkId();
+
+  // Env this window was created with. Env::GetInstance() if a null Env was
+  // supplied.
+  Env* const env_;
+
   bool registered_frame_sink_id_ = false;
   bool disable_frame_sink_id_registration_ = false;
 
diff --git a/ui/aura/window_event_dispatcher.cc b/ui/aura/window_event_dispatcher.cc
index 68dcb9ab..81fabbc 100644
--- a/ui/aura/window_event_dispatcher.cc
+++ b/ui/aura/window_event_dispatcher.cc
@@ -81,16 +81,16 @@
 WindowEventDispatcher::ObserverNotifier::ObserverNotifier(
     WindowEventDispatcher* dispatcher,
     const ui::Event& event)
-    : dispatcher_(dispatcher) {
+    : env_(dispatcher->host()->window()->env()), dispatcher_(dispatcher) {
   for (WindowEventDispatcherObserver& observer :
-       Env::GetInstance()->window_event_dispatcher_observers()) {
+       env_->window_event_dispatcher_observers()) {
     observer.OnWindowEventDispatcherStartedProcessing(dispatcher, event);
   }
 }
 
 WindowEventDispatcher::ObserverNotifier::~ObserverNotifier() {
   for (WindowEventDispatcherObserver& observer :
-       Env::GetInstance()->window_event_dispatcher_observers()) {
+       env_->window_event_dispatcher_observers()) {
     observer.OnWindowEventDispatcherFinishedProcessingEvent(dispatcher_);
   }
 }
@@ -100,19 +100,20 @@
 
 WindowEventDispatcher::WindowEventDispatcher(WindowTreeHost* host,
                                              bool are_events_in_pixels)
-    : host_(host),
+    : env_(host->window()->env()),
+      host_(host),
       are_events_in_pixels_(are_events_in_pixels),
       observer_manager_(this),
       event_targeter_(std::make_unique<WindowTargeter>()) {
   ui::GestureRecognizer::Get()->AddGestureEventHelper(this);
-  Env::GetInstance()->AddObserver(this);
-  if (Env::GetInstance()->mode() == Env::Mode::MUS)
+  env_->AddObserver(this);
+  if (env_->mode() == Env::Mode::MUS)
     mus_mouse_location_updater_ = std::make_unique<MusMouseLocationUpdater>();
 }
 
 WindowEventDispatcher::~WindowEventDispatcher() {
   TRACE_EVENT0("shutdown", "WindowEventDispatcher::Destructor");
-  Env::GetInstance()->RemoveObserver(this);
+  env_->RemoveObserver(this);
   ui::GestureRecognizer::Get()->RemoveGestureEventHelper(this);
 }
 
@@ -236,7 +237,7 @@
 }
 
 gfx::Point WindowEventDispatcher::GetLastMouseLocationInRoot() const {
-  gfx::Point location = Env::GetInstance()->last_mouse_location();
+  gfx::Point location = host_->window()->env()->last_mouse_location();
   ConvertPointFromScreen(&location);
   return location;
 }
@@ -248,8 +249,8 @@
 
 void WindowEventDispatcher::OnCursorMovedToRootLocation(
     const gfx::Point& root_location) {
-  Env::GetInstance()->env_controller()->SetLastMouseLocation(window(),
-                                                             root_location);
+  host_->window()->env()->env_controller()->SetLastMouseLocation(window(),
+                                                                 root_location);
 
   // Synthesize a mouse move in case the cursor's location in root coordinates
   // changed but its position in WindowTreeHost coordinates did not.
@@ -305,8 +306,8 @@
     Window* target,
     const ui::MouseEvent& event,
     ui::EventType type) {
-  Env::GetInstance()->env_controller()->UpdateStateForMouseEvent(window(),
-                                                                 event);
+  host_->window()->env()->env_controller()->UpdateStateForMouseEvent(window(),
+                                                                     event);
   if (!mouse_moved_handler_ || !mouse_moved_handler_->HasTargetHandler() ||
       !window()->Contains(mouse_moved_handler_))
     return DispatchDetails();
@@ -424,7 +425,7 @@
   if (new_capture) {
     // Make all subsequent mouse events go to the capture window. We shouldn't
     // need to send an event here as OnCaptureLost() should take care of that.
-    if (mouse_moved_handler_ || Env::GetInstance()->IsMouseButtonDown())
+    if (mouse_moved_handler_ || host_->window()->env()->IsMouseButtonDown())
       mouse_moved_handler_ = new_capture;
   } else {
     // Make sure mouse_moved_handler gets updated.
@@ -471,7 +472,7 @@
 
 ui::EventTarget* WindowEventDispatcher::GetInitialEventTarget(
     ui::Event* event) {
-  if (Env::GetInstance()->mode() == Env::Mode::LOCAL ||
+  if (host_->window()->env()->mode() == Env::Mode::LOCAL ||
       !event->IsLocatedEvent() || !event->target()) {
     return nullptr;
   }
@@ -508,7 +509,7 @@
 }
 
 ui::EventTarget* WindowEventDispatcher::GetRootForEvent(ui::Event* event) {
-  if (Env::GetInstance()->mode() == Env::Mode::LOCAL)
+  if (host_->window()->env()->mode() == Env::Mode::LOCAL)
     return window();
 
   if (!event->target())
@@ -831,7 +832,7 @@
   if (!dispatch_details.dispatcher_destroyed) {
     dispatching_held_event_ = nullptr;
     for (WindowEventDispatcherObserver& observer :
-         Env::GetInstance()->window_event_dispatcher_observers()) {
+         host_->window()->env()->window_event_dispatcher_observers()) {
       observer.OnWindowEventDispatcherDispatchedHeldEvents(this);
     }
     if (did_dispatch_held_move_event_callback_)
@@ -880,7 +881,7 @@
   // instead of a MOVED event, but in multi-display/multi-host scenarios, the
   // DRAGGED event can be synthesized in the incorrect host. So avoid
   // synthesizing any events at all.
-  if (Env::GetInstance()->mouse_button_flags())
+  if (host_->window()->env()->mouse_button_flags())
     return details;
 
   // Do not use GetLastMouseLocationInRoot here because it's not updated when
@@ -930,8 +931,8 @@
     return DispatchDetails();
   }
 
-  Env::GetInstance()->env_controller()->UpdateStateForMouseEvent(window(),
-                                                                 *event);
+  host_->window()->env()->env_controller()->UpdateStateForMouseEvent(window(),
+                                                                     *event);
 
   if (IsEventCandidateForHold(*event) && !dispatching_held_event_) {
     if (move_hold_count_) {
@@ -1046,7 +1047,7 @@
     return DispatchDetails();
   }
 
-  Env::GetInstance()->env_controller()->UpdateStateForTouchEvent(*event);
+  host_->window()->env()->env_controller()->UpdateStateForTouchEvent(*event);
 
   ui::TouchEvent orig_event(*event, target, window());
   if (!ui::GestureRecognizer::Get()->ProcessTouchEventPreDispatch(&orig_event,
diff --git a/ui/aura/window_event_dispatcher.h b/ui/aura/window_event_dispatcher.h
index 95747b07..e3fcb83 100644
--- a/ui/aura/window_event_dispatcher.h
+++ b/ui/aura/window_event_dispatcher.h
@@ -38,6 +38,7 @@
 }
 
 namespace aura {
+class Env;
 class MusMouseLocationUpdater;
 class TestScreen;
 class WindowTargeter;
@@ -153,6 +154,7 @@
     ~ObserverNotifier();
 
    private:
+    Env* env_;
     WindowEventDispatcher* dispatcher_;
 
     DISALLOW_COPY_AND_ASSIGN(ObserverNotifier);
@@ -281,6 +283,10 @@
                                                  ui::TouchEvent* event);
   ui::EventDispatchDetails PreDispatchKeyEvent(ui::KeyEvent* event);
 
+  // Comes from host_->window()->env(). Cached as it's needed in the destructor
+  // and at that time the window has been deleted.
+  Env* env_;
+
   WindowTreeHost* host_;
 
   const bool are_events_in_pixels_;
diff --git a/ui/aura/window_tree_host.cc b/ui/aura/window_tree_host.cc
index eb60ca9..64d0817c 100644
--- a/ui/aura/window_tree_host.cc
+++ b/ui/aura/window_tree_host.cc
@@ -17,7 +17,6 @@
 #include "ui/aura/scoped_simple_keyboard_hook.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_event_dispatcher.h"
-#include "ui/aura/window_port.h"
 #include "ui/aura/window_targeter.h"
 #include "ui/aura/window_tree_host_observer.h"
 #include "ui/base/ime/input_method.h"
@@ -47,11 +46,11 @@
 const char kWindowTreeHostForAcceleratedWidget[] =
     "__AURA_WINDOW_TREE_HOST_ACCELERATED_WIDGET__";
 
-bool ShouldAllocateLocalSurfaceId() {
+bool ShouldAllocateLocalSurfaceId(Window* window) {
   // When running with the window service (either in 'mus' or 'mash' mode), the
   // LocalSurfaceId allocation for the WindowTreeHost is managed by the
   // WindowTreeClient and WindowTreeHostMus.
-  return Env::GetInstance()->mode() == Env::Mode::LOCAL;
+  return window->env()->mode() == Env::Mode::LOCAL;
 }
 
 #if DCHECK_IS_ON()
@@ -62,9 +61,8 @@
         local_surface_id_(window ? window->GetLocalSurfaceId()
                                  : viz::LocalSurfaceId()) {}
   ~ScopedLocalSurfaceIdValidator() {
-    if (ShouldAllocateLocalSurfaceId() && window_) {
+    if (window_ && ShouldAllocateLocalSurfaceId(window_))
       DCHECK_EQ(local_surface_id_, window_->GetLocalSurfaceId());
-    }
   }
 
  private:
@@ -109,7 +107,7 @@
 
   UpdateRootWindowSizeInPixels();
   InitCompositor();
-  Env::GetInstance()->NotifyHostInitialized(this);
+  window()->env()->NotifyHostInitialized(this);
 }
 
 void WindowTreeHost::AddObserver(WindowTreeHostObserver* observer) {
@@ -291,15 +289,14 @@
 ////////////////////////////////////////////////////////////////////////////////
 // WindowTreeHost, protected:
 
-WindowTreeHost::WindowTreeHost() : WindowTreeHost(nullptr) {
-}
-
-WindowTreeHost::WindowTreeHost(std::unique_ptr<WindowPort> window_port)
-    : window_(new Window(nullptr, std::move(window_port))),
+WindowTreeHost::WindowTreeHost(std::unique_ptr<Window> window)
+    : window_(window.release()),  // See header for details on ownership.
       last_cursor_(ui::CursorType::kNull),
       input_method_(nullptr),
       owned_input_method_(false),
       weak_factory_(this) {
+  if (!window_)
+    window_ = new Window(nullptr);
   display::Screen::GetScreen()->AddObserver(this);
 }
 
@@ -329,13 +326,14 @@
                                       bool force_software_compositor,
                                       bool external_begin_frames_enabled,
                                       bool are_events_in_pixels) {
-  DCHECK(Env::GetInstance());
-  ui::ContextFactory* context_factory = Env::GetInstance()->context_factory();
+  DCHECK(window()->env());
+  Env* env = window()->env();
+  ui::ContextFactory* context_factory = env->context_factory();
   DCHECK(context_factory);
   ui::ContextFactoryPrivate* context_factory_private =
-      Env::GetInstance()->context_factory_private();
+      env->context_factory_private();
   bool enable_surface_synchronization =
-      aura::Env::GetInstance()->mode() == aura::Env::Mode::MUS ||
+      env->mode() == aura::Env::Mode::MUS ||
       features::IsSurfaceSynchronizationEnabled();
   compositor_.reset(new ui::Compositor(
       (!context_factory_private || frame_sink_id.is_valid())
@@ -393,7 +391,8 @@
 
   // Allocate a new LocalSurfaceId for the new state.
   auto local_surface_id = new_local_surface_id;
-  if (ShouldAllocateLocalSurfaceId() && !new_local_surface_id.is_valid()) {
+  if (ShouldAllocateLocalSurfaceId(window()) &&
+      !new_local_surface_id.is_valid()) {
     window_->AllocateLocalSurfaceId();
     local_surface_id = window_->GetLocalSurfaceId();
   }
@@ -424,7 +423,7 @@
 }
 
 void WindowTreeHost::OnHostActivated() {
-  Env::GetInstance()->NotifyHostActivated(this);
+  window()->env()->NotifyHostActivated(this);
 }
 
 void WindowTreeHost::OnHostLostWindowCapture() {
@@ -503,7 +502,7 @@
 }
 
 void WindowTreeHost::OnCompositingChildResizing(ui::Compositor* compositor) {
-  if (!Env::GetInstance()->throttle_input_on_resize() || holding_pointer_moves_)
+  if (!window()->env()->throttle_input_on_resize() || holding_pointer_moves_)
     return;
   synchronization_start_time_ = base::TimeTicks::Now();
   dispatcher_->HoldPointerMoves();
diff --git a/ui/aura/window_tree_host.h b/ui/aura/window_tree_host.h
index 77c28cf..660b1570 100644
--- a/ui/aura/window_tree_host.h
+++ b/ui/aura/window_tree_host.h
@@ -19,6 +19,7 @@
 #include "components/viz/common/surfaces/frame_sink_id.h"
 #include "components/viz/common/surfaces/local_surface_id.h"
 #include "ui/aura/aura_export.h"
+#include "ui/aura/window.h"
 #include "ui/base/cursor/cursor.h"
 #include "ui/base/ime/input_method_delegate.h"
 #include "ui/compositor/compositor_observer.h"
@@ -51,7 +52,6 @@
 }
 
 class WindowEventDispatcher;
-class WindowPort;
 class WindowTreeHostObserver;
 
 // WindowTreeHost bridges between a native window and the embedded RootWindow.
@@ -222,8 +222,7 @@
   friend class ScopedKeyboardHook;
   friend class TestScreen;  // TODO(beng): see if we can remove/consolidate.
 
-  WindowTreeHost();
-  explicit WindowTreeHost(std::unique_ptr<WindowPort> window_port);
+  explicit WindowTreeHost(std::unique_ptr<Window> window = nullptr);
 
   void DestroyCompositor();
   void DestroyDispatcher();
diff --git a/ui/aura/window_tree_host_platform.cc b/ui/aura/window_tree_host_platform.cc
index 7176c8b..75eb9f5 100644
--- a/ui/aura/window_tree_host_platform.cc
+++ b/ui/aura/window_tree_host_platform.cc
@@ -10,8 +10,8 @@
 #include "base/run_loop.h"
 #include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
+#include "ui/aura/window.h"
 #include "ui/aura/window_event_dispatcher.h"
-#include "ui/aura/window_port.h"
 #include "ui/base/layout.h"
 #include "ui/compositor/compositor.h"
 #include "ui/events/event.h"
@@ -46,18 +46,16 @@
 }
 
 WindowTreeHostPlatform::WindowTreeHostPlatform(
-    ui::PlatformWindowInitProperties properties) {
+    ui::PlatformWindowInitProperties properties,
+    std::unique_ptr<Window> window)
+    : WindowTreeHost(std::move(window)) {
   bounds_ = properties.bounds;
   CreateCompositor();
   CreateAndSetPlatformWindow(std::move(properties));
 }
 
-WindowTreeHostPlatform::WindowTreeHostPlatform()
-    : WindowTreeHostPlatform(nullptr) {}
-
-WindowTreeHostPlatform::WindowTreeHostPlatform(
-    std::unique_ptr<WindowPort> window_port)
-    : WindowTreeHost(std::move(window_port)),
+WindowTreeHostPlatform::WindowTreeHostPlatform(std::unique_ptr<Window> window)
+    : WindowTreeHost(std::move(window)),
       widget_(gfx::kNullAcceleratedWidget),
       current_cursor_(ui::CursorType::kNull) {}
 
diff --git a/ui/aura/window_tree_host_platform.h b/ui/aura/window_tree_host_platform.h
index b5bd90a..5ea1727 100644
--- a/ui/aura/window_tree_host_platform.h
+++ b/ui/aura/window_tree_host_platform.h
@@ -11,6 +11,7 @@
 #include "base/macros.h"
 #include "ui/aura/aura_export.h"
 #include "ui/aura/client/window_types.h"
+#include "ui/aura/window.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/platform_window/platform_window.h"
@@ -24,14 +25,13 @@
 
 namespace aura {
 
-class WindowPort;
-
 // The unified WindowTreeHost implementation for platforms
 // that implement PlatformWindow.
 class AURA_EXPORT WindowTreeHostPlatform : public WindowTreeHost,
                                            public ui::PlatformWindowDelegate {
  public:
-  explicit WindowTreeHostPlatform(ui::PlatformWindowInitProperties properties);
+  explicit WindowTreeHostPlatform(ui::PlatformWindowInitProperties properties,
+                                  std::unique_ptr<Window> = nullptr);
   ~WindowTreeHostPlatform() override;
 
   // WindowTreeHost:
@@ -51,10 +51,9 @@
   void OnCursorVisibilityChangedNative(bool show) override;
 
  protected:
-  // NOTE: neither of these calls CreateCompositor(); subclasses must call
+  // NOTE: this does not call CreateCompositor(); subclasses must call
   // CreateCompositor() at the appropriate time.
-  WindowTreeHostPlatform();
-  explicit WindowTreeHostPlatform(std::unique_ptr<WindowPort> window_port);
+  explicit WindowTreeHostPlatform(std::unique_ptr<Window> window = nullptr);
 
   // Creates a ui::PlatformWindow appropriate for the current platform and
   // installs it at as the PlatformWindow for this WindowTreeHostPlatform.