Bug 1244944 - Inline ExtendedJSONObject.parseJSONObject. r?rnewman draft
authorNick Alexander <nalexander@mozilla.com>
Wed, 20 Jan 2016 16:40:32 -0800
changeset 327803 9514d4c4a8fcdad570e30b5ff9c45e7721adcfa4
parent 327802 66c12013e1a5eb8f9a26851565a931c38246e76f
child 327804 1c362221f096ab0da8c338fae1dff2cf8e043fee
push id10307
push usernalexander@mozilla.com
push dateTue, 02 Feb 2016 01:08:05 +0000
reviewersrnewman
bugs1244944
milestone47.0a1
Bug 1244944 - Inline ExtendedJSONObject.parseJSONObject. r?rnewman
mobile/android/services/src/main/java/org/mozilla/gecko/fxa/authenticator/AccountPickler.java
mobile/android/services/src/main/java/org/mozilla/gecko/sync/CryptoRecord.java
mobile/android/services/src/main/java/org/mozilla/gecko/sync/ExtendedJSONObject.java
mobile/android/services/src/main/java/org/mozilla/gecko/sync/SyncConfiguration.java
mobile/android/services/src/main/java/org/mozilla/gecko/sync/Utils.java
mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/MozResponse.java
mobile/android/services/src/main/java/org/mozilla/gecko/sync/repositories/RepositorySessionBundle.java
mobile/android/tests/background/junit4/src/org/mozilla/android/sync/net/test/TestMetaGlobal.java
mobile/android/tests/background/junit4/src/org/mozilla/android/sync/test/TestCryptoRecord.java
mobile/android/tests/background/junit4/src/org/mozilla/android/sync/test/TestRecord.java
mobile/android/tests/background/junit4/src/org/mozilla/gecko/sync/stage/test/TestEnsureCrypto5KeysStage.java
mobile/android/tests/background/junit4/src/org/mozilla/gecko/sync/stage/test/TestFetchMetaGlobalStage.java
mobile/android/tests/background/junit4/src/org/mozilla/gecko/sync/test/TestInfoCollections.java
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/authenticator/AccountPickler.java
+++ b/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/authenticator/AccountPickler.java
@@ -169,17 +169,17 @@ public class AccountPickler {
     final String jsonString = Utils.readFile(context, filename);
     if (jsonString == null) {
       Logger.info(LOG_TAG, "Pickle file '" + filename + "' not found; aborting.");
       return null;
     }
 
     ExtendedJSONObject json = null;
     try {
-      json = ExtendedJSONObject.parseJSONObject(jsonString);
+      json = new ExtendedJSONObject(jsonString);
     } catch (Exception e) {
       Logger.warn(LOG_TAG, "Got exception reading pickle file '" + filename + "'; aborting.", e);
       return null;
     }
 
     final UnpickleParams params;
     try {
       params = UnpickleParams.fromJSON(json);
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/CryptoRecord.java
+++ b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/CryptoRecord.java
@@ -83,17 +83,18 @@ public class CryptoRecord extends Record
     if (payload == null) {
       throw new IllegalArgumentException(
           "No payload provided to CryptoRecord constructor.");
     }
     this.payload = payload;
   }
 
   public CryptoRecord(String jsonString) throws IOException, ParseException, NonObjectJSONException {
-    this(ExtendedJSONObject.parseJSONObject(jsonString));
+
+    this(new ExtendedJSONObject(jsonString));
   }
 
   /**
    * Create a new CryptoRecord with the same metadata as an existing record.
    *
    * @param source
    */
   public CryptoRecord(Record source) {
@@ -138,17 +139,17 @@ public class CryptoRecord extends Record
 
   // TODO: defensive programming.
   public static CryptoRecord fromJSONRecord(ExtendedJSONObject jsonRecord)
       throws IOException, ParseException, NonObjectJSONException, RecordParseException {
     String id                  = (String) jsonRecord.get(KEY_ID);
     String collection          = (String) jsonRecord.get(KEY_COLLECTION);
     String jsonEncodedPayload  = (String) jsonRecord.get(KEY_PAYLOAD);
 
-    ExtendedJSONObject payload = ExtendedJSONObject.parseJSONObject(jsonEncodedPayload);
+    ExtendedJSONObject payload = new ExtendedJSONObject(jsonEncodedPayload);
 
     CryptoRecord record = new CryptoRecord(payload);
     record.guid         = id;
     record.collection   = collection;
     if (jsonRecord.containsKey(KEY_MODIFIED)) {
       Long timestamp = jsonRecord.getTimestamp(KEY_MODIFIED);
       if (timestamp == null) {
         throw new RecordParseException("timestamp could not be parsed");
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/ExtendedJSONObject.java
+++ b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/ExtendedJSONObject.java
@@ -121,54 +121,26 @@ public class ExtendedJSONObject {
     if (o instanceof JSONArray) {
       return (JSONArray) o;
     }
 
     throw new NonArrayJSONException("value must be a JSON array");
   }
 
   /**
-   * Helper method to get a JSON object from a stream.
-   *
-   * @param in input {@link Reader}.
-   * @throws ParseException
-   * @throws IOException
-   * @throws NonArrayJSONException if the object is valid JSON, but not an object.
-   */
-  public static ExtendedJSONObject parseJSONObject(Reader in)
-      throws IOException, ParseException, NonObjectJSONException {
-    return new ExtendedJSONObject(in);
-  }
-
-  /**
-   * Helper method to get a JSON object from a string.
-   * <p>
-   * You should prefer the stream interface {@link #parseJSONObject(Reader)}.
-   *
-   * @param jsonString input.
-   * @throws ParseException
-   * @throws IOException
-   * @throws NonObjectJSONException if the object is valid JSON, but not an object.
-   */
-  public static ExtendedJSONObject parseJSONObject(String jsonString)
-      throws IOException, ParseException, NonObjectJSONException {
-    return new ExtendedJSONObject(jsonString);
-  }
-
-  /**
    * Helper method to get a JSON object from a UTF-8 byte array.
    *
    * @param in UTF-8 bytes.
    * @throws ParseException
    * @throws NonObjectJSONException if the object is valid JSON, but not an object.
    * @throws IOException
    */
   public static ExtendedJSONObject parseUTF8AsJSONObject(byte[] in)
       throws ParseException, NonObjectJSONException, IOException {
-    return parseJSONObject(new String(in, "UTF-8"));
+    return new ExtendedJSONObject(new String(in, "UTF-8"));
   }
 
   public ExtendedJSONObject() {
     this.object = new JSONObject();
   }
 
   public ExtendedJSONObject(JSONObject o) {
     this.object = o;
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/SyncConfiguration.java
+++ b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/SyncConfiguration.java
@@ -166,17 +166,17 @@ public class SyncConfiguration {
    *         or null otherwise.
    */
   protected static Set<String> getEngineNamesFromPref(SharedPreferences prefs, String pref) {
     final String json = prefs.getString(pref, null);
     if (json == null) {
       return null;
     }
     try {
-      final ExtendedJSONObject o = ExtendedJSONObject.parseJSONObject(json);
+      final ExtendedJSONObject o = new ExtendedJSONObject(json);
       return new HashSet<String>(o.keySet());
     } catch (Exception e) {
       return null;
     }
   }
 
   /**
    * Returns the set of engine names that the user has enabled. If none
@@ -207,17 +207,17 @@ public class SyncConfiguration {
    *         engine name, Value is the new sync state.
    */
   public static Map<String, Boolean> getUserSelectedEngines(SharedPreferences prefs) {
     String json = prefs.getString(PREF_USER_SELECTED_ENGINES_TO_SYNC, null);
     if (json == null) {
       return null;
     }
     try {
-      ExtendedJSONObject o = ExtendedJSONObject.parseJSONObject(json);
+      ExtendedJSONObject o = new ExtendedJSONObject(json);
       Map<String, Boolean> map = new HashMap<String, Boolean>();
       for (Entry<String, Object> e : o.entrySet()) {
         String key = e.getKey();
         Boolean value = (Boolean) e.getValue();
         map.put(key, value);
         // Forms depends on history. Add forms if history is selected.
         if ("history".equals(key)) {
           map.put("forms", value);
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/Utils.java
+++ b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/Utils.java
@@ -29,19 +29,16 @@ import org.mozilla.apache.commons.codec.
 import org.mozilla.apache.commons.codec.binary.Base64;
 import org.mozilla.gecko.background.common.log.Logger;
 import org.mozilla.gecko.background.nativecode.NativeCrypto;
 import org.mozilla.gecko.sync.setup.Constants;
 
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.os.Bundle;
-import android.text.Spannable;
-import android.text.Spanned;
-import android.text.style.ClickableSpan;
 
 public class Utils {
 
   private static final String LOG_TAG = "Utils";
 
   private static final SecureRandom sharedSecureRandom = new SecureRandom();
 
   // See <http://developer.android.com/reference/android/content/Context.html#getSharedPreferences%28java.lang.String,%20int%29>
@@ -420,24 +417,24 @@ public class Utils {
     if (toSyncString == null && toSkipString == null) {
       return knownStageNames;
     }
 
     ArrayList<String> toSync = null;
     ArrayList<String> toSkip = null;
     if (toSyncString != null) {
       try {
-        toSync = new ArrayList<String>(ExtendedJSONObject.parseJSONObject(toSyncString).keySet());
+        toSync = new ArrayList<String>(new ExtendedJSONObject(toSyncString).keySet());
       } catch (Exception e) {
         Logger.warn(LOG_TAG, "Got exception parsing stages to sync: '" + toSyncString + "'.", e);
       }
     }
     if (toSkipString != null) {
       try {
-        toSkip = new ArrayList<String>(ExtendedJSONObject.parseJSONObject(toSkipString).keySet());
+        toSkip = new ArrayList<String>(new ExtendedJSONObject(toSkipString).keySet());
       } catch (Exception e) {
         Logger.warn(LOG_TAG, "Got exception parsing stages to skip: '" + toSkipString + "'.", e);
       }
     }
 
     Logger.info(LOG_TAG, "Asked to sync '" + Utils.toCommaSeparatedString(toSync) +
                          "' and to skip '" + Utils.toCommaSeparatedString(toSkip) + "'.");
     return getStagesToSync(knownStageNames, toSync, toSkip);
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/MozResponse.java
+++ b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/MozResponse.java
@@ -91,28 +91,28 @@ public class MozResponse {
    * @throws IOException
    * @throws ParseException
    * @throws NonObjectJSONException
    */
   public ExtendedJSONObject jsonObjectBody() throws IllegalStateException, IOException,
                                  ParseException, NonObjectJSONException {
     if (body != null) {
       // Do it from the cached String.
-      return ExtendedJSONObject.parseJSONObject(body);
+      return new ExtendedJSONObject(body);
     }
 
     HttpEntity entity = this.response.getEntity();
     if (entity == null) {
       throw new IOException("no entity");
     }
 
     InputStream content = entity.getContent();
     try {
       Reader in = new BufferedReader(new InputStreamReader(content, "UTF-8"));
-      return ExtendedJSONObject.parseJSONObject(in);
+      return new ExtendedJSONObject(in);
     } finally {
       content.close();
     }
   }
 
   protected boolean hasHeader(String h) {
     return this.response.containsHeader(h);
   }
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/repositories/RepositorySessionBundle.java
+++ b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/repositories/RepositorySessionBundle.java
@@ -14,17 +14,18 @@ import org.mozilla.gecko.sync.NonObjectJ
 public class RepositorySessionBundle {
   public static final String LOG_TAG = RepositorySessionBundle.class.getSimpleName();
 
   protected static final String JSON_KEY_TIMESTAMP = "timestamp";
 
   protected final ExtendedJSONObject object;
 
   public RepositorySessionBundle(String jsonString) throws IOException, ParseException, NonObjectJSONException {
-    object = ExtendedJSONObject.parseJSONObject(jsonString);
+
+    object = new ExtendedJSONObject(jsonString);
   }
 
   public RepositorySessionBundle(long lastSyncTimestamp) {
     object = new ExtendedJSONObject();
     this.setTimestamp(lastSyncTimestamp);
   }
 
   public long getTimestamp() {
--- a/mobile/android/tests/background/junit4/src/org/mozilla/android/sync/net/test/TestMetaGlobal.java
+++ b/mobile/android/tests/background/junit4/src/org/mozilla/android/sync/net/test/TestMetaGlobal.java
@@ -314,17 +314,17 @@ public class TestMetaGlobal {
 
     final AtomicBoolean mgUploaded = new AtomicBoolean(false);
     final MetaGlobal uploadedMg = new MetaGlobal(null, null);
 
     MockServer server = new MockServer() {
       public void handle(Request request, Response response) {
         if (request.getMethod().equals("PUT")) {
           try {
-            ExtendedJSONObject body = ExtendedJSONObject.parseJSONObject(request.getContent());
+            ExtendedJSONObject body = new ExtendedJSONObject(request.getContent());
             System.out.println(body.toJSONString());
             assertTrue(body.containsKey("payload"));
             assertFalse(body.containsKey("default"));
 
             CryptoRecord rec = CryptoRecord.fromJSONRecord(body);
             uploadedMg.setFromRecord(rec);
             mgUploaded.set(true);
           } catch (Exception e) {
--- a/mobile/android/tests/background/junit4/src/org/mozilla/android/sync/test/TestCryptoRecord.java
+++ b/mobile/android/tests/background/junit4/src/org/mozilla/android/sync/test/TestCryptoRecord.java
@@ -31,17 +31,23 @@ import static org.junit.Assert.assertTru
 
 @RunWith(TestRunner.class)
 public class TestCryptoRecord {
   String base64EncryptionKey = "9K/wLdXdw+nrTtXo4ZpECyHFNr4d7aYHqeg3KW9+m6Q=";
   String base64HmacKey = "MMntEfutgLTc8FlTLQFms8/xMPmCldqPlq/QQXEjx70=";
 
   @Test
   public void testBaseCryptoRecordEncrypt() throws IOException, ParseException, NonObjectJSONException, CryptoException {
-    ExtendedJSONObject clearPayload = ExtendedJSONObject.parseJSONObject("{\"id\":\"5qRsgXWRJZXr\",\"title\":\"Index of file:///Users/jason/Library/Application Support/Firefox/Profiles/ksgd7wpk.LocalSyncServer/weave/logs/\",\"histUri\":\"file:///Users/jason/Library/Application%20Support/Firefox/Profiles/ksgd7wpk.LocalSyncServer/weave/logs/\",\"visits\":[{\"type\":1,\"date\":1319149012372425}]}");
+
+    ExtendedJSONObject clearPayload = new ExtendedJSONObject("{\"id\":\"5qRsgXWRJZXr\"," +
+            "\"title\":\"Index of file:///Users/jason/Library/Application " +
+            "Support/Firefox/Profiles/ksgd7wpk.LocalSyncServer/weave/logs/\"," +
+            "\"histUri\":\"file:///Users/jason/Library/Application%20Support/Firefox/Profiles" +
+            "/ksgd7wpk.LocalSyncServer/weave/logs/\",\"visits\":[{\"type\":1," +
+            "\"date\":1319149012372425}]}");
 
     CryptoRecord record = new CryptoRecord();
     record.payload = clearPayload;
     String expectedGUID = "5qRsgXWRJZXr";
     record.guid = expectedGUID;
     record.keyBundle = KeyBundle.fromBase64EncodedKeys(base64EncryptionKey, base64HmacKey);
     record.encrypt();
     assertTrue(record.payload.get("title") == null);
@@ -251,17 +257,17 @@ public class TestCryptoRecord {
     // We don't necessarily produce exactly the same JSON but we do have the same values.
     ExtendedJSONObject expectedJson = new ExtendedJSONObject(expectedDecryptedText);
     assertEquals(expectedJson.get("id"), decrypted.payload.get("id"));
     assertEquals(expectedJson.get("default"), decrypted.payload.get("default"));
     assertEquals(expectedJson.get("collection"), decrypted.payload.get("collection"));
     assertEquals(expectedJson.get("collections"), decrypted.payload.get("collections"));
 
     // Check that the extracted keys were as expected.
-    JSONArray keys = ExtendedJSONObject.parseJSONObject(decrypted.payload.toJSONString()).getArray("default");
+    JSONArray keys = new ExtendedJSONObject(decrypted.payload.toJSONString()).getArray("default");
     KeyBundle keyBundle = KeyBundle.fromBase64EncodedKeys((String)keys.get(0), (String)keys.get(1));
 
     assertArrayEquals(Base64.decodeBase64(expectedBase64EncryptionKey.getBytes("UTF-8")), keyBundle.getEncryptionKey());
     assertArrayEquals(Base64.decodeBase64(expectedBase64HmacKey.getBytes("UTF-8")), keyBundle.getHMACKey());
   }
 
   @Test
   public void testTTL() throws UnsupportedEncodingException, CryptoException {
--- a/mobile/android/tests/background/junit4/src/org/mozilla/android/sync/test/TestRecord.java
+++ b/mobile/android/tests/background/junit4/src/org/mozilla/android/sync/test/TestRecord.java
@@ -188,28 +188,28 @@ public class TestRecord {
 
   @SuppressWarnings("static-method")
   @Test
   public void testTabParsing() throws Exception {
     String json = "{\"title\":\"mozilla-central mozilla/browser/base/content/syncSetup.js\"," +
                   " \"urlHistory\":[\"http://mxr.mozilla.org/mozilla-central/source/browser/base/content/syncSetup.js#72\"]," +
                   " \"icon\":\"http://mxr.mozilla.org/mxr.png\"," +
                   " \"lastUsed\":\"1306374531\"}";
-    Tab tab = TabsRecord.tabFromJSONObject(ExtendedJSONObject.parseJSONObject(json).object);
+    Tab tab = TabsRecord.tabFromJSONObject(new ExtendedJSONObject(json).object);
 
     assertEquals("mozilla-central mozilla/browser/base/content/syncSetup.js", tab.title);
     assertEquals("http://mxr.mozilla.org/mxr.png", tab.icon);
     assertEquals("http://mxr.mozilla.org/mozilla-central/source/browser/base/content/syncSetup.js#72", tab.history.get(0));
     assertEquals(1306374531000L, tab.lastUsed);
 
     String zeroJSON = "{\"title\":\"a\"," +
         " \"urlHistory\":[\"http://example.com\"]," +
         " \"icon\":\"\"," +
         " \"lastUsed\":0}";
-    Tab zero = TabsRecord.tabFromJSONObject(ExtendedJSONObject.parseJSONObject(zeroJSON).object);
+    Tab zero = TabsRecord.tabFromJSONObject(new ExtendedJSONObject(zeroJSON).object);
 
     assertEquals("a", zero.title);
     assertEquals("", zero.icon);
     assertEquals("http://example.com", zero.history.get(0));
     assertEquals(0L, zero.lastUsed);
   }
 
   @SuppressWarnings({ "unchecked", "static-method" })
--- a/mobile/android/tests/background/junit4/src/org/mozilla/gecko/sync/stage/test/TestEnsureCrypto5KeysStage.java
+++ b/mobile/android/tests/background/junit4/src/org/mozilla/gecko/sync/stage/test/TestEnsureCrypto5KeysStage.java
@@ -82,17 +82,17 @@ public class TestEnsureCrypto5KeysStage 
       public void resetStagesByName(Collection<String> names) {
         calledResetStages = true;
         stagesReset = names;
       }
     };
     session.config.setClusterURL(new URI(TEST_CLUSTER_URL));
 
     // Set info collections to not have crypto.
-    final ExtendedJSONObject noCrypto = ExtendedJSONObject.parseJSONObject(TEST_JSON_NO_CRYPTO);
+    final ExtendedJSONObject noCrypto = new ExtendedJSONObject(TEST_JSON_NO_CRYPTO);
     session.config.infoCollections = new InfoCollections(noCrypto);
     calledResetStages = false;
     stagesReset = null;
   }
 
   public void doSession(MockServer server) {
     data.startHTTPServer(server);
     try {
@@ -108,17 +108,18 @@ public class TestEnsureCrypto5KeysStage 
       });
     } finally {
     data.stopHTTPServer();
     }
   }
 
   @Test
   public void testDownloadUsesPersisted() throws Exception {
-    session.config.infoCollections = new InfoCollections(ExtendedJSONObject.parseJSONObject(TEST_JSON_OLD_CRYPTO));
+    session.config.infoCollections = new InfoCollections(new ExtendedJSONObject
+            (TEST_JSON_OLD_CRYPTO));
     session.config.persistedCryptoKeys().persistLastModified(System.currentTimeMillis());
 
     assertNull(session.config.collectionKeys);
     final CollectionKeys keys = CollectionKeys.generateCollectionKeys();
     keys.setDefaultKeyBundle(syncKeyBundle);
     session.config.persistedCryptoKeys().persistKeys(keys);
 
     MockServer server = new MockServer() {
@@ -131,17 +132,17 @@ public class TestEnsureCrypto5KeysStage 
 
     assertTrue(callback.calledSuccess);
     assertNotNull(session.config.collectionKeys);
     assertTrue(CollectionKeys.differences(session.config.collectionKeys, keys).isEmpty());
   }
 
   @Test
   public void testDownloadFetchesNew() throws Exception {
-    session.config.infoCollections = new InfoCollections(ExtendedJSONObject.parseJSONObject(TEST_JSON_NEW_CRYPTO));
+    session.config.infoCollections = new InfoCollections(new ExtendedJSONObject(TEST_JSON_NEW_CRYPTO));
     session.config.persistedCryptoKeys().persistLastModified(System.currentTimeMillis());
 
     assertNull(session.config.collectionKeys);
     final CollectionKeys keys = CollectionKeys.generateCollectionKeys();
     keys.setDefaultKeyBundle(syncKeyBundle);
     session.config.persistedCryptoKeys().persistKeys(keys);
 
     MockServer server = new MockServer() {
@@ -167,17 +168,17 @@ public class TestEnsureCrypto5KeysStage 
   /**
    * Change the default key but keep one collection key the same. Should reset
    * all but that one collection.
    */
   @Test
   public void testDownloadResetsOnDifferentDefaultKey() throws Exception {
     String TEST_COLLECTION = "bookmarks";
 
-    session.config.infoCollections = new InfoCollections(ExtendedJSONObject.parseJSONObject(TEST_JSON_NEW_CRYPTO));
+    session.config.infoCollections = new InfoCollections(new ExtendedJSONObject(TEST_JSON_NEW_CRYPTO));
     session.config.persistedCryptoKeys().persistLastModified(System.currentTimeMillis());
 
     KeyBundle keyBundle = KeyBundle.withRandomKeys();
     assertNull(session.config.collectionKeys);
     final CollectionKeys keys = CollectionKeys.generateCollectionKeys();
     keys.setKeyBundleForCollection(TEST_COLLECTION, keyBundle);
     session.config.persistedCryptoKeys().persistKeys(keys);
     keys.setDefaultKeyBundle(syncKeyBundle); // Change the default key bundle, but keep "bookmarks" the same.
@@ -207,17 +208,17 @@ public class TestEnsureCrypto5KeysStage 
     assertTrue(allButCollection.containsAll(stagesReset));
     assertTrue(callback.calledError);
   }
 
   @Test
   public void testDownloadResetsEngineOnDifferentKey() throws Exception {
     final String TEST_COLLECTION = "history";
 
-    session.config.infoCollections = new InfoCollections(ExtendedJSONObject.parseJSONObject(TEST_JSON_NEW_CRYPTO));
+    session.config.infoCollections = new InfoCollections(new ExtendedJSONObject(TEST_JSON_NEW_CRYPTO));
     session.config.persistedCryptoKeys().persistLastModified(System.currentTimeMillis());
 
     assertNull(session.config.collectionKeys);
     final CollectionKeys keys = CollectionKeys.generateCollectionKeys();
     session.config.persistedCryptoKeys().persistKeys(keys);
     keys.setKeyBundleForCollection(TEST_COLLECTION, syncKeyBundle); // Change one key bundle.
 
     CryptoRecord rec = keys.asCryptoRecord();
--- a/mobile/android/tests/background/junit4/src/org/mozilla/gecko/sync/stage/test/TestFetchMetaGlobalStage.java
+++ b/mobile/android/tests/background/junit4/src/org/mozilla/gecko/sync/stage/test/TestFetchMetaGlobalStage.java
@@ -88,17 +88,17 @@ public class TestFetchMetaGlobalStage {
     calledRequiresUpgrade = false;
     calledProcessMissingMetaGlobal = false;
     calledFreshStart = false;
     calledWipeServer = false;
     calledUploadKeys = false;
     calledResetAllStages = false;
 
     // Set info collections to not have crypto.
-    infoCollections = new InfoCollections(ExtendedJSONObject.parseJSONObject(TEST_INFO_COLLECTIONS_JSON));
+    infoCollections = new InfoCollections(new ExtendedJSONObject(TEST_INFO_COLLECTIONS_JSON));
 
     syncKeyBundle = new KeyBundle(TEST_USERNAME, TEST_SYNC_KEY);
     callback = new MockGlobalSessionCallback();
     session = new MockGlobalSession(TEST_USERNAME, TEST_PASSWORD,
       syncKeyBundle, callback) {
       @Override
       protected void prepareStages() {
         super.prepareStages();
@@ -355,17 +355,17 @@ public class TestFetchMetaGlobalStage {
     final AtomicBoolean mgDownloaded = new AtomicBoolean(false);
     final MetaGlobal uploadedMg = new MetaGlobal(null, null);
 
     MockServer server = new MockServer() {
       @Override
       public void handle(Request request, Response response) {
         if (request.getMethod().equals("PUT")) {
           try {
-            ExtendedJSONObject body = ExtendedJSONObject.parseJSONObject(request.getContent());
+            ExtendedJSONObject body = new ExtendedJSONObject(request.getContent());
             assertTrue(body.containsKey("payload"));
             assertFalse(body.containsKey("default"));
 
             CryptoRecord rec = CryptoRecord.fromJSONRecord(body);
             uploadedMg.setFromRecord(rec);
             mgUploaded.set(true);
           } catch (Exception e) {
             throw new RuntimeException(e);
--- a/mobile/android/tests/background/junit4/src/org/mozilla/gecko/sync/test/TestInfoCollections.java
+++ b/mobile/android/tests/background/junit4/src/org/mozilla/gecko/sync/test/TestInfoCollections.java
@@ -44,39 +44,39 @@ public class TestInfoCollections {
       "}";
 
   @SuppressWarnings("static-method")
   @Test
   public void testSetCountsFromRecord() throws Exception {
     InfoCounts infoCountsEmpty = new InfoCounts(new ExtendedJSONObject("{}"));
     assertEquals(null, infoCountsEmpty.getCount("bookmarks"));
 
-    ExtendedJSONObject record = ExtendedJSONObject.parseJSONObject(TEST_COUNTS_JSON);
+    ExtendedJSONObject record = new ExtendedJSONObject(TEST_COUNTS_JSON);
     InfoCounts infoCountsFull = new InfoCounts(record);
     assertEquals(Integer.valueOf(766), infoCountsFull.getCount("bookmarks"));
     assertEquals(null, infoCountsFull.getCount("notpresent"));
   }
 
 
   @SuppressWarnings("static-method")
   @Test
   public void testSetCollectionsFromRecord() throws Exception {
-    ExtendedJSONObject record = ExtendedJSONObject.parseJSONObject(TEST_COLLECTIONS_JSON);
+    ExtendedJSONObject record = new ExtendedJSONObject(TEST_COLLECTIONS_JSON);
     InfoCollections infoCollections = new InfoCollections(record);
 
     assertEquals(Utils.decimalSecondsToMilliseconds(1.3319567131E9), infoCollections.getTimestamp("history").longValue());
     assertEquals(Utils.decimalSecondsToMilliseconds(1.321E9), infoCollections.getTimestamp("meta").longValue());
     assertEquals(Utils.decimalSecondsToMilliseconds(1.35E9), infoCollections.getTimestamp("tabs").longValue());
     assertNull(infoCollections.getTimestamp("missing"));
   }
 
   @SuppressWarnings("static-method")
   @Test
   public void testUpdateNeeded() throws Exception {
-    ExtendedJSONObject record = ExtendedJSONObject.parseJSONObject(TEST_COLLECTIONS_JSON);
+    ExtendedJSONObject record = new ExtendedJSONObject(TEST_COLLECTIONS_JSON);
     InfoCollections infoCollections = new InfoCollections(record);
 
     long none = -1;
     long past = Utils.decimalSecondsToMilliseconds(1.3E9);
     long same = Utils.decimalSecondsToMilliseconds(1.35E9);
     long future = Utils.decimalSecondsToMilliseconds(1.4E9);