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 "services/service_manager/service_manager.h" | 5 #include "services/service_manager/service_manager.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 state_ = State::STARTING; | 158 state_ = State::STARTING; |
159 service_ = std::move(service); | 159 service_ = std::move(service); |
160 service_.set_connection_error_handler( | 160 service_.set_connection_error_handler( |
161 base::Bind(&Instance::OnServiceLost, base::Unretained(this), | 161 base::Bind(&Instance::OnServiceLost, base::Unretained(this), |
162 service_manager_->GetWeakPtr())); | 162 service_manager_->GetWeakPtr())); |
163 service_->OnStart(ServiceInfo(identity_, interface_provider_specs_), | 163 service_->OnStart(ServiceInfo(identity_, interface_provider_specs_), |
164 base::Bind(&Instance::OnStartComplete, | 164 base::Bind(&Instance::OnStartComplete, |
165 base::Unretained(this))); | 165 base::Unretained(this))); |
166 } | 166 } |
167 | 167 |
168 void StartWithClientProcessConnection( | |
169 mojom::ClientProcessConnectionPtr client_process_connection) { | |
170 mojom::ServicePtr service; | |
171 service.Bind(mojom::ServicePtrInfo( | |
172 std::move(client_process_connection->service), 0)); | |
173 pid_receiver_binding_.Bind( | |
174 std::move(client_process_connection->pid_receiver_request)); | |
175 StartWithService(std::move(service)); | |
176 } | |
177 | |
178 bool StartWithFilePath(const base::FilePath& path) { | 168 bool StartWithFilePath(const base::FilePath& path) { |
179 DCHECK(!service_); | 169 DCHECK(!service_); |
180 DCHECK(!path.empty()); | 170 DCHECK(!path.empty()); |
181 runner_ = service_manager_->service_process_launcher_factory_->Create(path); | 171 runner_ = service_manager_->service_process_launcher_factory_->Create(path); |
182 if (!runner_) | 172 if (!runner_) |
183 return false; | 173 return false; |
184 bool start_sandboxed = false; | 174 bool start_sandboxed = false; |
185 mojom::ServicePtr service = runner_->Start( | 175 mojom::ServicePtr service = runner_->Start( |
186 identity_, start_sandboxed, | 176 identity_, start_sandboxed, |
187 base::Bind(&Instance::PIDAvailable, weak_factory_.GetWeakPtr())); | 177 base::Bind(&Instance::PIDAvailable, weak_factory_.GetWeakPtr())); |
188 StartWithService(std::move(service)); | 178 StartWithService(std::move(service)); |
189 return true; | 179 return true; |
190 } | 180 } |
191 | 181 |
| 182 void BindPIDReceiver(mojom::PIDReceiverRequest request) { |
| 183 pid_receiver_binding_.Bind(std::move(request)); |
| 184 } |
| 185 |
192 mojom::RunningServiceInfoPtr CreateRunningServiceInfo() const { | 186 mojom::RunningServiceInfoPtr CreateRunningServiceInfo() const { |
193 mojom::RunningServiceInfoPtr info(mojom::RunningServiceInfo::New()); | 187 mojom::RunningServiceInfoPtr info(mojom::RunningServiceInfo::New()); |
194 info->id = id_; | 188 info->id = id_; |
195 info->identity = identity_; | 189 info->identity = identity_; |
196 info->pid = pid_; | 190 info->pid = pid_; |
197 return info; | 191 return info; |
198 } | 192 } |
199 | 193 |
200 const InterfaceProviderSpec& GetConnectionSpec() const { | 194 const InterfaceProviderSpec& GetConnectionSpec() const { |
201 auto it = interface_provider_specs_.find( | 195 auto it = interface_provider_specs_.find( |
(...skipping 25 matching lines...) Expand all Loading... |
227 | 221 |
228 // The service was started but the service manager hasn't received the | 222 // The service was started but the service manager hasn't received the |
229 // initial response from it yet. | 223 // initial response from it yet. |
230 STARTING, | 224 STARTING, |
231 | 225 |
232 // The service was started successfully. | 226 // The service was started successfully. |
233 STARTED | 227 STARTED |
234 }; | 228 }; |
235 | 229 |
236 // mojom::Connector implementation: | 230 // mojom::Connector implementation: |
237 void Connect(const service_manager::Identity& in_target, | 231 void Start( |
| 232 const Identity& target, |
| 233 mojo::ScopedMessagePipeHandle service_handle, |
| 234 mojom::PIDReceiverRequest pid_receiver_request) override { |
| 235 mojom::ServicePtr service; |
| 236 service.Bind(mojom::ServicePtrInfo(std::move(service_handle), 0)); |
| 237 ConnectImpl( |
| 238 target, |
| 239 mojom::InterfaceProviderRequest(), |
| 240 std::move(service), |
| 241 std::move(pid_receiver_request), |
| 242 base::Bind( |
| 243 &service_manager::ServiceManager::Instance::EmptyConnectCallback, |
| 244 weak_factory_.GetWeakPtr())); |
| 245 } |
| 246 |
| 247 void Connect(const service_manager::Identity& target, |
238 mojom::InterfaceProviderRequest remote_interfaces, | 248 mojom::InterfaceProviderRequest remote_interfaces, |
239 mojom::ClientProcessConnectionPtr client_process_connection, | |
240 const ConnectCallback& callback) override { | 249 const ConnectCallback& callback) override { |
| 250 ConnectImpl(target, std::move(remote_interfaces), mojom::ServicePtr(), |
| 251 mojom::PIDReceiverRequest(), callback); |
| 252 } |
| 253 |
| 254 void ConnectImpl(const service_manager::Identity& in_target, |
| 255 mojom::InterfaceProviderRequest remote_interfaces, |
| 256 mojom::ServicePtr service, |
| 257 mojom::PIDReceiverRequest pid_receiver_request, |
| 258 const ConnectCallback& callback) { |
241 Identity target = in_target; | 259 Identity target = in_target; |
242 if (target.user_id() == mojom::kInheritUserID) | 260 if (target.user_id() == mojom::kInheritUserID) |
243 target.set_user_id(identity_.user_id()); | 261 target.set_user_id(identity_.user_id()); |
244 | 262 |
245 if (!ValidateIdentity(target, callback)) | 263 if (!ValidateIdentity(target, callback)) |
246 return; | 264 return; |
247 if (!ValidateClientProcessConnection(&client_process_connection, target, | 265 if (!ValidateClientProcessInfo(&service, &pid_receiver_request, target, |
248 callback)) { | 266 callback)) { |
249 return; | 267 return; |
250 } | 268 } |
251 if (!ValidateConnectionSpec(target, callback)) | 269 if (!ValidateConnectionSpec(target, callback)) |
252 return; | 270 return; |
253 | 271 |
254 std::unique_ptr<ConnectParams> params(new ConnectParams); | 272 std::unique_ptr<ConnectParams> params(new ConnectParams); |
255 params->set_source(identity_); | 273 params->set_source(identity_); |
256 params->set_target(target); | 274 params->set_target(target); |
257 params->set_remote_interfaces(std::move(remote_interfaces)); | 275 params->set_remote_interfaces(std::move(remote_interfaces)); |
258 params->set_client_process_connection(std::move(client_process_connection)); | 276 params->set_client_process_info(std::move(service), |
| 277 std::move(pid_receiver_request)); |
259 params->set_connect_callback(callback); | 278 params->set_connect_callback(callback); |
260 service_manager_->Connect( | 279 service_manager_->Connect( |
261 std::move(params), nullptr, weak_factory_.GetWeakPtr()); | 280 std::move(params), nullptr, weak_factory_.GetWeakPtr()); |
262 } | 281 } |
263 | 282 |
264 void Clone(mojom::ConnectorRequest request) override { | 283 void Clone(mojom::ConnectorRequest request) override { |
265 connectors_.AddBinding(this, std::move(request)); | 284 connectors_.AddBinding(this, std::move(request)); |
266 } | 285 } |
267 | 286 |
268 // mojom::PIDReceiver: | 287 // mojom::PIDReceiver: |
(...skipping 24 matching lines...) Expand all Loading... |
293 } | 312 } |
294 if (!base::IsValidGUID(identity.user_id())) { | 313 if (!base::IsValidGUID(identity.user_id())) { |
295 LOG(ERROR) << "Error: invalid user_id: " << identity.user_id(); | 314 LOG(ERROR) << "Error: invalid user_id: " << identity.user_id(); |
296 callback.Run(mojom::ConnectResult::INVALID_ARGUMENT, | 315 callback.Run(mojom::ConnectResult::INVALID_ARGUMENT, |
297 mojom::kInheritUserID); | 316 mojom::kInheritUserID); |
298 return false; | 317 return false; |
299 } | 318 } |
300 return true; | 319 return true; |
301 } | 320 } |
302 | 321 |
303 bool ValidateClientProcessConnection( | 322 bool ValidateClientProcessInfo( |
304 mojom::ClientProcessConnectionPtr* client_process_connection, | 323 mojom::ServicePtr* service, |
| 324 mojom::PIDReceiverRequest* pid_receiver_request, |
305 const Identity& target, | 325 const Identity& target, |
306 const ConnectCallback& callback) { | 326 const ConnectCallback& callback) { |
307 if (!client_process_connection->is_null()) { | 327 if (service->is_bound() || pid_receiver_request->is_pending()) { |
308 if (!HasCapability(GetConnectionSpec(), kCapability_ClientProcess)) { | 328 if (!HasCapability(GetConnectionSpec(), kCapability_ClientProcess)) { |
309 LOG(ERROR) << "Instance: " << identity_.name() << " attempting " | 329 LOG(ERROR) << "Instance: " << identity_.name() << " attempting " |
310 << "to register an instance for a process it created for " | 330 << "to register an instance for a process it created for " |
311 << "target: " << target.name() << " without the " | 331 << "target: " << target.name() << " without the " |
312 << "service_manager{client_process} capability " | 332 << "service_manager{client_process} capability " |
313 << "class."; | 333 << "class."; |
314 callback.Run(mojom::ConnectResult::ACCESS_DENIED, | 334 callback.Run(mojom::ConnectResult::ACCESS_DENIED, |
315 mojom::kInheritUserID); | 335 mojom::kInheritUserID); |
316 return false; | 336 return false; |
317 } | 337 } |
318 | 338 |
319 if (!(*client_process_connection)->service.is_valid() || | 339 if (!service->is_bound() || !pid_receiver_request->is_pending()) { |
320 !(*client_process_connection)->pid_receiver_request.is_valid()) { | |
321 LOG(ERROR) << "Must supply both service AND " | 340 LOG(ERROR) << "Must supply both service AND " |
322 << "pid_receiver_request when sending " | 341 << "pid_receiver_request when sending client process info"; |
323 << "client_process_connection."; | |
324 callback.Run(mojom::ConnectResult::INVALID_ARGUMENT, | 342 callback.Run(mojom::ConnectResult::INVALID_ARGUMENT, |
325 mojom::kInheritUserID); | 343 mojom::kInheritUserID); |
326 return false; | 344 return false; |
327 } | 345 } |
328 if (service_manager_->GetExistingInstance(target)) { | 346 if (service_manager_->GetExistingInstance(target)) { |
329 LOG(ERROR) << "Cannot client process matching existing identity:" | 347 LOG(ERROR) << "Cannot client process matching existing identity:" |
330 << "Name: " << target.name() << " User: " | 348 << "Name: " << target.name() << " User: " |
331 << target.user_id() << " Instance: " << target.instance(); | 349 << target.user_id() << " Instance: " << target.instance(); |
332 callback.Run(mojom::ConnectResult::INVALID_ARGUMENT, | 350 callback.Run(mojom::ConnectResult::INVALID_ARGUMENT, |
333 mojom::kInheritUserID); | 351 mojom::kInheritUserID); |
334 return false; | 352 return false; |
335 } | 353 } |
336 } | 354 } |
337 return true; | 355 return true; |
338 } | 356 } |
339 | 357 |
340 bool ValidateConnectionSpec(const Identity& target, | 358 bool ValidateConnectionSpec(const Identity& target, |
341 const ConnectCallback& callback) { | 359 const ConnectCallback& callback) { |
342 InterfaceProviderSpec connection_spec = GetConnectionSpec(); | 360 InterfaceProviderSpec connection_spec = GetConnectionSpec(); |
343 // TODO(beng): Need to do the following additional policy validation of | 361 // TODO(beng): Need to do the following additional policy validation of |
344 // whether this instance is allowed to connect using: | 362 // whether this instance is allowed to connect using: |
345 // - a non-null client_process_connection. | 363 // - non-null client process info. |
346 if (target.user_id() != identity_.user_id() && | 364 if (target.user_id() != identity_.user_id() && |
347 target.user_id() != mojom::kRootUserID && | 365 target.user_id() != mojom::kRootUserID && |
348 !HasCapability(connection_spec, kCapability_UserID)) { | 366 !HasCapability(connection_spec, kCapability_UserID)) { |
349 LOG(ERROR) << "Instance: " << identity_.name() | 367 LOG(ERROR) << "Instance: " << identity_.name() |
350 << " running as: " << identity_.user_id() | 368 << " running as: " << identity_.user_id() |
351 << " attempting to connect to: " << target.name() | 369 << " attempting to connect to: " << target.name() |
352 << " as: " << target.user_id() << " without " | 370 << " as: " << target.user_id() << " without " |
353 << " the service:service_manager{user_id} capability."; | 371 << " the service:service_manager{user_id} capability."; |
354 callback.Run(mojom::ConnectResult::ACCESS_DENIED, | 372 callback.Run(mojom::ConnectResult::ACCESS_DENIED, |
355 mojom::kInheritUserID); | 373 mojom::kInheritUserID); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
425 service_manager_->NotifyServiceStarted(identity_, pid_); | 443 service_manager_->NotifyServiceStarted(identity_, pid_); |
426 } | 444 } |
427 | 445 |
428 // mojom::ServiceControl: | 446 // mojom::ServiceControl: |
429 void RequestQuit() override { | 447 void RequestQuit() override { |
430 // If quit is requested, oblige when there are no pending OnConnects. | 448 // If quit is requested, oblige when there are no pending OnConnects. |
431 if (!pending_service_connections_) | 449 if (!pending_service_connections_) |
432 OnServiceLost(service_manager_->GetWeakPtr()); | 450 OnServiceLost(service_manager_->GetWeakPtr()); |
433 } | 451 } |
434 | 452 |
| 453 void EmptyConnectCallback(mojom::ConnectResult result, |
| 454 const std::string& user_id) {} |
| 455 |
435 service_manager::ServiceManager* const service_manager_; | 456 service_manager::ServiceManager* const service_manager_; |
436 | 457 |
437 // An id that identifies this instance. Distinct from pid, as a single process | 458 // An id that identifies this instance. Distinct from pid, as a single process |
438 // may vend multiple application instances, and this object may exist before a | 459 // may vend multiple application instances, and this object may exist before a |
439 // process is launched. | 460 // process is launched. |
440 const uint32_t id_; | 461 const uint32_t id_; |
441 Identity identity_; | 462 Identity identity_; |
442 const InterfaceProviderSpecMap interface_provider_specs_; | 463 const InterfaceProviderSpecMap interface_provider_specs_; |
443 const InterfaceProviderSpec empty_spec_; | 464 const InterfaceProviderSpec empty_spec_; |
444 const bool allow_any_application_; | 465 const bool allow_any_application_; |
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
865 // the lifetime of the service that started them, instead they are owned by | 886 // the lifetime of the service that started them, instead they are owned by |
866 // the Service Manager. | 887 // the Service Manager. |
867 Identity source_identity_for_creation; | 888 Identity source_identity_for_creation; |
868 if (HasCapability(connection_spec, kCapability_AllUsers)) { | 889 if (HasCapability(connection_spec, kCapability_AllUsers)) { |
869 singletons_.insert(target.name()); | 890 singletons_.insert(target.name()); |
870 source_identity_for_creation = CreateServiceManagerIdentity(); | 891 source_identity_for_creation = CreateServiceManagerIdentity(); |
871 } else { | 892 } else { |
872 source_identity_for_creation = params->source(); | 893 source_identity_for_creation = params->source(); |
873 } | 894 } |
874 | 895 |
875 mojom::ClientProcessConnectionPtr client_process_connection = | |
876 params->TakeClientProcessConnection(); | |
877 Instance* instance = CreateInstance(source_identity_for_creation, | 896 Instance* instance = CreateInstance(source_identity_for_creation, |
878 target, result->interface_provider_specs); | 897 target, result->interface_provider_specs); |
879 | 898 |
880 // Below are various paths through which a new Instance can be bound to a | 899 // Below are various paths through which a new Instance can be bound to a |
881 // Service proxy. | 900 // Service proxy. |
882 if (service.is_bound()) { | 901 if (service.is_bound()) { |
883 // If a ServicePtr was provided, there's no more work to do: someone | 902 // If a ServicePtr was provided, there's no more work to do: someone |
884 // is already holding a corresponding ServiceRequest. | 903 // is already holding a corresponding ServiceRequest. |
885 instance->StartWithService(std::move(service)); | 904 instance->StartWithService(std::move(service)); |
886 } else if (!client_process_connection.is_null()) { | 905 } else if (params->HasClientProcessInfo()) { |
887 // Likewise if a ClientProcessConnection was given via Connect(), it | 906 // This branch should be reachable only via a call to RegisterService(). We |
888 // provides the Service proxy to use. | 907 // start the instance but return early before we connect to it. Clients will |
889 instance->StartWithClientProcessConnection( | 908 // call Connect() with the target identity subsequently. |
890 std::move(client_process_connection)); | 909 instance->BindPIDReceiver(params->TakePIDReceiverRequest()); |
| 910 instance->StartWithService(params->TakeService()); |
| 911 return; |
891 } else { | 912 } else { |
892 // Otherwise we create a new Service pipe. | 913 // Otherwise we create a new Service pipe. |
893 mojom::ServiceRequest request(&service); | 914 mojom::ServiceRequest request(&service); |
894 CHECK(!result->package_path.empty()); | 915 CHECK(!result->package_path.empty()); |
895 | 916 |
896 // The catalog was unable to read a manifest for this service. We can't do | 917 // The catalog was unable to read a manifest for this service. We can't do |
897 // anything more. | 918 // anything more. |
898 // TODO(beng): There may be some cases where it's valid to have an empty | 919 // TODO(beng): There may be some cases where it's valid to have an empty |
899 // spec, so we should probably include a return value in |result|. | 920 // spec, so we should probably include a return value in |result|. |
900 if (result->interface_provider_specs.empty()) { | 921 if (result->interface_provider_specs.empty()) { |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
951 // Now that the instance has a Service, we can connect to it. | 972 // Now that the instance has a Service, we can connect to it. |
952 bool connected = instance->ConnectToService(¶ms); | 973 bool connected = instance->ConnectToService(¶ms); |
953 DCHECK(connected); | 974 DCHECK(connected); |
954 } | 975 } |
955 | 976 |
956 base::WeakPtr<ServiceManager> ServiceManager::GetWeakPtr() { | 977 base::WeakPtr<ServiceManager> ServiceManager::GetWeakPtr() { |
957 return weak_ptr_factory_.GetWeakPtr(); | 978 return weak_ptr_factory_.GetWeakPtr(); |
958 } | 979 } |
959 | 980 |
960 } // namespace service_manager | 981 } // namespace service_manager |
OLD | NEW |