diff --git a/mobile/android/base/GeckoApp.java b/mobile/android/base/GeckoApp.java index 341343fa1b2c..55b9373245b1 100644 --- a/mobile/android/base/GeckoApp.java +++ b/mobile/android/base/GeckoApp.java @@ -44,11 +44,13 @@ import org.mozilla.gecko.health.StubbedHealthRecorder; import org.mozilla.gecko.menu.GeckoMenu; import org.mozilla.gecko.menu.GeckoMenuInflater; import org.mozilla.gecko.menu.MenuPanel; +import org.mozilla.gecko.mozglue.GeckoLoader; import org.mozilla.gecko.preferences.GeckoPreferences; import org.mozilla.gecko.prompts.PromptService; import org.mozilla.gecko.updater.UpdateService; import org.mozilla.gecko.updater.UpdateServiceHelper; import org.mozilla.gecko.util.ActivityResultHandler; +import org.mozilla.gecko.util.FileUtils; import org.mozilla.gecko.util.GeckoEventListener; import org.mozilla.gecko.util.HardwareUtils; import org.mozilla.gecko.util.ThreadUtils; @@ -133,6 +135,7 @@ public abstract class GeckoApp Tabs.OnTabsChangedListener { private static final String LOGTAG = "GeckoApp"; + private static final int ONE_DAY_MS = 1000*60*60*24; private static enum StartupAction { NORMAL, /* normal application start */ @@ -156,6 +159,7 @@ public abstract class GeckoApp public static final String PREFS_OOM_EXCEPTION = "OOMException"; public static final String PREFS_VERSION_CODE = "versionCode"; public static final String PREFS_WAS_STOPPED = "wasStopped"; + public static final String PREFS_CLEANUP_TEMP_FILES = "cleanupTempFiles"; public static final String SAVED_STATE_IN_BACKGROUND = "inBackground"; public static final String SAVED_STATE_PRIVATE_SESSION = "privateSession"; @@ -2053,6 +2057,15 @@ public abstract class GeckoApp if (rec != null) { rec.recordSessionEnd("P", editor); } + + // If we haven't done it before, cleanup any old files in our old temp dir + if (prefs.getBoolean(GeckoApp.PREFS_CLEANUP_TEMP_FILES, true)) { + File tempDir = GeckoLoader.getGREDir(this); + FileUtils.delTree(tempDir, new FileUtils.NameAndAgeFilter(null, ONE_DAY_MS), false); + + editor.putBoolean(GeckoApp.PREFS_CLEANUP_TEMP_FILES, false); + } + editor.commit(); // In theory, the first browser session will not run long enough that we need to diff --git a/mobile/android/base/moz.build b/mobile/android/base/moz.build index 2487acac5248..94c441b252b9 100644 --- a/mobile/android/base/moz.build +++ b/mobile/android/base/moz.build @@ -48,6 +48,7 @@ gujar.sources += [ 'util/ActivityResultHandler.java', 'util/ActivityResultHandlerMap.java', 'util/Clipboard.java', + 'util/FileUtils.java', 'util/FloatUtils.java', 'util/GamepadUtils.java', 'util/GeckoBackgroundThread.java', diff --git a/mobile/android/base/util/FileUtils.java b/mobile/android/base/util/FileUtils.java new file mode 100644 index 000000000000..25a26e541b7f --- /dev/null +++ b/mobile/android/base/util/FileUtils.java @@ -0,0 +1,81 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.gecko.util; + +import android.util.Log; + +import java.io.File; +import java.io.IOException; +import java.io.FilenameFilter; + +public class FileUtils { + private static final String LOGTAG= "GeckoFileUtils"; + /* + * A basic Filter for checking a filename and age. + **/ + static public class NameAndAgeFilter implements FilenameFilter { + final private String mName; + final private double mMaxAge; + + public NameAndAgeFilter(String name, double age) { + mName = name; + mMaxAge = age; + } + + @Override + public boolean accept(File dir, String filename) { + if (mName == null || mName.matches(filename)) { + File f = new File(dir, filename); + + if (mMaxAge < 0 || System.currentTimeMillis() - f.lastModified() > mMaxAge) { + return true; + } + } + + return false; + } + } + + public static void delTree(File dir, FilenameFilter filter, boolean recurse) { + String[] files = null; + + if (filter != null) { + files = dir.list(filter); + } else { + files = dir.list(); + } + + if (files == null) { + return; + } + + for (String file : files) { + File f = new File(dir, file); + delete(f, recurse); + } + } + + public static boolean delete(File file) throws IOException { + return delete(file, true); + } + + public static boolean delete(File file, boolean recurse) { + if (file.isDirectory() && recurse) { + // If the quick delete failed and this is a dir, recursively delete the contents of the dir + String files[] = file.list(); + for (String temp : files) { + File fileDelete = new File(file, temp); + try { + delete(fileDelete); + } catch(IOException ex) { + Log.i(LOGTAG, "Error deleting " + fileDelete.getPath(), ex); + } + } + } + + // Even if this is a dir, it should now be empty and delete should work + return file.delete(); + } +}