context.cc revision 03b57e008b61dfcb1fbad3aea950ae0e001748b0
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/services/native_viewport/gpu_impl.h" 25#include "mojo/services/native_viewport/native_viewport_impl.h" 26#include "mojo/shell/dynamic_application_loader.h" 27#include "mojo/shell/in_process_dynamic_service_runner.h" 28#include "mojo/shell/out_of_process_dynamic_service_runner.h" 29#include "mojo/shell/switches.h" 30#include "mojo/shell/ui_application_loader_android.h" 31#include "mojo/spy/spy.h" 32#include "ui/gl/gl_share_group.h" 33 34#if defined(OS_LINUX) 35#include "mojo/shell/dbus_application_loader_linux.h" 36#endif // defined(OS_LINUX) 37 38#if defined(OS_ANDROID) 39#include "mojo/shell/network_application_loader.h" 40#endif // defined(OS_ANDROID) 41 42#if defined(USE_AURA) 43#include "mojo/shell/view_manager_loader.h" 44#endif 45 46namespace mojo { 47namespace shell { 48namespace { 49 50// These mojo: URLs are loaded directly from the local filesystem. They 51// correspond to shared libraries bundled alongside the mojo_shell. 52const char* kLocalMojoURLs[] = { 53 "mojo:mojo_network_service", 54}; 55 56// Used to ensure we only init once. 57class Setup { 58 public: 59 Setup() { 60 embedder::Init(scoped_ptr<mojo::embedder::PlatformSupport>( 61 new mojo::embedder::SimplePlatformSupport())); 62 } 63 64 ~Setup() { 65 } 66 67 private: 68 DISALLOW_COPY_AND_ASSIGN(Setup); 69}; 70 71static base::LazyInstance<Setup>::Leaky setup = LAZY_INSTANCE_INITIALIZER; 72 73void InitContentHandlers(DynamicApplicationLoader* loader, 74 base::CommandLine* command_line) { 75 std::string handlers_spec = command_line->GetSwitchValueASCII( 76 switches::kContentHandlers); 77 if (handlers_spec.empty()) 78 return; 79 80 std::vector<std::string> parts; 81 base::SplitString(handlers_spec, ',', &parts); 82 if (parts.size() % 2 != 0) { 83 LOG(ERROR) << "Invalid value for switch " << switches::kContentHandlers 84 << ": must be a comma-separated list of mimetype/url pairs."; 85 return; 86 } 87 88 for (size_t i = 0; i < parts.size(); i += 2) { 89 GURL url(parts[i + 1]); 90 if (!url.is_valid()) { 91 LOG(ERROR) << "Invalid value for switch " << switches::kContentHandlers 92 << ": '" << parts[i + 1] << "' is not a valid URL."; 93 return; 94 } 95 loader->RegisterContentHandler(parts[i], url); 96 } 97} 98 99} // namespace 100 101class Context::NativeViewportApplicationLoader 102 : public ApplicationLoader, 103 public ApplicationDelegate, 104 public InterfaceFactory<NativeViewport>, 105 public InterfaceFactory<Gpu> { 106 public: 107 NativeViewportApplicationLoader() 108 : share_group_(new gfx::GLShareGroup), 109 mailbox_manager_(new gpu::gles2::MailboxManager) {} 110 virtual ~NativeViewportApplicationLoader() {} 111 112 private: 113 // ApplicationLoader implementation. 114 virtual void Load(ApplicationManager* manager, 115 const GURL& url, 116 scoped_refptr<LoadCallbacks> callbacks) OVERRIDE { 117 ScopedMessagePipeHandle shell_handle = callbacks->RegisterApplication(); 118 if (shell_handle.is_valid()) 119 app_.reset(new ApplicationImpl(this, shell_handle.Pass())); 120 } 121 122 virtual void OnServiceError(ApplicationManager* manager, 123 const GURL& url) OVERRIDE {} 124 125 // ApplicationDelegate implementation. 126 virtual bool ConfigureIncomingConnection( 127 mojo::ApplicationConnection* connection) OVERRIDE { 128 connection->AddService<NativeViewport>(this); 129 connection->AddService<Gpu>(this); 130 return true; 131 } 132 133 // InterfaceFactory<NativeViewport> implementation. 134 virtual void Create(ApplicationConnection* connection, 135 InterfaceRequest<NativeViewport> request) OVERRIDE { 136 BindToRequest(new NativeViewportImpl, &request); 137 } 138 139 // InterfaceFactory<Gpu> implementation. 140 virtual void Create(ApplicationConnection* connection, 141 InterfaceRequest<Gpu> request) OVERRIDE { 142 BindToRequest(new GpuImpl(share_group_.get(), mailbox_manager_.get()), 143 &request); 144 } 145 146 scoped_refptr<gfx::GLShareGroup> share_group_; 147 scoped_refptr<gpu::gles2::MailboxManager> mailbox_manager_; 148 scoped_ptr<ApplicationImpl> app_; 149 DISALLOW_COPY_AND_ASSIGN(NativeViewportApplicationLoader); 150}; 151 152Context::Context() { 153 DCHECK(!base::MessageLoop::current()); 154} 155 156void Context::Init() { 157 setup.Get(); 158 task_runners_.reset( 159 new TaskRunners(base::MessageLoop::current()->message_loop_proxy())); 160 161 for (size_t i = 0; i < arraysize(kLocalMojoURLs); ++i) 162 mojo_url_resolver_.AddLocalFileMapping(GURL(kLocalMojoURLs[i])); 163 164 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); 165 scoped_ptr<DynamicServiceRunnerFactory> runner_factory; 166 if (command_line->HasSwitch(switches::kEnableMultiprocess)) 167 runner_factory.reset(new OutOfProcessDynamicServiceRunnerFactory()); 168 else 169 runner_factory.reset(new InProcessDynamicServiceRunnerFactory()); 170 171 DynamicApplicationLoader* dynamic_application_loader = 172 new DynamicApplicationLoader(this, runner_factory.Pass()); 173 InitContentHandlers(dynamic_application_loader, command_line); 174 application_manager_.set_default_loader( 175 scoped_ptr<ApplicationLoader>(dynamic_application_loader)); 176 177 // The native viewport service synchronously waits for certain messages. If we 178 // don't run it on its own thread we can easily deadlock. Long term native 179 // viewport should run its own process so that this isn't an issue. 180#if defined(OS_ANDROID) 181 application_manager_.SetLoaderForURL( 182 scoped_ptr<ApplicationLoader>(new UIApplicationLoader( 183 scoped_ptr<ApplicationLoader>(new NativeViewportApplicationLoader()), 184 this)), 185 GURL("mojo:mojo_native_viewport_service")); 186#else 187 { 188 scoped_ptr<BackgroundShellApplicationLoader> loader( 189 new BackgroundShellApplicationLoader( 190 scoped_ptr<ApplicationLoader>( 191 new NativeViewportApplicationLoader()), 192 "native_viewport", 193 base::MessageLoop::TYPE_UI)); 194 application_manager_.SetLoaderForURL( 195 loader.PassAs<ApplicationLoader>(), 196 GURL("mojo:mojo_native_viewport_service")); 197 } 198#endif 199#if defined(USE_AURA) 200 // TODO(sky): need a better way to find this. It shouldn't be linked in. 201 application_manager_.SetLoaderForURL( 202 scoped_ptr<ApplicationLoader>(new ViewManagerLoader()), 203 GURL("mojo:mojo_view_manager")); 204#endif 205 206#if defined(OS_LINUX) 207 application_manager_.SetLoaderForScheme( 208 scoped_ptr<ApplicationLoader>(new DBusApplicationLoader(this)), "dbus"); 209#endif // defined(OS_LINUX) 210 211 if (command_line->HasSwitch(switches::kSpy)) { 212 spy_.reset( 213 new mojo::Spy(&application_manager_, 214 command_line->GetSwitchValueASCII(switches::kSpy))); 215 } 216 217#if defined(OS_ANDROID) 218 // On android, the network service is bundled with the shell because the 219 // network stack depends on the android runtime. 220 { 221 scoped_ptr<BackgroundShellApplicationLoader> loader( 222 new BackgroundShellApplicationLoader( 223 scoped_ptr<ApplicationLoader>(new NetworkApplicationLoader()), 224 "network_service", 225 base::MessageLoop::TYPE_IO)); 226 application_manager_.SetLoaderForURL(loader.PassAs<ApplicationLoader>(), 227 GURL("mojo:mojo_network_service")); 228 } 229#endif 230} 231 232Context::~Context() { 233 DCHECK(!base::MessageLoop::current()); 234} 235 236} // namespace shell 237} // namespace mojo 238