// Copyright 2014 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 "ui/aura/mus/window_tree_client.h"

#include <stddef.h>

#include <string>
#include <utility>
#include <vector>

#include "base/auto_reset.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/threading/thread.h"
#include "cc/base/switches.h"
#include "components/discardable_memory/client/client_discardable_shared_memory_manager.h"
#include "mojo/public/cpp/bindings/map.h"
#include "services/service_manager/public/cpp/connector.h"
#include "services/ui/common/accelerator_util.h"
#include "services/ui/common/util.h"
#include "services/ui/public/cpp/gpu/gpu.h"
#include "services/ui/public/cpp/property_type_converters.h"
#include "services/ui/public/interfaces/constants.mojom.h"
#include "services/ui/public/interfaces/window_manager.mojom.h"
#include "services/ui/public/interfaces/window_manager_window_tree_factory.mojom.h"
#include "services/ui/public/interfaces/window_tree_host_factory.mojom.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/drag_drop_client.h"
#include "ui/aura/client/transient_window_client.h"
#include "ui/aura/env.h"
#include "ui/aura/env_input_state_controller.h"
#include "ui/aura/mus/capture_synchronizer.h"
#include "ui/aura/mus/drag_drop_controller_mus.h"
#include "ui/aura/mus/focus_synchronizer.h"
#include "ui/aura/mus/in_flight_change.h"
#include "ui/aura/mus/input_method_mus.h"
#include "ui/aura/mus/mus_context_factory.h"
#include "ui/aura/mus/property_converter.h"
#include "ui/aura/mus/property_utils.h"
#include "ui/aura/mus/window_manager_delegate.h"
#include "ui/aura/mus/window_mus.h"
#include "ui/aura/mus/window_port_mus.h"
#include "ui/aura/mus/window_tree_client_delegate.h"
#include "ui/aura/mus/window_tree_client_observer.h"
#include "ui/aura/mus/window_tree_client_test_observer.h"
#include "ui/aura/mus/window_tree_host_mus.h"
#include "ui/aura/mus/window_tree_host_mus_init_params.h"
#include "ui/aura/window.h"
#include "ui/aura/window_delegate.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_port_for_shutdown.h"
#include "ui/aura/window_tracker.h"
#include "ui/base/layout.h"
#include "ui/base/ui_base_features.h"
#include "ui/base/ui_base_switches_util.h"
#include "ui/base/ui_base_types.h"
#include "ui/display/screen.h"
#include "ui/display/types/display_constants.h"
#include "ui/events/event.h"
#include "ui/gfx/geometry/dip_util.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/geometry/size.h"

namespace aura {
namespace {

struct WindowPortPropertyDataMus : public ui::PropertyData {
  std::string transport_name;
  std::unique_ptr<std::vector<uint8_t>> transport_value;
};

// Handles acknowledgment of an input event, either immediately when a nested
// message loop starts, or upon destruction.
class EventAckHandler : public base::RunLoop::NestingObserver {
 public:
  explicit EventAckHandler(std::unique_ptr<EventResultCallback> ack_callback)
      : ack_callback_(std::move(ack_callback)) {
    DCHECK(ack_callback_);
    base::RunLoop::AddNestingObserverOnCurrentThread(this);
  }

  ~EventAckHandler() override {
    base::RunLoop::RemoveNestingObserverOnCurrentThread(this);
    if (ack_callback_) {
      ack_callback_->Run(handled_ ? ui::mojom::EventResult::HANDLED
                                  : ui::mojom::EventResult::UNHANDLED);
    }
  }

  void set_handled(bool handled) { handled_ = handled; }

  // base::RunLoop::NestingObserver:
  void OnBeginNestedRunLoop() override {
    // Acknowledge the event immediately if a nested run loop starts.
    // Otherwise we appear unresponsive for the life of the nested run loop.
    if (ack_callback_) {
      ack_callback_->Run(ui::mojom::EventResult::HANDLED);
      ack_callback_.reset();
    }
  }

 private:
  std::unique_ptr<EventResultCallback> ack_callback_;
  bool handled_ = false;

  DISALLOW_COPY_AND_ASSIGN(EventAckHandler);
};

WindowTreeHostMus* GetWindowTreeHostMus(Window* window) {
  return WindowTreeHostMus::ForWindow(window);
}

WindowTreeHostMus* GetWindowTreeHostMus(WindowMus* window) {
  return GetWindowTreeHostMus(window->GetWindow());
}

bool IsInternalProperty(const void* key) {
  return key == client::kModalKey || key == client::kChildModalParentKey;
}

void SetWindowTypeFromProperties(
    Window* window,
    const std::unordered_map<std::string, std::vector<uint8_t>>& properties) {
  auto type_iter =
      properties.find(ui::mojom::WindowManager::kWindowType_InitProperty);
  if (type_iter == properties.end())
    return;

  // TODO: need to validate type! http://crbug.com/654924.
  ui::mojom::WindowType window_type = static_cast<ui::mojom::WindowType>(
      mojo::ConvertTo<int32_t>(type_iter->second));
  SetWindowType(window, window_type);
}

// Create and return a MouseEvent or TouchEvent from |event| if |event| is a
// PointerEvent, otherwise return the copy of |event|.
std::unique_ptr<ui::Event> MapEvent(const ui::Event& event) {
  if (event.IsPointerEvent()) {
    const ui::PointerEvent& pointer_event = *event.AsPointerEvent();
    // Use a switch statement in case more pointer types are added.
    switch (pointer_event.pointer_details().pointer_type) {
      case ui::EventPointerType::POINTER_TYPE_MOUSE:
        if (event.type() == ui::ET_POINTER_WHEEL_CHANGED)
          return std::make_unique<ui::MouseWheelEvent>(pointer_event);
        return std::make_unique<ui::MouseEvent>(pointer_event);
      case ui::EventPointerType::POINTER_TYPE_TOUCH:
      case ui::EventPointerType::POINTER_TYPE_PEN:
        return std::make_unique<ui::TouchEvent>(pointer_event);
      case ui::EventPointerType::POINTER_TYPE_ERASER:
        NOTIMPLEMENTED();
        break;
      case ui::EventPointerType::POINTER_TYPE_UNKNOWN:
        NOTREACHED();
        break;
    }
  }
  return ui::Event::Clone(event);
}

// Use for acks from mus that are expected to always succeed and if they don't
// a crash is triggered.
void OnAckMustSucceed(const base::Location& from_here, bool success) {
  CHECK(success) << "Context: " << from_here.ToString();
}

ui::Id GetServerIdForWindow(Window* window) {
  return window ? WindowMus::Get(window)->server_id() : kInvalidServerId;
}

}  // namespace

// static
std::unique_ptr<WindowTreeClient> WindowTreeClient::CreateForWindowManager(
    service_manager::Connector* connector,
    WindowTreeClientDelegate* delegate,
    WindowManagerDelegate* window_manager_delegate,
    bool automatically_create_display_roots,
    bool create_discardable_memory) {
  std::unique_ptr<WindowTreeClient> wtc(
      new WindowTreeClient(connector, delegate, window_manager_delegate,
                           nullptr, nullptr, create_discardable_memory));

  ui::mojom::WindowManagerWindowTreeFactoryPtr factory;
  connector->BindInterface(ui::mojom::kServiceName, &factory);
  ui::mojom::WindowTreePtr window_tree;
  ui::mojom::WindowTreeClientPtr client;
  wtc->binding_.Bind(MakeRequest(&client));
  factory->CreateWindowTree(MakeRequest(&window_tree), std::move(client),
                            automatically_create_display_roots);
  wtc->SetWindowTree(std::move(window_tree));
  return wtc;
}

// static
std::unique_ptr<WindowTreeClient> WindowTreeClient::CreateForEmbedding(
    service_manager::Connector* connector,
    WindowTreeClientDelegate* delegate,
    ui::mojom::WindowTreeClientRequest request,
    bool create_discardable_memory) {
  std::unique_ptr<WindowTreeClient> wtc(
      new WindowTreeClient(connector, delegate, nullptr, std::move(request),
                           nullptr, create_discardable_memory));
  return wtc;
}

// static
std::unique_ptr<WindowTreeClient> WindowTreeClient::CreateForWindowTreeFactory(
    service_manager::Connector* connector,
    WindowTreeClientDelegate* delegate,
    bool create_discardable_memory,
    scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) {
  std::unique_ptr<WindowTreeClient> wtc(
      new WindowTreeClient(connector, delegate, nullptr, nullptr, nullptr,
                           create_discardable_memory));
  ui::mojom::WindowTreeFactoryPtr factory;
  connector->BindInterface(ui::mojom::kServiceName, &factory);
  ui::mojom::WindowTreePtr window_tree;
  ui::mojom::WindowTreeClientPtr client;
  wtc->binding_.Bind(MakeRequest(&client));
  factory->CreateWindowTree(MakeRequest(&window_tree), std::move(client));
  wtc->SetWindowTree(std::move(window_tree));
  return wtc;
}

// static
std::unique_ptr<WindowTreeClient>
WindowTreeClient::CreateForWindowTreeHostFactory(
    service_manager::Connector* connector,
    WindowTreeClientDelegate* delegate,
    bool create_discardable_memory) {
  std::unique_ptr<WindowTreeClient> wtc(
      new WindowTreeClient(connector, delegate, nullptr, nullptr, nullptr,
                           create_discardable_memory));
  ui::mojom::WindowTreeHostFactoryPtr factory;
  connector->BindInterface(ui::mojom::kServiceName, &factory);

  ui::mojom::WindowTreeHostPtr window_tree_host;
  ui::mojom::WindowTreeClientPtr client;
  wtc->binding_.Bind(MakeRequest(&client));
  factory->CreateWindowTreeHost(MakeRequest(&window_tree_host),
                                std::move(client));
  return wtc;
}

WindowTreeClient::~WindowTreeClient() {
  in_destructor_ = true;

  if (discardable_shared_memory_manager_)
    base::DiscardableMemoryAllocator::SetInstance(nullptr);

  for (WindowTreeClientObserver& observer : observers_)
    observer.OnWillDestroyClient(this);

  capture_synchronizer_.reset();

  // Some tests may not create a TransientWindowClient.
  if (client::GetTransientWindowClient())
    client::GetTransientWindowClient()->RemoveObserver(this);

  Env* env = Env::GetInstance();
  if (compositor_context_factory_ &&
      env->context_factory() == compositor_context_factory_.get()) {
    env->set_context_factory(initial_context_factory_);
  }

  // Allow for windows to exist (and be created) after we are destroyed. This
  // is necessary because of shutdown ordering (WindowTreeClient is destroyed
  // before windows).
  in_shutdown_ = true;

  // Windows of type WindowMusType::OTHER were implicitly created from the
  // server and may not have been destroyed. Delete them to ensure we don't
  // leak.
  WindowTracker windows_to_destroy;
  for (auto& pair : windows_) {
    if (pair.second->window_mus_type() == WindowMusType::OTHER)
      windows_to_destroy.Add(pair.second->GetWindow());
  }
  while (!windows_to_destroy.windows().empty())
    delete windows_to_destroy.Pop();

  IdToWindowMap windows;
  std::swap(windows, windows_);
  for (auto& pair : windows)
    WindowPortForShutdown::Install(pair.second->GetWindow());

  env->WindowTreeClientDestroyed(this);
  CHECK(windows_.empty());
}

void WindowTreeClient::SetCanFocus(Window* window, bool can_focus) {
  DCHECK(tree_);
  DCHECK(window);
  tree_->SetCanFocus(WindowMus::Get(window)->server_id(), can_focus);
}

void WindowTreeClient::SetCursor(WindowMus* window,
                                 const ui::CursorData& old_cursor,
                                 const ui::CursorData& new_cursor) {
  DCHECK(tree_);

  const uint32_t change_id = ScheduleInFlightChange(
      std::make_unique<InFlightCursorChange>(window, old_cursor));
  tree_->SetCursor(change_id, window->server_id(), new_cursor);
}

void WindowTreeClient::SetWindowTextInputState(
    WindowMus* window,
    ui::mojom::TextInputStatePtr state) {
  DCHECK(tree_);
  tree_->SetWindowTextInputState(window->server_id(), std::move(state));
}

void WindowTreeClient::SetImeVisibility(WindowMus* window,
                                        bool visible,
                                        ui::mojom::TextInputStatePtr state) {
  DCHECK(tree_);
  tree_->SetImeVisibility(window->server_id(), visible, std::move(state));
}

void WindowTreeClient::SetHitTestMask(
    WindowMus* window,
    const base::Optional<gfx::Rect>& mask_rect) {
  base::Optional<gfx::Rect> out_rect = base::nullopt;
  if (mask_rect) {
    out_rect = gfx::ConvertRectToPixel(window->GetDeviceScaleFactor(),
                                       mask_rect.value());
  }

  tree_->SetHitTestMask(window->server_id(), out_rect);
}

void WindowTreeClient::Embed(
    Window* window,
    ui::mojom::WindowTreeClientPtr client,
    uint32_t flags,
    const ui::mojom::WindowTree::EmbedCallback& callback) {
  DCHECK(tree_);
  // Window::Init() must be called before Embed() (otherwise the server hasn't
  // been told about the window).
  DCHECK(window->layer());
  if (!window->children().empty()) {
    // The window server removes all children before embedding. In other words,
    // it's generally an error to Embed() with existing children. So, fail
    // early.
    callback.Run(false);
    return;
  }

  tree_->Embed(WindowMus::Get(window)->server_id(), std::move(client), flags,
               callback);
}

void WindowTreeClient::ScheduleEmbed(
    ui::mojom::WindowTreeClientPtr client,
    base::OnceCallback<void(const base::UnguessableToken&)> callback) {
  tree_->ScheduleEmbed(std::move(client),
                       base::AdaptCallbackForRepeating(std::move(callback)));
}

void WindowTreeClient::AttachCompositorFrameSink(
    ui::Id window_id,
    viz::mojom::CompositorFrameSinkRequest compositor_frame_sink,
    viz::mojom::CompositorFrameSinkClientPtr client) {
  DCHECK(tree_);
  tree_->AttachCompositorFrameSink(window_id, std::move(compositor_frame_sink),
                                   std::move(client));
}

WindowTreeClient::WindowTreeClient(
    service_manager::Connector* connector,
    WindowTreeClientDelegate* delegate,
    WindowManagerDelegate* window_manager_delegate,
    mojo::InterfaceRequest<ui::mojom::WindowTreeClient> request,
    scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
    bool create_discardable_memory)
    : connector_(connector),
      next_window_id_(1),
      next_change_id_(1),
      delegate_(delegate),
      window_manager_delegate_(window_manager_delegate),
      binding_(this),
      tree_(nullptr),
      in_destructor_(false),
      weak_factory_(this) {
  DCHECK(delegate_);
  // Allow for a null request in tests.
  if (request.is_pending())
    binding_.Bind(std::move(request));
  // Some tests may not create a TransientWindowClient.
  if (client::GetTransientWindowClient())
    client::GetTransientWindowClient()->AddObserver(this);
  if (window_manager_delegate)
    window_manager_delegate->SetWindowManagerClient(this);
  if (connector) {  // |connector| can be null in tests.
    if (!io_task_runner) {
      // |io_task_runner| is null in most case. But for the browser process,
      // the |io_task_runner| is the browser's IO thread.
      io_thread_ = std::make_unique<base::Thread>("IOThread");
      base::Thread::Options thread_options(base::MessageLoop::TYPE_IO, 0);
      thread_options.priority = base::ThreadPriority::NORMAL;
      CHECK(io_thread_->StartWithOptions(thread_options));
      io_task_runner = io_thread_->task_runner();
    }

    if (base::FeatureList::IsEnabled(features::kMash)) {
      gpu_ =
          ui::Gpu::Create(connector, ui::mojom::kServiceName, io_task_runner);
      compositor_context_factory_ =
          std::make_unique<MusContextFactory>(gpu_.get());
      initial_context_factory_ = Env::GetInstance()->context_factory();
      Env::GetInstance()->set_context_factory(
          compositor_context_factory_.get());
    }

    // WindowServerTest will create more than one WindowTreeClient. We will not
    // create the discardable memory manager for those tests.
    if (create_discardable_memory) {
      discardable_memory::mojom::DiscardableSharedMemoryManagerPtr manager_ptr;
      connector->BindInterface(ui::mojom::kServiceName, &manager_ptr);
      discardable_shared_memory_manager_ = std::make_unique<
          discardable_memory::ClientDiscardableSharedMemoryManager>(
          std::move(manager_ptr), std::move(io_task_runner));
      base::DiscardableMemoryAllocator::SetInstance(
          discardable_shared_memory_manager_.get());
    }
  }
}

void WindowTreeClient::RegisterWindowMus(WindowMus* window) {
  DCHECK(windows_.find(window->server_id()) == windows_.end());
  windows_[window->server_id()] = window;
  if (window->GetWindow()) {
    auto* port = WindowPortMus::Get(window->GetWindow());
    window->GetWindow()->set_frame_sink_id(
        port->GenerateFrameSinkIdFromServerId());
  }
}

WindowMus* WindowTreeClient::GetWindowByServerId(ui::Id id) {
  IdToWindowMap::const_iterator it = windows_.find(id);
  return it != windows_.end() ? it->second : nullptr;
}

bool WindowTreeClient::IsWindowKnown(aura::Window* window) {
  WindowMus* window_mus = WindowMus::Get(window);
  return windows_.count(window_mus->server_id()) > 0;
}

void WindowTreeClient::ConvertPointerEventLocationToDip(
    int64_t display_id,
    WindowMus* window,
    ui::LocatedEvent* event) const {
  // PointerEvents shouldn't have the target set.
  DCHECK(!event->target());
  if (window_manager_delegate_) {
    ConvertPointerEventLocationToDipInWindowManager(display_id, window, event);
    return;
  }
  display::Screen* screen = display::Screen::GetScreen();
  display::Display display;
  // TODO(sky): this needs to take into account the ui display scale.
  // http://crbug.com/758399.
  if (!screen->GetDisplayWithDisplayId(display_id, &display) ||
      display.device_scale_factor() == 1.f) {
    return;
  }
  const gfx::Point root_location = gfx::ConvertPointToDIP(
      display.device_scale_factor(), event->root_location());
  event->set_root_location(root_location);
  if (window) {
    const gfx::Point host_location = gfx::ConvertPointToDIP(
        display.device_scale_factor(), event->location());
    event->set_location(host_location);
  } else {
    // When there is no window force the root and location to be the same. They
    // may differ it |window| was valid at the time of the event, but was since
    // deleted.
    event->set_location(root_location);
  }
}

void WindowTreeClient::ConvertPointerEventLocationToDipInWindowManager(
    int64_t display_id,
    WindowMus* window,
    ui::LocatedEvent* event) const {
  const WindowTreeHostMus* window_tree_host =
      GetWindowTreeHostForDisplayId(display_id);
  if (!window_tree_host)
    return;

  ui::Event::DispatcherApi dispatcher_api(event);
  if (window) {
    dispatcher_api.set_target(window->GetWindow());
  } else {
    // UpdateForRootTransform() in the case of no target uses |location_|.
    // |location_| may be relative to a window that wasn't found. To ensure we
    // convert from the root, reset |location_| to |root_location_|.
    event->set_location_f(event->root_location_f());
  }
  event->UpdateForRootTransform(
      window_tree_host->GetInverseRootTransform(),
      window_tree_host->GetInverseRootTransformForLocalEventCoordinates());
  dispatcher_api.set_target(nullptr);
}

InFlightChange* WindowTreeClient::GetOldestInFlightChangeMatching(
    const InFlightChange& change) {
  for (const auto& pair : in_flight_map_) {
    if (pair.second->window() == change.window() &&
        pair.second->change_type() == change.change_type() &&
        pair.second->Matches(change)) {
      return pair.second.get();
    }
  }
  return nullptr;
}

uint32_t WindowTreeClient::ScheduleInFlightChange(
    std::unique_ptr<InFlightChange> change) {
  DCHECK(!change->window() ||
         windows_.count(change->window()->server_id()) > 0);
  ChangeType t = change->change_type();
  const uint32_t change_id = next_change_id_++;
  in_flight_map_[change_id] = std::move(change);
  for (auto& observer : test_observers_)
    observer.OnChangeStarted(change_id, t);
  return change_id;
}

bool WindowTreeClient::ApplyServerChangeToExistingInFlightChange(
    const InFlightChange& change) {
  InFlightChange* existing_change = GetOldestInFlightChangeMatching(change);
  if (!existing_change)
    return false;

  existing_change->SetRevertValueFrom(change);
  return true;
}

void WindowTreeClient::BuildWindowTree(
    const std::vector<ui::mojom::WindowDataPtr>& windows) {
  for (const auto& window_data : windows)
    CreateOrUpdateWindowFromWindowData(*window_data);
}

void WindowTreeClient::CreateOrUpdateWindowFromWindowData(
    const ui::mojom::WindowData& window_data) {
  WindowMus* parent = window_data.parent_id == kInvalidServerId
                          ? nullptr
                          : GetWindowByServerId(window_data.parent_id);
  WindowMus* window = GetWindowByServerId(window_data.window_id);
  if (!window)
    window = NewWindowFromWindowData(parent, window_data);
  else if (parent)
    parent->AddChildFromServer(window);

  if (window_data.transient_parent_id == kInvalidServerId)
    return;

  // Some tests may not create a TransientWindowClient.
  client::TransientWindowClient* transient_window_client =
      client::GetTransientWindowClient();
  if (!transient_window_client)
    return;

  // Adjust the transient parent if necessary.
  Window* existing_transient_parent =
      transient_window_client->GetTransientParent(window->GetWindow());
  WindowMus* new_transient_parent =
      GetWindowByServerId(window_data.transient_parent_id);
  if (!new_transient_parent && existing_transient_parent) {
    WindowMus::Get(existing_transient_parent)
        ->RemoveTransientChildFromServer(window);
  } else if (new_transient_parent &&
             new_transient_parent->GetWindow() != existing_transient_parent) {
    if (existing_transient_parent) {
      WindowMus::Get(existing_transient_parent)
          ->RemoveTransientChildFromServer(window);
    }
    new_transient_parent->AddTransientChildFromServer(window);
  }
}

std::unique_ptr<WindowPortMus> WindowTreeClient::CreateWindowPortMus(
    const ui::mojom::WindowData& window_data,
    WindowMusType window_mus_type) {
  std::unique_ptr<WindowPortMus> window_port_mus(
      std::make_unique<WindowPortMus>(this, window_mus_type));
  window_port_mus->set_server_id(window_data.window_id);
  RegisterWindowMus(window_port_mus.get());
  return window_port_mus;
}

void WindowTreeClient::SetLocalPropertiesFromServerProperties(
    WindowMus* window,
    const ui::mojom::WindowData& window_data) {
  for (auto& pair : window_data.properties)
    window->SetPropertyFromServer(pair.first, &pair.second);
}

const WindowTreeHostMus* WindowTreeClient::GetWindowTreeHostForDisplayId(
    int64_t display_id) const {
  if (!window_manager_delegate_)
    return nullptr;

  for (WindowMus* window : roots_) {
    WindowTreeHostMus* window_tree_host =
        static_cast<WindowTreeHostMus*>(window->GetWindow()->GetHost());
    if (window_tree_host->display_id() == display_id)
      return window_tree_host;
  }
  return nullptr;
}

std::unique_ptr<WindowTreeHostMus> WindowTreeClient::CreateWindowTreeHost(
    WindowMusType window_mus_type,
    const ui::mojom::WindowData& window_data,
    int64_t display_id,
    const base::Optional<viz::LocalSurfaceId>& local_surface_id) {
  std::unique_ptr<WindowPortMus> window_port =
      CreateWindowPortMus(window_data, window_mus_type);
  roots_.insert(window_port.get());
  WindowTreeHostMusInitParams init_params;
  init_params.window_port = std::move(window_port);
  init_params.window_tree_client = this;
  init_params.display_id = display_id;
  if (window_manager_delegate_ &&
      (window_mus_type == WindowMusType::EMBED ||
       window_mus_type == WindowMusType::DISPLAY_AUTOMATICALLY_CREATED)) {
    init_params.uses_real_accelerated_widget =
        !::base::FeatureList::IsEnabled(features::kMash);
  }
  std::unique_ptr<WindowTreeHostMus> window_tree_host =
      std::make_unique<WindowTreeHostMus>(std::move(init_params));
  window_tree_host->InitHost();
  SetLocalPropertiesFromServerProperties(
      WindowMus::Get(window_tree_host->window()), window_data);
  if (window_data.visible) {
    SetWindowVisibleFromServer(WindowMus::Get(window_tree_host->window()),
                               true);
  }
  WindowMus* window = WindowMus::Get(window_tree_host->window());

  SetWindowBoundsFromServer(window, window_data.bounds, local_surface_id);
  return window_tree_host;
}

WindowMus* WindowTreeClient::NewWindowFromWindowData(
    WindowMus* parent,
    const ui::mojom::WindowData& window_data) {
  // This function is only called for windows coming from other clients.
  std::unique_ptr<WindowPortMus> window_port_mus(
      CreateWindowPortMus(window_data, WindowMusType::OTHER));
  WindowPortMus* window_port_mus_ptr = window_port_mus.get();
  // Children of windows created from another client need to be restacked by
  // the client that created them. To do otherwise means two clients will
  // attempt to restack the same windows, leading to raciness (and most likely
  // be rejected by the server anyway).
  window_port_mus_ptr->should_restack_transient_children_ = false;
  Window* window = new Window(nullptr, std::move(window_port_mus));
  WindowMus* window_mus = window_port_mus_ptr;
  SetWindowTypeFromProperties(window, window_data.properties);
  window->Init(ui::LAYER_NOT_DRAWN);
  SetLocalPropertiesFromServerProperties(window_mus, window_data);
  window_mus->SetBoundsFromServer(
      gfx::ConvertRectToDIP(window_mus->GetDeviceScaleFactor(),
                            window_data.bounds),
      base::nullopt);
  if (parent)
    parent->AddChildFromServer(window_port_mus_ptr);
  if (window_data.visible)
    window_mus->SetVisibleFromServer(true);
  return window_port_mus_ptr;
}

void WindowTreeClient::SetWindowTree(ui::mojom::WindowTreePtr window_tree_ptr) {
  tree_ptr_ = std::move(window_tree_ptr);

  WindowTreeConnectionEstablished(tree_ptr_.get());
  tree_ptr_->GetCursorLocationMemory(
      base::Bind(&WindowTreeClient::OnReceivedCursorLocationMemory,
                 weak_factory_.GetWeakPtr()));

  tree_ptr_.set_connection_error_handler(base::Bind(
      &WindowTreeClient::OnConnectionLost, weak_factory_.GetWeakPtr()));

  if (window_manager_delegate_) {
    tree_ptr_->GetWindowManagerClient(
        MakeRequest(&window_manager_internal_client_));
    window_manager_client_ = window_manager_internal_client_.get();
  }
}

void WindowTreeClient::WindowTreeConnectionEstablished(
    ui::mojom::WindowTree* window_tree) {
  tree_ = window_tree;

  drag_drop_controller_ = std::make_unique<DragDropControllerMus>(this, tree_);
  capture_synchronizer_ = std::make_unique<CaptureSynchronizer>(this, tree_);
  focus_synchronizer_ = std::make_unique<FocusSynchronizer>(this, tree_);
}

void WindowTreeClient::OnConnectionLost() {
  delegate_->OnLostConnection(this);
}

bool WindowTreeClient::HandleInternalPropertyChanged(WindowMus* window,
                                                     const void* key,
                                                     int64_t old_value) {
  if (key == client::kModalKey) {
    const uint32_t change_id =
        ScheduleInFlightChange(std::make_unique<InFlightSetModalTypeChange>(
            window, static_cast<ui::ModalType>(old_value)));
    tree_->SetModalType(change_id, window->server_id(),
                        window->GetWindow()->GetProperty(client::kModalKey));
    return true;
  }
  if (key == client::kChildModalParentKey) {
    const uint32_t change_id =
        ScheduleInFlightChange(std::make_unique<CrashInFlightChange>(
            window, ChangeType::CHILD_MODAL_PARENT));
    Window* child_modal_parent =
        window->GetWindow()->GetProperty(client::kChildModalParentKey);
    tree_->SetChildModalParent(
        change_id, window->server_id(),
        child_modal_parent ? WindowMus::Get(child_modal_parent)->server_id()
                           : kInvalidServerId);
    return true;
  }
  return false;
}

void WindowTreeClient::OnEmbedImpl(
    ui::mojom::WindowTree* window_tree,
    ui::mojom::WindowDataPtr root_data,
    int64_t display_id,
    ui::Id focused_window_id,
    bool drawn,
    const base::Optional<viz::LocalSurfaceId>& local_surface_id) {
  WindowTreeConnectionEstablished(window_tree);

  DCHECK(roots_.empty());
  std::unique_ptr<WindowTreeHostMus> window_tree_host = CreateWindowTreeHost(
      WindowMusType::EMBED, *root_data, display_id, local_surface_id);

  focus_synchronizer_->SetFocusFromServer(
      GetWindowByServerId(focused_window_id));

  delegate_->OnEmbed(std::move(window_tree_host));
}

WindowTreeHostMus* WindowTreeClient::WmNewDisplayAddedImpl(
    const display::Display& display,
    ui::mojom::WindowDataPtr root_data,
    bool parent_drawn,
    const base::Optional<viz::LocalSurfaceId>& local_surface_id) {
  DCHECK(window_manager_delegate_);

  got_initial_displays_ = true;

  window_manager_delegate_->OnWmWillCreateDisplay(display);

  std::unique_ptr<WindowTreeHostMus> window_tree_host =
      CreateWindowTreeHost(WindowMusType::DISPLAY_AUTOMATICALLY_CREATED,
                           *root_data, display.id(), local_surface_id);

  WindowTreeHostMus* window_tree_host_ptr = window_tree_host.get();
  window_manager_delegate_->OnWmNewDisplay(std::move(window_tree_host),
                                           display);
  return window_tree_host_ptr;
}

std::unique_ptr<EventResultCallback>
WindowTreeClient::CreateEventResultCallback(int32_t event_id) {
  return std::make_unique<EventResultCallback>(
      base::Bind(&ui::mojom::WindowTree::OnWindowInputEventAck,
                 base::Unretained(tree_), event_id));
}

void WindowTreeClient::OnReceivedCursorLocationMemory(
    mojo::ScopedSharedBufferHandle handle) {
  cursor_location_mapping_ = handle->Map(sizeof(base::subtle::Atomic32));
  DCHECK(cursor_location_mapping_);
}

void WindowTreeClient::SetWindowBoundsFromServer(
    WindowMus* window,
    const gfx::Rect& revert_bounds_in_pixels,
    const base::Optional<viz::LocalSurfaceId>& local_surface_id) {
  if (IsRoot(window)) {
    // WindowTreeHost expects bounds to be in pixels.
    GetWindowTreeHostMus(window)->SetBoundsFromServer(revert_bounds_in_pixels);
    if (local_surface_id && local_surface_id->is_valid()) {
      ui::Compositor* compositor = window->GetWindow()->GetHost()->compositor();
      compositor->SetLocalSurfaceId(*local_surface_id);
    }
    return;
  }

  window->SetBoundsFromServer(
      gfx::ConvertRectToDIP(window->GetDeviceScaleFactor(),
                            revert_bounds_in_pixels),
      local_surface_id);
}

void WindowTreeClient::SetWindowTransformFromServer(
    WindowMus* window,
    const gfx::Transform& transform) {
  window->SetTransformFromServer(transform);
}

void WindowTreeClient::SetWindowVisibleFromServer(WindowMus* window,
                                                  bool visible) {
  if (!IsRoot(window)) {
    window->SetVisibleFromServer(visible);
    return;
  }

  std::unique_ptr<WindowMusChangeData> data =
      window->PrepareForServerVisibilityChange(visible);
  WindowTreeHostMus* window_tree_host = GetWindowTreeHostMus(window);
  if (visible)
    window_tree_host->Show();
  else
    window_tree_host->Hide();
}

void WindowTreeClient::ScheduleInFlightBoundsChange(
    WindowMus* window,
    const gfx::Rect& old_bounds,
    const gfx::Rect& new_bounds) {
  const uint32_t change_id =
      ScheduleInFlightChange(std::make_unique<InFlightBoundsChange>(
          this, window, old_bounds, window->GetLocalSurfaceId()));
  base::Optional<viz::LocalSurfaceId> local_surface_id;
  if (window->window_mus_type() == WindowMusType::TOP_LEVEL_IN_WM ||
      window->window_mus_type() == WindowMusType::EMBED_IN_OWNER ||
      window->window_mus_type() == WindowMusType::DISPLAY_MANUALLY_CREATED ||
      window->HasLocalLayerTreeFrameSink()) {
    local_surface_id = window->GetOrAllocateLocalSurfaceId(new_bounds.size());
    // |window_tree_host| may be null if this is called during creation of
    // the window associated with the WindowTreeHostMus.
    WindowTreeHost* window_tree_host = window->GetWindow()->GetHost();
    if (window_tree_host)
      window_tree_host->compositor()->OnChildResizing();
  }
  tree_->SetWindowBounds(change_id, window->server_id(), new_bounds,
                         local_surface_id);
}

void WindowTreeClient::OnWindowMusCreated(WindowMus* window) {
  if (window->server_id() != kInvalidServerId)
    return;

  window->set_server_id(next_window_id_++);
  RegisterWindowMus(window);

  DCHECK(window_manager_delegate_ || !IsRoot(window));

  std::unordered_map<std::string, std::vector<uint8_t>> transport_properties;
  std::set<const void*> property_keys =
      window->GetWindow()->GetAllPropertyKeys();
  PropertyConverter* property_converter = delegate_->GetPropertyConverter();
  for (const void* key : property_keys) {
    std::string transport_name;
    std::unique_ptr<std::vector<uint8_t>> transport_value;
    if (!property_converter->ConvertPropertyForTransport(
            window->GetWindow(), key, &transport_name, &transport_value)) {
      continue;
    }
    transport_properties[transport_name] =
        transport_value ? std::move(*transport_value) : std::vector<uint8_t>();
  }

  const uint32_t change_id = ScheduleInFlightChange(
      std::make_unique<CrashInFlightChange>(window, ChangeType::NEW_WINDOW));
  tree_->NewWindow(change_id, window->server_id(),
                   std::move(transport_properties));
  if (window->GetWindow()->event_targeting_policy() !=
      ui::mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS) {
    SetEventTargetingPolicy(window,
                            window->GetWindow()->event_targeting_policy());
  }
  if (window->window_mus_type() == WindowMusType::DISPLAY_MANUALLY_CREATED) {
    WindowTreeHostMus* window_tree_host = GetWindowTreeHostMus(window);
    std::unique_ptr<DisplayInitParams> display_init_params =
        window_tree_host->ReleaseDisplayInitParams();
    DCHECK(display_init_params);
    display::Display display;
    if (display_init_params->display) {
      display = *display_init_params->display;
    } else {
      const bool has_display =
          display::Screen::GetScreen()->GetDisplayWithDisplayId(
              window_tree_host->display_id(), &display);
      DCHECK(has_display);
    }
    // As |window| is a root, changes to its bounds are ignored (it's assumed
    // bounds changes are routed through OnWindowTreeHostBoundsWillChange()).
    // But the display is created with an initial bounds, and we need to push
    // that to the server.
    ScheduleInFlightBoundsChange(
        window, gfx::Rect(),
        gfx::Rect(
            display_init_params->viewport_metrics.bounds_in_pixels.size()));

    if (window_manager_client_) {
      window_manager_client_->SetDisplayRoot(
          display, display_init_params->viewport_metrics.Clone(),
          display_init_params->is_primary_display, window->server_id(),
          base::FeatureList::IsEnabled(features::kMash)
              ? display_init_params->mirrors
              : std::vector<display::Display>(),
          base::Bind(&OnAckMustSucceed, FROM_HERE));
    }
  }
}

void WindowTreeClient::OnWindowMusDestroyed(WindowMus* window, Origin origin) {
  if (focus_synchronizer_->focused_window() == window)
    focus_synchronizer_->OnFocusedWindowDestroyed();

  // If we're |in_shutdown_| there is no point in telling the server about the
  // deletion. The connection to the server is about to be dropped and the
  // server will take appropriate action.
  // TODO: decide how to deal with windows not owned by this client.
  if (!in_shutdown_ && origin == Origin::CLIENT &&
      (WasCreatedByThisClient(window) || IsRoot(window))) {
    const uint32_t change_id =
        ScheduleInFlightChange(std::make_unique<CrashInFlightChange>(
            window, ChangeType::DELETE_WINDOW));
    tree_->DeleteWindow(change_id, window->server_id());
  }

  windows_.erase(window->server_id());

  for (auto& entry : embedded_windows_) {
    auto it = entry.second.find(window->GetWindow());
    if (it != entry.second.end()) {
      entry.second.erase(it);
      break;
    }
  }

  // Remove any InFlightChanges associated with the window.
  std::set<uint32_t> in_flight_change_ids_to_remove;
  for (const auto& pair : in_flight_map_) {
    if (pair.second->window() == window)
      in_flight_change_ids_to_remove.insert(pair.first);
  }
  for (auto change_id : in_flight_change_ids_to_remove)
    in_flight_map_.erase(change_id);

  roots_.erase(window);
}

void WindowTreeClient::OnWindowMusBoundsChanged(WindowMus* window,
                                                const gfx::Rect& old_bounds,
                                                const gfx::Rect& new_bounds) {
  // Changes to bounds of root windows are routed through
  // OnWindowTreeHostBoundsWillChange(). Any bounds that happen here are a side
  // effect of those and can be ignored.
  if (IsRoot(window)) {
    // NOTE: this has to happen to here as during the call to
    // OnWindowTreeHostBoundsWillChange() the compositor hasn't been updated
    // yet.
    if (window->window_mus_type() == WindowMusType::DISPLAY_MANUALLY_CREATED) {
      WindowTreeHost* window_tree_host = window->GetWindow()->GetHost();
      // |window_tree_host| may be null if this is called during creation of
      // the window associated with the WindowTreeHostMus.
      if (window_tree_host) {
        viz::LocalSurfaceId local_surface_id =
            window->GetOrAllocateLocalSurfaceId(
                window_tree_host->GetBoundsInPixels().size());
        DCHECK(local_surface_id.is_valid());
        window_tree_host->compositor()->SetLocalSurfaceId(local_surface_id);
      }
    }
    return;
  }

  float device_scale_factor = window->GetDeviceScaleFactor();
  ScheduleInFlightBoundsChange(
      window, gfx::ConvertRectToPixel(device_scale_factor, old_bounds),
      gfx::ConvertRectToPixel(device_scale_factor, new_bounds));
}

void WindowTreeClient::OnWindowMusTransformChanged(
    WindowMus* window,
    const gfx::Transform& old_transform,
    const gfx::Transform& new_transform) {
  const uint32_t change_id = ScheduleInFlightChange(
      std::make_unique<InFlightTransformChange>(this, window, old_transform));
  tree_->SetWindowTransform(change_id, window->server_id(), new_transform);
}

void WindowTreeClient::OnWindowMusAddChild(WindowMus* parent,
                                           WindowMus* child) {
  // TODO: add checks to ensure this can work.
  const uint32_t change_id = ScheduleInFlightChange(
      std::make_unique<CrashInFlightChange>(parent, ChangeType::ADD_CHILD));
  tree_->AddWindow(change_id, parent->server_id(), child->server_id());
}

void WindowTreeClient::OnWindowMusRemoveChild(WindowMus* parent,
                                              WindowMus* child) {
  // TODO: add checks to ensure this can work.
  const uint32_t change_id = ScheduleInFlightChange(
      std::make_unique<CrashInFlightChange>(parent, ChangeType::REMOVE_CHILD));
  tree_->RemoveWindowFromParent(change_id, child->server_id());
}

void WindowTreeClient::OnWindowMusMoveChild(WindowMus* parent,
                                            size_t current_index,
                                            size_t dest_index) {
  DCHECK_NE(current_index, dest_index);
  // TODO: add checks to ensure this can work, e.g. we own the parent.
  const uint32_t change_id = ScheduleInFlightChange(
      std::make_unique<CrashInFlightChange>(parent, ChangeType::REORDER));
  WindowMus* window =
      WindowMus::Get(parent->GetWindow()->children()[current_index]);
  WindowMus* relative_window = nullptr;
  ui::mojom::OrderDirection direction;
  if (dest_index < current_index) {
    relative_window =
        WindowMus::Get(parent->GetWindow()->children()[dest_index]);
    direction = ui::mojom::OrderDirection::BELOW;
  } else {
    relative_window =
        WindowMus::Get(parent->GetWindow()->children()[dest_index]);
    direction = ui::mojom::OrderDirection::ABOVE;
  }
  tree_->ReorderWindow(change_id, window->server_id(),
                       relative_window->server_id(), direction);
}

void WindowTreeClient::OnWindowMusSetVisible(WindowMus* window, bool visible) {
  // TODO: add checks to ensure this can work.
  DCHECK(tree_);
  const uint32_t change_id = ScheduleInFlightChange(
      std::make_unique<InFlightVisibleChange>(this, window, !visible));
  tree_->SetWindowVisibility(change_id, window->server_id(), visible);
}

std::unique_ptr<ui::PropertyData>
WindowTreeClient::OnWindowMusWillChangeProperty(WindowMus* window,
                                                const void* key) {
  if (IsInternalProperty(key))
    return nullptr;

  std::unique_ptr<WindowPortPropertyDataMus> data(
      std::make_unique<WindowPortPropertyDataMus>());
  if (!delegate_->GetPropertyConverter()->ConvertPropertyForTransport(
          window->GetWindow(), key, &data->transport_name,
          &data->transport_value)) {
    return nullptr;
  }
  return std::move(data);
}

void WindowTreeClient::OnWindowMusPropertyChanged(
    WindowMus* window,
    const void* key,
    int64_t old_value,
    std::unique_ptr<ui::PropertyData> data) {
  if (HandleInternalPropertyChanged(window, key, old_value) || !data)
    return;

  WindowPortPropertyDataMus* data_mus =
      static_cast<WindowPortPropertyDataMus*>(data.get());

  std::string transport_name;
  std::unique_ptr<std::vector<uint8_t>> transport_value;
  if (!delegate_->GetPropertyConverter()->ConvertPropertyForTransport(
          window->GetWindow(), key, &transport_name, &transport_value)) {
    return;
  }
  DCHECK_EQ(transport_name, data_mus->transport_name);

  base::Optional<std::vector<uint8_t>> transport_value_mojo;
  if (transport_value)
    transport_value_mojo.emplace(std::move(*transport_value));

  const uint32_t change_id =
      ScheduleInFlightChange(std::make_unique<InFlightPropertyChange>(
          window, transport_name, std::move(data_mus->transport_value)));
  tree_->SetWindowProperty(change_id, window->server_id(), transport_name,
                           transport_value_mojo);
}

void WindowTreeClient::OnWindowMusDeviceScaleFactorChanged(
    WindowMus* window,
    float old_scale_factor,
    float new_scale_factor) {
  // Root changes are handled else where.
  if (IsRoot(window))
    return;

  const gfx::Rect old_bounds =
      gfx::ConvertRectToPixel(old_scale_factor, window->GetWindow()->bounds());
  const gfx::Rect new_bounds =
      gfx::ConvertRectToPixel(new_scale_factor, window->GetWindow()->bounds());
  ScheduleInFlightBoundsChange(window, old_bounds, new_bounds);
}

void WindowTreeClient::OnWmMoveLoopCompleted(uint32_t change_id,
                                             bool completed) {
  if (window_manager_client_)
    window_manager_client_->WmResponse(change_id, completed);

  if (change_id == current_wm_move_loop_change_) {
    current_wm_move_loop_change_ = 0;
    current_wm_move_loop_window_id_ = 0;
  }
}

std::set<Window*> WindowTreeClient::GetRoots() {
  std::set<Window*> roots;
  for (WindowMus* window : roots_)
    roots.insert(window->GetWindow());
  return roots;
}

bool WindowTreeClient::WasCreatedByThisClient(const WindowMus* window) const {
  // Windows created via CreateTopLevelWindow() are not owned by us, but don't
  // have high-word set. const_cast is required by set.
  return !ui::ClientIdFromTransportId(window->server_id()) &&
         roots_.count(const_cast<WindowMus*>(window)) == 0;
}

gfx::Point WindowTreeClient::GetCursorScreenPoint() {
  // We raced initialization. Return (0, 0).
  if (!cursor_location_memory())
    return gfx::Point();

  base::subtle::Atomic32 location =
      base::subtle::NoBarrier_Load(cursor_location_memory());
  return gfx::Point(static_cast<int16_t>(location >> 16),
                    static_cast<int16_t>(location & 0xFFFF));
}

void WindowTreeClient::StartPointerWatcher(bool want_moves) {
  if (has_pointer_watcher_)
    StopPointerWatcher();
  has_pointer_watcher_ = true;
  tree_->StartPointerWatcher(want_moves);
}

void WindowTreeClient::StopPointerWatcher() {
  DCHECK(has_pointer_watcher_);
  tree_->StopPointerWatcher();
  has_pointer_watcher_ = false;
}

void WindowTreeClient::AddObserver(WindowTreeClientObserver* observer) {
  observers_.AddObserver(observer);
}

void WindowTreeClient::RemoveObserver(WindowTreeClientObserver* observer) {
  observers_.RemoveObserver(observer);
}

void WindowTreeClient::AddTestObserver(WindowTreeClientTestObserver* observer) {
  test_observers_.AddObserver(observer);
}

void WindowTreeClient::RemoveTestObserver(
    WindowTreeClientTestObserver* observer) {
  test_observers_.RemoveObserver(observer);
}

void WindowTreeClient::SetCanAcceptDrops(WindowMus* window,
                                         bool can_accept_drops) {
  DCHECK(tree_);
  tree_->SetCanAcceptDrops(window->server_id(), can_accept_drops);
}

void WindowTreeClient::SetEventTargetingPolicy(
    WindowMus* window,
    ui::mojom::EventTargetingPolicy policy) {
  DCHECK(tree_);
  tree_->SetEventTargetingPolicy(window->server_id(), policy);
}

void WindowTreeClient::OnEmbed(
    ui::mojom::WindowDataPtr root_data,
    ui::mojom::WindowTreePtr tree,
    int64_t display_id,
    ui::Id focused_window_id,
    bool drawn,
    const base::Optional<viz::LocalSurfaceId>& local_surface_id) {
  DCHECK(!tree_ptr_);
  tree_ptr_ = std::move(tree);

  is_from_embed_ = true;
  got_initial_displays_ = true;

  if (window_manager_delegate_) {
    tree_ptr_->GetWindowManagerClient(
        MakeRequest(&window_manager_internal_client_));
    window_manager_client_ = window_manager_internal_client_.get();
  }
  OnEmbedImpl(tree_ptr_.get(), std::move(root_data), display_id,
              focused_window_id, drawn, local_surface_id);
}

void WindowTreeClient::OnEmbeddedAppDisconnected(ui::Id window_id) {
  WindowMus* window = GetWindowByServerId(window_id);
  if (window)
    window->NotifyEmbeddedAppDisconnected();
}

void WindowTreeClient::OnUnembed(ui::Id window_id) {
  WindowMus* window = GetWindowByServerId(window_id);
  if (!window)
    return;

  delegate_->OnUnembed(window->GetWindow());
  delete window;
}

void WindowTreeClient::OnCaptureChanged(ui::Id new_capture_window_id,
                                        ui::Id old_capture_window_id) {
  WindowMus* new_capture_window = GetWindowByServerId(new_capture_window_id);
  WindowMus* lost_capture_window = GetWindowByServerId(old_capture_window_id);
  if (!new_capture_window && !lost_capture_window)
    return;

  InFlightCaptureChange change(this, capture_synchronizer_.get(),
                               new_capture_window);
  if (ApplyServerChangeToExistingInFlightChange(change))
    return;

  capture_synchronizer_->SetCaptureFromServer(new_capture_window);
}

void WindowTreeClient::OnFrameSinkIdAllocated(
    ui::Id window_id,
    const viz::FrameSinkId& frame_sink_id) {
  if (!base::FeatureList::IsEnabled(features::kMash))
    return;
  WindowMus* window = GetWindowByServerId(window_id);
  if (!window)
    return;

  window->SetFrameSinkIdFromServer(frame_sink_id);
}

void WindowTreeClient::OnTopLevelCreated(
    uint32_t change_id,
    ui::mojom::WindowDataPtr data,
    int64_t display_id,
    bool drawn,
    const base::Optional<viz::LocalSurfaceId>& local_surface_id) {
  // The server ack'd the top level window we created and supplied the state
  // of the window at the time the server created it. For properties we do not
  // have changes in flight for we can update them immediately. For properties
  // with changes in flight we set the revert value from the server.

  if (!in_flight_map_.count(change_id)) {
    // The window may have been destroyed locally before the server could finish
    // creating the window, and before the server received the notification that
    // the window has been destroyed.
    return;
  }
  std::unique_ptr<InFlightChange> change(std::move(in_flight_map_[change_id]));
  in_flight_map_.erase(change_id);

  WindowMus* window = change->window();
  WindowTreeHostMus* window_tree_host = GetWindowTreeHostMus(window);

  // Drawn state and display-id always come from the server (they can't be
  // modified locally).
  window_tree_host->set_display_id(display_id);

  // The default visibilty is false, we only need update visibility if it
  // differs from that.
  if (data->visible) {
    InFlightVisibleChange visible_change(this, window, data->visible);
    InFlightChange* current_change =
        GetOldestInFlightChangeMatching(visible_change);
    if (current_change)
      current_change->SetRevertValueFrom(visible_change);
    else
      SetWindowVisibleFromServer(window, true);
  }

  const gfx::Rect bounds(data->bounds);
  {
    InFlightBoundsChange bounds_change(this, window, bounds, local_surface_id);
    InFlightChange* current_change =
        GetOldestInFlightChangeMatching(bounds_change);
    if (current_change) {
      current_change->SetRevertValueFrom(bounds_change);
    } else if (gfx::ConvertRectToPixel(window->GetDeviceScaleFactor(),
                                       window->GetWindow()->bounds()) !=
               bounds) {
      SetWindowBoundsFromServer(window, bounds, local_surface_id);
    }
  }

  // There is currently no API to bulk set properties, so we iterate over each
  // property individually.
  for (const auto& pair : data->properties) {
    std::unique_ptr<std::vector<uint8_t>> revert_value(
        std::make_unique<std::vector<uint8_t>>(pair.second));
    InFlightPropertyChange property_change(window, pair.first,
                                           std::move(revert_value));
    InFlightChange* current_change =
        GetOldestInFlightChangeMatching(property_change);
    if (current_change) {
      current_change->SetRevertValueFrom(property_change);
    } else {
      window->SetPropertyFromServer(pair.first, &pair.second);
    }
  }

  // Top level windows should not have a parent.
  DCHECK_EQ(0u, data->parent_id);
}

void WindowTreeClient::OnWindowBoundsChanged(
    ui::Id window_id,
    const gfx::Rect& old_bounds,
    const gfx::Rect& new_bounds,
    const base::Optional<viz::LocalSurfaceId>& local_surface_id) {
  WindowMus* window = GetWindowByServerId(window_id);
  if (!window)
    return;

  InFlightBoundsChange new_change(this, window, new_bounds, local_surface_id);
  if (ApplyServerChangeToExistingInFlightChange(new_change))
    return;

  SetWindowBoundsFromServer(window, new_bounds, local_surface_id);
}

void WindowTreeClient::OnWindowTransformChanged(
    ui::Id window_id,
    const gfx::Transform& old_transform,
    const gfx::Transform& new_transform) {
  WindowMus* window = GetWindowByServerId(window_id);
  if (!window)
    return;

  InFlightTransformChange new_change(this, window, new_transform);
  if (ApplyServerChangeToExistingInFlightChange(new_change))
    return;

  SetWindowTransformFromServer(window, new_transform);
}

void WindowTreeClient::OnClientAreaChanged(
    ui::Id window_id,
    const gfx::Insets& new_client_area,
    const std::vector<gfx::Rect>& new_additional_client_areas) {
  WindowMus* window = GetWindowByServerId(window_id);
  if (!window)
    return;

  float device_scale_factor = window->GetDeviceScaleFactor();
  std::vector<gfx::Rect> new_additional_client_areas_in_dip;
  for (const gfx::Rect& area : new_additional_client_areas) {
    new_additional_client_areas_in_dip.push_back(
        gfx::ConvertRectToDIP(device_scale_factor, area));
  }
  window_manager_delegate_->OnWmSetClientArea(
      window->GetWindow(),
      gfx::ConvertInsetsToDIP(device_scale_factor, new_client_area),
      new_additional_client_areas_in_dip);
}

void WindowTreeClient::OnTransientWindowAdded(ui::Id window_id,
                                              ui::Id transient_window_id) {
  WindowMus* window = GetWindowByServerId(window_id);
  WindowMus* transient_window = GetWindowByServerId(transient_window_id);
  // window or transient_window or both may be null if a local delete occurs
  // with an in flight add from the server.
  if (window && transient_window)
    window->AddTransientChildFromServer(transient_window);
}

void WindowTreeClient::OnTransientWindowRemoved(ui::Id window_id,
                                                ui::Id transient_window_id) {
  WindowMus* window = GetWindowByServerId(window_id);
  WindowMus* transient_window = GetWindowByServerId(transient_window_id);
  // window or transient_window or both may be null if a local delete occurs
  // with an in flight delete from the server.
  if (window && transient_window)
    window->RemoveTransientChildFromServer(transient_window);
}

void WindowTreeClient::OnWindowHierarchyChanged(
    ui::Id window_id,
    ui::Id old_parent_id,
    ui::Id new_parent_id,
    std::vector<ui::mojom::WindowDataPtr> windows) {
  const bool was_window_known = GetWindowByServerId(window_id) != nullptr;

  BuildWindowTree(windows);

  // If the window was not known, then BuildWindowTree() will have created it
  // and parented the window.
  if (!was_window_known)
    return;

  WindowMus* new_parent = GetWindowByServerId(new_parent_id);
  WindowMus* old_parent = GetWindowByServerId(old_parent_id);
  WindowMus* window = GetWindowByServerId(window_id);
  if (new_parent)
    new_parent->AddChildFromServer(window);
  else
    old_parent->RemoveChildFromServer(window);
}

void WindowTreeClient::OnWindowReordered(ui::Id window_id,
                                         ui::Id relative_window_id,
                                         ui::mojom::OrderDirection direction) {
  WindowMus* window = GetWindowByServerId(window_id);
  WindowMus* relative_window = GetWindowByServerId(relative_window_id);
  WindowMus* parent = WindowMus::Get(window->GetWindow()->parent());
  if (window && relative_window && parent &&
      parent == WindowMus::Get(relative_window->GetWindow()->parent())) {
    parent->ReorderFromServer(window, relative_window, direction);
  }
}

void WindowTreeClient::OnWindowDeleted(ui::Id window_id) {
  WindowMus* window = GetWindowByServerId(window_id);
  if (!window)
    return;

  if (roots_.count(window)) {
    // Roots are associated with WindowTreeHosts. The WindowTreeHost owns the
    // root, so we have to delete the WindowTreeHost to indirectly delete the
    // Window. Additionally clients may want to do extra processing before the
    // delete, so call to the delegate to handle it. Let the window know it is
    // going to be deleted so we don't callback to the server.
    window->PrepareForDestroy();
    delegate_->OnEmbedRootDestroyed(GetWindowTreeHostMus(window));
  } else {
    window->DestroyFromServer();
  }
}

void WindowTreeClient::OnWindowVisibilityChanged(ui::Id window_id,
                                                 bool visible) {
  WindowMus* window = GetWindowByServerId(window_id);
  if (!window)
    return;

  InFlightVisibleChange new_change(this, window, visible);
  if (ApplyServerChangeToExistingInFlightChange(new_change))
    return;

  SetWindowVisibleFromServer(window, visible);
}

void WindowTreeClient::OnWindowOpacityChanged(ui::Id window_id,
                                              float old_opacity,
                                              float new_opacity) {
  WindowMus* window = GetWindowByServerId(window_id);
  if (!window)
    return;

  InFlightOpacityChange new_change(window, new_opacity);
  if (ApplyServerChangeToExistingInFlightChange(new_change))
    return;

  window->SetOpacityFromServer(new_opacity);
}

void WindowTreeClient::OnWindowParentDrawnStateChanged(ui::Id window_id,
                                                       bool drawn) {
  // TODO: route to WindowTreeHost.
  /*
  Window* window = GetWindowByServerId(window_id);
  if (window)
    WindowPrivate(window).LocalSetParentDrawn(drawn);
  */
}

void WindowTreeClient::OnWindowSharedPropertyChanged(
    ui::Id window_id,
    const std::string& name,
    const base::Optional<std::vector<uint8_t>>& transport_data) {
  WindowMus* window = GetWindowByServerId(window_id);
  if (!window)
    return;

  std::unique_ptr<std::vector<uint8_t>> data;
  if (transport_data.has_value())
    data = std::make_unique<std::vector<uint8_t>>(transport_data.value());

  InFlightPropertyChange new_change(window, name, std::move(data));
  if (ApplyServerChangeToExistingInFlightChange(new_change))
    return;

  window->SetPropertyFromServer(
      name, transport_data.has_value() ? &transport_data.value() : nullptr);
}

void WindowTreeClient::OnWindowInputEvent(
    uint32_t event_id,
    ui::Id window_id,
    int64_t display_id,
    ui::Id display_root_window_id,
    const gfx::PointF& event_location_in_screen_pixel_layout,
    std::unique_ptr<ui::Event> event,
    bool matches_pointer_watcher) {
  DCHECK(event);
  WindowMus* window = GetWindowByServerId(window_id);  // May be null.

  if (matches_pointer_watcher && has_pointer_watcher_) {
    DCHECK(event->IsPointerEvent());
    std::unique_ptr<ui::Event> event_in_dip(ui::Event::Clone(*event));
    ConvertPointerEventLocationToDip(display_id, window,
                                     event_in_dip->AsLocatedEvent());
    delegate_->OnPointerEventObserved(*event_in_dip->AsPointerEvent(),
                                      window ? window->GetWindow() : nullptr);
  }

  // If the window has already been deleted, use |event| to update event states
  // kept in aura::Env.
  if (!window || !window->GetWindow()->GetHost()) {
    EnvInputStateController* env_controller =
        Env::GetInstance()->env_controller();
    std::unique_ptr<ui::Event> mapped_event = MapEvent(*event.get());
    if (mapped_event->IsMouseEvent()) {
      env_controller->UpdateStateForMouseEvent(nullptr,
                                               *mapped_event->AsMouseEvent());
    } else if (mapped_event->IsTouchEvent()) {
      env_controller->UpdateStateForTouchEvent(*mapped_event->AsTouchEvent());
    }
    tree_->OnWindowInputEventAck(event_id, ui::mojom::EventResult::UNHANDLED);
    return;
  }

  if (event->IsKeyEvent()) {
    InputMethodMus* input_method = GetWindowTreeHostMus(window)->input_method();
    if (input_method) {
      ignore_result(input_method->DispatchKeyEvent(
          event->AsKeyEvent(), CreateEventResultCallback(event_id)));
      return;
    }
  }

  EventAckHandler ack_handler(CreateEventResultCallback(event_id));
  // TODO(moshayedi): crbug.com/617222. No need to convert to ui::MouseEvent or
  // ui::TouchEvent once we have proper support for pointer events.
  std::unique_ptr<ui::Event> mapped_event = MapEvent(*event.get());
  ui::Event* event_to_dispatch = mapped_event.get();
// Ash wants the native events in one place (see ExtendedMouseWarpController).
// By using the constructor that takes a MouseEvent we ensure the MouseEvent
// has a NativeEvent that can be used to extract the pixel coordinates.
//
// TODO: this should really be covered by |root_location|. See 608547 for
// details.
#if defined(USE_OZONE)
  std::unique_ptr<ui::MouseEvent> mapped_event_with_native;
  if (mapped_event->type() == ui::ET_MOUSE_MOVED ||
      mapped_event->type() == ui::ET_MOUSE_DRAGGED) {
    mapped_event_with_native = std::make_unique<ui::MouseEvent>(
        static_cast<const base::NativeEvent&>(mapped_event.get()));
    // MouseEvent(NativeEvent) sets the root_location to location.
    mapped_event_with_native->set_root_location_f(
        event_location_in_screen_pixel_layout);
    // |mapped_event| is now the NativeEvent. It's expected the location of the
    // NativeEvent is the same as root_location.
    mapped_event->AsMouseEvent()->set_location_f(
        event_location_in_screen_pixel_layout);
    event_to_dispatch = mapped_event_with_native.get();
  }
#endif

  WindowMus* display_root_window = GetWindowByServerId(display_root_window_id);
  if (display_root_window && event->IsLocatedEvent() &&
      display::Screen::GetScreen()->GetPrimaryDisplay().id() ==
          display::kUnifiedDisplayId) {
    // In Ash's unified desktop mode, each physical display mirrors part of a
    // single virtual display. Dispatch events to the root window of the mirror
    // display supplying the event, using locations relative to that display.
    // Use a null target to ensure events reach the MusUnifiedEventTargeter.
    // This paralells the behavior of unified desktop mode in classic Ash.
    ui::Event::DispatcherApi(event_to_dispatch).set_target(nullptr);
    ui::LocatedEvent* located_event = event_to_dispatch->AsLocatedEvent();
    located_event->set_location_f(located_event->root_location_f());
    window = display_root_window;
  } else if (!event->IsKeyEvent()) {
    // Set |window| as the target, except for key events. Key events go to the
    // focused window, which may have changed by the time we process the event.
    ui::Event::DispatcherApi(event_to_dispatch).set_target(window->GetWindow());
  }
  GetWindowTreeHostMus(window)->SendEventToSink(event_to_dispatch);

  ack_handler.set_handled(event_to_dispatch->handled());
}

void WindowTreeClient::OnPointerEventObserved(std::unique_ptr<ui::Event> event,
                                              ui::Id window_id,
                                              int64_t display_id) {
  DCHECK(event);
  DCHECK(event->IsPointerEvent());
  if (!has_pointer_watcher_)
    return;

  WindowMus* target_window = GetWindowByServerId(window_id);
  ConvertPointerEventLocationToDip(display_id, target_window,
                                   event->AsLocatedEvent());
  delegate_->OnPointerEventObserved(
      *event->AsPointerEvent(),
      target_window ? target_window->GetWindow() : nullptr);
}

void WindowTreeClient::OnWindowFocused(ui::Id focused_window_id) {
  WindowMus* focused_window = GetWindowByServerId(focused_window_id);
  InFlightFocusChange new_change(this, focus_synchronizer_.get(),
                                 focused_window);
  if (ApplyServerChangeToExistingInFlightChange(new_change))
    return;

  focus_synchronizer_->SetFocusFromServer(focused_window);
}

void WindowTreeClient::OnWindowCursorChanged(ui::Id window_id,
                                             ui::CursorData cursor) {
  WindowMus* window = GetWindowByServerId(window_id);
  if (!window)
    return;

  InFlightCursorChange new_change(window, cursor);
  if (ApplyServerChangeToExistingInFlightChange(new_change))
    return;

  window->SetCursorFromServer(cursor);
}

void WindowTreeClient::OnWindowSurfaceChanged(
    ui::Id window_id,
    const viz::SurfaceInfo& surface_info) {
  WindowMus* window = GetWindowByServerId(window_id);
  if (!window)
    return;

  // If the parent is informed of a child's surface then that surface ID is
  // guaranteed to be available in the display compositor so we set it as the
  // fallback. If surface synchronization is enabled, the primary SurfaceInfo
  // is created by the embedder, and the LocalSurfaceId is allocated by the
  // embedder.
  window->SetFallbackSurfaceInfo(surface_info);
}

void WindowTreeClient::OnDragDropStart(
    const std::unordered_map<std::string, std::vector<uint8_t>>& mime_data) {
  drag_drop_controller_->OnDragDropStart(mojo::UnorderedMapToMap(mime_data));
}

void WindowTreeClient::OnDragEnter(ui::Id window_id,
                                   uint32_t key_state,
                                   const gfx::Point& position,
                                   uint32_t effect_bitmask,
                                   const OnDragEnterCallback& callback) {
  callback.Run(drag_drop_controller_->OnDragEnter(
      GetWindowByServerId(window_id), key_state, position, effect_bitmask));
}

void WindowTreeClient::OnDragOver(ui::Id window_id,
                                  uint32_t key_state,
                                  const gfx::Point& position,
                                  uint32_t effect_bitmask,
                                  const OnDragOverCallback& callback) {
  callback.Run(drag_drop_controller_->OnDragOver(
      GetWindowByServerId(window_id), key_state, position, effect_bitmask));
}

void WindowTreeClient::OnDragLeave(ui::Id window_id) {
  drag_drop_controller_->OnDragLeave(GetWindowByServerId(window_id));
}

void WindowTreeClient::OnDragDropDone() {
  drag_drop_controller_->OnDragDropDone();
}

void WindowTreeClient::OnCompleteDrop(ui::Id window_id,
                                      uint32_t key_state,
                                      const gfx::Point& position,
                                      uint32_t effect_bitmask,
                                      const OnCompleteDropCallback& callback) {
  callback.Run(drag_drop_controller_->OnCompleteDrop(
      GetWindowByServerId(window_id), key_state, position, effect_bitmask));
}

void WindowTreeClient::OnPerformDragDropCompleted(uint32_t change_id,
                                                  bool success,
                                                  uint32_t action_taken) {
  OnChangeCompleted(change_id, success);
  if (drag_drop_controller_->DoesChangeIdMatchDragChangeId(change_id))
    drag_drop_controller_->OnPerformDragDropCompleted(action_taken);
}

void WindowTreeClient::OnChangeCompleted(uint32_t change_id, bool success) {
  std::unique_ptr<InFlightChange> change(std::move(in_flight_map_[change_id]));
  in_flight_map_.erase(change_id);
  if (!change)
    return;

  for (auto& observer : test_observers_)
    observer.OnChangeCompleted(change_id, change->change_type(), success);

  if (!success)
    change->ChangeFailed();

  InFlightChange* next_change = GetOldestInFlightChangeMatching(*change);
  if (next_change) {
    if (!success)
      next_change->SetRevertValueFrom(*change);
  } else if (!success) {
    change->Revert();
  }

  if (change_id == current_move_loop_change_) {
    current_move_loop_change_ = 0;
    on_current_move_finished_.Run(success);
    on_current_move_finished_.Reset();
  }
}

void WindowTreeClient::SetBlockingContainers(
    const std::vector<BlockingContainers>& all_blocking_containers) {
  std::vector<ui::mojom::BlockingContainersPtr>
      transport_all_blocking_containers;
  for (const BlockingContainers& blocking_containers :
       all_blocking_containers) {
    ui::mojom::BlockingContainersPtr transport_blocking_containers =
        ui::mojom::BlockingContainers::New();
    // The |system_modal_container| must be specified, |min_container| may be
    // null.
    DCHECK(blocking_containers.system_modal_container);
    transport_blocking_containers->system_modal_container_id =
        GetServerIdForWindow(blocking_containers.system_modal_container);
    transport_blocking_containers->min_container_id =
        GetServerIdForWindow(blocking_containers.min_container);
    transport_all_blocking_containers.push_back(
        std::move(transport_blocking_containers));
  }
  window_manager_client_->SetBlockingContainers(
      std::move(transport_all_blocking_containers),
      base::Bind(&OnAckMustSucceed, FROM_HERE));
}

void WindowTreeClient::GetWindowManager(
    mojo::AssociatedInterfaceRequest<WindowManager> internal) {
  window_manager_internal_.reset(
      new mojo::AssociatedBinding<ui::mojom::WindowManager>(
          this, std::move(internal)));
}

void WindowTreeClient::RequestClose(ui::Id window_id) {
  WindowMus* window = GetWindowByServerId(window_id);
  if (!window || !IsRoot(window))
    return;

  // Since the window is the root window, we send close request to the entire
  // WindowTreeHost.
  GetWindowTreeHostMus(window->GetWindow())->OnCloseRequest();
}

bool WindowTreeClient::WaitForInitialDisplays() {
  if (got_initial_displays_)
    return true;

  bool valid_wait = true;
  // TODO(sky): having to block here is not ideal. http://crbug.com/594852.
  while (!got_initial_displays_ && valid_wait)
    valid_wait = binding_.WaitForIncomingMethodCall();
  return valid_wait;
}

WindowTreeHostMusInitParams WindowTreeClient::CreateInitParamsForNewDisplay() {
  WindowTreeHostMusInitParams init_params;
  init_params.window_port = std::make_unique<WindowPortMus>(
      this, WindowMusType::DISPLAY_MANUALLY_CREATED);
  roots_.insert(init_params.window_port.get());
  init_params.window_tree_client = this;
  return init_params;
}

void WindowTreeClient::OnConnect() {
  got_initial_displays_ = true;
  if (window_manager_delegate_)
    window_manager_delegate_->OnWmConnected();
}

void WindowTreeClient::WmOnAcceleratedWidgetForDisplay(
    int64_t display,
    gpu::SurfaceHandle surface_handle) {
  if (window_manager_delegate_) {
    window_manager_delegate_->OnWmAcceleratedWidgetAvailableForDisplay(
        display, surface_handle);
  }
}

void WindowTreeClient::WmNewDisplayAdded(
    const display::Display& display,
    ui::mojom::WindowDataPtr root_data,
    bool parent_drawn,
    const base::Optional<viz::LocalSurfaceId>& local_surface_id) {
  WmNewDisplayAddedImpl(display, std::move(root_data), parent_drawn,
                        local_surface_id);
}

void WindowTreeClient::WmDisplayRemoved(int64_t display_id) {
  DCHECK(window_manager_delegate_);
  for (WindowMus* root : roots_) {
    DCHECK(root->GetWindow()->GetHost());
    WindowTreeHostMus* window_tree_host =
        static_cast<WindowTreeHostMus*>(root->GetWindow()->GetHost());
    if (window_tree_host->display_id() == display_id) {
      window_manager_delegate_->OnWmDisplayRemoved(window_tree_host);
      return;
    }
  }
}

void WindowTreeClient::WmDisplayModified(const display::Display& display) {
  DCHECK(window_manager_delegate_);
  // TODO(sky): this should likely route to WindowTreeHost.
  window_manager_delegate_->OnWmDisplayModified(display);
}

void WindowTreeClient::WmSetBounds(uint32_t change_id,
                                   ui::Id window_id,
                                   const gfx::Rect& transit_bounds_in_pixels) {
  WindowMus* window = GetWindowByServerId(window_id);
  if (window) {
    float device_scale_factor = window->GetDeviceScaleFactor();
    DCHECK(window_manager_delegate_);
    gfx::Rect transit_bounds_in_dip =
        gfx::ConvertRectToDIP(device_scale_factor, transit_bounds_in_pixels);
    window_manager_delegate_->OnWmSetBounds(window->GetWindow(),
                                            transit_bounds_in_dip);
  } else {
    DVLOG(1) << "Unknown window passed to WmSetBounds().";
  }
  if (window_manager_client_)
    window_manager_client_->WmSetBoundsResponse(change_id);
}

void WindowTreeClient::WmSetProperty(
    uint32_t change_id,
    ui::Id window_id,
    const std::string& name,
    const base::Optional<std::vector<uint8_t>>& transit_data) {
  WindowMus* window = GetWindowByServerId(window_id);
  bool result = false;
  if (window) {
    DCHECK(window_manager_delegate_);
    std::unique_ptr<std::vector<uint8_t>> data;
    if (transit_data.has_value())
      data.reset(new std::vector<uint8_t>(transit_data.value()));

    result = window_manager_delegate_->OnWmSetProperty(window->GetWindow(),
                                                       name, &data);
    if (result) {
      delegate_->GetPropertyConverter()->SetPropertyFromTransportValue(
          window->GetWindow(), name, data.get());
    }
  }
  if (window_manager_client_)
    window_manager_client_->WmResponse(change_id, result);
}

void WindowTreeClient::WmSetModalType(ui::Id window_id, ui::ModalType type) {
  WindowMus* window = GetWindowByServerId(window_id);
  if (window)
    window_manager_delegate_->OnWmSetModalType(window->GetWindow(), type);
}

void WindowTreeClient::WmSetCanFocus(ui::Id window_id, bool can_focus) {
  WindowMus* window = GetWindowByServerId(window_id);
  if (window)
    window_manager_delegate_->OnWmSetCanFocus(window->GetWindow(), can_focus);
}

void WindowTreeClient::WmCreateTopLevelWindow(
    uint32_t change_id,
    const viz::FrameSinkId& frame_sink_id,
    const std::unordered_map<std::string, std::vector<uint8_t>>&
        transport_properties) {
  DCHECK(frame_sink_id.is_valid());
  std::map<std::string, std::vector<uint8_t>> properties =
      mojo::UnorderedMapToMap(transport_properties);
  ui::mojom::WindowType window_type = ui::mojom::WindowType::UNKNOWN;
  auto type_iter =
      properties.find(ui::mojom::WindowManager::kWindowType_InitProperty);
  if (type_iter != properties.end()) {
    // TODO: validation! http://crbug.com/654924.
    window_type = static_cast<ui::mojom::WindowType>(
        mojo::ConvertTo<int32_t>(type_iter->second));
  }
  Window* window = window_manager_delegate_->OnWmCreateTopLevelWindow(
      window_type, &properties);
  if (!window) {
    window_manager_client_->OnWmCreatedTopLevelWindow(change_id,
                                                      kInvalidServerId);
    return;
  }
  embedded_windows_[base::checked_cast<ui::ClientSpecificId>(
                        frame_sink_id.client_id())]
      .insert(window);
  if (window_manager_client_) {
    window_manager_client_->OnWmCreatedTopLevelWindow(
        change_id, WindowMus::Get(window)->server_id());
    OnFrameSinkIdAllocated(WindowMus::Get(window)->server_id(), frame_sink_id);
  }
}

void WindowTreeClient::WmClientJankinessChanged(ui::ClientSpecificId client_id,
                                                bool janky) {
  if (window_manager_delegate_) {
    auto it = embedded_windows_.find(client_id);
    // TODO(sky): early return necessitated because of http://crbug.com/766890.
    if (it == embedded_windows_.end())
      return;
    window_manager_delegate_->OnWmClientJankinessChanged(
        embedded_windows_[client_id], janky);
  }
}

void WindowTreeClient::WmBuildDragImage(const gfx::Point& screen_location,
                                        const SkBitmap& drag_image,
                                        const gfx::Vector2d& drag_image_offset,
                                        ui::mojom::PointerKind source) {
  if (!window_manager_delegate_)
    return;

  window_manager_delegate_->OnWmBuildDragImage(screen_location, drag_image,
                                               drag_image_offset, source);
}

void WindowTreeClient::WmMoveDragImage(
    const gfx::Point& screen_location,
    const WmMoveDragImageCallback& callback) {
  if (!window_manager_delegate_) {
    callback.Run();
    return;
  }

  window_manager_delegate_->OnWmMoveDragImage(screen_location);
  callback.Run();
}

void WindowTreeClient::WmDestroyDragImage() {
  if (!window_manager_delegate_)
    return;

  window_manager_delegate_->OnWmDestroyDragImage();
}

void WindowTreeClient::WmPerformMoveLoop(uint32_t change_id,
                                         ui::Id window_id,
                                         ui::mojom::MoveLoopSource source,
                                         const gfx::Point& cursor_location) {
  if (!window_manager_delegate_ || current_wm_move_loop_change_ != 0) {
    OnWmMoveLoopCompleted(change_id, false);
    return;
  }

  current_wm_move_loop_change_ = change_id;
  current_wm_move_loop_window_id_ = window_id;
  WindowMus* window = GetWindowByServerId(window_id);
  if (window) {
    window_manager_delegate_->OnWmPerformMoveLoop(
        window->GetWindow(), source, cursor_location,
        base::Bind(&WindowTreeClient::OnWmMoveLoopCompleted,
                   weak_factory_.GetWeakPtr(), change_id));
  } else {
    OnWmMoveLoopCompleted(change_id, false);
  }
}

void WindowTreeClient::WmCancelMoveLoop(uint32_t change_id) {
  if (!window_manager_delegate_ || change_id != current_wm_move_loop_change_)
    return;

  WindowMus* window = GetWindowByServerId(current_wm_move_loop_window_id_);
  if (window)
    window_manager_delegate_->OnWmCancelMoveLoop(window->GetWindow());
}

void WindowTreeClient::WmDeactivateWindow(ui::Id window_id) {
  if (!window_manager_delegate_)
    return;

  WindowMus* window = GetWindowByServerId(window_id);
  if (!window) {
    DVLOG(1) << "Attempt to deactivate invalid window " << window_id;
    return;
  }

  if (!window_manager_delegate_->IsWindowActive(window->GetWindow())) {
    DVLOG(1) << "Non-active window requested deactivation.";
    return;
  }

  window_manager_delegate_->OnWmDeactivateWindow(window->GetWindow());
}

void WindowTreeClient::WmStackAbove(uint32_t wm_change_id,
                                    ui::Id above_id,
                                    ui::Id below_id) {
  if (!window_manager_delegate_)
    return;

  WindowMus* below_mus = GetWindowByServerId(below_id);
  if (!below_mus) {
    DVLOG(1) << "Attempt to stack at top invalid window " << below_id;
    if (window_manager_client_)
      window_manager_client_->WmResponse(wm_change_id, false);
    return;
  }

  WindowMus* above_mus = GetWindowByServerId(above_id);
  if (!above_mus) {
    DVLOG(1) << "Attempt to stack at top invalid window " << above_id;
    if (window_manager_client_)
      window_manager_client_->WmResponse(wm_change_id, false);
    return;
  }

  Window* above = above_mus->GetWindow();
  Window* below = below_mus->GetWindow();

  if (above->parent() != below->parent()) {
    DVLOG(1) << "Windows do not share the same parent";
    if (window_manager_client_)
      window_manager_client_->WmResponse(wm_change_id, false);
    return;
  }

  above->parent()->StackChildAbove(above, below);

  if (window_manager_client_)
    window_manager_client_->WmResponse(wm_change_id, true);
}

void WindowTreeClient::WmStackAtTop(uint32_t wm_change_id, ui::Id window_id) {
  if (!window_manager_delegate_)
    return;

  WindowMus* window = GetWindowByServerId(window_id);
  if (!window) {
    DVLOG(1) << "Attempt to stack at top invalid window " << window_id;
    if (window_manager_client_)
      window_manager_client_->WmResponse(wm_change_id, false);
    return;
  }

  Window* parent = window->GetWindow()->parent();
  parent->StackChildAtTop(window->GetWindow());

  if (window_manager_client_)
    window_manager_client_->WmResponse(wm_change_id, true);
}

void WindowTreeClient::WmPerformWmAction(ui::Id window_id,
                                         const std::string& action) {
  if (!window_manager_delegate_)
    return;

  WindowMus* window = GetWindowByServerId(window_id);
  if (window)
    window_manager_delegate_->OnWmPerformAction(window->GetWindow(), action);
}

void WindowTreeClient::OnAccelerator(uint32_t ack_id,
                                     uint32_t accelerator_id,
                                     std::unique_ptr<ui::Event> event) {
  DCHECK(event);
  std::unordered_map<std::string, std::vector<uint8_t>> properties;
  const ui::mojom::EventResult result = window_manager_delegate_->OnAccelerator(
      accelerator_id, *event.get(), &properties);
  if (ack_id && window_manager_client_)
    window_manager_client_->OnAcceleratorAck(ack_id, result, properties);
}

void WindowTreeClient::OnCursorTouchVisibleChanged(bool enabled) {
  if (window_manager_client_)
    window_manager_delegate_->OnCursorTouchVisibleChanged(enabled);
}

void WindowTreeClient::OnEventBlockedByModalWindow(ui::Id window_id) {
  if (!window_manager_delegate_)
    return;

  WindowMus* window = GetWindowByServerId(window_id);
  if (window)
    window_manager_delegate_->OnEventBlockedByModalWindow(window->GetWindow());
}

void WindowTreeClient::SetFrameDecorationValues(
    ui::mojom::FrameDecorationValuesPtr values) {
  if (window_manager_client_) {
    normal_client_area_insets_ = values->normal_client_area_insets;
    window_manager_client_->WmSetFrameDecorationValues(std::move(values));
  }
}

void WindowTreeClient::SetNonClientCursor(Window* window,
                                          const ui::CursorData& cursor) {
  if (window_manager_client_) {
    window_manager_client_->WmSetNonClientCursor(
        WindowMus::Get(window)->server_id(), cursor);
  }
}

void WindowTreeClient::AddAccelerators(
    std::vector<ui::mojom::WmAcceleratorPtr> accelerators,
    const base::Callback<void(bool)>& callback) {
  if (window_manager_client_) {
    window_manager_client_->AddAccelerators(std::move(accelerators), callback);
  }
}

void WindowTreeClient::RemoveAccelerator(uint32_t id) {
  if (window_manager_client_) {
    window_manager_client_->RemoveAccelerator(id);
  }
}

void WindowTreeClient::AddActivationParent(Window* window) {
  if (window_manager_client_) {
    window_manager_client_->AddActivationParent(
        WindowMus::Get(window)->server_id());
  }
}

void WindowTreeClient::RemoveActivationParent(Window* window) {
  if (window_manager_client_) {
    window_manager_client_->RemoveActivationParent(
        WindowMus::Get(window)->server_id());
  }
}

void WindowTreeClient::SetExtendedHitRegionForChildren(
    Window* window,
    const gfx::Insets& mouse_insets,
    const gfx::Insets& touch_insets) {
  if (!window_manager_client_)
    return;

  WindowMus* window_mus = WindowMus::Get(window);
  const float device_scale_factor = window_mus->GetDeviceScaleFactor();
  window_manager_client_->SetExtendedHitRegionForChildren(
      window_mus->server_id(),
      gfx::ConvertInsetsToPixel(device_scale_factor, mouse_insets),
      gfx::ConvertInsetsToPixel(device_scale_factor, touch_insets));
}

void WindowTreeClient::LockCursor() {
  if (window_manager_client_)
    window_manager_client_->WmLockCursor();
}

void WindowTreeClient::UnlockCursor() {
  if (window_manager_client_)
    window_manager_client_->WmUnlockCursor();
}

void WindowTreeClient::SetCursorVisible(bool visible) {
  if (window_manager_client_)
    window_manager_client_->WmSetCursorVisible(visible);
}

void WindowTreeClient::SetCursorSize(ui::CursorSize cursor_size) {
  if (window_manager_client_)
    window_manager_client_->WmSetCursorSize(cursor_size);
}

void WindowTreeClient::SetGlobalOverrideCursor(
    base::Optional<ui::CursorData> cursor) {
  if (window_manager_client_)
    window_manager_client_->WmSetGlobalOverrideCursor(std::move(cursor));
}

void WindowTreeClient::SetCursorTouchVisible(bool enabled) {
  if (window_manager_client_)
    window_manager_client_->WmSetCursorTouchVisible(enabled);
}

void WindowTreeClient::InjectEvent(const ui::Event& event, int64_t display_id) {
  if (!event_injector_)
    connector()->BindInterface(ui::mojom::kServiceName, &event_injector_);
  // Check event_injector_ so we don't crash if access to the interface was
  // refused.
  if (event_injector_) {
    event_injector_->DispatchEvent(display_id, ui::Event::Clone(event),
                                   base::DoNothing());
  }
}

void WindowTreeClient::SetKeyEventsThatDontHideCursor(
    std::vector<ui::mojom::EventMatcherPtr> cursor_key_list) {
  if (window_manager_client_) {
    window_manager_client_->SetKeyEventsThatDontHideCursor(
        std::move(cursor_key_list));
  }
}

void WindowTreeClient::RequestClose(Window* window) {
  DCHECK(window);
  if (window_manager_client_)
    window_manager_client_->WmRequestClose(WindowMus::Get(window)->server_id());
}

void WindowTreeClient::SetDisplayConfiguration(
    const std::vector<display::Display>& displays,
    std::vector<ui::mojom::WmViewportMetricsPtr> viewport_metrics,
    int64_t primary_display_id,
    const std::vector<display::Display>& mirrors) {
  DCHECK_EQ(displays.size() + mirrors.size(), viewport_metrics.size());
  if (window_manager_client_) {
    const int64_t internal_display_id =
        display::Display::HasInternalDisplay()
            ? display::Display::InternalDisplayId()
            : display::kInvalidDisplayId;
    window_manager_client_->SetDisplayConfiguration(
        displays, std::move(viewport_metrics), primary_display_id,
        internal_display_id, mirrors, base::Bind(&OnAckMustSucceed, FROM_HERE));
  }
}

void WindowTreeClient::AddDisplayReusingWindowTreeHost(
    WindowTreeHostMus* window_tree_host,
    const display::Display& display,
    ui::mojom::WmViewportMetricsPtr viewport_metrics) {
  DCHECK_NE(display.id(), window_tree_host->display_id());
  window_tree_host->set_display_id(display.id());
  if (window_manager_client_) {
    // NOTE: The values of |is_primary_display| and |mirrors| do not matter,
    // because SetDisplayConfiguration() is called shortly after this completes.
    const bool is_primary_display = true;
    std::vector<display::Display> mirrors;
    WindowMus* display_root_window = WindowMus::Get(window_tree_host->window());
    window_manager_client_->SetDisplayRoot(
        display, std::move(viewport_metrics), is_primary_display,
        display_root_window->server_id(), mirrors,
        base::Bind(&OnAckMustSucceed, FROM_HERE));
    window_tree_host->compositor()->SetLocalSurfaceId(
        display_root_window->GetOrAllocateLocalSurfaceId(
            window_tree_host->GetBoundsInPixels().size()));
  }
}

void WindowTreeClient::SwapDisplayRoots(WindowTreeHostMus* window_tree_host1,
                                        WindowTreeHostMus* window_tree_host2) {
  DCHECK_NE(window_tree_host1, window_tree_host2);
  const int64_t display_id1 = window_tree_host1->display_id();
  const int64_t display_id2 = window_tree_host2->display_id();
  DCHECK_NE(display_id1, display_id2);
  window_tree_host1->set_display_id(display_id2);
  window_tree_host2->set_display_id(display_id1);

  // Swap the accelerated widgets so each host paints to the correct display.
  gfx::AcceleratedWidget widget1 = window_tree_host1->GetAcceleratedWidget();
  gfx::AcceleratedWidget widget2 = window_tree_host2->GetAcceleratedWidget();
  window_tree_host1->OverrideAcceleratedWidget(widget2);
  window_tree_host2->OverrideAcceleratedWidget(widget1);

  if (window_manager_client_) {
    window_manager_client_->SwapDisplayRoots(
        display_id1, display_id2, base::Bind(&OnAckMustSucceed, FROM_HERE));
  }
}

void WindowTreeClient::OnWindowTreeHostBoundsWillChange(
    WindowTreeHostMus* window_tree_host,
    const gfx::Rect& bounds) {
  gfx::Rect old_bounds = window_tree_host->GetBoundsInPixels();
  gfx::Rect new_bounds = bounds;
  if (window_manager_delegate_) {
    // The window manager origins should always be 0x0. The real origin is
    // communicated by way of SetDisplayConfiguration().
    old_bounds.set_origin(gfx::Point());
    new_bounds.set_origin(gfx::Point());
  }
  ScheduleInFlightBoundsChange(WindowMus::Get(window_tree_host->window()),
                               old_bounds, new_bounds);
}

void WindowTreeClient::OnWindowTreeHostClientAreaWillChange(
    WindowTreeHostMus* window_tree_host,
    const gfx::Insets& client_area,
    const std::vector<gfx::Rect>& additional_client_areas) {
  DCHECK(tree_);
  WindowMus* window = WindowMus::Get(window_tree_host->window());
  float device_scale_factor = window->GetDeviceScaleFactor();
  std::vector<gfx::Rect> additional_client_areas_in_pixel;
  for (const gfx::Rect& area : additional_client_areas) {
    additional_client_areas_in_pixel.push_back(
        gfx::ConvertRectToPixel(device_scale_factor, area));
  }
  tree_->SetClientArea(
      window->server_id(),
      gfx::ConvertInsetsToPixel(device_scale_factor, client_area),
      additional_client_areas_in_pixel);
}

void WindowTreeClient::OnWindowTreeHostSetOpacity(
    WindowTreeHostMus* window_tree_host,
    float opacity) {
  WindowMus* window = WindowMus::Get(window_tree_host->window());
  const uint32_t change_id = ScheduleInFlightChange(
      std::make_unique<CrashInFlightChange>(window, ChangeType::OPACITY));
  tree_->SetWindowOpacity(change_id, window->server_id(), opacity);
}

void WindowTreeClient::OnWindowTreeHostDeactivateWindow(
    WindowTreeHostMus* window_tree_host) {
  tree_->DeactivateWindow(
      WindowMus::Get(window_tree_host->window())->server_id());
}

void WindowTreeClient::OnWindowTreeHostStackAbove(
    WindowTreeHostMus* window_tree_host,
    Window* window) {
  WindowMus* above = WindowMus::Get(window_tree_host->window());
  WindowMus* below = WindowMus::Get(window);
  const uint32_t change_id = ScheduleInFlightChange(
      std::make_unique<CrashInFlightChange>(above, ChangeType::REORDER));
  tree_->StackAbove(change_id, above->server_id(), below->server_id());
}

void WindowTreeClient::OnWindowTreeHostStackAtTop(
    WindowTreeHostMus* window_tree_host) {
  WindowMus* window = WindowMus::Get(window_tree_host->window());
  const uint32_t change_id = ScheduleInFlightChange(
      std::make_unique<CrashInFlightChange>(window, ChangeType::REORDER));
  tree_->StackAtTop(change_id, window->server_id());
}

void WindowTreeClient::OnWindowTreeHostPerformWmAction(
    WindowTreeHostMus* window_tree_host,
    const std::string& action) {
  WindowMus* window = WindowMus::Get(window_tree_host->window());
  tree_->PerformWmAction(window->server_id(), action);
}

void WindowTreeClient::OnWindowTreeHostPerformWindowMove(
    WindowTreeHostMus* window_tree_host,
    ui::mojom::MoveLoopSource source,
    const gfx::Point& cursor_location,
    const base::Callback<void(bool)>& callback) {
  DCHECK(on_current_move_finished_.is_null());
  on_current_move_finished_ = callback;

  WindowMus* window_mus = WindowMus::Get(window_tree_host->window());
  current_move_loop_change_ = ScheduleInFlightChange(
      std::make_unique<InFlightDragChange>(window_mus, ChangeType::MOVE_LOOP));
  // Tell the window manager to take over moving us.
  tree_->PerformWindowMove(current_move_loop_change_, window_mus->server_id(),
                           source, cursor_location);
}

void WindowTreeClient::OnWindowTreeHostCancelWindowMove(
    WindowTreeHostMus* window_tree_host) {
  tree_->CancelWindowMove(
      WindowMus::Get(window_tree_host->window())->server_id());
}

void WindowTreeClient::OnWindowTreeHostMoveCursorToDisplayLocation(
    const gfx::Point& location_in_pixels,
    int64_t display_id) {
  DCHECK(window_manager_client_);
  if (window_manager_client_) {
    window_manager_client_->WmMoveCursorToDisplayLocation(location_in_pixels,
                                                          display_id);
  }
}

void WindowTreeClient::OnWindowTreeHostConfineCursorToBounds(
    const gfx::Rect& bounds_in_pixels,
    int64_t display_id) {
  DCHECK(window_manager_client_);
  if (window_manager_client_) {
    window_manager_client_->WmConfineCursorToBounds(bounds_in_pixels,
                                                    display_id);
  }
}

std::unique_ptr<WindowPortMus> WindowTreeClient::CreateWindowPortForTopLevel(
    const std::map<std::string, std::vector<uint8_t>>* properties) {
  std::unique_ptr<WindowPortMus> window_port =
      std::make_unique<WindowPortMus>(this, WindowMusType::TOP_LEVEL);
  roots_.insert(window_port.get());

  window_port->set_server_id(next_window_id_++);
  RegisterWindowMus(window_port.get());

  std::unordered_map<std::string, std::vector<uint8_t>> transport_properties;
  if (properties) {
    for (const auto& property_pair : *properties)
      transport_properties[property_pair.first] = property_pair.second;
  }

  const uint32_t change_id =
      ScheduleInFlightChange(std::make_unique<CrashInFlightChange>(
          window_port.get(), ChangeType::NEW_TOP_LEVEL_WINDOW));
  tree_->NewTopLevelWindow(change_id, window_port->server_id(),
                           transport_properties);
  return window_port;
}

void WindowTreeClient::OnWindowTreeHostCreated(
    WindowTreeHostMus* window_tree_host) {
  // All WindowTreeHosts are destroyed before this, so we don't need to unset
  // the DragDropClient.
  if (install_drag_drop_client_) {
    client::SetDragDropClient(window_tree_host->window(),
                              drag_drop_controller_.get());
  }
}

void WindowTreeClient::OnTransientChildWindowAdded(Window* parent,
                                                   Window* transient_child) {
  // TransientWindowClient is a singleton and we allow multiple
  // WindowTreeClients. Ignore changes to windows we don't know about (assume
  // they came from another connection).
  if (!IsWindowKnown(parent) || !IsWindowKnown(transient_child))
    return;

  if (WindowMus::Get(parent)->OnTransientChildAdded(
          WindowMus::Get(transient_child)) == WindowMus::ChangeSource::SERVER) {
    return;
  }

  // The change originated from client code and needs to be sent to the server.
  DCHECK(tree_);
  WindowMus* parent_mus = WindowMus::Get(parent);
  const uint32_t change_id =
      ScheduleInFlightChange(std::make_unique<CrashInFlightChange>(
          parent_mus, ChangeType::ADD_TRANSIENT_WINDOW));
  tree_->AddTransientWindow(change_id, parent_mus->server_id(),
                            WindowMus::Get(transient_child)->server_id());
}

void WindowTreeClient::OnTransientChildWindowRemoved(Window* parent,
                                                     Window* transient_child) {
  // See comments in OnTransientChildWindowAdded() for details on early return.
  if (!IsWindowKnown(parent) || !IsWindowKnown(transient_child))
    return;

  if (WindowMus::Get(parent)->OnTransientChildRemoved(
          WindowMus::Get(transient_child)) == WindowMus::ChangeSource::SERVER) {
    return;
  }
  // The change originated from client code and needs to be sent to the server.
  DCHECK(tree_);
  WindowMus* child_mus = WindowMus::Get(transient_child);
  const uint32_t change_id =
      ScheduleInFlightChange(std::make_unique<CrashInFlightChange>(
          child_mus, ChangeType::REMOVE_TRANSIENT_WINDOW_FROM_PARENT));
  tree_->RemoveTransientWindowFromParent(change_id, child_mus->server_id());
}

uint32_t WindowTreeClient::CreateChangeIdForDrag(WindowMus* window) {
  return ScheduleInFlightChange(
      std::make_unique<InFlightDragChange>(window, ChangeType::DRAG_LOOP));
}

uint32_t WindowTreeClient::CreateChangeIdForCapture(WindowMus* window) {
  return ScheduleInFlightChange(std::make_unique<InFlightCaptureChange>(
      this, capture_synchronizer_.get(), window));
}

uint32_t WindowTreeClient::CreateChangeIdForFocus(WindowMus* window) {
  return ScheduleInFlightChange(std::make_unique<InFlightFocusChange>(
      this, focus_synchronizer_.get(), window));
}

}  // namespace aura
