| 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_
|
|
|