OLD | NEW |
| (Empty) |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include <map> | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/macros.h" | |
9 #include "base/stl_util.h" | |
10 #include "examples/bitmap_uploader/bitmap_uploader.h" | |
11 #include "examples/wm_flow/app/embedder.mojom.h" | |
12 #include "examples/wm_flow/embedded/embeddee.mojom.h" | |
13 #include "mojo/application/application_runner_chromium.h" | |
14 #include "mojo/common/binding_set.h" | |
15 #include "mojo/public/c/system/main.h" | |
16 #include "mojo/public/cpp/application/application_connection.h" | |
17 #include "mojo/public/cpp/application/application_delegate.h" | |
18 #include "mojo/public/cpp/application/application_impl.h" | |
19 #include "mojo/public/cpp/application/connect.h" | |
20 #include "mojo/public/cpp/application/interface_factory_impl.h" | |
21 #include "mojo/public/cpp/application/service_provider_impl.h" | |
22 #include "mojo/public/cpp/bindings/strong_binding.h" | |
23 #include "mojo/public/interfaces/application/service_provider.mojom.h" | |
24 #include "mojo/services/view_manager/cpp/view.h" | |
25 #include "mojo/services/view_manager/cpp/view_manager.h" | |
26 #include "mojo/services/view_manager/cpp/view_manager_client_factory.h" | |
27 #include "mojo/services/view_manager/cpp/view_manager_context.h" | |
28 #include "mojo/services/view_manager/cpp/view_manager_delegate.h" | |
29 #include "mojo/services/view_manager/cpp/view_observer.h" | |
30 #include "third_party/skia/include/core/SkColor.h" | |
31 #include "url/gurl.h" | |
32 | |
33 namespace examples { | |
34 namespace { | |
35 | |
36 // TODO(johngro) : investigate extending mojom with a formal flags type which it | |
37 // generates good bindings for, so we don't need to resort to this. | |
38 static inline constexpr bool operator &(const mojo::EventFlags& f1, | |
39 const mojo::EventFlags& f2) { | |
40 return ((static_cast<uint32_t>(f1) & static_cast<uint32_t>(f2)) != 0); | |
41 } | |
42 | |
43 const SkColor kColors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorYELLOW }; | |
44 | |
45 class EmbedderImpl : public Embedder { | |
46 public: | |
47 explicit EmbedderImpl(mojo::InterfaceRequest<Embedder> request) | |
48 : binding_(this, request.Pass()) {} | |
49 ~EmbedderImpl() override {} | |
50 | |
51 private: | |
52 // Overridden from Embedder: | |
53 void HelloWorld(const mojo::Callback<void()>& callback) override { | |
54 callback.Run(); | |
55 } | |
56 | |
57 mojo::StrongBinding<Embedder> binding_; | |
58 DISALLOW_COPY_AND_ASSIGN(EmbedderImpl); | |
59 }; | |
60 | |
61 class EmbedderImplProvider : public mojo::ServiceProvider { | |
62 public: | |
63 EmbedderImplProvider() {} | |
64 ~EmbedderImplProvider() override {} | |
65 | |
66 void AddBinding(mojo::InterfaceRequest<mojo::ServiceProvider> request) { | |
67 embeddee_exposed_services_.AddBinding(this, request.Pass()); | |
68 } | |
69 | |
70 private: | |
71 // mojo::ServiceProvider implementation | |
72 void ConnectToService(const mojo::String& interface_name, | |
73 mojo::ScopedMessagePipeHandle pipe_handle) override { | |
74 if (interface_name != Embedder::Name_) | |
75 return; | |
76 new EmbedderImpl(mojo::MakeRequest<Embedder>(pipe_handle.Pass())); | |
77 } | |
78 | |
79 mojo::BindingSet<mojo::ServiceProvider> embeddee_exposed_services_; | |
80 | |
81 DISALLOW_COPY_AND_ASSIGN(EmbedderImplProvider); | |
82 }; | |
83 | |
84 } // namespace | |
85 | |
86 // This app starts its life via Connect() rather than by being embed, so it does | |
87 // not start with a connection to the ViewManager service. It has to obtain a | |
88 // connection by connecting to the ViewManagerInit service and asking to be | |
89 // embed without a view context. | |
90 class WMFlowApp : public mojo::ApplicationDelegate, | |
91 public mojo::ViewManagerDelegate, | |
92 public mojo::ViewObserver { | |
93 public: | |
94 WMFlowApp() : shell_(nullptr), embed_count_(0) {} | |
95 ~WMFlowApp() override { STLDeleteValues(&uploaders_); } | |
96 | |
97 private: | |
98 typedef std::map<mojo::View*, mojo::BitmapUploader*> ViewToUploader; | |
99 | |
100 // Overridden from ApplicationDelegate: | |
101 void Initialize(mojo::ApplicationImpl* app) override { | |
102 shell_ = app->shell(); | |
103 view_manager_client_factory_.reset( | |
104 new mojo::ViewManagerClientFactory(app->shell(), this)); | |
105 view_manager_context_.reset(new mojo::ViewManagerContext(app)); | |
106 // FIXME: Mojo applications don't know their URLs yet: | |
107 // https://docs.google.com/a/chromium.org/document/d/1AQ2y6ekzvbdaMF5WrUQmne
yXJnke-MnYYL4Gz1AKDos | |
108 url_ = GURL(app->args()[1]); | |
109 OpenNewWindow(); | |
110 OpenNewWindow(); | |
111 OpenNewWindow(); | |
112 } | |
113 bool ConfigureIncomingConnection( | |
114 mojo::ApplicationConnection* connection) override { | |
115 connection->AddService(view_manager_client_factory_.get()); | |
116 return true; | |
117 } | |
118 | |
119 // Overridden from mojo::ViewManagerDelegate: | |
120 void OnEmbed(mojo::View* root, | |
121 mojo::InterfaceRequest<mojo::ServiceProvider> services, | |
122 mojo::ServiceProviderPtr exposed_services) override { | |
123 root->AddObserver(this); | |
124 mojo::BitmapUploader* uploader = new mojo::BitmapUploader(root); | |
125 uploaders_[root] = uploader; | |
126 uploader->Init(shell_); | |
127 // BitmapUploader does not track view size changes, we would | |
128 // need to subscribe to OnViewBoundsChanged and tell the bitmap uploader | |
129 // to invalidate itself. This is better done once if had a per-view | |
130 // object instead of holding per-view state on the ApplicationDelegate. | |
131 uploader->SetColor(kColors[embed_count_++ % arraysize(kColors)]); | |
132 | |
133 mojo::View* embed = root->view_manager()->CreateView(); | |
134 root->AddChild(embed); | |
135 mojo::Rect bounds; | |
136 bounds.x = bounds.y = 25; | |
137 bounds.width = root->bounds().width - 50; | |
138 bounds.height = root->bounds().height - 50; | |
139 embed->SetBounds(bounds); | |
140 embed->SetVisible(true); | |
141 | |
142 mojo::ServiceProviderPtr embedee_exposed_services; | |
143 embeddee_provider_.AddBinding(GetProxy(&embedee_exposed_services)); | |
144 | |
145 GURL embedded_app_url = url_.Resolve("wm_flow_embedded.mojo"); | |
146 mojo::ServiceProviderPtr imported; | |
147 embed->Embed(embedded_app_url.spec(), GetProxy(&imported), | |
148 embedee_exposed_services.Pass()); | |
149 // FIXME: This is wrong. We're storing per-view state on this per-app | |
150 // delegate. Every time a new view is created embedee_ is replaced | |
151 // causing the previous one to shut down. This class should not | |
152 // be a ViewManagerDelegate, but rather a separate object should be | |
153 // created for each embedding. | |
154 mojo::ConnectToService(imported.get(), &embeddee_); | |
155 embeddee_->HelloBack(base::Bind(&WMFlowApp::HelloBackAck, | |
156 base::Unretained(this))); | |
157 } | |
158 void OnViewManagerDisconnected(mojo::ViewManager* view_manager) override { | |
159 STLDeleteValues(&uploaders_); | |
160 } | |
161 | |
162 // Overridden from mojo::ViewObserver: | |
163 void OnViewInputEvent(mojo::View* view, | |
164 const mojo::EventPtr& event) override { | |
165 if (event->action == mojo::EventType::POINTER_UP && | |
166 event->flags & mojo::EventFlags::LEFT_MOUSE_BUTTON) { | |
167 OpenNewWindow(); | |
168 } | |
169 } | |
170 void OnViewDestroyed(mojo::View* view) override { | |
171 if (uploaders_.find(view) != uploaders_.end()) { | |
172 delete uploaders_[view]; | |
173 uploaders_.erase(view); | |
174 } | |
175 --embed_count_; | |
176 view->RemoveObserver(this); | |
177 } | |
178 | |
179 void HelloBackAck() { | |
180 printf("HelloBack() ack'ed\n"); | |
181 } | |
182 | |
183 void OpenNewWindow() { view_manager_context_->Embed(url_.spec()); } | |
184 | |
185 mojo::Shell* shell_; | |
186 int embed_count_; | |
187 scoped_ptr<mojo::ViewManagerClientFactory> view_manager_client_factory_; | |
188 scoped_ptr<mojo::ViewManagerContext> view_manager_context_; | |
189 EmbeddeePtr embeddee_; | |
190 EmbedderImplProvider embeddee_provider_; | |
191 ViewToUploader uploaders_; | |
192 GURL url_; | |
193 | |
194 DISALLOW_COPY_AND_ASSIGN(WMFlowApp); | |
195 }; | |
196 | |
197 } // namespace examples | |
198 | |
199 MojoResult MojoMain(MojoHandle application_request) { | |
200 mojo::ApplicationRunnerChromium runner(new examples::WMFlowApp); | |
201 return runner.Run(application_request); | |
202 } | |
OLD | NEW |