Bug 896092 - Restore session when returning from guest mode. r=bnicholson DONTBUILD

This commit is contained in:
Wes Johnston 2013-08-02 11:04:42 -07:00
parent be913a3443
commit 1abd07786d
2 changed files with 144 additions and 22 deletions

View File

@ -100,6 +100,9 @@ abstract public class BrowserApp extends GeckoApp
private AboutHome mAboutHome;
protected Telemetry.Timer mAboutHomeStartupTimer = null;
// Set the default session restore value
private int mSessionRestore = -1;
private static final int GECKO_TOOLS_MENU = -1;
private static final int ADDON_MENU_OFFSET = 1000;
private class MenuItemInfo {
@ -393,6 +396,15 @@ abstract public class BrowserApp extends GeckoApp
super.onStatePurged();
}
@Override
protected int getSessionRestoreState(Bundle savedInstanceState) {
if (mSessionRestore > -1) {
return mSessionRestore;
}
return super.getSessionRestoreState(savedInstanceState);
}
@Override
public void onCreate(Bundle savedInstanceState) {
mAboutHomeStartupTimer = new Telemetry.Timer("FENNEC_STARTUP_TIME_ABOUTHOME");
@ -400,13 +412,8 @@ abstract public class BrowserApp extends GeckoApp
String args = getIntent().getStringExtra("args");
if (args != null && args.contains("--guest-mode")) {
mProfile = GeckoProfile.createGuestProfile(this);
} else {
ThreadUtils.postToBackgroundThread(new Runnable() {
@Override
public void run() {
GeckoProfile.removeGuestProfile(BrowserApp.this);
}
});
} else if (GeckoProfile.maybeCleanupGuestProfile(this)) {
mSessionRestore = RESTORE_NORMAL;
}
super.onCreate(savedInstanceState);
@ -1814,6 +1821,8 @@ abstract public class BrowserApp extends GeckoApp
String args = "";
if (type == GuestModeDialog.ENTERING) {
args = "--guest-mode";
} else {
GeckoProfile.leaveGuestSession(BrowserApp.this);
}
doRestart(args);
System.exit(0);

View File

@ -7,6 +7,7 @@ package org.mozilla.gecko;
import org.mozilla.gecko.util.INIParser;
import org.mozilla.gecko.util.INISection;
import org.mozilla.gecko.util.ThreadUtils;
import android.content.Context;
import android.text.TextUtils;
@ -24,6 +25,8 @@ import java.util.Hashtable;
public final class GeckoProfile {
private static final String LOGTAG = "GeckoProfile";
// Used to "lock" the guest profile, so that we'll always restart in it
private static final String LOCK_FILE_NAME = ".active_lock";
private static HashMap<String, GeckoProfile> sProfileCache = new HashMap<String, GeckoProfile>();
private static String sDefaultProfileName = null;
@ -33,7 +36,21 @@ public final class GeckoProfile {
private File mMozDir;
private File mDir;
// Constants to cache whether or not a profile is "locked".
private enum LockState {
LOCKED,
UNLOCKED,
UNDEFINED
};
// Caches whether or not a profile is "locked". Only used by the guest profile to determine if it should
// be reused or deleted on startup
private LockState mLocked = LockState.UNDEFINED;
// Caches the guest profile dir
private static File mGuestDir = null;
private boolean mInGuestMode = false;
private static GeckoProfile mGuestProfile = null;
static private INIParser getProfilesINI(Context context) {
File filesDir = context.getFilesDir();
@ -44,8 +61,19 @@ public final class GeckoProfile {
public static GeckoProfile get(Context context) {
if (context instanceof GeckoApp) {
if (((GeckoApp)context).mProfile != null)
// Check for a cached profile on this context already
// TODO: We should not be caching profile information on the Activity context
if (((GeckoApp)context).mProfile != null) {
return ((GeckoApp)context).mProfile;
}
GeckoProfile guest = GeckoProfile.getGuestProfile(context);
// if the guest profile exists and is locked, return it
if (guest != null && guest.locked()) {
return guest;
}
// Otherwise, get the default profile for the Activity
return get(context, ((GeckoApp)context).getDefaultProfileName());
}
@ -112,17 +140,13 @@ public final class GeckoProfile {
}
public static GeckoProfile createGuestProfile(Context context) {
if (context == null) {
throw new IllegalArgumentException("context must be non-null");
}
try {
removeGuestProfile(context);
File guestDir = context.getDir("guest", Context.MODE_PRIVATE);
guestDir.mkdir();
GeckoProfile profile = get(context, "guest", guestDir);
profile.mInGuestMode = true;
// We need to force the creation of a new guest profile if we want it outside of the normal profile path,
// otherwise GeckoProfile.getDir will try to be smart and build it for us in the normal profiles dir.
getGuestDir(context).mkdir();
GeckoProfile profile = getGuestProfile(context);
profile.lock();
return profile;
} catch (Exception ex) {
Log.e(LOGTAG, "Error creating guest profile", ex);
@ -130,12 +154,50 @@ public final class GeckoProfile {
return null;
}
public static void removeGuestProfile(Context context) {
if (context == null) {
throw new IllegalArgumentException("context must be non-null");
public static void leaveGuestSession(Context context) {
GeckoProfile profile = getGuestProfile(context);
if (profile != null) {
profile.unlock();
}
}
private static File getGuestDir(Context context) {
if (mGuestDir == null) {
mGuestDir = context.getDir("guest", Context.MODE_PRIVATE);
}
return mGuestDir;
}
private static GeckoProfile getGuestProfile(Context context) {
if (mGuestProfile == null) {
File guestDir = getGuestDir(context);
mGuestProfile = get(context, "guest", guestDir);
mGuestProfile.mInGuestMode = true;
}
return mGuestProfile;
}
public static boolean maybeCleanupGuestProfile(final Context context) {
// Don't use profile.getDir() here, so that we don't accidently create the dir
File guestDir = getGuestDir(context);
final GeckoProfile profile = getGuestProfile(context);
if (guestDir.exists() && !profile.locked()) {
// if the guest dir exists, but its unlocked, delete it
ThreadUtils.postToBackgroundThread(new Runnable() {
@Override
public void run() {
removeGuestProfile(context);
}
});
return true;
}
return false;
}
private static void removeGuestProfile(Context context) {
try {
File guestDir = context.getDir("guest", Context.MODE_PRIVATE);
File guestDir = getGuestDir(context);
if (guestDir.exists()) {
delete(guestDir);
}
@ -162,6 +224,52 @@ public final class GeckoProfile {
return file.delete();
}
// Warning, Changing the lock file state from outside apis will cause this to become out of sync
public boolean locked() {
if (mLocked != LockState.UNDEFINED) {
return mLocked == LockState.LOCKED;
}
File lockFile = new File(getDir(), LOCK_FILE_NAME);
boolean res = lockFile.exists();
mLocked = res ? LockState.LOCKED : LockState.UNLOCKED;
return res;
}
public boolean lock() {
try {
File lockFile = new File(getDir(), LOCK_FILE_NAME);
boolean result = lockFile.createNewFile();
if (result) {
mLocked = LockState.LOCKED;
} else {
mLocked = LockState.UNLOCKED;
}
return result;
} catch(IOException ex) {
Log.e(LOGTAG, "Error locking profile", ex);
}
mLocked = LockState.UNLOCKED;
return false;
}
public boolean unlock() {
try {
File lockFile = new File(getDir(), LOCK_FILE_NAME);
boolean result = delete(lockFile);
if (result) {
mLocked = LockState.UNLOCKED;
} else {
mLocked = LockState.LOCKED;
}
return result;
} catch(IOException ex) {
Log.e(LOGTAG, "Error unlocking profile", ex);
}
mLocked = LockState.LOCKED;
return false;
}
private GeckoProfile(Context context, String profileName) {
mContext = context;
mName = profileName;
@ -292,10 +400,15 @@ public final class GeckoProfile {
private boolean remove() {
try {
File dir = getDir();
if (dir.exists())
delete(dir);
File mozillaDir = ensureMozillaDirectory(mContext);
mDir = findProfileDir(mozillaDir);
if (mDir == null)
if (mDir == null) {
return false;
}
INIParser parser = getProfilesINI(mContext);