Index: chrome_frame/scoped_ns_ptr_win.h |
=================================================================== |
--- chrome_frame/scoped_ns_ptr_win.h (revision 0) |
+++ chrome_frame/scoped_ns_ptr_win.h (revision 0) |
@@ -0,0 +1,149 @@ |
+// Copyright (c) 2009 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 CHROME_FRAME_SCOPED_NS_PTR_WIN_H_ |
+#define CHROME_FRAME_SCOPED_NS_PTR_WIN_H_ |
+ |
+#include "base/logging.h" |
+#include "base/ref_counted.h" |
+ |
+#include "third_party/xulrunner-sdk/win/include/xpcom/nsISupports.h" |
+ |
+ |
+// Utility template to prevent users of ScopedNsPtr from calling AddRef and/or |
+// Release() without going through the ScopedNsPtr class. |
+template <class nsInterface> |
+class BlocknsISupportsMethods : public nsInterface { |
+ private: |
+ NS_IMETHOD QueryInterface(REFNSIID iid, void** object) = 0; |
+ NS_IMETHOD_(nsrefcnt) AddRef() = 0; |
+ NS_IMETHOD_(nsrefcnt) Release() = 0; |
+}; |
+ |
+// A smart pointer class for nsISupports. |
+// Based on ScopedComPtr. |
+// We have our own class instead of nsCOMPtr. nsCOMPtr has parts of its |
+// implementation in the xpcomglue lib which we can't use since that lib |
+// is built with incompatible build flags to ours. |
+template <class nsInterface, |
+ const nsIID* interface_id = |
+ reinterpret_cast<const nsIID*>(&__uuidof(nsInterface))> |
+class ScopedNsPtr : public scoped_refptr<nsInterface> { |
+ public: |
+ typedef scoped_refptr<nsInterface> ParentClass; |
+ |
+ ScopedNsPtr() { |
+ } |
+ |
+ explicit ScopedNsPtr(nsInterface* p) : ParentClass(p) { |
+ } |
+ |
+ explicit ScopedNsPtr(const ScopedNsPtr<nsInterface, interface_id>& p) |
+ : ParentClass(p) { |
+ } |
+ |
+ ~ScopedNsPtr() { |
+ // We don't want the smart pointer class to be bigger than the pointer |
+ // it wraps. |
+ COMPILE_ASSERT(sizeof(ScopedNsPtr<nsInterface, interface_id>) == |
+ sizeof(nsInterface*), ScopedNsPtrSize); |
+ } |
+ |
+ // Explicit Release() of the held object. Useful for reuse of the |
+ // ScopedNsPtr instance. |
+ // Note that this function equates to nsISupports::Release and should not |
+ // be confused with e.g. scoped_ptr::release(). |
+ void Release() { |
+ if (ptr_ != NULL) { |
+ ptr_->Release(); |
+ ptr_ = NULL; |
+ } |
+ } |
+ |
+ // Sets the internal pointer to NULL and returns the held object without |
+ // releasing the reference. |
+ nsInterface* Detach() { |
+ nsInterface* p = ptr_; |
+ ptr_ = NULL; |
+ return p; |
+ } |
+ |
+ // Accepts an interface pointer that has already been addref-ed. |
+ void Attach(nsInterface* p) { |
+ DCHECK(ptr_ == NULL); |
+ ptr_ = p; |
+ } |
+ |
+ // Retrieves the pointer address. |
+ // Used to receive object pointers as out arguments (and take ownership). |
+ // The function DCHECKs on the current value being NULL. |
+ // Usage: Foo(p.Receive()); |
+ nsInterface** Receive() { |
+ DCHECK(ptr_ == NULL) << "Object leak. Pointer must be NULL"; |
+ return &ptr_; |
+ } |
+ |
+ template <class Query> |
+ nsresult QueryInterface(Query** p) { |
+ DCHECK(p != NULL); |
+ DCHECK(ptr_ != NULL); |
+ return ptr_->QueryInterface(Query::GetIID(), reinterpret_cast<void**>(p)); |
+ } |
+ |
+ template <class Query> |
+ nsresult QueryInterface(const nsIID& iid, Query** p) { |
+ DCHECK(p != NULL); |
+ DCHECK(ptr_ != NULL); |
+ return ptr_->QueryInterface(iid, reinterpret_cast<void**>(p)); |
+ } |
+ |
+ // Queries |other| for the interface this object wraps and returns the |
+ // error code from the other->QueryInterface operation. |
+ nsresult QueryFrom(nsISupports* other) { |
+ DCHECK(other != NULL); |
+ return other->QueryInterface(iid(), reinterpret_cast<void**>(Receive())); |
+ } |
+ |
+ // Checks if the identity of |other| and this object is the same. |
+ bool IsSameObject(nsISupports* other) { |
+ if (!other && !ptr_) |
+ return true; |
+ |
+ if (!other || !ptr_) |
+ return false; |
+ |
+ nsIID iid = NS_ISUPPORTS_IID; |
+ ScopedNsPtr<nsISupports, iid> my_identity; |
+ QueryInterface(my_identity.Receive()); |
+ |
+ ScopedNsPtr<nsISupports, iid> other_identity; |
+ other->QueryInterface(other_identity.Receive()); |
+ |
+ return static_cast<nsISupports*>(my_identity) == |
+ static_cast<nsISupports*>(other_identity); |
+ } |
+ |
+ // Provides direct access to the interface. |
+ // Here we use a well known trick to make sure we block access to |
+ // IUknown methods so that something bad like this doesn't happen: |
+ // ScopedNsPtr<nsISupports> p(Foo()); |
+ // p->Release(); |
+ // ... later the destructor runs, which will Release() again. |
+ // and to get the benefit of the DCHECKs we add to QueryInterface. |
+ // There's still a way to call these methods if you absolutely must |
+ // by statically casting the ScopedNsPtr instance to the wrapped interface |
+ // and then making the call... but generally that shouldn't be necessary. |
+ BlocknsISupportsMethods<nsInterface>* operator->() const { |
+ DCHECK(ptr_ != NULL); |
+ return reinterpret_cast<BlocknsISupportsMethods<nsInterface>*>(ptr_); |
+ } |
+ |
+ // static methods |
+ |
+ static const nsIID& iid() { |
+ return *interface_id; |
+ } |
+}; |
+ |
+#endif // CHROME_FRAME_SCOPED_NS_PTR_WIN_H_ |