diff options
author | janekptacijarabaci <janekptacijarabaci@seznam.cz> | 2018-04-20 22:54:26 +0200 |
---|---|---|
committer | janekptacijarabaci <janekptacijarabaci@seznam.cz> | 2018-04-20 22:54:26 +0200 |
commit | 4549256c2b685782587f2ccad6a105c0392492c7 (patch) | |
tree | b4364b3e0c84ed2c812158e89054e2c57b47f962 /widget/windows/nsDataObj.cpp | |
parent | 20a3f8c006445b176fa8559f6529c2cf3cb75b0d (diff) | |
download | UXP-4549256c2b685782587f2ccad6a105c0392492c7.tar UXP-4549256c2b685782587f2ccad6a105c0392492c7.tar.gz UXP-4549256c2b685782587f2ccad6a105c0392492c7.tar.lz UXP-4549256c2b685782587f2ccad6a105c0392492c7.tar.xz UXP-4549256c2b685782587f2ccad6a105c0392492c7.zip |
moebius#56: Fix: DataTransfer - Pasting image from clipboard fails in some cases
https://github.com/MoonchildProductions/moebius/pull/56
Diffstat (limited to 'widget/windows/nsDataObj.cpp')
-rw-r--r-- | widget/windows/nsDataObj.cpp | 99 |
1 files changed, 80 insertions, 19 deletions
diff --git a/widget/windows/nsDataObj.cpp b/widget/windows/nsDataObj.cpp index 02ec3b2fe..977a87c08 100644 --- a/widget/windows/nsDataObj.cpp +++ b/widget/windows/nsDataObj.cpp @@ -443,6 +443,82 @@ STDMETHODIMP_(ULONG) nsDataObj::AddRef() return m_cRef; } +namespace { +class RemoveTempFileHelper : public nsIObserver +{ +public: + explicit RemoveTempFileHelper(nsIFile* aTempFile) + : mTempFile(aTempFile) + { + MOZ_ASSERT(mTempFile); + } + + // The attach method is seperate from the constructor as we may be addref-ing + // ourself, and we want to be sure someone has a strong reference to us. + void Attach() + { + // We need to listen to both the xpcom shutdown message and our timer, and + // fire when the first of either of these two messages is received. + nsresult rv; + mTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv); + if (NS_WARN_IF(NS_FAILED(rv))) { + return; + } + mTimer->Init(this, 500, nsITimer::TYPE_ONE_SHOT); + + nsCOMPtr<nsIObserverService> observerService = + do_GetService("@mozilla.org/observer-service;1"); + if (NS_WARN_IF(!observerService)) { + mTimer->Cancel(); + mTimer = nullptr; + return; + } + observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false); + } + + NS_DECL_ISUPPORTS + NS_DECL_NSIOBSERVER + +private: + ~RemoveTempFileHelper() + { + if (mTempFile) { + mTempFile->Remove(false); + } + } + + nsCOMPtr<nsIFile> mTempFile; + nsCOMPtr<nsITimer> mTimer; +}; + +NS_IMPL_ISUPPORTS(RemoveTempFileHelper, nsIObserver); + +NS_IMETHODIMP +RemoveTempFileHelper::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData) +{ + // Let's be careful and make sure that we don't die immediately + RefPtr<RemoveTempFileHelper> grip = this; + + // Make sure that we aren't called again by destroying references to ourself. + nsCOMPtr<nsIObserverService> observerService = + do_GetService("@mozilla.org/observer-service;1"); + if (observerService) { + observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID); + } + + if (mTimer) { + mTimer->Cancel(); + mTimer = nullptr; + } + + // Remove the tempfile + if (mTempFile) { + mTempFile->Remove(false); + mTempFile = nullptr; + } + return NS_OK; +} +} // namespace //----------------------------------------------------- STDMETHODIMP_(ULONG) nsDataObj::Release() @@ -456,17 +532,12 @@ STDMETHODIMP_(ULONG) nsDataObj::Release() // We have released our last ref on this object and need to delete the // temp file. External app acting as drop target may still need to open the // temp file. Addref a timer so it can delay deleting file and destroying - // this object. Delete file anyway and destroy this obj if there's a problem. + // this object. if (mCachedTempFile) { - nsresult rv; - mTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv); - if (NS_SUCCEEDED(rv)) { - mTimer->InitWithFuncCallback(nsDataObj::RemoveTempFile, this, - 500, nsITimer::TYPE_ONE_SHOT); - return AddRef(); - } - mCachedTempFile->Remove(false); + RefPtr<RemoveTempFileHelper> helper = + new RemoveTempFileHelper(mCachedTempFile); mCachedTempFile = nullptr; + helper->Attach(); } delete this; @@ -2153,13 +2224,3 @@ HRESULT nsDataObj::GetFileContents_IStream(FORMATETC& aFE, STGMEDIUM& aSTG) return S_OK; } - -void nsDataObj::RemoveTempFile(nsITimer* aTimer, void* aClosure) -{ - nsDataObj *timedDataObj = static_cast<nsDataObj *>(aClosure); - if (timedDataObj->mCachedTempFile) { - timedDataObj->mCachedTempFile->Remove(false); - timedDataObj->mCachedTempFile = nullptr; - } - timedDataObj->Release(); -} |