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 "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
6
7 #include <map>
8
9 #include "base/no_destructor.h"
10 #include "mojo/public/cpp/bindings/associated_receiver.h"
11
12 namespace blink {
13
14 class AssociatedInterfaceProvider::LocalProvider
15 : public mojom::AssociatedInterfaceProvider {
16 public:
17 using Binder =
18 base::RepeatingCallback<void(mojo::ScopedInterfaceEndpointHandle)>;
19
LocalProvider(scoped_refptr<base::SingleThreadTaskRunner> task_runner)20 explicit LocalProvider(
21 scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
22 associated_interface_provider_receiver_.Bind(
23 remote_.BindNewEndpointAndPassDedicatedReceiver(),
24 std::move(task_runner));
25 }
26
~LocalProvider()27 ~LocalProvider() override {}
28
SetBinderForName(const std::string & name,const Binder & binder)29 void SetBinderForName(const std::string& name, const Binder& binder) {
30 binders_[name] = binder;
31 }
32
HasInterface(const std::string & name) const33 bool HasInterface(const std::string& name) const {
34 return binders_.find(name) != binders_.end();
35 }
36
GetInterface(const std::string & name,mojo::ScopedInterfaceEndpointHandle handle)37 void GetInterface(const std::string& name,
38 mojo::ScopedInterfaceEndpointHandle handle) {
39 return remote_->GetAssociatedInterface(
40 name, mojo::PendingAssociatedReceiver<mojom::AssociatedInterface>(
41 std::move(handle)));
42 }
43
44 private:
45 // mojom::AssociatedInterfaceProvider:
GetAssociatedInterface(const std::string & name,mojo::PendingAssociatedReceiver<mojom::AssociatedInterface> receiver)46 void GetAssociatedInterface(
47 const std::string& name,
48 mojo::PendingAssociatedReceiver<mojom::AssociatedInterface> receiver)
49 override {
50 auto it = binders_.find(name);
51 if (it != binders_.end())
52 it->second.Run(receiver.PassHandle());
53 }
54
55 std::map<std::string, Binder> binders_;
56 mojo::AssociatedReceiver<mojom::AssociatedInterfaceProvider>
57 associated_interface_provider_receiver_{this};
58 mojo::AssociatedRemote<mojom::AssociatedInterfaceProvider> remote_;
59
60 DISALLOW_COPY_AND_ASSIGN(LocalProvider);
61 };
62
AssociatedInterfaceProvider(mojo::PendingAssociatedRemote<mojom::AssociatedInterfaceProvider> proxy,scoped_refptr<base::SingleThreadTaskRunner> task_runner)63 AssociatedInterfaceProvider::AssociatedInterfaceProvider(
64 mojo::PendingAssociatedRemote<mojom::AssociatedInterfaceProvider> proxy,
65 scoped_refptr<base::SingleThreadTaskRunner> task_runner)
66 : proxy_(std::move(proxy), task_runner),
67 task_runner_(std::move(task_runner)) {
68 DCHECK(proxy_.is_bound());
69 }
70
AssociatedInterfaceProvider(scoped_refptr<base::SingleThreadTaskRunner> task_runner)71 AssociatedInterfaceProvider::AssociatedInterfaceProvider(
72 scoped_refptr<base::SingleThreadTaskRunner> task_runner)
73 : local_provider_(std::make_unique<LocalProvider>(task_runner)),
74 task_runner_(std::move(task_runner)) {}
75
76 AssociatedInterfaceProvider::~AssociatedInterfaceProvider() = default;
77
GetInterface(const std::string & name,mojo::ScopedInterfaceEndpointHandle handle)78 void AssociatedInterfaceProvider::GetInterface(
79 const std::string& name,
80 mojo::ScopedInterfaceEndpointHandle handle) {
81 if (local_provider_ && (local_provider_->HasInterface(name) || !proxy_)) {
82 local_provider_->GetInterface(name, std::move(handle));
83 return;
84 }
85 DCHECK(proxy_);
86 proxy_->GetAssociatedInterface(
87 name, mojo::PendingAssociatedReceiver<mojom::AssociatedInterface>(
88 std::move(handle)));
89 }
90
OverrideBinderForTesting(const std::string & name,const base::RepeatingCallback<void (mojo::ScopedInterfaceEndpointHandle)> & binder)91 void AssociatedInterfaceProvider::OverrideBinderForTesting(
92 const std::string& name,
93 const base::RepeatingCallback<void(mojo::ScopedInterfaceEndpointHandle)>&
94 binder) {
95 if (!local_provider_)
96 local_provider_ = std::make_unique<LocalProvider>(task_runner_);
97 local_provider_->SetBinderForName(name, binder);
98 }
99
100 AssociatedInterfaceProvider*
GetEmptyAssociatedInterfaceProvider()101 AssociatedInterfaceProvider::GetEmptyAssociatedInterfaceProvider() {
102 static base::NoDestructor<AssociatedInterfaceProvider>
103 associated_interface_provider(base::ThreadTaskRunnerHandle::Get());
104 return associated_interface_provider.get();
105 }
106
107 } // namespace blink
108