Home | History | Annotate | Download | only in bindings
      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 <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/binding.h"
     18 #include "mojo/public/cpp/bindings/connection_error_callback.h"
     19 #include "mojo/public/cpp/bindings/filter_chain.h"
     20 #include "mojo/public/cpp/bindings/interface_ptr.h"
     21 #include "mojo/public/cpp/bindings/interface_request.h"
     22 #include "mojo/public/cpp/bindings/message_header_validator.h"
     23 #include "mojo/public/cpp/system/core.h"
     24 
     25 namespace mojo {
     26 
     27 template <typename Interface>
     28 class StrongBinding;
     29 
     30 template <typename Interface>
     31 using StrongBindingPtr = base::WeakPtr<StrongBinding<Interface>>;
     32 
     33 // This connects an interface implementation strongly to a pipe. When a
     34 // connection error is detected the implementation is deleted. If the task
     35 // runner that a StrongBinding is bound on is stopped, the connection error
     36 // handler will not be invoked and the implementation will not be deleted.
     37 //
     38 // To use, call StrongBinding<T>::Create() (see below) or the helper
     39 // MakeStrongBinding function:
     40 //
     41 //   mojo::MakeStrongBinding(base::MakeUnique<FooImpl>(),
     42 //                           std::move(foo_request));
     43 //
     44 template <typename Interface>
     45 class StrongBinding {
     46  public:
     47   // Create a new StrongBinding instance. The instance owns itself, cleaning up
     48   // only in the event of a pipe connection error. Returns a WeakPtr to the new
     49   // StrongBinding instance.
     50   static StrongBindingPtr<Interface> Create(
     51       std::unique_ptr<Interface> impl,
     52       InterfaceRequest<Interface> request) {
     53     StrongBinding* binding =
     54         new StrongBinding(std::move(impl), std::move(request));
     55     return binding->weak_factory_.GetWeakPtr();
     56   }
     57 
     58   // Note: The error handler must not delete the interface implementation.
     59   //
     60   // This method may only be called after this StrongBinding has been bound to a
     61   // message pipe.
     62   void set_connection_error_handler(const base::Closure& error_handler) {
     63     DCHECK(binding_.is_bound());
     64     connection_error_handler_ = error_handler;
     65     connection_error_with_reason_handler_.Reset();
     66   }
     67 
     68   void set_connection_error_with_reason_handler(
     69       const ConnectionErrorWithReasonCallback& error_handler) {
     70     DCHECK(binding_.is_bound());
     71     connection_error_with_reason_handler_ = error_handler;
     72     connection_error_handler_.Reset();
     73   }
     74 
     75   // Forces the binding to close. This destroys the StrongBinding instance.
     76   void Close() { delete this; }
     77 
     78   Interface* impl() { return impl_.get(); }
     79 
     80   // Sends a message on the underlying message pipe and runs the current
     81   // message loop until its response is received. This can be used in tests to
     82   // verify that no message was sent on a message pipe in response to some
     83   // stimulus.
     84   void FlushForTesting() { binding_.FlushForTesting(); }
     85 
     86  private:
     87   StrongBinding(std::unique_ptr<Interface> impl,
     88                 InterfaceRequest<Interface> request)
     89       : impl_(std::move(impl)),
     90         binding_(impl_.get(), std::move(request)),
     91         weak_factory_(this) {
     92     binding_.set_connection_error_with_reason_handler(
     93         base::Bind(&StrongBinding::OnConnectionError, base::Unretained(this)));
     94   }
     95 
     96   ~StrongBinding() {}
     97 
     98   void OnConnectionError(uint32_t custom_reason,
     99                          const std::string& description) {
    100     if (!connection_error_handler_.is_null())
    101       connection_error_handler_.Run();
    102     else if (!connection_error_with_reason_handler_.is_null())
    103       connection_error_with_reason_handler_.Run(custom_reason, description);
    104     Close();
    105   }
    106 
    107   std::unique_ptr<Interface> impl_;
    108   base::Closure connection_error_handler_;
    109   ConnectionErrorWithReasonCallback connection_error_with_reason_handler_;
    110   Binding<Interface> binding_;
    111   base::WeakPtrFactory<StrongBinding> weak_factory_;
    112 
    113   DISALLOW_COPY_AND_ASSIGN(StrongBinding);
    114 };
    115 
    116 template <typename Interface, typename Impl>
    117 StrongBindingPtr<Interface> MakeStrongBinding(
    118     std::unique_ptr<Impl> impl,
    119     InterfaceRequest<Interface> request) {
    120   return StrongBinding<Interface>::Create(std::move(impl), std::move(request));
    121 }
    122 
    123 }  // namespace mojo
    124 
    125 #endif  // MOJO_PUBLIC_CPP_BINDINGS_STRONG_BINDING_H_
    126