OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "mojo/shell/application_manager.h" | 5 #include "mojo/shell/application_manager.h" |
6 | 6 |
| 7 #include <utility> |
| 8 |
7 #include "base/bind.h" | 9 #include "base/bind.h" |
8 #include "base/command_line.h" | 10 #include "base/command_line.h" |
9 #include "base/logging.h" | 11 #include "base/logging.h" |
10 #include "base/macros.h" | 12 #include "base/macros.h" |
11 #include "base/stl_util.h" | 13 #include "base/stl_util.h" |
12 #include "base/strings/string_util.h" | 14 #include "base/strings/string_util.h" |
13 #include "base/trace_event/trace_event.h" | 15 #include "base/trace_event/trace_event.h" |
14 #include "mojo/public/cpp/bindings/binding.h" | 16 #include "mojo/public/cpp/bindings/binding.h" |
15 #include "mojo/shell/application_instance.h" | 17 #include "mojo/shell/application_instance.h" |
16 #include "mojo/shell/fetcher.h" | 18 #include "mojo/shell/fetcher.h" |
(...skipping 27 matching lines...) Expand all Loading... |
44 } | 46 } |
45 | 47 |
46 bool ApplicationManager::TestAPI::HasRunningInstanceForURL( | 48 bool ApplicationManager::TestAPI::HasRunningInstanceForURL( |
47 const GURL& url) const { | 49 const GURL& url) const { |
48 return manager_->identity_to_instance_.find(Identity(url)) != | 50 return manager_->identity_to_instance_.find(Identity(url)) != |
49 manager_->identity_to_instance_.end(); | 51 manager_->identity_to_instance_.end(); |
50 } | 52 } |
51 | 53 |
52 ApplicationManager::ApplicationManager( | 54 ApplicationManager::ApplicationManager( |
53 scoped_ptr<PackageManager> package_manager) | 55 scoped_ptr<PackageManager> package_manager) |
54 : ApplicationManager(package_manager.Pass(), nullptr, nullptr) {} | 56 : ApplicationManager(std::move(package_manager), nullptr, nullptr) {} |
55 | 57 |
56 ApplicationManager::ApplicationManager( | 58 ApplicationManager::ApplicationManager( |
57 scoped_ptr<PackageManager> package_manager, | 59 scoped_ptr<PackageManager> package_manager, |
58 scoped_ptr<NativeRunnerFactory> native_runner_factory, | 60 scoped_ptr<NativeRunnerFactory> native_runner_factory, |
59 base::TaskRunner* task_runner) | 61 base::TaskRunner* task_runner) |
60 : package_manager_(package_manager.Pass()), | 62 : package_manager_(std::move(package_manager)), |
61 task_runner_(task_runner), | 63 task_runner_(task_runner), |
62 native_runner_factory_(native_runner_factory.Pass()), | 64 native_runner_factory_(std::move(native_runner_factory)), |
63 weak_ptr_factory_(this) { | 65 weak_ptr_factory_(this) { |
64 package_manager_->SetApplicationManager(this); | 66 package_manager_->SetApplicationManager(this); |
65 SetLoaderForURL(make_scoped_ptr(new ShellApplicationLoader(this)), | 67 SetLoaderForURL(make_scoped_ptr(new ShellApplicationLoader(this)), |
66 GURL("mojo:shell")); | 68 GURL("mojo:shell")); |
67 } | 69 } |
68 | 70 |
69 ApplicationManager::~ApplicationManager() { | 71 ApplicationManager::~ApplicationManager() { |
70 TerminateShellConnections(); | 72 TerminateShellConnections(); |
71 STLDeleteValues(&url_to_loader_); | 73 STLDeleteValues(&url_to_loader_); |
72 } | 74 } |
73 | 75 |
74 void ApplicationManager::TerminateShellConnections() { | 76 void ApplicationManager::TerminateShellConnections() { |
75 STLDeleteValues(&identity_to_instance_); | 77 STLDeleteValues(&identity_to_instance_); |
76 } | 78 } |
77 | 79 |
78 void ApplicationManager::ConnectToApplication( | 80 void ApplicationManager::ConnectToApplication( |
79 scoped_ptr<ConnectToApplicationParams> params) { | 81 scoped_ptr<ConnectToApplicationParams> params) { |
80 TRACE_EVENT_INSTANT1("mojo_shell", "ApplicationManager::ConnectToApplication", | 82 TRACE_EVENT_INSTANT1("mojo_shell", "ApplicationManager::ConnectToApplication", |
81 TRACE_EVENT_SCOPE_THREAD, "original_url", | 83 TRACE_EVENT_SCOPE_THREAD, "original_url", |
82 params->target().url().spec()); | 84 params->target().url().spec()); |
83 DCHECK(params->target().url().is_valid()); | 85 DCHECK(params->target().url().is_valid()); |
84 | 86 |
85 // Connect to an existing matching instance, if possible. | 87 // Connect to an existing matching instance, if possible. |
86 if (ConnectToRunningApplication(¶ms)) | 88 if (ConnectToRunningApplication(¶ms)) |
87 return; | 89 return; |
88 | 90 |
89 ApplicationLoader* loader = GetLoaderForURL(params->target().url()); | 91 ApplicationLoader* loader = GetLoaderForURL(params->target().url()); |
90 if (loader) { | 92 if (loader) { |
91 GURL url = params->target().url(); | 93 GURL url = params->target().url(); |
92 loader->Load(url, CreateAndConnectToInstance(params.Pass(), nullptr)); | 94 loader->Load(url, CreateAndConnectToInstance(std::move(params), nullptr)); |
93 return; | 95 return; |
94 } | 96 } |
95 | 97 |
96 URLRequestPtr original_url_request = params->TakeTargetURLRequest(); | 98 URLRequestPtr original_url_request = params->TakeTargetURLRequest(); |
97 auto callback = | 99 auto callback = |
98 base::Bind(&ApplicationManager::HandleFetchCallback, | 100 base::Bind(&ApplicationManager::HandleFetchCallback, |
99 weak_ptr_factory_.GetWeakPtr(), base::Passed(¶ms)); | 101 weak_ptr_factory_.GetWeakPtr(), base::Passed(¶ms)); |
100 package_manager_->FetchRequest(original_url_request.Pass(), callback); | 102 package_manager_->FetchRequest(std::move(original_url_request), callback); |
101 } | 103 } |
102 | 104 |
103 bool ApplicationManager::ConnectToRunningApplication( | 105 bool ApplicationManager::ConnectToRunningApplication( |
104 scoped_ptr<ConnectToApplicationParams>* params) { | 106 scoped_ptr<ConnectToApplicationParams>* params) { |
105 ApplicationInstance* instance = GetApplicationInstance((*params)->target()); | 107 ApplicationInstance* instance = GetApplicationInstance((*params)->target()); |
106 if (!instance) | 108 if (!instance) |
107 return false; | 109 return false; |
108 | 110 |
109 instance->ConnectToClient(params->Pass()); | 111 instance->ConnectToClient(std::move(*params)); |
110 return true; | 112 return true; |
111 } | 113 } |
112 | 114 |
113 ApplicationInstance* ApplicationManager::GetApplicationInstance( | 115 ApplicationInstance* ApplicationManager::GetApplicationInstance( |
114 const Identity& identity) const { | 116 const Identity& identity) const { |
115 const auto& it = identity_to_instance_.find(identity); | 117 const auto& it = identity_to_instance_.find(identity); |
116 return it != identity_to_instance_.end() ? it->second : nullptr; | 118 return it != identity_to_instance_.end() ? it->second : nullptr; |
117 } | 119 } |
118 | 120 |
119 void ApplicationManager::CreateInstanceForHandle(ScopedHandle channel, | 121 void ApplicationManager::CreateInstanceForHandle(ScopedHandle channel, |
120 const GURL& url, | 122 const GURL& url, |
121 CapabilityFilterPtr filter) { | 123 CapabilityFilterPtr filter) { |
122 // Instances created by others are considered unique, and thus have no | 124 // Instances created by others are considered unique, and thus have no |
123 // identity. As such they cannot be connected to by anyone else, and so we | 125 // identity. As such they cannot be connected to by anyone else, and so we |
124 // never call ConnectToClient(). | 126 // never call ConnectToClient(). |
125 // TODO(beng): GetPermissiveCapabilityFilter() here obviously cannot make it | 127 // TODO(beng): GetPermissiveCapabilityFilter() here obviously cannot make it |
126 // to production. See note in application_manager.mojom. | 128 // to production. See note in application_manager.mojom. |
127 // http://crbug.com/555392 | 129 // http://crbug.com/555392 |
128 CapabilityFilter local_filter = filter->filter.To<CapabilityFilter>(); | 130 CapabilityFilter local_filter = filter->filter.To<CapabilityFilter>(); |
129 Identity target_id(url, std::string(), local_filter); | 131 Identity target_id(url, std::string(), local_filter); |
130 ApplicationInstance* instance = nullptr; | 132 ApplicationInstance* instance = nullptr; |
131 InterfaceRequest<Application> application_request = | 133 InterfaceRequest<Application> application_request = |
132 CreateInstance(target_id, base::Closure(), &instance); | 134 CreateInstance(target_id, base::Closure(), &instance); |
133 scoped_ptr<NativeRunner> runner = | 135 scoped_ptr<NativeRunner> runner = |
134 native_runner_factory_->Create(base::FilePath()); | 136 native_runner_factory_->Create(base::FilePath()); |
135 runner->InitHost(channel.Pass(), application_request.Pass()); | 137 runner->InitHost(std::move(channel), std::move(application_request)); |
136 instance->SetNativeRunner(runner.get()); | 138 instance->SetNativeRunner(runner.get()); |
137 native_runners_.push_back(std::move(runner)); | 139 native_runners_.push_back(std::move(runner)); |
138 } | 140 } |
139 | 141 |
140 void ApplicationManager::AddListener( | 142 void ApplicationManager::AddListener( |
141 mojom::ApplicationManagerListenerPtr listener) { | 143 mojom::ApplicationManagerListenerPtr listener) { |
142 Array<mojom::ApplicationInfoPtr> applications; | 144 Array<mojom::ApplicationInfoPtr> applications; |
143 for (auto& entry : identity_to_instance_) | 145 for (auto& entry : identity_to_instance_) |
144 applications.push_back(CreateApplicationInfoForInstance(entry.second)); | 146 applications.push_back(CreateApplicationInfoForInstance(entry.second)); |
145 listener->SetRunningApplications(std::move(applications)); | 147 listener->SetRunningApplications(std::move(applications)); |
146 | 148 |
147 listeners_.AddInterfacePtr(std::move(listener)); | 149 listeners_.AddInterfacePtr(std::move(listener)); |
148 } | 150 } |
149 | 151 |
150 InterfaceRequest<Application> ApplicationManager::CreateAndConnectToInstance( | 152 InterfaceRequest<Application> ApplicationManager::CreateAndConnectToInstance( |
151 scoped_ptr<ConnectToApplicationParams> params, | 153 scoped_ptr<ConnectToApplicationParams> params, |
152 ApplicationInstance** resulting_instance) { | 154 ApplicationInstance** resulting_instance) { |
153 ApplicationInstance* instance = nullptr; | 155 ApplicationInstance* instance = nullptr; |
154 InterfaceRequest<Application> application_request = | 156 InterfaceRequest<Application> application_request = |
155 CreateInstance(params->target(), params->on_application_end(), &instance); | 157 CreateInstance(params->target(), params->on_application_end(), &instance); |
156 instance->ConnectToClient(params.Pass()); | 158 instance->ConnectToClient(std::move(params)); |
157 if (resulting_instance) | 159 if (resulting_instance) |
158 *resulting_instance = instance; | 160 *resulting_instance = instance; |
159 return application_request.Pass(); | 161 return application_request; |
160 } | 162 } |
161 | 163 |
162 InterfaceRequest<Application> ApplicationManager::CreateInstance( | 164 InterfaceRequest<Application> ApplicationManager::CreateInstance( |
163 const Identity& target_id, | 165 const Identity& target_id, |
164 const base::Closure& on_application_end, | 166 const base::Closure& on_application_end, |
165 ApplicationInstance** resulting_instance) { | 167 ApplicationInstance** resulting_instance) { |
166 ApplicationPtr application; | 168 ApplicationPtr application; |
167 InterfaceRequest<Application> application_request = GetProxy(&application); | 169 InterfaceRequest<Application> application_request = GetProxy(&application); |
168 ApplicationInstance* instance = new ApplicationInstance( | 170 ApplicationInstance* instance = new ApplicationInstance( |
169 application.Pass(), this, target_id, Shell::kInvalidContentHandlerID, | 171 std::move(application), this, target_id, Shell::kInvalidContentHandlerID, |
170 on_application_end); | 172 on_application_end); |
171 DCHECK(identity_to_instance_.find(target_id) == | 173 DCHECK(identity_to_instance_.find(target_id) == |
172 identity_to_instance_.end()); | 174 identity_to_instance_.end()); |
173 identity_to_instance_[target_id] = instance; | 175 identity_to_instance_[target_id] = instance; |
174 mojom::ApplicationInfoPtr application_info = | 176 mojom::ApplicationInfoPtr application_info = |
175 CreateApplicationInfoForInstance(instance); | 177 CreateApplicationInfoForInstance(instance); |
176 listeners_.ForAllPtrs( | 178 listeners_.ForAllPtrs( |
177 [this, &application_info](mojom::ApplicationManagerListener* listener) { | 179 [this, &application_info](mojom::ApplicationManagerListener* listener) { |
178 listener->ApplicationStarted(application_info.Clone()); | 180 listener->ApplicationStarted(application_info.Clone()); |
179 }); | 181 }); |
180 instance->InitializeApplication(); | 182 instance->InitializeApplication(); |
181 if (resulting_instance) | 183 if (resulting_instance) |
182 *resulting_instance = instance; | 184 *resulting_instance = instance; |
183 return application_request.Pass(); | 185 return application_request; |
184 } | 186 } |
185 | 187 |
186 void ApplicationManager::HandleFetchCallback( | 188 void ApplicationManager::HandleFetchCallback( |
187 scoped_ptr<ConnectToApplicationParams> params, | 189 scoped_ptr<ConnectToApplicationParams> params, |
188 scoped_ptr<Fetcher> fetcher) { | 190 scoped_ptr<Fetcher> fetcher) { |
189 if (!fetcher) { | 191 if (!fetcher) { |
190 // Network error. Drop |params| to tell the requestor. | 192 // Network error. Drop |params| to tell the requestor. |
191 params->connect_callback().Run(Shell::kInvalidContentHandlerID); | 193 params->connect_callback().Run(Shell::kInvalidContentHandlerID); |
192 return; | 194 return; |
193 } | 195 } |
194 | 196 |
195 GURL redirect_url = fetcher->GetRedirectURL(); | 197 GURL redirect_url = fetcher->GetRedirectURL(); |
196 if (!redirect_url.is_empty()) { | 198 if (!redirect_url.is_empty()) { |
197 // And around we go again... Whee! | 199 // And around we go again... Whee! |
198 // TODO(sky): this loses the original URL info. | 200 // TODO(sky): this loses the original URL info. |
199 URLRequestPtr new_request = URLRequest::New(); | 201 URLRequestPtr new_request = URLRequest::New(); |
200 new_request->url = redirect_url.spec(); | 202 new_request->url = redirect_url.spec(); |
201 HttpHeaderPtr header = HttpHeader::New(); | 203 HttpHeaderPtr header = HttpHeader::New(); |
202 header->name = "Referer"; | 204 header->name = "Referer"; |
203 header->value = fetcher->GetRedirectReferer().spec(); | 205 header->value = fetcher->GetRedirectReferer().spec(); |
204 new_request->headers.push_back(header.Pass()); | 206 new_request->headers.push_back(std::move(header)); |
205 params->SetTargetURLRequest(new_request.Pass()); | 207 params->SetTargetURLRequest(std::move(new_request)); |
206 ConnectToApplication(params.Pass()); | 208 ConnectToApplication(std::move(params)); |
207 return; | 209 return; |
208 } | 210 } |
209 | 211 |
210 // We already checked if the application was running before we fetched it, but | 212 // We already checked if the application was running before we fetched it, but |
211 // it might have started while the fetch was outstanding. We don't want to | 213 // it might have started while the fetch was outstanding. We don't want to |
212 // have two copies of the app running, so check again. | 214 // have two copies of the app running, so check again. |
213 if (ConnectToRunningApplication(¶ms)) | 215 if (ConnectToRunningApplication(¶ms)) |
214 return; | 216 return; |
215 | 217 |
216 Identity source = params->source(); | 218 Identity source = params->source(); |
217 Identity target = params->target(); | 219 Identity target = params->target(); |
218 Shell::ConnectToApplicationCallback connect_callback = | 220 Shell::ConnectToApplicationCallback connect_callback = |
219 params->connect_callback(); | 221 params->connect_callback(); |
220 params->set_connect_callback(EmptyConnectCallback()); | 222 params->set_connect_callback(EmptyConnectCallback()); |
221 ApplicationInstance* app = nullptr; | 223 ApplicationInstance* app = nullptr; |
222 InterfaceRequest<Application> request( | 224 InterfaceRequest<Application> request( |
223 CreateAndConnectToInstance(params.Pass(), &app)); | 225 CreateAndConnectToInstance(std::move(params), &app)); |
224 | 226 |
225 uint32_t content_handler_id = package_manager_->HandleWithContentHandler( | 227 uint32_t content_handler_id = package_manager_->HandleWithContentHandler( |
226 fetcher.get(), source, target.url(), target.filter(), &request); | 228 fetcher.get(), source, target.url(), target.filter(), &request); |
227 if (content_handler_id != Shell::kInvalidContentHandlerID) { | 229 if (content_handler_id != Shell::kInvalidContentHandlerID) { |
228 app->set_requesting_content_handler_id(content_handler_id); | 230 app->set_requesting_content_handler_id(content_handler_id); |
229 connect_callback.Run(content_handler_id); | 231 connect_callback.Run(content_handler_id); |
230 return; | 232 return; |
231 } | 233 } |
232 | 234 |
233 // TODO(erg): Have a better way of switching the sandbox on. For now, switch | 235 // TODO(erg): Have a better way of switching the sandbox on. For now, switch |
234 // it on hard coded when we're using some of the sandboxable core services. | 236 // it on hard coded when we're using some of the sandboxable core services. |
235 bool start_sandboxed = false; | 237 bool start_sandboxed = false; |
236 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( | 238 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( |
237 switches::kMojoNoSandbox)) { | 239 switches::kMojoNoSandbox)) { |
238 start_sandboxed = (target.url() == GURL("mojo://core_services/") && | 240 start_sandboxed = (target.url() == GURL("mojo://core_services/") && |
239 target.qualifier() == "Core") || | 241 target.qualifier() == "Core") || |
240 target.url() == GURL("mojo://html_viewer/"); | 242 target.url() == GURL("mojo://html_viewer/"); |
241 } | 243 } |
242 | 244 |
243 connect_callback.Run(Shell::kInvalidContentHandlerID); | 245 connect_callback.Run(Shell::kInvalidContentHandlerID); |
244 | 246 |
245 fetcher->AsPath(task_runner_, | 247 fetcher->AsPath( |
246 base::Bind(&ApplicationManager::RunNativeApplication, | 248 task_runner_, |
247 weak_ptr_factory_.GetWeakPtr(), | 249 base::Bind(&ApplicationManager::RunNativeApplication, |
248 base::Passed(request.Pass()), start_sandboxed, | 250 weak_ptr_factory_.GetWeakPtr(), |
249 base::Passed(fetcher.Pass()), | 251 base::Passed(std::move(request)), start_sandboxed, |
250 base::Unretained(app))); | 252 base::Passed(std::move(fetcher)), base::Unretained(app))); |
251 } | 253 } |
252 | 254 |
253 void ApplicationManager::RunNativeApplication( | 255 void ApplicationManager::RunNativeApplication( |
254 InterfaceRequest<Application> application_request, | 256 InterfaceRequest<Application> application_request, |
255 bool start_sandboxed, | 257 bool start_sandboxed, |
256 scoped_ptr<Fetcher> fetcher, | 258 scoped_ptr<Fetcher> fetcher, |
257 ApplicationInstance* instance, | 259 ApplicationInstance* instance, |
258 const base::FilePath& path, | 260 const base::FilePath& path, |
259 bool path_exists) { | 261 bool path_exists) { |
260 // We only passed fetcher to keep it alive. Done with it now. | 262 // We only passed fetcher to keep it alive. Done with it now. |
261 fetcher.reset(); | 263 fetcher.reset(); |
262 | 264 |
263 DCHECK(application_request.is_pending()); | 265 DCHECK(application_request.is_pending()); |
264 | 266 |
265 if (!path_exists) { | 267 if (!path_exists) { |
266 LOG(ERROR) << "Library not started because library path '" << path.value() | 268 LOG(ERROR) << "Library not started because library path '" << path.value() |
267 << "' does not exist."; | 269 << "' does not exist."; |
268 return; | 270 return; |
269 } | 271 } |
270 | 272 |
271 TRACE_EVENT1("mojo_shell", "ApplicationManager::RunNativeApplication", "path", | 273 TRACE_EVENT1("mojo_shell", "ApplicationManager::RunNativeApplication", "path", |
272 path.AsUTF8Unsafe()); | 274 path.AsUTF8Unsafe()); |
273 scoped_ptr<NativeRunner> runner = native_runner_factory_->Create(path); | 275 scoped_ptr<NativeRunner> runner = native_runner_factory_->Create(path); |
274 runner->Start(path, start_sandboxed, application_request.Pass(), | 276 runner->Start(path, start_sandboxed, std::move(application_request), |
275 base::Bind(&ApplicationManager::CleanupRunner, | 277 base::Bind(&ApplicationManager::CleanupRunner, |
276 weak_ptr_factory_.GetWeakPtr(), runner.get())); | 278 weak_ptr_factory_.GetWeakPtr(), runner.get())); |
277 instance->SetNativeRunner(runner.get()); | 279 instance->SetNativeRunner(runner.get()); |
278 native_runners_.push_back(std::move(runner)); | 280 native_runners_.push_back(std::move(runner)); |
279 } | 281 } |
280 | 282 |
281 void ApplicationManager::SetLoaderForURL(scoped_ptr<ApplicationLoader> loader, | 283 void ApplicationManager::SetLoaderForURL(scoped_ptr<ApplicationLoader> loader, |
282 const GURL& url) { | 284 const GURL& url) { |
283 URLToLoaderMap::iterator it = url_to_loader_.find(url); | 285 URLToLoaderMap::iterator it = url_to_loader_.find(url); |
284 if (it != url_to_loader_.end()) | 286 if (it != url_to_loader_.end()) |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
329 } | 331 } |
330 } | 332 } |
331 } | 333 } |
332 | 334 |
333 Shell::ConnectToApplicationCallback EmptyConnectCallback() { | 335 Shell::ConnectToApplicationCallback EmptyConnectCallback() { |
334 return base::Bind(&OnEmptyOnConnectCallback); | 336 return base::Bind(&OnEmptyOnConnectCallback); |
335 } | 337 } |
336 | 338 |
337 } // namespace shell | 339 } // namespace shell |
338 } // namespace mojo | 340 } // namespace mojo |
OLD | NEW |