Index: mojo/public/cpp/bindings/associated_interface_ptr.h |
diff --git a/mojo/public/cpp/bindings/associated_interface_ptr.h b/mojo/public/cpp/bindings/associated_interface_ptr.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..9ae61280b9c28740db1029a638eb43d673e95e3e |
--- /dev/null |
+++ b/mojo/public/cpp/bindings/associated_interface_ptr.h |
@@ -0,0 +1,191 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_PTR_H_ |
+#define MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_PTR_H_ |
+ |
+#include <algorithm> |
+ |
+#include "base/macros.h" |
+#include "mojo/public/cpp/bindings/associated_group.h" |
+#include "mojo/public/cpp/bindings/associated_interface_ptr_info.h" |
+#include "mojo/public/cpp/bindings/associated_interface_request.h" |
+#include "mojo/public/cpp/bindings/callback.h" |
+#include "mojo/public/cpp/bindings/lib/associated_interface_ptr_internal.h" |
+ |
+namespace mojo { |
+ |
+// Represents the client side of an associated interface. It is similar to |
+// InterfacePtr, except that it doesn't own a message pipe handle. |
+template <typename Interface> |
+class AssociatedInterfacePtr { |
+ MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(AssociatedInterfacePtr) |
+ |
+ public: |
+ // Constructs an unbound AssociatedInterfacePtr. |
+ AssociatedInterfacePtr() {} |
+ AssociatedInterfacePtr(decltype(nullptr)) {} |
+ |
+ AssociatedInterfacePtr(AssociatedInterfacePtr&& other) { |
+ internal_state_.Swap(&other.internal_state_); |
+ } |
+ |
+ AssociatedInterfacePtr& operator=(AssociatedInterfacePtr&& other) { |
+ reset(); |
+ internal_state_.Swap(&other.internal_state_); |
+ return *this; |
+ } |
+ |
+ // Assigning nullptr to this class causes it to closes the associated |
+ // interface (if any) and returns the pointer to the unbound state. |
+ AssociatedInterfacePtr& operator=(decltype(nullptr)) { |
+ reset(); |
+ return *this; |
+ } |
+ |
+ ~AssociatedInterfacePtr() {} |
+ |
+ // Sets up this object as the client side of an associated interface. |
+ // Calling with an invalid |info| has the same effect as reset(). In this |
+ // case, the AssociatedInterfacePtr is not considered as bound. |
+ // |
+ // NOTE: Please see the comments of |
+ // AssociatedGroup.CreateAssociatedInterface() about when you can use this |
+ // object to make calls. |
+ void Bind(AssociatedInterfacePtrInfo<Interface> info) { |
+ reset(); |
+ |
+ bool is_local = |
+ internal::AssociatedInterfacePtrInfoHelper::GetHandle(&info).is_local(); |
+ |
+ DCHECK(is_local) << "The AssociatedInterfacePtrInfo is supposed to be used " |
+ "at the other side of the message pipe."; |
+ |
+ if (info.is_valid() && is_local) |
+ internal_state_.Bind(info.Pass()); |
+ } |
+ |
+ bool is_bound() const { return internal_state_.is_bound(); } |
+ |
+ Interface* get() const { return internal_state_.instance(); } |
+ |
+ // Functions like a pointer to Interface. Must already be bound. |
+ Interface* operator->() const { return get(); } |
+ Interface& operator*() const { return *get(); } |
+ |
+ // Returns the version number of the interface that the remote side supports. |
+ uint32_t version() const { return internal_state_.version(); } |
+ |
+ // Queries the max version that the remote side supports. On completion, the |
+ // result will be returned as the input of |callback|. The version number of |
+ // this object will also be updated. |
+ void QueryVersion(const Callback<void(uint32_t)>& callback) { |
+ internal_state_.QueryVersion(callback); |
+ } |
+ |
+ // If the remote side doesn't support the specified version, it will close the |
+ // associated interface asynchronously. This does nothing if it's already |
+ // known that the remote side supports the specified version, i.e., if |
+ // |version <= this->version()|. |
+ // |
+ // After calling RequireVersion() with a version not supported by the remote |
+ // side, all subsequent calls to interface methods will be ignored. |
+ void RequireVersion(uint32_t version) { |
+ internal_state_.RequireVersion(version); |
+ } |
+ |
+ // Closes the associated interface (if any) and returns the pointer to the |
+ // unbound state. |
+ void reset() { |
+ State doomed; |
+ internal_state_.Swap(&doomed); |
+ } |
+ |
+ // Indicates whether an error has been encountered. If true, method calls made |
+ // on this interface will be dropped (and may already have been dropped). |
+ bool encountered_error() const { return internal_state_.encountered_error(); } |
+ |
+ // Registers a handler to receive error notifications. |
+ // |
+ // This method may only be called after the AssociatedInterfacePtr has been |
+ // bound. |
+ void set_connection_error_handler(const Closure& error_handler) { |
+ internal_state_.set_connection_error_handler(error_handler); |
+ } |
+ |
+ // Unbinds and returns the associated interface pointer information which |
+ // could be used to setup an AssociatedInterfacePtr again. This method may be |
+ // used to move the proxy to a different thread. |
+ // |
+ // It is an error to call PassInterface() while there are pending responses. |
+ // TODO: fix this restriction, it's not always obvious when there is a |
+ // pending response. |
+ AssociatedInterfacePtrInfo<Interface> PassInterface() { |
+ DCHECK(!internal_state_.has_pending_callbacks()); |
+ State state; |
+ internal_state_.Swap(&state); |
+ |
+ return state.PassInterface(); |
+ } |
+ |
+ // Returns the associated group that this object belongs to. Returns null if |
+ // the object is not bound. |
+ AssociatedGroup* associated_group() { |
+ return internal_state_->associated_group(); |
+ } |
+ |
+ // DO NOT USE. Exposed only for internal use and for testing. |
+ internal::AssociatedInterfacePtrState<Interface>* internal_state() { |
+ return &internal_state_; |
+ } |
+ |
+ // Allow AssociatedInterfacePtr<> to be used in boolean expressions, but not |
+ // implicitly convertible to a real bool (which is dangerous). |
+ private: |
+ typedef internal::AssociatedInterfacePtrState<Interface> |
+ AssociatedInterfacePtr::*Testable; |
+ |
+ public: |
+ operator Testable() const { |
+ return internal_state_.is_bound() ? &AssociatedInterfacePtr::internal_state_ |
+ : nullptr; |
+ } |
+ |
+ private: |
+ // Forbid the == and != operators explicitly, otherwise AssociatedInterfacePtr |
+ // will be converted to Testable to do == or != comparison. |
+ template <typename T> |
+ bool operator==(const AssociatedInterfacePtr<T>& other) const = delete; |
+ template <typename T> |
+ bool operator!=(const AssociatedInterfacePtr<T>& other) const = delete; |
+ |
+ typedef internal::AssociatedInterfacePtrState<Interface> State; |
+ mutable State internal_state_; |
+}; |
+ |
+// Creates an associated interface. The output |ptr| should be used locally |
+// while the returned request should be passed through the message pipe endpoint |
+// referred to by |associated_group| to setup the corresponding asssociated |
+// interface implementation at the remote side. |
+// |
+// NOTE: |ptr| should NOT be used to make calls before the request is sent. |
+// Violating that will cause the message pipe to be closed. On the other hand, |
+// as soon as the request is sent, |ptr| is usable. There is no need to wait |
+// until the request is bound to an implementation at the remote side. |
+template <typename Interface> |
+AssociatedInterfaceRequest<Interface> GetProxy( |
+ AssociatedInterfacePtr<Interface>* ptr, |
+ AssociatedGroup* group) { |
+ AssociatedInterfaceRequest<Interface> request; |
+ AssociatedInterfacePtrInfo<Interface> ptr_info; |
+ group->CreateAssociatedInterface(AssociatedGroup::WILL_PASS_REQUEST, |
+ &ptr_info, &request); |
+ |
+ ptr->Bind(ptr_info.Pass()); |
+ return request.Pass(); |
+} |
+ |
+} // namespace mojo |
+ |
+#endif // MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_PTR_H_ |