1 // Copyright 2018 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 "services/service_manager/public/cpp/service_receiver.h"
6 
7 #include <utility>
8 
9 #include "base/bind.h"
10 #include "base/no_destructor.h"
11 #include "base/synchronization/lock.h"
12 #include "mojo/public/cpp/bindings/remote.h"
13 #include "services/service_manager/public/cpp/service.h"
14 
15 namespace service_manager {
16 
ServiceReceiver(service_manager::Service * service)17 ServiceReceiver::ServiceReceiver(service_manager::Service* service)
18     : service_(service) {
19   DCHECK(service_);
20 }
21 
ServiceReceiver(service_manager::Service * service,mojo::PendingReceiver<mojom::Service> receiver)22 ServiceReceiver::ServiceReceiver(service_manager::Service* service,
23                                  mojo::PendingReceiver<mojom::Service> receiver)
24     : ServiceReceiver(service) {
25   if (receiver.is_valid())
26     Bind(std::move(receiver));
27 }
28 
29 ServiceReceiver::~ServiceReceiver() = default;
30 
GetConnector()31 Connector* ServiceReceiver::GetConnector() {
32   if (!connector_)
33     connector_ = Connector::Create(&pending_connector_receiver_);
34   return connector_.get();
35 }
36 
Bind(mojo::PendingReceiver<mojom::Service> receiver)37 void ServiceReceiver::Bind(mojo::PendingReceiver<mojom::Service> receiver) {
38   DCHECK(!is_bound());
39   receiver_.Bind(std::move(receiver));
40   receiver_.set_disconnect_handler(base::BindOnce(
41       &ServiceReceiver::OnConnectionError, base::Unretained(this)));
42 }
43 
RequestClose()44 void ServiceReceiver::RequestClose() {
45   // We allow for innoccuous RequestClose() calls on unbound ServiceReceivers.
46   // This may occur e.g. when running a service in-process.
47   if (!is_bound())
48     return;
49 
50   if (service_control_.is_bound()) {
51     service_control_->RequestQuit();
52   } else {
53     // It's possible that the service may request closure before receiving the
54     // initial |OnStart()| event, in which case there is not yet a control
55     // interface on which to request closure. In that case we defer until
56     // |OnStart()| is received.
57     request_closure_on_start_ = true;
58   }
59 }
60 
Close()61 void ServiceReceiver::Close() {
62   DCHECK(is_bound());
63   receiver_.reset();
64   service_control_.reset();
65   connector_.reset();
66 }
67 
OnConnectionError()68 void ServiceReceiver::OnConnectionError() {
69   service_->OnDisconnected();
70 }
71 
OnStart(const Identity & identity,OnStartCallback callback)72 void ServiceReceiver::OnStart(const Identity& identity,
73                               OnStartCallback callback) {
74   identity_ = identity;
75 
76   if (!pending_connector_receiver_.is_valid())
77     connector_ = Connector::Create(&pending_connector_receiver_);
78   std::move(callback).Run(std::move(pending_connector_receiver_),
79                           service_control_.BindNewEndpointAndPassReceiver());
80 
81   service_->OnStart();
82 
83   // Execute any prior |RequestClose()| request on the service's behalf.
84   if (request_closure_on_start_)
85     service_control_->RequestQuit();
86 }
87 
OnBindInterface(const BindSourceInfo & source_info,const std::string & interface_name,mojo::ScopedMessagePipeHandle interface_pipe,OnBindInterfaceCallback callback)88 void ServiceReceiver::OnBindInterface(
89     const BindSourceInfo& source_info,
90     const std::string& interface_name,
91     mojo::ScopedMessagePipeHandle interface_pipe,
92     OnBindInterfaceCallback callback) {
93   // Acknowledge this request.
94   std::move(callback).Run();
95 
96   service_->OnConnect(source_info, interface_name, std::move(interface_pipe));
97 }
98 
CreatePackagedServiceInstance(const Identity & identity,mojo::PendingReceiver<mojom::Service> receiver,mojo::PendingRemote<mojom::ProcessMetadata> metadata)99 void ServiceReceiver::CreatePackagedServiceInstance(
100     const Identity& identity,
101     mojo::PendingReceiver<mojom::Service> receiver,
102     mojo::PendingRemote<mojom::ProcessMetadata> metadata) {
103   service_->CreatePackagedServiceInstance(
104       identity.name(), std::move(receiver),
105       base::BindOnce(
106           [](mojo::PendingRemote<mojom::ProcessMetadata> pending_metadata,
107              base::Optional<base::ProcessId> pid) {
108             if (pid) {
109               mojo::Remote<mojom::ProcessMetadata> metadata(
110                   std::move(pending_metadata));
111               metadata->SetPID(*pid);
112             }
113           },
114           std::move(metadata)));
115 }
116 
117 }  // namespace service_manager
118