diff options
author | sky <sky@chromium.org> | 2016-01-29 11:13:20 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-01-29 19:14:23 +0000 |
commit | d69f14eddfa376290c50a76b18163c727b38c7c4 (patch) | |
tree | 9ac6dd3a826d34adfbad1bec980cb02c0e738df5 /components/mus | |
parent | 1f6ff1834b00890762f4bea1a979ab62a3cb6a30 (diff) | |
download | chromium_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.cc | 26 | ||||
-rw-r--r-- | components/mus/mus_app.h | 8 | ||||
-rw-r--r-- | components/mus/public/cpp/lib/window_tree_client_impl.cc | 27 | ||||
-rw-r--r-- | components/mus/public/cpp/lib/window_tree_client_impl.h | 3 | ||||
-rw-r--r-- | components/mus/public/cpp/window_tree_connection.h | 14 | ||||
-rw-r--r-- | components/mus/public/cpp/window_tree_delegate.h | 2 | ||||
-rw-r--r-- | components/mus/public/interfaces/window_tree.mojom | 4 | ||||
-rw-r--r-- | components/mus/ws/BUILD.gn | 2 | ||||
-rw-r--r-- | components/mus/ws/connection_manager.cc | 24 | ||||
-rw-r--r-- | components/mus/ws/connection_manager.h | 7 | ||||
-rw-r--r-- | components/mus/ws/window_manager_client_apptest.cc | 105 | ||||
-rw-r--r-- | components/mus/ws/window_tree_factory.cc | 37 | ||||
-rw-r--r-- | components/mus/ws/window_tree_factory.h | 40 | ||||
-rw-r--r-- | components/mus/ws/window_tree_impl.cc | 10 |
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); |