// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "services/ws/window_tree.h"

#include <algorithm>

#include "base/auto_reset.h"
#include "base/bind.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
#include "base/unguessable_token.h"
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "components/viz/common/surfaces/surface_info.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "mojo/public/cpp/bindings/map.h"
#include "services/ws/client_change.h"
#include "services/ws/client_change_tracker.h"
#include "services/ws/client_root.h"
#include "services/ws/common/util.h"
#include "services/ws/drag_drop_delegate.h"
#include "services/ws/embedding.h"
#include "services/ws/event_observer_helper.h"
#include "services/ws/proxy_window.h"
#include "services/ws/public/cpp/property_type_converters.h"
#include "services/ws/top_level_proxy_window_impl.h"
#include "services/ws/topmost_window_observer.h"
#include "services/ws/window_delegate_impl.h"
#include "services/ws/window_manager_interface.h"
#include "services/ws/window_service.h"
#include "services/ws/window_service_delegate.h"
#include "services/ws/window_service_observer.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/transient_window_client.h"
#include "ui/aura/env.h"
#include "ui/aura/mus/os_exchange_data_provider_mus.h"
#include "ui/aura/mus/property_converter.h"
#include "ui/aura/mus/property_utils.h"
#include "ui/aura/window.h"
#include "ui/aura/window_observer.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/base/hit_test.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_type.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/events/event_utils.h"
#include "ui/events/gestures/gesture_recognizer.h"
#include "ui/events/mojo/event_struct_traits.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/wm/core/capture_controller.h"
#include "ui/wm/core/window_modality_controller.h"
#include "ui/wm/core/window_util.h"
#include "ui/wm/public/activation_client.h"

#if defined(USE_OZONE)
#include "ui/ozone/public/cursor_factory_ozone.h"
#endif

namespace ws {
namespace {

// Max number of event we let a client queue before pruning. In general only
// bad (or buggy) clients should hit this cap.
#if defined(NDEBUG)
constexpr size_t kMaxQueuedEvents = 100;
#else
constexpr size_t kMaxQueuedEvents = 1000;
#endif

uint32_t GenerateEventAckId() {
  // We do not want to create a sequential id for each event, because that can
  // leak some information to the client. So instead, manufacture the id
  // randomly.
  return 0x1000000 | (rand() & 0xffffff);
}

gfx::Insets MakeInsetsPositive(const gfx::Insets& insets) {
  return gfx::Insets(std::max(0, insets.top()), std::max(0, insets.left()),
                     std::max(0, insets.bottom()), std::max(0, insets.right()));
}

}  // namespace

// Used to track events sent to the client.
struct WindowTree::InFlightEvent {
  // Unique identifier for the event. It is expected that the client respond
  // with this id.
  uint32_t id;

  // Only used for KeyEvents sent to the client. If a KeyEvent is not handled
  // by the client, it's processed locally for accelerators.
  std::unique_ptr<ui::Event> event;
};

WindowTree::KnownWindow::KnownWindow() = default;
WindowTree::KnownWindow::~KnownWindow() = default;

WindowTree::WindowTree(WindowService* window_service,
                       ClientSpecificId client_id,
                       mojom::WindowTreeClient* client,
                       const std::string& client_name)
    : window_service_(window_service),
      client_id_(client_id),
      client_name_(client_name),
      window_tree_client_(client),
      property_change_tracker_(std::make_unique<ClientChangeTracker>()) {
  wm::CaptureController::Get()->AddObserver(this);
}

WindowTree::~WindowTree() {
  wm::CaptureController::Get()->RemoveObserver(this);

  // Delete the embeddings first, that way we don't attempt to notify the client
  // when the windows the client created are deleted.
  while (!client_roots_.empty()) {
    DeleteClientRoot(client_roots_.begin()->get(),
                     DeleteClientRootReason::kDestructor);
  }

  while (FindFirstClientCreatedWindow()) {
    // RemoveWindowFromKnownWindows() should make it such that the Window is no
    // longer recognized as being created (owned) by this client.
    const bool delete_if_owned = true;
    RemoveWindowFromKnownWindows(FindFirstClientCreatedWindow(),
                                 delete_if_owned);
  }

  window_service_->OnWillDestroyWindowTree(this);
}

void WindowTree::InitForEmbed(aura::Window* root,
                              mojom::WindowTreePtr window_tree_ptr) {
  // Force ProxyWindow to be created for |root|.
  ProxyWindow* proxy_window =
      window_service_->GetProxyWindowForWindowCreateIfNecessary(root);
  const ClientWindowId client_window_id = proxy_window->frame_sink_id();
  AddWindowToKnownWindows(root, client_window_id, nullptr);
  const bool is_top_level = false;
  ClientRoot* client_root = CreateClientRoot(root, is_top_level);

  const int64_t display_id =
      display::Screen::GetScreen()->GetDisplayNearestWindow(root).id();
  const ClientWindowId focused_window_id =
      root->HasFocus() ? ClientWindowIdForWindow(root) : ClientWindowId();
  const bool drawn = root->IsVisible() && root->GetHost();
  window_tree_client_->OnEmbed(
      WindowToWindowData(root), std::move(window_tree_ptr), display_id,
      ClientWindowIdToTransportId(focused_window_id), drawn,
      proxy_window->local_surface_id_allocation());

  // Reset the frame sink id locally (after calling OnEmbed()). This is
  // needed so that the id used by the client matches the id used locally.
  proxy_window->set_frame_sink_id(ClientWindowId(client_id_, 0));

  client_root->RegisterVizEmbeddingSupport();
}

void WindowTree::InitFromFactory() {
  connection_type_ = ConnectionType::kOther;
}

void WindowTree::SendEventToClient(aura::Window* window,
                                   const ui::Event& event) {
  // As gesture recognition runs in the client, GestureEvents should not be
  // forwarded. ProxyWindow's event processing should ensure no GestureEvents
  // are sent. Some pinch events are allowed.
  DCHECK(!event.IsGestureEvent() || event.IsPinchEvent());

  const uint32_t event_id = GenerateEventAckId();
  auto* in_flight_event_queue =
      event.IsKeyEvent() ? &in_flight_key_events_ : &in_flight_other_events_;
  if (in_flight_event_queue->size() < kMaxQueuedEvents) {
    std::unique_ptr<InFlightEvent> in_flight_event =
        std::make_unique<InFlightEvent>();
    in_flight_event->id = event_id;
    if (event.type() == ui::ET_KEY_PRESSED ||
        event.type() == ui::ET_KEY_RELEASED) {
      in_flight_event->event = ui::Event::Clone(event);
    }
    in_flight_event_queue->push(std::move(in_flight_event));
  } else {
    DVLOG(1) << "client not responding to events in a timely manner, "
             << "dropping event";
  }

  // Events should only come to windows connected to displays.
  DCHECK(window->GetHost());
  const int64_t display_id = window->GetHost()->GetDisplayId();
  const bool matches_event_observer =
      event_observer_helper_ && event_observer_helper_->DoesEventMatch(event);
  if (event_observer_helper_)
    event_observer_helper_->ClearPendingEvent();

  for (WindowServiceObserver& observer : window_service_->observers())
    observer.OnWillSendEventToClient(client_id_, event_id, event);

  std::unique_ptr<ui::Event> event_to_send = ui::Event::Clone(event);
  if (event.IsLocatedEvent()) {
    ui::LocatedEvent* located_event = event_to_send->AsLocatedEvent();
    // Translate the root location for located events. Event's root location
    // should be in the coordinate of the root window, however the root for the
    // target window in the client can be different from the one in the server,
    // thus the root location needs to be converted from the original coordinate
    // to the one used in the client. See also 'WindowTreeTest.EventLocation'
    // test case.
    located_event->set_root_location_f(
        ConvertRootLocationForClient(window, located_event->root_location_f()));
  }
  DVLOG(4) << "SendEventToClient window="
           << ProxyWindow::GetMayBeNull(window)->GetIdForDebugging()
           << " event_type=" << ui::EventTypeName(event.type())
           << " event_id=" << event_id;
  TRACE_EVENT_ASYNC_BEGIN1("ui", "WindowTree::SendEventToClient", event_id,
                           "event_type",
                           ui::EventTypeName(event_to_send->type()));
  window_tree_client_->OnWindowInputEvent(
      event_id, TransportIdForWindow(window), display_id,
      std::move(event_to_send), matches_event_observer);
}

void WindowTree::SendObservedEventToClient(int64_t display_id,
                                           std::unique_ptr<ui::Event> event) {
  if (event->IsLocatedEvent()) {
    // Send event locations in screen coordinates, since the client will have no
    // knowledge of the event's target window.
    ui::LocatedEvent* located_event = event->AsLocatedEvent();
    gfx::PointF location = located_event->root_location_f();
    display::Display display;
    if (located_event->target()) {
      location = located_event->target()->GetScreenLocationF(*located_event);
    } else if (display::Screen::GetScreen()->GetDisplayWithDisplayId(
                   display_id, &display)) {
      location += display.bounds().OffsetFromOrigin();
    }
    located_event->set_location_f(location);
    located_event->set_root_location_f(location);
  }
  DVLOG(4) << "SendObservedEventToClient event_type="
           << ui::EventTypeName(event->type());
  window_tree_client_->OnObservedInputEvent(std::move(event));
}

bool WindowTree::IsTopLevel(aura::Window* window) {
  auto iter = FindClientRootWithRoot(window);
  return iter != client_roots_.end() && (*iter)->is_top_level();
}

aura::Window* WindowTree::GetWindowByTransportId(Id transport_window_id) {
  return GetWindowByClientId(MakeClientWindowId(transport_window_id));
}

void WindowTree::RequestClose(ProxyWindow* window) {
  DCHECK(window->IsTopLevel());
  DCHECK_EQ(this, window->owning_window_tree());
  window_tree_client_->RequestClose(TransportIdForWindow(window->window()));
}

void WindowTree::OnEmbeddingDestroyed(Embedding* embedding) {
  DVLOG(3) << "OnEmbeddingDestroyed client=" << client_id_
           << " window=" << ClientWindowIdForWindow(embedding->window());
  auto iter = FindClientRootWithRoot(embedding->window());
  DCHECK(iter != client_roots_.end());
  window_tree_client_->OnWindowDeleted(
      TransportIdForWindow(embedding->window()));
  DeleteClientRoot(iter->get(), DeleteClientRootReason::kDeleted);
}

ClientWindowId WindowTree::RemoveScheduledEmbedUsingExistingClient(
    const base::UnguessableToken& embed_token) {
  auto iter = scheduled_embeds_for_existing_client_.find(embed_token);
  if (iter == scheduled_embeds_for_existing_client_.end())
    return ClientWindowId();

  const ClientWindowId client_window_id = MakeClientWindowId(iter->second);
  if (!IsValidIdForNewWindow(client_window_id)) {
    DVLOG(1) << "EmbedUsingToken failed (access denied)";
    return ClientWindowId();
  }
  return client_window_id;
}

void WindowTree::CompleteScheduleEmbedForExistingClient(
    aura::Window* window,
    const ClientWindowId& id,
    const base::UnguessableToken& token) {
  AddWindowToKnownWindows(window, id, nullptr);
  const bool is_top_level = false;
  ClientRoot* client_root = CreateClientRoot(window, is_top_level);

  ProxyWindow* proxy_window = ProxyWindow::GetMayBeNull(window);
  // It's expected we only get here if a ProxyWindow exists for |window|.
  DCHECK(proxy_window);

  const int64_t display_id =
      display::Screen::GetScreen()->GetDisplayNearestWindow(window).id();
  window_tree_client_->OnEmbedFromToken(
      token, WindowToWindowData(window), display_id,
      proxy_window->local_surface_id_allocation());

  // Reset the frame sink id locally (after calling OnEmbedFromToken()). This is
  // needed so that the id used by the client matches the id used locally.
  proxy_window->set_frame_sink_id(id);

  client_root->RegisterVizEmbeddingSupport();
}

ClientRoot* WindowTree::GetFirstRootWithCompositorFrameSink() {
  for (auto& client_root : client_roots_) {
    if (ProxyWindow::GetMayBeNull(client_root->window())
            ->attached_compositor_frame_sink()) {
      return client_root.get();
    }
  }
  return nullptr;
}

bool WindowTree::IsWindowKnown(aura::Window* window) const {
  return window && known_windows_map_.count(window) > 0u;
}

Id WindowTree::TransportIdForWindow(aura::Window* window) const {
  DCHECK(IsWindowKnown(window));
  return ClientWindowIdToTransportId(ClientWindowIdForWindow(window));
}

ClientWindowId WindowTree::ClientWindowIdForWindow(aura::Window* window) const {
  auto iter = known_windows_map_.find(window);
  return iter == known_windows_map_.end() ? ClientWindowId()
                                          : iter->second.client_window_id;
}

ClientRoot* WindowTree::GetClientRootForWindow(aura::Window* window) {
  auto iter = FindClientRootWithRoot(window);
  return iter == client_roots_.end() ? nullptr : iter->get();
}

gfx::PointF WindowTree::ConvertRootLocationForClient(
    aura::Window* window,
    const gfx::PointF& root_location) {
  ClientRoot* client_root = FindClientRootContaining(window);
  // The |client_root| may have been removed on shutdown.
  if (!client_root)
    return root_location;
  gfx::PointF client_root_location = root_location;
  aura::Window::ConvertPointToTarget(
      window->GetRootWindow(), client_root->window(), &client_root_location);
  return client_root_location;
}

void WindowTree::CleanupGestureState(aura::Window* window) {
  DCHECK(IsWindowKnown(window));
  window_tree_client_->CleanupGestureState(TransportIdForWindow(window));
}

ClientRoot* WindowTree::CreateClientRoot(aura::Window* window,
                                         bool is_top_level) {
  DCHECK(window);

  // Only one client may be embedded in a window at a time.
  ProxyWindow* proxy_window =
      window_service_->GetProxyWindowForWindowCreateIfNecessary(window);
  if (proxy_window->embedded_window_tree()) {
    proxy_window->embedded_window_tree()->DeleteClientRootWithRoot(window);
    DCHECK(!proxy_window->embedded_window_tree());
  }

  // Because a new client is being embedded all existing children are removed.
  // This is because this client is no longer able to add children to |window|
  // (until the embedding is removed).
  while (!window->children().empty())
    window->RemoveChild(window->children().front());

  client_roots_.push_back(
      std::make_unique<ClientRoot>(this, window, is_top_level));
  return client_roots_.back().get();
}

void WindowTree::DeleteClientRoot(ClientRoot* client_root,
                                  DeleteClientRootReason reason) {
  aura::Window* window = client_root->window();

  ProxyWindow* proxy_window = ProxyWindow::GetMayBeNull(window);
  client_root->UnattachChildFrameSinkIdRecursive(proxy_window);
  if (proxy_window->capture_owner() == this) {
    // This client will no longer know about |window|, so it should not receive
    // any events sent to the client.
    proxy_window->SetCaptureOwner(nullptr);
  }

  // Delete the ClientRoot first, so that we don't attempt to spam the
  // client with a bunch of notifications.
  auto iter = FindClientRootWithRoot(client_root->window());
  DCHECK(iter != client_roots_.end());
  client_roots_.erase(iter);
  client_root = nullptr;  // |client_root| has been deleted.

  const Id client_window_id = TransportIdForWindow(window);

  if (reason == DeleteClientRootReason::kEmbed) {
    // This case happens when another client is embedded in the window this
    // client is embedded in. A window can have at most one client embedded in
    // it. Inform the client of this by way of OnUnembed() and OnWindowDeleted()
    // because the window is no longer known to this client.
    //
    // TODO(sky): consider simplifying this case and just deleting |this|. This
    // is because at this point the client can't do anything useful (the client
    // is unable to reattach to a Window in a display at this point).
    window_tree_client_->OnUnembed(client_window_id);
    window_tree_client_->OnWindowDeleted(client_window_id);
  }

  // This client no longer knows about |window|. Unparent any windows that
  // were created by this client and parented to windows in |window|. Recursion
  // should stop at windows created by this client because the client always
  // knows about such windows, and that never changes. Only windows created by
  // other clients may be removed from the set of known windows.
  std::vector<aura::Window*> created_windows;
  RemoveWindowFromKnownWindowsRecursive(window, &created_windows);
  for (aura::Window* created_window : created_windows) {
    if (created_window != window && created_window->parent())
      created_window->parent()->RemoveChild(created_window);
  }

  if (reason == DeleteClientRootReason::kUnembed ||
      reason == DeleteClientRootReason::kDestructor) {
    // Notify the owner of the window it no longer has a client embedded in it.
    ProxyWindow* proxy_window = ProxyWindow::GetMayBeNull(window);
    if (proxy_window->owning_window_tree() &&
        proxy_window->owning_window_tree() != this) {
      // ClientRoots always trigger creation of a ProxyWindow, so
      // |proxy_window| must exist at this point.
      DCHECK(proxy_window);
      proxy_window->owning_window_tree()
          ->window_tree_client_->OnEmbeddedAppDisconnected(
              proxy_window->owning_window_tree()->TransportIdForWindow(window));
    }
    if (proxy_window->embedding())
      proxy_window->embedding()->clear_embedded_tree();
    // Only reset the embedding if it's for an existing tree. To do otherwise
    // results in trying to delete this.
    if (proxy_window->embedding() && !proxy_window->embedding()->binding()) {
      proxy_window->SetEmbedding(nullptr);
      if (!proxy_window->owning_window_tree())
        proxy_window->Destroy();
    }
  }
}

void WindowTree::DeleteClientRootWithRoot(aura::Window* window) {
  auto iter = FindClientRootWithRoot(window);
  if (iter == client_roots_.end())
    return;

  DeleteClientRoot(iter->get(), DeleteClientRootReason::kEmbed);
}

aura::Window* WindowTree::GetWindowByClientId(const ClientWindowId& id) {
  auto iter = client_window_id_to_window_map_.find(id);
  return iter == client_window_id_to_window_map_.end() ? nullptr : iter->second;
}

bool WindowTree::IsClientCreatedWindow(aura::Window* window) {
  auto iter = known_windows_map_.find(window);
  return iter == known_windows_map_.end() ? false
                                          : iter->second.is_client_created;
}

bool WindowTree::IsClientRootWindow(aura::Window* window) {
  return window && FindClientRootWithRoot(window) != client_roots_.end();
}

ClientRoot* WindowTree::FindClientRootContaining(aura::Window* window) {
  if (!window)
    return nullptr;
  auto iter = FindClientRootWithRoot(window);
  if (iter != client_roots_.end())
    return iter->get();
  return FindClientRootContaining(window->parent());
}

WindowTree::ClientRoots::iterator WindowTree::FindClientRootWithRoot(
    aura::Window* window) {
  if (!window)
    return client_roots_.end();
  for (auto iter = client_roots_.begin(); iter != client_roots_.end(); ++iter) {
    if (iter->get()->window() == window)
      return iter;
  }
  return client_roots_.end();
}

bool WindowTree::IsWindowRootOfAnotherClient(aura::Window* window) const {
  ProxyWindow* proxy_window = ProxyWindow::GetMayBeNull(window);
  return proxy_window && proxy_window->embedded_window_tree() != nullptr &&
         proxy_window->embedded_window_tree() != this;
}

bool WindowTree::DoesAnyAncestorInterceptEvents(ProxyWindow* window) {
  if (window->embedding() && window->embedding()->embedding_tree() != this &&
      window->embedding()->embedding_tree_intercepts_events()) {
    return true;
  }
  ProxyWindow* parent = ProxyWindow::GetMayBeNull(window->window()->parent());
  return parent && DoesAnyAncestorInterceptEvents(parent);
}

void WindowTree::OnCaptureLost(aura::Window* lost_capture) {
  DCHECK(IsWindowKnown(lost_capture));
  window_tree_client_->OnCaptureChanged(kInvalidTransportId,
                                        TransportIdForWindow(lost_capture));
}

void WindowTree::OnPerformWindowMoveDone(uint32_t change_id, bool result) {
  window_moving_ = nullptr;
  window_tree_client_->OnChangeCompleted(change_id, result);
}

void WindowTree::DoPerformDragDrop(
    uint32_t change_id,
    Id source_window_id,
    const gfx::Point& screen_location,
    const base::flat_map<std::string, std::vector<uint8_t>>& drag_data,
    const gfx::ImageSkia& drag_image,
    const gfx::Vector2d& drag_image_offset,
    uint32_t drag_operation,
    ::ui::mojom::PointerKind source) {
  if (pending_drag_source_window_id_ != source_window_id) {
    // Pending drag is canceled before DoPerformDragDrop runs.
    window_tree_client_->OnPerformDragDropCompleted(change_id, false,
                                                    mojom::kDropEffectNone);
    return;
  }

  aura::Window* source_window = GetWindowByTransportId(source_window_id);
  if (!source_window) {
    DVLOG(1) << "PerformDragDrop failed (no window)";
    OnPerformDragDropDone(change_id, mojom::kDropEffectNone);
    return;
  }
  if (!IsClientCreatedWindow(source_window)) {
    DVLOG(1) << "PerformDragDrop failed (access denied)";
    OnPerformDragDropDone(change_id, mojom::kDropEffectNone);
    return;
  }

  ui::OSExchangeData data(std::make_unique<aura::OSExchangeDataProviderMus>(
      mojo::FlatMapToMap(drag_data)));
  data.provider().SetDragImage(drag_image, drag_image_offset);

  window_service_->delegate()->RunDragLoop(
      source_window, data, screen_location, drag_operation,
      source == ::ui::mojom::PointerKind::MOUSE
          ? ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE
          : ui::DragDropTypes::DRAG_EVENT_SOURCE_TOUCH,
      base::BindOnce(&WindowTree::OnPerformDragDropDone,
                     weak_factory_.GetWeakPtr(), change_id));
}

void WindowTree::OnPerformDragDropDone(uint32_t change_id, int drag_result) {
  pending_drag_source_window_id_ = kInvalidTransportId;
  window_tree_client_->OnPerformDragDropCompleted(
      change_id, drag_result != ui::DragDropTypes::DRAG_NONE, drag_result);
}

aura::Window* WindowTree::FindFirstClientCreatedWindow() {
  for (auto& pair : known_windows_map_) {
    if (pair.second.is_client_created)
      return pair.first;
  }
  return nullptr;
}

aura::Window* WindowTree::AddClientCreatedWindow(
    const ClientWindowId& id,
    bool is_top_level,
    std::unique_ptr<aura::Window> window_ptr) {
  aura::Window* window = window_ptr.get();
  ProxyWindow::Create(window, this, id, is_top_level);
  AddWindowToKnownWindows(window, id, std::move(window_ptr));
  return window;
}

void WindowTree::AddWindowToKnownWindows(
    aura::Window* window,
    const ClientWindowId& id,
    std::unique_ptr<aura::Window> owned_window) {
  DCHECK(!IsWindowKnown(window));
  KnownWindow& known_window = known_windows_map_[window];
  known_window.client_window_id = id;
  known_window.is_client_created = owned_window.get() != nullptr;
  known_window.owned_window = std::move(owned_window);

  DCHECK(IsWindowKnown(window));
  client_window_id_to_window_map_[id] = window;
  if (IsClientCreatedWindow(window))
    window->AddObserver(this);
}

void WindowTree::RemoveWindowFromKnownWindows(aura::Window* window,
                                              bool delete_if_owned) {
  DCHECK(IsWindowKnown(window));

  ProxyWindow* proxy_window = ProxyWindow::GetMayBeNull(window);
  ClientRoot* client_root = FindClientRootContaining(window);
  if (client_root)
    client_root->UnattachChildFrameSinkIdRecursive(proxy_window);

  proxy_window->set_attached_frame_sink_id(viz::FrameSinkId());

  auto iter = known_windows_map_.find(window);
  DCHECK(iter != known_windows_map_.end());
  if (iter->second.owned_window) {
    window->RemoveObserver(this);
    if (!delete_if_owned) {
      // |window| is in the process of being deleted, release() to avoid double
      // deletion.
      iter->second.owned_window.release();
    }
    iter->second.owned_window.reset();
  }
  // Sanity check to make sure deletion didn't result in removal
  DCHECK(iter == known_windows_map_.find(window));

  // Remove from these maps after destruction. This is necessary as destruction
  // may end up expecting to find a ProxyWindow.
  DCHECK(iter != known_windows_map_.end());
  client_window_id_to_window_map_.erase(iter->second.client_window_id);
  known_windows_map_.erase(iter);
}

void WindowTree::RemoveWindowFromKnownWindowsRecursive(
    aura::Window* window,
    std::vector<aura::Window*>* created_windows) {
  if (IsClientCreatedWindow(window)) {
    // Stop iterating at windows created by this client. We assume the client
    // will keep seeing any descendants.
    if (created_windows)
      created_windows->push_back(window);
    return;
  }

  if (IsWindowKnown(window)) {
    const bool delete_if_owned = true;
    RemoveWindowFromKnownWindows(window, delete_if_owned);
  }

  for (aura::Window* child : window->children())
    RemoveWindowFromKnownWindowsRecursive(child, created_windows);
}

bool WindowTree::IsValidIdForNewWindow(const ClientWindowId& id) const {
  return client_window_id_to_window_map_.count(id) == 0u &&
         base::checked_cast<ClientSpecificId>(id.client_id()) == client_id_;
}

Id WindowTree::ClientWindowIdToTransportId(
    const ClientWindowId& client_window_id) const {
  if (client_window_id.client_id() == client_id_)
    return client_window_id.sink_id();
  const Id client_id = client_window_id.client_id();
  return (client_id << 32) | client_window_id.sink_id();
}

ClientWindowId WindowTree::MakeClientWindowId(Id transport_window_id) const {
  if (!ClientIdFromTransportId(transport_window_id))
    return ClientWindowId(client_id_, transport_window_id);
  return ClientWindowId(ClientIdFromTransportId(transport_window_id),
                        ClientWindowIdFromTransportId(transport_window_id));
}

std::vector<mojom::WindowDataPtr> WindowTree::WindowsToWindowDatas(
    const std::vector<aura::Window*>& windows) {
  std::vector<mojom::WindowDataPtr> array(windows.size());
  for (size_t i = 0; i < windows.size(); ++i)
    array[i] = WindowToWindowData(windows[i]);
  return array;
}

mojom::WindowDataPtr WindowTree::WindowToWindowData(aura::Window* window) {
  aura::Window* parent = window->parent();
  aura::Window* transient_parent =
      aura::client::GetTransientWindowClient()->GetTransientParent(window);

  // If a window isn't known, it means it is not known to the client and should
  // not be sent over.
  if (!IsWindowKnown(parent))
    parent = nullptr;
  if (!IsWindowKnown(transient_parent))
    transient_parent = nullptr;
  const bool is_top_level = IsTopLevel(window);
  mojom::WindowDataPtr window_data(mojom::WindowData::New());
  window_data->parent_id =
      parent ? TransportIdForWindow(parent) : kInvalidTransportId;
  window_data->window_id =
      window ? TransportIdForWindow(window) : kInvalidTransportId;
  window_data->transient_parent_id =
      transient_parent ? TransportIdForWindow(transient_parent)
                       : kInvalidTransportId;
  window_data->bounds =
      is_top_level ? window->GetBoundsInScreen() : window->bounds();
  window_data->properties =
      window_service_->property_converter()->GetTransportProperties(window);
  window_data->visible = (!IsClientRootWindow(window) || is_top_level)
                             ? window->TargetVisibility()
                             : window->IsVisible();
  return window_data;
}

mojom::WindowTreeClientPtr
WindowTree::GetAndRemoveScheduledEmbedWindowTreeClient(
    const base::UnguessableToken& token,
    std::set<WindowTree*>* visited_trees) {
  if (visited_trees->count(this))
    return nullptr;

  auto iter = scheduled_embeds_.find(token);
  if (iter != scheduled_embeds_.end()) {
    mojom::WindowTreeClientPtr client = std::move(iter->second);
    scheduled_embeds_.erase(iter);
    return client;
  }

  visited_trees->insert(this);
  for (auto& client_root : client_roots_) {
    ProxyWindow* root_window = ProxyWindow::GetMayBeNull(client_root->window());
    DCHECK(root_window);  // There should always be a ProxyWindow for a root.
    WindowTree* owning_tree = root_window->owning_window_tree();
    if (owning_tree) {
      auto result = owning_tree->GetAndRemoveScheduledEmbedWindowTreeClient(
          token, visited_trees);
      if (result)
        return result;
    }
  }
  return nullptr;
}

void WindowTree::SendTopmostWindows(
    const std::vector<aura::Window*>& topmosts) {
  DCHECK_NE(connection_type_, ConnectionType::kEmbedding);
  std::vector<Id> topmost_ids;
  for (auto* window : topmosts) {
    topmost_ids.push_back(IsWindowKnown(window) ? TransportIdForWindow(window)
                                                : kInvalidTransportId);
  }
  window_tree_client_->OnTopmostWindowChanged(topmost_ids);
}

void WindowTree::SendOcclusionStates(const std::set<aura::Window*>& windows) {
  base::flat_map<ws::Id, ws::mojom::OcclusionState> occlusion_changes;
  for (auto* window : windows) {
    DCHECK(IsWindowKnown(window));

    // TODO(crbug.com/900568): Send occluded region.
    occlusion_changes[TransportIdForWindow(window)] =
        aura::WindowOcclusionStateToMojom(window->occlusion_state());
  }
  window_tree_client_->OnOcclusionStatesChanged(occlusion_changes);
}

void WindowTree::OnWindowTreeHostsSwappedDisplays(
    aura::Window* new_primary_root,
    aura::Window* old_primary_root) {
  DCHECK(new_primary_root->IsRootWindow() && old_primary_root->IsRootWindow());
  for (auto& client_root : client_roots_) {
    aura::Window* root_window = client_root->window()->GetRootWindow();
    if (root_window != new_primary_root && root_window != old_primary_root)
      continue;

    client_root->NotifyClientOfDisplayIdChange();
  }
}

bool WindowTree::NewWindowImpl(
    const ClientWindowId& client_window_id,
    const std::map<std::string, std::vector<uint8_t>>& properties) {
  DVLOG(3) << "new window client=" << client_id_
           << " window_id=" << client_window_id.ToString();
  if (!IsValidIdForNewWindow(client_window_id)) {
    DVLOG(1) << "NewWindow failed (id is not valid for client)";
    return false;
  }
  const bool is_top_level = false;
  // WindowDelegateImpl deletes itself when |window| is destroyed.
  WindowDelegateImpl* window_delegate = new WindowDelegateImpl();
  std::unique_ptr<aura::Window> window_ptr = std::make_unique<aura::Window>(
      window_delegate, aura::client::WINDOW_TYPE_UNKNOWN,
      window_service_->env());
  window_delegate->set_window(window_ptr.get());
  aura::Window* window = AddClientCreatedWindow(client_window_id, is_top_level,
                                                std::move(window_ptr));

  SetWindowType(window, aura::GetWindowTypeFromProperties(properties));
  for (auto& pair : properties) {
    window_service_->property_converter()->SetPropertyFromTransportValue(
        window, pair.first, &pair.second);
  }
  window->Init(ui::LAYER_NOT_DRAWN);
  // Windows created by the client should only be destroyed by the client.
  window->set_owned_by_parent(false);
  return true;
}

bool WindowTree::DeleteWindowImpl(const ClientWindowId& window_id) {
  aura::Window* window = GetWindowByClientId(window_id);
  DVLOG(3) << "deleting window client=" << client_id_
           << " client window_id=" << window_id.ToString();
  if (!window) {
    DVLOG(1) << "DeleteWindow: no window, returning true anyway";
    // Even though there is no window, return true. This way, if both sides
    // try to delete the window at the same time, there is no race. Deletion
    // at the same should generally only happen for embed roots, but shutdown
    // paths (in Ash) may also trigger deletion.
    return true;
  }

  const bool is_client_created_window = IsClientCreatedWindow(window);
  auto iter = FindClientRootWithRoot(window);
  if (iter != client_roots_.end()) {
    DeleteClientRoot(iter->get(), DeleteClientRootReason::kUnembed);
    if (!is_client_created_window)
      return true;
    // If client created, fall through to delete window.
  } else if (!is_client_created_window) {
    DVLOG(1) << "DeleteWindow failed (client did not create window)";
    return false;
  }

  const bool delete_if_owned = true;
  RemoveWindowFromKnownWindows(window, delete_if_owned);
  return true;
}

bool WindowTree::SetCaptureImpl(const ClientWindowId& window_id) {
  DVLOG(3) << "SetCapture window_id=" << window_id;
  aura::Window* window = GetWindowByClientId(window_id);
  if (!window) {
    DVLOG(1) << "SetCapture failed (no window)";
    return false;
  }

  if ((!IsClientCreatedWindow(window) && !IsClientRootWindow(window)) ||
      !window->IsVisible() || !window->GetRootWindow()) {
    DVLOG(1) << "SetCapture failed (access denied or invalid window)";
    return false;
  }

  ProxyWindow* proxy_window = ProxyWindow::GetMayBeNull(window);

  if (DoesAnyAncestorInterceptEvents(proxy_window)) {
    // If an ancestor is intercepting events, than the descendants are not
    // allowed to set capture. This is primarily to prevent renderers from
    // setting capture.
    DVLOG(1) << "SetCapture failed (ancestor intercepts events)";
    return false;
  }

  wm::CaptureController* capture_controller = wm::CaptureController::Get();
  DCHECK(capture_controller);

  if (capture_controller->GetCaptureWindow() == window) {
    if (proxy_window->capture_owner() != this) {
      // The capture window didn't change, but the client that owns capture
      // changed (see |ProxyWindow::capture_owner_| for details on this).
      // Notify the current owner that it lost capture.
      if (proxy_window->capture_owner())
        proxy_window->capture_owner()->OnCaptureLost(window);
      proxy_window->SetCaptureOwner(this);
    }
    return true;
  }

  ClientChange change(property_change_tracker_.get(), window,
                      ClientChangeType::kCapture);
  proxy_window->SetCaptureOwner(this);
  capture_controller->SetCapture(window);
  return capture_controller->GetCaptureWindow() == window;
}

bool WindowTree::ReleaseCaptureImpl(const ClientWindowId& window_id) {
  DVLOG(3) << "ReleaseCapture window_id=" << window_id;
  aura::Window* window = GetWindowByClientId(window_id);
  if (!window) {
    DVLOG(1) << "ReleaseCapture failed (no window)";
    return false;
  }

  if (!IsClientCreatedWindow(window) && !IsClientRootWindow(window)) {
    DVLOG(1) << "ReleaseCapture failed (access denied)";
    return false;
  }

  wm::CaptureController* capture_controller = wm::CaptureController::Get();
  DCHECK(capture_controller);

  if (!capture_controller->GetCaptureWindow())
    return true;  // Capture window is already null.

  if (capture_controller->GetCaptureWindow() != window) {
    DVLOG(1) << "ReleaseCapture failed (supplied window does not have capture)";
    return false;
  }

  ProxyWindow* proxy_window = ProxyWindow::GetMayBeNull(window);
  if (proxy_window->capture_owner() && proxy_window->capture_owner() != this) {
    // This client is trying to release capture, but it doesn't own capture.
    DVLOG(1) << "ReleaseCapture failed (client did not request capture)";
    return false;
  }
  proxy_window->SetCaptureOwner(nullptr);

  ClientChange change(property_change_tracker_.get(), window,
                      ClientChangeType::kCapture);
  capture_controller->ReleaseCapture(window);
  return capture_controller->GetCaptureWindow() != window;
}

bool WindowTree::AddWindowImpl(const ClientWindowId& parent_id,
                               const ClientWindowId& child_id) {
  aura::Window* parent = GetWindowByClientId(parent_id);
  aura::Window* child = GetWindowByClientId(child_id);
  DVLOG(3) << "add window client=" << client_id_
           << " client parent window_id=" << parent_id.ToString()
           << " client child window_id=" << child_id.ToString();
  if (!parent) {
    DVLOG(1) << "AddWindow failed (no parent)";
    return false;
  }
  if (!child) {
    DVLOG(1) << "AddWindow failed (no child)";
    return false;
  }
  if (child->parent() == parent) {
    DVLOG(1) << "AddWindow failed (already has parent)";
    return false;
  }
  if (child->Contains(parent)) {
    DVLOG(1) << "AddWindow failed (child contains parent)";
    return false;
  }
  if (IsClientCreatedWindow(child) && !IsTopLevel(child) &&
      (IsClientRootWindow(parent) || (IsClientCreatedWindow(parent) &&
                                      !IsWindowRootOfAnotherClient(parent)))) {
    parent->AddChild(child);
    return true;
  }
  DVLOG(1) << "AddWindow failed (access denied)";
  return false;
}

bool WindowTree::RemoveWindowFromParentImpl(
    const ClientWindowId& client_window_id) {
  aura::Window* window = GetWindowByClientId(client_window_id);
  DVLOG(3) << "removing window from parent client=" << client_id_
           << " client window_id=" << client_window_id;
  if (!window) {
    DVLOG(1) << "RemoveWindowFromParent failed (invalid window id="
             << client_window_id.ToString() << ")";
    return false;
  }
  if (!window->parent()) {
    DVLOG(1) << "RemoveWindowFromParent failed (no parent id="
             << client_window_id.ToString() << ")";
    return false;
  }
  if (IsClientCreatedWindow(window) && !IsClientRootWindow(window)) {
    window->parent()->RemoveChild(window);
    return true;
  }
  DVLOG(1) << "RemoveWindowFromParent failed (access policy disallowed id="
           << client_window_id.ToString() << ")";
  return false;
}

bool WindowTree::AddTransientWindowImpl(const ClientWindowId& parent_id,
                                        const ClientWindowId& transient_id) {
  DVLOG(3) << "adding transient window client=" << client_id_
           << " parent_id=" << parent_id << " transient_id=" << transient_id;
  aura::Window* parent = GetWindowByClientId(parent_id);
  aura::Window* transient = GetWindowByClientId(transient_id);
  if (!parent || !transient) {
    DVLOG(1) << "AddTransientWindow failed (invalid window parent_id="
             << parent_id << " transient_id=" << transient_id << ")";
    return false;
  }

  if (parent->Contains(transient)) {
    DVLOG(1) << "AddTransientWindow failed (parent contains transient"
             << " parent_id=" << parent_id << " transient_id=" << transient_id
             << ")";
    return false;
  }

  if (!IsClientCreatedWindow(parent) || !IsClientCreatedWindow(transient)) {
    DVLOG(1) << "SetModalType failed (access policy disallowed parent_id="
             << parent_id << " transient_id=" << transient_id << ")";
    return false;
  }

  ::wm::AddTransientChild(parent, transient);
  return true;
}

bool WindowTree::RemoveTransientWindowFromParentImpl(
    const ClientWindowId& transient_id) {
  DVLOG(3) << "removing transient window from parent client=" << client_id_
           << " transient_id=" << transient_id;
  aura::Window* transient = GetWindowByClientId(transient_id);
  aura::Window* parent = ::wm::GetTransientParent(transient);
  if (!parent || !transient) {
    DVLOG(1) << "AddTransientWindow failed (invalid window or no transient"
             << " parent transient_id=" << transient_id << ")";
    return false;
  }

  if (!IsClientCreatedWindow(parent) || !IsClientCreatedWindow(transient)) {
    DVLOG(1) << "SetModalType failed (access policy disallowed transient_id="
             << transient_id << ")";
    return false;
  }

  ::wm::RemoveTransientChild(parent, transient);
  return true;
}

bool WindowTree::SetModalTypeImpl(const ClientWindowId& client_window_id,
                                  ui::ModalType type) {
  DVLOG(3) << "setting window modal type client=" << client_id_
           << " client_window_id=" << client_window_id << " type=" << type;
  aura::Window* window = GetWindowByClientId(client_window_id);
  if (!window) {
    DVLOG(1) << "SetModalType failed (invalid window id="
             << client_window_id.ToString() << ")";
    return false;
  }

  if (!IsClientRootWindow(window) && type == ui::MODAL_TYPE_SYSTEM) {
    DVLOG(1) << "SetModalType failed (not allowed for embedded clients)";
    return false;
  }

  if (type == ui::MODAL_TYPE_SYSTEM &&
      window->type() != aura::client::WINDOW_TYPE_NORMAL &&
      window->type() != aura::client::WINDOW_TYPE_POPUP) {
    DVLOG(1) << "Window type cannot be made system modal: " << window->type();
    return false;
  }

  if (!IsClientCreatedWindow(window)) {
    DVLOG(1) << "SetModalType failed (access policy disallowed id="
             << client_window_id.ToString() << ")";
    return false;
  }

  window_service_->delegate()->SetModalType(window, type);
  return true;
}

bool WindowTree::SetWindowVisibilityImpl(const ClientWindowId& window_id,
                                         bool visible) {
  aura::Window* window = GetWindowByClientId(window_id);
  DVLOG(3) << "SetWindowVisibility client=" << client_id_
           << " client window_id=" << window_id.ToString();
  if (!window) {
    DVLOG(1) << "SetWindowVisibility failed (no window)";
    return false;
  }
  if (IsClientCreatedWindow(window) ||
      (IsClientRootWindow(window) && can_change_root_window_visibility_)) {
    if (window->TargetVisibility() == visible)
      return true;
    ClientChange change(property_change_tracker_.get(), window,
                        ClientChangeType::kVisibility);
    if (visible)
      window->Show();
    else
      window->Hide();
    // Return true only if the change actually took. It's entirely possible an
    // observer may effectively revert the change.
    return window->TargetVisibility() == visible;
  }
  DVLOG(1) << "SetWindowVisibility failed (access policy denied change)";
  return false;
}

bool WindowTree::SetWindowPropertyImpl(
    const ClientWindowId& window_id,
    const std::string& name,
    const base::Optional<std::vector<uint8_t>>& value) {
  aura::Window* window = GetWindowByClientId(window_id);
  DVLOG(3) << "SetWindowProperty client=" << client_id_
           << " client window_id=" << window_id.ToString()
           << " property=" << name;
  if (!window) {
    DVLOG(1) << "SetWindowProperty failed (no window)";
    return false;
  }
  aura::PropertyConverter* property_converter =
      window_service_->property_converter();
  if (!property_converter->IsTransportNameRegistered(name)) {
    NOTREACHED() << "Attempting to set an unregistered property; this is not "
                    "implemented. property name="
                 << name;
    return false;
  }
  if (!IsClientCreatedWindow(window) && !IsClientRootWindow(window)) {
    DVLOG(1) << "SetWindowProperty failed (access policy denied change)";
    return false;
  }

  ClientChange change(
      property_change_tracker_.get(), window, ClientChangeType::kProperty,
      property_converter->GetPropertyKeyFromTransportName(name));

  // Special handle the property whose value is a pointer to aura::Window since
  // property converter can't convert the transported value.
  const aura::WindowProperty<aura::Window*>* property =
      property_converter->GetWindowPtrProperty(name);
  if (property) {
    aura::Window* prop_window = nullptr;
    if (value.has_value())
      prop_window = GetWindowByTransportId(mojo::ConvertTo<Id>(value.value()));
    window->SetProperty(property, prop_window);
    return true;
  }

  std::unique_ptr<std::vector<uint8_t>> data;
  if (value.has_value())
    data = std::make_unique<std::vector<uint8_t>>(value.value());
  property_converter->SetPropertyFromTransportValue(window, name, data.get());
  return true;
}

bool WindowTree::EmbedImpl(const ClientWindowId& window_id,
                           mojom::WindowTreeClientPtr window_tree_client_ptr,
                           mojom::WindowTreeClient* window_tree_client,
                           uint32_t flags) {
  DVLOG(3) << "Embed window_id=" << window_id;
  aura::Window* window = GetWindowByClientId(window_id);
  if (!window) {
    DVLOG(1) << "Embed failed (no window)";
    return false;
  }
  if (!IsClientCreatedWindow(window) || IsTopLevel(window)) {
    DVLOG(1) << "Embed failed (access denied)";
    return false;
  }

  const bool owner_intercept_events =
      (connection_type_ != ConnectionType::kEmbedding &&
       (flags & mojom::kEmbedFlagEmbedderInterceptsEvents) != 0);
  std::unique_ptr<Embedding> embedding =
      std::make_unique<Embedding>(this, window, owner_intercept_events);
  embedding->Init(window_service_, std::move(window_tree_client_ptr),
                  window_tree_client,
                  base::BindOnce(&WindowTree::OnEmbeddedClientConnectionLost,
                                 base::Unretained(this), embedding.get()));
  if (flags & mojom::kEmbedFlagEmbedderControlsVisibility)
    embedding->embedded_tree()->can_change_root_window_visibility_ = false;
  ProxyWindow* proxy_window = ProxyWindow::GetMayBeNull(window);
  proxy_window->SetEmbedding(std::move(embedding));
  window_tree_client_->OnFrameSinkIdAllocated(
      ClientWindowIdToTransportId(window_id), proxy_window->frame_sink_id());
  return true;
}

bool WindowTree::SetWindowOpacityImpl(const ClientWindowId& window_id,
                                      float opacity) {
  aura::Window* window = GetWindowByClientId(window_id);
  DVLOG(3) << "SetWindowOpacity client=" << client_id_
           << " client window_id=" << window_id.ToString();
  if (IsClientCreatedWindow(window) ||
      (IsClientRootWindow(window) && can_change_root_window_visibility_)) {
    if (window->layer()->opacity() == opacity)
      return true;
    window->layer()->SetOpacity(opacity);
    return true;
  }
  DVLOG(1) << "SetWindowOpacity failed (invalid window or access denied)";
  return false;
}

bool WindowTree::SetWindowBoundsImpl(
    const ClientWindowId& window_id,
    const gfx::Rect& bounds,
    const base::Optional<viz::LocalSurfaceIdAllocation>&
        local_surface_id_allocation) {
  aura::Window* window = GetWindowByClientId(window_id);

  DVLOG(3) << "SetWindowBounds window_id=" << window_id
           << " bounds=" << bounds.ToString() << " local_surface_id="
           << (local_surface_id_allocation
                   ? local_surface_id_allocation->ToString()
                   : "null");

  if (!window) {
    DVLOG(1) << "SetWindowBounds failed (invalid window id)";
    return false;
  }

  // Only the owner of the window can change the bounds.
  if (!IsClientCreatedWindow(window)) {
    DVLOG(1) << "SetWindowBounds failed (access denied)";
    return false;
  }

  ProxyWindow* proxy_window = ProxyWindow::GetMayBeNull(window);
  DCHECK(proxy_window);  // Earlier checks mean this should be true.
  const bool local_surface_id_changed =
      proxy_window->local_surface_id_allocation() !=
      local_surface_id_allocation;

  const gfx::Rect original_bounds =
      IsTopLevel(window) ? window->GetBoundsInScreen() : window->bounds();

  if (original_bounds == bounds && !local_surface_id_changed)
    return true;

  ClientChange change(property_change_tracker_.get(), window,
                      ClientChangeType::kBounds);

  ClientRoot* client_root = GetClientRootForWindow(window);
  if (IsTopLevel(window)) {
    // If IsTopLevel() returns true, there should be a ClientRoot.
    DCHECK(client_root);
    if (local_surface_id_allocation &&
        local_surface_id_allocation->local_surface_id().embed_token() !=
            proxy_window->local_surface_id_allocation()
                ->local_surface_id()
                .embed_token()) {
      DVLOG(1) << "SetWindowBounds failed (embed token changed)";
      return false;
    }
    return client_root->SetBoundsInScreenFromClient(
        bounds, local_surface_id_allocation);
  }
  proxy_window->set_local_surface_id_allocation(local_surface_id_allocation);
  window->SetBounds(bounds);

  if (!change.window())
    return true;  // Return value doesn't matter if window destroyed.

  if (window->bounds() == original_bounds) {
    if (local_surface_id_changed) {
      // If the bounds didn't change, but the LocalSurfaceId did, then the
      // LocalSurfaceId needs to be propagated to any embeddings.
      if (proxy_window->HasEmbedding() &&
          proxy_window->embedding()->embedding_tree() == this) {
        WindowTree* embedded_tree = proxy_window->embedding()->embedded_tree();
        ClientRoot* embedded_client_root =
            embedded_tree->GetClientRootForWindow(window);
        DCHECK(embedded_client_root);
        embedded_client_root->OnLocalSurfaceIdChanged();
      }
    }
    return (bounds == original_bounds);
  }

  if (window->bounds() == bounds &&
      proxy_window->local_surface_id_allocation() ==
          local_surface_id_allocation) {
    return true;
  }

  // The window's bounds changed, but not to the value the client requested.
  // Tell the client the new value, and return false, which triggers the client
  // to use the value supplied to OnWindowBoundsChanged().
  window_tree_client_->OnWindowBoundsChanged(TransportIdForWindow(window),
                                             window->bounds(),
                                             local_surface_id_allocation);
  return false;
}

bool WindowTree::SetWindowTransformImpl(const ClientWindowId& window_id,
                                        const gfx::Transform& transform) {
  DVLOG(3) << "SetWindowTransform window_id=" << window_id;
  aura::Window* window = GetWindowByClientId(window_id);
  // This doesn't allow setting the transform on top-levels as that may conflict
  // with top-level animations done by the window-manager. Additionally the
  // window-manager is really the one that should be animating top-levels.
  if (!window || !IsClientCreatedWindow(window) || IsTopLevel(window)) {
    DVLOG(1) << "SetWindowTransform failed (invalid window)";
    return false;
  }
  window->SetTransform(transform);
  return true;
}

bool WindowTree::ReorderWindowImpl(const ClientWindowId& window_id,
                                   const ClientWindowId& relative_window_id,
                                   mojom::OrderDirection direction) {
  DVLOG(3) << "ReorderWindow window_id=" << window_id
           << " relative_window_id=" << relative_window_id;
  aura::Window* window = GetWindowByClientId(window_id);
  aura::Window* relative_window = GetWindowByClientId(relative_window_id);
  // Only allow reordering of windows the client created, and windows that are
  // siblings.
  if (!IsClientCreatedWindow(window) ||
      !IsClientCreatedWindow(relative_window) ||
      window->parent() != relative_window->parent() || !window->parent() ||
      !IsClientCreatedWindow(window->parent())) {
    DVLOG(1) << "ReorderWindow failed (invalid windows)";
    return false;
  }
  if (direction == mojom::OrderDirection::ABOVE)
    window->parent()->StackChildAbove(window, relative_window);
  else
    window->parent()->StackChildBelow(window, relative_window);
  return true;
}

std::vector<aura::Window*> WindowTree::GetWindowTreeImpl(
    const ClientWindowId& window_id) {
  aura::Window* window = GetWindowByClientId(window_id);
  std::vector<aura::Window*> results;
  GetWindowTreeRecursive(window, &results);
  return results;
}

bool WindowTree::SetFocusImpl(const ClientWindowId& window_id) {
  DVLOG(3) << "SetFocus window_id=" << window_id;
  // FocusHandler deals with a null window.
  return focus_handler_.SetFocus(GetWindowByClientId(window_id));
}

bool WindowTree::SetCursorImpl(const ClientWindowId& window_id,
                               ui::Cursor cursor) {
  aura::Window* window = GetWindowByClientId(window_id);
  if (!window) {
    DVLOG(1) << "SetCursor failed (no window)";
    return false;
  }
  if (!IsClientCreatedWindow(window) && !IsClientRootWindow(window)) {
    DVLOG(1) << "SetCursor failed (access denied)";
    return false;
  }

  auto* proxy_window = ProxyWindow::GetMayBeNull(window);

#if defined(USE_OZONE)
  auto* factory = ui::CursorFactoryOzone::GetInstance();
  if (cursor.native_type() != ui::CursorType::kCustom) {
    cursor.SetPlatformCursor(factory->GetDefaultCursor(cursor.native_type()));
  } else {
    cursor.SetPlatformCursor(factory->CreateImageCursor(
        cursor.GetBitmap(), cursor.GetHotspot(), cursor.device_scale_factor()));
    cursor.UnrefCustomCursor();
  }
#else
  NOTIMPLEMENTED();
#endif

  // Ask our delegate to set the cursor. This will save the cursor for toplevels
  // and also update the active cursor if appropriate (i.e. if |window| is the
  // last to have set the cursor/is currently hovered).
  if (!window_service_->delegate()->StoreAndSetCursor(window, cursor)) {
    // Store the cursor on ProxyWindow. This will later be accessed by the
    // WindowDelegate for non-toplevels, i.e. WindowDelegateImpl.
    proxy_window->StoreCursor(cursor);
  }

  return true;
}

bool WindowTree::StackAboveImpl(const ClientWindowId& above_window_id,
                                const ClientWindowId& below_window_id) {
  DVLOG(3) << "StackAbove above_window_id=" << above_window_id
           << " below_window_id=" << below_window_id;
  aura::Window* above_window = GetWindowByClientId(above_window_id);
  aura::Window* below_window = GetWindowByClientId(below_window_id);
  // This function only applies to top-levels.
  if (!IsClientCreatedWindow(above_window) ||
      !IsClientCreatedWindow(below_window) || !IsTopLevel(above_window) ||
      !IsTopLevel(below_window) || !above_window->parent() ||
      above_window->parent() != below_window->parent()) {
    DVLOG(1) << "StackAbove failed (invalid windows)";
    return false;
  }
  above_window->parent()->StackChildAbove(above_window, below_window);
  return true;
}

bool WindowTree::StackAtTopImpl(const ClientWindowId& window_id) {
  DVLOG(3) << "StackAtTop window_id=" << window_id;

  aura::Window* window = GetWindowByClientId(window_id);
  if (!window || !IsTopLevel(window)) {
    DVLOG(1) << "StackAtTop failed (invalid id, or invalid window)";
    return false;
  }

  if (window->parent())
    window->parent()->StackChildAtTop(window);
  return true;
}

void WindowTree::GetWindowTreeRecursive(aura::Window* window,
                                        std::vector<aura::Window*>* windows) {
  if (!IsWindowKnown(window))
    return;

  windows->push_back(window);
  for (aura::Window* child : window->children())
    GetWindowTreeRecursive(child, windows);
}

void WindowTree::OnEmbeddedClientConnectionLost(Embedding* embedding) {
  ProxyWindow::GetMayBeNull(embedding->window())->SetEmbedding(nullptr);
}

void WindowTree::OnWindowHierarchyChanging(
    const HierarchyChangeParams& params) {
  if (params.target != params.receiver || !IsClientCreatedWindow(params.target))
    return;

  ProxyWindow* proxy_window = ProxyWindow::GetMayBeNull(params.target);
  DCHECK(proxy_window);  // non-null because of IsClientCreatedWindow() check.
  ClientRoot* old_root = FindClientRootContaining(params.old_parent);
  ClientRoot* new_root = FindClientRootContaining(params.new_parent);
  if (old_root == new_root)
    return;

  if (old_root)
    old_root->UnattachChildFrameSinkIdRecursive(proxy_window);
  if (new_root)
    new_root->AttachChildFrameSinkIdRecursive(proxy_window);
}

void WindowTree::OnWindowDestroyed(aura::Window* window) {
  DCHECK(IsWindowKnown(window));

  // WARNING: this function is not necessarily called. In particular it isn't
  // called when the client requests the window to be deleted, or from the
  // destructor.

  auto iter = FindClientRootWithRoot(window);
  if (iter != client_roots_.end())
    DeleteClientRoot(iter->get(), WindowTree::DeleteClientRootReason::kDeleted);

  DCHECK(IsWindowKnown(window));
  window_tree_client_->OnWindowDeleted(TransportIdForWindow(window));

  const bool delete_if_owned = false;
  RemoveWindowFromKnownWindows(window, delete_if_owned);
}

void WindowTree::OnWindowVisibilityChanging(aura::Window* window,
                                            bool visible) {
  if (property_change_tracker_->IsProcessingChangeForWindow(
          window, ClientChangeType::kVisibility)) {
    return;
  }
  window_tree_client_->OnWindowVisibilityChanged(TransportIdForWindow(window),
                                                 visible);
}

void WindowTree::OnCaptureChanged(aura::Window* lost_capture,
                                  aura::Window* gained_capture) {
  if (property_change_tracker_->IsProcessingChangeForWindow(
          lost_capture, ClientChangeType::kCapture) ||
      property_change_tracker_->IsProcessingChangeForWindow(
          gained_capture, ClientChangeType::kCapture)) {
    // The client initiated the change, don't notify the client.
    return;
  }

  // Assume the environment the WindowService is running in is not requesting
  // capture on windows created by clients. With this assumption, the only time
  // the client needs to be notified is if the client had set capture on one of
  // its windows, and capture changed. This might happen if the window is no
  // longer valid for capture, or the local environment requests capture on
  // another window.
  if (lost_capture && (IsClientCreatedWindow(lost_capture) ||
                       IsClientRootWindow(lost_capture))) {
    ProxyWindow* proxy_window = ProxyWindow::GetMayBeNull(lost_capture);
    if (proxy_window->capture_owner() == this) {
      // One of the windows known to this client had capture. Notify the client
      // of the change. If the client does not know about the window that gained
      // capture, an invalid window id is used.
      proxy_window->SetCaptureOwner(nullptr);
      const Id gained_capture_id = gained_capture &&
                                           IsWindowKnown(gained_capture) &&
                                           !IsClientRootWindow(gained_capture)
                                       ? TransportIdForWindow(gained_capture)
                                       : kInvalidTransportId;
      window_tree_client_->OnCaptureChanged(gained_capture_id,
                                            TransportIdForWindow(lost_capture));
    }
  }
}

void WindowTree::NewWindow(
    uint32_t change_id,
    Id transport_window_id,
    const base::Optional<base::flat_map<std::string, std::vector<uint8_t>>>&
        transport_properties) {
  std::map<std::string, std::vector<uint8_t>> properties;
  if (transport_properties.has_value())
    properties = mojo::FlatMapToMap(transport_properties.value());
  window_tree_client_->OnChangeCompleted(
      change_id,
      NewWindowImpl(MakeClientWindowId(transport_window_id), properties));
}

void WindowTree::NewTopLevelWindow(
    uint32_t change_id,
    Id transport_window_id,
    const base::flat_map<std::string, std::vector<uint8_t>>& properties) {
  const ClientWindowId client_window_id =
      MakeClientWindowId(transport_window_id);
  DVLOG(3) << "NewTopLevelWindow client_window_id="
           << client_window_id.ToString();
  if (!IsValidIdForNewWindow(client_window_id)) {
    DVLOG(1) << "NewTopLevelWindow failed (invalid window id)";
    window_tree_client_->OnChangeCompleted(change_id, false);
    return;
  }
  if (connection_type_ == ConnectionType::kEmbedding) {
    // This is done to disallow clients such as renderers from creating
    // top-level windows.
    DVLOG(1) << "NewTopLevelWindow failed (access denied)";
    window_tree_client_->OnChangeCompleted(change_id, false);
    return;
  }
  std::unique_ptr<TopLevelProxyWindowImpl> top_level_proxy_window =
      std::make_unique<TopLevelProxyWindowImpl>(window_tree_client_,
                                                transport_window_id);
  std::unique_ptr<aura::Window> top_level_ptr =
      window_service_->delegate()->NewTopLevel(
          top_level_proxy_window.get(), window_service_->property_converter(),
          properties);
  if (!top_level_ptr) {
    DVLOG(1) << "NewTopLevelWindow failed (delegate window creation failed)";
    window_tree_client_->OnChangeCompleted(change_id, false);
    return;
  }
  top_level_ptr->set_owned_by_parent(false);
  const bool is_top_level = true;
  aura::Window* top_level = AddClientCreatedWindow(
      client_window_id, is_top_level, std::move(top_level_ptr));
  ProxyWindow* proxy_window = ProxyWindow::GetMayBeNull(top_level);
  proxy_window->SetTopLevelProxyWindow(std::move(top_level_proxy_window));
  proxy_window->set_frame_sink_id(client_window_id);
  const int64_t display_id =
      display::Screen::GetScreen()->GetDisplayNearestWindow(top_level).id();
  // This passes null for the mojom::WindowTreePtr because the client has
  // already been given the mojom::WindowTreePtr that is backed by this
  // WindowTree.
  CreateClientRoot(top_level, is_top_level)->RegisterVizEmbeddingSupport();
  // Creating the ClientRoot should trigger setting a LocalSurfaceIdAllocation.
  DCHECK(proxy_window->local_surface_id_allocation());
  window_tree_client_->OnTopLevelCreated(
      change_id, WindowToWindowData(top_level), display_id,
      top_level->IsVisible(), *(proxy_window->local_surface_id_allocation()));
}

void WindowTree::DeleteWindow(uint32_t change_id, Id transport_window_id) {
  window_tree_client_->OnChangeCompleted(
      change_id, DeleteWindowImpl(MakeClientWindowId(transport_window_id)));
}

void WindowTree::SetCapture(uint32_t change_id, Id transport_window_id) {
  window_tree_client_->OnChangeCompleted(
      change_id, SetCaptureImpl(MakeClientWindowId(transport_window_id)));
}

void WindowTree::ReleaseCapture(uint32_t change_id, Id transport_window_id) {
  window_tree_client_->OnChangeCompleted(
      change_id, ReleaseCaptureImpl(MakeClientWindowId(transport_window_id)));
}

void WindowTree::ObserveEventTypes(
    const std::vector<ui::mojom::EventType>& types) {
  if (types.empty()) {
    event_observer_helper_.reset();
  } else {
    if (!event_observer_helper_)
      event_observer_helper_ = std::make_unique<EventObserverHelper>(this);
    std::set<ui::EventType> event_types;
    for (auto type : types)
      event_types.insert(mojo::ConvertTo<ui::EventType>(type));
    event_observer_helper_->set_types(event_types);
  }
}

void WindowTree::SetWindowBounds(
    uint32_t change_id,
    Id window_id,
    const gfx::Rect& bounds,
    const base::Optional<viz::LocalSurfaceIdAllocation>&
        local_surface_id_allocation) {
  window_tree_client_->OnChangeCompleted(
      change_id, SetWindowBoundsImpl(MakeClientWindowId(window_id), bounds,
                                     local_surface_id_allocation));
}

void WindowTree::UpdateLocalSurfaceIdFromChild(
    Id transport_window_id,
    const viz::LocalSurfaceIdAllocation& local_surface_id_allocation) {
  const ClientWindowId window_id = MakeClientWindowId(transport_window_id);
  aura::Window* window = GetWindowByClientId(window_id);

  DVLOG(3) << "UpdateLocalSurfaceIdFromChild window_id=" << window_id
           << " local_surface_id=" << local_surface_id_allocation.ToString();

  ClientRoot* client_root = GetClientRootForWindow(window);
  if (!client_root || !client_root->ShouldAssignLocalSurfaceId()) {
    DVLOG(1) << "UpdateLocalSurfaceIdFromChild failed (invalid window id)";
    return;
  }

  ProxyWindow* proxy_window = ProxyWindow::GetMayBeNull(window);
  DCHECK(window);  // Earlier checks ensure this is non-null.
  if (local_surface_id_allocation.local_surface_id().embed_token() !=
      proxy_window->local_surface_id_allocation()
          ->local_surface_id()
          .embed_token()) {
    DVLOG(1) << "UpdateLocalSurfaceIdFromChild failed (embed token changed)";
    return;
  }
  client_root->UpdateLocalSurfaceIdFromChild(local_surface_id_allocation);
}

void WindowTree::AllocateLocalSurfaceId(Id transport_window_id) {
  const ClientWindowId window_id = MakeClientWindowId(transport_window_id);
  aura::Window* window = GetWindowByClientId(window_id);
  DVLOG(3) << "AllocateLocalSurfaceId client window_id="
           << window_id.ToString();
  if (!window || !IsTopLevel(window)) {
    DVLOG(1) << "AllocateLocalSurfaceId failed (invalid window id)";
    return;
  }
  ClientRoot* client_root = GetClientRootForWindow(window);
  DCHECK(client_root);
  client_root->AllocateLocalSurfaceIdAndNotifyClient();
}

void WindowTree::SetWindowTransform(uint32_t change_id,
                                    Id transport_window_id,
                                    const gfx::Transform& transform) {
  window_tree_client_->OnChangeCompleted(
      change_id, SetWindowTransformImpl(MakeClientWindowId(transport_window_id),
                                        transform));
}

void WindowTree::SetClientArea(
    Id transport_window_id,
    const gfx::Insets& insets,
    const base::Optional<std::vector<gfx::Rect>>& additional_client_areas) {
  const ClientWindowId window_id = MakeClientWindowId(transport_window_id);
  aura::Window* window = GetWindowByClientId(window_id);
  DVLOG(3) << "SetClientArea client window_id=" << window_id.ToString()
           << " insets=" << insets.ToString();
  if (!window) {
    DVLOG(1) << "SetClientArea failed (invalid window id)";
    return;
  }
  if (!IsClientRootWindow(window) || !IsTopLevel(window)) {
    DVLOG(1) << "SetClientArea failed (access denied)";
    return;
  }

  ProxyWindow* proxy_window = ProxyWindow::GetMayBeNull(window);
  DCHECK(proxy_window);  // Must exist because of preceding conditionals.
  proxy_window->SetClientArea(
      insets, additional_client_areas.value_or(std::vector<gfx::Rect>()));
}

void WindowTree::SetHitTestInsets(Id transport_window_id,
                                  const gfx::Insets& mouse,
                                  const gfx::Insets& touch) {
  const ClientWindowId window_id = MakeClientWindowId(transport_window_id);
  aura::Window* window = GetWindowByClientId(window_id);
  DVLOG(3) << "SetHitTestInsets client window_id=" << window_id.ToString()
           << " mouse=" << mouse.ToString() << " touch=" << touch.ToString();
  if (!window) {
    DVLOG(1) << "SetHitTestInsets failed (invalid window id)";
    return;
  }
  if (!IsClientCreatedWindow(window)) {
    DVLOG(1) << "SetHitTestInsets failed (access denied)";
    return;
  }

  ProxyWindow* proxy_window = ProxyWindow::GetMayBeNull(window);
  DCHECK(proxy_window);  // Must exist because of preceding conditionals.
  proxy_window->SetHitTestInsets(MakeInsetsPositive(mouse),
                                 MakeInsetsPositive(touch));
}

void WindowTree::AttachFrameSinkId(Id transport_window_id,
                                   const viz::FrameSinkId& f) {
  if (!f.is_valid()) {
    DVLOG(3) << "AttachFrameSinkId failed (invalid frame sink)";
    return;
  }
  const ClientWindowId window_id = MakeClientWindowId(transport_window_id);
  aura::Window* window = GetWindowByClientId(window_id);
  if (!window || !IsClientCreatedWindow(window)) {
    DVLOG(3) << "AttachFrameSinkId failed (invalid window id)";
    return;
  }
  ProxyWindow* proxy_window = ProxyWindow::GetMayBeNull(window);
  DCHECK(proxy_window);  // Must exist because of preceding conditionals.
  if (proxy_window->attached_frame_sink_id() == f)
    return;
  if (f.is_valid() && proxy_window->attached_frame_sink_id().is_valid()) {
    DVLOG(3) << "AttachFrameSinkId failed (window already has frame sink)";
    return;
  }
  proxy_window->set_attached_frame_sink_id(f);
  ClientRoot* client_root = FindClientRootContaining(window);
  if (client_root)
    client_root->AttachChildFrameSinkId(proxy_window);
}

void WindowTree::UnattachFrameSinkId(Id transport_window_id) {
  const ClientWindowId window_id = MakeClientWindowId(transport_window_id);
  aura::Window* window = GetWindowByClientId(window_id);
  if (!window || !IsClientCreatedWindow(window)) {
    DVLOG(3) << "UnattachFrameSinkId failed (invalid window id)";
    return;
  }
  ProxyWindow* proxy_window = ProxyWindow::GetMayBeNull(window);
  DCHECK(proxy_window);  // Must exist because of preceding conditionals.
  if (!proxy_window->attached_frame_sink_id().is_valid()) {
    DVLOG(3) << "UnattachFrameSinkId failed (frame sink already cleared)";
    return;
  }

  ClientRoot* client_root = FindClientRootContaining(window);
  if (client_root)
    client_root->UnattachChildFrameSinkId(proxy_window);
  proxy_window->set_attached_frame_sink_id(viz::FrameSinkId());
}

void WindowTree::SetCanAcceptDrops(Id window_id, bool accepts_drops) {
  DVLOG(3) << "SetCanAcceptDrops id="
           << MakeClientWindowId(window_id).ToString()
           << " value=" << accepts_drops;
  aura::Window* window = GetWindowByTransportId(window_id);
  if (!window) {
    DVLOG(1) << "SetCanAcceptDrops failed (no window)";
    return;
  }
  if (!IsClientCreatedWindow(window)) {
    DVLOG(1) << "SetCanAcceptDrops failed (access denied)";
    return;
  }

  ProxyWindow* proxy_window = ProxyWindow::GetMayBeNull(window);
  DCHECK(proxy_window);  // Must exist because of preceding conditionals.
  if (accepts_drops && !proxy_window->HasDragDropDelegate()) {
    auto drag_drop_delegate = std::make_unique<DragDropDelegate>(
        this, window_tree_client_, window, window_id);
    aura::client::SetDragDropDelegate(window, drag_drop_delegate.get());
    proxy_window->SetDragDropDelegate(std::move(drag_drop_delegate));
  } else if (!accepts_drops && proxy_window->HasDragDropDelegate()) {
    aura::client::SetDragDropDelegate(window, nullptr);
    proxy_window->SetDragDropDelegate(nullptr);
  }
}

void WindowTree::SetWindowVisibility(uint32_t change_id,
                                     Id transport_window_id,
                                     bool visible) {
  window_tree_client_->OnChangeCompleted(
      change_id, SetWindowVisibilityImpl(
                     MakeClientWindowId(transport_window_id), visible));
}

void WindowTree::SetWindowProperty(
    uint32_t change_id,
    Id window_id,
    const std::string& name,
    const base::Optional<std::vector<uint8_t>>& value) {
  window_tree_client_->OnChangeCompleted(
      change_id,
      SetWindowPropertyImpl(MakeClientWindowId(window_id), name, value));
}

void WindowTree::SetWindowOpacity(uint32_t change_id,
                                  Id transport_window_id,
                                  float opacity) {
  window_tree_client_->OnChangeCompleted(
      change_id,
      SetWindowOpacityImpl(MakeClientWindowId(transport_window_id), opacity));
}

void WindowTree::AttachCompositorFrameSink(
    Id transport_window_id,
    viz::mojom::CompositorFrameSinkRequest compositor_frame_sink,
    viz::mojom::CompositorFrameSinkClientPtr client) {
  DVLOG(3) << "AttachCompositorFrameSink id="
           << MakeClientWindowId(transport_window_id).ToString();
  aura::Window* window = GetWindowByTransportId(transport_window_id);
  if (!window) {
    DVLOG(1) << "AttachCompositorFrameSink failed (invalid window id)";
    return;
  }
  ProxyWindow* proxy_window = ProxyWindow::GetMayBeNull(window);
  // If this isn't called on the root, then only allow it if there is not
  // another client embedded in the window.
  const bool allow = IsClientRootWindow(window) ||
                     (IsClientCreatedWindow(window) &&
                      proxy_window->embedded_window_tree() == nullptr);
  if (!allow) {
    DVLOG(1) << "AttachCompositorFrameSink failed (policy disallowed)";
    return;
  }

  proxy_window->AttachCompositorFrameSink(std::move(compositor_frame_sink),
                                          std::move(client));
}

void WindowTree::AddWindow(uint32_t change_id, Id parent_id, Id child_id) {
  window_tree_client_->OnChangeCompleted(
      change_id, AddWindowImpl(MakeClientWindowId(parent_id),
                               MakeClientWindowId(child_id)));
}

void WindowTree::RemoveWindowFromParent(uint32_t change_id, Id window_id) {
  window_tree_client_->OnChangeCompleted(
      change_id, RemoveWindowFromParentImpl(MakeClientWindowId(window_id)));
}

void WindowTree::AddTransientWindow(uint32_t change_id,
                                    Id window_id,
                                    Id transient_window_id) {
  window_tree_client_->OnChangeCompleted(
      change_id,
      AddTransientWindowImpl(MakeClientWindowId(window_id),
                             MakeClientWindowId(transient_window_id)));
}

void WindowTree::RemoveTransientWindowFromParent(uint32_t change_id,
                                                 Id transient_window_id) {
  window_tree_client_->OnChangeCompleted(
      change_id, RemoveTransientWindowFromParentImpl(
                     MakeClientWindowId(transient_window_id)));
}

void WindowTree::SetModalType(uint32_t change_id,
                              Id window_id,
                              ui::ModalType type) {
  window_tree_client_->OnChangeCompleted(
      change_id, SetModalTypeImpl(MakeClientWindowId(window_id), type));
}

void WindowTree::ReorderWindow(uint32_t change_id,
                               Id transport_window_id,
                               Id transport_relative_window_id,
                               mojom::OrderDirection direction) {
  const bool result = ReorderWindowImpl(
      MakeClientWindowId(transport_window_id),
      MakeClientWindowId(transport_relative_window_id), direction);
  window_tree_client_->OnChangeCompleted(change_id, result);
}

void WindowTree::GetWindowTree(Id window_id, GetWindowTreeCallback callback) {
  std::vector<aura::Window*> windows =
      GetWindowTreeImpl(MakeClientWindowId(window_id));
  std::move(callback).Run(WindowsToWindowDatas(windows));
}

void WindowTree::Embed(Id transport_window_id,
                       mojom::WindowTreeClientPtr client_ptr,
                       uint32_t embed_flags,
                       EmbedCallback callback) {
  mojom::WindowTreeClient* client = client_ptr.get();
  std::move(callback).Run(EmbedImpl(MakeClientWindowId(transport_window_id),
                                    std::move(client_ptr), client,
                                    embed_flags));
}

void WindowTree::ScheduleEmbed(mojom::WindowTreeClientPtr client,
                               ScheduleEmbedCallback callback) {
  const base::UnguessableToken token = base::UnguessableToken::Create();
  DCHECK(!scheduled_embeds_.count(token));
  scheduled_embeds_[token] = std::move(client);
  std::move(callback).Run(token);
}

void WindowTree::ScheduleEmbedForExistingClient(
    uint32_t window_id,
    ScheduleEmbedForExistingClientCallback callback) {
  const base::UnguessableToken token = base::UnguessableToken::Create();
  DCHECK(!scheduled_embeds_for_existing_client_.count(token));
  scheduled_embeds_for_existing_client_[token] = window_id;
  std::move(callback).Run(token);
}

void WindowTree::EmbedUsingToken(Id transport_window_id,
                                 const base::UnguessableToken& token,
                                 uint32_t embed_flags,
                                 EmbedUsingTokenCallback callback) {
  DVLOG(3) << "EmbedUsingToken transport_window_id="
           << MakeClientWindowId(transport_window_id).ToString()
           << " token=" << token.ToString();
  aura::Window* window =
      GetWindowByClientId(MakeClientWindowId(transport_window_id));
  if (!window) {
    DVLOG(1) << "EmbedUsingToken failed (no window)";
    std::move(callback).Run(false);
    return;
  }

  // Check for a client registered using ScheduleEmbed().
  std::set<WindowTree*> visited_trees;
  mojom::WindowTreeClientPtr client =
      GetAndRemoveScheduledEmbedWindowTreeClient(token, &visited_trees);
  if (client) {
    Embed(transport_window_id, std::move(client), embed_flags,
          std::move(callback));
    return;
  }

  // No client found using ScheduleEmbed(), check for a call to
  // ScheduleEmbedForExistingClient().
  WindowService::TreeAndWindowId tree_and_id =
      window_service_->FindTreeWithScheduleEmbedForExistingClient(token);
  if (!tree_and_id.tree) {
    DVLOG(1) << "EmbedUsingToken failed (token not found)";
    std::move(callback).Run(false);
    return;
  }
  if (tree_and_id.tree == this) {
    DVLOG(1) << "EmbedUsingToken failed, attempt to embed self, token="
             << token.ToString();
    std::move(callback).Run(false);
    return;
  }

  if (!IsClientCreatedWindow(window) || IsTopLevel(window)) {
    DVLOG(1) << "EmbedUsingToken failed (access denied)";
    std::move(callback).Run(false);
    return;
  }

  ProxyWindow* proxy_window = ProxyWindow::GetMayBeNull(window);
  const bool owner_intercept_events =
      (connection_type_ != ConnectionType::kEmbedding &&
       (embed_flags & mojom::kEmbedFlagEmbedderInterceptsEvents) != 0);
  tree_and_id.tree->CompleteScheduleEmbedForExistingClient(
      window, tree_and_id.id, token);
  std::unique_ptr<Embedding> embedding =
      std::make_unique<Embedding>(this, window, owner_intercept_events);
  embedding->InitForEmbedInExistingTree(tree_and_id.tree);
  proxy_window->SetEmbedding(std::move(embedding));
  // Convert |transport_window_id| to ensure the client is supplied a consistent
  // client-id.
  window_tree_client_->OnFrameSinkIdAllocated(
      ClientWindowIdToTransportId(MakeClientWindowId(transport_window_id)),
      proxy_window->frame_sink_id());
  std::move(callback).Run(true);
}

void WindowTree::SetFocus(uint32_t change_id, Id transport_window_id) {
  window_tree_client_->OnChangeCompleted(
      change_id, SetFocusImpl(MakeClientWindowId(transport_window_id)));
}

void WindowTree::SetCanFocus(Id transport_window_id, bool can_focus) {
  focus_handler_.SetCanFocus(GetWindowByTransportId(transport_window_id),
                             can_focus);
}

void WindowTree::SetCursor(uint32_t change_id,
                           Id transport_window_id,
                           ui::Cursor cursor) {
  window_tree_client_->OnChangeCompleted(
      change_id,
      SetCursorImpl(MakeClientWindowId(transport_window_id), cursor));
}

void WindowTree::SetWindowTextInputState(Id window_id,
                                         ::ui::mojom::TextInputStatePtr state) {
  aura::Window* window = GetWindowByTransportId(window_id);
  if (!window) {
    DVLOG(1) << "SetWindowTextInputState failed (no window)";
    return;
  }
  if (!IsClientCreatedWindow(window)) {
    DVLOG(1) << "SetWindowTextInputState failed (access denied)";
    return;
  }

  window_service_->delegate()->UpdateTextInputState(window, std::move(state));
}

void WindowTree::SetImeVisibility(Id window_id,
                                  bool visible,
                                  ::ui::mojom::TextInputStatePtr state) {
  aura::Window* window = GetWindowByTransportId(window_id);
  if (!window) {
    DVLOG(1) << "SetImeVisibility failed (no window)";
    return;
  }
  if (!IsClientCreatedWindow(window)) {
    DVLOG(1) << "SetImeVisibility failed (access denied)";
    return;
  }

  window_service_->delegate()->UpdateImeVisibility(window, visible,
                                                   std::move(state));
}

void WindowTree::SetEventTargetingPolicy(Id transport_window_id,
                                         mojom::EventTargetingPolicy policy) {
  aura::Window* window = GetWindowByTransportId(transport_window_id);
  if (IsClientCreatedWindow(window) || IsClientRootWindow(window))
    window->SetEventTargetingPolicy(policy);
}

void WindowTree::OnWindowInputEventAck(uint32_t event_id,
                                       mojom::EventResult result) {
  DVLOG(4) << "OnWindowInputEventAck id=" << event_id;
  std::unique_ptr<ui::Event> key_event;
  if (!in_flight_key_events_.empty() &&
      in_flight_key_events_.front()->id == event_id) {
    key_event = std::move(in_flight_key_events_.front()->event);
    in_flight_key_events_.pop();
  } else if (!in_flight_other_events_.empty() &&
             in_flight_other_events_.front()->id == event_id) {
    DVLOG_IF(1, in_flight_other_events_.front()->event) << "Unexpected event";
    in_flight_other_events_.pop();
  } else {
    DVLOG(1) << "client acked unknown event";
    return;
  }

  if (key_event && result == mojom::EventResult::UNHANDLED) {
    window_service_->delegate()->OnUnhandledKeyEvent(
        *(key_event->AsKeyEvent()));
  }

  for (WindowServiceObserver& observer : window_service_->observers())
    observer.OnClientAckedEvent(client_id_, event_id);
  TRACE_EVENT_ASYNC_END0("ui", "WindowTree::SendEventToClient", event_id);
}

void WindowTree::DeactivateWindow(Id transport_window_id) {
  DVLOG(3) << "DeactivateWindow id="
           << MakeClientWindowId(transport_window_id).ToString();
  aura::Window* window = GetWindowByTransportId(transport_window_id);
  if (!window) {
    DVLOG(1) << "DeactivateWindow failed (no window)";
    return;
  }

  if (!IsClientCreatedWindow(window) || !IsTopLevel(window)) {
    DVLOG(1) << "DeactivateWindow failed (access denied)";
    return;
  }

  wm::ActivationClient* activation_client =
      wm::GetActivationClient(window->GetRootWindow());
  if (!activation_client) {
    DVLOG(1) << "DeactivateWindow failed (no activation client)";
    return;
  }

  // Only allow deactivation if |window| is the active window.
  if (activation_client->GetActiveWindow() != window) {
    DVLOG(1) << "DeactivateWindow failed (window is not active)";
    return;
  }

  activation_client->DeactivateWindow(window);
}

void WindowTree::StackAbove(uint32_t change_id, Id above_id, Id below_id) {
  const bool result = StackAboveImpl(MakeClientWindowId(above_id),
                                     MakeClientWindowId(below_id));
  window_tree_client_->OnChangeCompleted(change_id, result);
}

void WindowTree::StackAtTop(uint32_t change_id, Id window_id) {
  const bool result = StackAtTopImpl(MakeClientWindowId(window_id));
  window_tree_client_->OnChangeCompleted(change_id, result);
}

void WindowTree::BindWindowManagerInterface(
    const std::string& name,
    mojom::WindowManagerAssociatedRequest window_manager) {
  auto wm_interface = window_service_->delegate()->CreateWindowManagerInterface(
      this, name, window_manager.PassHandle());
  if (wm_interface)
    window_manager_interfaces_.push_back(std::move(wm_interface));
}

void WindowTree::GetCursorLocationMemory(
    GetCursorLocationMemoryCallback callback) {
  auto shared_buffer_handle =
      aura::Env::GetInstance()->GetLastMouseLocationMemory();
  DCHECK(shared_buffer_handle.is_valid());
  std::move(callback).Run(std::move(shared_buffer_handle));
}

void WindowTree::PerformWindowMove(uint32_t change_id,
                                   Id transport_window_id,
                                   mojom::MoveLoopSource source,
                                   const gfx::Point& cursor,
                                   int hit_test) {
  DVLOG(3) << "PerformWindowMove id="
           << MakeClientWindowId(transport_window_id).ToString()
           << " source=" << source << " cursor=" << cursor.ToString()
           << " hit_test=" << hit_test;
  aura::Window* window = GetWindowByTransportId(transport_window_id);
  if (!IsClientCreatedWindow(window) || !IsTopLevel(window) ||
      !window->IsVisible() || window_moving_) {
    DVLOG(1) << "PerformWindowMove failed (invalid window)";
    window_tree_client_->OnChangeCompleted(change_id, false);
    return;
  }

  if (source == mojom::MoveLoopSource::MOUSE &&
      !window->env()->IsMouseButtonDown()) {
    DVLOG(1) << "PerformWindowMove failed (mouse not down)";
    window_tree_client_->OnChangeCompleted(change_id, false);
    return;
  }

  window_moving_ = window;
  window_service_->delegate()->RunWindowMoveLoop(
      window, source, cursor, hit_test,
      base::BindOnce(&WindowTree::OnPerformWindowMoveDone,
                     weak_factory_.GetWeakPtr(), change_id));
}

void WindowTree::CancelWindowMove(Id transport_window_id) {
  if (!window_moving_) {
    DVLOG(1) << "CancelWindowMove called and a move is not underway";
    return;
  }

  aura::Window* window = GetWindowByTransportId(transport_window_id);
  if (window == window_moving_)
    window_service_->delegate()->CancelWindowMoveLoop();
  else
    DVLOG(1) << "CancelWindowMove called with wrong window";
}

void WindowTree::PerformDragDrop(
    uint32_t change_id,
    Id source_window_id,
    const gfx::Point& screen_location,
    const base::flat_map<std::string, std::vector<uint8_t>>& drag_data,
    const gfx::ImageSkia& drag_image,
    const gfx::Vector2d& drag_image_offset,
    uint32_t drag_operation,
    ::ui::mojom::PointerKind source) {
  if (pending_drag_source_window_id_ != kInvalidTransportId) {
    DVLOG(1) << "PerformDragDrop failed (only one drag allowed)";
    window_tree_client_->OnPerformDragDropCompleted(change_id, false,
                                                    mojom::kDropEffectNone);
    return;
  }

  pending_drag_source_window_id_ = source_window_id;

  // Runs the drag loop as a posted task to unwind mojo call stack.
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE,
      base::BindOnce(&WindowTree::DoPerformDragDrop, weak_factory_.GetWeakPtr(),
                     change_id, source_window_id, screen_location, drag_data,
                     drag_image, drag_image_offset, drag_operation, source));
}

void WindowTree::CancelDragDrop(Id window_id) {
  if (pending_drag_source_window_id_ == kInvalidTransportId) {
    DVLOG(1) << "CancelDragDrop called and a drag is not underway";
    return;
  }

  if (pending_drag_source_window_id_ != window_id) {
    DVLOG(1) << "CancelDragDrop called with wrong window";
    return;
  }

  // Clear |pending_drag_source_window_id_| to cancel posted drag loop task.
  pending_drag_source_window_id_ = kInvalidTransportId;

  aura::Window* window = GetWindowByTransportId(window_id);
  if (!window) {
    DVLOG(1) << "CancelDragDrop failed (no window)";
    return;
  }

  if (!IsClientCreatedWindow(window)) {
    DVLOG(1) << "CancelDragDrop failed (access denied)";
    return;
  }

  // Cancel the current drag loop if it is running.
  window_service_->delegate()->CancelDragLoop(window);
}

void WindowTree::ObserveTopmostWindow(mojom::MoveLoopSource source,
                                      Id window_id) {
  if (connection_type_ == ConnectionType::kEmbedding) {
    DVLOG(1) << "ObserveTopmostWindow failed (access denied)";
    return;
  }
  DVLOG(3) << "ObserveTopmostWindow id="
           << MakeClientWindowId(window_id).ToString();
  aura::Window* window = GetWindowByTransportId(window_id);
  if (!IsClientCreatedWindow(window) || !IsTopLevel(window) ||
      !window->IsVisible() || topmost_window_observer_) {
    DVLOG(1) << "ObserveTopmostWindow failed (invalid window)";
    return;
  }

  topmost_window_observer_ =
      std::make_unique<TopmostWindowObserver>(this, source, window);
}

void WindowTree::StopObservingTopmostWindow() {
  if (connection_type_ == ConnectionType::kEmbedding) {
    DVLOG(1) << "StopObservingTopmostWindow failed (access denied)";
    return;
  }
  if (!topmost_window_observer_) {
    DVLOG(1) << "StopObservingTopmostWindow failed";
    return;
  }
  topmost_window_observer_.reset();
}

void WindowTree::SetWindowResizeShadow(Id window_id, int hit_test) {
  DVLOG(3) << "SetWindowResizeShadow id="
           << MakeClientWindowId(window_id).ToString()
           << " hit_test=" << hit_test;
  aura::Window* window = GetWindowByTransportId(window_id);
  if (!IsClientCreatedWindow(window) || !IsTopLevel(window) ||
      !window->IsVisible()) {
    DVLOG(1) << "SetWindowResizeShadow failed (invalid window)";
    return;
  }
  if (hit_test != HTNOWHERE && !ui::IsResizingComponent(hit_test)) {
    DVLOG(1) << "SetWindowResizeShadow failed (invalid hit_test)";
    return;
  }
  window_service_->delegate()->SetWindowResizeShadow(window, hit_test);
}

void WindowTree::CancelActiveTouchesExcept(Id not_cancelled_window_id) {
  if (connection_type_ == ConnectionType::kEmbedding) {
    DVLOG(1) << "CancelActiveTouchesExcept failed (access denied)";
    return;
  }
  DVLOG(3) << "CancelActiveTouchesExcept not_cancelled_window_id="
           << MakeClientWindowId(not_cancelled_window_id).ToString();
  aura::Window* not_cancelled_window = nullptr;
  if (not_cancelled_window_id != kInvalidTransportId) {
    not_cancelled_window = GetWindowByTransportId(not_cancelled_window_id);
    if (!not_cancelled_window || !IsClientCreatedWindow(not_cancelled_window)) {
      DVLOG(1) << "CancelActiveTouchesExcept failed (invalid window)";
      return;
    }
  }
  window_service_->env()->gesture_recognizer()->CancelActiveTouchesExcept(
      not_cancelled_window);
}

void WindowTree::CancelActiveTouches(Id window_id) {
  if (connection_type_ == ConnectionType::kEmbedding) {
    DVLOG(1) << "CancelActiveTouches failed (access denied)";
    return;
  }
  DVLOG(3) << "CancelActiveTouches window_id="
           << MakeClientWindowId(window_id).ToString();
  aura::Window* window = GetWindowByTransportId(window_id);
  if (!window || !IsClientCreatedWindow(window)) {
    DVLOG(1) << "CancelActiveTouches failed (invalid window)";
    return;
  }
  window_service_->env()->gesture_recognizer()->CancelActiveTouches(window);
}

void WindowTree::TransferGestureEventsTo(Id current_id,
                                         Id new_id,
                                         bool should_cancel) {
  if (connection_type_ == ConnectionType::kEmbedding) {
    DVLOG(1) << "TransferGestureEventsTo failed (access denied)";
    return;
  }
  DVLOG(3) << "TransferGestureEventsTo current_id="
           << MakeClientWindowId(current_id).ToString()
           << " new_id=" << MakeClientWindowId(new_id)
           << " should_cancel=" << should_cancel;
  aura::Window* current_window = GetWindowByTransportId(current_id);
  aura::Window* new_window = GetWindowByTransportId(new_id);
  if (!current_window || !IsClientCreatedWindow(current_window)) {
    DVLOG(1) << "TransferGestureEventsTo failed (invalid current_window)";
    return;
  }
  if (!new_window || !IsClientCreatedWindow(new_window)) {
    DVLOG(1) << "TransferGestureEventsTo failed (invalid new_window)";
    return;
  }
  window_service_->env()->gesture_recognizer()->TransferEventsTo(
      current_window, new_window,
      should_cancel ? ui::TransferTouchesBehavior::kCancel
                    : ui::TransferTouchesBehavior::kDontCancel);
}

void WindowTree::TrackOcclusionState(Id transport_window_id) {
  aura::Window* window = GetWindowByTransportId(transport_window_id);
  if (!window) {
    DVLOG(1) << "TrackOcclusionState failed (no window)";
    return;
  }
  if (!IsClientCreatedWindow(window)) {
    DVLOG(1) << "TrackOcclusionState failed (access denied)";
    return;
  }

  window->TrackOcclusionState();
}

void WindowTree::PauseWindowOcclusionTracking() {
  window_occlusion_tracking_pauses_.emplace_back(
      std::make_unique<aura::WindowOcclusionTracker::ScopedPause>(
          window_service_->env()));
}

void WindowTree::UnpauseWindowOcclusionTracking() {
  if (window_occlusion_tracking_pauses_.empty()) {
    DVLOG(1) << "Unbalanced UnpauseWindowOcclusionTracking call.";
    return;
  }

  window_occlusion_tracking_pauses_.pop_back();
}

}  // namespace ws
