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..3defdd84aca58edd7b52824c6dda8f3c61432b7a |
--- /dev/null |
+++ b/mojo/shell/service_manager.cc |
@@ -0,0 +1,142 @@ |
+// 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_); |
+ 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, |
+ ScopedMessagePipeHandle client_pipe) MOJO_OVERRIDE { |
+ manager_->Connect(GURL(url.To<std::string>()), client_pipe.Pass()); |
+ } |
+ |
+ 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::AutoLock lock(lock_); |
abarth-chromium
2013/12/10 01:06:03
So, this lock is held as long as the app is runnin
DaveMoore
2013/12/10 03:00:45
You are right. It was left in accidentally
On 2013
|
+ 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_; |
+ 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 01:06:03
This won't work on Window or Mac.
DaveMoore
2013/12/10 03:00:45
You're right...it won't. I'll take a look at that
|
+ app_url = GURL(origin + std::string("/") + lib); |
+ } |
+ base::AutoLock lock(service_map_lock_); |
abarth-chromium
2013/12/10 01:06:03
I don't understand this lock either. Isn't this f
DaveMoore
2013/12/10 03:00:45
At one point I was thinking that each Service migh
|
+ 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 |