| 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 |