Reify view ownership as a message pipe.
This patch changes the View Manager API to allow for pipelined
creation and addition of views into the view hierarchy using a
new |ViewOwner| object to mediate the transfer of ownership
between clients.
The ownership model ensures that views always belong either to
a view hierarchy (as a child of some other view or as the root
of a view tree) or to a |ViewOwner| in transit.
Previously, it was more difficult to reason about the lifetime
of views since the |ViewToken| afforded no way to track ownership
transfer and therefore lifetime had to be negotiated out-of-band
by applications themselves (a fact which was not adequately captured
by the |ViewProvider| mechanism or example programs).
Bug #654
BUG=
R=abarth@google.com
Review URL: https://codereview.chromium.org/1679023006 .
diff --git a/apps/moterm/moterm_app.cc b/apps/moterm/moterm_app.cc
index efdb0fa..e8d2e2d 100644
--- a/apps/moterm/moterm_app.cc
+++ b/apps/moterm/moterm_app.cc
@@ -10,11 +10,10 @@
MotermApp::~MotermApp() {}
-bool MotermApp::CreateView(
+void MotermApp::CreateView(
const std::string& connection_url,
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request,
mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::ServiceProviderPtr exposed_services,
- const mojo::ui::ViewProvider::CreateViewCallback& callback) {
- new MotermView(app_impl(), services.Pass(), callback);
- return true;
+ mojo::ServiceProviderPtr exposed_services) {
+ new MotermView(app_impl(), view_owner_request.Pass(), services.Pass());
}
diff --git a/apps/moterm/moterm_app.h b/apps/moterm/moterm_app.h
index 0b4aead..7ff9f68 100644
--- a/apps/moterm/moterm_app.h
+++ b/apps/moterm/moterm_app.h
@@ -13,11 +13,11 @@
MotermApp();
~MotermApp() override;
- bool CreateView(
+ void CreateView(
const std::string& connection_url,
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request,
mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::ServiceProviderPtr exposed_services,
- const mojo::ui::ViewProvider::CreateViewCallback& callback) override;
+ mojo::ServiceProviderPtr exposed_services) override;
private:
DISALLOW_COPY_AND_ASSIGN(MotermApp);
diff --git a/apps/moterm/moterm_view.cc b/apps/moterm/moterm_view.cc
index 4f992cc..30b8e94 100644
--- a/apps/moterm/moterm_view.cc
+++ b/apps/moterm/moterm_view.cc
@@ -38,9 +38,9 @@
MotermView::MotermView(
mojo::ApplicationImpl* app_impl,
- mojo::InterfaceRequest<mojo::ServiceProvider> service_provider_request,
- const mojo::ui::ViewProvider::CreateViewCallback& create_view_callback)
- : GaneshView(app_impl, "Moterm", create_view_callback),
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request,
+ mojo::InterfaceRequest<mojo::ServiceProvider> service_provider_request)
+ : GaneshView(app_impl, view_owner_request.Pass(), "Moterm"),
choreographer_(scene(), this),
input_handler_(view_service_provider(), this),
model_(MotermModel::Size(240, 160), MotermModel::Size(24, 80), this),
diff --git a/apps/moterm/moterm_view.h b/apps/moterm/moterm_view.h
index 4569f3d..06c319b 100644
--- a/apps/moterm/moterm_view.h
+++ b/apps/moterm/moterm_view.h
@@ -35,8 +35,8 @@
public:
MotermView(
mojo::ApplicationImpl* app_impl,
- mojo::InterfaceRequest<mojo::ServiceProvider> service_provider_request,
- const mojo::ui::ViewProvider::CreateViewCallback& create_view_callback);
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request,
+ mojo::InterfaceRequest<mojo::ServiceProvider> service_provider_request);
~MotermView() override;
private:
diff --git a/examples/moterm_example_app/BUILD.gn b/examples/moterm_example_app/BUILD.gn
index dc3701d..007ad07 100644
--- a/examples/moterm_example_app/BUILD.gn
+++ b/examples/moterm_example_app/BUILD.gn
@@ -20,5 +20,6 @@
"//mojo/services/geometry/interfaces",
"//mojo/services/terminal/interfaces",
"//mojo/services/ui/views/interfaces",
+ "//mojo/ui",
]
}
diff --git a/examples/moterm_example_app/moterm_example_app.cc b/examples/moterm_example_app/moterm_example_app.cc
index edab7ac..e6364fc 100644
--- a/examples/moterm_example_app/moterm_example_app.cc
+++ b/examples/moterm_example_app/moterm_example_app.cc
@@ -32,6 +32,7 @@
#include "mojo/services/ui/views/interfaces/view_manager.mojom.h"
#include "mojo/services/ui/views/interfaces/view_provider.mojom.h"
#include "mojo/services/ui/views/interfaces/views.mojom.h"
+#include "mojo/ui/view_provider_app.h"
// Kind of like |fputs()| (doesn't wait for result).
void Fputs(mojo::files::File* file, const char* s) {
@@ -47,7 +48,7 @@
public:
MotermExampleAppView(
mojo::Shell* shell,
- const mojo::ui::ViewProvider::CreateViewCallback& callback)
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request)
: shell_(shell), weak_factory_(this) {
// Connect to the moterm app.
LOG(INFO) << "Connecting to moterm";
@@ -57,8 +58,8 @@
// Create the moterm view and pass it back to the client directly.
mojo::ConnectToService(moterm_app.get(), &moterm_view_provider_);
mojo::ServiceProviderPtr moterm_service_provider;
- moterm_view_provider_->CreateView(GetProxy(&moterm_service_provider),
- nullptr, callback);
+ moterm_view_provider_->CreateView(
+ view_owner_request.Pass(), GetProxy(&moterm_service_provider), nullptr);
// Connect to the moterm terminal service associated with the view
// we just created.
@@ -154,42 +155,21 @@
DISALLOW_COPY_AND_ASSIGN(MotermExampleAppView);
};
-class MotermExampleApp : public mojo::ApplicationDelegate,
- public mojo::InterfaceFactory<mojo::ui::ViewProvider>,
- public mojo::ui::ViewProvider {
+class MotermExampleApp : public mojo::ui::ViewProviderApp {
public:
- MotermExampleApp() : application_impl_() {}
+ MotermExampleApp() {}
~MotermExampleApp() override {}
+ // |ViewProviderApp|:
+ void CreateView(
+ const std::string& connection_url,
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request,
+ mojo::InterfaceRequest<mojo::ServiceProvider> services,
+ mojo::ServiceProviderPtr exposed_services) override {
+ new MotermExampleAppView(app_impl()->shell(), view_owner_request.Pass());
+ }
+
private:
- // |mojo::ApplicationDelegate|:
- void Initialize(mojo::ApplicationImpl* application_impl) override {
- DCHECK(!application_impl_);
- application_impl_ = application_impl;
- }
-
- bool ConfigureIncomingConnection(
- mojo::ApplicationConnection* connection) override {
- connection->AddService<mojo::ui::ViewProvider>(this);
- return true;
- }
-
- // |InterfaceFactory<mojo::ui::ViewProvider>|:
- void Create(mojo::ApplicationConnection* connection,
- mojo::InterfaceRequest<mojo::ui::ViewProvider> request) override {
- bindings_.AddBinding(this, request.Pass());
- }
-
- // |ViewProvider|:
- void CreateView(mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::ServiceProviderPtr exposed_services,
- const CreateViewCallback& callback) override {
- new MotermExampleAppView(application_impl_->shell(), callback);
- }
-
- mojo::ApplicationImpl* application_impl_;
- mojo::BindingSet<mojo::ui::ViewProvider> bindings_;
-
DISALLOW_COPY_AND_ASSIGN(MotermExampleApp);
};
diff --git a/examples/ui/noodles/noodles_app.cc b/examples/ui/noodles/noodles_app.cc
index 31a3c4c..4a6543d 100644
--- a/examples/ui/noodles/noodles_app.cc
+++ b/examples/ui/noodles/noodles_app.cc
@@ -12,13 +12,12 @@
NoodlesApp::~NoodlesApp() {}
-bool NoodlesApp::CreateView(
+void NoodlesApp::CreateView(
const std::string& connection_url,
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request,
mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::ServiceProviderPtr exposed_services,
- const mojo::ui::ViewProvider::CreateViewCallback& callback) {
- new NoodlesView(app_impl(), callback);
- return true;
+ mojo::ServiceProviderPtr exposed_services) {
+ new NoodlesView(app_impl(), view_owner_request.Pass());
}
} // namespace examples
diff --git a/examples/ui/noodles/noodles_app.h b/examples/ui/noodles/noodles_app.h
index 221cd8e..6556b2b 100644
--- a/examples/ui/noodles/noodles_app.h
+++ b/examples/ui/noodles/noodles_app.h
@@ -14,11 +14,11 @@
NoodlesApp();
~NoodlesApp() override;
- bool CreateView(
+ void CreateView(
const std::string& connection_url,
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request,
mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::ServiceProviderPtr exposed_services,
- const mojo::ui::ViewProvider::CreateViewCallback& callback) override;
+ mojo::ServiceProviderPtr exposed_services) override;
private:
DISALLOW_COPY_AND_ASSIGN(NoodlesApp);
diff --git a/examples/ui/noodles/noodles_view.cc b/examples/ui/noodles/noodles_view.cc
index 921e00a..ad85ded 100644
--- a/examples/ui/noodles/noodles_view.cc
+++ b/examples/ui/noodles/noodles_view.cc
@@ -50,8 +50,8 @@
NoodlesView::NoodlesView(
mojo::ApplicationImpl* app_impl,
- const mojo::ui::ViewProvider::CreateViewCallback& create_view_callback)
- : BaseView(app_impl, "Noodles", create_view_callback),
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request)
+ : BaseView(app_impl, view_owner_request.Pass(), "Noodles"),
choreographer_(scene(), this),
frame_queue_(std::make_shared<FrameQueue>()),
rasterizer_delegate_(
diff --git a/examples/ui/noodles/noodles_view.h b/examples/ui/noodles/noodles_view.h
index f64ec53..adc01c8 100644
--- a/examples/ui/noodles/noodles_view.h
+++ b/examples/ui/noodles/noodles_view.h
@@ -27,9 +27,8 @@
class NoodlesView : public mojo::ui::BaseView,
public mojo::ui::ChoreographerDelegate {
public:
- NoodlesView(
- mojo::ApplicationImpl* app_impl,
- const mojo::ui::ViewProvider::CreateViewCallback& create_view_callback);
+ NoodlesView(mojo::ApplicationImpl* app_impl,
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request);
~NoodlesView() override;
diff --git a/examples/ui/pdf_viewer/pdf_viewer.cc b/examples/ui/pdf_viewer/pdf_viewer.cc
index ee760ab..ce5c605 100644
--- a/examples/ui/pdf_viewer/pdf_viewer.cc
+++ b/examples/ui/pdf_viewer/pdf_viewer.cc
@@ -117,9 +117,9 @@
public:
PDFDocumentView(
mojo::ApplicationImpl* app_impl,
- const std::shared_ptr<PDFDocument>& pdf_document,
- const mojo::ui::ViewProvider::CreateViewCallback& create_view_callback)
- : GaneshView(app_impl, "PDFDocumentViewer", create_view_callback),
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request,
+ const std::shared_ptr<PDFDocument>& pdf_document)
+ : GaneshView(app_impl, view_owner_request.Pass(), "PDFDocumentViewer"),
pdf_document_(pdf_document),
choreographer_(scene(), this),
input_handler_(view_service_provider(), this) {
@@ -256,13 +256,12 @@
~PDFContentViewProviderApp() override {}
- bool CreateView(
+ void CreateView(
const std::string& connection_url,
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request,
mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::ServiceProviderPtr exposed_services,
- const mojo::ui::ViewProvider::CreateViewCallback& callback) override {
- new PDFDocumentView(app_impl(), pdf_document_, callback);
- return true;
+ mojo::ServiceProviderPtr exposed_services) override {
+ new PDFDocumentView(app_impl(), view_owner_request.Pass(), pdf_document_);
}
private:
diff --git a/examples/ui/png_viewer/png_viewer.cc b/examples/ui/png_viewer/png_viewer.cc
index abd5c48..16265e4 100644
--- a/examples/ui/png_viewer/png_viewer.cc
+++ b/examples/ui/png_viewer/png_viewer.cc
@@ -27,11 +27,11 @@
class PNGView : public mojo::ui::GaneshView {
public:
- PNGView(
- mojo::ApplicationImpl* app_impl,
- const skia::RefPtr<SkImage>& image,
- const mojo::ui::ViewProvider::CreateViewCallback& create_view_callback)
- : GaneshView(app_impl, "PNGViewer", create_view_callback), image_(image) {
+ PNGView(mojo::ApplicationImpl* app_impl,
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request,
+ const skia::RefPtr<SkImage>& image)
+ : GaneshView(app_impl, view_owner_request.Pass(), "PNGViewer"),
+ image_(image) {
DCHECK(image_);
}
@@ -106,13 +106,12 @@
~PNGContentViewProviderApp() override {}
- bool CreateView(
+ void CreateView(
const std::string& connection_url,
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request,
mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::ServiceProviderPtr exposed_services,
- const mojo::ui::ViewProvider::CreateViewCallback& callback) override {
- new PNGView(app_impl(), image_, callback);
- return true;
+ mojo::ServiceProviderPtr exposed_services) override {
+ new PNGView(app_impl(), view_owner_request.Pass(), image_);
}
private:
diff --git a/examples/ui/shapes/shapes_app.cc b/examples/ui/shapes/shapes_app.cc
index 86443a1..917c274 100644
--- a/examples/ui/shapes/shapes_app.cc
+++ b/examples/ui/shapes/shapes_app.cc
@@ -12,13 +12,12 @@
ShapesApp::~ShapesApp() {}
-bool ShapesApp::CreateView(
+void ShapesApp::CreateView(
const std::string& connection_url,
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request,
mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::ServiceProviderPtr exposed_services,
- const mojo::ui::ViewProvider::CreateViewCallback& callback) {
- new ShapesView(app_impl(), callback);
- return true;
+ mojo::ServiceProviderPtr exposed_services) {
+ new ShapesView(app_impl(), view_owner_request.Pass());
}
} // namespace examples
diff --git a/examples/ui/shapes/shapes_app.h b/examples/ui/shapes/shapes_app.h
index 4aba71c..d44c2d7 100644
--- a/examples/ui/shapes/shapes_app.h
+++ b/examples/ui/shapes/shapes_app.h
@@ -14,11 +14,11 @@
ShapesApp();
~ShapesApp() override;
- bool CreateView(
+ void CreateView(
const std::string& connection_url,
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request,
mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::ServiceProviderPtr exposed_services,
- const mojo::ui::ViewProvider::CreateViewCallback& callback) override;
+ mojo::ServiceProviderPtr exposed_services) override;
private:
DISALLOW_COPY_AND_ASSIGN(ShapesApp);
diff --git a/examples/ui/shapes/shapes_view.cc b/examples/ui/shapes/shapes_view.cc
index 8bea9c3..1a6803b 100644
--- a/examples/ui/shapes/shapes_view.cc
+++ b/examples/ui/shapes/shapes_view.cc
@@ -19,8 +19,8 @@
ShapesView::ShapesView(
mojo::ApplicationImpl* app_impl,
- const mojo::ui::ViewProvider::CreateViewCallback& create_view_callback)
- : GaneshView(app_impl, "Shapes", create_view_callback) {}
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request)
+ : GaneshView(app_impl, view_owner_request.Pass(), "Shapes") {}
ShapesView::~ShapesView() {}
diff --git a/examples/ui/shapes/shapes_view.h b/examples/ui/shapes/shapes_view.h
index d041f7e..fb53987 100644
--- a/examples/ui/shapes/shapes_view.h
+++ b/examples/ui/shapes/shapes_view.h
@@ -13,9 +13,8 @@
class ShapesView : public mojo::ui::GaneshView {
public:
- ShapesView(
- mojo::ApplicationImpl* app_impl,
- const mojo::ui::ViewProvider::CreateViewCallback& create_view_callback);
+ ShapesView(mojo::ApplicationImpl* app_impl,
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request);
~ShapesView() override;
diff --git a/examples/ui/spinning_cube/spinning_cube_app.cc b/examples/ui/spinning_cube/spinning_cube_app.cc
index 79818ee..8c1d797 100644
--- a/examples/ui/spinning_cube/spinning_cube_app.cc
+++ b/examples/ui/spinning_cube/spinning_cube_app.cc
@@ -12,13 +12,12 @@
SpinningCubeApp::~SpinningCubeApp() {}
-bool SpinningCubeApp::CreateView(
+void SpinningCubeApp::CreateView(
const std::string& connection_url,
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request,
mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::ServiceProviderPtr exposed_services,
- const mojo::ui::ViewProvider::CreateViewCallback& callback) {
- new SpinningCubeView(app_impl(), callback);
- return true;
+ mojo::ServiceProviderPtr exposed_services) {
+ new SpinningCubeView(app_impl(), view_owner_request.Pass());
}
} // namespace examples
diff --git a/examples/ui/spinning_cube/spinning_cube_app.h b/examples/ui/spinning_cube/spinning_cube_app.h
index e658717..5aa3f5f 100644
--- a/examples/ui/spinning_cube/spinning_cube_app.h
+++ b/examples/ui/spinning_cube/spinning_cube_app.h
@@ -14,11 +14,11 @@
SpinningCubeApp();
~SpinningCubeApp() override;
- bool CreateView(
+ void CreateView(
const std::string& connection_url,
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request,
mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::ServiceProviderPtr exposed_services,
- const mojo::ui::ViewProvider::CreateViewCallback& callback) override;
+ mojo::ServiceProviderPtr exposed_services) override;
private:
DISALLOW_COPY_AND_ASSIGN(SpinningCubeApp);
diff --git a/examples/ui/spinning_cube/spinning_cube_view.cc b/examples/ui/spinning_cube/spinning_cube_view.cc
index 68fb4f6..294d328 100644
--- a/examples/ui/spinning_cube/spinning_cube_view.cc
+++ b/examples/ui/spinning_cube/spinning_cube_view.cc
@@ -54,8 +54,8 @@
SpinningCubeView::SpinningCubeView(
mojo::ApplicationImpl* app_impl,
- const mojo::ui::ViewProvider::CreateViewCallback& create_view_callback)
- : GLView(app_impl, "SpinningCube", create_view_callback),
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request)
+ : GLView(app_impl, view_owner_request.Pass(), "SpinningCube"),
choreographer_(scene(), this),
input_handler_(view_service_provider(), this),
weak_ptr_factory_(this) {
diff --git a/examples/ui/spinning_cube/spinning_cube_view.h b/examples/ui/spinning_cube/spinning_cube_view.h
index e65220c..7ef4d3f 100644
--- a/examples/ui/spinning_cube/spinning_cube_view.h
+++ b/examples/ui/spinning_cube/spinning_cube_view.h
@@ -20,7 +20,7 @@
public:
SpinningCubeView(
mojo::ApplicationImpl* app_impl,
- const mojo::ui::ViewProvider::CreateViewCallback& create_view_callback);
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request);
~SpinningCubeView() override;
diff --git a/examples/ui/tile/tile_app.cc b/examples/ui/tile/tile_app.cc
index 2f5d4a4..fcec7c6 100644
--- a/examples/ui/tile/tile_app.cc
+++ b/examples/ui/tile/tile_app.cc
@@ -15,11 +15,11 @@
TileApp::~TileApp() {}
-bool TileApp::CreateView(
+void TileApp::CreateView(
const std::string& connection_url,
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request,
mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::ServiceProviderPtr exposed_services,
- const mojo::ui::ViewProvider::CreateViewCallback& callback) {
+ mojo::ServiceProviderPtr exposed_services) {
GURL url(connection_url);
std::vector<std::string> view_urls;
base::SplitString(url.query(), ',', &view_urls);
@@ -27,11 +27,10 @@
if (view_urls.empty()) {
LOG(ERROR) << "Must supply comma-delimited URLs of mojo views to tile as a "
"query parameter.";
- return false;
+ return;
}
- new TileView(app_impl(), view_urls, callback);
- return true;
+ new TileView(app_impl(), view_owner_request.Pass(), view_urls);
}
} // namespace examples
diff --git a/examples/ui/tile/tile_app.h b/examples/ui/tile/tile_app.h
index 1b4d619..35ba767 100644
--- a/examples/ui/tile/tile_app.h
+++ b/examples/ui/tile/tile_app.h
@@ -14,11 +14,11 @@
TileApp();
~TileApp() override;
- bool CreateView(
+ void CreateView(
const std::string& connection_url,
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request,
mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::ServiceProviderPtr exposed_services,
- const mojo::ui::ViewProvider::CreateViewCallback& callback) override;
+ mojo::ServiceProviderPtr exposed_services) override;
private:
DISALLOW_COPY_AND_ASSIGN(TileApp);
diff --git a/examples/ui/tile/tile_view.cc b/examples/ui/tile/tile_view.cc
index 744f9c4..a5fb1e8 100644
--- a/examples/ui/tile/tile_view.cc
+++ b/examples/ui/tile/tile_view.cc
@@ -19,10 +19,12 @@
constexpr uint32_t kViewFallbackNodeIdOffset = 2;
} // namespace
-TileView::TileView(mojo::ApplicationImpl* app_impl,
- const std::vector<std::string>& view_urls,
- const mojo::ui::ViewProvider::CreateViewCallback& callback)
- : BaseView(app_impl, "Tile", callback), view_urls_(view_urls) {
+TileView::TileView(
+ mojo::ApplicationImpl* app_impl,
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request,
+ const std::vector<std::string>& view_urls)
+ : BaseView(app_impl, view_owner_request.Pass(), "Tile"),
+ view_urls_(view_urls) {
ConnectViews();
}
@@ -34,44 +36,20 @@
// Start connecting to the view provider.
mojo::ui::ViewProviderPtr provider;
app_impl()->ConnectToService(url, &provider);
- provider.set_connection_error_handler(
- base::Bind(&TileView::OnChildConnectionError, base::Unretained(this),
- child_key, url));
- // Create the view.
- // We include the provider reference in the callback so that the
- // binding will be kept alive until the callback completes.
LOG(INFO) << "Connecting to view: child_key=" << child_key
<< ", url=" << url;
- provider->CreateView(
- nullptr, nullptr,
- base::Bind(&TileView::OnChildCreated, base::Unretained(this), child_key,
- url, base::Passed(provider.Pass())));
+ mojo::ui::ViewOwnerPtr child_view_owner;
+ provider->CreateView(mojo::GetProxy(&child_view_owner), nullptr, nullptr);
+
+ view_host()->AddChild(child_key, child_view_owner.Pass());
+ views_.emplace(std::make_pair(
+ child_key, std::unique_ptr<ViewData>(new ViewData(url, child_key))));
+
child_key++;
}
}
-void TileView::OnChildConnectionError(uint32_t child_key,
- const std::string& url) {
- LOG(ERROR) << "Could not connect to view: child_key=" << child_key
- << ", url=" << url;
-}
-
-void TileView::OnChildCreated(uint32_t child_key,
- const std::string& url,
- mojo::ui::ViewProviderPtr provider,
- mojo::ui::ViewTokenPtr token) {
- DCHECK(views_.find(child_key) == views_.end());
- LOG(INFO) << "View created: child_key=" << child_key << ", url=" << url;
-
- view_host()->AddChild(child_key, token.Pass());
- views_.emplace(std::make_pair(
- child_key, std::unique_ptr<ViewData>(new ViewData(url, child_key))));
-
- // Note that the view provider will be destroyed once this function
- // returns which is fine now that we are done creating the view.
-}
-
void TileView::OnChildUnavailable(uint32_t child_key,
const OnChildUnavailableCallback& callback) {
auto it = views_.find(child_key);
@@ -82,7 +60,7 @@
std::unique_ptr<ViewData> view_data = std::move(it->second);
views_.erase(it);
- view_host()->RemoveChild(child_key);
+ view_host()->RemoveChild(child_key, nullptr);
if (view_data->layout_pending) {
DCHECK(pending_child_layout_count_);
diff --git a/examples/ui/tile/tile_view.h b/examples/ui/tile/tile_view.h
index 085e431..85f4b85 100644
--- a/examples/ui/tile/tile_view.h
+++ b/examples/ui/tile/tile_view.h
@@ -8,6 +8,7 @@
#include <map>
#include <memory>
+#include "mojo/services/ui/views/interfaces/view_provider.mojom.h"
#include "mojo/ui/base_view.h"
namespace examples {
@@ -15,8 +16,8 @@
class TileView : public mojo::ui::BaseView {
public:
TileView(mojo::ApplicationImpl* app_impl_,
- const std::vector<std::string>& view_urls,
- const mojo::ui::ViewProvider::CreateViewCallback& callback);
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request,
+ const std::vector<std::string>& view_urls);
~TileView() override;
@@ -42,11 +43,6 @@
const OnChildUnavailableCallback& callback) override;
void ConnectViews();
- void OnChildConnectionError(uint32_t child_key, const std::string& url);
- void OnChildCreated(uint32_t child_key,
- const std::string& url,
- mojo::ui::ViewProviderPtr provider,
- mojo::ui::ViewTokenPtr token);
void OnChildLayoutFinished(uint32_t child_key,
mojo::ui::ViewLayoutInfoPtr child_layout_info);
void FinishLayout();
diff --git a/mojo/dart/packages/mojo_services/lib/mojo/ui/view_manager.mojom.dart b/mojo/dart/packages/mojo_services/lib/mojo/ui/view_manager.mojom.dart
index f1d603a..6c95ce3 100644
--- a/mojo/dart/packages/mojo_services/lib/mojo/ui/view_manager.mojom.dart
+++ b/mojo/dart/packages/mojo_services/lib/mojo/ui/view_manager.mojom.dart
@@ -23,6 +23,7 @@
];
Object view = null;
Object viewHost = null;
+ Object viewOwner = null;
String label = null;
_ViewManagerRegisterViewParams() : super(kVersions.last.size);
@@ -70,6 +71,10 @@
}
if (mainDataHeader.version >= 0) {
+ result.viewOwner = decoder0.decodeInterfaceRequest(20, false, views_mojom.ViewOwnerStub.newFromEndpoint);
+ }
+ if (mainDataHeader.version >= 0) {
+
result.label = decoder0.decodeString(24, true);
}
return result;
@@ -92,6 +97,13 @@
rethrow;
}
try {
+ encoder0.encodeInterfaceRequest(viewOwner, 20, false);
+ } on bindings.MojoCodecError catch(e) {
+ e.message = "Error encountered while encoding field "
+ "viewOwner of struct _ViewManagerRegisterViewParams: $e";
+ rethrow;
+ }
+ try {
encoder0.encodeString(label, 24, true);
} on bindings.MojoCodecError catch(e) {
e.message = "Error encountered while encoding field "
@@ -104,6 +116,7 @@
return "_ViewManagerRegisterViewParams("
"view: $view" ", "
"viewHost: $viewHost" ", "
+ "viewOwner: $viewOwner" ", "
"label: $label" ")";
}
@@ -116,81 +129,6 @@
-class ViewManagerRegisterViewResponseParams extends bindings.Struct {
- static const List<bindings.StructDataHeader> kVersions = const [
- const bindings.StructDataHeader(16, 0)
- ];
- views_mojom.ViewToken viewToken = null;
-
- ViewManagerRegisterViewResponseParams() : super(kVersions.last.size);
-
- static ViewManagerRegisterViewResponseParams deserialize(bindings.Message message) {
- var decoder = new bindings.Decoder(message);
- var result = decode(decoder);
- if (decoder.excessHandles != null) {
- decoder.excessHandles.forEach((h) => h.close());
- }
- return result;
- }
-
- static ViewManagerRegisterViewResponseParams decode(bindings.Decoder decoder0) {
- if (decoder0 == null) {
- return null;
- }
- ViewManagerRegisterViewResponseParams result = new ViewManagerRegisterViewResponseParams();
-
- var mainDataHeader = decoder0.decodeStructDataHeader();
- if (mainDataHeader.version <= kVersions.last.version) {
- // Scan in reverse order to optimize for more recent versions.
- for (int i = kVersions.length - 1; i >= 0; --i) {
- if (mainDataHeader.version >= kVersions[i].version) {
- if (mainDataHeader.size == kVersions[i].size) {
- // Found a match.
- break;
- }
- throw new bindings.MojoCodecError(
- 'Header size doesn\'t correspond to known version size.');
- }
- }
- } else if (mainDataHeader.size < kVersions.last.size) {
- throw new bindings.MojoCodecError(
- 'Message newer than the last known version cannot be shorter than '
- 'required by the last known version.');
- }
- if (mainDataHeader.version >= 0) {
-
- var decoder1 = decoder0.decodePointer(8, false);
- result.viewToken = views_mojom.ViewToken.decode(decoder1);
- }
- return result;
- }
-
- void encode(bindings.Encoder encoder) {
- var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
- try {
- encoder0.encodeStruct(viewToken, 8, false);
- } on bindings.MojoCodecError catch(e) {
- e.message = "Error encountered while encoding field "
- "viewToken of struct ViewManagerRegisterViewResponseParams: $e";
- rethrow;
- }
- }
-
- String toString() {
- return "ViewManagerRegisterViewResponseParams("
- "viewToken: $viewToken" ")";
- }
-
- Map toJson() {
- Map map = new Map();
- map["viewToken"] = viewToken;
- return map;
- }
-}
-
-
-
-
class _ViewManagerRegisterViewTreeParams extends bindings.Struct {
static const List<bindings.StructDataHeader> kVersions = const [
const bindings.StructDataHeader(32, 0)
@@ -290,81 +228,6 @@
-class ViewManagerRegisterViewTreeResponseParams extends bindings.Struct {
- static const List<bindings.StructDataHeader> kVersions = const [
- const bindings.StructDataHeader(16, 0)
- ];
- view_trees_mojom.ViewTreeToken viewTreeToken = null;
-
- ViewManagerRegisterViewTreeResponseParams() : super(kVersions.last.size);
-
- static ViewManagerRegisterViewTreeResponseParams deserialize(bindings.Message message) {
- var decoder = new bindings.Decoder(message);
- var result = decode(decoder);
- if (decoder.excessHandles != null) {
- decoder.excessHandles.forEach((h) => h.close());
- }
- return result;
- }
-
- static ViewManagerRegisterViewTreeResponseParams decode(bindings.Decoder decoder0) {
- if (decoder0 == null) {
- return null;
- }
- ViewManagerRegisterViewTreeResponseParams result = new ViewManagerRegisterViewTreeResponseParams();
-
- var mainDataHeader = decoder0.decodeStructDataHeader();
- if (mainDataHeader.version <= kVersions.last.version) {
- // Scan in reverse order to optimize for more recent versions.
- for (int i = kVersions.length - 1; i >= 0; --i) {
- if (mainDataHeader.version >= kVersions[i].version) {
- if (mainDataHeader.size == kVersions[i].size) {
- // Found a match.
- break;
- }
- throw new bindings.MojoCodecError(
- 'Header size doesn\'t correspond to known version size.');
- }
- }
- } else if (mainDataHeader.size < kVersions.last.size) {
- throw new bindings.MojoCodecError(
- 'Message newer than the last known version cannot be shorter than '
- 'required by the last known version.');
- }
- if (mainDataHeader.version >= 0) {
-
- var decoder1 = decoder0.decodePointer(8, false);
- result.viewTreeToken = view_trees_mojom.ViewTreeToken.decode(decoder1);
- }
- return result;
- }
-
- void encode(bindings.Encoder encoder) {
- var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
- try {
- encoder0.encodeStruct(viewTreeToken, 8, false);
- } on bindings.MojoCodecError catch(e) {
- e.message = "Error encountered while encoding field "
- "viewTreeToken of struct ViewManagerRegisterViewTreeResponseParams: $e";
- rethrow;
- }
- }
-
- String toString() {
- return "ViewManagerRegisterViewTreeResponseParams("
- "viewTreeToken: $viewTreeToken" ")";
- }
-
- Map toJson() {
- Map map = new Map();
- map["viewTreeToken"] = viewTreeToken;
- return map;
- }
-}
-
-
-
-
const int _ViewManager_registerViewName = 0;
const int _ViewManager_registerViewTreeName = 1;
@@ -380,8 +243,8 @@
abstract class ViewManager {
static const String serviceName = "mojo::ui::ViewManager";
- dynamic registerView(Object view,Object viewHost,String label,[Function responseFactory = null]);
- dynamic registerViewTree(Object viewTree,Object viewTreeHost,String label,[Function responseFactory = null]);
+ void registerView(Object view, Object viewHost, Object viewOwner, String label);
+ void registerViewTree(Object viewTree, Object viewTreeHost, String label);
}
@@ -405,46 +268,6 @@
void handleResponse(bindings.ServiceMessage message) {
switch (message.header.type) {
- case _ViewManager_registerViewName:
- var r = ViewManagerRegisterViewResponseParams.deserialize(
- message.payload);
- if (!message.header.hasRequestId) {
- proxyError("Expected a message with a valid request Id.");
- return;
- }
- Completer c = completerMap[message.header.requestId];
- if (c == null) {
- proxyError(
- "Message had unknown request Id: ${message.header.requestId}");
- return;
- }
- completerMap.remove(message.header.requestId);
- if (c.isCompleted) {
- proxyError("Response completer already completed");
- return;
- }
- c.complete(r);
- break;
- case _ViewManager_registerViewTreeName:
- var r = ViewManagerRegisterViewTreeResponseParams.deserialize(
- message.payload);
- if (!message.header.hasRequestId) {
- proxyError("Expected a message with a valid request Id.");
- return;
- }
- Completer c = completerMap[message.header.requestId];
- if (c == null) {
- proxyError(
- "Message had unknown request Id: ${message.header.requestId}");
- return;
- }
- completerMap.remove(message.header.requestId);
- if (c.isCompleted) {
- proxyError("Response completer already completed");
- return;
- }
- c.complete(r);
- break;
default:
proxyError("Unexpected message type: ${message.header.type}");
close(immediate: true);
@@ -463,27 +286,28 @@
_ViewManagerProxyImpl _proxyImpl;
_ViewManagerProxyCalls(this._proxyImpl);
- dynamic registerView(Object view,Object viewHost,String label,[Function responseFactory = null]) {
+ void registerView(Object view, Object viewHost, Object viewOwner, String label) {
+ if (!_proxyImpl.isBound) {
+ _proxyImpl.proxyError("The Proxy is closed.");
+ return;
+ }
var params = new _ViewManagerRegisterViewParams();
params.view = view;
params.viewHost = viewHost;
+ params.viewOwner = viewOwner;
params.label = label;
- return _proxyImpl.sendMessageWithRequestId(
- params,
- _ViewManager_registerViewName,
- -1,
- bindings.MessageHeader.kMessageExpectsResponse);
+ _proxyImpl.sendMessage(params, _ViewManager_registerViewName);
}
- dynamic registerViewTree(Object viewTree,Object viewTreeHost,String label,[Function responseFactory = null]) {
+ void registerViewTree(Object viewTree, Object viewTreeHost, String label) {
+ if (!_proxyImpl.isBound) {
+ _proxyImpl.proxyError("The Proxy is closed.");
+ return;
+ }
var params = new _ViewManagerRegisterViewTreeParams();
params.viewTree = viewTree;
params.viewTreeHost = viewTreeHost;
params.label = label;
- return _proxyImpl.sendMessageWithRequestId(
- params,
- _ViewManager_registerViewTreeName,
- -1,
- bindings.MessageHeader.kMessageExpectsResponse);
+ _proxyImpl.sendMessage(params, _ViewManager_registerViewTreeName);
}
}
@@ -566,16 +390,6 @@
}
- ViewManagerRegisterViewResponseParams _ViewManagerRegisterViewResponseParamsFactory(views_mojom.ViewToken viewToken) {
- var mojo_factory_result = new ViewManagerRegisterViewResponseParams();
- mojo_factory_result.viewToken = viewToken;
- return mojo_factory_result;
- }
- ViewManagerRegisterViewTreeResponseParams _ViewManagerRegisterViewTreeResponseParamsFactory(view_trees_mojom.ViewTreeToken viewTreeToken) {
- var mojo_factory_result = new ViewManagerRegisterViewTreeResponseParams();
- mojo_factory_result.viewTreeToken = viewTreeToken;
- return mojo_factory_result;
- }
dynamic handleMessage(bindings.ServiceMessage message) {
if (bindings.ControlMessageHandler.isControlMessage(message)) {
@@ -588,46 +402,12 @@
case _ViewManager_registerViewName:
var params = _ViewManagerRegisterViewParams.deserialize(
message.payload);
- var response = _impl.registerView(params.view,params.viewHost,params.label,_ViewManagerRegisterViewResponseParamsFactory);
- if (response is Future) {
- return response.then((response) {
- if (response != null) {
- return buildResponseWithId(
- response,
- _ViewManager_registerViewName,
- message.header.requestId,
- bindings.MessageHeader.kMessageIsResponse);
- }
- });
- } else if (response != null) {
- return buildResponseWithId(
- response,
- _ViewManager_registerViewName,
- message.header.requestId,
- bindings.MessageHeader.kMessageIsResponse);
- }
+ _impl.registerView(params.view, params.viewHost, params.viewOwner, params.label);
break;
case _ViewManager_registerViewTreeName:
var params = _ViewManagerRegisterViewTreeParams.deserialize(
message.payload);
- var response = _impl.registerViewTree(params.viewTree,params.viewTreeHost,params.label,_ViewManagerRegisterViewTreeResponseParamsFactory);
- if (response is Future) {
- return response.then((response) {
- if (response != null) {
- return buildResponseWithId(
- response,
- _ViewManager_registerViewTreeName,
- message.header.requestId,
- bindings.MessageHeader.kMessageIsResponse);
- }
- });
- } else if (response != null) {
- return buildResponseWithId(
- response,
- _ViewManager_registerViewTreeName,
- message.header.requestId,
- bindings.MessageHeader.kMessageIsResponse);
- }
+ _impl.registerViewTree(params.viewTree, params.viewTreeHost, params.label);
break;
default:
throw new bindings.MojoCodecError("Unexpected message name");
diff --git a/mojo/dart/packages/mojo_services/lib/mojo/ui/view_provider.mojom.dart b/mojo/dart/packages/mojo_services/lib/mojo/ui/view_provider.mojom.dart
index e1e5acf..0052a86 100644
--- a/mojo/dart/packages/mojo_services/lib/mojo/ui/view_provider.mojom.dart
+++ b/mojo/dart/packages/mojo_services/lib/mojo/ui/view_provider.mojom.dart
@@ -19,6 +19,7 @@
static const List<bindings.StructDataHeader> kVersions = const [
const bindings.StructDataHeader(24, 0)
];
+ Object viewOwner = null;
Object services = null;
Object exposedServices = null;
@@ -59,11 +60,15 @@
}
if (mainDataHeader.version >= 0) {
- result.services = decoder0.decodeInterfaceRequest(8, true, service_provider_mojom.ServiceProviderStub.newFromEndpoint);
+ result.viewOwner = decoder0.decodeInterfaceRequest(8, false, views_mojom.ViewOwnerStub.newFromEndpoint);
}
if (mainDataHeader.version >= 0) {
- result.exposedServices = decoder0.decodeServiceInterface(12, true, service_provider_mojom.ServiceProviderProxy.newFromEndpoint);
+ result.services = decoder0.decodeInterfaceRequest(12, true, service_provider_mojom.ServiceProviderStub.newFromEndpoint);
+ }
+ if (mainDataHeader.version >= 0) {
+
+ result.exposedServices = decoder0.decodeServiceInterface(16, true, service_provider_mojom.ServiceProviderProxy.newFromEndpoint);
}
return result;
}
@@ -71,14 +76,21 @@
void encode(bindings.Encoder encoder) {
var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
try {
- encoder0.encodeInterfaceRequest(services, 8, true);
+ encoder0.encodeInterfaceRequest(viewOwner, 8, false);
+ } on bindings.MojoCodecError catch(e) {
+ e.message = "Error encountered while encoding field "
+ "viewOwner of struct _ViewProviderCreateViewParams: $e";
+ rethrow;
+ }
+ try {
+ encoder0.encodeInterfaceRequest(services, 12, true);
} on bindings.MojoCodecError catch(e) {
e.message = "Error encountered while encoding field "
"services of struct _ViewProviderCreateViewParams: $e";
rethrow;
}
try {
- encoder0.encodeInterface(exposedServices, 12, true);
+ encoder0.encodeInterface(exposedServices, 16, true);
} on bindings.MojoCodecError catch(e) {
e.message = "Error encountered while encoding field "
"exposedServices of struct _ViewProviderCreateViewParams: $e";
@@ -88,6 +100,7 @@
String toString() {
return "_ViewProviderCreateViewParams("
+ "viewOwner: $viewOwner" ", "
"services: $services" ", "
"exposedServices: $exposedServices" ")";
}
@@ -101,81 +114,6 @@
-class ViewProviderCreateViewResponseParams extends bindings.Struct {
- static const List<bindings.StructDataHeader> kVersions = const [
- const bindings.StructDataHeader(16, 0)
- ];
- views_mojom.ViewToken viewToken = null;
-
- ViewProviderCreateViewResponseParams() : super(kVersions.last.size);
-
- static ViewProviderCreateViewResponseParams deserialize(bindings.Message message) {
- var decoder = new bindings.Decoder(message);
- var result = decode(decoder);
- if (decoder.excessHandles != null) {
- decoder.excessHandles.forEach((h) => h.close());
- }
- return result;
- }
-
- static ViewProviderCreateViewResponseParams decode(bindings.Decoder decoder0) {
- if (decoder0 == null) {
- return null;
- }
- ViewProviderCreateViewResponseParams result = new ViewProviderCreateViewResponseParams();
-
- var mainDataHeader = decoder0.decodeStructDataHeader();
- if (mainDataHeader.version <= kVersions.last.version) {
- // Scan in reverse order to optimize for more recent versions.
- for (int i = kVersions.length - 1; i >= 0; --i) {
- if (mainDataHeader.version >= kVersions[i].version) {
- if (mainDataHeader.size == kVersions[i].size) {
- // Found a match.
- break;
- }
- throw new bindings.MojoCodecError(
- 'Header size doesn\'t correspond to known version size.');
- }
- }
- } else if (mainDataHeader.size < kVersions.last.size) {
- throw new bindings.MojoCodecError(
- 'Message newer than the last known version cannot be shorter than '
- 'required by the last known version.');
- }
- if (mainDataHeader.version >= 0) {
-
- var decoder1 = decoder0.decodePointer(8, false);
- result.viewToken = views_mojom.ViewToken.decode(decoder1);
- }
- return result;
- }
-
- void encode(bindings.Encoder encoder) {
- var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
- try {
- encoder0.encodeStruct(viewToken, 8, false);
- } on bindings.MojoCodecError catch(e) {
- e.message = "Error encountered while encoding field "
- "viewToken of struct ViewProviderCreateViewResponseParams: $e";
- rethrow;
- }
- }
-
- String toString() {
- return "ViewProviderCreateViewResponseParams("
- "viewToken: $viewToken" ")";
- }
-
- Map toJson() {
- Map map = new Map();
- map["viewToken"] = viewToken;
- return map;
- }
-}
-
-
-
-
const int _ViewProvider_createViewName = 0;
@@ -190,7 +128,7 @@
abstract class ViewProvider {
static const String serviceName = "mojo::ui::ViewProvider";
- dynamic createView(Object services,Object exposedServices,[Function responseFactory = null]);
+ void createView(Object viewOwner, Object services, Object exposedServices);
}
@@ -214,26 +152,6 @@
void handleResponse(bindings.ServiceMessage message) {
switch (message.header.type) {
- case _ViewProvider_createViewName:
- var r = ViewProviderCreateViewResponseParams.deserialize(
- message.payload);
- if (!message.header.hasRequestId) {
- proxyError("Expected a message with a valid request Id.");
- return;
- }
- Completer c = completerMap[message.header.requestId];
- if (c == null) {
- proxyError(
- "Message had unknown request Id: ${message.header.requestId}");
- return;
- }
- completerMap.remove(message.header.requestId);
- if (c.isCompleted) {
- proxyError("Response completer already completed");
- return;
- }
- c.complete(r);
- break;
default:
proxyError("Unexpected message type: ${message.header.type}");
close(immediate: true);
@@ -252,15 +170,16 @@
_ViewProviderProxyImpl _proxyImpl;
_ViewProviderProxyCalls(this._proxyImpl);
- dynamic createView(Object services,Object exposedServices,[Function responseFactory = null]) {
+ void createView(Object viewOwner, Object services, Object exposedServices) {
+ if (!_proxyImpl.isBound) {
+ _proxyImpl.proxyError("The Proxy is closed.");
+ return;
+ }
var params = new _ViewProviderCreateViewParams();
+ params.viewOwner = viewOwner;
params.services = services;
params.exposedServices = exposedServices;
- return _proxyImpl.sendMessageWithRequestId(
- params,
- _ViewProvider_createViewName,
- -1,
- bindings.MessageHeader.kMessageExpectsResponse);
+ _proxyImpl.sendMessage(params, _ViewProvider_createViewName);
}
}
@@ -343,11 +262,6 @@
}
- ViewProviderCreateViewResponseParams _ViewProviderCreateViewResponseParamsFactory(views_mojom.ViewToken viewToken) {
- var mojo_factory_result = new ViewProviderCreateViewResponseParams();
- mojo_factory_result.viewToken = viewToken;
- return mojo_factory_result;
- }
dynamic handleMessage(bindings.ServiceMessage message) {
if (bindings.ControlMessageHandler.isControlMessage(message)) {
@@ -360,24 +274,7 @@
case _ViewProvider_createViewName:
var params = _ViewProviderCreateViewParams.deserialize(
message.payload);
- var response = _impl.createView(params.services,params.exposedServices,_ViewProviderCreateViewResponseParamsFactory);
- if (response is Future) {
- return response.then((response) {
- if (response != null) {
- return buildResponseWithId(
- response,
- _ViewProvider_createViewName,
- message.header.requestId,
- bindings.MessageHeader.kMessageIsResponse);
- }
- });
- } else if (response != null) {
- return buildResponseWithId(
- response,
- _ViewProvider_createViewName,
- message.header.requestId,
- bindings.MessageHeader.kMessageIsResponse);
- }
+ _impl.createView(params.viewOwner, params.services, params.exposedServices);
break;
default:
throw new bindings.MojoCodecError("Unexpected message name");
diff --git a/mojo/dart/packages/mojo_services/lib/mojo/ui/view_trees.mojom.dart b/mojo/dart/packages/mojo_services/lib/mojo/ui/view_trees.mojom.dart
index a0fa2d0..9cc565e 100644
--- a/mojo/dart/packages/mojo_services/lib/mojo/ui/view_trees.mojom.dart
+++ b/mojo/dart/packages/mojo_services/lib/mojo/ui/view_trees.mojom.dart
@@ -344,6 +344,141 @@
+class _ViewTreeHostGetTokenParams extends bindings.Struct {
+ static const List<bindings.StructDataHeader> kVersions = const [
+ const bindings.StructDataHeader(8, 0)
+ ];
+
+ _ViewTreeHostGetTokenParams() : super(kVersions.last.size);
+
+ static _ViewTreeHostGetTokenParams deserialize(bindings.Message message) {
+ var decoder = new bindings.Decoder(message);
+ var result = decode(decoder);
+ if (decoder.excessHandles != null) {
+ decoder.excessHandles.forEach((h) => h.close());
+ }
+ return result;
+ }
+
+ static _ViewTreeHostGetTokenParams decode(bindings.Decoder decoder0) {
+ if (decoder0 == null) {
+ return null;
+ }
+ _ViewTreeHostGetTokenParams result = new _ViewTreeHostGetTokenParams();
+
+ var mainDataHeader = decoder0.decodeStructDataHeader();
+ if (mainDataHeader.version <= kVersions.last.version) {
+ // Scan in reverse order to optimize for more recent versions.
+ for (int i = kVersions.length - 1; i >= 0; --i) {
+ if (mainDataHeader.version >= kVersions[i].version) {
+ if (mainDataHeader.size == kVersions[i].size) {
+ // Found a match.
+ break;
+ }
+ throw new bindings.MojoCodecError(
+ 'Header size doesn\'t correspond to known version size.');
+ }
+ }
+ } else if (mainDataHeader.size < kVersions.last.size) {
+ throw new bindings.MojoCodecError(
+ 'Message newer than the last known version cannot be shorter than '
+ 'required by the last known version.');
+ }
+ return result;
+ }
+
+ void encode(bindings.Encoder encoder) {
+ encoder.getStructEncoderAtOffset(kVersions.last);
+ }
+
+ String toString() {
+ return "_ViewTreeHostGetTokenParams("")";
+ }
+
+ Map toJson() {
+ Map map = new Map();
+ return map;
+ }
+}
+
+
+
+
+class ViewTreeHostGetTokenResponseParams extends bindings.Struct {
+ static const List<bindings.StructDataHeader> kVersions = const [
+ const bindings.StructDataHeader(16, 0)
+ ];
+ ViewTreeToken token = null;
+
+ ViewTreeHostGetTokenResponseParams() : super(kVersions.last.size);
+
+ static ViewTreeHostGetTokenResponseParams deserialize(bindings.Message message) {
+ var decoder = new bindings.Decoder(message);
+ var result = decode(decoder);
+ if (decoder.excessHandles != null) {
+ decoder.excessHandles.forEach((h) => h.close());
+ }
+ return result;
+ }
+
+ static ViewTreeHostGetTokenResponseParams decode(bindings.Decoder decoder0) {
+ if (decoder0 == null) {
+ return null;
+ }
+ ViewTreeHostGetTokenResponseParams result = new ViewTreeHostGetTokenResponseParams();
+
+ var mainDataHeader = decoder0.decodeStructDataHeader();
+ if (mainDataHeader.version <= kVersions.last.version) {
+ // Scan in reverse order to optimize for more recent versions.
+ for (int i = kVersions.length - 1; i >= 0; --i) {
+ if (mainDataHeader.version >= kVersions[i].version) {
+ if (mainDataHeader.size == kVersions[i].size) {
+ // Found a match.
+ break;
+ }
+ throw new bindings.MojoCodecError(
+ 'Header size doesn\'t correspond to known version size.');
+ }
+ }
+ } else if (mainDataHeader.size < kVersions.last.size) {
+ throw new bindings.MojoCodecError(
+ 'Message newer than the last known version cannot be shorter than '
+ 'required by the last known version.');
+ }
+ if (mainDataHeader.version >= 0) {
+
+ var decoder1 = decoder0.decodePointer(8, false);
+ result.token = ViewTreeToken.decode(decoder1);
+ }
+ return result;
+ }
+
+ void encode(bindings.Encoder encoder) {
+ var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
+ try {
+ encoder0.encodeStruct(token, 8, false);
+ } on bindings.MojoCodecError catch(e) {
+ e.message = "Error encountered while encoding field "
+ "token of struct ViewTreeHostGetTokenResponseParams: $e";
+ rethrow;
+ }
+ }
+
+ String toString() {
+ return "ViewTreeHostGetTokenResponseParams("
+ "token: $token" ")";
+ }
+
+ Map toJson() {
+ Map map = new Map();
+ map["token"] = token;
+ return map;
+ }
+}
+
+
+
+
class _ViewTreeHostGetServiceProviderParams extends bindings.Struct {
static const List<bindings.StructDataHeader> kVersions = const [
const bindings.StructDataHeader(16, 0)
@@ -482,7 +617,7 @@
const bindings.StructDataHeader(24, 0)
];
int rootKey = 0;
- views_mojom.ViewToken rootViewToken = null;
+ Object rootViewOwner = null;
_ViewTreeHostSetRootParams() : super(kVersions.last.size);
@@ -525,8 +660,7 @@
}
if (mainDataHeader.version >= 0) {
- var decoder1 = decoder0.decodePointer(16, false);
- result.rootViewToken = views_mojom.ViewToken.decode(decoder1);
+ result.rootViewOwner = decoder0.decodeServiceInterface(12, false, views_mojom.ViewOwnerProxy.newFromEndpoint);
}
return result;
}
@@ -541,10 +675,10 @@
rethrow;
}
try {
- encoder0.encodeStruct(rootViewToken, 16, false);
+ encoder0.encodeInterface(rootViewOwner, 12, false);
} on bindings.MojoCodecError catch(e) {
e.message = "Error encountered while encoding field "
- "rootViewToken of struct _ViewTreeHostSetRootParams: $e";
+ "rootViewOwner of struct _ViewTreeHostSetRootParams: $e";
rethrow;
}
}
@@ -552,14 +686,12 @@
String toString() {
return "_ViewTreeHostSetRootParams("
"rootKey: $rootKey" ", "
- "rootViewToken: $rootViewToken" ")";
+ "rootViewOwner: $rootViewOwner" ")";
}
Map toJson() {
- Map map = new Map();
- map["rootKey"] = rootKey;
- map["rootViewToken"] = rootViewToken;
- return map;
+ throw new bindings.MojoCodecError(
+ 'Object containing handles cannot be encoded to JSON.');
}
}
@@ -568,8 +700,9 @@
class _ViewTreeHostResetRootParams extends bindings.Struct {
static const List<bindings.StructDataHeader> kVersions = const [
- const bindings.StructDataHeader(8, 0)
+ const bindings.StructDataHeader(16, 0)
];
+ Object transferredViewOwner = null;
_ViewTreeHostResetRootParams() : super(kVersions.last.size);
@@ -606,20 +739,32 @@
'Message newer than the last known version cannot be shorter than '
'required by the last known version.');
}
+ if (mainDataHeader.version >= 0) {
+
+ result.transferredViewOwner = decoder0.decodeInterfaceRequest(8, true, views_mojom.ViewOwnerStub.newFromEndpoint);
+ }
return result;
}
void encode(bindings.Encoder encoder) {
- encoder.getStructEncoderAtOffset(kVersions.last);
+ var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
+ try {
+ encoder0.encodeInterfaceRequest(transferredViewOwner, 8, true);
+ } on bindings.MojoCodecError catch(e) {
+ e.message = "Error encountered while encoding field "
+ "transferredViewOwner of struct _ViewTreeHostResetRootParams: $e";
+ rethrow;
+ }
}
String toString() {
- return "_ViewTreeHostResetRootParams("")";
+ return "_ViewTreeHostResetRootParams("
+ "transferredViewOwner: $transferredViewOwner" ")";
}
Map toJson() {
- Map map = new Map();
- return map;
+ throw new bindings.MojoCodecError(
+ 'Object containing handles cannot be encoded to JSON.');
}
}
@@ -1057,11 +1202,12 @@
new _ViewTreeServiceDescription();
}
-const int _ViewTreeHost_getServiceProviderName = 0;
-const int _ViewTreeHost_requestLayoutName = 1;
-const int _ViewTreeHost_setRootName = 2;
-const int _ViewTreeHost_resetRootName = 3;
-const int _ViewTreeHost_layoutRootName = 4;
+const int _ViewTreeHost_getTokenName = 0;
+const int _ViewTreeHost_getServiceProviderName = 1;
+const int _ViewTreeHost_requestLayoutName = 2;
+const int _ViewTreeHost_setRootName = 3;
+const int _ViewTreeHost_resetRootName = 4;
+const int _ViewTreeHost_layoutRootName = 5;
@@ -1075,10 +1221,11 @@
abstract class ViewTreeHost {
static const String serviceName = null;
+ dynamic getToken([Function responseFactory = null]);
void getServiceProvider(Object serviceProvider);
void requestLayout();
- void setRoot(int rootKey, views_mojom.ViewToken rootViewToken);
- void resetRoot();
+ void setRoot(int rootKey, Object rootViewOwner);
+ void resetRoot(Object transferredViewOwner);
dynamic layoutRoot(layouts_mojom.ViewLayoutParams rootLayoutParams,[Function responseFactory = null]);
}
@@ -1103,6 +1250,26 @@
void handleResponse(bindings.ServiceMessage message) {
switch (message.header.type) {
+ case _ViewTreeHost_getTokenName:
+ var r = ViewTreeHostGetTokenResponseParams.deserialize(
+ message.payload);
+ if (!message.header.hasRequestId) {
+ proxyError("Expected a message with a valid request Id.");
+ return;
+ }
+ Completer c = completerMap[message.header.requestId];
+ if (c == null) {
+ proxyError(
+ "Message had unknown request Id: ${message.header.requestId}");
+ return;
+ }
+ completerMap.remove(message.header.requestId);
+ if (c.isCompleted) {
+ proxyError("Response completer already completed");
+ return;
+ }
+ c.complete(r);
+ break;
case _ViewTreeHost_layoutRootName:
var r = ViewTreeHostLayoutRootResponseParams.deserialize(
message.payload);
@@ -1141,6 +1308,14 @@
_ViewTreeHostProxyImpl _proxyImpl;
_ViewTreeHostProxyCalls(this._proxyImpl);
+ dynamic getToken([Function responseFactory = null]) {
+ var params = new _ViewTreeHostGetTokenParams();
+ return _proxyImpl.sendMessageWithRequestId(
+ params,
+ _ViewTreeHost_getTokenName,
+ -1,
+ bindings.MessageHeader.kMessageExpectsResponse);
+ }
void getServiceProvider(Object serviceProvider) {
if (!_proxyImpl.isBound) {
_proxyImpl.proxyError("The Proxy is closed.");
@@ -1158,22 +1333,23 @@
var params = new _ViewTreeHostRequestLayoutParams();
_proxyImpl.sendMessage(params, _ViewTreeHost_requestLayoutName);
}
- void setRoot(int rootKey, views_mojom.ViewToken rootViewToken) {
+ void setRoot(int rootKey, Object rootViewOwner) {
if (!_proxyImpl.isBound) {
_proxyImpl.proxyError("The Proxy is closed.");
return;
}
var params = new _ViewTreeHostSetRootParams();
params.rootKey = rootKey;
- params.rootViewToken = rootViewToken;
+ params.rootViewOwner = rootViewOwner;
_proxyImpl.sendMessage(params, _ViewTreeHost_setRootName);
}
- void resetRoot() {
+ void resetRoot(Object transferredViewOwner) {
if (!_proxyImpl.isBound) {
_proxyImpl.proxyError("The Proxy is closed.");
return;
}
var params = new _ViewTreeHostResetRootParams();
+ params.transferredViewOwner = transferredViewOwner;
_proxyImpl.sendMessage(params, _ViewTreeHost_resetRootName);
}
dynamic layoutRoot(layouts_mojom.ViewLayoutParams rootLayoutParams,[Function responseFactory = null]) {
@@ -1266,6 +1442,11 @@
}
+ ViewTreeHostGetTokenResponseParams _ViewTreeHostGetTokenResponseParamsFactory(ViewTreeToken token) {
+ var mojo_factory_result = new ViewTreeHostGetTokenResponseParams();
+ mojo_factory_result.token = token;
+ return mojo_factory_result;
+ }
ViewTreeHostLayoutRootResponseParams _ViewTreeHostLayoutRootResponseParamsFactory(layouts_mojom.ViewLayoutInfo info) {
var mojo_factory_result = new ViewTreeHostLayoutRootResponseParams();
mojo_factory_result.info = info;
@@ -1280,6 +1461,28 @@
}
assert(_impl != null);
switch (message.header.type) {
+ case _ViewTreeHost_getTokenName:
+ var params = _ViewTreeHostGetTokenParams.deserialize(
+ message.payload);
+ var response = _impl.getToken(_ViewTreeHostGetTokenResponseParamsFactory);
+ if (response is Future) {
+ return response.then((response) {
+ if (response != null) {
+ return buildResponseWithId(
+ response,
+ _ViewTreeHost_getTokenName,
+ message.header.requestId,
+ bindings.MessageHeader.kMessageIsResponse);
+ }
+ });
+ } else if (response != null) {
+ return buildResponseWithId(
+ response,
+ _ViewTreeHost_getTokenName,
+ message.header.requestId,
+ bindings.MessageHeader.kMessageIsResponse);
+ }
+ break;
case _ViewTreeHost_getServiceProviderName:
var params = _ViewTreeHostGetServiceProviderParams.deserialize(
message.payload);
@@ -1293,12 +1496,12 @@
case _ViewTreeHost_setRootName:
var params = _ViewTreeHostSetRootParams.deserialize(
message.payload);
- _impl.setRoot(params.rootKey, params.rootViewToken);
+ _impl.setRoot(params.rootKey, params.rootViewOwner);
break;
case _ViewTreeHost_resetRootName:
var params = _ViewTreeHostResetRootParams.deserialize(
message.payload);
- _impl.resetRoot();
+ _impl.resetRoot(params.transferredViewOwner);
break;
case _ViewTreeHost_layoutRootName:
var params = _ViewTreeHostLayoutRootParams.deserialize(
diff --git a/mojo/dart/packages/mojo_services/lib/mojo/ui/views.mojom.dart b/mojo/dart/packages/mojo_services/lib/mojo/ui/views.mojom.dart
index 39df1e1..d00a29a 100644
--- a/mojo/dart/packages/mojo_services/lib/mojo/ui/views.mojom.dart
+++ b/mojo/dart/packages/mojo_services/lib/mojo/ui/views.mojom.dart
@@ -90,6 +90,141 @@
+class _ViewOwnerGetTokenParams extends bindings.Struct {
+ static const List<bindings.StructDataHeader> kVersions = const [
+ const bindings.StructDataHeader(8, 0)
+ ];
+
+ _ViewOwnerGetTokenParams() : super(kVersions.last.size);
+
+ static _ViewOwnerGetTokenParams deserialize(bindings.Message message) {
+ var decoder = new bindings.Decoder(message);
+ var result = decode(decoder);
+ if (decoder.excessHandles != null) {
+ decoder.excessHandles.forEach((h) => h.close());
+ }
+ return result;
+ }
+
+ static _ViewOwnerGetTokenParams decode(bindings.Decoder decoder0) {
+ if (decoder0 == null) {
+ return null;
+ }
+ _ViewOwnerGetTokenParams result = new _ViewOwnerGetTokenParams();
+
+ var mainDataHeader = decoder0.decodeStructDataHeader();
+ if (mainDataHeader.version <= kVersions.last.version) {
+ // Scan in reverse order to optimize for more recent versions.
+ for (int i = kVersions.length - 1; i >= 0; --i) {
+ if (mainDataHeader.version >= kVersions[i].version) {
+ if (mainDataHeader.size == kVersions[i].size) {
+ // Found a match.
+ break;
+ }
+ throw new bindings.MojoCodecError(
+ 'Header size doesn\'t correspond to known version size.');
+ }
+ }
+ } else if (mainDataHeader.size < kVersions.last.size) {
+ throw new bindings.MojoCodecError(
+ 'Message newer than the last known version cannot be shorter than '
+ 'required by the last known version.');
+ }
+ return result;
+ }
+
+ void encode(bindings.Encoder encoder) {
+ encoder.getStructEncoderAtOffset(kVersions.last);
+ }
+
+ String toString() {
+ return "_ViewOwnerGetTokenParams("")";
+ }
+
+ Map toJson() {
+ Map map = new Map();
+ return map;
+ }
+}
+
+
+
+
+class ViewOwnerGetTokenResponseParams extends bindings.Struct {
+ static const List<bindings.StructDataHeader> kVersions = const [
+ const bindings.StructDataHeader(16, 0)
+ ];
+ ViewToken token = null;
+
+ ViewOwnerGetTokenResponseParams() : super(kVersions.last.size);
+
+ static ViewOwnerGetTokenResponseParams deserialize(bindings.Message message) {
+ var decoder = new bindings.Decoder(message);
+ var result = decode(decoder);
+ if (decoder.excessHandles != null) {
+ decoder.excessHandles.forEach((h) => h.close());
+ }
+ return result;
+ }
+
+ static ViewOwnerGetTokenResponseParams decode(bindings.Decoder decoder0) {
+ if (decoder0 == null) {
+ return null;
+ }
+ ViewOwnerGetTokenResponseParams result = new ViewOwnerGetTokenResponseParams();
+
+ var mainDataHeader = decoder0.decodeStructDataHeader();
+ if (mainDataHeader.version <= kVersions.last.version) {
+ // Scan in reverse order to optimize for more recent versions.
+ for (int i = kVersions.length - 1; i >= 0; --i) {
+ if (mainDataHeader.version >= kVersions[i].version) {
+ if (mainDataHeader.size == kVersions[i].size) {
+ // Found a match.
+ break;
+ }
+ throw new bindings.MojoCodecError(
+ 'Header size doesn\'t correspond to known version size.');
+ }
+ }
+ } else if (mainDataHeader.size < kVersions.last.size) {
+ throw new bindings.MojoCodecError(
+ 'Message newer than the last known version cannot be shorter than '
+ 'required by the last known version.');
+ }
+ if (mainDataHeader.version >= 0) {
+
+ var decoder1 = decoder0.decodePointer(8, false);
+ result.token = ViewToken.decode(decoder1);
+ }
+ return result;
+ }
+
+ void encode(bindings.Encoder encoder) {
+ var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
+ try {
+ encoder0.encodeStruct(token, 8, false);
+ } on bindings.MojoCodecError catch(e) {
+ e.message = "Error encountered while encoding field "
+ "token of struct ViewOwnerGetTokenResponseParams: $e";
+ rethrow;
+ }
+ }
+
+ String toString() {
+ return "ViewOwnerGetTokenResponseParams("
+ "token: $token" ")";
+ }
+
+ Map toJson() {
+ Map map = new Map();
+ map["token"] = token;
+ return map;
+ }
+}
+
+
+
+
class _ViewOnLayoutParams extends bindings.Struct {
static const List<bindings.StructDataHeader> kVersions = const [
const bindings.StructDataHeader(24, 0)
@@ -388,6 +523,141 @@
+class _ViewHostGetTokenParams extends bindings.Struct {
+ static const List<bindings.StructDataHeader> kVersions = const [
+ const bindings.StructDataHeader(8, 0)
+ ];
+
+ _ViewHostGetTokenParams() : super(kVersions.last.size);
+
+ static _ViewHostGetTokenParams deserialize(bindings.Message message) {
+ var decoder = new bindings.Decoder(message);
+ var result = decode(decoder);
+ if (decoder.excessHandles != null) {
+ decoder.excessHandles.forEach((h) => h.close());
+ }
+ return result;
+ }
+
+ static _ViewHostGetTokenParams decode(bindings.Decoder decoder0) {
+ if (decoder0 == null) {
+ return null;
+ }
+ _ViewHostGetTokenParams result = new _ViewHostGetTokenParams();
+
+ var mainDataHeader = decoder0.decodeStructDataHeader();
+ if (mainDataHeader.version <= kVersions.last.version) {
+ // Scan in reverse order to optimize for more recent versions.
+ for (int i = kVersions.length - 1; i >= 0; --i) {
+ if (mainDataHeader.version >= kVersions[i].version) {
+ if (mainDataHeader.size == kVersions[i].size) {
+ // Found a match.
+ break;
+ }
+ throw new bindings.MojoCodecError(
+ 'Header size doesn\'t correspond to known version size.');
+ }
+ }
+ } else if (mainDataHeader.size < kVersions.last.size) {
+ throw new bindings.MojoCodecError(
+ 'Message newer than the last known version cannot be shorter than '
+ 'required by the last known version.');
+ }
+ return result;
+ }
+
+ void encode(bindings.Encoder encoder) {
+ encoder.getStructEncoderAtOffset(kVersions.last);
+ }
+
+ String toString() {
+ return "_ViewHostGetTokenParams("")";
+ }
+
+ Map toJson() {
+ Map map = new Map();
+ return map;
+ }
+}
+
+
+
+
+class ViewHostGetTokenResponseParams extends bindings.Struct {
+ static const List<bindings.StructDataHeader> kVersions = const [
+ const bindings.StructDataHeader(16, 0)
+ ];
+ ViewToken token = null;
+
+ ViewHostGetTokenResponseParams() : super(kVersions.last.size);
+
+ static ViewHostGetTokenResponseParams deserialize(bindings.Message message) {
+ var decoder = new bindings.Decoder(message);
+ var result = decode(decoder);
+ if (decoder.excessHandles != null) {
+ decoder.excessHandles.forEach((h) => h.close());
+ }
+ return result;
+ }
+
+ static ViewHostGetTokenResponseParams decode(bindings.Decoder decoder0) {
+ if (decoder0 == null) {
+ return null;
+ }
+ ViewHostGetTokenResponseParams result = new ViewHostGetTokenResponseParams();
+
+ var mainDataHeader = decoder0.decodeStructDataHeader();
+ if (mainDataHeader.version <= kVersions.last.version) {
+ // Scan in reverse order to optimize for more recent versions.
+ for (int i = kVersions.length - 1; i >= 0; --i) {
+ if (mainDataHeader.version >= kVersions[i].version) {
+ if (mainDataHeader.size == kVersions[i].size) {
+ // Found a match.
+ break;
+ }
+ throw new bindings.MojoCodecError(
+ 'Header size doesn\'t correspond to known version size.');
+ }
+ }
+ } else if (mainDataHeader.size < kVersions.last.size) {
+ throw new bindings.MojoCodecError(
+ 'Message newer than the last known version cannot be shorter than '
+ 'required by the last known version.');
+ }
+ if (mainDataHeader.version >= 0) {
+
+ var decoder1 = decoder0.decodePointer(8, false);
+ result.token = ViewToken.decode(decoder1);
+ }
+ return result;
+ }
+
+ void encode(bindings.Encoder encoder) {
+ var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
+ try {
+ encoder0.encodeStruct(token, 8, false);
+ } on bindings.MojoCodecError catch(e) {
+ e.message = "Error encountered while encoding field "
+ "token of struct ViewHostGetTokenResponseParams: $e";
+ rethrow;
+ }
+ }
+
+ String toString() {
+ return "ViewHostGetTokenResponseParams("
+ "token: $token" ")";
+ }
+
+ Map toJson() {
+ Map map = new Map();
+ map["token"] = token;
+ return map;
+ }
+}
+
+
+
+
class _ViewHostGetServiceProviderParams extends bindings.Struct {
static const List<bindings.StructDataHeader> kVersions = const [
const bindings.StructDataHeader(16, 0)
@@ -599,7 +869,7 @@
const bindings.StructDataHeader(24, 0)
];
int childKey = 0;
- ViewToken childViewToken = null;
+ Object childViewOwner = null;
_ViewHostAddChildParams() : super(kVersions.last.size);
@@ -642,8 +912,7 @@
}
if (mainDataHeader.version >= 0) {
- var decoder1 = decoder0.decodePointer(16, false);
- result.childViewToken = ViewToken.decode(decoder1);
+ result.childViewOwner = decoder0.decodeServiceInterface(12, false, ViewOwnerProxy.newFromEndpoint);
}
return result;
}
@@ -658,10 +927,10 @@
rethrow;
}
try {
- encoder0.encodeStruct(childViewToken, 16, false);
+ encoder0.encodeInterface(childViewOwner, 12, false);
} on bindings.MojoCodecError catch(e) {
e.message = "Error encountered while encoding field "
- "childViewToken of struct _ViewHostAddChildParams: $e";
+ "childViewOwner of struct _ViewHostAddChildParams: $e";
rethrow;
}
}
@@ -669,14 +938,12 @@
String toString() {
return "_ViewHostAddChildParams("
"childKey: $childKey" ", "
- "childViewToken: $childViewToken" ")";
+ "childViewOwner: $childViewOwner" ")";
}
Map toJson() {
- Map map = new Map();
- map["childKey"] = childKey;
- map["childViewToken"] = childViewToken;
- return map;
+ throw new bindings.MojoCodecError(
+ 'Object containing handles cannot be encoded to JSON.');
}
}
@@ -688,6 +955,7 @@
const bindings.StructDataHeader(16, 0)
];
int childKey = 0;
+ Object transferredViewOwner = null;
_ViewHostRemoveChildParams() : super(kVersions.last.size);
@@ -728,6 +996,10 @@
result.childKey = decoder0.decodeUint32(8);
}
+ if (mainDataHeader.version >= 0) {
+
+ result.transferredViewOwner = decoder0.decodeInterfaceRequest(12, true, ViewOwnerStub.newFromEndpoint);
+ }
return result;
}
@@ -740,17 +1012,24 @@
"childKey of struct _ViewHostRemoveChildParams: $e";
rethrow;
}
+ try {
+ encoder0.encodeInterfaceRequest(transferredViewOwner, 12, true);
+ } on bindings.MojoCodecError catch(e) {
+ e.message = "Error encountered while encoding field "
+ "transferredViewOwner of struct _ViewHostRemoveChildParams: $e";
+ rethrow;
+ }
}
String toString() {
return "_ViewHostRemoveChildParams("
- "childKey: $childKey" ")";
+ "childKey: $childKey" ", "
+ "transferredViewOwner: $transferredViewOwner" ")";
}
Map toJson() {
- Map map = new Map();
- map["childKey"] = childKey;
- return map;
+ throw new bindings.MojoCodecError(
+ 'Object containing handles cannot be encoded to JSON.');
}
}
@@ -921,6 +1200,231 @@
+const int _ViewOwner_getTokenName = 0;
+
+
+
+class _ViewOwnerServiceDescription implements service_describer.ServiceDescription {
+ dynamic getTopLevelInterface([Function responseFactory]) => null;
+
+ dynamic getTypeDefinition(String typeKey, [Function responseFactory]) => null;
+
+ dynamic getAllTypeDefinitions([Function responseFactory]) => null;
+}
+
+abstract class ViewOwner {
+ static const String serviceName = null;
+ dynamic getToken([Function responseFactory = null]);
+}
+
+
+class _ViewOwnerProxyImpl extends bindings.Proxy {
+ _ViewOwnerProxyImpl.fromEndpoint(
+ core.MojoMessagePipeEndpoint endpoint) : super.fromEndpoint(endpoint);
+
+ _ViewOwnerProxyImpl.fromHandle(core.MojoHandle handle) :
+ super.fromHandle(handle);
+
+ _ViewOwnerProxyImpl.unbound() : super.unbound();
+
+ static _ViewOwnerProxyImpl newFromEndpoint(
+ core.MojoMessagePipeEndpoint endpoint) {
+ assert(endpoint.setDescription("For _ViewOwnerProxyImpl"));
+ return new _ViewOwnerProxyImpl.fromEndpoint(endpoint);
+ }
+
+ service_describer.ServiceDescription get serviceDescription =>
+ new _ViewOwnerServiceDescription();
+
+ void handleResponse(bindings.ServiceMessage message) {
+ switch (message.header.type) {
+ case _ViewOwner_getTokenName:
+ var r = ViewOwnerGetTokenResponseParams.deserialize(
+ message.payload);
+ if (!message.header.hasRequestId) {
+ proxyError("Expected a message with a valid request Id.");
+ return;
+ }
+ Completer c = completerMap[message.header.requestId];
+ if (c == null) {
+ proxyError(
+ "Message had unknown request Id: ${message.header.requestId}");
+ return;
+ }
+ completerMap.remove(message.header.requestId);
+ if (c.isCompleted) {
+ proxyError("Response completer already completed");
+ return;
+ }
+ c.complete(r);
+ break;
+ default:
+ proxyError("Unexpected message type: ${message.header.type}");
+ close(immediate: true);
+ break;
+ }
+ }
+
+ String toString() {
+ var superString = super.toString();
+ return "_ViewOwnerProxyImpl($superString)";
+ }
+}
+
+
+class _ViewOwnerProxyCalls implements ViewOwner {
+ _ViewOwnerProxyImpl _proxyImpl;
+
+ _ViewOwnerProxyCalls(this._proxyImpl);
+ dynamic getToken([Function responseFactory = null]) {
+ var params = new _ViewOwnerGetTokenParams();
+ return _proxyImpl.sendMessageWithRequestId(
+ params,
+ _ViewOwner_getTokenName,
+ -1,
+ bindings.MessageHeader.kMessageExpectsResponse);
+ }
+}
+
+
+class ViewOwnerProxy implements bindings.ProxyBase {
+ final bindings.Proxy impl;
+ ViewOwner ptr;
+
+ ViewOwnerProxy(_ViewOwnerProxyImpl proxyImpl) :
+ impl = proxyImpl,
+ ptr = new _ViewOwnerProxyCalls(proxyImpl);
+
+ ViewOwnerProxy.fromEndpoint(
+ core.MojoMessagePipeEndpoint endpoint) :
+ impl = new _ViewOwnerProxyImpl.fromEndpoint(endpoint) {
+ ptr = new _ViewOwnerProxyCalls(impl);
+ }
+
+ ViewOwnerProxy.fromHandle(core.MojoHandle handle) :
+ impl = new _ViewOwnerProxyImpl.fromHandle(handle) {
+ ptr = new _ViewOwnerProxyCalls(impl);
+ }
+
+ ViewOwnerProxy.unbound() :
+ impl = new _ViewOwnerProxyImpl.unbound() {
+ ptr = new _ViewOwnerProxyCalls(impl);
+ }
+
+ factory ViewOwnerProxy.connectToService(
+ bindings.ServiceConnector s, String url, [String serviceName]) {
+ ViewOwnerProxy p = new ViewOwnerProxy.unbound();
+ s.connectToService(url, p, serviceName);
+ return p;
+ }
+
+ static ViewOwnerProxy newFromEndpoint(
+ core.MojoMessagePipeEndpoint endpoint) {
+ assert(endpoint.setDescription("For ViewOwnerProxy"));
+ return new ViewOwnerProxy.fromEndpoint(endpoint);
+ }
+
+ String get serviceName => ViewOwner.serviceName;
+
+ Future close({bool immediate: false}) => impl.close(immediate: immediate);
+
+ Future responseOrError(Future f) => impl.responseOrError(f);
+
+ Future get errorFuture => impl.errorFuture;
+
+ int get version => impl.version;
+
+ Future<int> queryVersion() => impl.queryVersion();
+
+ void requireVersion(int requiredVersion) {
+ impl.requireVersion(requiredVersion);
+ }
+
+ String toString() {
+ return "ViewOwnerProxy($impl)";
+ }
+}
+
+
+class ViewOwnerStub extends bindings.Stub {
+ ViewOwner _impl = null;
+
+ ViewOwnerStub.fromEndpoint(
+ core.MojoMessagePipeEndpoint endpoint, [this._impl])
+ : super.fromEndpoint(endpoint);
+
+ ViewOwnerStub.fromHandle(core.MojoHandle handle, [this._impl])
+ : super.fromHandle(handle);
+
+ ViewOwnerStub.unbound() : super.unbound();
+
+ static ViewOwnerStub newFromEndpoint(
+ core.MojoMessagePipeEndpoint endpoint) {
+ assert(endpoint.setDescription("For ViewOwnerStub"));
+ return new ViewOwnerStub.fromEndpoint(endpoint);
+ }
+
+
+ ViewOwnerGetTokenResponseParams _ViewOwnerGetTokenResponseParamsFactory(ViewToken token) {
+ var mojo_factory_result = new ViewOwnerGetTokenResponseParams();
+ mojo_factory_result.token = token;
+ return mojo_factory_result;
+ }
+
+ dynamic handleMessage(bindings.ServiceMessage message) {
+ if (bindings.ControlMessageHandler.isControlMessage(message)) {
+ return bindings.ControlMessageHandler.handleMessage(this,
+ 0,
+ message);
+ }
+ assert(_impl != null);
+ switch (message.header.type) {
+ case _ViewOwner_getTokenName:
+ var params = _ViewOwnerGetTokenParams.deserialize(
+ message.payload);
+ var response = _impl.getToken(_ViewOwnerGetTokenResponseParamsFactory);
+ if (response is Future) {
+ return response.then((response) {
+ if (response != null) {
+ return buildResponseWithId(
+ response,
+ _ViewOwner_getTokenName,
+ message.header.requestId,
+ bindings.MessageHeader.kMessageIsResponse);
+ }
+ });
+ } else if (response != null) {
+ return buildResponseWithId(
+ response,
+ _ViewOwner_getTokenName,
+ message.header.requestId,
+ bindings.MessageHeader.kMessageIsResponse);
+ }
+ break;
+ default:
+ throw new bindings.MojoCodecError("Unexpected message name");
+ break;
+ }
+ return null;
+ }
+
+ ViewOwner get impl => _impl;
+ set impl(ViewOwner d) {
+ assert(_impl == null);
+ _impl = d;
+ }
+
+ String toString() {
+ var superString = super.toString();
+ return "ViewOwnerStub($superString)";
+ }
+
+ int get version => 0;
+
+ service_describer.ServiceDescription get serviceDescription =>
+ new _ViewOwnerServiceDescription();
+}
+
const int _View_onLayoutName = 0;
const int _View_onChildUnavailableName = 1;
@@ -1205,12 +1709,13 @@
new _ViewServiceDescription();
}
-const int _ViewHost_getServiceProviderName = 0;
-const int _ViewHost_createSceneName = 1;
-const int _ViewHost_requestLayoutName = 2;
-const int _ViewHost_addChildName = 3;
-const int _ViewHost_removeChildName = 4;
-const int _ViewHost_layoutChildName = 5;
+const int _ViewHost_getTokenName = 0;
+const int _ViewHost_getServiceProviderName = 1;
+const int _ViewHost_createSceneName = 2;
+const int _ViewHost_requestLayoutName = 3;
+const int _ViewHost_addChildName = 4;
+const int _ViewHost_removeChildName = 5;
+const int _ViewHost_layoutChildName = 6;
@@ -1224,11 +1729,12 @@
abstract class ViewHost {
static const String serviceName = null;
+ dynamic getToken([Function responseFactory = null]);
void getServiceProvider(Object serviceProvider);
void createScene(Object scene);
void requestLayout();
- void addChild(int childKey, ViewToken childViewToken);
- void removeChild(int childKey);
+ void addChild(int childKey, Object childViewOwner);
+ void removeChild(int childKey, Object transferredViewOwner);
dynamic layoutChild(int childKey,layouts_mojom.ViewLayoutParams childLayoutParams,[Function responseFactory = null]);
}
@@ -1253,6 +1759,26 @@
void handleResponse(bindings.ServiceMessage message) {
switch (message.header.type) {
+ case _ViewHost_getTokenName:
+ var r = ViewHostGetTokenResponseParams.deserialize(
+ message.payload);
+ if (!message.header.hasRequestId) {
+ proxyError("Expected a message with a valid request Id.");
+ return;
+ }
+ Completer c = completerMap[message.header.requestId];
+ if (c == null) {
+ proxyError(
+ "Message had unknown request Id: ${message.header.requestId}");
+ return;
+ }
+ completerMap.remove(message.header.requestId);
+ if (c.isCompleted) {
+ proxyError("Response completer already completed");
+ return;
+ }
+ c.complete(r);
+ break;
case _ViewHost_layoutChildName:
var r = ViewHostLayoutChildResponseParams.deserialize(
message.payload);
@@ -1291,6 +1817,14 @@
_ViewHostProxyImpl _proxyImpl;
_ViewHostProxyCalls(this._proxyImpl);
+ dynamic getToken([Function responseFactory = null]) {
+ var params = new _ViewHostGetTokenParams();
+ return _proxyImpl.sendMessageWithRequestId(
+ params,
+ _ViewHost_getTokenName,
+ -1,
+ bindings.MessageHeader.kMessageExpectsResponse);
+ }
void getServiceProvider(Object serviceProvider) {
if (!_proxyImpl.isBound) {
_proxyImpl.proxyError("The Proxy is closed.");
@@ -1317,23 +1851,24 @@
var params = new _ViewHostRequestLayoutParams();
_proxyImpl.sendMessage(params, _ViewHost_requestLayoutName);
}
- void addChild(int childKey, ViewToken childViewToken) {
+ void addChild(int childKey, Object childViewOwner) {
if (!_proxyImpl.isBound) {
_proxyImpl.proxyError("The Proxy is closed.");
return;
}
var params = new _ViewHostAddChildParams();
params.childKey = childKey;
- params.childViewToken = childViewToken;
+ params.childViewOwner = childViewOwner;
_proxyImpl.sendMessage(params, _ViewHost_addChildName);
}
- void removeChild(int childKey) {
+ void removeChild(int childKey, Object transferredViewOwner) {
if (!_proxyImpl.isBound) {
_proxyImpl.proxyError("The Proxy is closed.");
return;
}
var params = new _ViewHostRemoveChildParams();
params.childKey = childKey;
+ params.transferredViewOwner = transferredViewOwner;
_proxyImpl.sendMessage(params, _ViewHost_removeChildName);
}
dynamic layoutChild(int childKey,layouts_mojom.ViewLayoutParams childLayoutParams,[Function responseFactory = null]) {
@@ -1427,6 +1962,11 @@
}
+ ViewHostGetTokenResponseParams _ViewHostGetTokenResponseParamsFactory(ViewToken token) {
+ var mojo_factory_result = new ViewHostGetTokenResponseParams();
+ mojo_factory_result.token = token;
+ return mojo_factory_result;
+ }
ViewHostLayoutChildResponseParams _ViewHostLayoutChildResponseParamsFactory(layouts_mojom.ViewLayoutInfo info) {
var mojo_factory_result = new ViewHostLayoutChildResponseParams();
mojo_factory_result.info = info;
@@ -1441,6 +1981,28 @@
}
assert(_impl != null);
switch (message.header.type) {
+ case _ViewHost_getTokenName:
+ var params = _ViewHostGetTokenParams.deserialize(
+ message.payload);
+ var response = _impl.getToken(_ViewHostGetTokenResponseParamsFactory);
+ if (response is Future) {
+ return response.then((response) {
+ if (response != null) {
+ return buildResponseWithId(
+ response,
+ _ViewHost_getTokenName,
+ message.header.requestId,
+ bindings.MessageHeader.kMessageIsResponse);
+ }
+ });
+ } else if (response != null) {
+ return buildResponseWithId(
+ response,
+ _ViewHost_getTokenName,
+ message.header.requestId,
+ bindings.MessageHeader.kMessageIsResponse);
+ }
+ break;
case _ViewHost_getServiceProviderName:
var params = _ViewHostGetServiceProviderParams.deserialize(
message.payload);
@@ -1459,12 +2021,12 @@
case _ViewHost_addChildName:
var params = _ViewHostAddChildParams.deserialize(
message.payload);
- _impl.addChild(params.childKey, params.childViewToken);
+ _impl.addChild(params.childKey, params.childViewOwner);
break;
case _ViewHost_removeChildName:
var params = _ViewHostRemoveChildParams.deserialize(
message.payload);
- _impl.removeChild(params.childKey);
+ _impl.removeChild(params.childKey, params.transferredViewOwner);
break;
case _ViewHost_layoutChildName:
var params = _ViewHostLayoutChildParams.deserialize(
diff --git a/mojo/services/ui/views/interfaces/view_manager.mojom b/mojo/services/ui/views/interfaces/view_manager.mojom
index 66f3861..fd67ebd 100644
--- a/mojo/services/ui/views/interfaces/view_manager.mojom
+++ b/mojo/services/ui/views/interfaces/view_manager.mojom
@@ -28,22 +28,26 @@
// local environment. The view host is private to the view and should
// not be shared with anyone else.
//
- // The |view_token| is used as a transferable reference which can
+ // The |view_owner| is used as a transferable reference which can
// be passed to the view's intended container as part of a request to
// add the view as a child. The view manager itself does not describe
- // how this interaction should take place, only that the token should
+ // how this interaction should take place, only that ownership should
// eventually be passed back through the container's view host interface
- // as an argument to AddChild().
+ // as an argument to |ViewHost.AddChild()|.
//
// The |label| is an optional name to associate with the view for
// diagnostic purposes. The label will be truncated if it is longer
// than |kLabelMaxLength|.
//
// To unregister the view and cause it to be removed from the view tree,
- // simply close the |view| and/or |view_host| message pipes.
+ // simply close the |view|, |view_host|, or |view_owner| message pipes.
+ //
+ // TODO(jeffbrown): Refactor this so View becomes a ViewListener,
+ // ViewHost becomes View, and there are only two pipes here.
RegisterView(mojo.ui.View view,
mojo.ui.ViewHost& view_host,
- string? label) => (mojo.ui.ViewToken view_token);
+ mojo.ui.ViewOwner& view_owner,
+ string? label);
// Registers a view tree with the view manager.
//
@@ -62,5 +66,5 @@
// |view_tree_host| message pipes.
RegisterViewTree(mojo.ui.ViewTree view_tree,
mojo.ui.ViewTreeHost& view_tree_host,
- string? label) => (mojo.ui.ViewTreeToken view_tree_token);
+ string? label);
};
diff --git a/mojo/services/ui/views/interfaces/view_provider.mojom b/mojo/services/ui/views/interfaces/view_provider.mojom
index a1062de..d719f01 100644
--- a/mojo/services/ui/views/interfaces/view_provider.mojom
+++ b/mojo/services/ui/views/interfaces/view_provider.mojom
@@ -15,17 +15,19 @@
[ServiceName="mojo::ui::ViewProvider"]
interface ViewProvider {
// Creates and registers a view with the view manager and returns its
- // view token (as provided by |ViewManager.RegisterView()|).
+ // view owner which may subsequently be passed to |ViewHost.AddChild()|
+ // to attach the view to a view hierarchy.
//
- // Having received the view token, the caller should attach the view to
- // a view tree and lay it out.
+ // Implementors of this interface are responsible for creating the view
+ // and forwarding the |view_owner| interface request to
+ // |ViewManager.RegisterView()|.
//
// The caller may provide services to the view via the |services|
// service provider.
//
// The caller may receive services from the view via the |exposed_services|
// service provider.
- CreateView(mojo.ServiceProvider&? services,
- mojo.ServiceProvider? exposed_services) =>
- (ViewToken view_token);
+ CreateView(ViewOwner& view_owner,
+ mojo.ServiceProvider&? services,
+ mojo.ServiceProvider? exposed_services);
};
diff --git a/mojo/services/ui/views/interfaces/view_trees.mojom b/mojo/services/ui/views/interfaces/view_trees.mojom
index ff7a426..cb545ab 100644
--- a/mojo/services/ui/views/interfaces/view_trees.mojom
+++ b/mojo/services/ui/views/interfaces/view_trees.mojom
@@ -62,6 +62,9 @@
// ViewManager. To unregister the view tree, close its view tree
// and/or view tree host message pipes.
interface ViewTreeHost {
+ // Gets the view tree's token.
+ GetToken() => (ViewTreeToken token);
+
// Gets a service provider to access services which are associated with
// the view tree such as input, accessibility and editing capabilities.
// The view tree service provider is private to the view tree and should
@@ -81,23 +84,31 @@
// is set so that callbacks related to the root can be clearly distinguished
// across these changes.
//
- // If |root_view_token| refers to a view which is already unavailable
+ // If |root_view_owner| refers to a view which is already unavailable
// then the call proceeds as if it succeeded but an OnChildUnavailable()
// message will be sent.
//
- // If |root_view_token| refers to a view which already has a parent or is
+ // If |root_view_owner| refers to a view which already has a parent or is
// the root of a view tree then an OnChildUnavailable() or OnRootUnavailable()
// message will be sent to its old parent or root and the the view will be
// used as the root of the new view tree as usual. This special case also
// applies when the specified view is already the root of this view tree, in
// which case the behavior is similar to the view having been transferred to
// some other view tree and then back again.
- SetRoot(uint32 root_key, mojo.ui.ViewToken root_view_token);
+ //
+ // It is an error to call this function if the root has already been set;
+ // the connection will be closed.
+ SetRoot(uint32 root_key, mojo.ui.ViewOwner root_view_owner);
// Removes the root of the view tree.
//
- // Does nothing if the view tree currently does not have a root.
- ResetRoot();
+ // If |transferred_view_owner| is not null, associates it with the previously
+ // configured view or closes the |transferred_view_owner| message pipe
+ // if there was none.
+ //
+ // It is an error to call this function if the root was not previously set;
+ // the connection will be closed.
+ ResetRoot(mojo.ui.ViewOwner&? transferred_view_owner);
// Sets the layout parameters of the root of the view tree and retrieves
// its layout information.
diff --git a/mojo/services/ui/views/interfaces/views.mojom b/mojo/services/ui/views/interfaces/views.mojom
index 9dbfd31..39f770a 100644
--- a/mojo/services/ui/views/interfaces/views.mojom
+++ b/mojo/services/ui/views/interfaces/views.mojom
@@ -25,6 +25,17 @@
uint32 value;
};
+// A view owner provides access to the view's token and keeps the
+// view alive. When the view owner is closed, the view will be
+// unregistered from the view manager.
+//
+// This interface is only intended to be implemented by the view manager
+// to obtain the desired ownership semantics.
+interface ViewOwner {
+ // Gets the |ViewToken| associated with the view.
+ GetToken() => (ViewToken token);
+};
+
// A view is a graphical user interface component which is responsible
// for drawing and supporting user interactions in the area of the screen
// that it occupies.
@@ -100,6 +111,9 @@
// Each view obtains its own view host when registered with the ViewManager.
// To unregister the view, close its view host message pipe.
interface ViewHost {
+ // Gets the view's token.
+ GetToken() => (ViewToken token);
+
// Gets a service provider to access services which are associated with
// the view such as input, accessibility and editing capabilities.
// The view service provider is private to the view and should not be
@@ -123,11 +137,13 @@
// new layout due to a change in the view's layout information.
RequestLayout();
- // Adds the view referenced by |child_view_token| as a child and assigns
+ // Adds the view referenced by |child_view_owner| as a child and assigns
// it the provided |child_key| to identify it among its children.
// The parent may remove the child later by passing the same |child_key|
// to RemoveChild().
//
+ // This method takes ownership of the view.
+ //
// It is important for the parent to choose locally unique values for
// |child_key| to ensure that each child can be distinguished even as
// more children are added or removed. We recommend using a simple
@@ -136,12 +152,12 @@
// If the child becomes unavailable at any time prior to being removed
// then an OnChildUnavailable() message will be sent.
//
- // If |child_view_token| refers to a view which is already unavailable or
+ // If |child_view_owner| refers to a view which is already unavailable or
// if adding the view would create a cycle in the view tree then the
// call proceeds as if it succeeded but an OnChildUnavailable() message
// will be sent.
//
- // If |child_view_token| refers to a view which already has a parent or is
+ // If |child_view_owner| refers to a view which already has a parent or is
// the root of a view tree then an OnChildUnavailable() or OnRootUnavailable()
// message will be sent to its old parent or root and the the view will be
// (re-)added to its new parent as usual. This special case also applies
@@ -155,14 +171,18 @@
//
// It is an error to add a view whose |child_key| already appears
// in the view's list of children; the connection will be closed.
- AddChild(uint32 child_key, mojo.ui.ViewToken child_view_token);
+ AddChild(uint32 child_key, mojo.ui.ViewOwner child_view_owner);
// Removes the view referenced by |child_key| from the view's
// list of children.
//
+ // If |transferred_view_owner| is not null, associates it with the
+ // previously added child to allow it to be transferred elsewhere or
+ // closes the |transferred_view_owner| message pipe if there was none.
+ //
// It is an error to remove a view whose |child_key| does not appear
// in the parent's list of children; the connection will be closed.
- RemoveChild(uint32 child_key);
+ RemoveChild(uint32 child_key, mojo.ui.ViewOwner&? transferred_view_owner);
// Sets the layout parameters of the child view referenced by |child_key|
// and retrieves its layout information.
diff --git a/mojo/ui/base_view.cc b/mojo/ui/base_view.cc
index b58faf4..7ff0068 100644
--- a/mojo/ui/base_view.cc
+++ b/mojo/ui/base_view.cc
@@ -11,16 +11,16 @@
BaseView::BaseView(
mojo::ApplicationImpl* app_impl,
- const std::string& label,
- const mojo::ui::ViewProvider::CreateViewCallback& create_view_callback)
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request,
+ const std::string& label)
: app_impl_(app_impl), view_binding_(this) {
DCHECK(app_impl_);
app_impl_->ConnectToService("mojo:view_manager_service", &view_manager_);
mojo::ui::ViewPtr view;
view_binding_.Bind(mojo::GetProxy(&view));
- view_manager_->RegisterView(view.Pass(), mojo::GetProxy(&view_host_), label,
- create_view_callback);
+ view_manager_->RegisterView(view.Pass(), mojo::GetProxy(&view_host_),
+ view_owner_request.Pass(), label);
view_host_->CreateScene(mojo::GetProxy(&scene_));
view_host_->GetServiceProvider(mojo::GetProxy(&view_service_provider_));
}
diff --git a/mojo/ui/base_view.h b/mojo/ui/base_view.h
index 757dcb9..b2cccef 100644
--- a/mojo/ui/base_view.h
+++ b/mojo/ui/base_view.h
@@ -13,7 +13,6 @@
#include "mojo/public/interfaces/application/service_provider.mojom.h"
#include "mojo/services/gfx/composition/interfaces/scenes.mojom.h"
#include "mojo/services/ui/views/interfaces/view_manager.mojom.h"
-#include "mojo/services/ui/views/interfaces/view_provider.mojom.h"
#include "mojo/services/ui/views/interfaces/views.mojom.h"
namespace mojo {
@@ -29,10 +28,9 @@
public:
// TODO(jeffbrown): Consider switching this over to an ApplicationConnector
// but having ApplicationImpl is handy for simple examples.
- BaseView(
- mojo::ApplicationImpl* app_impl,
- const std::string& label,
- const mojo::ui::ViewProvider::CreateViewCallback& create_view_callback);
+ BaseView(mojo::ApplicationImpl* app_impl,
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request,
+ const std::string& label);
~BaseView() override;
diff --git a/mojo/ui/ganesh_view.cc b/mojo/ui/ganesh_view.cc
index 56962e5..395888a 100644
--- a/mojo/ui/ganesh_view.cc
+++ b/mojo/ui/ganesh_view.cc
@@ -13,9 +13,9 @@
GaneshView::GaneshView(
mojo::ApplicationImpl* app_impl,
- const std::string& label,
- const mojo::ui::ViewProvider::CreateViewCallback& create_view_callback)
- : BaseView(app_impl, label, create_view_callback),
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request,
+ const std::string& label)
+ : BaseView(app_impl, view_owner_request.Pass(), label),
gl_context_owner_(mojo::ApplicationConnectorPtr::Create(
app_impl->CreateApplicationConnector())
.get()),
diff --git a/mojo/ui/ganesh_view.h b/mojo/ui/ganesh_view.h
index 7cf29e9..7f28e35 100644
--- a/mojo/ui/ganesh_view.h
+++ b/mojo/ui/ganesh_view.h
@@ -21,10 +21,9 @@
// content for the scene.
class GaneshView : public BaseView {
public:
- GaneshView(
- mojo::ApplicationImpl* app_impl,
- const std::string& label,
- const mojo::ui::ViewProvider::CreateViewCallback& create_view_callback);
+ GaneshView(mojo::ApplicationImpl* app_impl,
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request,
+ const std::string& label);
~GaneshView() override;
diff --git a/mojo/ui/gl_view.cc b/mojo/ui/gl_view.cc
index d07b8cd..27b8c09 100644
--- a/mojo/ui/gl_view.cc
+++ b/mojo/ui/gl_view.cc
@@ -9,11 +9,10 @@
namespace mojo {
namespace ui {
-GLView::GLView(
- mojo::ApplicationImpl* app_impl,
- const std::string& label,
- const mojo::ui::ViewProvider::CreateViewCallback& create_view_callback)
- : BaseView(app_impl, label, create_view_callback),
+GLView::GLView(mojo::ApplicationImpl* app_impl,
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request,
+ const std::string& label)
+ : BaseView(app_impl, view_owner_request.Pass(), label),
gl_context_owner_(ApplicationConnectorPtr::Create(
app_impl->CreateApplicationConnector())
.get()),
diff --git a/mojo/ui/gl_view.h b/mojo/ui/gl_view.h
index 1f9796c..655cfd4 100644
--- a/mojo/ui/gl_view.h
+++ b/mojo/ui/gl_view.h
@@ -18,10 +18,9 @@
// content for the scene.
class GLView : public BaseView {
public:
- GLView(
- mojo::ApplicationImpl* app_impl,
- const std::string& label,
- const mojo::ui::ViewProvider::CreateViewCallback& create_view_callback);
+ GLView(mojo::ApplicationImpl* app_impl,
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request,
+ const std::string& label);
~GLView() override;
diff --git a/mojo/ui/view_provider_app.cc b/mojo/ui/view_provider_app.cc
index 40d5a5b..e7b9dd5 100644
--- a/mojo/ui/view_provider_app.cc
+++ b/mojo/ui/view_provider_app.cc
@@ -21,11 +21,11 @@
private:
// |ViewProvider|:
void CreateView(
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request,
mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::ServiceProviderPtr exposed_services,
- const mojo::ui::ViewProvider::CreateViewCallback& callback) override {
- app_->CreateView(this, view_provider_url_, services.Pass(),
- exposed_services.Pass(), callback);
+ mojo::ServiceProviderPtr exposed_services) override {
+ app_->CreateView(this, view_provider_url_, view_owner_request.Pass(),
+ services.Pass(), exposed_services.Pass());
}
ViewProviderApp* app_;
@@ -65,14 +65,11 @@
void ViewProviderApp::CreateView(
DelegatingViewProvider* provider,
const std::string& view_provider_url,
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request,
mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::ServiceProviderPtr exposed_services,
- const mojo::ui::ViewProvider::CreateViewCallback& callback) {
- if (!CreateView(view_provider_url, services.Pass(), exposed_services.Pass(),
- callback)) {
- bindings_.RemoveBindings(provider);
- delete provider;
- }
+ mojo::ServiceProviderPtr exposed_services) {
+ CreateView(view_provider_url, view_owner_request.Pass(), services.Pass(),
+ exposed_services.Pass());
}
} // namespace ui
diff --git a/mojo/ui/view_provider_app.h b/mojo/ui/view_provider_app.h
index 07668c6..f5c4b35 100644
--- a/mojo/ui/view_provider_app.h
+++ b/mojo/ui/view_provider_app.h
@@ -42,12 +42,19 @@
//
// The |view_provider_url| is the connection URL of the view provider request.
//
- // Returns true if successful, false if the view could not be created.
- virtual bool CreateView(
+ // The |view_owner_request| should be attached to the newly created view
+ // and closed or left pending if the view could not be created.
+ //
+ // The |services| parameter is used to receive services from the view
+ // on behalf of the caller.
+ //
+ // The |exposed_services| parameters is used to provide services to
+ // the view from the caller.
+ virtual void CreateView(
const std::string& view_provider_url,
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request,
mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::ServiceProviderPtr exposed_services,
- const mojo::ui::ViewProvider::CreateViewCallback& callback) = 0;
+ mojo::ServiceProviderPtr exposed_services) = 0;
private:
class DelegatingViewProvider;
@@ -56,11 +63,12 @@
void Create(mojo::ApplicationConnection* connection,
mojo::InterfaceRequest<mojo::ui::ViewProvider> request) override;
- void CreateView(DelegatingViewProvider* provider,
- const std::string& view_provider_url,
- mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::ServiceProviderPtr exposed_services,
- const mojo::ui::ViewProvider::CreateViewCallback& callback);
+ void CreateView(
+ DelegatingViewProvider* provider,
+ const std::string& view_provider_url,
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request,
+ mojo::InterfaceRequest<mojo::ServiceProvider> services,
+ mojo::ServiceProviderPtr exposed_services);
mojo::ApplicationImpl* app_impl_ = nullptr;
mojo::StrongBindingSet<mojo::ui::ViewProvider> bindings_;
diff --git a/services/ui/launcher/launcher_app.cc b/services/ui/launcher/launcher_app.cc
index 55a58be..08572b4 100644
--- a/services/ui/launcher/launcher_app.cc
+++ b/services/ui/launcher/launcher_app.cc
@@ -12,6 +12,7 @@
#include "mojo/public/c/system/main.h"
#include "mojo/public/cpp/application/application_connection.h"
#include "mojo/public/cpp/application/application_impl.h"
+#include "mojo/services/ui/views/interfaces/view_provider.mojom.h"
#include "services/ui/launcher/launcher_view_tree.h"
namespace launcher {
@@ -97,7 +98,8 @@
compositor_.get(), view_manager_.get(), context_provider.Pass(),
metrics.Pass(),
base::Bind(&LauncherApp::Shutdown, base::Unretained(this))));
- UpdateClientView();
+ view_tree_->SetRoot(client_view_owner_.Pass());
+
RequestUpdatedViewportMetrics();
}
@@ -123,28 +125,11 @@
void LauncherApp::LaunchClient(std::string app_url) {
DVLOG(1) << "Launching " << app_url;
- app_impl_->ConnectToService(app_url, &client_view_provider_);
- client_view_provider_.set_connection_error_handler(base::Bind(
- &LauncherApp::OnClientConnectionError, base::Unretained(this)));
+ mojo::ui::ViewProviderPtr client_view_provider;
+ app_impl_->ConnectToService(app_url, &client_view_provider);
- client_view_provider_->CreateView(
- nullptr, nullptr,
- base::Bind(&LauncherApp::OnClientViewCreated, base::Unretained(this)));
-}
-
-void LauncherApp::OnClientConnectionError() {
- LOG(ERROR) << "Exiting due to client application connection error.";
- Shutdown();
-}
-
-void LauncherApp::OnClientViewCreated(mojo::ui::ViewTokenPtr view_token) {
- client_view_token_ = view_token.Pass();
- UpdateClientView();
-}
-
-void LauncherApp::UpdateClientView() {
- if (view_tree_)
- view_tree_->SetRoot(client_view_token_.Clone());
+ client_view_provider->CreateView(mojo::GetProxy(&client_view_owner_), nullptr,
+ nullptr);
}
void LauncherApp::Shutdown() {
diff --git a/services/ui/launcher/launcher_app.h b/services/ui/launcher/launcher_app.h
index 9753961..7240b7e 100644
--- a/services/ui/launcher/launcher_app.h
+++ b/services/ui/launcher/launcher_app.h
@@ -13,7 +13,6 @@
#include "mojo/services/native_viewport/interfaces/native_viewport.mojom.h"
#include "mojo/services/native_viewport/interfaces/native_viewport_event_dispatcher.mojom.h"
#include "mojo/services/ui/views/interfaces/view_manager.mojom.h"
-#include "mojo/services/ui/views/interfaces/view_provider.mojom.h"
namespace launcher {
@@ -43,8 +42,6 @@
void RequestUpdatedViewportMetrics();
void LaunchClient(std::string app_url);
- void OnClientConnectionError();
- void OnClientViewCreated(mojo::ui::ViewTokenPtr view_token);
void UpdateClientView();
@@ -62,8 +59,7 @@
std::unique_ptr<LauncherViewTree> view_tree_;
- mojo::ui::ViewProviderPtr client_view_provider_;
- mojo::ui::ViewTokenPtr client_view_token_;
+ mojo::ui::ViewOwnerPtr client_view_owner_;
DISALLOW_COPY_AND_ASSIGN(LauncherApp);
};
diff --git a/services/ui/launcher/launcher_view_tree.cc b/services/ui/launcher/launcher_view_tree.cc
index 1c2beb6..3763e9b 100644
--- a/services/ui/launcher/launcher_view_tree.cc
+++ b/services/ui/launcher/launcher_view_tree.cc
@@ -48,10 +48,8 @@
// Register the view tree.
mojo::ui::ViewTreePtr view_tree;
view_tree_binding_.Bind(mojo::GetProxy(&view_tree));
- view_manager_->RegisterViewTree(
- view_tree.Pass(), mojo::GetProxy(&view_tree_host_), "Launcher",
- base::Bind(&LauncherViewTree::OnViewTreeRegistered,
- base::Unretained(this)));
+ view_manager_->RegisterViewTree(view_tree.Pass(),
+ mojo::GetProxy(&view_tree_host_), "Launcher");
view_tree_host_.set_connection_error_handler(base::Bind(
&LauncherViewTree::OnViewTreeConnectionError, base::Unretained(this)));
@@ -68,12 +66,14 @@
LauncherViewTree::~LauncherViewTree() {}
-void LauncherViewTree::SetRoot(mojo::ui::ViewTokenPtr token) {
- root_ = token.Pass();
- if (root_)
- view_tree_host_->SetRoot(++root_key_, root_.Clone());
- else
- view_tree_host_->ResetRoot();
+void LauncherViewTree::SetRoot(mojo::ui::ViewOwnerPtr owner) {
+ if (owner) {
+ view_tree_host_->SetRoot(++root_key_, owner.Pass());
+ root_was_set_ = true;
+ } else {
+ view_tree_host_->ResetRoot(nullptr);
+ root_was_set_ = false;
+ }
root_layout_info_.reset();
}
@@ -118,11 +118,6 @@
SetRootScene();
}
-void LauncherViewTree::OnViewTreeRegistered(
- mojo::ui::ViewTreeTokenPtr view_tree_token) {
- DVLOG(1) << "OnViewTreeRegistered: view_tree_token=" << view_tree_token;
-}
-
void LauncherViewTree::OnResourceUnavailable(
uint32_t resource_id,
const OnResourceUnavailableCallback& callback) {
@@ -145,7 +140,7 @@
}
void LauncherViewTree::LayoutRoot() {
- if (!root_)
+ if (!root_was_set_)
return;
auto params = mojo::ui::ViewLayoutParams::New();
diff --git a/services/ui/launcher/launcher_view_tree.h b/services/ui/launcher/launcher_view_tree.h
index 4c4a303..7118c38 100644
--- a/services/ui/launcher/launcher_view_tree.h
+++ b/services/ui/launcher/launcher_view_tree.h
@@ -26,7 +26,7 @@
~LauncherViewTree() override;
- void SetRoot(mojo::ui::ViewTokenPtr token);
+ void SetRoot(mojo::ui::ViewOwnerPtr owner);
void SetViewportMetrics(mojo::ViewportMetricsPtr viewport_metrics);
void DispatchEvent(mojo::EventPtr event);
@@ -47,7 +47,6 @@
void OnInputDispatcherConnectionError();
void OnSceneRegistered(mojo::gfx::composition::SceneTokenPtr scene_token);
- void OnViewTreeRegistered(mojo::ui::ViewTreeTokenPtr view_tree_token);
void LayoutRoot();
void OnLayoutResult(mojo::ui::ViewLayoutInfoPtr info);
@@ -76,8 +75,8 @@
mojo::ui::ViewTreeHostPtr view_tree_host_;
mojo::ui::InputDispatcherPtr input_dispatcher_;
- mojo::ui::ViewTokenPtr root_;
uint32_t root_key_ = 0u;
+ bool root_was_set_ = false;
mojo::ui::ViewLayoutInfoPtr root_layout_info_;
DISALLOW_COPY_AND_ASSIGN(LauncherViewTree);
diff --git a/services/ui/view_manager/BUILD.gn b/services/ui/view_manager/BUILD.gn
index 0a14325..21d322b 100644
--- a/services/ui/view_manager/BUILD.gn
+++ b/services/ui/view_manager/BUILD.gn
@@ -24,6 +24,8 @@
"view_registry.h",
"view_state.cc",
"view_state.h",
+ "view_stub.cc",
+ "view_stub.h",
"view_tree_host_impl.cc",
"view_tree_host_impl.h",
"view_tree_state.cc",
diff --git a/services/ui/view_manager/view_host_impl.cc b/services/ui/view_manager/view_host_impl.cc
index 976644e..7e32e89 100644
--- a/services/ui/view_manager/view_host_impl.cc
+++ b/services/ui/view_manager/view_host_impl.cc
@@ -5,20 +5,21 @@
#include "services/ui/view_manager/view_host_impl.h"
#include "base/bind.h"
-#include "base/bind_helpers.h"
+#include "services/ui/view_manager/view_registry.h"
+#include "services/ui/view_manager/view_state.h"
namespace view_manager {
-ViewHostImpl::ViewHostImpl(
- ViewRegistry* registry,
- ViewState* state,
- mojo::InterfaceRequest<mojo::ui::ViewHost> view_host_request)
- : registry_(registry),
- state_(state),
- binding_(this, view_host_request.Pass()) {}
+ViewHostImpl::ViewHostImpl(ViewRegistry* registry, ViewState* state)
+ : registry_(registry), state_(state) {}
ViewHostImpl::~ViewHostImpl() {}
+void ViewHostImpl::GetToken(
+ const mojo::ui::ViewHost::GetTokenCallback& callback) {
+ callback.Run(state_->view_token()->Clone());
+}
+
void ViewHostImpl::GetServiceProvider(
mojo::InterfaceRequest<mojo::ServiceProvider> service_provider_request) {
service_provider_bindings_.AddBinding(this, service_provider_request.Pass());
@@ -34,12 +35,15 @@
}
void ViewHostImpl::AddChild(uint32_t child_key,
- mojo::ui::ViewTokenPtr child_view_token) {
- registry_->AddChild(state_, child_key, child_view_token.Pass());
+ mojo::ui::ViewOwnerPtr child_view_owner) {
+ registry_->AddChild(state_, child_key, child_view_owner.Pass());
}
-void ViewHostImpl::RemoveChild(uint32_t child_key) {
- registry_->RemoveChild(state_, child_key);
+void ViewHostImpl::RemoveChild(uint32_t child_key,
+ mojo::InterfaceRequest<mojo::ui::ViewOwner>
+ transferred_view_owner_request) {
+ registry_->RemoveChild(state_, child_key,
+ transferred_view_owner_request.Pass());
}
static void RunLayoutChildCallback(
diff --git a/services/ui/view_manager/view_host_impl.h b/services/ui/view_manager/view_host_impl.h
index 907c8f1..2ed54f6 100644
--- a/services/ui/view_manager/view_host_impl.h
+++ b/services/ui/view_manager/view_host_impl.h
@@ -7,36 +7,35 @@
#include "base/macros.h"
#include "mojo/common/binding_set.h"
-#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/services/ui/views/interfaces/views.mojom.h"
-#include "services/ui/view_manager/view_registry.h"
-#include "services/ui/view_manager/view_state.h"
namespace view_manager {
+class ViewRegistry;
+class ViewState;
+
// ViewHost interface implementation.
// This object is owned by its associated ViewState.
-class ViewHostImpl : public mojo::ui::ViewHost, public mojo::ServiceProvider {
+class ViewHostImpl : public mojo::ui::ViewHost,
+ public mojo::ui::ViewOwner,
+ public mojo::ServiceProvider {
public:
- ViewHostImpl(ViewRegistry* registry,
- ViewState* state,
- mojo::InterfaceRequest<mojo::ui::ViewHost> view_host_request);
+ ViewHostImpl(ViewRegistry* registry, ViewState* state);
~ViewHostImpl() override;
- void set_view_host_connection_error_handler(const base::Closure& handler) {
- binding_.set_connection_error_handler(handler);
- }
-
private:
// |ViewHost|:
+ void GetToken(const mojo::ui::ViewHost::GetTokenCallback& callback) override;
void GetServiceProvider(mojo::InterfaceRequest<mojo::ServiceProvider>
service_provider_request) override;
void CreateScene(
mojo::InterfaceRequest<mojo::gfx::composition::Scene> scene) override;
void RequestLayout() override;
void AddChild(uint32_t child_key,
- mojo::ui::ViewTokenPtr child_view_token) override;
- void RemoveChild(uint32_t child_key) override;
+ mojo::ui::ViewOwnerPtr child_view_owner) override;
+ void RemoveChild(uint32_t child_key,
+ mojo::InterfaceRequest<mojo::ui::ViewOwner>
+ transferred_view_owner_request) override;
void LayoutChild(uint32_t child_key,
mojo::ui::ViewLayoutParamsPtr child_layout_params,
const LayoutChildCallback& callback) override;
@@ -47,7 +46,6 @@
ViewRegistry* const registry_;
ViewState* const state_;
- mojo::Binding<mojo::ui::ViewHost> binding_;
mojo::BindingSet<mojo::ServiceProvider> service_provider_bindings_;
DISALLOW_COPY_AND_ASSIGN(ViewHostImpl);
diff --git a/services/ui/view_manager/view_manager_impl.cc b/services/ui/view_manager/view_manager_impl.cc
index fa66868..22e9483 100644
--- a/services/ui/view_manager/view_manager_impl.cc
+++ b/services/ui/view_manager/view_manager_impl.cc
@@ -17,21 +17,18 @@
void ViewManagerImpl::RegisterView(
mojo::ui::ViewPtr view,
mojo::InterfaceRequest<mojo::ui::ViewHost> view_host_request,
- const mojo::String& label,
- const RegisterViewCallback& callback) {
- mojo::ui::ViewTokenPtr view_token =
- registry_->RegisterView(view.Pass(), view_host_request.Pass(), label);
- callback.Run(view_token.Pass());
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request,
+ const mojo::String& label) {
+ registry_->RegisterView(view.Pass(), view_host_request.Pass(),
+ view_owner_request.Pass(), label);
}
void ViewManagerImpl::RegisterViewTree(
mojo::ui::ViewTreePtr view_tree,
mojo::InterfaceRequest<mojo::ui::ViewTreeHost> view_tree_host_request,
- const mojo::String& label,
- const RegisterViewTreeCallback& callback) {
- mojo::ui::ViewTreeTokenPtr view_tree_token = registry_->RegisterViewTree(
- view_tree.Pass(), view_tree_host_request.Pass(), label);
- callback.Run(view_tree_token.Pass());
+ const mojo::String& label) {
+ registry_->RegisterViewTree(view_tree.Pass(), view_tree_host_request.Pass(),
+ label);
}
} // namespace view_manager
diff --git a/services/ui/view_manager/view_manager_impl.h b/services/ui/view_manager/view_manager_impl.h
index 89c463f..fcb490e 100644
--- a/services/ui/view_manager/view_manager_impl.h
+++ b/services/ui/view_manager/view_manager_impl.h
@@ -22,13 +22,12 @@
void RegisterView(
mojo::ui::ViewPtr view,
mojo::InterfaceRequest<mojo::ui::ViewHost> view_host_request,
- const mojo::String& label,
- const RegisterViewCallback& callback) override;
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request,
+ const mojo::String& label) override;
void RegisterViewTree(
mojo::ui::ViewTreePtr view_tree,
mojo::InterfaceRequest<mojo::ui::ViewTreeHost> view_tree_host_request,
- const mojo::String& label,
- const RegisterViewTreeCallback& callback) override;
+ const mojo::String& label) override;
ViewRegistry* registry_;
diff --git a/services/ui/view_manager/view_registry.cc b/services/ui/view_manager/view_registry.cc
index a92c7f1..c86177a 100644
--- a/services/ui/view_manager/view_registry.cc
+++ b/services/ui/view_manager/view_registry.cc
@@ -14,8 +14,8 @@
#include "services/ui/view_manager/view_tree_host_impl.h"
namespace view_manager {
-
-static bool AreViewLayoutParamsValid(const mojo::ui::ViewLayoutParams* params) {
+namespace {
+bool AreViewLayoutParamsValid(const mojo::ui::ViewLayoutParams* params) {
return params && params->constraints && params->constraints->min_width >= 0 &&
params->constraints->max_width >= params->constraints->min_width &&
params->constraints->min_height >= 0 &&
@@ -23,6 +23,14 @@
params->device_pixel_ratio > 0;
}
+bool IsSizeInBounds(mojo::ui::BoxConstraints* constraints, mojo::Size* size) {
+ return size && size->width >= constraints->min_width &&
+ size->width <= constraints->max_width &&
+ size->height >= constraints->min_height &&
+ size->height <= constraints->max_height;
+}
+} // namespace
+
ViewRegistry::ViewRegistry(mojo::gfx::composition::CompositorPtr compositor)
: compositor_(compositor.Pass()) {}
@@ -36,11 +44,14 @@
connection_error_callback);
}
-mojo::ui::ViewTokenPtr ViewRegistry::RegisterView(
+void ViewRegistry::RegisterView(
mojo::ui::ViewPtr view,
mojo::InterfaceRequest<mojo::ui::ViewHost> view_host_request,
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request,
const mojo::String& label) {
DCHECK(view);
+ DCHECK(view_host_request.is_pending());
+ DCHECK(view_owner_request.is_pending());
auto view_token = mojo::ui::ViewToken::New();
view_token->value = next_view_token_value_++;
@@ -51,26 +62,19 @@
std::string sanitized_label =
label.get().substr(0, mojo::ui::kLabelMaxLength);
ViewState* view_state =
- new ViewState(view.Pass(), view_token.Pass(), sanitized_label);
- ViewHostImpl* view_host =
- new ViewHostImpl(this, view_state, view_host_request.Pass());
- view_state->set_view_host(view_host);
- view_state->set_view_connection_error_handler(
- base::Bind(&ViewRegistry::OnViewConnectionError, base::Unretained(this),
- view_state));
- view_host->set_view_host_connection_error_handler(
- base::Bind(&ViewRegistry::OnViewConnectionError, base::Unretained(this),
- view_state));
+ new ViewState(this, view.Pass(), view_token.Pass(),
+ view_host_request.Pass(), sanitized_label);
+ view_state->BindOwner(view_owner_request.Pass());
// Add to registry and return token.
views_by_token_.insert({view_state->view_token()->value, view_state});
DVLOG(1) << "RegisterView: view=" << view_state;
- return view_state->view_token()->Clone();
}
-void ViewRegistry::OnViewConnectionError(ViewState* view_state) {
+void ViewRegistry::OnViewDied(ViewState* view_state,
+ const std::string& reason) {
DCHECK(IsViewStateRegisteredDebug(view_state));
- DVLOG(1) << "OnViewConnectionError: view=" << view_state;
+ DVLOG(1) << "OnViewDied: view=" << view_state << ", reason=" << reason;
UnregisterView(view_state);
}
@@ -80,18 +84,25 @@
DVLOG(1) << "UnregisterView: view=" << view_state;
// Remove from parent or roots.
+ // This may send a view unavailable message to the view's parent or tree.
HijackView(view_state);
+ // Recursively unregister all children since they will become unowned
+ // at this point taking care to unlink each one before its unregistration.
+ for (auto& child : view_state->UnlinkAllChildren())
+ UnregisterViewStub(std::move(child));
+
// Remove from registry.
views_by_token_.erase(view_state->view_token()->value);
delete view_state;
}
-mojo::ui::ViewTreeTokenPtr ViewRegistry::RegisterViewTree(
+void ViewRegistry::RegisterViewTree(
mojo::ui::ViewTreePtr view_tree,
mojo::InterfaceRequest<mojo::ui::ViewTreeHost> view_tree_host_request,
const mojo::String& label) {
DCHECK(view_tree);
+ DCHECK(view_tree_host_request.is_pending());
auto view_tree_token = mojo::ui::ViewTreeToken::New();
view_tree_token->value = next_view_tree_token_value_++;
@@ -101,28 +112,20 @@
// Create the state and bind host to it.
std::string sanitized_label =
label.get().substr(0, mojo::ui::kLabelMaxLength);
- ViewTreeState* tree_state = new ViewTreeState(
- view_tree.Pass(), view_tree_token.Pass(), sanitized_label);
- ViewTreeHostImpl* tree_host =
- new ViewTreeHostImpl(this, tree_state, view_tree_host_request.Pass());
- tree_state->set_view_tree_host(tree_host);
- tree_state->set_view_tree_connection_error_handler(
- base::Bind(&ViewRegistry::OnViewTreeConnectionError,
- base::Unretained(this), tree_state));
- tree_host->set_view_tree_host_connection_error_handler(
- base::Bind(&ViewRegistry::OnViewTreeConnectionError,
- base::Unretained(this), tree_state));
+ ViewTreeState* tree_state =
+ new ViewTreeState(this, view_tree.Pass(), view_tree_token.Pass(),
+ view_tree_host_request.Pass(), sanitized_label);
// Add to registry.
view_trees_by_token_.insert(
{tree_state->view_tree_token()->value, tree_state});
DVLOG(1) << "RegisterViewTree: tree=" << tree_state;
- return tree_state->view_tree_token()->Clone();
}
-void ViewRegistry::OnViewTreeConnectionError(ViewTreeState* tree_state) {
+void ViewRegistry::OnViewTreeDied(ViewTreeState* tree_state,
+ const std::string& reason) {
DCHECK(IsViewTreeStateRegisteredDebug(tree_state));
- DVLOG(1) << "OnViewTreeConnectionError: tree=" << tree_state;
+ DVLOG(1) << "OnViewTreeDied: tree=" << tree_state << ", reason=" << reason;
UnregisterViewTree(tree_state);
}
@@ -133,7 +136,7 @@
// Unlink the root if needed.
if (tree_state->root())
- UnlinkRoot(tree_state);
+ UnregisterViewStub(tree_state->UnlinkRoot());
// Remove from registry.
view_trees_by_token_.erase(tree_state->view_tree_token()->value);
@@ -144,6 +147,7 @@
ViewState* view_state,
mojo::InterfaceRequest<mojo::gfx::composition::Scene> scene) {
DCHECK(IsViewStateRegisteredDebug(view_state));
+ DCHECK(scene.is_pending());
DVLOG(1) << "CreateScene: view=" << view_state;
compositor_->CreateScene(
@@ -175,46 +179,40 @@
void ViewRegistry::AddChild(ViewState* parent_state,
uint32_t child_key,
- mojo::ui::ViewTokenPtr child_view_token) {
+ mojo::ui::ViewOwnerPtr child_view_owner) {
DCHECK(IsViewStateRegisteredDebug(parent_state));
- DCHECK(child_view_token);
- DVLOG(1) << "AddChild: parent=" << parent_state << ", child_key=" << child_key
- << ", child=" << child_view_token;
+ DCHECK(child_view_owner);
+ DVLOG(1) << "AddChild: parent=" << parent_state
+ << ", child_key=" << child_key;
- // Check for duplicate children.
+ // Ensure there are no other children with the same key.
if (parent_state->children().find(child_key) !=
parent_state->children().end()) {
LOG(ERROR) << "View attempted to add a child with a duplicate key: "
- << "parent=" << parent_state << ", child_key=" << child_key
- << ", child=" << child_view_token;
+ << "parent=" << parent_state << ", child_key=" << child_key;
UnregisterView(parent_state);
return;
}
- // Check whether the desired child view still exists.
- // Adding a non-existent child still succeeds but the view manager will
- // immediately report it as being unavailable.
- ViewState* child_state = FindView(child_view_token->value);
- if (!child_state) {
- LinkChildAsUnavailable(parent_state, child_key);
- return;
- }
+ // Add a stub, pending resolution of the view owner.
+ parent_state->LinkChild(child_key, std::unique_ptr<ViewStub>(new ViewStub(
+ this, child_view_owner.Pass())));
- // Check whether the child needs to be reparented.
- // The old parent will receive an unavailable event. For interface symmetry,
- // we deliberately do this even if the old and new parents are the same.
- HijackView(child_state);
-
- // Link the child into its new parent.
- LinkChild(parent_state, child_key, child_state);
+ // Schedule layout of the parent on behalf of its newly added child.
+ // We don't need to schedule layout of the child until the parent provides
+ // new layout parameters.
+ InvalidateLayoutForChild(parent_state, child_key);
}
-void ViewRegistry::RemoveChild(ViewState* parent_state, uint32_t child_key) {
+void ViewRegistry::RemoveChild(ViewState* parent_state,
+ uint32_t child_key,
+ mojo::InterfaceRequest<mojo::ui::ViewOwner>
+ transferred_view_owner_request) {
DCHECK(IsViewStateRegisteredDebug(parent_state));
DVLOG(1) << "RemoveChild: parent=" << parent_state
<< ", child_key=" << child_key;
- // Check whether the child key exists in the parent.
+ // Ensure the child key exists in the parent.
auto child_it = parent_state->children().find(child_key);
if (child_it == parent_state->children().end()) {
LOG(ERROR) << "View attempted to remove a child with an invalid key: "
@@ -224,7 +222,13 @@
}
// Unlink the child from its parent.
- UnlinkChild(parent_state, child_it);
+ TransferOrUnregisterViewStub(parent_state->UnlinkChild(child_key),
+ transferred_view_owner_request.Pass());
+
+ // Schedule layout for the parent now that it has lost its child.
+ // We don't need to schedule layout for the child itself since it will
+ // retain its old layout parameters until it is reparented.
+ InvalidateLayout(parent_state);
}
void ViewRegistry::LayoutChild(
@@ -260,7 +264,7 @@
return;
}
- SetLayout(child_it->second, child_layout_params.Pass(), callback);
+ SetLayout(child_it->second.get(), child_layout_params.Pass(), callback);
}
void ViewRegistry::ConnectToViewService(
@@ -282,32 +286,52 @@
void ViewRegistry::SetRoot(ViewTreeState* tree_state,
uint32_t root_key,
- mojo::ui::ViewTokenPtr root_view_token) {
+ mojo::ui::ViewOwnerPtr root_view_owner) {
DCHECK(IsViewTreeStateRegisteredDebug(tree_state));
- DCHECK(root_view_token);
- DVLOG(1) << "SetRoot: tree=" << tree_state << ", root_key=" << root_key
- << ", root=" << root_view_token;
+ DCHECK(root_view_owner);
+ DVLOG(1) << "SetRoot: tree=" << tree_state << ", root_key=" << root_key;
- // Check whether the desired root view still exists.
- // Using a non-existent root view still succeeds but the view manager will
- // immediately report it as being unavailable.
- ViewState* root_state = FindView(root_view_token->value);
- if (root_state) {
- HijackView(root_state);
- LinkRoot(tree_state, root_state, root_key);
- } else {
- SendRootUnavailable(tree_state, root_key);
+ // Ensure there isn't already a root.
+ if (tree_state->root()) {
+ LOG(ERROR)
+ << "View tree attempted to set the root while one is already set: tree="
+ << tree_state << ", root_key=" << root_key;
+ UnregisterViewTree(tree_state);
+ return;
}
- tree_state->set_explicit_root(true);
+
+ // Set the root to a stub, pending resolution of the view owner.
+ tree_state->LinkRoot(root_key, std::unique_ptr<ViewStub>(new ViewStub(
+ this, root_view_owner.Pass())));
+
+ // Schedule layout of the tree on behalf of its newly added root.
+ // We don't need to schedule layout of the root until the tree provides
+ // new layout parameters.
+ InvalidateLayoutForRoot(tree_state);
}
-void ViewRegistry::ResetRoot(ViewTreeState* tree_state) {
+void ViewRegistry::ResetRoot(ViewTreeState* tree_state,
+ mojo::InterfaceRequest<mojo::ui::ViewOwner>
+ transferred_view_owner_request) {
DCHECK(IsViewTreeStateRegisteredDebug(tree_state));
DVLOG(1) << "ResetRoot: tree=" << tree_state;
- if (tree_state->root())
- UnlinkRoot(tree_state);
- tree_state->set_explicit_root(false);
+ // Ensure there is a root.
+ if (!tree_state->root()) {
+ LOG(ERROR)
+ << "View tree attempted to reset the root but there is none: tree="
+ << tree_state;
+ UnregisterViewTree(tree_state);
+ return;
+ }
+
+ // Unlink the root from its tree.
+ TransferOrUnregisterViewStub(tree_state->UnlinkRoot(),
+ transferred_view_owner_request.Pass());
+
+ // Note: We don't need to schedule layout for the root since it will retain
+ // its old layout parameters. And there's no need to tell the tree
+ // either since it won't have any work to do. So we're done.
}
void ViewRegistry::LayoutRoot(ViewTreeState* tree_state,
@@ -331,8 +355,8 @@
// Check whether the client called LayoutRoot without first having actually
// set a root.
- if (!tree_state->explicit_root()) {
- LOG(ERROR) << "View tree attempted to layout the rout without having "
+ if (!tree_state->root()) {
+ LOG(ERROR) << "View tree attempted to layout the root without having "
"set one first: tree="
<< tree_state << ", root_layout_params=" << root_layout_params;
UnregisterViewTree(tree_state);
@@ -340,13 +364,6 @@
return;
}
- // Check whether the root is unavailable and therefore cannot be laid out.
- // This is not an error.
- if (!tree_state->root()) {
- callback.Run(nullptr);
- return;
- }
-
SetLayout(tree_state->root(), root_layout_params.Pass(), callback);
}
@@ -366,137 +383,159 @@
return it != views_by_token_.end() ? it->second : nullptr;
}
-void ViewRegistry::LinkChild(ViewState* parent_state,
- uint32_t child_key,
- ViewState* child_state) {
- DCHECK(IsViewStateRegisteredDebug(parent_state));
- DCHECK(parent_state->children().find(child_key) ==
- parent_state->children().end());
- DCHECK(IsViewStateRegisteredDebug(child_state));
-
- DVLOG(2) << "Added child " << child_key << " {" << child_state->label()
- << "} to parent {" << parent_state->label() << "}";
-
- parent_state->children().insert({child_key, child_state});
- child_state->SetParent(parent_state, child_key);
-
- // Schedule layout of the parent on behalf of its newly added child.
- // We don't need to schedule layout of the child until the parent provides
- // new layout parameters.
- InvalidateLayoutForChild(parent_state, child_key);
-}
-
-void ViewRegistry::LinkChildAsUnavailable(ViewState* parent_state,
- uint32_t child_key) {
- DCHECK(IsViewStateRegisteredDebug(parent_state));
- DCHECK(parent_state->children().find(child_key) ==
- parent_state->children().end());
-
- DVLOG(2) << "Added unavailable child " << child_key << " to parent {"
- << parent_state->label() << "}";
-
- parent_state->children().insert({child_key, nullptr});
- SendChildUnavailable(parent_state, child_key);
-
- // Don't schedule layout for the parent just yet. Wait for it to
- // remove its child in response to the OnChildUnavailable notification.
-}
-
-void ViewRegistry::MarkChildAsUnavailable(ViewState* parent_state,
- uint32_t child_key) {
- DCHECK(IsViewStateRegisteredDebug(parent_state));
- auto child_it = parent_state->children().find(child_key);
- DCHECK(child_it != parent_state->children().end());
- DCHECK(child_it->second);
-
- DVLOG(2) << "Marked unavailable child " << child_key << " {"
- << child_it->second->label() << "} from parent {"
- << parent_state->label() << "}";
-
- ResetStateWhenUnlinking(child_it->second);
- child_it->second->ResetContainer();
- child_it->second = nullptr;
- SendChildUnavailable(parent_state, child_key);
-
- // Don't schedule layout for the parent just yet. Wait for it to
- // remove its child in response to the OnChildUnavailable notification.
- // We don't need to schedule layout for the child either since it will
- // retain its old layout parameters.
-}
-
-void ViewRegistry::UnlinkChild(ViewState* parent_state,
- ViewState::ChildrenMap::iterator child_it) {
- DCHECK(IsViewStateRegisteredDebug(parent_state));
- DCHECK(child_it != parent_state->children().end());
-
- ViewState* child_state = child_it->second;
- if (child_state) {
- DVLOG(2) << "Removed child " << child_state->key() << " {"
- << child_state->label() << "} from parent {"
- << parent_state->label() << "}";
- ResetStateWhenUnlinking(child_it->second);
- child_state->ResetContainer();
- } else {
- DVLOG(2) << "Removed unavailable child " << child_it->first
- << "} from parent {" << parent_state->label() << "}";
- }
- parent_state->children().erase(child_it);
-
- // Schedule layout for the parent now that it has lost its child.
- // We don't need to schedule layout for the child itself since it will
- // retain its old layout parameters.
- InvalidateLayout(parent_state);
-}
-
ViewTreeState* ViewRegistry::FindViewTree(uint32_t view_tree_token_value) {
auto it = view_trees_by_token_.find(view_tree_token_value);
return it != view_trees_by_token_.end() ? it->second : nullptr;
}
-void ViewRegistry::LinkRoot(ViewTreeState* tree_state,
- ViewState* root_state,
- uint32_t root_key) {
- DCHECK(IsViewTreeStateRegisteredDebug(tree_state));
- DCHECK(IsViewStateRegisteredDebug(root_state));
- DCHECK(!tree_state->root());
- DCHECK(!root_state->parent());
-
- DVLOG(2) << "Linked view tree root " << root_key << " {"
- << root_state->label() << "}";
-
- tree_state->SetRoot(root_state, root_key);
-
- // Schedule layout of the tree on behalf of its newly added root.
- // We don't need to schedule layout of the root until the tree provides
- // new layout parameters.
- InvalidateLayoutForRoot(tree_state);
-}
-
-void ViewRegistry::UnlinkRoot(ViewTreeState* tree_state) {
- DCHECK(IsViewTreeStateRegisteredDebug(tree_state));
- DCHECK(tree_state->root());
-
- DVLOG(2) << "Unlinked view tree root " << tree_state->root()->key() << " {"
- << tree_state->root()->label() << "}";
-
- ResetStateWhenUnlinking(tree_state->root());
- tree_state->ResetRoot();
-
- // We don't need to schedule layout for the root since it will retain
- // its old layout parameters.
-}
-
void ViewRegistry::HijackView(ViewState* view_state) {
- if (view_state->parent()) {
- MarkChildAsUnavailable(view_state->parent(), view_state->key());
- } else if (view_state->tree()) {
- ViewTreeState* tree_state = view_state->tree();
- uint32_t root_key = tree_state->root()->key();
- UnlinkRoot(tree_state);
- SendRootUnavailable(tree_state, root_key);
+ DCHECK(IsViewStateRegisteredDebug(view_state));
+
+ ViewStub* view_stub = view_state->view_stub();
+ if (view_stub)
+ ReleaseViewStubAndNotify(view_stub);
+}
+
+void ViewRegistry::OnViewResolved(ViewStub* view_stub,
+ mojo::ui::ViewTokenPtr view_token) {
+ DCHECK(view_stub);
+
+ ViewState* view_state = view_token ? FindView(view_token->value) : nullptr;
+ if (view_state)
+ AttachViewStubAndNotify(view_stub, view_state);
+ else
+ ReleaseViewStubAndNotify(view_stub);
+}
+
+void ViewRegistry::AttachViewStubAndNotify(ViewStub* view_stub,
+ ViewState* view_state) {
+ DCHECK(view_stub);
+
+ view_state->ReleaseOwner(); // don't need the ViewOwner pipe anymore
+ view_stub->AttachView(view_state);
+
+ if (view_stub->pending_layout_request()) {
+ view_state->pending_layout_requests().push_back(
+ std::move(view_stub->pending_layout_request()));
+ IssueNextViewLayoutRequest(view_state);
}
}
+void ViewRegistry::ReleaseViewStubAndNotify(ViewStub* view_stub) {
+ DCHECK(view_stub);
+
+ view_stub->ReleaseView();
+
+ if (view_stub->parent())
+ SendChildUnavailable(view_stub->parent(), view_stub->key());
+ else if (view_stub->tree())
+ SendRootUnavailable(view_stub->tree(), view_stub->key());
+
+ // Note: We don't need to schedule layout for the previous owner.
+ // We can simply wait for it to remove its unavailable child or root in
+ // response to the notification at which point layout will occur.
+ // We don't need to schedule layout for the child either since it will
+ // retain its old layout parameters.
+}
+
+void ViewRegistry::TransferOrUnregisterViewStub(
+ std::unique_ptr<ViewStub> view_stub,
+ mojo::InterfaceRequest<mojo::ui::ViewOwner>
+ transferred_view_owner_request) {
+ DCHECK(view_stub);
+
+ if (transferred_view_owner_request.is_pending()) {
+ if (view_stub->state())
+ view_stub->state()->BindOwner(transferred_view_owner_request.Pass());
+ else if (view_stub->is_pending())
+ CHECK(false); // TODO(jeffbrown): Handle transfer of pending view
+ } else {
+ UnregisterViewStub(std::move(view_stub));
+ }
+}
+
+void ViewRegistry::UnregisterViewStub(std::unique_ptr<ViewStub> view_stub) {
+ DCHECK(view_stub);
+
+ if (view_stub->state())
+ UnregisterView(view_stub->state());
+}
+
+void ViewRegistry::SetLayout(ViewStub* view_stub,
+ mojo::ui::ViewLayoutParamsPtr layout_params,
+ const ViewLayoutCallback& callback) {
+ DCHECK(view_stub);
+ DCHECK(AreViewLayoutParamsValid(layout_params.get()));
+
+ // Immediately discard layout requests on unavailable views.
+ if (view_stub->is_unavailable()) {
+ callback.Run(nullptr);
+ return;
+ }
+
+ // For pending views, only remember the most recent distinct layout request.
+ if (view_stub->is_pending()) {
+ if (!view_stub->pending_layout_request() ||
+ !view_stub->pending_layout_request()->layout_params()->Equals(
+ *layout_params)) {
+ view_stub->pending_layout_request().reset(
+ new ViewLayoutRequest(layout_params.Pass()));
+ }
+ view_stub->pending_layout_request()->AddCallback(callback);
+ return;
+ }
+
+ // For actual views, maintain a queue of pending layout requests.
+ ViewState* view_state = view_stub->state();
+ DCHECK(view_state);
+ DCHECK(!view_stub->pending_layout_request());
+
+ // Check whether the currently cached layout parameters are the same
+ // and we already have a result and we have no pending layout requests.
+ if (view_state->pending_layout_requests().empty() &&
+ view_state->layout_params() &&
+ view_state->layout_params()->Equals(*layout_params)) {
+ mojo::ui::ViewLayoutInfoPtr info = view_state->CreateLayoutInfo();
+ if (info) {
+ DVLOG(2) << "Layout cache hit";
+ view_state->set_scene_changed_since_last_report(false);
+ callback.Run(info.Pass());
+ return;
+ }
+ }
+
+ // Check whether the layout parameters are different from the most
+ // recent pending layout request if we have one.
+ if (view_state->pending_layout_requests().empty() ||
+ !view_state->pending_layout_requests().back()->layout_params()->Equals(
+ *layout_params)) {
+ // Enqueue a new request for these parameters.
+ EnqueueLayoutRequest(view_state, layout_params.Pass());
+ }
+
+ // Enlist ourselves into the callbacks for the pending request.
+ view_state->pending_layout_requests().back()->AddCallback(callback);
+ IssueNextViewLayoutRequest(view_state);
+}
+
+void ViewRegistry::EnqueueLayoutRequest(
+ ViewState* view_state,
+ mojo::ui::ViewLayoutParamsPtr layout_params) {
+ DCHECK(view_state);
+ DCHECK(AreViewLayoutParamsValid(layout_params.get()));
+
+ // Drop the previous layout request if it hasn't been issued yet.
+ // This may cause callbacks to be invoked will null information.
+ if (!view_state->pending_layout_requests().empty() &&
+ !view_state->pending_layout_requests().back()->issued())
+ view_state->pending_layout_requests().pop_back();
+
+ // Enqueue the new request.
+ view_state->pending_layout_requests().emplace_back(
+ std::unique_ptr<ViewLayoutRequest>(
+ new ViewLayoutRequest(layout_params.Pass())));
+}
+
void ViewRegistry::InvalidateLayout(ViewState* view_state) {
DCHECK(IsViewStateRegisteredDebug(view_state));
@@ -531,138 +570,42 @@
}
}
-void ViewRegistry::SetLayout(ViewState* view_state,
- mojo::ui::ViewLayoutParamsPtr layout_params,
- const ViewLayoutCallback& callback) {
- DCHECK(IsViewStateRegisteredDebug(view_state));
- DCHECK(AreViewLayoutParamsValid(layout_params.get()));
-
- // Check whether the currently cached layout parameters are the same
- // and we already have a result and we have no pending layout requests.
- if (view_state->pending_layout_requests().empty() &&
- view_state->layout_params() &&
- view_state->layout_params()->Equals(*layout_params)) {
- mojo::ui::ViewLayoutInfoPtr info = view_state->CreateLayoutInfo();
- if (info) {
- DVLOG(2) << "Layout cache hit";
- view_state->set_scene_changed_since_last_report(false);
- callback.Run(info.Pass());
- return;
- }
- }
-
- // Check whether the layout parameters are different from the most
- // recent pending layout request if we have one.
- if (view_state->pending_layout_requests().empty() ||
- !view_state->pending_layout_requests().back()->layout_params()->Equals(
- *layout_params)) {
- // Enqueue a new request for these parameters.
- EnqueueLayoutRequest(view_state, layout_params.Pass());
- }
-
- // Enlist ourselves into the callbacks for the pending request.
- view_state->pending_layout_requests().back()->AddCallback(callback);
- IssueNextViewLayoutRequest(view_state);
-}
-
-void ViewRegistry::EnqueueLayoutRequest(
- ViewState* view_state,
- mojo::ui::ViewLayoutParamsPtr layout_params) {
- DCHECK(IsViewStateRegisteredDebug(view_state));
- DCHECK(AreViewLayoutParamsValid(layout_params.get()));
-
- // Drop the previous layout request if it hasn't been issued yet.
- // This may cause callbacks to be invoked will null information.
- if (!view_state->pending_layout_requests().empty() &&
- !view_state->pending_layout_requests().back()->issued())
- view_state->pending_layout_requests().pop_back();
-
- // Enqueue the new request.
- view_state->pending_layout_requests().emplace_back(
- std::unique_ptr<ViewLayoutRequest>(
- new ViewLayoutRequest(layout_params.Pass())));
-}
-
void ViewRegistry::IssueNextViewLayoutRequest(ViewState* view_state) {
DCHECK(IsViewStateRegisteredDebug(view_state));
- if (!view_state->pending_layout_requests().empty() &&
- !view_state->pending_layout_requests().front()->issued()) {
- view_state->pending_layout_requests().front()->set_issued(true);
- SendViewLayoutRequest(view_state);
- }
+ if (view_state->pending_layout_requests().empty())
+ return;
+
+ ViewLayoutRequest* request =
+ view_state->pending_layout_requests().front().get();
+ if (request->issued())
+ return;
+
+ // TODO: Detect ANRs
+ DVLOG(1) << "IssueNextViewLayoutRequest: view_state=" << view_state;
+ view_state->view()->OnLayout(
+ request->layout_params()->Clone(),
+ mojo::Array<uint32_t>::From(view_state->children_needing_layout()),
+ base::Bind(&ViewRegistry::OnViewLayoutResult, base::Unretained(this),
+ view_state->GetWeakPtr()));
+ view_state->children_needing_layout().clear();
+ request->set_issued(true);
}
void ViewRegistry::IssueNextViewTreeLayoutRequest(ViewTreeState* tree_state) {
DCHECK(IsViewTreeStateRegisteredDebug(tree_state));
- if (tree_state->layout_request_pending() &&
- !tree_state->layout_request_issued()) {
- tree_state->set_layout_request_pending(false);
- tree_state->set_layout_request_issued(true);
- SendViewTreeLayoutRequest(tree_state);
- }
-}
-
-void ViewRegistry::ResetStateWhenUnlinking(ViewState* view_state) {
- // Clean up parent's recorded state for the child.
- if (view_state->parent()) {
- view_state->parent()->children_needing_layout().erase(view_state->key());
- }
-}
-
-void ViewRegistry::SendChildUnavailable(ViewState* parent_state,
- uint32_t child_key) {
- DCHECK(IsViewStateRegisteredDebug(parent_state));
-
- // TODO: Detect ANRs
- DVLOG(1) << "SendChildUnavailable: child_key=" << child_key;
- parent_state->view()->OnChildUnavailable(child_key,
- base::Bind(&base::DoNothing));
-}
-
-void ViewRegistry::SendRootUnavailable(ViewTreeState* tree_state,
- uint32_t root_key) {
- DCHECK(IsViewTreeStateRegisteredDebug(tree_state));
-
- // TODO: Detect ANRs
- DVLOG(1) << "SendRootUnavailable: root_key=" << root_key;
- tree_state->view_tree()->OnRootUnavailable(root_key,
- base::Bind(&base::DoNothing));
-}
-
-void ViewRegistry::SendViewLayoutRequest(ViewState* view_state) {
- DCHECK(IsViewStateRegisteredDebug(view_state));
- DCHECK(!view_state->pending_layout_requests().empty());
- DCHECK(view_state->pending_layout_requests().front()->issued());
-
- // TODO: Detect ANRs
- DVLOG(1) << "SendViewLayoutRequest: view.token=" << view_state->label();
- view_state->view()->OnLayout(
- view_state->pending_layout_requests().front()->layout_params()->Clone(),
- mojo::Array<uint32_t>::From(view_state->children_needing_layout()),
- base::Bind(&ViewRegistry::OnViewLayoutResult, base::Unretained(this),
- view_state->GetWeakPtr()));
- view_state->children_needing_layout().clear();
-}
-
-void ViewRegistry::SendViewTreeLayoutRequest(ViewTreeState* tree_state) {
- DCHECK(IsViewTreeStateRegisteredDebug(tree_state));
- DCHECK(tree_state->layout_request_issued());
+ if (!tree_state->layout_request_pending() ||
+ tree_state->layout_request_issued())
+ return;
// TODO: Detect ANRs
DVLOG(1) << "SendViewTreeLayoutRequest";
tree_state->view_tree()->OnLayout(
base::Bind(&ViewRegistry::OnViewTreeLayoutResult, base::Unretained(this),
tree_state->GetWeakPtr()));
-}
-
-static bool IsSizeInBounds(mojo::ui::BoxConstraints* constraints,
- mojo::Size* size) {
- return size && size->width >= constraints->min_width &&
- size->width <= constraints->max_width &&
- size->height >= constraints->min_height &&
- size->height <= constraints->max_height;
+ tree_state->set_layout_request_pending(false);
+ tree_state->set_layout_request_issued(true);
}
void ViewRegistry::OnViewLayoutResult(base::WeakPtr<ViewState> view_state_weak,
@@ -682,14 +625,14 @@
view_state->pending_layout_requests().begin());
DVLOG(1) << "OnViewLayoutResult: view=" << view_state
- << ", params=" << request->layout_params() << ", result=" << result;
+ << ", params=" << *request->layout_params() << ", result=" << result;
// Validate the layout info.
if (!IsSizeInBounds(request->layout_params()->constraints.get(),
result->size.get())) {
LOG(ERROR) << "View returned invalid size in its layout info: "
<< "view=" << view_state
- << ", params=" << request->layout_params()
+ << ", params=" << *request->layout_params()
<< ", result=" << result;
UnregisterView(view_state);
return;
@@ -713,11 +656,12 @@
request->DispatchLayoutInfo(info.Pass());
}
- if (recurse) {
- if (view_state->parent()) {
- InvalidateLayoutForChild(view_state->parent(), view_state->key());
- } else if (view_state->tree()) {
- InvalidateLayoutForRoot(view_state->tree());
+ if (recurse && view_state->view_stub()) {
+ if (view_state->view_stub()->parent()) {
+ InvalidateLayoutForChild(view_state->view_stub()->parent(),
+ view_state->view_stub()->key());
+ } else if (view_state->view_stub()->tree()) {
+ InvalidateLayoutForRoot(view_state->view_stub()->tree());
}
}
@@ -737,4 +681,26 @@
}
}
+void ViewRegistry::SendChildUnavailable(ViewState* parent_state,
+ uint32_t child_key) {
+ DCHECK(IsViewStateRegisteredDebug(parent_state));
+
+ // TODO: Detect ANRs
+ DVLOG(1) << "SendChildUnavailable: parent_state=" << parent_state
+ << ", child_key=" << child_key;
+ parent_state->view()->OnChildUnavailable(child_key,
+ base::Bind(&base::DoNothing));
+}
+
+void ViewRegistry::SendRootUnavailable(ViewTreeState* tree_state,
+ uint32_t root_key) {
+ DCHECK(IsViewTreeStateRegisteredDebug(tree_state));
+
+ // TODO: Detect ANRs
+ DVLOG(1) << "SendRootUnavailable: tree_state=" << tree_state
+ << ", root_key=" << root_key;
+ tree_state->view_tree()->OnRootUnavailable(root_key,
+ base::Bind(&base::DoNothing));
+}
+
} // namespace view_manager
diff --git a/services/ui/view_manager/view_registry.h b/services/ui/view_manager/view_registry.h
index c056209..3f2b7ba 100644
--- a/services/ui/view_manager/view_registry.h
+++ b/services/ui/view_manager/view_registry.h
@@ -5,6 +5,7 @@
#ifndef SERVICES_UI_VIEW_MANAGER_VIEW_REGISTRY_H_
#define SERVICES_UI_VIEW_MANAGER_VIEW_REGISTRY_H_
+#include <string>
#include <unordered_map>
#include "base/macros.h"
@@ -15,6 +16,7 @@
#include "services/ui/view_manager/view_associate_table.h"
#include "services/ui/view_manager/view_layout_request.h"
#include "services/ui/view_manager/view_state.h"
+#include "services/ui/view_manager/view_stub.h"
#include "services/ui/view_manager/view_tree_state.h"
namespace view_manager {
@@ -40,17 +42,22 @@
// VIEW MANAGER REQUESTS
// Registers a view and returns its ViewToken.
- mojo::ui::ViewTokenPtr RegisterView(
+ void RegisterView(
mojo::ui::ViewPtr view,
mojo::InterfaceRequest<mojo::ui::ViewHost> view_host_request,
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request,
const mojo::String& label);
// Registers a view tree.
- mojo::ui::ViewTreeTokenPtr RegisterViewTree(
+ void RegisterViewTree(
mojo::ui::ViewTreePtr view_tree,
mojo::InterfaceRequest<mojo::ui::ViewTreeHost> view_tree_host_request,
const mojo::String& label);
+ // VIEW STUB REQUESTS
+
+ void OnViewResolved(ViewStub* view_stub, mojo::ui::ViewTokenPtr view_token);
+
// VIEW HOST REQUESTS
// Creates a scene for the view, replacing its current scene.
@@ -66,11 +73,14 @@
// Destroys |parent_state| if an error occurs.
void AddChild(ViewState* parent_state,
uint32_t child_key,
- mojo::ui::ViewTokenPtr child_view_token);
+ mojo::ui::ViewOwnerPtr child_view_owner);
// Removes a child.
// Destroys |parent_state| if an error occurs.
- void RemoveChild(ViewState* parent_state, uint32_t child_key);
+ void RemoveChild(ViewState* parent_state,
+ uint32_t child_key,
+ mojo::InterfaceRequest<mojo::ui::ViewOwner>
+ transferred_view_owner_request);
// Lays out a child and optionally provides its size.
// Destroys |parent_state| if an error occurs.
@@ -85,6 +95,9 @@
const mojo::String& service_name,
mojo::ScopedMessagePipeHandle client_handle);
+ // Called when one of the view pipes is closed remotely.
+ void OnViewDied(ViewState* view_state, const std::string& reason);
+
// VIEW TREE HOST REQUESTS
// Requests layout.
@@ -95,11 +108,13 @@
// Destroys |tree_state| if an error occurs.
void SetRoot(ViewTreeState* tree_state,
uint32_t root_key,
- mojo::ui::ViewTokenPtr root_view_token);
+ mojo::ui::ViewOwnerPtr root_view_owner);
// Resets the root of the view tree.
// Destroys |tree_state| if an error occurs.
- void ResetRoot(ViewTreeState* tree_state);
+ void ResetRoot(ViewTreeState* tree_state,
+ mojo::InterfaceRequest<mojo::ui::ViewOwner>
+ transferred_view_owner_request);
// Lays out a view tree's root and optionally provides its size.
// Destroys |tree_state| if an error occurs.
@@ -113,48 +128,45 @@
const mojo::String& service_name,
mojo::ScopedMessagePipeHandle client_handle);
+ // Called when one of the view tree pipes is closed remotely.
+ void OnViewTreeDied(ViewTreeState* tree_state, const std::string& reason);
+
private:
// LIFETIME
- void OnViewConnectionError(ViewState* view_state);
void UnregisterView(ViewState* view_state);
- void OnViewTreeConnectionError(ViewTreeState* tree_state);
void UnregisterViewTree(ViewTreeState* tree_state);
// TREE MANIPULATION
ViewState* FindView(uint32_t view_token_value);
- void LinkChild(ViewState* parent_state,
- uint32_t child_key,
- ViewState* child_state);
- void LinkChildAsUnavailable(ViewState* parent_state, uint32_t child_key);
- void MarkChildAsUnavailable(ViewState* parent_state, uint32_t child_key);
- void UnlinkChild(ViewState* parent_state,
- ViewState::ChildrenMap::iterator child_it);
-
ViewTreeState* FindViewTree(uint32_t view_tree_token_value);
- void LinkRoot(ViewTreeState* tree_state,
- ViewState* root_state,
- uint32_t root_key);
- void UnlinkRoot(ViewTreeState* tree_state);
+
void HijackView(ViewState* view_state);
- // Must be called before the view is actually unlinked from the tree.
- // Caller is still responsible for actually unlinking the view.
- void ResetStateWhenUnlinking(ViewState* view_state);
+ void AttachViewStubAndNotify(ViewStub* view_stub, ViewState* view_state);
+ void ReleaseViewStubAndNotify(ViewStub* view_stub);
+ void TransferOrUnregisterViewStub(std::unique_ptr<ViewStub> view_stub,
+ mojo::InterfaceRequest<mojo::ui::ViewOwner>
+ transferred_view_owner_request);
+ void UnregisterViewStub(std::unique_ptr<ViewStub> view_stub);
// LAYOUT
- void InvalidateLayout(ViewState* view_state);
- void InvalidateLayoutForChild(ViewState* parent_state, uint32_t child_key);
- void InvalidateLayoutForRoot(ViewTreeState* tree_state);
- void SetLayout(ViewState* view_state,
+ void SetLayout(ViewStub* view_stub,
mojo::ui::ViewLayoutParamsPtr layout_params,
const ViewLayoutCallback& callback);
void EnqueueLayoutRequest(ViewState* view_state,
mojo::ui::ViewLayoutParamsPtr layout_params);
+ void InvalidateLayout(ViewState* view_state);
+ void InvalidateLayoutForChild(ViewState* parent_state, uint32_t child_key);
+ void InvalidateLayoutForRoot(ViewTreeState* tree_state);
+
void IssueNextViewLayoutRequest(ViewState* view_state);
void IssueNextViewTreeLayoutRequest(ViewTreeState* tree_state);
+ void OnViewLayoutResult(base::WeakPtr<ViewState> view_state_weak,
+ mojo::ui::ViewLayoutResultPtr result);
+ void OnViewTreeLayoutResult(base::WeakPtr<ViewTreeState> tree_state_weak);
// SCENE MANAGEMENT
@@ -165,11 +177,6 @@
void SendChildUnavailable(ViewState* parent_state, uint32_t child_key);
void SendRootUnavailable(ViewTreeState* tree_state, uint32_t root_key);
- void SendViewLayoutRequest(ViewState* view_state);
- void SendViewTreeLayoutRequest(ViewTreeState* tree_state);
- void OnViewLayoutResult(base::WeakPtr<ViewState> view_state_weak,
- mojo::ui::ViewLayoutResultPtr result);
- void OnViewTreeLayoutResult(base::WeakPtr<ViewTreeState> tree_state_weak);
bool IsViewStateRegisteredDebug(ViewState* view_state) {
return view_state && FindView(view_state->view_token()->value);
diff --git a/services/ui/view_manager/view_state.cc b/services/ui/view_manager/view_state.cc
index 643f6f5..70125f4 100644
--- a/services/ui/view_manager/view_state.cc
+++ b/services/ui/view_manager/view_state.cc
@@ -4,52 +4,83 @@
#include "services/ui/view_manager/view_state.h"
+#include "base/bind.h"
#include "base/logging.h"
#include "base/strings/stringprintf.h"
-#include "services/ui/view_manager/view_tree_state.h"
+#include "services/ui/view_manager/view_host_impl.h"
+#include "services/ui/view_manager/view_registry.h"
+#include "services/ui/view_manager/view_stub.h"
namespace view_manager {
-ViewState::ViewState(mojo::ui::ViewPtr view,
- mojo::ui::ViewTokenPtr view_token,
- const std::string& label)
+ViewState::ViewState(
+ ViewRegistry* registry,
+ mojo::ui::ViewPtr view,
+ mojo::ui::ViewTokenPtr view_token,
+ mojo::InterfaceRequest<mojo::ui::ViewHost> view_host_request,
+ const std::string& label)
: view_(view.Pass()),
view_token_(view_token.Pass()),
label_(label),
+ impl_(new ViewHostImpl(registry, this)),
+ host_binding_(impl_.get(), view_host_request.Pass()),
+ owner_binding_(impl_.get()),
weak_factory_(this) {
DCHECK(view_);
DCHECK(view_token_);
+
+ view_.set_connection_error_handler(
+ base::Bind(&ViewRegistry::OnViewDied, base::Unretained(registry),
+ base::Unretained(this), "View connection closed"));
+ host_binding_.set_connection_error_handler(
+ base::Bind(&ViewRegistry::OnViewDied, base::Unretained(registry),
+ base::Unretained(this), "ViewHost connection closed"));
+ owner_binding_.set_connection_error_handler(
+ base::Bind(&ViewRegistry::OnViewDied, base::Unretained(registry),
+ base::Unretained(this), "ViewOwner connection closed"));
}
ViewState::~ViewState() {}
-void ViewState::SetTree(ViewTreeState* tree, uint32_t key) {
- DCHECK(tree);
- DCHECK(!parent_); // must be the root
- if (tree_ != tree) {
- SetTreeUnchecked(tree);
+void ViewState::LinkChild(uint32_t key, std::unique_ptr<ViewStub> child) {
+ DCHECK(children_.find(key) == children_.end());
+ DCHECK(child);
+ DCHECK(!child->is_linked());
+
+ child->SetParent(this, key);
+ children_.emplace(key, std::move(child));
+}
+
+std::unique_ptr<ViewStub> ViewState::UnlinkChild(uint32_t key) {
+ auto child_it = children_.find(key);
+ DCHECK(child_it != children_.end());
+ std::unique_ptr<ViewStub> child(std::move(child_it->second));
+ child->Unlink();
+ children_.erase(child_it);
+ children_needing_layout_.erase(child->key());
+ return child;
+}
+
+std::vector<std::unique_ptr<ViewStub>> ViewState::UnlinkAllChildren() {
+ std::vector<std::unique_ptr<ViewStub>> stubs;
+ for (auto& pair : children_) {
+ pair.second->Unlink();
+ stubs.push_back(std::move(pair.second));
}
- key_ = key;
+ children_.clear();
+ children_needing_layout_.clear();
+ return stubs;
}
-void ViewState::SetTreeUnchecked(ViewTreeState* tree) {
- tree_ = tree;
- for (const auto& pair : children_) {
- pair.second->SetTreeUnchecked(tree);
- }
+void ViewState::BindOwner(
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request) {
+ DCHECK(!owner_binding_.is_bound());
+ owner_binding_.Bind(view_owner_request.Pass());
}
-void ViewState::SetParent(ViewState* parent, uint32_t key) {
- DCHECK(parent);
- parent_ = parent;
- key_ = key;
- SetTreeUnchecked(parent->tree_);
-}
-
-void ViewState::ResetContainer() {
- parent_ = nullptr;
- key_ = 0;
- SetTreeUnchecked(nullptr);
+void ViewState::ReleaseOwner() {
+ DCHECK(owner_binding_.is_bound());
+ owner_binding_.Close();
}
mojo::ui::ViewLayoutInfoPtr ViewState::CreateLayoutInfo() {
@@ -62,7 +93,7 @@
return info;
}
-const std::string& ViewState::FormattedLabel() {
+const std::string& ViewState::FormattedLabel() const {
if (formatted_label_cache_.empty()) {
formatted_label_cache_ =
label_.empty()
diff --git a/services/ui/view_manager/view_state.h b/services/ui/view_manager/view_state.h
index 2919f91..9b733f6 100644
--- a/services/ui/view_manager/view_state.h
+++ b/services/ui/view_manager/view_state.h
@@ -10,25 +10,29 @@
#include <string>
#include <unordered_map>
-#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
+#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/services/ui/views/cpp/formatting.h"
#include "mojo/services/ui/views/interfaces/views.mojom.h"
#include "services/ui/view_manager/view_layout_request.h"
namespace view_manager {
-class ViewTreeState;
+class ViewRegistry;
+class ViewHostImpl;
+class ViewStub;
// Describes the state of a particular view.
// This object is owned by the ViewRegistry that created it.
class ViewState {
public:
- using ChildrenMap = std::unordered_map<uint32_t, ViewState*>;
+ using ChildrenMap = std::unordered_map<uint32_t, std::unique_ptr<ViewStub>>;
- ViewState(mojo::ui::ViewPtr view,
+ ViewState(ViewRegistry* registry,
+ mojo::ui::ViewPtr view,
mojo::ui::ViewTokenPtr view_token,
+ mojo::InterfaceRequest<mojo::ui::ViewHost> view_host_request,
const std::string& label);
~ViewState();
@@ -42,39 +46,24 @@
// Caller does not obtain ownership of the token.
mojo::ui::ViewToken* view_token() const { return view_token_.get(); }
- // Sets the associated host implementation and takes ownership of it.
- void set_view_host(mojo::ui::ViewHost* host) { view_host_.reset(host); }
-
- // Sets the connection error handler for the view.
- void set_view_connection_error_handler(const base::Closure& handler) {
- view_.set_connection_error_handler(handler);
- }
-
- // Gets the view tree to which this view belongs, or null if none.
- ViewTreeState* tree() const { return tree_; }
-
- // Gets the parent view state, or null if none.
- ViewState* parent() const { return parent_; }
-
- // Gets the key that this child has in its container, or 0 if none.
- uint32_t key() const { return key_; }
-
- // Recursively sets the view tree to which this view and all of its
- // descendents belongs. Must not be null. This method must only be called
- // on root views.
- void SetTree(ViewTreeState* tree, uint32_t key);
-
- // Sets the parent view state pointer, the child's key in its parent,
- // and set its view tree to that of its parent. Must not be null.
- void SetParent(ViewState* parent, uint32_t key);
-
- // Resets the parent view state and tree pointers to null.
- void ResetContainer();
+ // Gets or sets the view stub which links this view into the
+ // view hierarchy, or null if the view isn't linked anywhere.
+ ViewStub* view_stub() const { return view_stub_; }
+ void set_view_stub(ViewStub* view_stub) { view_stub_ = view_stub; }
// The map of children, indexed by child key.
- // Child view state may be null if the child with the given key has
- // become unavailable but not yet removed.
- ChildrenMap& children() { return children_; }
+ // The view stub pointers are never null but some view stubs may
+ // have been marked unavailable.
+ const ChildrenMap& children() const { return children_; }
+
+ // Links a child into the view tree.
+ void LinkChild(uint32_t key, std::unique_ptr<ViewStub> child);
+
+ // Unlinks a child of the view tree.
+ std::unique_ptr<ViewStub> UnlinkChild(uint32_t key);
+
+ // Unlinks all children as a single operation.
+ std::vector<std::unique_ptr<ViewStub>> UnlinkAllChildren();
// The set of children needing layout.
// This set must never contain non-existent or unavailable children.
@@ -123,21 +112,30 @@
// Returns null if unavailable.
mojo::ui::ViewLayoutInfoPtr CreateLayoutInfo();
- const std::string& label() { return label_; }
- const std::string& FormattedLabel();
+ // Binds the |ViewOwner| interface to the view which has the effect of
+ // tying the view's lifetime to that of the owner's pipe.
+ void BindOwner(
+ mojo::InterfaceRequest<mojo::ui::ViewOwner> view_owner_request);
+
+ // Unbinds the view from its owner.
+ void ReleaseOwner();
+
+ const std::string& label() const { return label_; }
+ const std::string& FormattedLabel() const;
private:
- void SetTreeUnchecked(ViewTreeState* tree);
-
mojo::ui::ViewPtr view_;
mojo::ui::ViewTokenPtr view_token_;
- const std::string label_;
- std::string formatted_label_cache_;
- std::unique_ptr<mojo::ui::ViewHost> view_host_;
- ViewTreeState* tree_ = nullptr;
- ViewState* parent_ = nullptr;
- uint32_t key_ = 0u;
+ const std::string label_;
+ mutable std::string formatted_label_cache_;
+
+ std::unique_ptr<ViewHostImpl> impl_;
+ mojo::Binding<mojo::ui::ViewHost> host_binding_;
+ mojo::Binding<mojo::ui::ViewOwner> owner_binding_;
+
+ ViewStub* view_stub_ = nullptr;
+
ChildrenMap children_;
std::set<uint32_t> children_needing_layout_;
std::vector<std::unique_ptr<ViewLayoutRequest>> pending_layout_requests_;
diff --git a/services/ui/view_manager/view_stub.cc b/services/ui/view_manager/view_stub.cc
new file mode 100644
index 0000000..8fd5eae
--- /dev/null
+++ b/services/ui/view_manager/view_stub.cc
@@ -0,0 +1,98 @@
+// 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 "services/ui/view_manager/view_stub.h"
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "services/ui/view_manager/view_registry.h"
+#include "services/ui/view_manager/view_state.h"
+#include "services/ui/view_manager/view_tree_state.h"
+
+namespace view_manager {
+
+ViewStub::ViewStub(ViewRegistry* registry, mojo::ui::ViewOwnerPtr owner)
+ : registry_(registry), owner_(owner.Pass()) {
+ DCHECK(registry_);
+ DCHECK(owner_);
+
+ owner_.set_connection_error_handler(
+ base::Bind(&ViewStub::OnViewResolved, base::Unretained(this), nullptr));
+ owner_->GetToken(
+ base::Bind(&ViewStub::OnViewResolved, base::Unretained(this)));
+}
+
+ViewStub::~ViewStub() {
+ // Ensure that everything was properly released before this object was
+ // destroyed. The |ViewRegistry| is responsible for maintaining the
+ // invariant that all |ViewState| objects are owned so by the time we
+ // get here, the view should have found a new owner or been unregistered.
+ DCHECK(is_unavailable());
+}
+
+void ViewStub::AttachView(ViewState* state) {
+ DCHECK(state);
+ DCHECK(!state->view_stub());
+ DCHECK(is_pending());
+
+ state_ = state;
+ state_->set_view_stub(this);
+}
+
+ViewState* ViewStub::ReleaseView() {
+ if (is_unavailable())
+ return nullptr;
+
+ ViewState* state = state_;
+ if (state) {
+ DCHECK(state->view_stub() == this);
+ state->set_view_stub(nullptr);
+ state_ = nullptr;
+ }
+ unavailable_ = true;
+ return state;
+}
+
+void ViewStub::SetTree(ViewTreeState* tree, uint32_t key) {
+ DCHECK(tree);
+ DCHECK(!tree_ && !parent_);
+
+ key_ = key;
+ SetTreeRecursively(tree);
+}
+
+void ViewStub::SetParent(ViewState* parent, uint32_t key) {
+ DCHECK(parent);
+ DCHECK(!tree_ && !parent_);
+
+ parent_ = parent;
+ key_ = key;
+ if (parent->view_stub())
+ SetTreeRecursively(parent->view_stub()->tree());
+}
+
+void ViewStub::Unlink() {
+ parent_ = nullptr;
+ key_ = 0;
+ SetTreeRecursively(nullptr);
+}
+
+void ViewStub::SetTreeRecursively(ViewTreeState* tree) {
+ if (tree_ == tree)
+ return;
+ tree_ = tree;
+ if (state_) {
+ for (const auto& pair : state_->children()) {
+ pair.second->SetTreeRecursively(tree);
+ }
+ }
+}
+
+void ViewStub::OnViewResolved(mojo::ui::ViewTokenPtr view_token) {
+ DCHECK(owner_);
+ owner_.reset();
+ registry_->OnViewResolved(this, view_token.Pass());
+}
+
+} // namespace view_manager
diff --git a/services/ui/view_manager/view_stub.h b/services/ui/view_manager/view_stub.h
new file mode 100644
index 0000000..db031bb
--- /dev/null
+++ b/services/ui/view_manager/view_stub.h
@@ -0,0 +1,110 @@
+// 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 SERVICES_UI_VIEW_MANAGER_VIEW_STUB_H_
+#define SERVICES_UI_VIEW_MANAGER_VIEW_STUB_H_
+
+#include <memory>
+#include <vector>
+
+#include "base/macros.h"
+#include "mojo/services/ui/views/interfaces/views.mojom.h"
+#include "services/ui/view_manager/view_layout_request.h"
+
+namespace view_manager {
+
+class ViewRegistry;
+class ViewState;
+class ViewTreeState;
+
+// Describes a link in the view hierarchy either from a parent view to one
+// of its children or from the view tree to its root view.
+//
+// When this object is created, it is not yet known whether the linked
+// view actually exists. We must wait for a response from the view owner
+// to resolve the view's token and associate the stub with its child.
+//
+// Instances of this object are held by a unique pointer owned by the
+// parent view or view tree at the point where the view is being linked.
+// Note that the lifetime of the views themselves is managed by the view
+// registry.
+class ViewStub {
+ public:
+ // Begins the process of resolving a view.
+ // Invokes |ViewRegistry.OnViewResolved| when the token is obtained
+ // from the owner or passes nullptr if an error occurs.
+ ViewStub(ViewRegistry* registry, mojo::ui::ViewOwnerPtr owner);
+ ~ViewStub();
+
+ // Gets the view state referenced by the stub, or null if the view
+ // has not yet been resolved or is unavailable.
+ ViewState* state() const { return state_; }
+
+ // Returns true if the view which was intended to be referenced by the
+ // stub has become unavailable.
+ bool is_unavailable() const { return unavailable_; }
+
+ // Returns true if awaiting resolution of the view.
+ bool is_pending() const { return !state_ && !unavailable_; }
+
+ // Returns true if the view is linked into a tree or parent.
+ bool is_linked() const { return tree_ && parent_; }
+
+ // Gets the view tree to which this view belongs, or null if none.
+ ViewTreeState* tree() const { return tree_; }
+
+ // Gets the parent view state, or null if none.
+ ViewState* parent() const { return parent_; }
+
+ // Gets the key that this child has in its container, or 0 if none.
+ uint32_t key() const { return key_; }
+
+ // A pending layout request, held until such time as the view is attached.
+ std::unique_ptr<ViewLayoutRequest>& pending_layout_request() {
+ return pending_layout_request_;
+ }
+
+ // Binds the stub to the specified actual view, which must not be null.
+ // Must be called at most once to apply the effects of resolving the
+ // view owner.
+ void AttachView(ViewState* state);
+
+ // Marks the stub as unavailable.
+ // Returns the previous view state, or null if none.
+ ViewState* ReleaseView();
+
+ // THESE METHODS SHOULD ONLY BE CALLED BY VIEW STATE OR VIEW TREE STATE
+
+ // Recursively sets the view tree to which this view and all of its
+ // descendents belong. Must not be null. This method must only be called
+ // on root views.
+ void SetTree(ViewTreeState* tree, uint32_t key);
+
+ // Sets the parent view state pointer, the child's key in its parent,
+ // and set its view tree to that of its parent. Must not be null.
+ void SetParent(ViewState* parent, uint32_t key);
+
+ // Resets the parent view state and tree pointers to null.
+ void Unlink();
+
+ private:
+ void SetTreeRecursively(ViewTreeState* tree);
+ void OnViewResolved(mojo::ui::ViewTokenPtr view_token);
+
+ ViewRegistry* registry_;
+ mojo::ui::ViewOwnerPtr owner_;
+ ViewState* state_ = nullptr;
+ bool unavailable_ = false;
+ std::unique_ptr<ViewLayoutRequest> pending_layout_request_;
+
+ ViewTreeState* tree_ = nullptr;
+ ViewState* parent_ = nullptr;
+ uint32_t key_ = 0u;
+
+ DISALLOW_COPY_AND_ASSIGN(ViewStub);
+};
+
+} // namespace view_manager
+
+#endif // SERVICES_UI_VIEW_MANAGER_VIEW_STUB_H_
diff --git a/services/ui/view_manager/view_tree_host_impl.cc b/services/ui/view_manager/view_tree_host_impl.cc
index 654b411..bbfc208 100644
--- a/services/ui/view_manager/view_tree_host_impl.cc
+++ b/services/ui/view_manager/view_tree_host_impl.cc
@@ -5,20 +5,20 @@
#include "services/ui/view_manager/view_tree_host_impl.h"
#include "base/bind.h"
-#include "base/bind_helpers.h"
+#include "services/ui/view_manager/view_registry.h"
+#include "services/ui/view_manager/view_tree_state.h"
namespace view_manager {
-ViewTreeHostImpl::ViewTreeHostImpl(
- ViewRegistry* registry,
- ViewTreeState* state,
- mojo::InterfaceRequest<mojo::ui::ViewTreeHost> view_tree_host_request)
- : registry_(registry),
- state_(state),
- binding_(this, view_tree_host_request.Pass()) {}
+ViewTreeHostImpl::ViewTreeHostImpl(ViewRegistry* registry, ViewTreeState* state)
+ : registry_(registry), state_(state) {}
ViewTreeHostImpl::~ViewTreeHostImpl() {}
+void ViewTreeHostImpl::GetToken(const GetTokenCallback& callback) {
+ callback.Run(state_->view_tree_token()->Clone());
+}
+
void ViewTreeHostImpl::GetServiceProvider(
mojo::InterfaceRequest<mojo::ServiceProvider> service_provider) {
service_provider_bindings_.AddBinding(this, service_provider.Pass());
@@ -29,12 +29,13 @@
}
void ViewTreeHostImpl::SetRoot(uint32_t root_key,
- mojo::ui::ViewTokenPtr root_view_token) {
- registry_->SetRoot(state_, root_key, root_view_token.Pass());
+ mojo::ui::ViewOwnerPtr root_view_owner) {
+ registry_->SetRoot(state_, root_key, root_view_owner.Pass());
}
-void ViewTreeHostImpl::ResetRoot() {
- registry_->ResetRoot(state_);
+void ViewTreeHostImpl::ResetRoot(mojo::InterfaceRequest<mojo::ui::ViewOwner>
+ transferred_view_owner_request) {
+ registry_->ResetRoot(state_, transferred_view_owner_request.Pass());
}
static void RunLayoutRootCallback(
diff --git a/services/ui/view_manager/view_tree_host_impl.h b/services/ui/view_manager/view_tree_host_impl.h
index 017ee88..4c832f1 100644
--- a/services/ui/view_manager/view_tree_host_impl.h
+++ b/services/ui/view_manager/view_tree_host_impl.h
@@ -7,37 +7,31 @@
#include "base/macros.h"
#include "mojo/common/binding_set.h"
-#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/services/ui/views/interfaces/view_trees.mojom.h"
-#include "services/ui/view_manager/view_registry.h"
-#include "services/ui/view_manager/view_tree_state.h"
namespace view_manager {
+class ViewRegistry;
+class ViewTreeState;
+
// ViewTreeHost interface implementation.
// This object is owned by its associated ViewTreeState.
class ViewTreeHostImpl : public mojo::ui::ViewTreeHost,
public mojo::ServiceProvider {
public:
- ViewTreeHostImpl(
- ViewRegistry* registry,
- ViewTreeState* state,
- mojo::InterfaceRequest<mojo::ui::ViewTreeHost> view_tree_host_request);
+ ViewTreeHostImpl(ViewRegistry* registry, ViewTreeState* state);
~ViewTreeHostImpl() override;
- void set_view_tree_host_connection_error_handler(
- const base::Closure& handler) {
- binding_.set_connection_error_handler(handler);
- }
-
private:
// |ViewTreeHost|:
+ void GetToken(const GetTokenCallback& callback) override;
void GetServiceProvider(
mojo::InterfaceRequest<mojo::ServiceProvider> service_provider) override;
void RequestLayout() override;
void SetRoot(uint32_t root_key,
- mojo::ui::ViewTokenPtr root_view_token) override;
- void ResetRoot() override;
+ mojo::ui::ViewOwnerPtr root_view_owner) override;
+ void ResetRoot(mojo::InterfaceRequest<mojo::ui::ViewOwner>
+ transferred_view_owner_request) override;
void LayoutRoot(mojo::ui::ViewLayoutParamsPtr root_layout_params,
const LayoutRootCallback& callback) override;
@@ -47,7 +41,6 @@
ViewRegistry* const registry_;
ViewTreeState* const state_;
- mojo::Binding<mojo::ui::ViewTreeHost> binding_;
mojo::BindingSet<mojo::ServiceProvider> service_provider_bindings_;
DISALLOW_COPY_AND_ASSIGN(ViewTreeHostImpl);
diff --git a/services/ui/view_manager/view_tree_state.cc b/services/ui/view_manager/view_tree_state.cc
index 4a69f2c..1d8f502 100644
--- a/services/ui/view_manager/view_tree_state.cc
+++ b/services/ui/view_manager/view_tree_state.cc
@@ -4,41 +4,56 @@
#include "services/ui/view_manager/view_tree_state.h"
+#include "base/bind.h"
#include "base/logging.h"
#include "base/strings/stringprintf.h"
+#include "services/ui/view_manager/view_registry.h"
+#include "services/ui/view_manager/view_state.h"
+#include "services/ui/view_manager/view_stub.h"
+#include "services/ui/view_manager/view_tree_host_impl.h"
namespace view_manager {
-ViewTreeState::ViewTreeState(mojo::ui::ViewTreePtr view_tree,
- mojo::ui::ViewTreeTokenPtr view_tree_token,
- const std::string& label)
+ViewTreeState::ViewTreeState(
+ ViewRegistry* registry,
+ mojo::ui::ViewTreePtr view_tree,
+ mojo::ui::ViewTreeTokenPtr view_tree_token,
+ mojo::InterfaceRequest<mojo::ui::ViewTreeHost> view_tree_host_request,
+ const std::string& label)
: view_tree_(view_tree.Pass()),
view_tree_token_(view_tree_token.Pass()),
label_(label),
+ impl_(new ViewTreeHostImpl(registry, this)),
+ host_binding_(impl_.get(), view_tree_host_request.Pass()),
weak_factory_(this) {
DCHECK(view_tree_);
DCHECK(view_tree_token_);
+
+ view_tree_.set_connection_error_handler(
+ base::Bind(&ViewRegistry::OnViewTreeDied, base::Unretained(registry),
+ base::Unretained(this), "ViewTree connection closed"));
+ host_binding_.set_connection_error_handler(
+ base::Bind(&ViewRegistry::OnViewTreeDied, base::Unretained(registry),
+ base::Unretained(this), "ViewTreeHost connection closed"));
}
ViewTreeState::~ViewTreeState() {}
-void ViewTreeState::SetRoot(ViewState* root, uint32_t key) {
+void ViewTreeState::LinkRoot(uint32_t key, std::unique_ptr<ViewStub> root) {
+ DCHECK(!root_);
DCHECK(root);
- if (root_ != root) {
- ResetRoot();
- root->SetTree(this, key);
- root_ = root;
- }
+ DCHECK(!root->is_linked());
+ root->SetTree(this, key);
+ root_ = std::move(root);
}
-void ViewTreeState::ResetRoot() {
- if (root_) {
- root_->ResetContainer();
- }
- root_ = nullptr;
+std::unique_ptr<ViewStub> ViewTreeState::UnlinkRoot() {
+ DCHECK(root_);
+ root_->Unlink();
+ return std::move(root_);
}
-const std::string& ViewTreeState::FormattedLabel() {
+const std::string& ViewTreeState::FormattedLabel() const {
if (formatted_label_cache_.empty()) {
formatted_label_cache_ =
label_.empty() ? base::StringPrintf("<%d>", view_tree_token_->value)
diff --git a/services/ui/view_manager/view_tree_state.h b/services/ui/view_manager/view_tree_state.h
index a6ea845..d1cfc98 100644
--- a/services/ui/view_manager/view_tree_state.h
+++ b/services/ui/view_manager/view_tree_state.h
@@ -10,24 +10,29 @@
#include <string>
#include <unordered_map>
-#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "mojo/common/binding_set.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/services/ui/views/cpp/formatting.h"
#include "mojo/services/ui/views/interfaces/view_trees.mojom.h"
-#include "services/ui/view_manager/view_state.h"
namespace view_manager {
+class ViewRegistry;
+class ViewState;
+class ViewStub;
+class ViewTreeHostImpl;
+
// Describes the state of a particular view tree.
// This object is owned by the ViewRegistry that created it.
class ViewTreeState {
public:
- explicit ViewTreeState(mojo::ui::ViewTreePtr view_tree,
- mojo::ui::ViewTreeTokenPtr view_tree_token,
- const std::string& label);
+ ViewTreeState(
+ ViewRegistry* registry,
+ mojo::ui::ViewTreePtr view_tree,
+ mojo::ui::ViewTreeTokenPtr view_tree_token,
+ mojo::InterfaceRequest<mojo::ui::ViewTreeHost> view_tree_host_request,
+ const std::string& label);
~ViewTreeState();
base::WeakPtr<ViewTreeState> GetWeakPtr() {
@@ -35,7 +40,7 @@
}
// Gets the view tree interface, never null.
- // Caller does not obtain ownership of the view.
+ // Caller does not obtain ownership of the view tree.
mojo::ui::ViewTree* view_tree() const { return view_tree_.get(); }
// Gets the token used to refer to this view tree globally.
@@ -44,30 +49,14 @@
return view_tree_token_.get();
}
- // Sets the associated host implementation and takes ownership of it.
- void set_view_tree_host(mojo::ui::ViewTreeHost* host) {
- view_tree_host_.reset(host);
- }
+ // Gets the root of the view tree, or null if there is no root.
+ ViewStub* root() const { return root_.get(); }
- // Sets the connection error handler for the view.
- void set_view_tree_connection_error_handler(const base::Closure& handler) {
- view_tree_.set_connection_error_handler(handler);
- }
+ // Links the root of the view tree.
+ void LinkRoot(uint32_t key, std::unique_ptr<ViewStub> root);
- // Gets the root of the view tree, or null if it is unavailable.
- ViewState* root() const { return root_; }
-
- // Sets the root of the view tree. Must not be null.
- // The view specified as the new root must not have any parents.
- void SetRoot(ViewState* root, uint32_t key);
-
- // Resets the root view to null.
- void ResetRoot();
-
- // True if the client previously set but has not yet explicitly unset
- // the root, independent of whether it is currently available.
- bool explicit_root() const { return explicit_root_; }
- void set_explicit_root(bool value) { explicit_root_ = value; }
+ // Unlinks the root of the view tree and returns it.
+ std::unique_ptr<ViewStub> UnlinkRoot();
// True if there is a pending layout request.
bool layout_request_pending() const { return layout_request_pending_; }
@@ -79,18 +68,21 @@
bool layout_request_issued() const { return layout_request_issued_; }
void set_layout_request_issued(bool value) { layout_request_issued_ = value; }
- const std::string& label() { return label_; }
- const std::string& FormattedLabel();
+ const std::string& label() const { return label_; }
+ const std::string& FormattedLabel() const;
private:
mojo::ui::ViewTreePtr view_tree_;
mojo::ui::ViewTreeTokenPtr view_tree_token_;
+
const std::string label_;
- std::string formatted_label_cache_;
+ mutable std::string formatted_label_cache_;
+
+ std::unique_ptr<ViewTreeHostImpl> impl_;
+ mojo::Binding<mojo::ui::ViewTreeHost> host_binding_;
std::unique_ptr<mojo::ui::ViewTreeHost> view_tree_host_;
- ViewState* root_ = nullptr;
- bool explicit_root_ = false;
+ std::unique_ptr<ViewStub> root_;
bool layout_request_pending_ = false;
bool layout_request_issued_ = false;