• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 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 #ifndef MOJO_PUBLIC_CPP_BINDINGS_STRONG_ASSOCIATED_BINDING_H_
6 #define MOJO_PUBLIC_CPP_BINDINGS_STRONG_ASSOCIATED_BINDING_H_
7 
8 #include <memory>
9 #include <string>
10 #include <utility>
11 
12 #include "base/bind.h"
13 #include "base/callback.h"
14 #include "base/logging.h"
15 #include "base/macros.h"
16 #include "base/memory/weak_ptr.h"
17 #include "mojo/public/cpp/bindings/associated_binding.h"
18 #include "mojo/public/cpp/bindings/associated_interface_request.h"
19 #include "mojo/public/cpp/bindings/connection_error_callback.h"
20 #include "mojo/public/cpp/system/core.h"
21 
22 namespace mojo {
23 
24 template <typename Interface>
25 class StrongAssociatedBinding;
26 
27 template <typename Interface>
28 using StrongAssociatedBindingPtr =
29     base::WeakPtr<StrongAssociatedBinding<Interface>>;
30 
31 // This connects an interface implementation strongly to an associated pipe.
32 // When a connection error is detected the implementation is deleted. If the
33 // task runner that a StrongAssociatedBinding is bound on is stopped, the
34 // connection error handler will not be invoked and the implementation will not
35 // be deleted.
36 //
37 // To use, call StrongAssociatedBinding<T>::Create() (see below) or the helper
38 // MakeStrongAssociatedBinding function:
39 //
40 //   mojo::MakeStrongAssociatedBinding(std::make_unique<FooImpl>(),
41 //                                     std::move(foo_request));
42 //
43 template <typename Interface>
44 class StrongAssociatedBinding {
45  public:
46   using ImplPointerType =
47       typename AssociatedBinding<Interface>::ImplPointerType;
48 
49   // Create a new StrongAssociatedBinding instance. The instance owns itself,
50   // cleaning up only in the event of a pipe connection error. Returns a WeakPtr
51   // to the new StrongAssociatedBinding instance.
Create(std::unique_ptr<Interface> impl,AssociatedInterfaceRequest<Interface> request)52   static StrongAssociatedBindingPtr<Interface> Create(
53       std::unique_ptr<Interface> impl,
54       AssociatedInterfaceRequest<Interface> request) {
55     StrongAssociatedBinding* binding =
56         new StrongAssociatedBinding(std::move(impl), std::move(request));
57     return binding->weak_factory_.GetWeakPtr();
58   }
59 
60   // Note: The error handler must not delete the interface implementation.
61   //
62   // This method may only be called after this StrongAssociatedBinding has been
63   // bound to a message pipe.
set_connection_error_handler(base::OnceClosure error_handler)64   void set_connection_error_handler(base::OnceClosure error_handler) {
65     DCHECK(binding_.is_bound());
66     connection_error_handler_ = std::move(error_handler);
67     connection_error_with_reason_handler_.Reset();
68   }
69 
set_connection_error_with_reason_handler(ConnectionErrorWithReasonCallback error_handler)70   void set_connection_error_with_reason_handler(
71       ConnectionErrorWithReasonCallback error_handler) {
72     DCHECK(binding_.is_bound());
73     connection_error_with_reason_handler_ = std::move(error_handler);
74     connection_error_handler_.Reset();
75   }
76 
77   // Forces the binding to close. This destroys the StrongBinding instance.
Close()78   void Close() { delete this; }
79 
impl()80   Interface* impl() { return impl_.get(); }
81 
82   // Sends a message on the underlying message pipe and runs the current
83   // message loop until its response is received. This can be used in tests to
84   // verify that no message was sent on a message pipe in response to some
85   // stimulus.
FlushForTesting()86   void FlushForTesting() { binding_.FlushForTesting(); }
87 
88   // Allows test code to swap the interface implementation.
SwapImplForTesting(ImplPointerType new_impl)89   ImplPointerType SwapImplForTesting(ImplPointerType new_impl) {
90     return binding_.SwapImplForTesting(new_impl);
91   }
92 
93  private:
StrongAssociatedBinding(std::unique_ptr<Interface> impl,AssociatedInterfaceRequest<Interface> request)94   StrongAssociatedBinding(std::unique_ptr<Interface> impl,
95                           AssociatedInterfaceRequest<Interface> request)
96       : impl_(std::move(impl)),
97         binding_(impl_.get(), std::move(request)),
98         weak_factory_(this) {
99     binding_.set_connection_error_with_reason_handler(base::Bind(
100         &StrongAssociatedBinding::OnConnectionError, base::Unretained(this)));
101   }
102 
~StrongAssociatedBinding()103   ~StrongAssociatedBinding() {}
104 
OnConnectionError(uint32_t custom_reason,const std::string & description)105   void OnConnectionError(uint32_t custom_reason,
106                          const std::string& description) {
107     if (connection_error_handler_) {
108       std::move(connection_error_handler_).Run();
109     } else if (connection_error_with_reason_handler_) {
110       std::move(connection_error_with_reason_handler_)
111           .Run(custom_reason, description);
112     }
113     Close();
114   }
115 
116   std::unique_ptr<Interface> impl_;
117   base::OnceClosure connection_error_handler_;
118   ConnectionErrorWithReasonCallback connection_error_with_reason_handler_;
119   AssociatedBinding<Interface> binding_;
120   base::WeakPtrFactory<StrongAssociatedBinding> weak_factory_;
121 
122   DISALLOW_COPY_AND_ASSIGN(StrongAssociatedBinding);
123 };
124 
125 template <typename Interface, typename Impl>
MakeStrongAssociatedBinding(std::unique_ptr<Impl> impl,AssociatedInterfaceRequest<Interface> request)126 StrongAssociatedBindingPtr<Interface> MakeStrongAssociatedBinding(
127     std::unique_ptr<Impl> impl,
128     AssociatedInterfaceRequest<Interface> request) {
129   return StrongAssociatedBinding<Interface>::Create(std::move(impl),
130                                                     std::move(request));
131 }
132 
133 }  // namespace mojo
134 
135 #endif  // MOJO_PUBLIC_CPP_BINDINGS_STRONG_ASSOCIATED_BINDING_H_
136