OLD | NEW |
---|---|
(Empty) | |
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/service_manager.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/callback_helpers.h" | |
9 #include "base/command_line.h" | |
10 #include "base/file_util.h" | |
11 #include "base/scoped_native_library.h" | |
12 #include "base/threading/simple_thread.h" | |
13 #include "mojo/public/bindings/lib/remote_ptr.h" | |
14 #include "mojo/shell/context.h" | |
15 #include "mojo/shell/switches.h" | |
16 #include "mojom/shell.h" | |
17 | |
18 typedef MojoResult (*MojoMainFunction)(MojoHandle pipe); | |
19 | |
20 namespace mojo { | |
21 namespace shell { | |
22 | |
23 class ServiceManager::Service | |
24 : public ::shell::ShellStub, | |
25 public Loader::Delegate, | |
26 public base::DelegateSimpleThread::Delegate { | |
27 public: | |
28 Service(ServiceManager* manager, const GURL& url) | |
29 : manager_(manager), | |
30 url_(url), | |
31 weak_factory_(this) { | |
32 base::AutoLock lock(lock_); | |
33 ScopedMessagePipeHandle shell_handle; | |
34 CreateMessagePipe(&shell_handle, &service_handle_); | |
35 shell_client_.reset(shell_handle.Pass()); | |
36 shell_client_.SetPeer(this); | |
37 request_ = manager_->context_->loader()->Load(url_, this); | |
38 } | |
39 | |
40 virtual ~Service() {} | |
41 | |
42 void ConnectToClient(ScopedMessagePipeHandle handle) { | |
43 if (handle.is_valid()) | |
44 shell_client_->Connect(handle.Pass()); | |
45 } | |
46 | |
47 virtual void Connect(const mojo::String& url, | |
48 ScopedMessagePipeHandle client_pipe) MOJO_OVERRIDE { | |
49 manager_->Connect(GURL(url.To<std::string>()), client_pipe.Pass()); | |
50 } | |
51 | |
52 private: | |
53 // From Loader::Delegate. | |
54 virtual void DidCompleteLoad(const GURL& app_url, | |
55 const base::FilePath& app_path) OVERRIDE { | |
56 base::AutoLock lock(lock_); | |
57 app_path_ = app_path; | |
58 ack_closure_ = | |
59 base::Bind(&Service::AppCompleted, weak_factory_.GetWeakPtr()); | |
60 thread_.reset(new base::DelegateSimpleThread(this, "app_thread")); | |
61 thread_->Start(); | |
62 } | |
63 | |
64 // From base::DelegateSimpleThread::Delegate. | |
65 virtual void Run() OVERRIDE { | |
66 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
| |
67 base::ScopedClosureRunner app_deleter( | |
68 base::Bind(base::IgnoreResult(&base::DeleteFile), app_path_, false)); | |
69 base::ScopedNativeLibrary app_library( | |
70 base::LoadNativeLibrary(app_path_, NULL)); | |
71 if (!app_library.is_valid()) { | |
72 LOG(ERROR) << "Failed to load library: " << app_path_.value().c_str(); | |
73 return; | |
74 } | |
75 | |
76 MojoMainFunction main_function = reinterpret_cast<MojoMainFunction>( | |
77 app_library.GetFunctionPointer("MojoMain")); | |
78 if (!main_function) { | |
79 LOG(ERROR) << "Entrypoint MojoMain not found."; | |
80 return; | |
81 } | |
82 | |
83 // |MojoMain()| takes ownership of the app handle. | |
84 MojoResult result = main_function(service_handle_.release().value()); | |
85 if (result < MOJO_RESULT_OK) { | |
86 LOG(ERROR) << "MojoMain returned an error: " << result; | |
87 return; | |
88 } | |
89 manager_->context_->task_runners()->ui_runner()->PostTask( | |
90 FROM_HERE, | |
91 ack_closure_); | |
92 } | |
93 | |
94 void AppCompleted() { | |
95 thread_->Join(); | |
96 thread_.reset(); | |
97 } | |
98 | |
99 base::Lock lock_; | |
100 ServiceManager* manager_; | |
101 GURL url_; | |
102 mojo::RemotePtr<::shell::ShellClient> shell_client_; | |
103 base::FilePath app_path_; | |
104 base::Closure ack_closure_; | |
105 scoped_ptr<Loader::Job> request_; | |
106 scoped_ptr<base::DelegateSimpleThread> thread_; | |
107 ScopedMessagePipeHandle service_handle_; | |
108 | |
109 base::WeakPtrFactory<Service> weak_factory_; | |
110 | |
111 DISALLOW_COPY_AND_ASSIGN(Service); | |
112 }; | |
113 | |
114 ServiceManager::ServiceManager(Context* context) : context_(context) { | |
115 } | |
116 | |
117 ServiceManager::~ServiceManager() { | |
118 } | |
119 | |
120 void ServiceManager::Connect(const GURL& url, | |
121 ScopedMessagePipeHandle client_handle) { | |
122 GURL app_url = url; | |
123 if (url.scheme() == "mojo") { | |
124 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); | |
125 std::string origin = command_line.GetSwitchValueASCII(switches::kOrigin); | |
126 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
| |
127 app_url = GURL(origin + std::string("/") + lib); | |
128 } | |
129 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
| |
130 ServiceMap::const_iterator service_it = url_to_service_.find(app_url); | |
131 Service* service; | |
132 if (service_it != url_to_service_.end()) { | |
133 service = service_it->second; | |
134 } else { | |
135 service = new Service(this, app_url); | |
136 url_to_service_[app_url] = service; | |
137 } | |
138 service->ConnectToClient(client_handle.Pass()); | |
139 } | |
140 | |
141 } // namespace shell | |
142 } // namespace mojo | |
OLD | NEW |