summaryrefslogtreecommitdiffstats
path: root/components/mus
diff options
context:
space:
mode:
authorsky <sky@chromium.org>2016-01-29 11:13:20 -0800
committerCommit bot <commit-bot@chromium.org>2016-01-29 19:14:23 +0000
commitd69f14eddfa376290c50a76b18163c727b38c7c4 (patch)
tree9ac6dd3a826d34adfbad1bec980cb02c0e738df5 /components/mus
parent1f6ff1834b00890762f4bea1a979ab62a3cb6a30 (diff)
downloadchromium_src-d69f14eddfa376290c50a76b18163c727b38c7c4.zip
chromium_src-d69f14eddfa376290c50a76b18163c727b38c7c4.tar.gz
chromium_src-d69f14eddfa376290c50a76b18163c727b38c7c4.tar.bz2
Adds WindowTreeFactory to mus
This is used to connect directly to mus and create top level windows. This means you can create a WindowTreeConnection (the client lib) and it can immediately create top level windows. After this patch WindowManagerDeprecated is no longer used. I'll remove it next. BUG=566155 TEST=covered by tests R=ben@chromium.org Review URL: https://codereview.chromium.org/1648163002 Cr-Commit-Position: refs/heads/master@{#372392}
Diffstat (limited to 'components/mus')
-rw-r--r--components/mus/mus_app.cc26
-rw-r--r--components/mus/mus_app.h8
-rw-r--r--components/mus/public/cpp/lib/window_tree_client_impl.cc27
-rw-r--r--components/mus/public/cpp/lib/window_tree_client_impl.h3
-rw-r--r--components/mus/public/cpp/window_tree_connection.h14
-rw-r--r--components/mus/public/cpp/window_tree_delegate.h2
-rw-r--r--components/mus/public/interfaces/window_tree.mojom4
-rw-r--r--components/mus/ws/BUILD.gn2
-rw-r--r--components/mus/ws/connection_manager.cc24
-rw-r--r--components/mus/ws/connection_manager.h7
-rw-r--r--components/mus/ws/window_manager_client_apptest.cc105
-rw-r--r--components/mus/ws/window_tree_factory.cc37
-rw-r--r--components/mus/ws/window_tree_factory.h40
-rw-r--r--components/mus/ws/window_tree_impl.cc10
14 files changed, 267 insertions, 42 deletions
diff --git a/components/mus/mus_app.cc b/components/mus/mus_app.cc
index fe4055e..f645d58 100644
--- a/components/mus/mus_app.cc
+++ b/components/mus/mus_app.cc
@@ -11,6 +11,7 @@
#include "components/mus/ws/client_connection.h"
#include "components/mus/ws/connection_manager.h"
#include "components/mus/ws/forwarding_window_manager.h"
+#include "components/mus/ws/window_tree_factory.h"
#include "components/mus/ws/window_tree_host_connection.h"
#include "components/mus/ws/window_tree_host_impl.h"
#include "components/mus/ws/window_tree_impl.h"
@@ -39,9 +40,11 @@ using mus::mojom::Gpu;
namespace mus {
+// TODO(sky): this is a pretty typical pattern, make it easier to do.
struct MandolineUIServicesApp::PendingRequest {
scoped_ptr<mojo::InterfaceRequest<mojom::DisplayManager>> dm_request;
scoped_ptr<mojo::InterfaceRequest<mojom::WindowManagerDeprecated>> wm_request;
+ scoped_ptr<mojo::InterfaceRequest<mojom::WindowTreeFactory>> wtf_request;
};
MandolineUIServicesApp::MandolineUIServicesApp()
@@ -94,6 +97,7 @@ bool MandolineUIServicesApp::ConfigureIncomingConnection(
connection->AddService<Gpu>(this);
connection->AddService<mojom::DisplayManager>(this);
connection->AddService<mojom::WindowManagerDeprecated>(this);
+ connection->AddService<mojom::WindowTreeFactory>(this);
connection->AddService<WindowTreeHostFactory>(this);
return true;
}
@@ -104,8 +108,10 @@ void MandolineUIServicesApp::OnFirstRootConnectionCreated() {
for (auto& request : requests) {
if (request->dm_request)
Create(nullptr, std::move(*request->dm_request));
- else
+ else if (request->wm_request)
Create(nullptr, std::move(*request->wm_request));
+ else
+ Create(nullptr, std::move(*request->wtf_request));
}
}
@@ -161,6 +167,24 @@ void MandolineUIServicesApp::Create(
void MandolineUIServicesApp::Create(
ApplicationConnection* connection,
+ InterfaceRequest<mojom::WindowTreeFactory> request) {
+ if (!connection_manager_->has_tree_host_connections()) {
+ scoped_ptr<PendingRequest> pending_request(new PendingRequest);
+ pending_request->wtf_request.reset(
+ new mojo::InterfaceRequest<mojom::WindowTreeFactory>(
+ std::move(request)));
+ pending_requests_.push_back(std::move(pending_request));
+ return;
+ }
+ if (!window_tree_factory_) {
+ window_tree_factory_.reset(
+ new ws::WindowTreeFactory(connection_manager_.get()));
+ }
+ window_tree_factory_->AddBinding(std::move(request));
+}
+
+void MandolineUIServicesApp::Create(
+ ApplicationConnection* connection,
InterfaceRequest<WindowTreeHostFactory> request) {
factory_bindings_.AddBinding(this, std::move(request));
}
diff --git a/components/mus/mus_app.h b/components/mus/mus_app.h
index 29e0822..6e55751 100644
--- a/components/mus/mus_app.h
+++ b/components/mus/mus_app.h
@@ -39,6 +39,7 @@ class SurfacesState;
namespace ws {
class ConnectionManager;
class ForwardingWindowManager;
+class WindowTreeFactory;
}
class MandolineUIServicesApp
@@ -46,6 +47,7 @@ class MandolineUIServicesApp
public ws::ConnectionManagerDelegate,
public mojo::InterfaceFactory<mojom::DisplayManager>,
public mojo::InterfaceFactory<mojom::WindowManagerDeprecated>,
+ public mojo::InterfaceFactory<mojom::WindowTreeFactory>,
public mojo::InterfaceFactory<mojom::WindowTreeHostFactory>,
public mojo::InterfaceFactory<mojom::Gpu>,
public mojom::WindowTreeHostFactory {
@@ -82,6 +84,11 @@ class MandolineUIServicesApp
mojo::ApplicationConnection* connection,
mojo::InterfaceRequest<mojom::WindowManagerDeprecated> request) override;
+ // mojo::InterfaceFactory<mojom::WindowTreeFactory>:
+ void Create(
+ mojo::ApplicationConnection* connection,
+ mojo::InterfaceRequest<mojom::WindowTreeFactory> request) override;
+
// mojo::InterfaceFactory<mojom::WindowTreeHostFactory>:
void Create(
mojo::ApplicationConnection* connection,
@@ -108,6 +115,7 @@ class MandolineUIServicesApp
mojo::TracingImpl tracing_;
using PendingRequests = std::vector<scoped_ptr<PendingRequest>>;
PendingRequests pending_requests_;
+ scoped_ptr<ws::WindowTreeFactory> window_tree_factory_;
// Surfaces
scoped_refptr<SurfacesState> surfaces_state_;
diff --git a/components/mus/public/cpp/lib/window_tree_client_impl.cc b/components/mus/public/cpp/lib/window_tree_client_impl.cc
index 3ba759b..8e1907a 100644
--- a/components/mus/public/cpp/lib/window_tree_client_impl.cc
+++ b/components/mus/public/cpp/lib/window_tree_client_impl.cc
@@ -82,6 +82,14 @@ Window* BuildWindowTree(WindowTreeClientImpl* client,
return root;
}
+WindowTreeConnection* WindowTreeConnection::Create(WindowTreeDelegate* delegate,
+ mojo::ApplicationImpl* app) {
+ WindowTreeClientImpl* client =
+ new WindowTreeClientImpl(delegate, nullptr, nullptr);
+ client->ConnectViaWindowTreeFactory(app);
+ return client;
+}
+
WindowTreeConnection* WindowTreeConnection::Create(
WindowTreeDelegate* delegate,
mojo::InterfaceRequest<mojom::WindowTreeClient> request,
@@ -152,6 +160,21 @@ WindowTreeClientImpl::~WindowTreeClientImpl() {
delegate_->OnConnectionLost(this);
}
+void WindowTreeClientImpl::ConnectViaWindowTreeFactory(
+ mojo::ApplicationImpl* app) {
+ // Clients created with no root shouldn't delete automatically.
+ delete_on_no_roots_ = false;
+
+ // The connection id doesn't really matter, we use 101 purely for debugging.
+ connection_id_ = 101;
+
+ mojom::WindowTreeFactoryPtr factory;
+ app->ConnectToService("mojo:mus", &factory);
+ factory->CreateWindowTree(GetProxy(&tree_ptr_),
+ binding_.CreateInterfacePtrAndBind());
+ tree_ = tree_ptr_.get();
+}
+
void WindowTreeClientImpl::WaitForEmbed() {
DCHECK(roots_.empty());
// OnEmbed() is the first function called.
@@ -407,6 +430,8 @@ Window* WindowTreeClientImpl::NewWindowImpl(
if (properties) {
transport_properties =
mojo::Map<mojo::String, mojo::Array<uint8_t>>::From(*properties);
+ } else {
+ transport_properties.mark_non_null();
}
if (type == NewWindowType::CHILD) {
tree_->NewWindow(change_id, window->id(), std::move(transport_properties));
@@ -423,6 +448,8 @@ void WindowTreeClientImpl::OnEmbedImpl(mojom::WindowTree* window_tree,
mojom::WindowDataPtr root_data,
Id focused_window_id,
uint32_t access_policy) {
+ // WARNING: this is only called if WindowTreeClientImpl was created as the
+ // result of an embedding.
tree_ = window_tree;
connection_id_ = connection_id;
is_embed_root_ =
diff --git a/components/mus/public/cpp/lib/window_tree_client_impl.h b/components/mus/public/cpp/lib/window_tree_client_impl.h
index 4d86fef..36432ea 100644
--- a/components/mus/public/cpp/lib/window_tree_client_impl.h
+++ b/components/mus/public/cpp/lib/window_tree_client_impl.h
@@ -44,6 +44,9 @@ class WindowTreeClientImpl : public WindowTreeConnection,
mojo::InterfaceRequest<mojom::WindowTreeClient> request);
~WindowTreeClientImpl() override;
+ // Establishes the connection by way of the WindowTreeFactory.
+ void ConnectViaWindowTreeFactory(mojo::ApplicationImpl* app);
+
// Wait for OnEmbed(), returning when done.
void WaitForEmbed();
diff --git a/components/mus/public/cpp/window_tree_connection.h b/components/mus/public/cpp/window_tree_connection.h
index f9b1740..98c6b37 100644
--- a/components/mus/public/cpp/window_tree_connection.h
+++ b/components/mus/public/cpp/window_tree_connection.h
@@ -15,6 +15,10 @@
#include "components/mus/public/interfaces/window_tree.mojom.h"
#include "mojo/public/cpp/bindings/interface_request.h"
+namespace mojo {
+class ApplicationImpl;
+}
+
namespace mus {
class Window;
@@ -36,13 +40,19 @@ class WindowTreeConnection {
virtual ~WindowTreeConnection() {}
- // The returned WindowTreeConnection instance owns itself, and is deleted when
- // the last root is destroyed or the connection to the service is broken.
+ // Creates a WindowTreeConnection with no roots. Use this to establish a
+ // connection directly to mus and create top level windows.
+ static WindowTreeConnection* Create(WindowTreeDelegate* delegate,
+ mojo::ApplicationImpl* app);
+
+ // Creates a WindowTreeConnection to service the specified request for
+ // a WindowTreeClient. Use this to be embedded in another app.
static WindowTreeConnection* Create(
WindowTreeDelegate* delegate,
mojo::InterfaceRequest<mojom::WindowTreeClient> request,
CreateType create_type);
+ // Create a WindowTreeConnection that is going to serve as the WindowManager.
static WindowTreeConnection* CreateForWindowManager(
WindowTreeDelegate* delegate,
mojo::InterfaceRequest<mojom::WindowTreeClient> request,
diff --git a/components/mus/public/cpp/window_tree_delegate.h b/components/mus/public/cpp/window_tree_delegate.h
index dd9bb37..d51b06b 100644
--- a/components/mus/public/cpp/window_tree_delegate.h
+++ b/components/mus/public/cpp/window_tree_delegate.h
@@ -33,6 +33,8 @@ class WindowTreeDelegate {
public:
// Called when the application implementing this interface is embedded at
// |root|.
+ // NOTE: this is only invoked if the WindowTreeConnection is created with
+ // an InterfaceRequest.
virtual void OnEmbed(Window* root) = 0;
// Sent when another app is embedded in |root| (one of the roots of the
diff --git a/components/mus/public/interfaces/window_tree.mojom b/components/mus/public/interfaces/window_tree.mojom
index 1dd204e..fa5fb83 100644
--- a/components/mus/public/interfaces/window_tree.mojom
+++ b/components/mus/public/interfaces/window_tree.mojom
@@ -413,3 +413,7 @@ interface WindowManagerClient {
// the new window.
OnWmCreatedTopLevelWindow(uint32 change_id, uint32 window_id);
};
+
+interface WindowTreeFactory {
+ CreateWindowTree(WindowTree& tree_request, WindowTreeClient client);
+};
diff --git a/components/mus/ws/BUILD.gn b/components/mus/ws/BUILD.gn
index 29b317d..b64da50 100644
--- a/components/mus/ws/BUILD.gn
+++ b/components/mus/ws/BUILD.gn
@@ -51,6 +51,8 @@ source_set("lib") {
"window_finder.h",
"window_manager_access_policy.cc",
"window_manager_access_policy.h",
+ "window_tree_factory.cc",
+ "window_tree_factory.h",
"window_tree_host_connection.cc",
"window_tree_host_connection.h",
"window_tree_host_delegate.h",
diff --git a/components/mus/ws/connection_manager.cc b/components/mus/ws/connection_manager.cc
index 4f96647..428668e 100644
--- a/components/mus/ws/connection_manager.cc
+++ b/components/mus/ws/connection_manager.cc
@@ -152,19 +152,24 @@ WindowTreeImpl* ConnectionManager::EmbedAtWindow(
ServerWindow* root,
uint32_t policy_bitmask,
mojom::WindowTreeClientPtr client) {
- mojom::WindowTreePtr service_ptr;
+ mojom::WindowTreePtr tree_ptr;
ClientConnection* client_connection =
delegate_->CreateClientConnectionForEmbedAtWindow(
- this, GetProxy(&service_ptr), root, policy_bitmask,
- std::move(client));
- AddConnection(client_connection);
- client_connection->service()->Init(client_connection->client(),
- std::move(service_ptr));
+ this, GetProxy(&tree_ptr), root, policy_bitmask, std::move(client));
+ AddConnection(make_scoped_ptr(client_connection), std::move(tree_ptr));
OnConnectionMessagedClient(client_connection->service()->id());
-
return client_connection->service();
}
+void ConnectionManager::AddConnection(
+ scoped_ptr<ClientConnection> owned_connection,
+ mojom::WindowTreePtr tree_ptr) {
+ ClientConnection* connection = owned_connection.release();
+ CHECK_EQ(0u, connection_map_.count(connection->service()->id()));
+ connection_map_[connection->service()->id()] = connection;
+ connection->service()->Init(connection->client(), std::move(tree_ptr));
+}
+
WindowTreeImpl* ConnectionManager::GetConnection(
ConnectionSpecificId connection_id) {
ConnectionMap::iterator i = connection_map_.find(connection_id);
@@ -441,11 +446,6 @@ void ConnectionManager::FinishOperation() {
current_operation_ = nullptr;
}
-void ConnectionManager::AddConnection(ClientConnection* connection) {
- DCHECK_EQ(0u, connection_map_.count(connection->service()->id()));
- connection_map_[connection->service()->id()] = connection;
-}
-
void ConnectionManager::MaybeUpdateNativeCursor(ServerWindow* window) {
// This can be null in unit tests.
WindowTreeHostImpl* impl = GetWindowTreeHostByWindow(window);
diff --git a/components/mus/ws/connection_manager.h b/components/mus/ws/connection_manager.h
index 9b7d5f4..343db9c 100644
--- a/components/mus/ws/connection_manager.h
+++ b/components/mus/ws/connection_manager.h
@@ -81,6 +81,10 @@ class ConnectionManager : public ServerWindowDelegate,
uint32_t policy_bitmask,
mojom::WindowTreeClientPtr client);
+ // Adds |connection| to internal maps.
+ void AddConnection(scoped_ptr<ClientConnection> owned_connection,
+ mojom::WindowTreePtr tree_ptr);
+
// Returns the connection by id.
WindowTreeImpl* GetConnection(ConnectionSpecificId connection_id);
@@ -221,9 +225,6 @@ class ConnectionManager : public ServerWindowDelegate,
current_operation_->source_connection_id() == connection_id;
}
- // Adds |connection| to internal maps.
- void AddConnection(ClientConnection* connection);
-
// Run in response to events which may cause us to change the native cursor.
void MaybeUpdateNativeCursor(ServerWindow* window);
diff --git a/components/mus/ws/window_manager_client_apptest.cc b/components/mus/ws/window_manager_client_apptest.cc
index f1d1db2..a35e478 100644
--- a/components/mus/ws/window_manager_client_apptest.cc
+++ b/components/mus/ws/window_manager_client_apptest.cc
@@ -33,6 +33,30 @@ int ValidIndexOf(const Window::Children& windows, Window* window) {
return (it != windows.end()) ? (it - windows.begin()) : -1;
}
+class TestWindowManagerDelegate : public WindowManagerDelegate {
+ public:
+ TestWindowManagerDelegate() {}
+ ~TestWindowManagerDelegate() override {}
+
+ // WindowManagerDelegate:
+ void SetWindowManagerClient(WindowManagerClient* client) override {}
+ bool OnWmSetBounds(Window* window, gfx::Rect* bounds) override {
+ return false;
+ }
+ bool OnWmSetProperty(Window* window,
+ const std::string& name,
+ scoped_ptr<std::vector<uint8_t>>* new_data) override {
+ return true;
+ }
+ Window* OnWmCreateTopLevelWindow(
+ std::map<std::string, std::vector<uint8_t>>* properties) override {
+ return nullptr;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestWindowManagerDelegate);
+};
+
class BoundsChangeObserver : public WindowObserver {
public:
explicit BoundsChangeObserver(Window* window) : window_(window) {
@@ -381,27 +405,6 @@ TEST_F(WindowServerTest, SetBounds) {
// Verifies that bounds changes applied to a window owned by a different
// connection can be refused.
TEST_F(WindowServerTest, SetBoundsSecurity) {
- class TestWindowManagerDelegate : public WindowManagerDelegate {
- public:
- TestWindowManagerDelegate() {}
- ~TestWindowManagerDelegate() override {}
-
- // WindowManagerDelegate:
- void SetWindowManagerClient(WindowManagerClient* client) override {}
- bool OnWmSetBounds(Window* window, gfx::Rect* bounds) override {
- return false;
- }
- bool OnWmSetProperty(Window* window,
- const std::string& name,
- scoped_ptr<std::vector<uint8_t>>* new_data) override {
- return true;
- }
- Window* OnWmCreateTopLevelWindow(
- std::map<std::string, std::vector<uint8_t>>* properties) override {
- return nullptr;
- }
- };
-
TestWindowManagerDelegate wm_delegate;
set_window_manager_delegate(&wm_delegate);
@@ -1107,5 +1110,65 @@ TEST_F(WindowServerTest, ClientAreaChanged) {
GetFirstRoot(embedded_connection)->client_area());
}
+class EstablishConnectionViaFactoryDelegate : public TestWindowManagerDelegate {
+ public:
+ explicit EstablishConnectionViaFactoryDelegate(
+ WindowTreeConnection* connection)
+ : connection_(connection), run_loop_(nullptr), created_window_(nullptr) {}
+ ~EstablishConnectionViaFactoryDelegate() override {}
+
+ bool QuitOnCreate() {
+ if (run_loop_)
+ return false;
+
+ created_window_ = nullptr;
+ run_loop_.reset(new base::RunLoop);
+ run_loop_->Run();
+ run_loop_.reset();
+ return created_window_ != nullptr;
+ }
+
+ Window* created_window() { return created_window_; }
+
+ // WindowManagerDelegate:
+ Window* OnWmCreateTopLevelWindow(
+ std::map<std::string, std::vector<uint8_t>>* properties) override {
+ created_window_ = connection_->NewWindow(properties);
+ (*connection_->GetRoots().begin())->AddChild(created_window_);
+ if (run_loop_)
+ run_loop_->Quit();
+ return created_window_;
+ }
+
+ private:
+ WindowTreeConnection* connection_;
+ scoped_ptr<base::RunLoop> run_loop_;
+ Window* created_window_;
+
+ DISALLOW_COPY_AND_ASSIGN(EstablishConnectionViaFactoryDelegate);
+};
+
+TEST_F(WindowServerTest, EstablishConnectionViaFactory) {
+ EstablishConnectionViaFactoryDelegate delegate(window_manager());
+ set_window_manager_delegate(&delegate);
+ scoped_ptr<WindowTreeConnection> second_connection(
+ WindowTreeConnection::Create(this, application_impl()));
+ Window* window_in_second_connection =
+ second_connection->NewTopLevelWindow(nullptr);
+ ASSERT_TRUE(window_in_second_connection);
+ ASSERT_TRUE(second_connection->GetRoots().count(window_in_second_connection) >
+ 0);
+ // Wait for the window to appear in the wm.
+ ASSERT_TRUE(delegate.QuitOnCreate());
+
+ 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.
+ window_in_wm->SetBounds(gfx::Rect(1, 11, 12, 101));
+ ASSERT_TRUE(WaitForBoundsToChange(window_in_second_connection));
+ EXPECT_EQ(gfx::Rect(1, 11, 12, 101), window_in_second_connection->bounds());
+}
+
} // namespace ws
} // namespace mus
diff --git a/components/mus/ws/window_tree_factory.cc b/components/mus/ws/window_tree_factory.cc
new file mode 100644
index 0000000..8c5fecd
--- /dev/null
+++ b/components/mus/ws/window_tree_factory.cc
@@ -0,0 +1,37 @@
+// Copyright 2016 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 "components/mus/ws/window_tree_factory.h"
+
+#include "components/mus/ws/client_connection.h"
+#include "components/mus/ws/connection_manager.h"
+#include "components/mus/ws/window_tree_impl.h"
+
+namespace mus {
+namespace ws {
+
+WindowTreeFactory::WindowTreeFactory(ConnectionManager* connection_manager)
+ : connection_manager_(connection_manager) {}
+
+WindowTreeFactory::~WindowTreeFactory() {}
+
+void WindowTreeFactory::AddBinding(
+ mojo::InterfaceRequest<mus::mojom::WindowTreeFactory> request) {
+ binding_.AddBinding(this, std::move(request));
+}
+
+void WindowTreeFactory::CreateWindowTree(
+ mojo::InterfaceRequest<mojom::WindowTree> tree_request,
+ mojom::WindowTreeClientPtr client) {
+ scoped_ptr<ws::WindowTreeImpl> service(new ws::WindowTreeImpl(
+ connection_manager_, nullptr, mojom::WindowTree::kAccessPolicyDefault));
+ scoped_ptr<ws::DefaultClientConnection> client_connection(
+ new ws::DefaultClientConnection(std::move(service), connection_manager_,
+ std::move(tree_request),
+ std::move(client)));
+ connection_manager_->AddConnection(std::move(client_connection), nullptr);
+}
+
+} // namespace ws
+} // namespace mus
diff --git a/components/mus/ws/window_tree_factory.h b/components/mus/ws/window_tree_factory.h
new file mode 100644
index 0000000..7e77773
--- /dev/null
+++ b/components/mus/ws/window_tree_factory.h
@@ -0,0 +1,40 @@
+// Copyright 2016 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.
+
+#ifndef COMPONENTS_MUS_WS_WINDOW_TREE_FACTORY_H_
+#define COMPONENTS_MUS_WS_WINDOW_TREE_FACTORY_H_
+
+#include "base/macros.h"
+#include "components/mus/public/interfaces/window_tree.mojom.h"
+#include "mojo/common/weak_binding_set.h"
+
+namespace mus {
+namespace ws {
+
+class ConnectionManager;
+
+class WindowTreeFactory : public mus::mojom::WindowTreeFactory {
+ public:
+ explicit WindowTreeFactory(ConnectionManager* connection_manager);
+ ~WindowTreeFactory() override;
+
+ void AddBinding(
+ mojo::InterfaceRequest<mus::mojom::WindowTreeFactory> request);
+
+ // mus::mojom::WindowTreeFactory:
+ void CreateWindowTree(mojo::InterfaceRequest<mojom::WindowTree> tree_request,
+ mojom::WindowTreeClientPtr client) override;
+
+ private:
+ ConnectionManager* connection_manager_;
+
+ mojo::WeakBindingSet<mus::mojom::WindowTreeFactory> binding_;
+
+ DISALLOW_COPY_AND_ASSIGN(WindowTreeFactory);
+};
+
+} // namespace ws
+} // namespace mus
+
+#endif // COMPONENTS_MUS_WS_WINDOW_TREE_FACTORY_H_
diff --git a/components/mus/ws/window_tree_impl.cc b/components/mus/ws/window_tree_impl.cc
index 3cdb88c..0b666c7 100644
--- a/components/mus/ws/window_tree_impl.cc
+++ b/components/mus/ws/window_tree_impl.cc
@@ -73,9 +73,9 @@ WindowTreeImpl::WindowTreeImpl(ConnectionManager* connection_manager,
event_source_host_(nullptr),
is_embed_root_(false),
window_manager_internal_(nullptr) {
- CHECK(root);
- roots_.insert(root);
- if (root->GetRoot() == root) {
+ if (root)
+ roots_.insert(root);
+ if (root && root->GetRoot() == root) {
access_policy_.reset(new WindowManagerAccessPolicy(id_, this));
is_embed_root_ = true;
} else {
@@ -92,6 +92,10 @@ void WindowTreeImpl::Init(mojom::WindowTreeClient* client,
mojom::WindowTreePtr tree) {
DCHECK(!client_);
client_ = client;
+
+ if (roots_.empty())
+ return;
+
std::vector<const ServerWindow*> to_send;
CHECK_EQ(1u, roots_.size());
GetUnknownWindowsFrom(*roots_.begin(), &to_send);