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