Bug 753625 - Use tri-state session restore flag. r=mfinkle
authorBrian Nicholson <bnicholson@mozilla.com>
Mon, 14 May 2012 14:48:04 -0700
changeset 93916 b776bb82fb4aad654dfffeaacbb00f0a3ee72375
parent 93915 bdd1e7c3335843180fe0fbac85b556661ac7beb0
child 93917 a0438a35c1ebdb9643aad0a0a8f5b35975fb0346
push id9379
push userbnicholson@mozilla.com
push dateMon, 14 May 2012 21:48:14 +0000
treeherdermozilla-inbound@b776bb82fb4a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmfinkle
bugs753625
milestone15.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 753625 - Use tri-state session restore flag. r=mfinkle
mobile/android/base/GeckoApp.java
mobile/android/base/GeckoAppShell.java
mobile/android/base/GeckoThread.java
mobile/android/chrome/content/browser.js
mobile/android/components/BrowserCLH.js
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -113,17 +113,16 @@ abstract public class GeckoApp
     public static final String ACTION_ALERT_CLEAR   = "org.mozilla.gecko.ACTION_ALERT_CLEAR";
     public static final String ACTION_WEBAPP        = "org.mozilla.gecko.WEBAPP";
     public static final String ACTION_DEBUG         = "org.mozilla.gecko.DEBUG";
     public static final String ACTION_BOOKMARK      = "org.mozilla.gecko.BOOKMARK";
     public static final String ACTION_LOAD          = "org.mozilla.gecko.LOAD";
     public static final String ACTION_UPDATE        = "org.mozilla.gecko.UPDATE";
     public static final String ACTION_INIT_PW       = "org.mozilla.gecko.INIT_PW";
     public static final String SAVED_STATE_TITLE    = "title";
-    public static final String SAVED_STATE_SESSION  = "session";
 
     StartupMode mStartupMode = null;
     private LinearLayout mMainLayout;
     private RelativeLayout mGeckoLayout;
     public static SurfaceView cameraView;
     public static GeckoApp mAppContext;
     public static boolean mDOMFullScreen = false;
     public static Menu sMenu;
@@ -141,17 +140,17 @@ abstract public class GeckoApp
     public static FormAssistPopup mFormAssistPopup;
     public Favicons mFavicons;
 
     private static LayerController mLayerController;
     private static GeckoLayerClient mLayerClient;
     private AboutHomeContent mAboutHomeContent;
     private static AbsoluteLayout mPluginContainer;
 
-    private boolean mRestoreSession = false;
+    private int mRestoreMode = GeckoAppShell.RESTORE_NONE;
     private boolean mInitialized = false;
 
     static class ExtraMenuItem implements MenuItem.OnMenuItemClickListener {
         String label;
         String icon;
         int id;
         public boolean onMenuItemClick(MenuItem item) {
             Log.i(LOGTAG, "menu item clicked");
@@ -545,17 +544,16 @@ abstract public class GeckoApp
         super.onSaveInstanceState(outState);
 
         if (outState == null)
             outState = new Bundle();
 
         Tab tab = Tabs.getInstance().getSelectedTab();
         if (tab != null)
             outState.putString(SAVED_STATE_TITLE, tab.getDisplayTitle());
-        outState.putBoolean(SAVED_STATE_SESSION, true);
     }
 
     void getAndProcessThumbnailForTab(final Tab tab) {
         boolean isSelectedTab = Tabs.getInstance().isSelectedTab(tab);
         final Bitmap bitmap = isSelectedTab ? mLayerClient.getBitmap() : null;
         
         if ("about:home".equals(tab.getURL())) {
             tab.updateThumbnail(null);
@@ -1555,17 +1553,17 @@ abstract public class GeckoApp
         mBrowserToolbar.from(actionBar);
 
         // setup gecko layout
         mGeckoLayout = (RelativeLayout) findViewById(R.id.gecko_layout);
         mMainLayout = (LinearLayout) findViewById(R.id.main_layout);
 
         if (savedInstanceState != null) {
             mBrowserToolbar.setTitle(savedInstanceState.getString(SAVED_STATE_TITLE));
-            mRestoreSession = savedInstanceState.getBoolean(SAVED_STATE_SESSION);
+            mRestoreMode = GeckoAppShell.RESTORE_OOM;
         }
 
         ((GeckoApplication) getApplication()).addApplicationLifecycleCallbacks(this);
     }
 
     private void initialize() {
         mInitialized = true;
 
@@ -1588,30 +1586,31 @@ abstract public class GeckoApp
 
         String passedUri = null;
         String uri = getURIFromIntent(intent);
         if (uri != null && uri.length() > 0) {
             passedUri = uri;
             mBrowserToolbar.setTitle(uri);
         }
 
-        mRestoreSession |= getProfile().shouldRestoreSession();
+        if (mRestoreMode == GeckoAppShell.RESTORE_NONE && getProfile().shouldRestoreSession())
+            mRestoreMode = GeckoAppShell.RESTORE_CRASH;
 
         boolean isExternalURL = passedUri != null && !passedUri.equals("about:home");
         if (!isExternalURL) {
             // show about:home if we aren't restoring previous session
-            if (!mRestoreSession) {
+            if (mRestoreMode == GeckoAppShell.RESTORE_NONE) {
                 mBrowserToolbar.updateTabCount(1);
                 showAboutHome();
             }
         } else {
             mBrowserToolbar.updateTabCount(1);
         }
 
-        mBrowserToolbar.setProgressVisibility(isExternalURL || mRestoreSession);
+        mBrowserToolbar.setProgressVisibility(isExternalURL || (mRestoreMode != GeckoAppShell.RESTORE_NONE));
 
         // Start migrating as early as possible, can do this in
         // parallel with Gecko load.
         checkMigrateProfile();
 
         Uri data = intent.getData();
         if (data != null && "http".equals(data.getScheme()) &&
             isHostOnPrefetchWhitelist(data.getHost())) {
@@ -1621,17 +1620,17 @@ abstract public class GeckoApp
             // We're going to handle this uri with the redirector, so setting
             // the action to MAIN and clearing the uri data prevents us from
             // loading it twice
             intent.setAction(Intent.ACTION_MAIN);
             intent.setData(null);
             passedUri = "about:empty";
         }
 
-        sGeckoThread = new GeckoThread(intent, passedUri, mRestoreSession);
+        sGeckoThread = new GeckoThread(intent, passedUri, mRestoreMode);
         if (!ACTION_DEBUG.equals(action) &&
             checkAndSetLaunchState(LaunchState.Launching, LaunchState.Launched)) {
             sGeckoThread.start();
         } else if (ACTION_DEBUG.equals(action) &&
             checkAndSetLaunchState(LaunchState.Launching, LaunchState.WaitForDebugger)) {
             mMainHandler.postDelayed(new Runnable() {
                 public void run() {
                     Log.i(LOGTAG, "Launching from debug intent after 5s wait");
--- a/mobile/android/base/GeckoAppShell.java
+++ b/mobile/android/base/GeckoAppShell.java
@@ -114,16 +114,20 @@ public class GeckoAppShell
 
     public static final String SHORTCUT_TYPE_WEBAPP = "webapp";
     public static final String SHORTCUT_TYPE_BOOKMARK = "bookmark";
 
     static public final int SCREENSHOT_THUMBNAIL = 0;
     static public final int SCREENSHOT_WHOLE_PAGE = 1;
     static public final int SCREENSHOT_UPDATE = 2;
 
+    static public final int RESTORE_NONE = 0;
+    static public final int RESTORE_OOM = 1;
+    static public final int RESTORE_CRASH = 2;
+
     static private File sCacheFile = null;
     static private int sFreeSpace = -1;
     static File sHomeDir = null;
     static private int sDensityDpi = 0;
     private static Boolean sSQLiteLibsLoaded = false;
     private static Boolean sNSSLibsLoaded = false;
     private static Boolean sLibsSetup = false;
     private static File sGREDir = null;
@@ -455,17 +459,17 @@ public class GeckoAppShell
             DecimalFormatSymbols dfs = df.getDecimalFormatSymbols();
 
             GeckoAppShell.putenv("LOCALE_DECIMAL_POINT=" + dfs.getDecimalSeparator());
             GeckoAppShell.putenv("LOCALE_THOUSANDS_SEP=" + dfs.getGroupingSeparator());
             GeckoAppShell.putenv("LOCALE_GROUPING=" + (char)df.getGroupingSize());
         }
     }
 
-    public static void runGecko(String apkPath, String args, String url, String type, boolean restoreSession) {
+    public static void runGecko(String apkPath, String args, String url, String type, int restoreMode) {
         Looper.prepare();
         sGeckoHandler = new Handler();
         
         // run gecko -- it will spawn its own thread
         GeckoAppShell.nativeInit();
 
         Log.i(LOGTAG, "post native init");
 
@@ -477,18 +481,18 @@ public class GeckoAppShell
         // First argument is the .apk path
         String combinedArgs = apkPath + " -greomni " + apkPath;
         if (args != null)
             combinedArgs += " " + args;
         if (url != null)
             combinedArgs += " -url " + url;
         if (type != null)
             combinedArgs += " " + type;
-        if (restoreSession)
-            combinedArgs += " -restoresession";
+        if (restoreMode != RESTORE_NONE)
+            combinedArgs += " -restoremode " + restoreMode;
 
         DisplayMetrics metrics = new DisplayMetrics();
         GeckoApp.mAppContext.getWindowManager().getDefaultDisplay().getMetrics(metrics);
         combinedArgs += " -width " + metrics.widthPixels + " -height " + metrics.heightPixels;
 
         GeckoApp.mAppContext.runOnUiThread(new Runnable() {
                 public void run() {
                     geckoLoaded();
--- a/mobile/android/base/GeckoThread.java
+++ b/mobile/android/base/GeckoThread.java
@@ -51,22 +51,22 @@ import java.io.StringWriter;
 import java.util.Date;
 import java.util.Locale;
 
 public class GeckoThread extends Thread {
     private static final String LOGTAG = "GeckoThread";
 
     Intent mIntent;
     String mUri;
-    boolean mRestoreSession;
+    int mRestoreMode;
 
-    GeckoThread (Intent intent, String uri, boolean restoreSession) {
+    GeckoThread(Intent intent, String uri, int restoreMode) {
         mIntent = intent;
         mUri = uri;
-        mRestoreSession = restoreSession;
+        mRestoreMode = restoreMode;
     }
 
     public void run() {
         final GeckoApp app = GeckoApp.mAppContext;
         File cacheFile = GeckoAppShell.getCacheDir(app);
         File libxulFile = new File(cacheFile, "libxul.so");
 
         if ((!libxulFile.exists() ||
@@ -108,11 +108,11 @@ public class GeckoThread extends Thread 
                       null;
 
         // and then fire us up
         Log.i(LOGTAG, "RunGecko - URI = " + mUri);
         GeckoAppShell.runGecko(app.getApplication().getPackageResourcePath(),
                                mIntent.getStringExtra("args"),
                                mUri,
                                type,
-                               mRestoreSession);
+                               mRestoreMode);
     }
 }
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -247,23 +247,23 @@ var BrowserApp = {
 
     // Init LoginManager
     Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
     // Init FormHistory
     Cc["@mozilla.org/satchel/form-history;1"].getService(Ci.nsIFormHistory2);
 
     let loadParams = {};
     let url = "about:home";
-    let forceRestore = false;
+    let restoreMode = 0;
     let pinned = false;
     if ("arguments" in window) {
       if (window.arguments[0])
         url = window.arguments[0];
       if (window.arguments[1])
-        forceRestore = window.arguments[1];
+        restoreMode = window.arguments[1];
       if (window.arguments[2])
         gScreenWidth = window.arguments[2];
       if (window.arguments[3])
         gScreenHeight = window.arguments[3];
       if (window.arguments[4])
         pinned = window.arguments[4];
     }
 
@@ -273,19 +273,22 @@ var BrowserApp = {
     // XXX maybe we don't do this if the launch was kicked off from external
     Services.io.offline = false;
 
     // Broadcast a UIReady message so add-ons know we are finished with startup
     let event = document.createEvent("Events");
     event.initEvent("UIReady", true, false);
     window.dispatchEvent(event);
 
-    // restore the previous session
+    // Restore the previous session
+    // restoreMode = 0 means no restore
+    // restoreMode = 1 means force restore (after an OOM kill)
+    // restoreMode = 2 means restore only if we haven't crashed multiple times
     let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
-    if (forceRestore || ss.shouldRestore()) {
+    if (restoreMode || ss.shouldRestore()) {
       // A restored tab should not be active if we are loading a URL
       let restoreToFront = false;
 
       sendMessageToJava({
         gecko: {
           type: "Session:RestoreBegin"
         }
       });
@@ -315,17 +318,17 @@ var BrowserApp = {
               type: "Session:RestoreEnd"
             }
           });
         }
       };
       Services.obs.addObserver(restoreCleanup, "sessionstore-windows-restored", false);
 
       // Start the restore
-      ss.restoreLastSession(restoreToFront, forceRestore);
+      ss.restoreLastSession(restoreToFront, restoreMode == 1);
     } else {
       loadParams.showProgress = (url != "about:home");
       loadParams.pinned = pinned;
       this.addTab(url, loadParams);
 
       // show telemetry door hanger if we aren't restoring a session
       this._showTelemetryPrompt();
     }
--- a/mobile/android/components/BrowserCLH.js
+++ b/mobile/android/components/BrowserCLH.js
@@ -8,32 +8,32 @@ Cu.import("resource://gre/modules/Servic
 
 function dump(a) {
   Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService).logStringMessage(a);
 }
 
 function openWindow(aParent, aURL, aTarget, aFeatures, aArgs) {
   let argsArray = Cc["@mozilla.org/supports-array;1"].createInstance(Ci.nsISupportsArray);
   let urlString = null;
-  let restoreSessionBool = Cc["@mozilla.org/supports-PRBool;1"].createInstance(Ci.nsISupportsPRBool);
+  let restoreModeInt = Cc["@mozilla.org/supports-PRInt32;1"].createInstance(Ci.nsISupportsPRInt32);
   let pinnedBool = Cc["@mozilla.org/supports-PRBool;1"].createInstance(Ci.nsISupportsPRBool);
   let widthInt = Cc["@mozilla.org/supports-PRInt32;1"].createInstance(Ci.nsISupportsPRInt32);
   let heightInt = Cc["@mozilla.org/supports-PRInt32;1"].createInstance(Ci.nsISupportsPRInt32);
 
   if ("url" in aArgs) {
     urlString = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
     urlString.data = aArgs.url;
   }
-  restoreSessionBool.data = "restoreSession" in aArgs ? aArgs.restoreSession : false;
+  restoreModeInt.data = "restoreMode" in aArgs ? aArgs.restoreMode : 0;
   widthInt.data = "width" in aArgs ? aArgs.width : 1;
   heightInt.data = "height" in aArgs ? aArgs.height : 1;
   pinnedBool.data = "pinned" in aArgs ? aArgs.pinned : false;
 
   argsArray.AppendElement(urlString, false);
-  argsArray.AppendElement(restoreSessionBool, false);
+  argsArray.AppendElement(restoreModeInt, false);
   argsArray.AppendElement(widthInt, false);
   argsArray.AppendElement(heightInt, false);
   argsArray.AppendElement(pinnedBool, false);
   return Services.ww.openWindow(aParent, aURL, aTarget, aFeatures, argsArray);
 }
 
 
 function resolveURIInternal(aCmdLine, aArgument) {
@@ -53,29 +53,29 @@ function resolveURIInternal(aCmdLine, aA
 
 function BrowserCLH() {}
 
 BrowserCLH.prototype = {
   handle: function fs_handle(aCmdLine) {
     let openURL = "about:home";
     let pinned = false;
 
-    let restoreSession = false;
+    let restoreMode = 0;
     let width = 1;
     let height = 1;
 
     try {
       openURL = aCmdLine.handleFlagWithParam("url", false);
     } catch (e) { /* Optional */ }
     try {
       pinned = aCmdLine.handleFlag("webapp", false);
     } catch (e) { /* Optional */ }
 
     try {
-      restoreSession = aCmdLine.handleFlag("restoresession", false);
+      restoreMode = aCmdLine.handleFlagWithParam("restoremode", false);
     } catch (e) { /* Optional */ }
     try {
       width = aCmdLine.handleFlagWithParam("width", false);
     } catch (e) { /* Optional */ }
     try {
       height = aCmdLine.handleFlagWithParam("height", false);
     } catch (e) { /* Optional */ }
 
@@ -86,17 +86,17 @@ BrowserCLH.prototype = {
 
       let browserWin = Services.wm.getMostRecentWindow("navigator:browser");
       if (browserWin) {
         let whereFlags = pinned ? Ci.nsIBrowserDOMWindow.OPEN_SWITCHTAB : Ci.nsIBrowserDOMWindow.OPEN_NEWTAB;
         browserWin.browserDOMWindow.openURI(uri, null, whereFlags, Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL);
       } else {
         let args = {
           url: openURL,
-          restoreSession: restoreSession,
+          restoreMode: restoreMode,
           pinned: pinned,
           width: width,
           height: height
         };
         browserWin = openWindow(null, "chrome://browser/content/browser.xul", "_blank", "chrome,dialog=no,all", args);
       }
 
       aCmdLine.preventDefault = true;