1 // Copyright 2017 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/test/test_connector_factory.h"
6
7 #include <vector>
8
9 #include "base/bind.h"
10 #include "base/callback_helpers.h"
11 #include "base/guid.h"
12 #include "base/macros.h"
13 #include "mojo/public/cpp/bindings/pending_associated_receiver.h"
14 #include "mojo/public/cpp/bindings/pending_receiver.h"
15 #include "mojo/public/cpp/bindings/pending_remote.h"
16 #include "mojo/public/cpp/bindings/receiver_set.h"
17 #include "services/service_manager/public/cpp/service.h"
18 #include "services/service_manager/public/mojom/connector.mojom.h"
19 #include "services/service_manager/public/mojom/service.mojom.h"
20
21 namespace service_manager {
22
23 namespace {
24
25 class ProxiedServiceConnector : public mojom::Connector {
26 public:
ProxiedServiceConnector(TestConnectorFactory * factory,TestConnectorFactory::NameToServiceProxyMap * proxies,const base::Token & test_instance_group)27 ProxiedServiceConnector(
28 TestConnectorFactory* factory,
29 TestConnectorFactory::NameToServiceProxyMap* proxies,
30 const base::Token& test_instance_group)
31 : fake_guid_(base::Token::CreateRandom()),
32 factory_(factory),
33 proxies_(proxies),
34 test_instance_group_(test_instance_group) {}
35
36 ~ProxiedServiceConnector() override = default;
37
38 private:
GetServiceProxy(const std::string & service_name)39 mojom::Service* GetServiceProxy(const std::string& service_name) {
40 auto proxy_it = proxies_->find(service_name);
41 if (proxy_it != proxies_->end())
42 return proxy_it->second.get();
43
44 return nullptr;
45 }
46
47 // mojom::Connector:
BindInterface(const ServiceFilter & service_filter,const std::string & interface_name,mojo::ScopedMessagePipeHandle interface_pipe,mojom::BindInterfacePriority priority,BindInterfaceCallback callback)48 void BindInterface(const ServiceFilter& service_filter,
49 const std::string& interface_name,
50 mojo::ScopedMessagePipeHandle interface_pipe,
51 mojom::BindInterfacePriority priority,
52 BindInterfaceCallback callback) override {
53 auto* proxy = GetServiceProxy(service_filter.service_name());
54 if (!proxy && factory_->ignore_unknown_service_requests()) {
55 std::move(callback).Run(mojom::ConnectResult::ACCESS_DENIED,
56 base::nullopt);
57 return;
58 }
59
60 CHECK(proxy)
61 << "TestConnectorFactory received a BindInterface request for an "
62 << "unregistered service '" << service_filter.service_name() << "'";
63 proxy->OnBindInterface(
64 BindSourceInfo(Identity("TestConnectorFactory", test_instance_group_,
65 base::Token{}, fake_guid_),
66 CapabilitySet()),
67 interface_name, std::move(interface_pipe), base::DoNothing());
68 std::move(callback).Run(mojom::ConnectResult::SUCCEEDED, base::nullopt);
69 }
70
WarmService(const ServiceFilter & filter,WarmServiceCallback callback)71 void WarmService(const ServiceFilter& filter,
72 WarmServiceCallback callback) override {
73 NOTREACHED();
74 }
75
QueryService(const std::string & service_name,QueryServiceCallback callback)76 void QueryService(const std::string& service_name,
77 QueryServiceCallback callback) override {
78 NOTREACHED();
79 }
80
RegisterServiceInstance(const Identity & identity,mojo::ScopedMessagePipeHandle service,mojo::PendingReceiver<mojom::ProcessMetadata> metadata_receiver,RegisterServiceInstanceCallback callback)81 void RegisterServiceInstance(
82 const Identity& identity,
83 mojo::ScopedMessagePipeHandle service,
84 mojo::PendingReceiver<mojom::ProcessMetadata> metadata_receiver,
85 RegisterServiceInstanceCallback callback) override {
86 NOTREACHED();
87 }
88
Clone(mojo::PendingReceiver<mojom::Connector> receiver)89 void Clone(mojo::PendingReceiver<mojom::Connector> receiver) override {
90 receivers_.Add(this, std::move(receiver));
91 }
92
93 const base::Token fake_guid_;
94 TestConnectorFactory* const factory_;
95 TestConnectorFactory::NameToServiceProxyMap* const proxies_;
96 const base::Token test_instance_group_;
97 mojo::ReceiverSet<mojom::Connector> receivers_;
98
99 DISALLOW_COPY_AND_ASSIGN(ProxiedServiceConnector);
100 };
101
102 } // namespace
103
TestConnectorFactory()104 TestConnectorFactory::TestConnectorFactory() {
105 test_instance_group_ = base::Token::CreateRandom();
106 impl_ = std::make_unique<ProxiedServiceConnector>(this, &service_proxies_,
107 test_instance_group_);
108 }
109
110 TestConnectorFactory::~TestConnectorFactory() = default;
111
GetDefaultConnector()112 Connector* TestConnectorFactory::GetDefaultConnector() {
113 if (!default_connector_)
114 default_connector_ = CreateConnector();
115 return default_connector_.get();
116 }
117
CreateConnector()118 std::unique_ptr<Connector> TestConnectorFactory::CreateConnector() {
119 mojo::PendingRemote<mojom::Connector> proxy;
120 impl_->Clone(proxy.InitWithNewPipeAndPassReceiver());
121 return std::make_unique<Connector>(std::move(proxy));
122 }
123
RegisterInstance(const std::string & service_name)124 mojo::PendingReceiver<mojom::Service> TestConnectorFactory::RegisterInstance(
125 const std::string& service_name) {
126 mojo::Remote<mojom::Service> proxy_remote;
127 mojo::PendingReceiver<mojom::Service> receiver =
128 proxy_remote.BindNewPipeAndPassReceiver();
129 proxy_remote->OnStart(
130 Identity(service_name, test_instance_group_, base::Token{},
131 base::Token::CreateRandom()),
132 base::BindOnce(&TestConnectorFactory::OnStartResponseHandler,
133 base::Unretained(this), service_name));
134 service_proxies_[service_name] = std::move(proxy_remote);
135 return receiver;
136 }
137
OnStartResponseHandler(const std::string & service_name,mojo::PendingReceiver<mojom::Connector> connector_receiver,mojo::PendingAssociatedReceiver<mojom::ServiceControl> control_receiver)138 void TestConnectorFactory::OnStartResponseHandler(
139 const std::string& service_name,
140 mojo::PendingReceiver<mojom::Connector> connector_receiver,
141 mojo::PendingAssociatedReceiver<mojom::ServiceControl> control_receiver) {
142 impl_->Clone(std::move(connector_receiver));
143 service_control_receivers_.Add(this, std::move(control_receiver),
144 service_name);
145 }
146
RequestQuit()147 void TestConnectorFactory::RequestQuit() {
148 if (ignore_quit_requests_)
149 return;
150
151 service_proxies_.erase(service_control_receivers_.current_context());
152 service_control_receivers_.Remove(
153 service_control_receivers_.current_receiver());
154 }
155
156 } // namespace service_manager
157