// 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 <stddef.h>
#include <stdint.h>

#include "base/bind.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "services/ui/common/util.h"
#include "services/ui/ws/window_server_test_base.h"
#include "ui/aura/client/transient_window_client.h"
#include "ui/aura/env.h"
#include "ui/aura/mus/window_port_mus.h"
#include "ui/aura/mus/window_tree_client.h"
#include "ui/aura/mus/window_tree_client_delegate.h"
#include "ui/aura/mus/window_tree_host_mus.h"
#include "ui/aura/mus/window_tree_host_mus_init_params.h"
#include "ui/aura/test/mus/window_tree_client_private.h"
#include "ui/aura/window.h"
#include "ui/aura/window_observer.h"
#include "ui/aura/window_tracker.h"
#include "ui/gfx/geometry/rect.h"

namespace ui {
namespace ws {

namespace {

Id server_id(aura::Window* window) {
  return aura::WindowMus::Get(window)->server_id();
}

aura::Window* GetChildWindowByServerId(aura::WindowTreeClient* client,
                                       aura::Id id) {
  return aura::WindowTreeClientPrivate(client).GetWindowByServerId(id);
}

class TestWindowManagerDelegate : public aura::WindowManagerDelegate {
 public:
  TestWindowManagerDelegate() {}
  ~TestWindowManagerDelegate() override {}

  // WindowManagerDelegate:
  void SetWindowManagerClient(aura::WindowManagerClient* client) override {}
  void OnWmConnected() override {}
  void OnWmSetBounds(aura::Window* window, const gfx::Rect& bounds) override {}
  bool OnWmSetProperty(
      aura::Window* window,
      const std::string& name,
      std::unique_ptr<std::vector<uint8_t>>* new_data) override {
    return false;
  }
  void OnWmSetModalType(aura::Window* window, ui::ModalType type) override {}
  void OnWmSetCanFocus(aura::Window* window, bool can_focus) override {}
  aura::Window* OnWmCreateTopLevelWindow(
      ui::mojom::WindowType window_type,
      std::map<std::string, std::vector<uint8_t>>* properties) override {
    return nullptr;
  }
  void OnWmClientJankinessChanged(const std::set<aura::Window*>& client_windows,
                                  bool not_responding) override {}
  void OnWmBuildDragImage(const gfx::Point& screen_location,
                          const SkBitmap& drag_image,
                          const gfx::Vector2d& drag_image_offset,
                          ui::mojom::PointerKind source) override {}
  void OnWmMoveDragImage(const gfx::Point& screen_location) override {}
  void OnWmDestroyDragImage() override {}
  void OnWmWillCreateDisplay(const display::Display& display) override {}
  void OnWmNewDisplay(std::unique_ptr<aura::WindowTreeHostMus> window_tree_host,
                      const display::Display& display) override {}
  void OnWmDisplayRemoved(aura::WindowTreeHostMus* window_tree_host) override {}
  void OnWmDisplayModified(const display::Display& display) override {}
  mojom::EventResult OnAccelerator(
      uint32_t accelerator_id,
      const ui::Event& event,
      std::unordered_map<std::string, std::vector<uint8_t>>* properties)
      override {
    return ui::mojom::EventResult::UNHANDLED;
  }
  void OnWmPerformMoveLoop(aura::Window* window,
                           mojom::MoveLoopSource source,
                           const gfx::Point& cursor_location,
                           const base::Callback<void(bool)>& on_done) override {
  }
  void OnWmCancelMoveLoop(aura::Window* window) override {}
  void OnWmSetClientArea(
      aura::Window* window,
      const gfx::Insets& insets,
      const std::vector<gfx::Rect>& additional_client_areas) override {}
  bool IsWindowActive(aura::Window* window) override { return true; }
  void OnWmDeactivateWindow(aura::Window* window) override {}

 private:
  DISALLOW_COPY_AND_ASSIGN(TestWindowManagerDelegate);
};

class BoundsChangeObserver : public aura::WindowObserver {
 public:
  explicit BoundsChangeObserver(aura::Window* window) : window_(window) {
    window_->AddObserver(this);
  }
  ~BoundsChangeObserver() override { window_->RemoveObserver(this); }

 private:
  // Overridden from WindowObserver:
  void OnWindowBoundsChanged(aura::Window* window,
                             const gfx::Rect& old_bounds,
                             const gfx::Rect& new_bounds) override {
    DCHECK_EQ(window, window_);
    EXPECT_TRUE(WindowServerTestBase::QuitRunLoop());
  }

  aura::Window* window_;

  DISALLOW_COPY_AND_ASSIGN(BoundsChangeObserver);
};

// Wait until the bounds of the supplied window change; returns false on
// timeout.
bool WaitForBoundsToChange(aura::Window* window) {
  BoundsChangeObserver observer(window);
  return WindowServerTestBase::DoRunLoopWithTimeout();
}

// Spins a run loop until the tree beginning at |root| has |tree_size| windows
// (including |root|).
class TreeSizeMatchesObserver : public aura::WindowObserver {
 public:
  TreeSizeMatchesObserver(aura::Window* tree, size_t tree_size)
      : tree_(tree), tree_size_(tree_size) {
    tree_->AddObserver(this);
  }
  ~TreeSizeMatchesObserver() override { tree_->RemoveObserver(this); }

  bool IsTreeCorrectSize() { return CountWindows(tree_) == tree_size_; }

 private:
  // Overridden from WindowObserver:
  void OnWindowHierarchyChanged(const HierarchyChangeParams& params) override {
    if (IsTreeCorrectSize())
      EXPECT_TRUE(WindowServerTestBase::QuitRunLoop());
  }

  size_t CountWindows(const aura::Window* window) const {
    size_t count = 1;
    for (const aura::Window* child : window->children())
      count += CountWindows(child);
    return count;
  }

  aura::Window* tree_;
  size_t tree_size_;

  DISALLOW_COPY_AND_ASSIGN(TreeSizeMatchesObserver);
};

// Wait until |window| has |tree_size| descendants; returns false on timeout.
// The count includes |window|. For example, if you want to wait for |window| to
// have a single child, use a |tree_size| of 2.
bool WaitForTreeSizeToMatch(aura::Window* window, size_t tree_size) {
  TreeSizeMatchesObserver observer(window, tree_size);
  return observer.IsTreeCorrectSize() ||
         WindowServerTestBase::DoRunLoopWithTimeout();
}

class StackingOrderChangeObserver : public aura::WindowObserver {
 public:
  StackingOrderChangeObserver(aura::Window* window) : window_(window) {
    window_->AddObserver(this);
  }
  ~StackingOrderChangeObserver() override { window_->RemoveObserver(this); }

 private:
  // Overridden from aura::WindowObserver:
  void OnWindowStackingChanged(aura::Window* window) override {
    DCHECK_EQ(window, window_);
    EXPECT_TRUE(WindowServerTestBase::QuitRunLoop());
  }

  aura::Window* window_;

  DISALLOW_COPY_AND_ASSIGN(StackingOrderChangeObserver);
};

// Wait until |window|'s tree size matches |tree_size|; returns false on
// timeout.
bool WaitForStackingOrderChange(aura::Window* window) {
  StackingOrderChangeObserver observer(window);
  return WindowServerTestBase::DoRunLoopWithTimeout();
}

// Tracks a window's destruction. Query is_valid() for current state.
class WindowTracker : public aura::WindowObserver {
 public:
  explicit WindowTracker(aura::Window* window) : window_(window) {
    window_->AddObserver(this);
  }
  ~WindowTracker() override {
    if (window_)
      window_->RemoveObserver(this);
  }

  bool is_valid() const { return !!window_; }

 private:
  // Overridden from WindowObserver:
  void OnWindowDestroyed(aura::Window* window) override {
    DCHECK_EQ(window, window_);
    window_ = nullptr;
  }

  aura::Window* window_;

  DISALLOW_COPY_AND_ASSIGN(WindowTracker);
};

// Creates a new visible Window. If |parent| is non-null the newly created
// window is added to it.
aura::Window* NewVisibleWindow(aura::Window* parent,
                               aura::WindowTreeClient* client) {
  std::unique_ptr<aura::WindowPortMus> window_port_mus =
      base::MakeUnique<aura::WindowPortMus>(client, aura::WindowMusType::LOCAL);
  aura::Window* window = new aura::Window(nullptr, std::move(window_port_mus));
  window->Init(ui::LAYER_NOT_DRAWN);
  window->Show();
  if (parent)
    parent->AddChild(window);
  return window;
}

}  // namespace

// WindowServer
// -----------------------------------------------------------------

struct EmbedResult {
  bool IsValid() const {
    return window_tree_client.get() != nullptr &&
           window_tree_host.get() != nullptr;
  }

  std::unique_ptr<aura::WindowTreeClient> window_tree_client;
  std::unique_ptr<aura::WindowTreeHostMus> window_tree_host;
};

aura::Window* GetFirstRoot(aura::WindowTreeClient* client) {
  return client->GetRoots().empty() ? nullptr : *client->GetRoots().begin();
}

// These tests model synchronization of two peer clients of the window server,
// that are given access to some root window.

class WindowServerTest : public WindowServerTestBase {
 public:
  struct ClientAreaChange {
    aura::Window* window = nullptr;
    gfx::Insets insets;
  };

  WindowServerTest() {}

  aura::Window* GetFirstWMRoot() { return GetFirstRoot(window_manager()); }

  // Embeds another version of the test app @ window. This runs a run loop until
  // a response is received, or a timeout. The return value is always non-null,
  // but if there is an error there is no WindowTreeClient. Always use
  // ASSERT_EQ(result->IsValid()) on the return value.
  std::unique_ptr<EmbedResult> Embed(aura::WindowTreeClient* window_tree_client,
                                     aura::Window* window) {
    DCHECK(!embed_details_);
    embed_details_ = base::MakeUnique<EmbedDetails>();
    window_tree_client->Embed(window, ConnectAndGetWindowServerClient(), 0,
                              base::Bind(&WindowServerTest::EmbedCallbackImpl,
                                         base::Unretained(this)));
    if (embed_details_->callback_run) {
      // The callback was run immediately, this indicates an immediate failure,
      // such as |window| has children.
      EXPECT_FALSE(embed_details_->embed_result);
      embed_details_.reset();
      return base::MakeUnique<EmbedResult>();
    }
    // Wait for EmbedCallbackImpl() to be called with the result.
    embed_details_->waiting = true;
    if (!WindowServerTestBase::DoRunLoopWithTimeout()) {
      embed_details_.reset();
      return base::MakeUnique<EmbedResult>();
    }
    std::unique_ptr<EmbedResult> result = std::move(embed_details_->result);
    embed_details_.reset();
    return result;
  }

  // Establishes a connection to this application and asks for a
  // WindowTreeClient.
  ui::mojom::WindowTreeClientPtr ConnectAndGetWindowServerClient() {
    ui::mojom::WindowTreeClientPtr client;
    connector()->BindInterface(test_name(), &client);
    return client;
  }

  std::unique_ptr<ClientAreaChange> WaitForClientAreaToChange() {
    client_area_change_ = base::MakeUnique<ClientAreaChange>();
    // The nested run loop is quit in OnWmSetClientArea(). Client area
    // changes don't route through the window, only the WindowManagerDelegate.
    if (!WindowServerTestBase::DoRunLoopWithTimeout()) {
      client_area_change_.reset();
      return nullptr;
    }
    return std::move(client_area_change_);
  }

  // WindowServerTestBase:
  void OnEmbed(
      std::unique_ptr<aura::WindowTreeHostMus> window_tree_host) override {
    if (!embed_details_) {
      WindowServerTestBase::OnEmbed(std::move(window_tree_host));
      return;
    }

    embed_details_->result->window_tree_host = std::move(window_tree_host);
    embed_details_->result->window_tree_client = ReleaseMostRecentClient();
    if (embed_details_->callback_run)
      EXPECT_TRUE(WindowServerTestBase::QuitRunLoop());
  }
  void OnWmSetClientArea(
      aura::Window* window,
      const gfx::Insets& insets,
      const std::vector<gfx::Rect>& additional_client_areas) override {
    if (!client_area_change_.get())
      return;

    client_area_change_->window = window;
    client_area_change_->insets = insets;
    EXPECT_TRUE(WindowServerTestBase::QuitRunLoop());
  }

 private:
  // Used to track the state of a call to window->Embed().
  struct EmbedDetails {
    EmbedDetails() : result(base::MakeUnique<EmbedResult>()) {}

    // The callback function supplied to Embed() was called.
    bool callback_run = false;

    // The boolean supplied to the Embed() callback.
    bool embed_result = false;

    // Whether a MessageLoop is running.
    bool waiting = false;

    std::unique_ptr<EmbedResult> result;
  };

  void EmbedCallbackImpl(bool result) {
    embed_details_->callback_run = true;
    embed_details_->embed_result = result;
    if (embed_details_->waiting &&
        (!result || embed_details_->result->window_tree_client))
      EXPECT_TRUE(WindowServerTestBase::QuitRunLoop());
  }

  std::unique_ptr<EmbedDetails> embed_details_;

  std::unique_ptr<ClientAreaChange> client_area_change_;

  DISALLOW_COPY_AND_ASSIGN(WindowServerTest);
};

TEST_F(WindowServerTest, RootWindow) {
  ASSERT_NE(nullptr, window_manager());
  EXPECT_EQ(1u, window_manager()->GetRoots().size());
}

TEST_F(WindowServerTest, Embed) {
  aura::Window* window = NewVisibleWindow(GetFirstWMRoot(), window_manager());
  std::unique_ptr<EmbedResult> embed_result = Embed(window_manager(), window);
  ASSERT_TRUE(embed_result->IsValid());

  aura::Window* embed_root = embed_result->window_tree_host->window();
  // WindowTreeHost::window() is the single root of the embed.
  EXPECT_EQ(1u, embed_result->window_tree_client->GetRoots().size());
  EXPECT_EQ(embed_root, GetFirstRoot(embed_result->window_tree_client.get()));
  EXPECT_EQ(server_id(window), server_id(embed_root));
  EXPECT_EQ(nullptr, embed_root->parent());
  EXPECT_TRUE(embed_root->children().empty());
}

// Window manager has two windows, N1 and N11. Embeds A at N1. A should not see
// N11.
TEST_F(WindowServerTest, EmbeddedDoesntSeeChild) {
  aura::Window* window = NewVisibleWindow(GetFirstWMRoot(), window_manager());
  std::unique_ptr<EmbedResult> embed_result = Embed(window_manager(), window);
  ASSERT_TRUE(embed_result->IsValid());
  aura::Window* embed_root = embed_result->window_tree_host->window();
  EXPECT_EQ(server_id(window), server_id(embed_root));
  EXPECT_EQ(nullptr, embed_root->parent());
  EXPECT_TRUE(embed_root->children().empty());
}

// TODO(beng): write a replacement test for the one that once existed here:
// This test validates the following scenario:
// -  a window originating from one client
// -  a window originating from a second client
// +  the client originating the window is destroyed
// -> the window should still exist (since the second client is live) but
//    should be disconnected from any windows.
// http://crbug.com/396300
//
// TODO(beng): The new test should validate the scenario as described above
//             except that the second client still has a valid tree.

// Verifies that bounds changes applied to a window hierarchy in one client
// are reflected to another.
TEST_F(WindowServerTest, SetBounds) {
  aura::Window* window = NewVisibleWindow(GetFirstWMRoot(), window_manager());

  std::unique_ptr<EmbedResult> embed_result = Embed(window_manager(), window);
  ASSERT_TRUE(embed_result->IsValid());
  aura::Window* embed_root = embed_result->window_tree_host->window();
  EXPECT_EQ(window->bounds(), embed_root->bounds());

  window->SetBounds(gfx::Rect(0, 0, 100, 100));
  ASSERT_TRUE(WaitForBoundsToChange(embed_root));
  EXPECT_EQ(window->bounds(), embed_root->bounds());
}

// Verifies that bounds changes applied to a window owned by a different
// client can be refused.
TEST_F(WindowServerTest, SetBoundsSecurity) {
  TestWindowManagerDelegate wm_delegate;
  set_window_manager_delegate(&wm_delegate);

  aura::Window* window = NewVisibleWindow(GetFirstWMRoot(), window_manager());

  std::unique_ptr<EmbedResult> embed_result = Embed(window_manager(), window);
  ASSERT_TRUE(embed_result->IsValid());
  aura::Window* embed_root = embed_result->window_tree_host->window();
  window->SetBounds(gfx::Rect(0, 0, 800, 600));
  ASSERT_TRUE(WaitForBoundsToChange(embed_root));

  embed_result->window_tree_host->SetBoundsInPixels(gfx::Rect(0, 0, 1024, 768));
  // Bounds change is initially accepted, but the server declines the request.
  EXPECT_NE(window->bounds(), embed_root->bounds());

  // The client is notified when the requested is declined, and updates the
  // local bounds accordingly.
  ASSERT_TRUE(WaitForBoundsToChange(embed_root));
  EXPECT_EQ(window->bounds(), embed_root->bounds());
  set_window_manager_delegate(nullptr);
}

// Verifies that a root window can always be destroyed.
TEST_F(WindowServerTest, DestroySecurity) {
  aura::Window* window = NewVisibleWindow(GetFirstWMRoot(), window_manager());

  std::unique_ptr<EmbedResult> embed_result = Embed(window_manager(), window);
  ASSERT_TRUE(embed_result->IsValid());
  aura::Window* embed_root = embed_result->window_tree_host->window();

  // The root can be destroyed, even though it was not created by the client.
  aura::WindowTracker tracker;
  tracker.Add(window);
  tracker.Add(embed_root);
  embed_result->window_tree_host.reset();
  EXPECT_FALSE(tracker.Contains(embed_root));
  EXPECT_TRUE(tracker.Contains(window));

  delete window;
  EXPECT_FALSE(tracker.Contains(window));
}

TEST_F(WindowServerTest, MultiRoots) {
  aura::Window* window1 = NewVisibleWindow(GetFirstWMRoot(), window_manager());
  aura::Window* window2 = NewVisibleWindow(GetFirstWMRoot(), window_manager());
  std::unique_ptr<EmbedResult> embed_result1 = Embed(window_manager(), window1);
  ASSERT_TRUE(embed_result1->IsValid());
  std::unique_ptr<EmbedResult> embed_result2 = Embed(window_manager(), window2);
  ASSERT_TRUE(embed_result2->IsValid());
}

TEST_F(WindowServerTest, Reorder) {
  aura::Window* window1 = NewVisibleWindow(GetFirstWMRoot(), window_manager());

  std::unique_ptr<EmbedResult> embed_result = Embed(window_manager(), window1);
  ASSERT_TRUE(embed_result->IsValid());
  aura::WindowTreeClient* embedded = embed_result->window_tree_client.get();
  aura::Window* embed_root = embed_result->window_tree_host->window();

  aura::Window* window11 = NewVisibleWindow(embed_root, embedded);
  aura::Window* window12 = NewVisibleWindow(embed_root, embedded);
  ASSERT_TRUE(WaitForTreeSizeToMatch(window1, 3u));


  {
    window11->parent()->StackChildAtTop(window11);
    // The |embedded| tree should be updated immediately.
    EXPECT_EQ(embed_root->children().front(),
              GetChildWindowByServerId(embedded, server_id(window12)));
    EXPECT_EQ(embed_root->children().back(),
              GetChildWindowByServerId(embedded, server_id(window11)));

    // The window_manager() tree is still not updated.
    EXPECT_EQ(window1->children().back(),
              GetChildWindowByServerId(window_manager(), server_id(window12)));

    // Wait until window_manager() tree is updated.
    ASSERT_TRUE(WaitForStackingOrderChange(
        GetChildWindowByServerId(window_manager(), server_id(window11))));
    EXPECT_EQ(window1->children().front(),
              GetChildWindowByServerId(window_manager(), server_id(window12)));
    EXPECT_EQ(window1->children().back(),
              GetChildWindowByServerId(window_manager(), server_id(window11)));
  }

  {
    window11->parent()->StackChildAtBottom(window11);
    // |embedded| should be updated immediately.
    EXPECT_EQ(embed_root->children().front(),
              GetChildWindowByServerId(embedded, server_id(window11)));
    EXPECT_EQ(embed_root->children().back(),
              GetChildWindowByServerId(embedded, server_id(window12)));

    // |window_manager()| is also eventually updated.
    EXPECT_EQ(window1->children().back(),
              GetChildWindowByServerId(window_manager(), server_id(window11)));
    ASSERT_TRUE(WaitForStackingOrderChange(
        GetChildWindowByServerId(window_manager(), server_id(window11))));
    EXPECT_EQ(window1->children().front(),
              GetChildWindowByServerId(window_manager(), server_id(window11)));
    EXPECT_EQ(window1->children().back(),
              GetChildWindowByServerId(window_manager(), server_id(window12)));
  }
}

namespace {

class VisibilityChangeObserver : public aura::WindowObserver {
 public:
  explicit VisibilityChangeObserver(aura::Window* window) : window_(window) {
    window_->AddObserver(this);
  }
  ~VisibilityChangeObserver() override { window_->RemoveObserver(this); }

 private:
  // Overridden from WindowObserver:
  void OnWindowVisibilityChanged(aura::Window* window, bool visible) override {
    EXPECT_EQ(window, window_);
    EXPECT_TRUE(WindowServerTestBase::QuitRunLoop());
  }

  aura::Window* window_;

  DISALLOW_COPY_AND_ASSIGN(VisibilityChangeObserver);
};

}  // namespace

TEST_F(WindowServerTest, Visible) {
  aura::Window* window1 = NewVisibleWindow(GetFirstWMRoot(), window_manager());

  // Embed another app and verify initial state.
  std::unique_ptr<EmbedResult> embed_result = Embed(window_manager(), window1);
  ASSERT_TRUE(embed_result->IsValid());
  aura::Window* embed_root = embed_result->window_tree_host->window();
  EXPECT_TRUE(embed_root->TargetVisibility());
  EXPECT_TRUE(embed_root->IsVisible());

  // Change the visible state from the first client and verify its mirrored
  // correctly to the embedded app.
  {
    VisibilityChangeObserver observer(embed_root);
    window1->Hide();
    ASSERT_TRUE(WindowServerTestBase::DoRunLoopWithTimeout());
  }

  EXPECT_FALSE(window1->TargetVisibility());
  EXPECT_FALSE(window1->IsVisible());

  EXPECT_FALSE(embed_root->TargetVisibility());
  EXPECT_FALSE(embed_root->IsVisible());

  // Make the node visible again.
  {
    VisibilityChangeObserver observer(embed_root);
    window1->Show();
    ASSERT_TRUE(WindowServerTestBase::DoRunLoopWithTimeout());
  }

  EXPECT_TRUE(window1->TargetVisibility());
  EXPECT_TRUE(window1->IsVisible());

  EXPECT_TRUE(embed_root->TargetVisibility());
  EXPECT_TRUE(embed_root->IsVisible());
}

// TODO(beng): tests for window event dispatcher.
// - verify that we see events for all windows.

TEST_F(WindowServerTest, EmbedFailsWithChildren) {
  aura::Window* window1 = NewVisibleWindow(GetFirstWMRoot(), window_manager());
  ASSERT_TRUE(NewVisibleWindow(window1, window_manager()));
  std::unique_ptr<EmbedResult> embed_result = Embed(window_manager(), window1);
  // Embed() should fail as |window1| has a child.
  EXPECT_FALSE(embed_result->IsValid());
}

namespace {

class DestroyObserver : public aura::WindowObserver {
 public:
  DestroyObserver(aura::WindowTreeClient* client, bool* got_destroy)
      : got_destroy_(got_destroy) {
    GetFirstRoot(client)->AddObserver(this);
  }
  ~DestroyObserver() override {}

 private:
  // Overridden from aura::WindowObserver:
  void OnWindowDestroyed(aura::Window* window) override {
    *got_destroy_ = true;
    window->RemoveObserver(this);

    EXPECT_TRUE(WindowServerTestBase::QuitRunLoop());
  }

  bool* got_destroy_;

  DISALLOW_COPY_AND_ASSIGN(DestroyObserver);
};

}  // namespace

// Verifies deleting a Window that is the root of another client notifies
// observers in the right order (OnWindowDestroyed() before
// OnWindowManagerDestroyed()).
TEST_F(WindowServerTest, WindowServerDestroyedAfterRootObserver) {
  aura::Window* window = NewVisibleWindow(GetFirstWMRoot(), window_manager());

  std::unique_ptr<EmbedResult> embed_result = Embed(window_manager(), window);
  ASSERT_TRUE(embed_result->IsValid());
  aura::WindowTreeClient* embedded_client =
      embed_result->window_tree_client.get();

  bool got_destroy = false;
  DestroyObserver observer(embedded_client, &got_destroy);
  // Delete the window |embedded_client| is embedded in. |embedded_client| is
  // asynchronously notified and cleans up.
  delete window;
  EXPECT_TRUE(DoRunLoopWithTimeout());
  ASSERT_TRUE(got_destroy);
  // The WindowTreeHost was destroyed as well (by
  // WindowServerTestBase::OnEmbedRootDestroyed()).
  embed_result->window_tree_host.release();
  EXPECT_EQ(0u, embed_result->window_tree_client->GetRoots().size());
}

TEST_F(WindowServerTest, ClientAreaChanged) {
  aura::Window* window = NewVisibleWindow(GetFirstWMRoot(), window_manager());

  std::unique_ptr<EmbedResult> embed_result = Embed(window_manager(), window);
  ASSERT_TRUE(embed_result->IsValid());

  // Verify change from embedded makes it to parent.
  const gfx::Insets insets(1, 2, 3, 4);
  embed_result->window_tree_host->SetClientArea(insets,
                                                std::vector<gfx::Rect>());
  std::unique_ptr<ClientAreaChange> client_area_change =
      WaitForClientAreaToChange();
  ASSERT_TRUE(client_area_change);
  EXPECT_EQ(window, client_area_change->window);
  EXPECT_EQ(insets, client_area_change->insets);
}

class EstablishConnectionViaFactoryDelegate : public TestWindowManagerDelegate {
 public:
  explicit EstablishConnectionViaFactoryDelegate(aura::WindowTreeClient* client)
      : client_(client), run_loop_(nullptr), created_window_(nullptr) {}
  ~EstablishConnectionViaFactoryDelegate() override {}

  bool QuitOnCreate() {
    if (run_loop_)
      return false;

    created_window_ = nullptr;
    run_loop_ = base::MakeUnique<base::RunLoop>();
    run_loop_->Run();
    run_loop_.reset();
    return created_window_ != nullptr;
  }

  aura::Window* created_window() { return created_window_; }

  // WindowManagerDelegate:
  aura::Window* OnWmCreateTopLevelWindow(
      ui::mojom::WindowType window_type,
      std::map<std::string, std::vector<uint8_t>>* properties) override {
    created_window_ = NewVisibleWindow((*client_->GetRoots().begin()), client_);
    if (run_loop_)
      run_loop_->Quit();
    return created_window_;
  }

 private:
  aura::WindowTreeClient* client_;
  std::unique_ptr<base::RunLoop> run_loop_;
  aura::Window* created_window_;

  DISALLOW_COPY_AND_ASSIGN(EstablishConnectionViaFactoryDelegate);
};

TEST_F(WindowServerTest, EstablishConnectionViaFactory) {
  EstablishConnectionViaFactoryDelegate delegate(window_manager());
  set_window_manager_delegate(&delegate);
  aura::WindowTreeClient second_client(connector(), this, nullptr, nullptr,
                                       nullptr, false);
  second_client.ConnectViaWindowTreeFactory();
  aura::WindowTreeHostMus window_tree_host_in_second_client(
      aura::CreateInitParamsForTopLevel(&second_client));
  window_tree_host_in_second_client.InitHost();
  window_tree_host_in_second_client.window()->Show();
  ASSERT_TRUE(second_client.GetRoots().count(
                  window_tree_host_in_second_client.window()) > 0);
  // Wait for the window to appear in the wm.
  ASSERT_TRUE(delegate.QuitOnCreate());

  aura::Window* window_in_wm = delegate.created_window();
  ASSERT_TRUE(window_in_wm);

  // Change the bounds in the wm, and make sure the child sees it.
  const gfx::Rect window_bounds(1, 11, 12, 101);
  window_in_wm->SetBounds(window_bounds);
  ASSERT_TRUE(
      WaitForBoundsToChange(window_tree_host_in_second_client.window()));
  EXPECT_EQ(window_bounds,
            window_tree_host_in_second_client.GetBoundsInPixels());
}

TEST_F(WindowServerTest, OnWindowHierarchyChangedIncludesTransientParent) {
  // Create a second connection. In the second connection create a window,
  // parent it to the root, create another window, mark it as a transient parent
  // of the first window and then add it.
  EstablishConnectionViaFactoryDelegate delegate(window_manager());
  set_window_manager_delegate(&delegate);
  aura::WindowTreeClient second_client(connector(), this, nullptr, nullptr,
                                       nullptr, false);
  second_client.ConnectViaWindowTreeFactory();
  aura::WindowTreeHostMus window_tree_host_in_second_client(
      aura::CreateInitParamsForTopLevel(&second_client));
  window_tree_host_in_second_client.InitHost();
  window_tree_host_in_second_client.window()->Show();
  aura::Window* second_client_child = NewVisibleWindow(
      window_tree_host_in_second_client.window(), &second_client);
  std::unique_ptr<aura::WindowPortMus> window_port_mus =
      base::MakeUnique<aura::WindowPortMus>(&second_client,
                                            aura::WindowMusType::LOCAL);
  // Create the transient without a parent, set transient parent, then add.
  aura::Window* transient = NewVisibleWindow(nullptr, &second_client);
  aura::client::TransientWindowClient* transient_window_client =
      aura::client::GetTransientWindowClient();
  transient_window_client->AddTransientChild(second_client_child, transient);
  second_client_child->AddChild(transient);

  // Wait for the top-level to appear in the window manager.
  ASSERT_TRUE(delegate.QuitOnCreate());
  aura::Window* top_level_in_wm = delegate.created_window();

  // Makes sure the window manager sees the same structure and the transient
  // parent is connected correctly.
  ASSERT_TRUE(WaitForTreeSizeToMatch(top_level_in_wm, 3u));
  ASSERT_EQ(1u, top_level_in_wm->children().size());
  aura::Window* second_client_child_in_wm = top_level_in_wm->children()[0];
  ASSERT_EQ(1u, second_client_child_in_wm->children().size());
  aura::Window* transient_in_wm = second_client_child_in_wm->children()[0];
  ASSERT_EQ(second_client_child_in_wm,
            transient_window_client->GetTransientParent(transient_in_wm));
}

}  // namespace ws
}  // namespace ui
