Adds Embed() variant to ViewManagerService that takes ViewManagerClient
This is for situations where an app wants to directly supply the
ViewManagerClient implementation.
R=msw@chromium.org
Review URL: https://codereview.chromium.org/905083002
diff --git a/mojo/services/view_manager/public/cpp/lib/view.cc b/mojo/services/view_manager/public/cpp/lib/view.cc
index 4a70072..1e8b2b0 100644
--- a/mojo/services/view_manager/public/cpp/lib/view.cc
+++ b/mojo/services/view_manager/public/cpp/lib/view.cc
@@ -379,6 +379,10 @@
->Embed(url, id_, services.Pass(), exposed_services.Pass());
}
+void View::Embed(ViewManagerClientPtr client) {
+ static_cast<ViewManagerClientImpl*>(manager_)->Embed(id_, client.Pass());
+}
+
////////////////////////////////////////////////////////////////////////////////
// View, protected:
diff --git a/mojo/services/view_manager/public/cpp/lib/view_manager_client_impl.cc b/mojo/services/view_manager/public/cpp/lib/view_manager_client_impl.cc
index 3fffac2..574d300 100644
--- a/mojo/services/view_manager/public/cpp/lib/view_manager_client_impl.cc
+++ b/mojo/services/view_manager/public/cpp/lib/view_manager_client_impl.cc
@@ -204,8 +204,13 @@
InterfaceRequest<ServiceProvider> services,
ServiceProviderPtr exposed_services) {
DCHECK(service_);
- service_->Embed(url, view_id, services.Pass(), exposed_services.Pass(),
- ActionCompletedCallback());
+ service_->EmbedUrl(url, view_id, services.Pass(), exposed_services.Pass(),
+ ActionCompletedCallback());
+}
+
+void ViewManagerClientImpl::Embed(Id view_id, ViewManagerClientPtr client) {
+ DCHECK(service_);
+ service_->Embed(view_id, client.Pass(), ActionCompletedCallback());
}
void ViewManagerClientImpl::AddView(View* view) {
diff --git a/mojo/services/view_manager/public/cpp/lib/view_manager_client_impl.h b/mojo/services/view_manager/public/cpp/lib/view_manager_client_impl.h
index b3dd1fd..c3a2ad5 100644
--- a/mojo/services/view_manager/public/cpp/lib/view_manager_client_impl.h
+++ b/mojo/services/view_manager/public/cpp/lib/view_manager_client_impl.h
@@ -64,6 +64,7 @@
Id view_id,
InterfaceRequest<ServiceProvider> services,
ServiceProviderPtr exposed_services);
+ void Embed(Id view_id, ViewManagerClientPtr client);
void set_change_acked_callback(const base::Callback<void(void)>& callback) {
change_acked_callback_ = callback;
diff --git a/mojo/services/view_manager/public/cpp/view.h b/mojo/services/view_manager/public/cpp/view.h
index 07bc5b0..d888ef0 100644
--- a/mojo/services/view_manager/public/cpp/view.h
+++ b/mojo/services/view_manager/public/cpp/view.h
@@ -122,11 +122,12 @@
// Focus.
void SetFocus();
- // Embedding.
+ // Embedding. See view_manager.mojom for details.
void Embed(const String& url);
void Embed(const String& url,
InterfaceRequest<ServiceProvider> services,
ServiceProviderPtr exposed_services);
+ void Embed(ViewManagerClientPtr client);
protected:
// This class is subclassed only by test classes that provide a public ctor.
diff --git a/mojo/services/view_manager/public/interfaces/view_manager.mojom b/mojo/services/view_manager/public/interfaces/view_manager.mojom
index 961b783..86560ba 100644
--- a/mojo/services/view_manager/public/interfaces/view_manager.mojom
+++ b/mojo/services/view_manager/public/interfaces/view_manager.mojom
@@ -105,10 +105,16 @@
// Shows the surface in the specified view.
SetViewSurfaceId(uint32 view_id, SurfaceId surface_id) => (bool success);
- // Embeds the app for |url| in the specified view. More specifically this
- // creates a new connection to the specified url, expecting to get a
- // ViewManagerClient and configures it with the root view |view|. Fails
- // if |view| was not created by this connection.
+ // A connection may grant access to a view from another connection by way of
+ // the embed functions. There are two variants of this call:
+ //
+ // . EmbedUrl: the ViewManager connects to the app at the supplied url and
+ // asks it for a ViewManagerClient.
+ // . With the second variant a ViewManagerClient is directly supplied.
+ //
+ // In both cases the new ViewManagerClient is configured with a root of
+ // |view_id|. The call fails if the originating connection did not create
+ // the view identified by |view_id|.
//
// A view may only be a root of one connection at a time. Subsequent calls to
// Embed() for the same view result in the view being removed from the
@@ -129,10 +135,11 @@
// if a different app is subsequently embedded at |view_id| the
// ServiceProvider connections to its client in the embedded app and any
// services it provided are not broken and continue to be valid.
- Embed(string url,
- uint32 view_id,
- ServiceProvider&? services,
- ServiceProvider? exposed_services) => (bool success);
+ EmbedUrl(string url,
+ uint32 view_id,
+ ServiceProvider&? services,
+ ServiceProvider? exposed_services) => (bool success);
+ Embed(uint32 view_id, ViewManagerClient client) => (bool success);
};
// Changes to views are not sent to the connection that originated the
diff --git a/services/view_manager/connection_manager.cc b/services/view_manager/connection_manager.cc
index ce2bb9c..8e06304 100644
--- a/services/view_manager/connection_manager.cc
+++ b/services/view_manager/connection_manager.cc
@@ -182,6 +182,25 @@
OnConnectionMessagedClient(client_connection->service()->id());
}
+void ConnectionManager::EmbedAtView(mojo::ConnectionSpecificId creator_id,
+ const ViewId& view_id,
+ mojo::ViewManagerClientPtr client) {
+ std::string creator_url;
+ ConnectionMap::const_iterator it = connection_map_.find(creator_id);
+ if (it != connection_map_.end())
+ creator_url = it->second->service()->url();
+
+ mojo::ViewManagerServicePtr service_ptr;
+ ClientConnection* client_connection =
+ delegate_->CreateClientConnectionForEmbedAtView(
+ this, GetProxy(&service_ptr), creator_id, creator_url, view_id,
+ client.Pass());
+ AddConnection(client_connection);
+ client_connection->service()->Init(client_connection->client(),
+ service_ptr.Pass(), nullptr, nullptr);
+ OnConnectionMessagedClient(client_connection->service()->id());
+}
+
ViewManagerServiceImpl* ConnectionManager::GetConnection(
ConnectionSpecificId connection_id) {
ConnectionMap::iterator i = connection_map_.find(connection_id);
diff --git a/services/view_manager/connection_manager.h b/services/view_manager/connection_manager.h
index 0515236..cb61806 100644
--- a/services/view_manager/connection_manager.h
+++ b/services/view_manager/connection_manager.h
@@ -82,6 +82,9 @@
const ViewId& view_id,
mojo::InterfaceRequest<mojo::ServiceProvider> services,
mojo::ServiceProviderPtr exposed_services);
+ void EmbedAtView(mojo::ConnectionSpecificId creator_id,
+ const ViewId& view_id,
+ mojo::ViewManagerClientPtr client);
// Returns the connection by id.
ViewManagerServiceImpl* GetConnection(
diff --git a/services/view_manager/connection_manager_delegate.h b/services/view_manager/connection_manager_delegate.h
index 652f513..fb4612f 100644
--- a/services/view_manager/connection_manager_delegate.h
+++ b/services/view_manager/connection_manager_delegate.h
@@ -33,6 +33,13 @@
const std::string& creator_url,
const std::string& url,
const ViewId& root_id) = 0;
+ virtual ClientConnection* CreateClientConnectionForEmbedAtView(
+ ConnectionManager* connection_manager,
+ mojo::InterfaceRequest<mojo::ViewManagerService> service_request,
+ mojo::ConnectionSpecificId creator_id,
+ const std::string& creator_url,
+ const ViewId& root_id,
+ mojo::ViewManagerClientPtr view_manager_client) = 0;
protected:
virtual ~ConnectionManagerDelegate() {}
diff --git a/services/view_manager/view_manager_app.cc b/services/view_manager/view_manager_app.cc
index 42548a7..29bd799 100644
--- a/services/view_manager/view_manager_app.cc
+++ b/services/view_manager/view_manager_app.cc
@@ -72,6 +72,20 @@
service_request.Pass(), client.Pass());
}
+ClientConnection* ViewManagerApp::CreateClientConnectionForEmbedAtView(
+ ConnectionManager* connection_manager,
+ mojo::InterfaceRequest<mojo::ViewManagerService> service_request,
+ mojo::ConnectionSpecificId creator_id,
+ const std::string& creator_url,
+ const ViewId& root_id,
+ mojo::ViewManagerClientPtr view_manager_client) {
+ scoped_ptr<ViewManagerServiceImpl> service(new ViewManagerServiceImpl(
+ connection_manager, creator_id, creator_url, std::string(), root_id));
+ return new DefaultClientConnection(service.Pass(), connection_manager,
+ service_request.Pass(),
+ view_manager_client.Pass());
+}
+
void ViewManagerApp::Create(ApplicationConnection* connection,
InterfaceRequest<ViewManagerService> request) {
if (connection_manager_->has_window_manager_client_connection()) {
diff --git a/services/view_manager/view_manager_app.h b/services/view_manager/view_manager_app.h
index 7d42f24..8ef6f3e 100644
--- a/services/view_manager/view_manager_app.h
+++ b/services/view_manager/view_manager_app.h
@@ -44,6 +44,13 @@
const std::string& creator_url,
const std::string& url,
const ViewId& root_id) override;
+ ClientConnection* CreateClientConnectionForEmbedAtView(
+ ConnectionManager* connection_manager,
+ mojo::InterfaceRequest<mojo::ViewManagerService> service_request,
+ mojo::ConnectionSpecificId creator_id,
+ const std::string& creator_url,
+ const ViewId& root_id,
+ mojo::ViewManagerClientPtr view_manager_client) override;
// mojo::InterfaceFactory<mojo::ViewManagerService>:
void Create(
diff --git a/services/view_manager/view_manager_service_apptest.cc b/services/view_manager/view_manager_service_apptest.cc
index 2389291..ccd97c7 100644
--- a/services/view_manager/view_manager_service_apptest.cc
+++ b/services/view_manager/view_manager_service_apptest.cc
@@ -80,11 +80,24 @@
return result == ERROR_CODE_NONE;
}
-bool Embed(ViewManagerService* vm, Id root_id) {
+bool EmbedUrl(ViewManagerService* vm, Id root_id) {
bool result = false;
base::RunLoop run_loop;
{
- vm->Embed("mojo:view_manager_service_apptests", root_id, nullptr, nullptr,
+ vm->EmbedUrl("mojo:view_manager_service_apptests", root_id, nullptr,
+ nullptr, base::Bind(&BoolResultCallback, &run_loop, &result));
+ }
+ run_loop.Run();
+ return result;
+}
+
+bool Embed(ViewManagerService* vm,
+ Id root_id,
+ mojo::ViewManagerClientPtr client) {
+ bool result = false;
+ base::RunLoop run_loop;
+ {
+ vm->Embed(root_id, client.Pass(),
base::Bind(&BoolResultCallback, &run_loop, &result));
}
run_loop.Run();
@@ -417,7 +430,7 @@
scoped_ptr<ViewManagerClientImpl> EstablishConnectionViaEmbed(
ViewManagerService* owner,
Id root_id) {
- if (!Embed(owner, root_id)) {
+ if (!EmbedUrl(owner, root_id)) {
ADD_FAILURE() << "Embed() failed";
return nullptr;
}
@@ -1321,7 +1334,6 @@
}
TEST_F(ViewManagerServiceAppTest, SetViewProperty) {
- // Create 1 and 2 in the first connection and parent both to the root.
ASSERT_TRUE(CreateView(vm1(), BuildViewId(1, 1)));
ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(false));
@@ -1450,6 +1462,19 @@
EXPECT_FALSE(HasClonedView(views));
}
+// Verifies Embed() works when supplying a ViewManagerClient.
+TEST_F(ViewManagerServiceAppTest, EmbedSupplyingViewManagerClient) {
+ ASSERT_TRUE(CreateView(vm1(), BuildViewId(1, 1)));
+
+ ViewManagerClientImpl client2;
+ mojo::ViewManagerClientPtr client2_ptr;
+ mojo::Binding<ViewManagerClient> client2_binding(&client2, &client2_ptr);
+ ASSERT_TRUE(Embed(vm1(), BuildViewId(1, 1), client2_ptr.Pass()));
+ client2.WaitForOnEmbed();
+ EXPECT_EQ("OnEmbed creator=mojo:window_manager",
+ SingleChangeToDescription(*client2.tracker()->changes()));
+}
+
// TODO(sky): need to better track changes to initial connection. For example,
// that SetBounsdViews/AddView and the like don't result in messages to the
// originating connection.
diff --git a/services/view_manager/view_manager_service_impl.cc b/services/view_manager/view_manager_service_impl.cc
index 7dc4d3b..0c8a583 100644
--- a/services/view_manager/view_manager_service_impl.cc
+++ b/services/view_manager/view_manager_service_impl.cc
@@ -140,30 +140,26 @@
return true;
}
-bool ViewManagerServiceImpl::Embed(const std::string& url,
- const ViewId& view_id,
- InterfaceRequest<ServiceProvider> services,
- ServiceProviderPtr exposed_services) {
- const ServerView* view = GetView(view_id);
- if (!view || !access_policy_->CanEmbed(view))
+bool ViewManagerServiceImpl::EmbedUrl(
+ const std::string& url,
+ const ViewId& view_id,
+ InterfaceRequest<ServiceProvider> services,
+ ServiceProviderPtr exposed_services) {
+ if (!PrepareForEmbed(view_id))
return false;
-
- // Only allow a node to be the root for one connection.
- ViewManagerServiceImpl* existing_owner =
- connection_manager_->GetConnectionWithRoot(view_id);
-
- ConnectionManager::ScopedChange change(this, connection_manager_, true);
- RemoveChildrenAsPartOfEmbed(view_id);
- if (existing_owner) {
- // Never message the originating connection.
- connection_manager_->OnConnectionMessagedClient(id_);
- existing_owner->RemoveRoot();
- }
connection_manager_->EmbedAtView(id_, url, view_id, services.Pass(),
exposed_services.Pass());
return true;
}
+bool ViewManagerServiceImpl::Embed(const ViewId& view_id,
+ mojo::ViewManagerClientPtr client) {
+ if (!client.get() || !PrepareForEmbed(view_id))
+ return false;
+ connection_manager_->EmbedAtView(id_, view_id, client.Pass());
+ return true;
+}
+
void ViewManagerServiceImpl::ProcessViewBoundsChanged(
const ServerView* view,
const gfx::Rect& old_bounds,
@@ -476,6 +472,25 @@
}
}
+bool ViewManagerServiceImpl::PrepareForEmbed(const ViewId& view_id) {
+ const ServerView* view = GetView(view_id);
+ if (!view || !access_policy_->CanEmbed(view))
+ return false;
+
+ // Only allow a node to be the root for one connection.
+ ViewManagerServiceImpl* existing_owner =
+ connection_manager_->GetConnectionWithRoot(view_id);
+
+ ConnectionManager::ScopedChange change(this, connection_manager_, true);
+ RemoveChildrenAsPartOfEmbed(view_id);
+ if (existing_owner) {
+ // Never message the originating connection.
+ connection_manager_->OnConnectionMessagedClient(id_);
+ existing_owner->RemoveRoot();
+ }
+ return true;
+}
+
void ViewManagerServiceImpl::CreateView(
Id transport_view_id,
const Callback<void(mojo::ErrorCode)>& callback) {
@@ -595,14 +610,21 @@
callback.Run(success);
}
-void ViewManagerServiceImpl::Embed(const String& url,
- Id transport_view_id,
- InterfaceRequest<ServiceProvider> services,
- ServiceProviderPtr exposed_services,
- const Callback<void(bool)>& callback) {
- callback.Run(Embed(url.To<std::string>(),
- ViewIdFromTransportId(transport_view_id), services.Pass(),
- exposed_services.Pass()));
+void ViewManagerServiceImpl::EmbedUrl(
+ const String& url,
+ Id transport_view_id,
+ InterfaceRequest<ServiceProvider> services,
+ ServiceProviderPtr exposed_services,
+ const Callback<void(bool)>& callback) {
+ callback.Run(EmbedUrl(url.To<std::string>(),
+ ViewIdFromTransportId(transport_view_id),
+ services.Pass(), exposed_services.Pass()));
+}
+
+void ViewManagerServiceImpl::Embed(mojo::Id transport_view_id,
+ mojo::ViewManagerClientPtr client,
+ const mojo::Callback<void(bool)>& callback) {
+ callback.Run(Embed(ViewIdFromTransportId(transport_view_id), client.Pass()));
}
bool ViewManagerServiceImpl::IsRootForAccessPolicy(const ViewId& id) const {
diff --git a/services/view_manager/view_manager_service_impl.h b/services/view_manager/view_manager_service_impl.h
index 2008d13..a315178 100644
--- a/services/view_manager/view_manager_service_impl.h
+++ b/services/view_manager/view_manager_service_impl.h
@@ -80,10 +80,11 @@
bool AddView(const ViewId& parent_id, const ViewId& child_id);
std::vector<const ServerView*> GetViewTree(const ViewId& view_id) const;
bool SetViewVisibility(const ViewId& view_id, bool visible);
- bool Embed(const std::string& url,
- const ViewId& view_id,
- mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::ServiceProviderPtr exposed_services);
+ bool EmbedUrl(const std::string& url,
+ const ViewId& view_id,
+ mojo::InterfaceRequest<mojo::ServiceProvider> services,
+ mojo::ServiceProviderPtr exposed_services);
+ bool Embed(const ViewId& view_id, mojo::ViewManagerClientPtr client);
// The following methods are invoked after the corresponding change has been
// processed. They do the appropriate bookkeeping and update the client as
@@ -167,6 +168,8 @@
// Deletes all Views we own.
void DestroyViews();
+ bool PrepareForEmbed(const ViewId& view_id);
+
// ViewManagerService:
void CreateView(
mojo::Id transport_view_id,
@@ -199,10 +202,13 @@
const mojo::String& name,
mojo::Array<uint8_t> value,
const mojo::Callback<void(bool)>& callback) override;
- void Embed(const mojo::String& url,
- mojo::Id view_id,
- mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::ServiceProviderPtr exposed_services,
+ void EmbedUrl(const mojo::String& url,
+ mojo::Id transport_view_id,
+ mojo::InterfaceRequest<mojo::ServiceProvider> services,
+ mojo::ServiceProviderPtr exposed_services,
+ const mojo::Callback<void(bool)>& callback) override;
+ void Embed(mojo::Id transport_view_id,
+ mojo::ViewManagerClientPtr client,
const mojo::Callback<void(bool)>& callback) override;
// AccessPolicyDelegate:
@@ -224,6 +230,8 @@
mojo::ConnectionSpecificId creator_id_;
// The URL of the app that embedded the app this connection was created for.
+ // NOTE: this is empty if the connection was created by way of directly
+ // supplying the ViewManagerClient.
const std::string creator_url_;
mojo::ViewManagerClient* client_;
diff --git a/services/view_manager/view_manager_service_unittest.cc b/services/view_manager/view_manager_service_unittest.cc
index b684fa5..7e95ff0 100644
--- a/services/view_manager/view_manager_service_unittest.cc
+++ b/services/view_manager/view_manager_service_unittest.cc
@@ -152,6 +152,16 @@
last_connection_ = new TestClientConnection(service.Pass());
return last_connection_;
}
+ ClientConnection* CreateClientConnectionForEmbedAtView(
+ ConnectionManager* connection_manager,
+ mojo::InterfaceRequest<mojo::ViewManagerService> service_request,
+ mojo::ConnectionSpecificId creator_id,
+ const std::string& creator_url,
+ const ViewId& root_id,
+ mojo::ViewManagerClientPtr client) override {
+ NOTIMPLEMENTED();
+ return nullptr;
+ }
TestClientConnection* last_connection_;
@@ -279,7 +289,8 @@
EXPECT_TRUE(test->wm_connection()->SetViewVisibility(*embed_view_id, true));
EXPECT_TRUE(test->wm_connection()->AddView(*(test->wm_connection()->root()),
*embed_view_id));
- test->wm_connection()->Embed(std::string(), *embed_view_id, nullptr, nullptr);
+ test->wm_connection()->EmbedUrl(std::string(), *embed_view_id, nullptr,
+ nullptr);
ViewManagerServiceImpl* connection1 =
test->connection_manager()->GetConnectionWithRoot(*embed_view_id);
ASSERT_TRUE(connection1 != nullptr);
@@ -415,7 +426,7 @@
EXPECT_TRUE(wm_connection()->SetViewVisibility(embed_view_id, true));
EXPECT_TRUE(
wm_connection()->AddView(*(wm_connection()->root()), embed_view_id));
- wm_connection()->Embed(std::string(), embed_view_id, nullptr, nullptr);
+ wm_connection()->EmbedUrl(std::string(), embed_view_id, nullptr, nullptr);
ViewManagerServiceImpl* connection1 =
connection_manager()->GetConnectionWithRoot(embed_view_id);
ASSERT_TRUE(connection1 != nullptr);