summaryrefslogtreecommitdiffstats
path: root/widget/windows
diff options
context:
space:
mode:
Diffstat (limited to 'widget/windows')
-rw-r--r--widget/windows/nsClipboard.cpp2
-rw-r--r--widget/windows/nsDataObj.cpp99
-rw-r--r--widget/windows/nsDataObj.h1
3 files changed, 81 insertions, 21 deletions
diff --git a/widget/windows/nsClipboard.cpp b/widget/windows/nsClipboard.cpp
index 1afee3496..0db1dd342 100644
--- a/widget/windows/nsClipboard.cpp
+++ b/widget/windows/nsClipboard.cpp
@@ -65,7 +65,7 @@ nsClipboard::nsClipboard() : nsBaseClipboard()
nsCOMPtr<nsIObserverService> observerService =
do_GetService("@mozilla.org/observer-service;1");
if (observerService)
- observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_FALSE);
+ observerService->AddObserver(this, NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID, PR_FALSE);
}
//-------------------------------------------------------------------------
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();
-}
diff --git a/widget/windows/nsDataObj.h b/widget/windows/nsDataObj.h
index 2d7fb75ee..61f209e85 100644
--- a/widget/windows/nsDataObj.h
+++ b/widget/windows/nsDataObj.h
@@ -289,7 +289,6 @@ protected:
bool LookupArbitraryFormat(FORMATETC *aFormat, LPDATAENTRY *aDataEntry, BOOL aAddorUpdate);
bool CopyMediumData(STGMEDIUM *aMediumDst, STGMEDIUM *aMediumSrc, LPFORMATETC aFormat, BOOL aSetData);
- static void RemoveTempFile(nsITimer* aTimer, void* aClosure);
};