Bug 1077590 - Part 4: fix profile access in BrowserApp. r=mfinkle
authorRichard Newman <rnewman@mozilla.com>
Mon, 12 Jan 2015 20:58:01 -0800
changeset 223428 fbdcb7d48dd9b11877048e542b6abd854af97541
parent 223427 0211ab7ba0d828fa1017011abce8f6d627b1992a
child 223429 c9ff49636eefb8aaedca8de13b0ff684389d2c13
push id10785
push userrnewman@mozilla.com
push dateTue, 13 Jan 2015 04:58:30 +0000
treeherderfx-team@fbdcb7d48dd9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmfinkle
bugs1077590
milestone38.0a1
Bug 1077590 - Part 4: fix profile access in BrowserApp. r=mfinkle
mobile/android/base/BrowserApp.java
mobile/android/base/GeckoApp.java
mobile/android/base/GeckoProfile.java
--- a/mobile/android/base/BrowserApp.java
+++ b/mobile/android/base/BrowserApp.java
@@ -492,17 +492,23 @@ public class BrowserApp extends GeckoApp
         return super.onKeyUp(keyCode, event);
     }
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
         mAboutHomeStartupTimer = new Telemetry.UptimeTimer("FENNEC_STARTUP_TIME_ABOUTHOME");
 
         final Intent intent = getIntent();
+
+        // Note that we're calling GeckoProfile.get *before GeckoApp.onCreate*.
+        // This means we're reliant on the logic in GeckoProfile to correctly
+        // look up our launch intent (via BrowserApp's Activity-ness) and pull
+        // out the arguments. Be careful if you change that!
         final GeckoProfile p = GeckoProfile.get(this);
+
         if (p != null && !p.inGuestMode()) {
             // This is *only* valid because we never want to use the guest mode
             // profile concurrently with a normal profile -- no syncing to it,
             // no dual-profile usage, nothing. BrowserApp startup with a conventional
             // GeckoProfile will cause the guest profile to be deleted.
             GeckoProfile.maybeCleanupGuestProfile(this);
         }
 
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -1157,43 +1157,25 @@ public abstract class GeckoApp
 
         earlyStartJavaSampler(intent);
 
         // GeckoLoader wants to dig some environment variables out of the
         // incoming intent, so pass it in here. GeckoLoader will do its
         // business later and dispose of the reference.
         GeckoLoader.setLastIntent(intent);
 
-        if (mProfile == null) {
-            String profileName = null;
-            String profilePath = null;
-            if (args != null) {
-                if (args.contains("-P")) {
-                    Pattern p = Pattern.compile("(?:-P\\s*)(\\w*)(\\s*)");
-                    Matcher m = p.matcher(args);
-                    if (m.find()) {
-                        profileName = m.group(1);
-                    }
-                }
-
-                if (args.contains("-profile")) {
-                    Pattern p = Pattern.compile("(?:-profile\\s*)(\\S*)(\\s*)");
-                    Matcher m = p.matcher(args);
-                    if (m.find()) {
-                        profilePath =  m.group(1);
-                    }
-                    if (profileName == null) {
-                        profileName = GeckoProfile.DEFAULT_PROFILE;
-                    }
-                    GeckoProfile.sIsUsingCustomProfile = true;
-                }
-
-                if (profileName != null || profilePath != null) {
-                    mProfile = GeckoProfile.get(this, profileName, profilePath);
-                }
+        // If we don't already have a profile, but we do have arguments,
+        // let's see if they're enough to find one.
+        // Note that subclasses must ensure that if they try to access
+        // the profile prior to this code being run, then they do something
+        // similar.
+        if (mProfile == null && args != null) {
+            final GeckoProfile p = GeckoProfile.getFromArgs(this, args);
+            if (p != null) {
+                mProfile = p;
             }
         }
 
         // Speculatively pre-fetch the profile in the background.
         ThreadUtils.postToBackgroundThread(new Runnable() {
             @Override
             public void run() {
                 getProfile();
--- a/mobile/android/base/GeckoProfile.java
+++ b/mobile/android/base/GeckoProfile.java
@@ -9,16 +9,18 @@ import java.io.File;
 import java.io.FileOutputStream;
 import java.io.FileReader;
 import java.io.IOException;
 import java.io.OutputStreamWriter;
 import java.nio.charset.Charset;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Hashtable;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import org.mozilla.gecko.GeckoProfileDirectories.NoMozillaDirectoryException;
 import org.mozilla.gecko.GeckoProfileDirectories.NoSuchProfileException;
 import org.mozilla.gecko.db.BrowserDB;
 import org.mozilla.gecko.db.LocalBrowserDB;
 import org.mozilla.gecko.db.StubBrowserDB;
 import org.mozilla.gecko.distribution.Distribution;
 import org.mozilla.gecko.mozglue.RobocopTarget;
@@ -84,16 +86,56 @@ public final class GeckoProfile {
 
     // Constants to cache whether or not a profile is "locked".
     private enum LockState {
         LOCKED,
         UNLOCKED,
         UNDEFINED
     };
 
+    /**
+     * Warning: has a side-effect of setting sIsUsingCustomProfile.
+     * Can return null.
+     */
+    public static GeckoProfile getFromArgs(final Context context, final String args) {
+        if (args == null) {
+            return null;
+        }
+
+        String profileName = null;
+        String profilePath = null;
+        if (args.contains("-P")) {
+            final Pattern p = Pattern.compile("(?:-P\\s*)(\\w*)(\\s*)");
+            final Matcher m = p.matcher(args);
+            if (m.find()) {
+                profileName = m.group(1);
+            }
+        }
+
+        if (args.contains("-profile")) {
+            final Pattern p = Pattern.compile("(?:-profile\\s*)(\\S*)(\\s*)");
+            final Matcher m = p.matcher(args);
+            if (m.find()) {
+                profilePath =  m.group(1);
+            }
+
+            if (profileName == null) {
+                profileName = GeckoProfile.DEFAULT_PROFILE;
+            }
+
+            GeckoProfile.sIsUsingCustomProfile = true;
+        }
+
+        if (profileName == null && profilePath == null) {
+            return null;
+        }
+
+        return GeckoProfile.get(context, profileName, profilePath);
+    }
+
     public static GeckoProfile get(Context context) {
         boolean isGeckoApp = false;
         try {
             isGeckoApp = context instanceof GeckoApp;
         } catch (NoClassDefFoundError ex) {}
 
         if (isGeckoApp) {
             // Check for a cached profile on this context already
@@ -107,23 +149,31 @@ public final class GeckoProfile {
         final String args;
         if (context instanceof Activity) {
             args = ((Activity) context).getIntent().getStringExtra("args");
         } else {
             args = null;
         }
 
         if (GuestSession.shouldUse(context, args)) {
-            GeckoProfile p = GeckoProfile.getOrCreateGuestProfile(context);
+            final GeckoProfile p = GeckoProfile.getOrCreateGuestProfile(context);
             if (isGeckoApp) {
                 ((GeckoApp) context).mProfile = p;
             }
             return p;
         }
 
+        final GeckoProfile fromArgs = GeckoProfile.getFromArgs(context, args);
+        if (fromArgs != null) {
+            if (isGeckoApp) {
+                ((GeckoApp) context).mProfile = fromArgs;
+            }
+            return fromArgs;
+        }
+
         if (isGeckoApp) {
             final GeckoApp geckoApp = (GeckoApp) context;
             String defaultProfileName;
             try {
                 defaultProfileName = geckoApp.getDefaultProfileName();
             } catch (NoMozillaDirectoryException e) {
                 // If this failed, we're screwed. But there are so many callers that
                 // we'll just throw a RuntimeException.