Home | History | Annotate | Download | only in shell
      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 
     32 namespace mojo {
     33 namespace shell {
     34 namespace {
     35 
     36 // These mojo: URLs are loaded directly from the local filesystem. They
     37 // correspond to shared libraries bundled alongside the mojo_shell.
     38 const char* kLocalMojoURLs[] = {
     39   "mojo:mojo_network_service",
     40 };
     41 
     42 // Used to ensure we only init once.
     43 class 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 
     57 static base::LazyInstance<Setup>::Leaky setup = LAZY_INSTANCE_INITIALIZER;
     58 
     59 }  // namespace
     60 
     61 class 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 
     82 Context::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 
    128 Context::~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