1 // Copyright 2014 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_BINDING_H_
6 #define MOJO_PUBLIC_CPP_BINDINGS_STRONG_BINDING_H_
7 
8 #include <utility>
9 
10 #include "base/bind.h"
11 #include "base/callback.h"
12 #include "base/logging.h"
13 #include "base/macros.h"
14 #include "mojo/public/cpp/bindings/binding.h"
15 #include "mojo/public/cpp/bindings/interface_ptr.h"
16 #include "mojo/public/cpp/bindings/interface_request.h"
17 #include "mojo/public/cpp/bindings/lib/filter_chain.h"
18 #include "mojo/public/cpp/bindings/lib/router.h"
19 #include "mojo/public/cpp/bindings/message_header_validator.h"
20 #include "mojo/public/cpp/system/core.h"
21 
22 namespace mojo {
23 
24 // This connects an interface implementation strongly to a pipe. When a
25 // connection error is detected the implementation is deleted. Deleting the
26 // connector also closes the pipe.
27 //
28 // Example of an implementation that is always bound strongly to a pipe
29 //
30 //   class StronglyBound : public Foo {
31 //    public:
32 //     explicit StronglyBound(InterfaceRequest<Foo> request)
33 //         : binding_(this, std::move(request)) {}
34 //
35 //     // Foo implementation here
36 //
37 //    private:
38 //     StrongBinding<Foo> binding_;
39 //   };
40 //
41 //   class MyFooFactory : public InterfaceFactory<Foo> {
42 //    public:
43 //     void Create(..., InterfaceRequest<Foo> request) override {
44 //       new StronglyBound(std::move(request));  // The binding now owns the
45 //                                               // instance of StronglyBound.
46 //     }
47 //   };
48 //
49 // This class is thread hostile once it is bound to a message pipe. Until it is
50 // bound, it may be bound or destroyed on any thread.
51 template <typename Interface>
52 class StrongBinding {
53  public:
StrongBinding(Interface * impl)54   explicit StrongBinding(Interface* impl) : binding_(impl) {}
55 
StrongBinding(Interface * impl,ScopedMessagePipeHandle handle)56   StrongBinding(Interface* impl, ScopedMessagePipeHandle handle)
57       : StrongBinding(impl) {
58     Bind(std::move(handle));
59   }
60 
StrongBinding(Interface * impl,InterfacePtr<Interface> * ptr)61   StrongBinding(Interface* impl, InterfacePtr<Interface>* ptr)
62       : StrongBinding(impl) {
63     Bind(ptr);
64   }
65 
StrongBinding(Interface * impl,InterfaceRequest<Interface> request)66   StrongBinding(Interface* impl, InterfaceRequest<Interface> request)
67       : StrongBinding(impl) {
68     Bind(std::move(request));
69   }
70 
~StrongBinding()71   ~StrongBinding() {}
72 
Bind(ScopedMessagePipeHandle handle)73   void Bind(ScopedMessagePipeHandle handle) {
74     DCHECK(!binding_.is_bound());
75     binding_.Bind(std::move(handle));
76     binding_.set_connection_error_handler(
77         base::Bind(&StrongBinding::OnConnectionError, base::Unretained(this)));
78   }
79 
Bind(InterfacePtr<Interface> * ptr)80   void Bind(InterfacePtr<Interface>* ptr) {
81     DCHECK(!binding_.is_bound());
82     binding_.Bind(ptr);
83     binding_.set_connection_error_handler(
84         base::Bind(&StrongBinding::OnConnectionError, base::Unretained(this)));
85   }
86 
Bind(InterfaceRequest<Interface> request)87   void Bind(InterfaceRequest<Interface> request) {
88     DCHECK(!binding_.is_bound());
89     binding_.Bind(std::move(request));
90     binding_.set_connection_error_handler(
91         base::Bind(&StrongBinding::OnConnectionError, base::Unretained(this)));
92   }
93 
WaitForIncomingMethodCall()94   bool WaitForIncomingMethodCall() {
95     return binding_.WaitForIncomingMethodCall();
96   }
97 
98   // Note: The error handler must not delete the interface implementation.
99   //
100   // This method may only be called after this StrongBinding has been bound to a
101   // message pipe.
set_connection_error_handler(const base::Closure & error_handler)102   void set_connection_error_handler(const base::Closure& error_handler) {
103     DCHECK(binding_.is_bound());
104     connection_error_handler_ = error_handler;
105   }
106 
impl()107   Interface* impl() { return binding_.impl(); }
108   // Exposed for testing, should not generally be used.
internal_router()109   internal::Router* internal_router() { return binding_.internal_router(); }
110 
OnConnectionError()111   void OnConnectionError() {
112     if (!connection_error_handler_.is_null())
113       connection_error_handler_.Run();
114     delete binding_.impl();
115   }
116 
117  private:
118   base::Closure connection_error_handler_;
119   Binding<Interface> binding_;
120 
121   DISALLOW_COPY_AND_ASSIGN(StrongBinding);
122 };
123 
124 }  // namespace mojo
125 
126 #endif  // MOJO_PUBLIC_CPP_BINDINGS_STRONG_BINDING_H_
127