• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 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_LIB_ASSOCIATED_INTERFACE_PTR_STATE_H_
6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_ASSOCIATED_INTERFACE_PTR_STATE_H_
7 
8 #include <stdint.h>
9 
10 #include <algorithm>  // For |std::swap()|.
11 #include <memory>
12 #include <utility>
13 
14 #include "base/bind.h"
15 #include "base/callback_forward.h"
16 #include "base/macros.h"
17 #include "base/memory/ptr_util.h"
18 #include "base/memory/ref_counted.h"
19 #include "base/single_thread_task_runner.h"
20 #include "mojo/public/cpp/bindings/associated_group.h"
21 #include "mojo/public/cpp/bindings/associated_group_controller.h"
22 #include "mojo/public/cpp/bindings/associated_interface_ptr_info.h"
23 #include "mojo/public/cpp/bindings/interface_endpoint_client.h"
24 #include "mojo/public/cpp/bindings/interface_id.h"
25 #include "mojo/public/cpp/bindings/lib/control_message_proxy.h"
26 #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
27 #include "mojo/public/cpp/system/message_pipe.h"
28 
29 namespace mojo {
30 namespace internal {
31 
32 template <typename Interface>
33 class AssociatedInterfacePtrState {
34  public:
AssociatedInterfacePtrState()35   AssociatedInterfacePtrState() : version_(0u) {}
36 
~AssociatedInterfacePtrState()37   ~AssociatedInterfacePtrState() {
38     endpoint_client_.reset();
39     proxy_.reset();
40   }
41 
instance()42   Interface* instance() {
43     // This will be null if the object is not bound.
44     return proxy_.get();
45   }
46 
version()47   uint32_t version() const { return version_; }
48 
interface_id()49   uint32_t interface_id() const {
50     DCHECK(is_bound());
51     return endpoint_client_->interface_id();
52   }
53 
QueryVersion(const base::Callback<void (uint32_t)> & callback)54   void QueryVersion(const base::Callback<void(uint32_t)>& callback) {
55     // Do a static cast in case the interface contains methods with the same
56     // name. It is safe to capture |this| because the callback won't be run
57     // after this object goes away.
58     static_cast<ControlMessageProxy*>(proxy_.get())
59         ->QueryVersion(base::Bind(&AssociatedInterfacePtrState::OnQueryVersion,
60                                   base::Unretained(this), callback));
61   }
62 
RequireVersion(uint32_t version)63   void RequireVersion(uint32_t version) {
64     if (version <= version_)
65       return;
66 
67     version_ = version;
68     // Do a static cast in case the interface contains methods with the same
69     // name.
70     static_cast<ControlMessageProxy*>(proxy_.get())->RequireVersion(version);
71   }
72 
Swap(AssociatedInterfacePtrState * other)73   void Swap(AssociatedInterfacePtrState* other) {
74     using std::swap;
75     swap(other->endpoint_client_, endpoint_client_);
76     swap(other->proxy_, proxy_);
77     swap(other->version_, version_);
78   }
79 
Bind(AssociatedInterfacePtrInfo<Interface> info,scoped_refptr<base::SingleThreadTaskRunner> runner)80   void Bind(AssociatedInterfacePtrInfo<Interface> info,
81             scoped_refptr<base::SingleThreadTaskRunner> runner) {
82     DCHECK(!endpoint_client_);
83     DCHECK(!proxy_);
84     DCHECK_EQ(0u, version_);
85     DCHECK(info.is_valid());
86 
87     version_ = info.version();
88     endpoint_client_.reset(new InterfaceEndpointClient(
89         info.PassHandle(), nullptr,
90         base::WrapUnique(new typename Interface::ResponseValidator_()), false,
91         std::move(runner)));
92     proxy_.reset(new Proxy(endpoint_client_.get()));
93     proxy_->serialization_context()->group_controller =
94         endpoint_client_->group_controller();
95   }
96 
97   // After this method is called, the object is in an invalid state and
98   // shouldn't be reused.
PassInterface()99   AssociatedInterfacePtrInfo<Interface> PassInterface() {
100     ScopedInterfaceEndpointHandle handle = endpoint_client_->PassHandle();
101     endpoint_client_.reset();
102     proxy_.reset();
103     return AssociatedInterfacePtrInfo<Interface>(std::move(handle), version_);
104   }
105 
is_bound()106   bool is_bound() const { return !!endpoint_client_; }
107 
encountered_error()108   bool encountered_error() const {
109     return endpoint_client_ ? endpoint_client_->encountered_error() : false;
110   }
111 
set_connection_error_handler(const base::Closure & error_handler)112   void set_connection_error_handler(const base::Closure& error_handler) {
113     DCHECK(endpoint_client_);
114     endpoint_client_->set_connection_error_handler(error_handler);
115   }
116 
117   // Returns true if bound and awaiting a response to a message.
has_pending_callbacks()118   bool has_pending_callbacks() const {
119     return endpoint_client_ && endpoint_client_->has_pending_responders();
120   }
121 
associated_group()122   AssociatedGroup* associated_group() {
123     return endpoint_client_ ? endpoint_client_->associated_group() : nullptr;
124   }
125 
126  private:
127   using Proxy = typename Interface::Proxy_;
128 
OnQueryVersion(const base::Callback<void (uint32_t)> & callback,uint32_t version)129   void OnQueryVersion(const base::Callback<void(uint32_t)>& callback,
130                       uint32_t version) {
131     version_ = version;
132     callback.Run(version);
133   }
134 
135   std::unique_ptr<InterfaceEndpointClient> endpoint_client_;
136   std::unique_ptr<Proxy> proxy_;
137 
138   uint32_t version_;
139 
140   DISALLOW_COPY_AND_ASSIGN(AssociatedInterfacePtrState);
141 };
142 
143 }  // namespace internal
144 }  // namespace mojo
145 
146 #endif  // MOJO_PUBLIC_CPP_BINDINGS_LIB_ASSOCIATED_INTERFACE_PTR_STATE_H_
147