Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / mojo / shell / context.cc
1 // Copyright 2013 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 "mojo/shell/context.h"
6
7 #include <vector>
8
9 #include "base/command_line.h"
10 #include "base/lazy_instance.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/memory/scoped_vector.h"
13 #include "base/strings/string_split.h"
14 #include "build/build_config.h"
15 #include "gpu/command_buffer/service/mailbox_manager.h"
16 #include "mojo/application_manager/application_loader.h"
17 #include "mojo/application_manager/application_manager.h"
18 #include "mojo/application_manager/background_shell_application_loader.h"
19 #include "mojo/embedder/embedder.h"
20 #include "mojo/embedder/simple_platform_support.h"
21 #include "mojo/public/cpp/application/application_connection.h"
22 #include "mojo/public/cpp/application/application_delegate.h"
23 #include "mojo/public/cpp/application/application_impl.h"
24 #include "mojo/shell/dynamic_application_loader.h"
25 #include "mojo/shell/in_process_dynamic_service_runner.h"
26 #include "mojo/shell/out_of_process_dynamic_service_runner.h"
27 #include "mojo/shell/switches.h"
28 #include "mojo/shell/ui_application_loader_android.h"
29 #include "mojo/spy/spy.h"
30
31 #if defined(OS_LINUX)
32 #include "mojo/shell/dbus_application_loader_linux.h"
33 #endif  // defined(OS_LINUX)
34
35 #if defined(OS_ANDROID)
36 #include "mojo/services/native_viewport/gpu_impl.h"
37 #include "mojo/services/native_viewport/native_viewport_impl.h"
38 #include "mojo/shell/network_application_loader.h"
39 #include "ui/gl/gl_share_group.h"
40 #endif  // defined(OS_ANDROID)
41
42 namespace mojo {
43 namespace shell {
44 namespace {
45
46 // These mojo: URLs are loaded directly from the local filesystem. They
47 // correspond to shared libraries bundled alongside the mojo_shell.
48 const char* kLocalMojoURLs[] = {
49   "mojo:mojo_network_service",
50 };
51
52 // Used to ensure we only init once.
53 class Setup {
54  public:
55   Setup() {
56     embedder::Init(scoped_ptr<mojo::embedder::PlatformSupport>(
57         new mojo::embedder::SimplePlatformSupport()));
58   }
59
60   ~Setup() {
61   }
62
63  private:
64   DISALLOW_COPY_AND_ASSIGN(Setup);
65 };
66
67 static base::LazyInstance<Setup>::Leaky setup = LAZY_INSTANCE_INITIALIZER;
68
69 void InitContentHandlers(DynamicApplicationLoader* loader,
70                          base::CommandLine* command_line) {
71   // Default content handlers.
72   loader->RegisterContentHandler("image/png", GURL("mojo://mojo_png_viewer/"));
73   loader->RegisterContentHandler("text/html", GURL("mojo://mojo_html_viewer/"));
74
75   // Command-line-specified content handlers.
76   std::string handlers_spec = command_line->GetSwitchValueASCII(
77       switches::kContentHandlers);
78   if (handlers_spec.empty())
79     return;
80
81   std::vector<std::string> parts;
82   base::SplitString(handlers_spec, ',', &parts);
83   if (parts.size() % 2 != 0) {
84     LOG(ERROR) << "Invalid value for switch " << switches::kContentHandlers
85                << ": must be a comma-separated list of mimetype/url pairs.";
86     return;
87   }
88
89   for (size_t i = 0; i < parts.size(); i += 2) {
90     GURL url(parts[i + 1]);
91     if (!url.is_valid()) {
92       LOG(ERROR) << "Invalid value for switch " << switches::kContentHandlers
93                  << ": '" << parts[i + 1] << "' is not a valid URL.";
94       return;
95     }
96     loader->RegisterContentHandler(parts[i], url);
97   }
98 }
99
100 class EmptyServiceProvider : public InterfaceImpl<ServiceProvider> {
101  private:
102   virtual void ConnectToService(const mojo::String& service_name,
103                                 ScopedMessagePipeHandle client_handle)
104       MOJO_OVERRIDE {
105   }
106 };
107
108 }  // namespace
109
110 #if defined(OS_ANDROID)
111 class Context::NativeViewportApplicationLoader
112     : public ApplicationLoader,
113       public ApplicationDelegate,
114       public InterfaceFactory<NativeViewport>,
115       public InterfaceFactory<Gpu> {
116  public:
117   NativeViewportApplicationLoader()
118       : share_group_(new gfx::GLShareGroup),
119         mailbox_manager_(new gpu::gles2::MailboxManager) {}
120   virtual ~NativeViewportApplicationLoader() {}
121
122  private:
123   // ApplicationLoader implementation.
124   virtual void Load(ApplicationManager* manager,
125                     const GURL& url,
126                     scoped_refptr<LoadCallbacks> callbacks) OVERRIDE {
127     ScopedMessagePipeHandle shell_handle = callbacks->RegisterApplication();
128     if (shell_handle.is_valid())
129       app_.reset(new ApplicationImpl(this, shell_handle.Pass()));
130   }
131
132   virtual void OnApplicationError(ApplicationManager* manager,
133                                   const GURL& url) OVERRIDE {}
134
135   // ApplicationDelegate implementation.
136   virtual bool ConfigureIncomingConnection(
137       mojo::ApplicationConnection* connection) OVERRIDE {
138     connection->AddService<NativeViewport>(this);
139     connection->AddService<Gpu>(this);
140     return true;
141   }
142
143   // InterfaceFactory<NativeViewport> implementation.
144   virtual void Create(ApplicationConnection* connection,
145                       InterfaceRequest<NativeViewport> request) OVERRIDE {
146     BindToRequest(new NativeViewportImpl(app_.get(), false), &request);
147   }
148
149   // InterfaceFactory<Gpu> implementation.
150   virtual void Create(ApplicationConnection* connection,
151                       InterfaceRequest<Gpu> request) OVERRIDE {
152     BindToRequest(new GpuImpl(share_group_.get(), mailbox_manager_.get()),
153                   &request);
154   }
155
156   scoped_refptr<gfx::GLShareGroup> share_group_;
157   scoped_refptr<gpu::gles2::MailboxManager> mailbox_manager_;
158   scoped_ptr<ApplicationImpl> app_;
159   DISALLOW_COPY_AND_ASSIGN(NativeViewportApplicationLoader);
160 };
161 #endif
162
163 Context::Context() {
164   DCHECK(!base::MessageLoop::current());
165 }
166
167 Context::~Context() {
168   DCHECK(!base::MessageLoop::current());
169 }
170
171 void Context::Init() {
172   application_manager_.set_delegate(this);
173   setup.Get();
174   task_runners_.reset(
175       new TaskRunners(base::MessageLoop::current()->message_loop_proxy()));
176
177   for (size_t i = 0; i < arraysize(kLocalMojoURLs); ++i)
178     mojo_url_resolver_.AddLocalFileMapping(GURL(kLocalMojoURLs[i]));
179
180   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
181   scoped_ptr<DynamicServiceRunnerFactory> runner_factory;
182   if (command_line->HasSwitch(switches::kEnableMultiprocess))
183     runner_factory.reset(new OutOfProcessDynamicServiceRunnerFactory());
184   else
185     runner_factory.reset(new InProcessDynamicServiceRunnerFactory());
186
187   DynamicApplicationLoader* dynamic_application_loader =
188       new DynamicApplicationLoader(this, runner_factory.Pass());
189   InitContentHandlers(dynamic_application_loader, command_line);
190   application_manager_.set_default_loader(
191       scoped_ptr<ApplicationLoader>(dynamic_application_loader));
192
193   // The native viewport service synchronously waits for certain messages. If we
194   // don't run it on its own thread we can easily deadlock. Long term native
195   // viewport should run its own process so that this isn't an issue.
196 #if defined(OS_ANDROID)
197   application_manager_.SetLoaderForURL(
198       scoped_ptr<ApplicationLoader>(new UIApplicationLoader(
199           scoped_ptr<ApplicationLoader>(new NativeViewportApplicationLoader()),
200           this)),
201       GURL("mojo:mojo_native_viewport_service"));
202 #endif
203
204 #if defined(OS_LINUX)
205   application_manager_.SetLoaderForScheme(
206       scoped_ptr<ApplicationLoader>(new DBusApplicationLoader(this)), "dbus");
207 #endif  // defined(OS_LINUX)
208
209   if (command_line->HasSwitch(switches::kSpy)) {
210     spy_.reset(
211         new mojo::Spy(&application_manager_,
212                       command_line->GetSwitchValueASCII(switches::kSpy)));
213   }
214
215 #if defined(OS_ANDROID)
216   // On android, the network service is bundled with the shell because the
217   // network stack depends on the android runtime.
218   {
219     scoped_ptr<BackgroundShellApplicationLoader> loader(
220         new BackgroundShellApplicationLoader(
221             scoped_ptr<ApplicationLoader>(new NetworkApplicationLoader()),
222             "network_service",
223             base::MessageLoop::TYPE_IO));
224     application_manager_.SetLoaderForURL(loader.PassAs<ApplicationLoader>(),
225                                          GURL("mojo:mojo_network_service"));
226   }
227 #endif
228 }
229
230 void Context::OnApplicationError(const GURL& gurl) {
231   if (app_urls_.find(gurl) != app_urls_.end()) {
232     app_urls_.erase(gurl);
233     if (app_urls_.empty() && base::MessageLoop::current()->is_running())
234       base::MessageLoop::current()->Quit();
235   }
236 }
237
238 void Context::Run(const GURL& url) {
239   EmptyServiceProvider* sp = new EmptyServiceProvider;
240   ServiceProviderPtr spp;
241   BindToProxy(sp, &spp);
242
243   app_urls_.insert(url);
244   application_manager_.ConnectToApplication(url, GURL(), spp.Pass());
245 }
246
247 ScopedMessagePipeHandle Context::ConnectToServiceByName(
248     const GURL& application_url,
249     const std::string& service_name) {
250   app_urls_.insert(application_url);
251   return application_manager_.ConnectToServiceByName(
252       application_url, service_name).Pass();
253 }
254
255 }  // namespace shell
256 }  // namespace mojo