context.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
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 "build/build_config.h"
8#include "base/command_line.h"
9#include "base/lazy_instance.h"
10#include "base/memory/scoped_vector.h"
11#include "mojo/embedder/embedder.h"
12#include "mojo/gles2/gles2_support_impl.h"
13#include "mojo/public/cpp/application/application.h"
14#include "mojo/service_manager/background_service_loader.h"
15#include "mojo/service_manager/service_loader.h"
16#include "mojo/service_manager/service_manager.h"
17#include "mojo/services/native_viewport/native_viewport_service.h"
18#include "mojo/shell/dynamic_service_loader.h"
19#include "mojo/shell/in_process_dynamic_service_runner.h"
20#include "mojo/shell/out_of_process_dynamic_service_runner.h"
21#include "mojo/shell/switches.h"
22#include "mojo/spy/spy.h"
23
24#if defined(OS_LINUX)
25#include "mojo/shell/dbus_service_loader_linux.h"
26#endif  // defined(OS_LINUX)
27
28#if defined(USE_AURA)
29#include "mojo/shell/view_manager_loader.h"
30#endif
31
32namespace mojo {
33namespace shell {
34namespace {
35
36// These mojo: URLs are loaded directly from the local filesystem. They
37// correspond to shared libraries bundled alongside the mojo_shell.
38const char* kLocalMojoURLs[] = {
39  "mojo:mojo_network_service",
40};
41
42// Used to ensure we only init once.
43class Setup {
44 public:
45  Setup() {
46    embedder::Init();
47    gles2::GLES2SupportImpl::Init();
48  }
49
50  ~Setup() {
51  }
52
53 private:
54  DISALLOW_COPY_AND_ASSIGN(Setup);
55};
56
57static base::LazyInstance<Setup>::Leaky setup = LAZY_INSTANCE_INITIALIZER;
58
59}  // namespace
60
61class Context::NativeViewportServiceLoader : public ServiceLoader {
62 public:
63  explicit NativeViewportServiceLoader(Context* context) : context_(context) {}
64  virtual ~NativeViewportServiceLoader() {}
65
66 private:
67  virtual void LoadService(ServiceManager* manager,
68                           const GURL& url,
69                           ScopedMessagePipeHandle service_handle) OVERRIDE {
70    app_.reset(::CreateNativeViewportService(context_, service_handle.Pass()));
71  }
72
73  virtual void OnServiceError(ServiceManager* manager,
74                              const GURL& url) OVERRIDE {
75  }
76
77  Context* context_;
78  scoped_ptr<Application> app_;
79  DISALLOW_COPY_AND_ASSIGN(NativeViewportServiceLoader);
80};
81
82Context::Context()
83    : task_runners_(base::MessageLoop::current()->message_loop_proxy()) {
84  setup.Get();
85
86  for (size_t i = 0; i < arraysize(kLocalMojoURLs); ++i)
87    mojo_url_resolver_.AddLocalFileMapping(GURL(kLocalMojoURLs[i]));
88
89  base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
90  scoped_ptr<DynamicServiceRunnerFactory> runner_factory;
91  if (cmdline->HasSwitch(switches::kEnableMultiprocess))
92    runner_factory.reset(new OutOfProcessDynamicServiceRunnerFactory());
93  else
94    runner_factory.reset(new InProcessDynamicServiceRunnerFactory());
95
96  service_manager_.set_default_loader(
97      scoped_ptr<ServiceLoader>(
98          new DynamicServiceLoader(this, runner_factory.Pass())));
99  // The native viewport service synchronously waits for certain messages. If we
100  // don't run it on its own thread we can easily deadlock. Long term native
101  // viewport should run its own process so that this isn't an issue.
102  service_manager_.SetLoaderForURL(
103      scoped_ptr<ServiceLoader>(
104          new BackgroundServiceLoader(
105              scoped_ptr<ServiceLoader>(new NativeViewportServiceLoader(this)),
106              "native_viewport",
107              base::MessageLoop::TYPE_UI)),
108      GURL("mojo:mojo_native_viewport_service"));
109#if defined(USE_AURA)
110  // TODO(sky): need a better way to find this. It shouldn't be linked in.
111  service_manager_.SetLoaderForURL(
112      scoped_ptr<ServiceLoader>(new ViewManagerLoader()),
113      GURL("mojo:mojo_view_manager"));
114#endif
115
116#if defined(OS_LINUX)
117  service_manager_.SetLoaderForScheme(
118      scoped_ptr<ServiceLoader>(new DBusServiceLoader(this)),
119      "dbus");
120#endif  // defined(OS_LINUX)
121
122  if (cmdline->HasSwitch(switches::kSpy)) {
123    spy_.reset(new mojo::Spy(&service_manager_,
124                             cmdline->GetSwitchValueASCII(switches::kSpy)));
125  }
126}
127
128Context::~Context() {
129  // mojo_view_manager uses native_viewport. Destroy mojo_view_manager first so
130  // that there aren't shutdown ordering issues. Once native viewport service is
131  // moved into its own process this can likely be nuked.
132#if defined(USE_AURA)
133  service_manager_.SetLoaderForURL(
134      scoped_ptr<ServiceLoader>(),
135      GURL("mojo:mojo_view_manager"));
136#endif
137  service_manager_.set_default_loader(scoped_ptr<ServiceLoader>());
138}
139
140}  // namespace shell
141}  // namespace mojo
142