Chromium Code Reviews| Index: mojo/shell/service_manager.cc |
| diff --git a/mojo/shell/service_manager.cc b/mojo/shell/service_manager.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..0822e8826fedf1857c020f082e7be9b3def06114 |
| --- /dev/null |
| +++ b/mojo/shell/service_manager.cc |
| @@ -0,0 +1,140 @@ |
| +// Copyright 2013 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "mojo/shell/service_manager.h" |
| + |
| +#include "base/bind.h" |
| +#include "base/callback_helpers.h" |
| +#include "base/command_line.h" |
| +#include "base/file_util.h" |
| +#include "base/scoped_native_library.h" |
| +#include "base/threading/simple_thread.h" |
| +#include "mojo/public/bindings/lib/remote_ptr.h" |
| +#include "mojo/shell/context.h" |
| +#include "mojo/shell/switches.h" |
| +#include "mojom/shell.h" |
| + |
| +typedef MojoResult (*MojoMainFunction)(MojoHandle pipe); |
| + |
| +namespace mojo { |
| +namespace shell { |
| + |
| +class ServiceManager::Service |
| + : public ::shell::ShellStub, |
| + public Loader::Delegate, |
| + public base::DelegateSimpleThread::Delegate { |
| + public: |
| + Service(ServiceManager* manager, const GURL& url) |
| + : manager_(manager), |
| + url_(url), |
| + weak_factory_(this) { |
| + base::AutoLock lock(lock_); |
|
abarth-chromium
2013/12/10 04:53:51
You're still planning to remove this lock, right?
DaveMoore
2013/12/11 18:56:44
Done.
|
| + ScopedMessagePipeHandle shell_handle; |
| + CreateMessagePipe(&shell_handle, &service_handle_); |
| + shell_client_.reset(shell_handle.Pass()); |
| + shell_client_.SetPeer(this); |
| + request_ = manager_->context_->loader()->Load(url_, this); |
| + } |
| + |
| + virtual ~Service() {} |
| + |
| + void ConnectToClient(ScopedMessagePipeHandle handle) { |
| + if (handle.is_valid()) |
| + shell_client_->Connect(handle.Pass()); |
| + } |
| + |
| + virtual void Connect(const mojo::String& url, |
|
darin (slow to review)
2013/12/10 06:12:36
nit: no need for the "mojo::" prefix inside the mo
DaveMoore
2013/12/11 18:56:44
Done.
|
| + ScopedMessagePipeHandle client_pipe) MOJO_OVERRIDE { |
| + manager_->Connect(GURL(url.To<std::string>()), client_pipe.Pass()); |
|
darin (slow to review)
2013/12/10 06:12:36
note: we could write a TypeConverter specializatio
|
| + } |
| + |
| + private: |
| + // From Loader::Delegate. |
| + virtual void DidCompleteLoad(const GURL& app_url, |
| + const base::FilePath& app_path) OVERRIDE { |
| + base::AutoLock lock(lock_); |
| + app_path_ = app_path; |
| + ack_closure_ = |
| + base::Bind(&Service::AppCompleted, weak_factory_.GetWeakPtr()); |
| + thread_.reset(new base::DelegateSimpleThread(this, "app_thread")); |
| + thread_->Start(); |
| + } |
| + |
| + // From base::DelegateSimpleThread::Delegate. |
| + virtual void Run() OVERRIDE { |
| + base::ScopedClosureRunner app_deleter( |
| + base::Bind(base::IgnoreResult(&base::DeleteFile), app_path_, false)); |
| + base::ScopedNativeLibrary app_library( |
| + base::LoadNativeLibrary(app_path_, NULL)); |
| + if (!app_library.is_valid()) { |
| + LOG(ERROR) << "Failed to load library: " << app_path_.value().c_str(); |
| + return; |
| + } |
| + |
| + MojoMainFunction main_function = reinterpret_cast<MojoMainFunction>( |
| + app_library.GetFunctionPointer("MojoMain")); |
| + if (!main_function) { |
| + LOG(ERROR) << "Entrypoint MojoMain not found."; |
| + return; |
| + } |
| + |
| + // |MojoMain()| takes ownership of the app handle. |
| + MojoResult result = main_function(service_handle_.release().value()); |
| + if (result < MOJO_RESULT_OK) { |
| + LOG(ERROR) << "MojoMain returned an error: " << result; |
| + return; |
| + } |
| + manager_->context_->task_runners()->ui_runner()->PostTask( |
| + FROM_HERE, |
| + ack_closure_); |
| + } |
| + |
| + void AppCompleted() { |
| + thread_->Join(); |
| + thread_.reset(); |
| + } |
| + |
| + base::Lock lock_; |
| + ServiceManager* manager_; |
| + GURL url_; |
| + mojo::RemotePtr<::shell::ShellClient> shell_client_; |
|
darin (slow to review)
2013/12/10 06:12:36
nit: ditto re: mojo::
DaveMoore
2013/12/11 18:56:44
Done.
|
| + base::FilePath app_path_; |
| + base::Closure ack_closure_; |
| + scoped_ptr<Loader::Job> request_; |
| + scoped_ptr<base::DelegateSimpleThread> thread_; |
| + ScopedMessagePipeHandle service_handle_; |
| + |
| + base::WeakPtrFactory<Service> weak_factory_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(Service); |
| +}; |
| + |
| +ServiceManager::ServiceManager(Context* context) : context_(context) { |
| +} |
| + |
| +ServiceManager::~ServiceManager() { |
| +} |
| + |
| +void ServiceManager::Connect(const GURL& url, |
| + ScopedMessagePipeHandle client_handle) { |
| + GURL app_url = url; |
| + if (url.scheme() == "mojo") { |
| + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); |
| + std::string origin = command_line.GetSwitchValueASCII(switches::kOrigin); |
| + std::string lib("lib" + url.ExtractFileName() + ".so"); |
|
abarth-chromium
2013/12/10 04:53:51
We still have the problem of this not working on W
Ben Goodger (Google)
2013/12/10 16:35:03
windows impl:
std::string lib(url.ExtractFileName
DaveMoore
2013/12/11 18:56:44
Added windows impl, still need to figure out mac
O
|
| + app_url = GURL(origin + std::string("/") + lib); |
| + } |
| + ServiceMap::const_iterator service_it = url_to_service_.find(app_url); |
| + Service* service; |
| + if (service_it != url_to_service_.end()) { |
| + service = service_it->second; |
| + } else { |
| + service = new Service(this, app_url); |
| + url_to_service_[app_url] = service; |
| + } |
| + service->ConnectToClient(client_handle.Pass()); |
| +} |
| + |
| +} // namespace shell |
| +} // namespace mojo |