Bug 1062377 - Try loading profile.ini in background; r=mfinkle r=rnewman
authorJim Chen <nchen@mozilla.com>
Tue, 30 Sep 2014 18:19:25 -0400
changeset 208070 b37f591b400e4ce5a1a37bf0d9d18f9c605641d7
parent 208069 da1b3063095cf09a81901b0cd9e2aecbc7d9180e
child 208071 c8c23bb480ec0aabdfcadb2f557a3bfcf96b3ec3
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersmfinkle, rnewman
bugs1062377
milestone35.0a1
Bug 1062377 - Try loading profile.ini in background; r=mfinkle r=rnewman We can move our profile accessing code to later in the startup process. The benefit of that is in early startup, we can prefetch the profile.ini file in the background and not block the UI thread
mobile/android/base/GeckoApp.java
mobile/android/base/db/SuggestedSites.java
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -1158,17 +1158,23 @@ public abstract class GeckoApp
                 }
 
                 if (profileName != null || profilePath != null) {
                     mProfile = GeckoProfile.get(this, profileName, profilePath);
                 }
             }
         }
 
-        BrowserDB.initialize(getProfile().getName());
+        // Speculatively pre-fetch the profile in the background.
+        ThreadUtils.postToBackgroundThread(new Runnable() {
+            @Override
+            public void run() {
+                getProfile();
+            }
+        });
 
         // Workaround for <http://code.google.com/p/android/issues/detail?id=20915>.
         try {
             Class.forName("android.os.AsyncTask");
         } catch (ClassNotFoundException e) {}
 
         MemoryMonitor.getInstance().init(getApplicationContext());
 
@@ -1420,16 +1426,18 @@ public abstract class GeckoApp
         // Start migrating as early as possible, can do this in
         // parallel with Gecko load.
         checkMigrateProfile();
 
         Tabs.registerOnTabsChangedListener(this);
 
         initializeChrome();
 
+        BrowserDB.initialize(getProfile().getName());
+
         // If we are doing a restore, read the session data and send it to Gecko
         if (!mIsRestoringActivity) {
             String restoreMessage = null;
             if (mShouldRestore) {
                 try {
                     // restoreSessionTabs() will create simple tab stubs with the
                     // URL and title for each page, but we also need to restore
                     // session history. restoreSessionTabs() will inject the IDs
@@ -1642,17 +1650,17 @@ public abstract class GeckoApp
             restoreData.put("sessionString", sessionString);
             return restoreData.toString();
 
         } catch (JSONException e) {
             throw new SessionRestoreException(e);
         }
     }
 
-    public GeckoProfile getProfile() {
+    public synchronized GeckoProfile getProfile() {
         // fall back to default profile if we didn't load a specific one
         if (mProfile == null) {
             mProfile = GeckoProfile.get(this);
         }
         return mProfile;
     }
 
     /**
--- a/mobile/android/base/db/SuggestedSites.java
+++ b/mobile/android/base/db/SuggestedSites.java
@@ -152,33 +152,39 @@ public class SuggestedSites {
             json.put(JSON_KEY_BG_COLOR, bgColor);
 
             return json;
         }
     }
 
     final Context context;
     final Distribution distribution;
-    final File file;
+    private File cachedFile;
     private Map<String, Site> cachedSites;
     private Set<String> cachedBlacklist;
 
     public SuggestedSites(Context appContext) {
         this(appContext, null);
     }
 
     public SuggestedSites(Context appContext, Distribution distribution) {
-        this(appContext, distribution,
-             GeckoProfile.get(appContext).getFile(FILENAME));
+        this(appContext, distribution, null);
     }
 
     public SuggestedSites(Context appContext, Distribution distribution, File file) {
         this.context = appContext;
         this.distribution = distribution;
-        this.file = file;
+        this.cachedFile = file;
+    }
+
+    synchronized File getFile() {
+        if (cachedFile == null) {
+            cachedFile = GeckoProfile.get(context).getFile(FILENAME);
+        }
+        return cachedFile;
     }
 
     private static boolean isNewLocale(Context context, Locale requestedLocale) {
         final SharedPreferences prefs = GeckoSharedPrefs.forProfile(context);
 
         String locale = prefs.getString(PREF_SUGGESTED_SITES_LOCALE, null);
         if (locale == null) {
             // Initialize config with the current locale
@@ -301,16 +307,17 @@ public class SuggestedSites {
                     sites = new LinkedHashMap<String, Site>();
                 }
                 sites.putAll(loadFromResource());
 
                 // Update cached list of sites.
                 setCachedSites(sites);
 
                 // Save the result to disk.
+                final File file = getFile();
                 synchronized (file) {
                     saveSites(file, sites);
                 }
 
                 // Then notify any active loaders about the changes.
                 final ContentResolver cr = context.getContentResolver();
                 cr.notifyChange(BrowserContract.SuggestedSites.CONTENT_URI, null);
             }
@@ -344,16 +351,17 @@ public class SuggestedSites {
             }
         }
 
         return null;
     }
 
     private Map<String, Site> loadFromProfile() {
         try {
+            final File file = getFile();
             synchronized (file) {
                 return loadSites(file);
             }
         } catch (FileNotFoundException e) {
             maybeWaitForDistribution();
         } catch (IOException e) {
             // Fall through, return null.
         }
@@ -457,17 +465,17 @@ public class SuggestedSites {
             return cursor;
         }
 
         final boolean isNewLocale = isNewLocale(context, locale);
 
         // Force the suggested sites file in profile dir to be re-generated
         // if the locale has changed.
         if (isNewLocale) {
-            file.delete();
+            getFile().delete();
         }
 
         if (cachedSites == null || isNewLocale) {
             Log.d(LOGTAG, "No cached sites, refreshing.");
             refresh();
         }
 
         // Return empty cursor if there was an error when