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