diff options
author | slightlyoff@chromium.org <slightlyoff@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-24 05:11:58 +0000 |
---|---|---|
committer | slightlyoff@chromium.org <slightlyoff@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-24 05:11:58 +0000 |
commit | f781782dd67077478e117c61dca4ea5eefce3544 (patch) | |
tree | 4801f724123cfdcbb69c4e7fe40a565b331723ae /chrome_frame/scoped_ns_ptr_win.h | |
parent | 63cf4759efa2373e33436fb5df6849f930081226 (diff) | |
download | chromium_src-f781782dd67077478e117c61dca4ea5eefce3544.zip chromium_src-f781782dd67077478e117c61dca4ea5eefce3544.tar.gz chromium_src-f781782dd67077478e117c61dca4ea5eefce3544.tar.bz2 |
Initial import of the Chrome Frame codebase. Integration in chrome.gyp coming in a separate CL.
BUG=None
TEST=None
Review URL: http://codereview.chromium.org/218019
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@27042 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome_frame/scoped_ns_ptr_win.h')
-rw-r--r-- | chrome_frame/scoped_ns_ptr_win.h | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/chrome_frame/scoped_ns_ptr_win.h b/chrome_frame/scoped_ns_ptr_win.h new file mode 100644 index 0000000..91780fd --- /dev/null +++ b/chrome_frame/scoped_ns_ptr_win.h @@ -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_ |