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