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