| 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 |