summaryrefslogtreecommitdiffstats
path: root/widget/windows/nsDataObj.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'widget/windows/nsDataObj.cpp')
-rw-r--r--widget/windows/nsDataObj.cpp99
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();
-}