diff --git a/content/media/nsMediaCache.cpp b/content/media/nsMediaCache.cpp index 75d7a8fa03a..704a585b544 100644 --- a/content/media/nsMediaCache.cpp +++ b/content/media/nsMediaCache.cpp @@ -559,9 +559,23 @@ nsMediaCache::Init() if (NS_FAILED(rv)) return rv; nsCOMPtr tmpFile = do_QueryInterface(tmp); + + // We put the media cache file in + // ${TempDir}/mozilla-media-cache/media_cache if (!tmpFile) return NS_ERROR_FAILURE; - rv = tmpFile->AppendNative(nsDependentCString("moz_media_cache")); + rv = tmpFile->AppendNative(nsDependentCString("mozilla-media-cache")); + if (NS_FAILED(rv)) + return rv; + rv = tmpFile->Create(nsIFile::DIRECTORY_TYPE, 0600); + if (NS_FAILED(rv) && rv != NS_ERROR_FILE_ALREADY_EXISTS) + return rv; + + rv = tmpFile->Create(nsIFile::DIRECTORY_TYPE, 0600); + if (NS_FAILED(rv) && rv != NS_ERROR_FILE_ALREADY_EXISTS) + return rv; + + rv = tmpFile->AppendNative(nsDependentCString("media_cache")); if (NS_FAILED(rv)) return rv; rv = tmpFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600); diff --git a/xpcom/build/nsXPComInit.cpp b/xpcom/build/nsXPComInit.cpp index 2d7f2d47f2f..95e24416c7b 100644 --- a/xpcom/build/nsXPComInit.cpp +++ b/xpcom/build/nsXPComInit.cpp @@ -179,6 +179,10 @@ static BrowserProcessSubThread* sIOThread; extern nsresult NS_RegistryGetFactory(nsIFactory** aFactory); extern nsresult NS_CategoryManagerGetFactory( nsIFactory** ); +#ifdef XP_WIN +extern nsresult nsMediaCacheRemover_Startup(); +#endif + #ifdef DEBUG extern void _FreeAutoLockStatics(); #endif @@ -555,7 +559,10 @@ NS_InitXPCOM2(nsIServiceManager* *result, NS_CreateServicesFromCategory(NS_XPCOM_STARTUP_CATEGORY, nsnull, NS_XPCOM_STARTUP_OBSERVER_ID); - +#ifdef XP_WIN + nsMediaCacheRemover_Startup(); +#endif + return NS_OK; } diff --git a/xpcom/io/Makefile.in b/xpcom/io/Makefile.in index 0337a3909fd..37c7ed6de61 100644 --- a/xpcom/io/Makefile.in +++ b/xpcom/io/Makefile.in @@ -94,7 +94,7 @@ ifeq ($(MOZ_WIDGET_TOOLKIT),os2) CPPSRCS += nsLocalFileOS2.cpp else ifeq ($(MOZ_WIDGET_TOOLKIT),windows) -CPPSRCS += nsLocalFileWin.cpp +CPPSRCS += nsLocalFileWin.cpp nsMediaCacheRemover.cpp else CPPSRCS += nsLocalFileUnix.cpp endif # windows diff --git a/xpcom/io/nsMediaCacheRemover.cpp b/xpcom/io/nsMediaCacheRemover.cpp new file mode 100644 index 00000000000..14d36c490df --- /dev/null +++ b/xpcom/io/nsMediaCacheRemover.cpp @@ -0,0 +1,132 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla code. + * + * The Initial Developer of the Original Code is + * the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chris Pearce + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef XP_WIN +#error nsMediaCacheRemover only needed on Windows. +#endif + +#include "nsIObserver.h" +#include "nsIIdleService.h" +#include "nsISimpleEnumerator.h" +#include "nsILocalFile.h" +#include "nsAppDirectoryServiceDefs.h" +#include "nsDirectoryServiceDefs.h" +#include "nsString.h" +#include "nsAutoPtr.h" + +// Duration of idle time before we'll get a callback whereupon we attempt to +// remove any stray and unused media cache temp files. +#define TEMP_FILE_IDLE_TIME 30 + +// This class is instantiated during the xpcom initialization, and adds itself +// as an idle observer. When the application has been idle for about 30 seconds +// we'll get a notification, whereupon we'll attempt to delete +// ${TempDir}/mozilla-media-cache/. This is to ensure all media cache temp +// files which were supposed to be deleted on application exit were actually +// deleted as they may not be if we previously crashed. See bug 572579. This +// is only needed on some versions of Windows, nsILocalFile::DELETE_ON_CLOSE +// works on other platforms. +class nsMediaCacheRemover : public nsIObserver { +public: + NS_DECL_ISUPPORTS + + nsMediaCacheRemover() { + MOZ_COUNT_CTOR(nsMediaCacheRemover); + } + + ~nsMediaCacheRemover() { + MOZ_COUNT_DTOR(nsMediaCacheRemover); + } + + NS_IMETHODIMP Observe(nsISupports *subject, + const char *topic, + const PRUnichar *data) + { + if (strcmp(topic, "idle") == 0) { + // The user has been idle for a while, clean up the temp files. + // The idle service will drop its reference to this object after + // we exit, destroying this object. + RemoveMediaCacheFiles(); + } + return NS_OK; + } + + nsresult RegisterIdleObserver() { + // Add this as an idle observer. When we've been idle for + // TEMP_FILE_IDLE_TIME seconds, we'll get a notification, and we'll then + // try to delete any stray media cache temp files. + nsCOMPtr idleSvc = + do_GetService("@mozilla.org/widget/idleservice;1"); + if (!idleSvc) + return NS_ERROR_FAILURE; + return idleSvc->AddIdleObserver(this, TEMP_FILE_IDLE_TIME); + } + + void RemoveMediaCacheFiles() { + nsCOMPtr idleSvc = + do_GetService("@mozilla.org/widget/idleservice;1"); + if (idleSvc) + idleSvc->RemoveIdleObserver(this, TEMP_FILE_IDLE_TIME); + + nsCOMPtr tmpDir; + nsresult rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, + getter_AddRefs(tmpDir)); + if (NS_FAILED(rv)) + return; + rv = tmpDir->AppendNative(nsDependentCString("mozilla-media-cache")); + if (NS_FAILED(rv)) + return; + + nsCOMPtr tmpFile = do_QueryInterface(tmpDir); + if (!tmpFile) + return; + + // Remove the directory recursively. + tmpFile->Remove(PR_TRUE); + } +}; + +NS_IMPL_ISUPPORTS1(nsMediaCacheRemover, nsIObserver) + +nsresult nsMediaCacheRemover_Startup() { + // Create a new nsMediaCacheRemover, and register it as an idle observer. + // If it is successfully registered as an idle observer, its owning reference + // will be held by the idle service, otherwise it will be destroyed by the + // refptr here when it goes out of scope. + nsRefPtr t = new nsMediaCacheRemover(); + return t->RegisterIdleObserver(); +}