Bug 1234629 - Part 0: Make Distribution look in /data/data/$PACKAGE/distribution last. r=rnewman a=sylvestre
☠☠ backed out by 927f615cf2c1 ☠ ☠
authorNick Alexander <nalexander@mozilla.com>
Tue, 08 Mar 2016 16:09:56 -0800
changeset 338848 b49a3c403769bb617ec23d82fcfeb1dc1c1533ff
parent 338847 45a841d2c188cb3dd958b0e0611d910ec1abffa8
child 338849 07f3e1db69aa48fba143ea8f1790ecbcd04abe00
push id12588
push userbmo:rail@mozilla.com
push dateThu, 10 Mar 2016 01:58:26 +0000
reviewersrnewman, sylvestre
bugs1234629
milestone46.0
Bug 1234629 - Part 0: Make Distribution look in /data/data/$PACKAGE/distribution last. r=rnewman a=sylvestre Call a distribution in /data/data/$PACKAGE/distribution a "data distribution". Right now we read data distributions only in response to writing them via another code path (extracting from APK, or downloading). We don't recognize a data distribution in the same way that we recognize a system distribution (in /system/.../distribution) in the Java code, simply because we don't look for it; and I haven't investigated, but I think that Gecko may in fact recognize a data distribution in this case. This patch simply recognizes data distributions after looking for other distributions. That way data distributions written by the bouncer APK are recognized and initialized, but not given precedence over other distribution channels. MozReview-Commit-ID: 4uFxu31lA64
mobile/android/base/java/org/mozilla/gecko/distribution/Distribution.java
mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testDistribution.java
--- a/mobile/android/base/java/org/mozilla/gecko/distribution/Distribution.java
+++ b/mobile/android/base/java/org/mozilla/gecko/distribution/Distribution.java
@@ -458,21 +458,23 @@ public class Distribution {
         // We've done the work once; don't do it again.
         if (this.state == STATE_SET) {
             // Note that we don't compute the distribution directory.
             // Call `ensureDistributionDir` if you need it.
             runReadyQueue();
             return true;
         }
 
-        // We try the install intent, then the APK, then the system directory.
+        // We try to find the install intent, then the APK, then the system directory, and finally
+        // an already copied distribution.  Already copied might originate from the bouncer APK.
         final boolean distributionSet =
                 checkIntentDistribution(referrer) ||
                 copyAndCheckAPKDistribution() ||
-                checkSystemDistribution();
+                checkSystemDistribution() ||
+                checkDataDistribution();
 
         // If this is our first run -- and thus we weren't already in STATE_NONE or STATE_SET above --
         // and we didn't find a distribution already, then we should hold on to callbacks in case we
         // get a late distribution.
         this.shouldDelayLateCallbacks = !distributionSet;
         this.state = distributionSet ? STATE_SET : STATE_NONE;
         settings.edit().putInt(keyName, this.state).apply();
 
--- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testDistribution.java
+++ b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testDistribution.java
@@ -132,16 +132,18 @@ public class testDistribution extends Co
         String mockPackagePath = getMockPackagePath();
 
         // Wait for any startup-related background distribution shenanigans to
         // finish. This reduces the chance of us racing with startup pref writes.
         waitForBackgroundHappiness();
 
         // Pre-clear distribution pref, run basic preferences and en-US localized preferences Tests
         clearDistributionPref();
+        clearDistributionFromDataData();
+
         setTestLocale("en-US");
         try {
             initDistribution(mockPackagePath);
         } catch(NoSuchElementException e) {
             // TODO: determine why this exception is intermittently thrown
             Log.w(LOGTAG, "NoSuchElementException on first initDistribution -- will retry");
             mSolo.sleep(4000);
             initDistribution(mockPackagePath);
@@ -149,26 +151,29 @@ public class testDistribution extends Co
         checkPreferences();
         checkAndroidPreferences();
         checkLocalizedPreferences("en-US");
         checkSearchPlugin();
         checkAddon();
 
         // Pre-clear distribution pref, and run es-MX localized preferences Test
         clearDistributionPref();
+        clearDistributionFromDataData();
         setTestLocale("es-MX");
         initDistribution(mockPackagePath);
         checkLocalizedPreferences("es-MX");
 
         // Test the (stubbed) download interaction.
         setTestLocale("en-US");
         clearDistributionPref();
+        clearDistributionFromDataData();
         doTestValidReferrerIntent();
 
         clearDistributionPref();
+        clearDistributionFromDataData();
         doTestInvalidReferrerIntent();
     }
 
     private void setOSLocale(Locale locale) {
         Locale.setDefault(locale);
         BrowserLocaleManager.storeAndNotifyOSLocale(GeckoSharedPrefs.forProfile(mActivity), locale);
     }
 
@@ -499,16 +504,32 @@ public class testDistribution extends Co
     private void clearDistributionPref() {
         mAsserter.dumpLog("Clearing distribution pref.");
         SharedPreferences settings = mActivity.getSharedPreferences("GeckoApp", Activity.MODE_PRIVATE);
         String keyName = mActivity.getPackageName() + ".distribution_state";
         settings.edit().remove(keyName).commit();
         TestableDistribution.clearReferrerDescriptorForTesting();
     }
 
+    /**
+     * Clears any distribution found in /data/data.
+     */
+    private void clearDistributionFromDataData() throws Exception {
+        File dataDir = new File(mActivity.getApplicationInfo().dataDir);
+
+        // Recursively delete distribution files that Distribution.init copied to data directory.
+        File distDir = new File(dataDir, "distribution");
+        if (distDir.exists()) {
+            mAsserter.dumpLog("Clearing distribution from " + distDir.getAbsolutePath());
+            delete(distDir);
+        } else {
+            mAsserter.dumpLog("No distribution to clear from " + distDir.getAbsolutePath());
+        }
+    }
+
     @Override
     public void setUp() throws Exception {
         // TODO: Set up the content provider after setting the distribution.
         super.setUp(sBrowserProviderCallable, BrowserContract.AUTHORITY, "browser.db");
     }
 
     private void delete(File file) throws Exception {
       if (file.isDirectory()) {
@@ -523,17 +544,14 @@ public class testDistribution extends Co
     @Override
     public void tearDown() throws Exception {
         File dataDir = new File(mActivity.getApplicationInfo().dataDir);
 
         // Delete mock package from data directory.
         File mockPackage = new File(dataDir, MOCK_PACKAGE);
         mAsserter.ok(mockPackage.delete(), "clean up mock package", "deleted " + mockPackage.getPath());
 
-        // Recursively delete distribution files that Distribution.init copied to data directory.
-        File distDir = new File(dataDir, "distribution");
-        delete(distDir);
-
+        clearDistributionFromDataData();
         clearDistributionPref();
 
         super.tearDown();
     }
 }