Bug 1392148 - Remove aliases to CommonUtils in util.js draft
authorNicolas Ouellet-Payeur <nicolaso@google.com>
Thu, 24 Aug 2017 22:41:44 -0700
changeset 654558 2bf4a56b1e965535d43fe093508e8ae5b9f5e5b9
parent 652622 2306e153fba9ca55726ffcce889eaca7a479c29f
child 728588 25d35f3cd1019936924b526b57dafdf279f57d40
push id76599
push userbmo:nicolaso@google.com
push dateMon, 28 Aug 2017 23:30:36 +0000
bugs1392148
milestone57.0a1
Bug 1392148 - Remove aliases to CommonUtils in util.js MozReview-Commit-ID: 1fv6AN0TMNW
services/sync/modules-testing/utils.js
services/sync/modules/browserid_identity.js
services/sync/modules/engines.js
services/sync/modules/engines/history.js
services/sync/modules/keys.js
services/sync/modules/policies.js
services/sync/modules/record.js
services/sync/modules/service.js
services/sync/modules/util.js
services/sync/tests/unit/head_helpers.js
services/sync/tests/unit/head_http_server.js
services/sync/tests/unit/test_bookmark_engine.js
services/sync/tests/unit/test_bookmark_smart_bookmarks.js
services/sync/tests/unit/test_bookmark_store.js
services/sync/tests/unit/test_bookmark_tracker.js
services/sync/tests/unit/test_corrupt_keys.js
services/sync/tests/unit/test_fxa_node_reassignment.js
services/sync/tests/unit/test_history_store.js
services/sync/tests/unit/test_history_tracker.js
services/sync/tests/unit/test_hmac_error.js
services/sync/tests/unit/test_httpd_sync_server.js
services/sync/tests/unit/test_interval_triggers.js
services/sync/tests/unit/test_places_guid_downgrade.js
services/sync/tests/unit/test_resource.js
services/sync/tests/unit/test_resource_async.js
services/sync/tests/unit/test_syncstoragerequest.js
services/sync/tests/unit/test_telemetry.js
services/sync/tps/extensions/tps/resource/tps.jsm
toolkit/components/extensions/ExtensionStorageSync.jsm
--- a/services/sync/modules-testing/utils.js
+++ b/services/sync/modules-testing/utils.js
@@ -70,17 +70,17 @@ MockFxaStorageManager.prototype = {
     this.accountData = null;
     return Promise.resolve();
   }
 }
 
 /**
  * First wait >100ms (nsITimers can take up to that much time to fire, so
  * we can account for the timer in delayedAutoconnect) and then two event
- * loop ticks (to account for the Utils.nextTick() in autoConnect).
+ * loop ticks (to account for the CommonUtils.nextTick() in autoConnect).
  */
 this.waitForZeroTimer = function waitForZeroTimer(callback) {
   let ticks = 2;
   function wait() {
     if (ticks) {
       ticks -= 1;
       CommonUtils.nextTick(wait);
       return;
@@ -93,17 +93,17 @@ this.waitForZeroTimer = function waitFor
 this.promiseZeroTimer = function() {
   return new Promise(resolve => {
     waitForZeroTimer(resolve);
   });
 }
 
 this.promiseNamedTimer = function(wait, thisObj, name) {
   return new Promise(resolve => {
-    Utils.namedTimer(resolve, wait, thisObj, name);
+    CommonUtils.namedTimer(resolve, wait, thisObj, name);
   });
 }
 
 // Return an identity configuration suitable for testing with our identity
 // providers.  |overrides| can specify overrides for any default values.
 // |server| is optional, but if specified, will be used to form the cluster
 // URL for the FxA identity.
 this.makeIdentityConfig = function(overrides) {
--- a/services/sync/modules/browserid_identity.js
+++ b/services/sync/modules/browserid_identity.js
@@ -212,17 +212,17 @@ this.BrowserIDManager.prototype = {
         this._shouldHaveSyncKeyBundle = true; // and we should actually have one...
         this.whenReadyToAuthenticate.resolve();
         this._log.info("Background fetch for key bundle done");
         Weave.Status.login = LOGIN_SUCCEEDED;
         if (isInitialSync) {
           this._log.info("Doing initial sync actions");
           Svc.Prefs.set("firstSync", "resetClient");
           Services.obs.notifyObservers(null, "weave:service:setup-complete");
-          Weave.Utils.nextTick(Weave.Service.sync, Weave.Service);
+          CommonUtils.nextTick(Weave.Service.sync, Weave.Service);
         }
       }).catch(authErr => {
         // report what failed...
         this._log.error("Background fetch for key bundle failed", authErr);
         this._shouldHaveSyncKeyBundle = true; // but we probably don't have one...
         this.whenReadyToAuthenticate.reject(authErr);
       });
       // and we are done - the fetch continues on in the background...
@@ -604,17 +604,17 @@ this.BrowserIDManager.prototype = {
       })
       .then(token => {
         // TODO: Make it be only 80% of the duration, so refresh the token
         // before it actually expires. This is to avoid sync storage errors
         // otherwise, we get a nasty notification bar briefly. Bug 966568.
         token.expiration = this._now() + (token.duration * 1000) * 0.80;
         if (!this._syncKeyBundle) {
           // We are given kA/kB as hex.
-          this._syncKeyBundle = deriveKeyBundle(Utils.hexToBytes(userData.kB));
+          this._syncKeyBundle = deriveKeyBundle(CommonUtils.hexToBytes(userData.kB));
         }
         return token;
       })
       .catch(err => {
         // TODO: unify these errors - we need to handle errors thrown by
         // both tokenserverclient and hawkclient.
         // A tokenserver error thrown based on a bad response.
         if (err.response && err.response.status === 401) {
--- a/services/sync/modules/engines.js
+++ b/services/sync/modules/engines.js
@@ -13,16 +13,17 @@ this.EXPORTED_SYMBOLS = [
 
 var {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/JSONFile.jsm");
 Cu.import("resource://gre/modules/Log.jsm");
 Cu.import("resource://services-common/async.js");
 Cu.import("resource://services-common/observers.js");
+Cu.import("resource://services-common/utils.js");
 Cu.import("resource://services-sync/constants.js");
 Cu.import("resource://services-sync/record.js");
 Cu.import("resource://services-sync/resource.js");
 Cu.import("resource://services-sync/util.js");
 
 XPCOMUtils.defineLazyModuleGetter(this, "fxAccounts",
   "resource://gre/modules/FxAccounts.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "OS",
@@ -882,17 +883,17 @@ SyncEngine.prototype = {
     return this._toFetch;
   },
   set toFetch(val) {
     // Coerce the array to a string for more efficient comparison.
     if (val + "" == this._toFetch) {
       return;
     }
     this._toFetch = val;
-    Utils.namedTimer(function() {
+    CommonUtils.namedTimer(function() {
       try {
         Async.promiseSpinningly(Utils.jsonSave("toFetch/" + this.name, this, val));
       } catch (error) {
         this._log.error("Failed to read JSON records to fetch", error);
       }
     }, 0, this, "_toFetchDelay");
   },
 
@@ -909,17 +910,17 @@ SyncEngine.prototype = {
     return this._previousFailed;
   },
   set previousFailed(val) {
     // Coerce the array to a string for more efficient comparison.
     if (val + "" == this._previousFailed) {
       return;
     }
     this._previousFailed = val;
-    Utils.namedTimer(function() {
+    CommonUtils.namedTimer(function() {
       Utils.jsonSave("failed/" + this.name, this, val).then(() => {
         this._log.debug("Successfully wrote previousFailed.");
       })
       .catch((error) => {
         this._log.error("Failed to set previousFailed", error);
       });
     }, 0, this, "_previousFailedDelay");
   },
--- a/services/sync/modules/engines/history.js
+++ b/services/sync/modules/engines/history.js
@@ -9,16 +9,17 @@ var Ci = Components.interfaces;
 var Cu = Components.utils;
 var Cr = Components.results;
 
 const HISTORY_TTL = 5184000; // 60 days in milliseconds
 const THIRTY_DAYS_IN_MS = 2592000000; // 30 days in milliseconds
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://services-common/async.js");
+Cu.import("resource://services-common/utils.js");
 Cu.import("resource://services-sync/constants.js");
 Cu.import("resource://services-sync/engines.js");
 Cu.import("resource://services-sync/record.js");
 Cu.import("resource://services-sync/util.js");
 
 XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
                                   "resource://gre/modules/PlacesUtils.jsm");
 
@@ -221,17 +222,17 @@ HistoryStore.prototype = {
    *
    * Throws if an invalid record is encountered (invalid URI, etc.),
    * returns true if the record is to be applied, false otherwise
    * (no visits to add, etc.),
    */
   async _recordToPlaceInfo(record) {
     // Sort out invalid URIs and ones Places just simply doesn't want.
     record.url = PlacesUtils.normalizeToURLOrGUID(record.histUri);
-    record.uri = Utils.makeURI(record.histUri);
+    record.uri = CommonUtils.makeURI(record.histUri);
 
     if (!Utils.checkGUID(record.id)) {
       this._log.warn("Encountered record with invalid GUID: " + record.id);
       return false;
     }
     record.guid = record.id;
 
     if (!PlacesUtils.history.canAddURI(record.uri)) {
--- a/services/sync/modules/keys.js
+++ b/services/sync/modules/keys.js
@@ -5,16 +5,17 @@
 "use strict";
 
 this.EXPORTED_SYMBOLS = [
   "BulkKeyBundle",
 ];
 
 var {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
+Cu.import("resource://services-common/utils.js");
 Cu.import("resource://services-sync/constants.js");
 Cu.import("resource://gre/modules/Log.jsm");
 Cu.import("resource://services-sync/main.js");
 Cu.import("resource://services-sync/util.js");
 
 /**
  * Represents a pair of keys.
  *
@@ -157,12 +158,12 @@ BulkKeyBundle.prototype = {
   },
 
   set keyPairB64(value) {
     if (!Array.isArray(value) || value.length != 2) {
       throw new Error("BulkKeyBundle.keyPairB64 value must be an array of 2 " +
                       "keys.");
     }
 
-    this.encryptionKey  = Utils.safeAtoB(value[0]);
-    this.hmacKey        = Utils.safeAtoB(value[1]);
+    this.encryptionKey  = CommonUtils.safeAtoB(value[0]);
+    this.hmacKey        = CommonUtils.safeAtoB(value[1]);
   },
 };
--- a/services/sync/modules/policies.js
+++ b/services/sync/modules/policies.js
@@ -11,16 +11,17 @@ var {classes: Cc, interfaces: Ci, utils:
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/Log.jsm");
 Cu.import("resource://services-sync/constants.js");
 Cu.import("resource://services-sync/util.js");
 Cu.import("resource://services-common/logmanager.js");
 Cu.import("resource://services-common/async.js");
+Cu.import("resource://services-common/utils.js");
 
 XPCOMUtils.defineLazyModuleGetter(this, "Status",
                                   "resource://services-sync/status.js");
 XPCOMUtils.defineLazyModuleGetter(this, "AddonManager",
                                   "resource://gre/modules/AddonManager.jsm");
 XPCOMUtils.defineLazyServiceGetter(this, "IdleService",
                                    "@mozilla.org/widget/idleservice;1",
                                    "nsIIdleService");
@@ -138,17 +139,17 @@ SyncScheduler.prototype = {
   },
 
   // eslint-disable-next-line complexity
   observe: function observe(subject, topic, data) {
     this._log.trace("Handling " + topic);
     switch (topic) {
       case "weave:engine:score:updated":
         if (Status.login == LOGIN_SUCCEEDED) {
-          Utils.namedTimer(this.calculateScore, SCORE_UPDATE_DELAY, this,
+          CommonUtils.namedTimer(this.calculateScore, SCORE_UPDATE_DELAY, this,
                            "_scoreTimer");
         }
         break;
       case "network:offline-status-changed":
         // Whether online or offline, we'll reschedule syncs
         this._log.trace("Network offline status change: " + data);
         this.checkSyncStatus();
         break;
@@ -293,33 +294,33 @@ SyncScheduler.prototype = {
         // Adjust the interval for future syncs. This won't actually have any
         // effect until the next pending sync (which will happen soon since we
         // were just active.)
         this.adjustSyncInterval();
         break;
       case "active":
         this._log.trace("Received notification that we're back from idle.");
         this.idle = false;
-        Utils.namedTimer(function onBack() {
+        CommonUtils.namedTimer(function onBack() {
           if (this.idle) {
             this._log.trace("... and we're idle again. " +
                             "Ignoring spurious back notification.");
             return;
           }
 
           this._log.trace("Genuine return from idle. Syncing.");
           // Trigger a sync if we have multiple clients.
           if (this.numClients > 1) {
             this.scheduleNextSync(0);
           }
         }, IDLE_OBSERVER_BACK_DELAY, this, "idleDebouncerTimer");
         break;
       case "wake_notification":
         this._log.debug("Woke from sleep.");
-        Utils.nextTick(() => {
+        CommonUtils.nextTick(() => {
           // Trigger a sync if we have multiple clients. We give it 5 seconds
           // incase the network is still in the process of coming back up.
           if (this.numClients > 1) {
             this._log.debug("More than 1 client. Will sync in 5s.");
             this.scheduleNextSync(5000);
           }
         });
         break;
@@ -434,17 +435,17 @@ SyncScheduler.prototype = {
       this.scheduleAtInterval(MASTER_PASSWORD_LOCKED_RETRY_INTERVAL);
       return;
     }
 
     if (!Async.isAppReady()) {
       this._log.debug("Not initiating sync: app is shutting down");
       return;
     }
-    Utils.nextTick(this.service.sync, this.service);
+    CommonUtils.nextTick(this.service.sync, this.service);
   },
 
   /**
    * Set a timer for the next sync
    */
   scheduleNextSync: function scheduleNextSync(interval) {
     // If no interval was specified, use the current sync interval.
     if (interval == null) {
@@ -476,17 +477,17 @@ SyncScheduler.prototype = {
     // Start the sync right away if we're already late.
     if (interval <= 0) {
       this._log.trace("Requested sync should happen right away.");
       this.syncIfMPUnlocked();
       return;
     }
 
     this._log.debug("Next sync in " + interval + " ms.");
-    Utils.namedTimer(this.syncIfMPUnlocked, interval, this, "syncTimer");
+    CommonUtils.namedTimer(this.syncIfMPUnlocked, interval, this, "syncTimer");
 
     // Save the next sync time in-case sync is disabled (logout/offline/etc.)
     this.nextSync = Date.now() + interval;
   },
 
 
   /**
    * Incorporates the backoff/retry logic used in error handling and elective
@@ -510,17 +511,17 @@ SyncScheduler.prototype = {
   *
   * Applications can define the `services.sync.autoconnectDelay` preference
   * to have this called automatically during start-up with the pref value as
   * the argument. Alternatively, they can call it themselves to control when
   * Sync should first start to sync.
   */
   delayedAutoConnect: function delayedAutoConnect(delay) {
     if (this.service._checkSetup() == STATUS_OK) {
-      Utils.namedTimer(this.autoConnect, delay * 1000, this, "_autoTimer");
+      CommonUtils.namedTimer(this.autoConnect, delay * 1000, this, "_autoTimer");
     }
   },
 
   autoConnect: function autoConnect() {
     if (this.service._checkSetup() == STATUS_OK && !this.service._checkSync()) {
       // Schedule a sync based on when a previous sync was scheduled.
       // scheduleNextSync() will do the right thing if that time lies in
       // the past.
@@ -720,32 +721,32 @@ ErrorHandler.prototype = {
       case "weave:service:start-over:finish":
         // ensure we capture any logs between the last sync and the reset completing.
         this.resetFileLog();
         break;
     }
   },
 
   notifyOnNextTick: function notifyOnNextTick(topic) {
-    Utils.nextTick(function() {
+    CommonUtils.nextTick(function() {
       this._log.trace("Notifying " + topic +
                       ". Status.login is " + Status.login +
                       ". Status.sync is " + Status.sync);
       Svc.Obs.notify(topic);
     }, this);
   },
 
   /**
    * Trigger a sync and don't muffle any errors, particularly network errors.
    */
   syncAndReportErrors: function syncAndReportErrors() {
     this._log.debug("Beginning user-triggered sync.");
 
     this.dontIgnoreErrors = true;
-    Utils.nextTick(this.service.sync, this.service);
+    CommonUtils.nextTick(this.service.sync, this.service);
   },
 
   async _dumpAddons() {
     // Just dump the items that sync may be concerned with. Specifically,
     // active extensions that are not hidden.
     let addons = [];
     try {
       addons = await AddonManager.getAddonsByTypes(["extension"]);
@@ -912,17 +913,17 @@ ErrorHandler.prototype = {
 
       // Tell the user that this service has shut down, and drop our syncing
       // frequency dramatically.
       case "hard-eol":
         // Note that both of these alerts should be subservient to future "sign
         // in with your Firefox Account" storage alerts.
         if ((this.currentAlertMode != xwa.code) ||
             (this.earliestNextAlert < Date.now())) {
-          Utils.nextTick(function() {
+          CommonUtils.nextTick(function() {
             Svc.Obs.notify("weave:eol", xwa);
           }, this);
           this._log.error("X-Weave-Alert: " + xwa.code + ": " + xwa.message);
           this.earliestNextAlert = Date.now() + this.MINIMUM_ALERT_INTERVAL_MSEC;
           this.currentAlertMode = xwa.code;
         }
         break;
       default:
--- a/services/sync/modules/record.js
+++ b/services/sync/modules/record.js
@@ -20,16 +20,17 @@ const KEYS_WBO = "keys";
 
 Cu.import("resource://gre/modules/Log.jsm");
 Cu.import("resource://services-sync/constants.js");
 Cu.import("resource://services-sync/keys.js");
 Cu.import("resource://services-sync/main.js");
 Cu.import("resource://services-sync/resource.js");
 Cu.import("resource://services-sync/util.js");
 Cu.import("resource://services-common/async.js");
+Cu.import("resource://services-common/utils.js");
 
 this.WBORecord = function WBORecord(collection, id) {
   this.data = {};
   this.payload = {};
   this.collection = collection;      // Optional.
   this.id = id;                      // Optional.
 }
 WBORecord.prototype = {
@@ -63,17 +64,17 @@ WBORecord.prototype = {
 
     return resource.put(this);
   },
 
   // Take a base URI string, with trailing slash, and return the URI of this
   // WBO based on collection and ID.
   uri(base) {
     if (this.collection && this.id) {
-      let url = Utils.makeURI(base + this.collection + "/" + this.id);
+      let url = CommonUtils.makeURI(base + this.collection + "/" + this.id);
       url.QueryInterface(Ci.nsIURL);
       return url;
     }
     return null;
   },
 
   deserialize: function deserialize(json) {
     this.data = json.constructor.toString() == String ? JSON.parse(json) : json;
@@ -118,17 +119,17 @@ CryptoWrapper.prototype = {
   _logName: "Sync.Record.CryptoWrapper",
 
   ciphertextHMAC: function ciphertextHMAC(keyBundle) {
     let hasher = keyBundle.sha256HMACHasher;
     if (!hasher) {
       throw new Error("Cannot compute HMAC without an HMAC key.");
     }
 
-    return Utils.bytesAsHex(Utils.digestUTF8(this.ciphertext, hasher));
+    return CommonUtils.bytesAsHex(Utils.digestUTF8(this.ciphertext, hasher));
   },
 
   /*
    * Don't directly use the sync key. Instead, grab a key for this
    * collection, which is decrypted with the sync key.
    *
    * Cache those keys; invalidate the cache if the time on the keys collection
    * changes, or other auth events occur.
--- a/services/sync/modules/service.js
+++ b/services/sync/modules/service.js
@@ -17,16 +17,17 @@ const PBKDF2_KEY_BYTES = 16;
 
 const CRYPTO_COLLECTION = "crypto";
 const KEYS_WBO = "keys";
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/Log.jsm");
 Cu.import("resource://services-common/async.js");
+Cu.import("resource://services-common/utils.js");
 Cu.import("resource://services-sync/constants.js");
 Cu.import("resource://services-sync/engines.js");
 Cu.import("resource://services-sync/engines/clients.js");
 Cu.import("resource://services-sync/main.js");
 Cu.import("resource://services-sync/policies.js");
 Cu.import("resource://services-sync/record.js");
 Cu.import("resource://services-sync/resource.js");
 Cu.import("resource://services-sync/rest.js");
@@ -338,17 +339,17 @@ Sync11Service.prototype = {
     let status = this._checkSetup();
     if (status != STATUS_DISABLED && status != CLIENT_NOT_CONFIGURED) {
       Svc.Obs.notify("weave:engine:start-tracking");
     }
 
     // Send an event now that Weave service is ready.  We don't do this
     // synchronously so that observers can import this module before
     // registering an observer.
-    Utils.nextTick(() => {
+    CommonUtils.nextTick(() => {
       this.status.ready = true;
 
       // UI code uses the flag on the XPCOM service so it doesn't have
       // to load a bunch of modules.
       let xps = Cc["@mozilla.org/weave/service;1"]
                   .getService(Ci.nsISupports)
                   .wrappedJSObject;
       xps.ready = true;
--- a/services/sync/modules/util.js
+++ b/services/sync/modules/util.js
@@ -39,30 +39,16 @@ class HMACMismatch extends Error {
     this.name = "HMACMismatch";
   }
 }
 
 /*
  * Utility functions
  */
 this.Utils = {
-  // Alias in functions from CommonUtils. These previously were defined here.
-  // In the ideal world, references to these would be removed.
-  nextTick: CommonUtils.nextTick,
-  namedTimer: CommonUtils.namedTimer,
-  makeURI: CommonUtils.makeURI,
-  encodeUTF8: CommonUtils.encodeUTF8,
-  decodeUTF8: CommonUtils.decodeUTF8,
-  safeAtoB: CommonUtils.safeAtoB,
-  byteArrayToString: CommonUtils.byteArrayToString,
-  bytesAsHex: CommonUtils.bytesAsHex,
-  hexToBytes: CommonUtils.hexToBytes,
-  encodeBase32: CommonUtils.encodeBase32,
-  decodeBase32: CommonUtils.decodeBase32,
-
   // Aliases from CryptoUtils.
   generateRandomBytes: CryptoUtils.generateRandomBytes,
   computeHTTPMACSHA1: CryptoUtils.computeHTTPMACSHA1,
   digestUTF8: CryptoUtils.digestUTF8,
   digestBytes: CryptoUtils.digestBytes,
   sha1: CryptoUtils.sha1,
   sha1Base32: CryptoUtils.sha1Base32,
   sha256: CryptoUtils.sha256,
@@ -292,22 +278,22 @@ this.Utils = {
 
   /**
    * Key manipulation.
    */
 
   // Return an octet string in friendly base32 *with no trailing =*.
   encodeKeyBase32: function encodeKeyBase32(keyData) {
     return Utils.base32ToFriendly(
-             Utils.encodeBase32(keyData))
+             CommonUtils.encodeBase32(keyData))
            .slice(0, SYNC_KEY_ENCODED_LENGTH);
   },
 
   decodeKeyBase32: function decodeKeyBase32(encoded) {
-    return Utils.decodeBase32(
+    return CommonUtils.decodeBase32(
              Utils.base32FromFriendly(
                Utils.normalizePassphrase(encoded)))
            .slice(0, SYNC_KEY_DECODED_LENGTH);
   },
 
   jsonFilePath(filePath) {
     return OS.Path.normalize(OS.Path.join(OS.Constants.Path.profileDir, "weave", filePath + ".json"));
   },
--- a/services/sync/tests/unit/head_helpers.js
+++ b/services/sync/tests/unit/head_helpers.js
@@ -6,16 +6,17 @@
 /* import-globals-from head_errorhandler_common.js */
 /* import-globals-from head_http_server.js */
 
 // This file expects Service to be defined in the global scope when EHTestsCommon
 // is used (from service.js).
 /* global Service */
 
 Cu.import("resource://services-common/async.js");
+Cu.import("resource://services-common/utils.js");
 Cu.import("resource://testing-common/services/common/utils.js");
 Cu.import("resource://testing-common/PlacesTestUtils.jsm");
 Cu.import("resource://services-sync/util.js");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/PlacesUtils.jsm");
 Cu.import("resource://gre/modules/ObjectUtils.jsm");
 
 add_task(async function head_setup() {
@@ -618,17 +619,17 @@ async function promiseVisit(expectedType
       onDeleteVisits() {},
     };
     PlacesUtils.history.addObserver(observer, false);
   });
 }
 
 async function addVisit(suffix, referrer = null, transition = PlacesUtils.history.TRANSITION_LINK) {
   let uriString = "http://getfirefox.com/" + suffix;
-  let uri = Utils.makeURI(uriString);
+  let uri = CommonUtils.makeURI(uriString);
   _("Adding visit for URI " + uriString);
 
   let visitAddedPromise = promiseVisit("added", uri);
   await PlacesTestUtils.addVisits({
     uri,
     visitDate: Date.now() * 1000,
     transition,
     referrer,
--- a/services/sync/tests/unit/head_http_server.js
+++ b/services/sync/tests/unit/head_http_server.js
@@ -1,16 +1,17 @@
 /* import-globals-from head_appinfo.js */
 /* import-globals-from ../../../common/tests/unit/head_helpers.js */
 /* import-globals-from head_helpers.js */
 
 var Cm = Components.manager;
 
 // Shared logging for all HTTP server functions.
 Cu.import("resource://gre/modules/Log.jsm");
+Cu.import("resource://services-common/utils.js");
 const SYNC_HTTP_LOGGER = "Sync.Test.Server";
 
 // While the sync code itself uses 1.5, the tests hard-code 1.1,
 // so we're sticking with 1.1 here.
 const SYNC_API_VERSION = "1.1";
 
 // Use the same method that record.js does, which mirrors the server.
 // The server returns timestamps with 1/100 sec granularity. Note that this is
@@ -31,25 +32,25 @@ function return_timestamp(request, respo
 }
 
 function has_hawk_header(req) {
   return req.hasHeader("Authorization") &&
          req.getHeader("Authorization").startsWith("Hawk");
 }
 
 function basic_auth_header(user, password) {
-  return "Basic " + btoa(user + ":" + Utils.encodeUTF8(password));
+  return "Basic " + btoa(user + ":" + CommonUtils.encodeUTF8(password));
 }
 
 function basic_auth_matches(req, user, password) {
   if (!req.hasHeader("Authorization")) {
     return false;
   }
 
-  let expected = basic_auth_header(user, Utils.encodeUTF8(password));
+  let expected = basic_auth_header(user, CommonUtils.encodeUTF8(password));
   return req.getHeader("Authorization") == expected;
 }
 
 function httpd_basic_auth_handler(body, metadata, response) {
   if (basic_auth_matches(metadata, "guest", "guest")) {
     response.setStatusLine(metadata.httpVersion, 200, "OK, authorized");
     response.setHeader("WWW-Authenticate", 'Basic realm="secret"', false);
   } else {
--- a/services/sync/tests/unit/test_bookmark_engine.js
+++ b/services/sync/tests/unit/test_bookmark_engine.js
@@ -1,22 +1,24 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 Cu.import("resource://gre/modules/PlacesSyncUtils.jsm");
 Cu.import("resource://gre/modules/BookmarkHTMLUtils.jsm");
 Cu.import("resource://gre/modules/BookmarkJSONUtils.jsm");
 Cu.import("resource://gre/modules/Log.jsm");
+Cu.import("resource://services-common/utils.js");
 Cu.import("resource://services-sync/constants.js");
 Cu.import("resource://services-sync/engines.js");
 Cu.import("resource://services-sync/engines/bookmarks.js");
 Cu.import("resource://services-sync/service.js");
 Cu.import("resource://services-sync/util.js");
 Cu.import("resource://testing-common/services/sync/utils.js");
 
+
 initTestLogging("Trace");
 
 async function fetchAllSyncIds() {
   let db = await PlacesUtils.promiseDBConnection();
   let rows = await db.executeCached(`
     WITH RECURSIVE
     syncedItems(id, guid) AS (
       SELECT b.id, b.guid FROM moz_bookmarks b
@@ -97,17 +99,17 @@ add_task(async function test_delete_inva
 add_task(async function bad_record_allIDs() {
   let server = new SyncServer();
   server.start();
   await SyncTestingInfrastructure(server);
 
   _("Ensure that bad Places queries don't cause an error in getAllIDs.");
   let badRecordID = PlacesUtils.bookmarks.insertBookmark(
       PlacesUtils.bookmarks.toolbarFolder,
-      Utils.makeURI("place:folder=1138"),
+      CommonUtils.makeURI("place:folder=1138"),
       PlacesUtils.bookmarks.DEFAULT_INDEX,
       null);
 
   do_check_true(badRecordID > 0);
   _("Record is " + badRecordID);
   _("Type: " + PlacesUtils.bookmarks.getItemType(badRecordID));
 
   _("Fetching all IDs.");
@@ -135,18 +137,18 @@ add_task(async function test_processInco
   let collection = server.user("foo").collection("bookmarks");
 
   try {
 
     let folder1_id = PlacesUtils.bookmarks.createFolder(
       PlacesUtils.bookmarks.toolbarFolder, "Folder 1", 0);
     let folder1_guid = await store.GUIDForId(folder1_id);
 
-    let fxuri = Utils.makeURI("http://getfirefox.com/");
-    let tburi = Utils.makeURI("http://getthunderbird.com/");
+    let fxuri = CommonUtils.makeURI("http://getfirefox.com/");
+    let tburi = CommonUtils.makeURI("http://getthunderbird.com/");
 
     let bmk1_id = PlacesUtils.bookmarks.insertBookmark(
       folder1_id, fxuri, PlacesUtils.bookmarks.DEFAULT_INDEX, "Get Firefox!");
     let bmk2_id = PlacesUtils.bookmarks.insertBookmark(
       folder1_id, tburi, PlacesUtils.bookmarks.DEFAULT_INDEX, "Get Thunderbird!");
 
     // Create a server record for folder1 where we flip the order of
     // the children.
@@ -224,18 +226,18 @@ async function test_restoreOrImport(aRep
 
   try {
 
     let folder1_id = PlacesUtils.bookmarks.createFolder(
       PlacesUtils.bookmarks.toolbarFolder, "Folder 1", 0);
     let folder1_guid = await store.GUIDForId(folder1_id);
     _("Folder 1: " + folder1_id + ", " + folder1_guid);
 
-    let fxuri = Utils.makeURI("http://getfirefox.com/");
-    let tburi = Utils.makeURI("http://getthunderbird.com/");
+    let fxuri = CommonUtils.makeURI("http://getfirefox.com/");
+    let tburi = CommonUtils.makeURI("http://getthunderbird.com/");
 
     _("Create a single record.");
     let bmk1_id = PlacesUtils.bookmarks.insertBookmark(
       folder1_id, fxuri, PlacesUtils.bookmarks.DEFAULT_INDEX, "Get Firefox!");
     let bmk1_guid = await store.GUIDForId(bmk1_id);
     _(`Get Firefox!: ${bmk1_id}, ${bmk1_guid}`);
 
     let dirSvc = Cc["@mozilla.org/file/directory_service;1"]
@@ -740,17 +742,17 @@ add_task(async function test_sync_dateAd
 
     // Update item2 and try resyncing it.
     item2.dateAdded = now - 100000;
     collection.insert(item2GUID, encryptPayload(item2.cleartext), now / 1000 - 50);
 
 
     // Also, add a local bookmark and make sure it's date added makes it up to the server
     let bzid = PlacesUtils.bookmarks.insertBookmark(
-      PlacesUtils.bookmarksMenuFolderId, Utils.makeURI("https://bugzilla.mozilla.org/"),
+      PlacesUtils.bookmarksMenuFolderId, CommonUtils.makeURI("https://bugzilla.mozilla.org/"),
       PlacesUtils.bookmarks.DEFAULT_INDEX, "Bugzilla");
 
     let bzguid = await PlacesUtils.promiseItemGuid(bzid);
 
     // last sync did a POST, which doesn't advance its lastModified value.
     // Next sync of the engine doesn't hit info/collections, so lastModified
     // remains stale. Setting it to null side-steps that.
     engine.lastModified = null;
--- a/services/sync/tests/unit/test_bookmark_smart_bookmarks.js
+++ b/services/sync/tests/unit/test_bookmark_smart_bookmarks.js
@@ -1,12 +1,13 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 Cu.import("resource://gre/modules/Log.jsm");
+Cu.import("resource://services-common/utils.js");
 Cu.import("resource://services-sync/engines.js");
 Cu.import("resource://services-sync/engines/bookmarks.js");
 Cu.import("resource://services-sync/service.js");
 Cu.import("resource://services-sync/util.js");
 Cu.import("resource://testing-common/services/sync/utils.js");
 
 const SMART_BOOKMARKS_ANNO = "Places/SmartBookmark";
 const IOService = Cc["@mozilla.org/network/io-service;1"]
@@ -59,17 +60,17 @@ add_task(async function test_annotation_
     // This can happen in XULRunner.
     clearBookmarks();
     _("Start count is now " + startCount);
   }
 
   _("Create a smart bookmark in the toolbar.");
   let parent = PlacesUtils.toolbarFolderId;
   let uri =
-    Utils.makeURI("place:sort=" +
+    CommonUtils.makeURI("place:sort=" +
                   Ci.nsINavHistoryQueryOptions.SORT_BY_VISITCOUNT_DESCENDING +
                   "&maxResults=10");
   let title = "Most Visited";
 
   let mostVisitedID = newSmartBookmark(parent, uri, -1, title, "MostVisited");
 
   _("New item ID: " + mostVisitedID);
   do_check_true(!!mostVisitedID);
@@ -118,17 +119,17 @@ add_task(async function test_annotation_
     do_check_eq(smartBookmarkCount(), startCount + 1);
 
     _("Clear local records; now we can't find it.");
 
     // "Clear" by changing attributes: if we delete it, apparently it sticks
     // around as a deleted record...
     PlacesUtils.bookmarks.setItemTitle(mostVisitedID, "Not Most Visited");
     PlacesUtils.bookmarks.changeBookmarkURI(
-      mostVisitedID, Utils.makeURI("http://something/else"));
+      mostVisitedID, CommonUtils.makeURI("http://something/else"));
     PlacesUtils.annotations.removeItemAnnotation(mostVisitedID,
                                                  SMART_BOOKMARKS_ANNO);
     await store.wipe();
     await engine.resetClient();
     do_check_eq(smartBookmarkCount(), startCount);
 
     _("Sync. Verify that the downloaded record carries the annotation.");
     await sync_engine_and_validate_telem(engine, false);
@@ -163,17 +164,17 @@ add_task(async function test_annotation_
 });
 
 add_task(async function test_smart_bookmarks_duped() {
   let server = serverForFoo(engine);
   await SyncTestingInfrastructure(server);
 
   let parent = PlacesUtils.toolbarFolderId;
   let uri =
-    Utils.makeURI("place:sort=" +
+    CommonUtils.makeURI("place:sort=" +
                   Ci.nsINavHistoryQueryOptions.SORT_BY_VISITCOUNT_DESCENDING +
                   "&maxResults=10");
   let title = "Most Visited";
   let mostVisitedID = newSmartBookmark(parent, uri, -1, title, "MostVisited");
   let mostVisitedGUID = await store.GUIDForId(mostVisitedID);
 
   let record = await store.createRecord(mostVisitedGUID);
 
--- a/services/sync/tests/unit/test_bookmark_store.js
+++ b/services/sync/tests/unit/test_bookmark_store.js
@@ -1,24 +1,25 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
+Cu.import("resource://services-common/utils.js");
 Cu.import("resource://services-sync/engines.js");
 Cu.import("resource://services-sync/engines/bookmarks.js");
 Cu.import("resource://services-sync/service.js");
 Cu.import("resource://services-sync/util.js");
 
 const PARENT_ANNO = "sync/parent";
 
 let engine;
 let store;
 let tracker;
 
-const fxuri = Utils.makeURI("http://getfirefox.com/");
-const tburi = Utils.makeURI("http://getthunderbird.com/");
+const fxuri = CommonUtils.makeURI("http://getfirefox.com/");
+const tburi = CommonUtils.makeURI("http://getthunderbird.com/");
 
 add_task(async function setup() {
   await Service.engineManager.register(BookmarksEngine);
 
   engine = Service.engineManager.get("bookmarks");
   store = engine._store;
   tracker = engine._tracker;
 
--- a/services/sync/tests/unit/test_bookmark_tracker.js
+++ b/services/sync/tests/unit/test_bookmark_tracker.js
@@ -1,11 +1,12 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
+Cu.import("resource://services-common/utils.js");
 Cu.import("resource://gre/modules/PlacesSyncUtils.jsm");
 Cu.import("resource://services-sync/constants.js");
 Cu.import("resource://services-sync/engines/bookmarks.js");
 Cu.import("resource://services-sync/engines.js");
 Cu.import("resource://services-sync/service.js");
 Cu.import("resource://services-sync/util.js");
 Cu.import("resource://gre/modules/osfile.jsm");
 Cu.import("resource://testing-common/PlacesTestUtils.jsm");
@@ -317,17 +318,17 @@ add_task(async function test_tracking() 
   // creating the folder should have made 2 changes - the folder itself and
   // the parent of the folder.
   await verifyTrackedCount(2);
   // Reset the changes as the rest of the test doesn't want to see these.
   await resetTracker();
 
   function createBmk() {
     return PlacesUtils.bookmarks.insertBookmark(
-      folder, Utils.makeURI("http://getfirefox.com"),
+      folder, CommonUtils.makeURI("http://getfirefox.com"),
       PlacesUtils.bookmarks.DEFAULT_INDEX, "Get Firefox!");
   }
 
   try {
     _("Tell the tracker to start tracking changes.");
     await startTracking();
     createBmk();
     // We expect two changed items because the containing folder
@@ -412,17 +413,17 @@ add_task(async function test_tracker_sql
 
   await startTracking();
 
   PlacesUtils.bookmarks.runInBatchMode({
     runBatched() {
       for (let i = 0; i < numItems; i++) {
         let syncBmkID = PlacesUtils.bookmarks.insertBookmark(
                           PlacesUtils.bookmarks.unfiledBookmarksFolder,
-                          Utils.makeURI("https://example.org/" + i),
+                          CommonUtils.makeURI("https://example.org/" + i),
                           PlacesUtils.bookmarks.DEFAULT_INDEX,
                           "Sync Bookmark " + i);
         createdIDs.push(syncBmkID);
       }
     }
   }, null);
 
   do_check_eq(createdIDs.length, numItems);
@@ -449,17 +450,17 @@ add_task(async function test_onItemAdded
     await verifyTrackedItems(["menu", syncFolderGUID]);
     do_check_eq(tracker.score, SCORE_INCREMENT_XLARGE);
 
     await resetTracker();
     await startTracking();
 
     _("Insert a bookmark using the sync API");
     let syncBmkID = PlacesUtils.bookmarks.insertBookmark(syncFolderID,
-      Utils.makeURI("https://example.org/sync"),
+      CommonUtils.makeURI("https://example.org/sync"),
       PlacesUtils.bookmarks.DEFAULT_INDEX,
       "Sync Bookmark");
     let syncBmkGUID = await engine._store.GUIDForId(syncBmkID);
     await verifyTrackedItems([syncFolderGUID, syncBmkGUID]);
     do_check_eq(tracker.score, SCORE_INCREMENT_XLARGE);
 
     await resetTracker();
     await startTracking();
@@ -561,17 +562,17 @@ add_task(async function test_onItemChang
   _("Changes to item dates should be tracked");
 
   try {
     await stopTracking();
 
     _("Insert a bookmark");
     let fx_id = PlacesUtils.bookmarks.insertBookmark(
       PlacesUtils.bookmarks.bookmarksMenuFolder,
-      Utils.makeURI("http://getfirefox.com"),
+      CommonUtils.makeURI("http://getfirefox.com"),
       PlacesUtils.bookmarks.DEFAULT_INDEX,
       "Get Firefox!");
     let fx_guid = await engine._store.GUIDForId(fx_id);
     _(`Firefox GUID: ${fx_guid}`);
 
     await startTracking();
 
     _("Reset the bookmark's added date");
@@ -597,32 +598,32 @@ add_task(async function test_onItemChang
   _("Changes to bookmark URIs should be tracked");
 
   try {
     await stopTracking();
 
     _("Insert a bookmark");
     let fx_id = PlacesUtils.bookmarks.insertBookmark(
       PlacesUtils.bookmarks.bookmarksMenuFolder,
-      Utils.makeURI("http://getfirefox.com"),
+      CommonUtils.makeURI("http://getfirefox.com"),
       PlacesUtils.bookmarks.DEFAULT_INDEX,
       "Get Firefox!");
     let fx_guid = await engine._store.GUIDForId(fx_id);
     _(`Firefox GUID: ${fx_guid}`);
 
     _("Set a tracked annotation to make sure we only notify once");
     PlacesUtils.annotations.setItemAnnotation(
       fx_id, PlacesSyncUtils.bookmarks.DESCRIPTION_ANNO, "A test description", 0,
       PlacesUtils.annotations.EXPIRE_NEVER);
 
     await startTracking();
 
     _("Change the bookmark's URI");
     PlacesUtils.bookmarks.changeBookmarkURI(fx_id,
-      Utils.makeURI("https://www.mozilla.org/firefox"));
+      CommonUtils.makeURI("https://www.mozilla.org/firefox"));
     await verifyTrackedItems([fx_guid]);
     do_check_eq(tracker.score, SCORE_INCREMENT_XLARGE);
   } finally {
     _("Clean up.");
     await cleanup();
   }
 });
 
@@ -636,17 +637,17 @@ add_task(async function test_onItemTagge
     let folder = PlacesUtils.bookmarks.createFolder(
       PlacesUtils.bookmarks.bookmarksMenuFolder, "Parent",
       PlacesUtils.bookmarks.DEFAULT_INDEX);
     let folderGUID = await engine._store.GUIDForId(folder);
     _("Folder ID: " + folder);
     _("Folder GUID: " + folderGUID);
 
     _("Track changes to tags");
-    let uri = Utils.makeURI("http://getfirefox.com");
+    let uri = CommonUtils.makeURI("http://getfirefox.com");
     let b = PlacesUtils.bookmarks.insertBookmark(
       folder, uri,
       PlacesUtils.bookmarks.DEFAULT_INDEX, "Get Firefox!");
     let bGUID = await engine._store.GUIDForId(b);
     _("New item is " + b);
     _("GUID: " + bGUID);
 
     await startTracking();
@@ -665,17 +666,17 @@ add_task(async function test_onItemTagge
 
 add_task(async function test_onItemUntagged() {
   _("Items untagged using the synchronous API should be tracked");
 
   try {
     await stopTracking();
 
     _("Insert tagged bookmarks");
-    let uri = Utils.makeURI("http://getfirefox.com");
+    let uri = CommonUtils.makeURI("http://getfirefox.com");
     let fx1ID = PlacesUtils.bookmarks.insertBookmark(
       PlacesUtils.bookmarks.bookmarksMenuFolder, uri,
       PlacesUtils.bookmarks.DEFAULT_INDEX, "Get Firefox!");
     let fx1GUID = await engine._store.GUIDForId(fx1ID);
     // Different parent and title; same URL.
     let fx2ID = PlacesUtils.bookmarks.insertBookmark(
       PlacesUtils.bookmarks.toolbarFolder, uri,
       PlacesUtils.bookmarks.DEFAULT_INDEX, "Download Firefox");
@@ -800,17 +801,17 @@ add_task(async function test_onItemKeywo
   _("Keyword changes via the synchronous API should be tracked");
 
   try {
     await stopTracking();
     let folder = PlacesUtils.bookmarks.createFolder(
       PlacesUtils.bookmarks.bookmarksMenuFolder, "Parent",
       PlacesUtils.bookmarks.DEFAULT_INDEX);
     _("Track changes to keywords");
-    let uri = Utils.makeURI("http://getfirefox.com");
+    let uri = CommonUtils.makeURI("http://getfirefox.com");
     let b = PlacesUtils.bookmarks.insertBookmark(
       folder, uri,
       PlacesUtils.bookmarks.DEFAULT_INDEX, "Get Firefox!");
     let bGUID = await engine._store.GUIDForId(b);
     _("New item is " + b);
     _("GUID: " + bGUID);
 
     await startTracking();
@@ -906,17 +907,17 @@ add_task(async function test_onItemPostD
   _("Post data changes should be tracked");
 
   try {
     await stopTracking();
 
     _("Insert a bookmark");
     let fx_id = PlacesUtils.bookmarks.insertBookmark(
       PlacesUtils.bookmarks.bookmarksMenuFolder,
-      Utils.makeURI("http://getfirefox.com"),
+      CommonUtils.makeURI("http://getfirefox.com"),
       PlacesUtils.bookmarks.DEFAULT_INDEX,
       "Get Firefox!");
     let fx_guid = await engine._store.GUIDForId(fx_id);
     _(`Firefox GUID: ${fx_guid}`);
 
     await startTracking();
 
     // PlacesUtils.setPostDataForBookmark is deprecated, but still used by
@@ -936,17 +937,17 @@ add_task(async function test_onItemAnnoC
 
   try {
     await stopTracking();
     let folder = PlacesUtils.bookmarks.createFolder(
       PlacesUtils.bookmarks.bookmarksMenuFolder, "Parent",
       PlacesUtils.bookmarks.DEFAULT_INDEX);
     _("Track changes to annos.");
     let b = PlacesUtils.bookmarks.insertBookmark(
-      folder, Utils.makeURI("http://getfirefox.com"),
+      folder, CommonUtils.makeURI("http://getfirefox.com"),
       PlacesUtils.bookmarks.DEFAULT_INDEX, "Get Firefox!");
     let bGUID = await engine._store.GUIDForId(b);
     _("New item is " + b);
     _("GUID: " + bGUID);
 
     await startTracking();
     PlacesUtils.annotations.setItemAnnotation(
       b, PlacesSyncUtils.bookmarks.DESCRIPTION_ANNO, "A test description", 0,
@@ -978,26 +979,26 @@ add_task(async function test_onItemAdded
       "New root",
       PlacesUtils.bookmarks.DEFAULT_INDEX);
     let rootGUID = await engine._store.GUIDForId(rootID);
     _(`New root GUID: ${rootGUID}`);
 
     _("Insert a bookmark underneath the new root");
     let untrackedBmkID = PlacesUtils.bookmarks.insertBookmark(
       rootID,
-      Utils.makeURI("http://getthunderbird.com"),
+      CommonUtils.makeURI("http://getthunderbird.com"),
       PlacesUtils.bookmarks.DEFAULT_INDEX,
       "Get Thunderbird!");
     let untrackedBmkGUID = await engine._store.GUIDForId(untrackedBmkID);
     _(`New untracked bookmark GUID: ${untrackedBmkGUID}`);
 
     _("Insert a bookmark underneath the Places root");
     let rootBmkID = PlacesUtils.bookmarks.insertBookmark(
       PlacesUtils.bookmarks.placesRoot,
-      Utils.makeURI("http://getfirefox.com"),
+      CommonUtils.makeURI("http://getfirefox.com"),
       PlacesUtils.bookmarks.DEFAULT_INDEX, "Get Firefox!");
     let rootBmkGUID = await engine._store.GUIDForId(rootBmkID);
     _(`New Places root bookmark GUID: ${rootBmkGUID}`);
 
     _("New root and bookmark should be ignored");
     await verifyTrackedItems([]);
     do_check_eq(tracker.score, SCORE_INCREMENT_XLARGE * 3);
   } finally {
@@ -1010,17 +1011,17 @@ add_task(async function test_onItemDelet
   _("Deleted items outside the change roots should not be tracked");
 
   try {
     await stopTracking();
 
     _("Insert a bookmark underneath the Places root");
     let rootBmkID = PlacesUtils.bookmarks.insertBookmark(
       PlacesUtils.bookmarks.placesRoot,
-      Utils.makeURI("http://getfirefox.com"),
+      CommonUtils.makeURI("http://getfirefox.com"),
       PlacesUtils.bookmarks.DEFAULT_INDEX, "Get Firefox!");
     let rootBmkGUID = await engine._store.GUIDForId(rootBmkID);
     _(`New Places root bookmark GUID: ${rootBmkGUID}`);
 
     await startTracking();
 
     PlacesUtils.bookmarks.removeItem(rootBmkID);
 
@@ -1035,17 +1036,17 @@ add_task(async function test_onItemDelet
 
 add_task(async function test_onPageAnnoChanged() {
   _("Page annotations should not be tracked");
 
   try {
     await stopTracking();
 
     _("Insert a bookmark without an annotation");
-    let pageURI = Utils.makeURI("http://getfirefox.com");
+    let pageURI = CommonUtils.makeURI("http://getfirefox.com");
     PlacesUtils.bookmarks.insertBookmark(
       PlacesUtils.bookmarks.bookmarksMenuFolder,
       pageURI,
       PlacesUtils.bookmarks.DEFAULT_INDEX,
       "Get Firefox!");
 
     await startTracking();
 
@@ -1068,18 +1069,18 @@ add_task(async function test_onPageAnnoC
 });
 
 add_task(async function test_onFaviconChanged() {
   _("Favicon changes should not be tracked");
 
   try {
     await stopTracking();
 
-    let pageURI = Utils.makeURI("http://getfirefox.com");
-    let iconURI = Utils.makeURI("http://getfirefox.com/icon");
+    let pageURI = CommonUtils.makeURI("http://getfirefox.com");
+    let iconURI = CommonUtils.makeURI("http://getfirefox.com/icon");
     PlacesUtils.bookmarks.insertBookmark(
       PlacesUtils.bookmarks.bookmarksMenuFolder,
       pageURI,
       PlacesUtils.bookmarks.DEFAULT_INDEX,
       "Get Firefox!");
 
     await PlacesTestUtils.addVisits(pageURI);
 
@@ -1113,17 +1114,17 @@ add_task(async function test_onLivemarkA
   try {
     await startTracking();
 
     _("Insert a livemark");
     let livemark = await PlacesUtils.livemarks.addLivemark({
       parentGuid: PlacesUtils.bookmarks.menuGuid,
       // Use a local address just in case, to avoid potential aborts for
       // non-local connections.
-      feedURI: Utils.makeURI("http://localhost:0"),
+      feedURI: CommonUtils.makeURI("http://localhost:0"),
     });
     // Prevent the livemark refresh timer from requesting the URI.
     livemark.terminate();
 
     await verifyTrackedItems(["menu", livemark.guid]);
     // Two observer notifications: one for creating the livemark folder, and
     // one for setting the "livemark/feedURI" anno on the folder.
     do_check_eq(tracker.score, SCORE_INCREMENT_XLARGE * 2);
@@ -1137,17 +1138,17 @@ add_task(async function test_onLivemarkD
   _("Deleted livemarks should be tracked");
 
   try {
     await stopTracking();
 
     _("Insert a livemark");
     let livemark = await PlacesUtils.livemarks.addLivemark({
       parentGuid: PlacesUtils.bookmarks.menuGuid,
-      feedURI: Utils.makeURI("http://localhost:0"),
+      feedURI: CommonUtils.makeURI("http://localhost:0"),
     });
     livemark.terminate();
 
     await startTracking();
 
     _("Remove a livemark");
     await PlacesUtils.livemarks.removeLivemark({
       guid: livemark.guid,
@@ -1162,24 +1163,24 @@ add_task(async function test_onLivemarkD
 });
 
 add_task(async function test_onItemMoved() {
   _("Items moved via the synchronous API should be tracked");
 
   try {
     let fx_id = PlacesUtils.bookmarks.insertBookmark(
       PlacesUtils.bookmarks.bookmarksMenuFolder,
-      Utils.makeURI("http://getfirefox.com"),
+      CommonUtils.makeURI("http://getfirefox.com"),
       PlacesUtils.bookmarks.DEFAULT_INDEX,
       "Get Firefox!");
     let fx_guid = await engine._store.GUIDForId(fx_id);
     _("Firefox GUID: " + fx_guid);
     let tb_id = PlacesUtils.bookmarks.insertBookmark(
       PlacesUtils.bookmarks.bookmarksMenuFolder,
-      Utils.makeURI("http://getthunderbird.com"),
+      CommonUtils.makeURI("http://getthunderbird.com"),
       PlacesUtils.bookmarks.DEFAULT_INDEX,
       "Get Thunderbird!");
     let tb_guid = await engine._store.GUIDForId(tb_id);
     _("Thunderbird GUID: " + tb_guid);
 
     await startTracking();
 
     // Moving within the folder will just track the folder.
@@ -1305,33 +1306,33 @@ add_task(async function test_onItemMoved
       PlacesUtils.bookmarks.bookmarksMenuFolder,
       "Test folder",
       PlacesUtils.bookmarks.DEFAULT_INDEX);
     let folder_guid = await engine._store.GUIDForId(folder_id);
     _(`Folder GUID: ${folder_guid}`);
 
     let tb_id = PlacesUtils.bookmarks.insertBookmark(
       folder_id,
-      Utils.makeURI("http://getthunderbird.com"),
+      CommonUtils.makeURI("http://getthunderbird.com"),
       PlacesUtils.bookmarks.DEFAULT_INDEX,
       "Thunderbird");
     let tb_guid = await engine._store.GUIDForId(tb_id);
     _(`Thunderbird GUID: ${tb_guid}`);
 
     let fx_id = PlacesUtils.bookmarks.insertBookmark(
       folder_id,
-      Utils.makeURI("http://getfirefox.com"),
+      CommonUtils.makeURI("http://getfirefox.com"),
       PlacesUtils.bookmarks.DEFAULT_INDEX,
       "Firefox");
     let fx_guid = await engine._store.GUIDForId(fx_id);
     _(`Firefox GUID: ${fx_guid}`);
 
     let moz_id = PlacesUtils.bookmarks.insertBookmark(
       PlacesUtils.bookmarks.bookmarksMenuFolder,
-      Utils.makeURI("https://mozilla.org"),
+      CommonUtils.makeURI("https://mozilla.org"),
       PlacesUtils.bookmarks.DEFAULT_INDEX,
       "Mozilla"
     );
     let moz_guid = await engine._store.GUIDForId(moz_id);
     _(`Mozilla GUID: ${moz_guid}`);
 
     await startTracking();
 
@@ -1367,24 +1368,24 @@ add_task(async function test_onItemDelet
     let folder_id = PlacesUtils.bookmarks.createFolder(
       PlacesUtils.bookmarks.bookmarksMenuFolder,
       "Test folder",
       PlacesUtils.bookmarks.DEFAULT_INDEX);
     let folder_guid = await engine._store.GUIDForId(folder_id);
     _(`Folder GUID: ${folder_guid}`);
     let fx_id = PlacesUtils.bookmarks.insertBookmark(
       folder_id,
-      Utils.makeURI("http://getfirefox.com"),
+      CommonUtils.makeURI("http://getfirefox.com"),
       PlacesUtils.bookmarks.DEFAULT_INDEX,
       "Get Firefox!");
     let fx_guid = await engine._store.GUIDForId(fx_id);
     _(`Firefox GUID: ${fx_guid}`);
     let tb_id = PlacesUtils.bookmarks.insertBookmark(
       folder_id,
-      Utils.makeURI("http://getthunderbird.com"),
+      CommonUtils.makeURI("http://getthunderbird.com"),
       PlacesUtils.bookmarks.DEFAULT_INDEX,
       "Get Thunderbird!");
     let tb_guid = await engine._store.GUIDForId(tb_id);
     _(`Thunderbird GUID: ${tb_guid}`);
 
     await startTracking();
 
     let txn = PlacesUtils.bookmarks.getRemoveFolderTransaction(folder_id);
@@ -1433,22 +1434,22 @@ add_task(async function test_treeMoved()
       folder1_id,
       "Second test folder",
       PlacesUtils.bookmarks.DEFAULT_INDEX);
     let folder2_guid = await engine._store.GUIDForId(folder2_id);
 
     // Create a couple of bookmarks in the second folder.
     PlacesUtils.bookmarks.insertBookmark(
       folder2_id,
-      Utils.makeURI("http://getfirefox.com"),
+      CommonUtils.makeURI("http://getfirefox.com"),
       PlacesUtils.bookmarks.DEFAULT_INDEX,
       "Get Firefox!");
     PlacesUtils.bookmarks.insertBookmark(
       folder2_id,
-      Utils.makeURI("http://getthunderbird.com"),
+      CommonUtils.makeURI("http://getthunderbird.com"),
       PlacesUtils.bookmarks.DEFAULT_INDEX,
       "Get Thunderbird!");
 
     await startTracking();
 
     // Move folder 2 to be a sibling of folder1.
     PlacesUtils.bookmarks.moveItem(
       folder2_id, PlacesUtils.bookmarks.bookmarksMenuFolder, 0);
@@ -1462,22 +1463,22 @@ add_task(async function test_treeMoved()
 });
 
 add_task(async function test_onItemDeleted() {
   _("Bookmarks deleted via the synchronous API should be tracked");
 
   try {
     PlacesUtils.bookmarks.insertBookmark(
       PlacesUtils.bookmarks.bookmarksMenuFolder,
-      Utils.makeURI("http://getfirefox.com"),
+      CommonUtils.makeURI("http://getfirefox.com"),
       PlacesUtils.bookmarks.DEFAULT_INDEX,
       "Get Firefox!");
     let tb_id = PlacesUtils.bookmarks.insertBookmark(
       PlacesUtils.bookmarks.bookmarksMenuFolder,
-      Utils.makeURI("http://getthunderbird.com"),
+      CommonUtils.makeURI("http://getthunderbird.com"),
       PlacesUtils.bookmarks.DEFAULT_INDEX,
       "Get Thunderbird!");
     let tb_guid = await engine._store.GUIDForId(tb_id);
 
     await startTracking();
 
     // Delete the last item - the item and parent should be tracked.
     PlacesUtils.bookmarks.removeItem(tb_id);
@@ -1607,33 +1608,33 @@ add_task(async function test_async_onIte
 });
 
 add_task(async function test_onItemDeleted_removeFolderChildren() {
   _("Removing a folder's children should track the folder and its children");
 
   try {
     let fx_id = PlacesUtils.bookmarks.insertBookmark(
       PlacesUtils.mobileFolderId,
-      Utils.makeURI("http://getfirefox.com"),
+      CommonUtils.makeURI("http://getfirefox.com"),
       PlacesUtils.bookmarks.DEFAULT_INDEX,
       "Get Firefox!");
     let fx_guid = await engine._store.GUIDForId(fx_id);
     _(`Firefox GUID: ${fx_guid}`);
 
     let tb_id = PlacesUtils.bookmarks.insertBookmark(
       PlacesUtils.mobileFolderId,
-      Utils.makeURI("http://getthunderbird.com"),
+      CommonUtils.makeURI("http://getthunderbird.com"),
       PlacesUtils.bookmarks.DEFAULT_INDEX,
       "Get Thunderbird!");
     let tb_guid = await engine._store.GUIDForId(tb_id);
     _(`Thunderbird GUID: ${tb_guid}`);
 
     let moz_id = PlacesUtils.bookmarks.insertBookmark(
       PlacesUtils.bookmarks.bookmarksMenuFolder,
-      Utils.makeURI("https://mozilla.org"),
+      CommonUtils.makeURI("https://mozilla.org"),
       PlacesUtils.bookmarks.DEFAULT_INDEX,
       "Mozilla"
     );
     let moz_guid = await engine._store.GUIDForId(moz_id);
     _(`Mozilla GUID: ${moz_guid}`);
 
     await startTracking();
 
@@ -1664,23 +1665,23 @@ add_task(async function test_onItemDelet
       folder1_id,
       "Second test folder",
       PlacesUtils.bookmarks.DEFAULT_INDEX);
     let folder2_guid = await engine._store.GUIDForId(folder2_id);
 
     // Create a couple of bookmarks in the second folder.
     let fx_id = PlacesUtils.bookmarks.insertBookmark(
       folder2_id,
-      Utils.makeURI("http://getfirefox.com"),
+      CommonUtils.makeURI("http://getfirefox.com"),
       PlacesUtils.bookmarks.DEFAULT_INDEX,
       "Get Firefox!");
     let fx_guid = await engine._store.GUIDForId(fx_id);
     let tb_id = PlacesUtils.bookmarks.insertBookmark(
       folder2_id,
-      Utils.makeURI("http://getthunderbird.com"),
+      CommonUtils.makeURI("http://getthunderbird.com"),
       PlacesUtils.bookmarks.DEFAULT_INDEX,
       "Get Thunderbird!");
     let tb_guid = await engine._store.GUIDForId(tb_id);
 
     await startTracking();
 
     // Delete folder2 - everything we created should be tracked.
     PlacesUtils.bookmarks.removeItem(folder2_id);
--- a/services/sync/tests/unit/test_corrupt_keys.js
+++ b/services/sync/tests/unit/test_corrupt_keys.js
@@ -1,12 +1,13 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 Cu.import("resource://gre/modules/Log.jsm");
+Cu.import("resource://services-common/utils.js");
 Cu.import("resource://services-sync/constants.js");
 Cu.import("resource://services-sync/engines.js");
 Cu.import("resource://services-sync/main.js");
 Cu.import("resource://services-sync/engines/tabs.js");
 Cu.import("resource://services-sync/engines/history.js");
 Cu.import("resource://services-sync/record.js");
 Cu.import("resource://services-sync/service.js");
 Cu.import("resource://services-sync/status.js");
@@ -196,13 +197,13 @@ function run_test() {
  * Asynchronously check a url is visited.
  * @param url the url
  * @return {Promise}
  * @resolves When the check has been added successfully.
  * @rejects JavaScript exception.
  */
 function promiseIsURIVisited(url) {
   return new Promise(resolve => {
-    PlacesUtils.asyncHistory.isURIVisited(Utils.makeURI(url), function(aURI, aIsVisited) {
+    PlacesUtils.asyncHistory.isURIVisited(CommonUtils.makeURI(url), function(aURI, aIsVisited) {
       resolve(aIsVisited);
     });
   });
 }
--- a/services/sync/tests/unit/test_fxa_node_reassignment.js
+++ b/services/sync/tests/unit/test_fxa_node_reassignment.js
@@ -4,16 +4,17 @@
 _("Test that node reassignment happens correctly using the FxA identity mgr.");
 // The node-reassignment logic is quite different for FxA than for the legacy
 // provider.  In particular, there's no special request necessary for
 // reassignment - it comes from the token server - so we need to ensure the
 // Fxa cluster manager grabs a new token.
 
 Cu.import("resource://gre/modules/Log.jsm");
 Cu.import("resource://services-common/rest.js");
+Cu.import("resource://services-common/utils.js");
 Cu.import("resource://services-sync/constants.js");
 Cu.import("resource://services-sync/service.js");
 Cu.import("resource://services-sync/status.js");
 Cu.import("resource://services-sync/util.js");
 Cu.import("resource://testing-common/services/sync/rotaryengine.js");
 Cu.import("resource://services-sync/browserid_identity.js");
 Cu.import("resource://testing-common/services/sync/utils.js");
 Cu.import("resource://gre/modules/PromiseUtils.jsm");
@@ -157,21 +158,21 @@ async function syncAndExpectNodeReassign
 
   // Make sure that we really do get a 401 (but we can only do that if we are
   // already logged in, as the login process is what sets up the URLs)
   if (Service.isLoggedIn) {
     _("Making request to " + url + " which should 401");
     let request = new RESTRequest(url);
     request.get(function() {
       do_check_eq(request.response.status, 401);
-      Utils.nextTick(onwards);
+      CommonUtils.nextTick(onwards);
     });
   } else {
     _("Skipping preliminary validation check for a 401 as we aren't logged in");
-    Utils.nextTick(onwards);
+    CommonUtils.nextTick(onwards);
   }
   await deferred.promise;
 }
 
 // Check that when we sync we don't request a new token by default - our
 // test setup has configured the client with a valid token, and that token
 // should be used to form the cluster URL.
 add_task(async function test_single_token_fetch() {
--- a/services/sync/tests/unit/test_history_store.js
+++ b/services/sync/tests/unit/test_history_store.js
@@ -1,14 +1,15 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 Cu.import("resource://testing-common/PlacesTestUtils.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://services-common/async.js");
+Cu.import("resource://services-common/utils.js");
 Cu.import("resource://services-sync/engines/history.js");
 Cu.import("resource://services-sync/service.js");
 Cu.import("resource://services-sync/util.js");
 
 const TIMESTAMP1 = (Date.now() - 103406528) * 1000;
 const TIMESTAMP2 = (Date.now() - 6592903) * 1000;
 const TIMESTAMP3 = (Date.now() - 123894) * 1000;
 
@@ -72,17 +73,17 @@ function run_test() {
   run_next_test();
 }
 
 add_task(async function test_store() {
   _("Verify that we've got an empty store to work with.");
   do_check_empty((await store.getAllIDs()));
 
   _("Let's create an entry in the database.");
-  fxuri = Utils.makeURI("http://getfirefox.com/");
+  fxuri = CommonUtils.makeURI("http://getfirefox.com/");
 
   await PlacesTestUtils.addVisits({ uri: fxuri, title: "Get Firefox!",
                                   visitDate: TIMESTAMP1 });
   _("Verify that the entry exists.");
   let ids = Object.keys((await store.getAllIDs()));
   do_check_eq(ids.length, 1);
   fxguid = ids[0];
   do_check_true((await store.itemExists(fxguid)));
@@ -121,17 +122,17 @@ add_task(async function test_store() {
     PlacesTestUtils.clearHistory();
     do_throw(ex);
   }
 });
 
 add_task(async function test_store_create() {
   _("Create a brand new record through the store.");
   tbguid = Utils.makeGUID();
-  tburi = Utils.makeURI("http://getthunderbird.com");
+  tburi = CommonUtils.makeURI("http://getthunderbird.com");
   let onVisitObserved = promiseOnVisitObserved();
   await applyEnsureNoFailures([
     {id: tbguid,
      histUri: tburi.spec,
      title: "The bird is the word!",
      visits: [{date: TIMESTAMP3,
                type: Ci.nsINavHistoryService.TRANSITION_TYPED}]}
   ]);
@@ -147,17 +148,17 @@ add_task(async function test_store_creat
     PlacesTestUtils.clearHistory();
     do_throw(ex);
   }
 });
 
 add_task(async function test_null_title() {
   _("Make sure we handle a null title gracefully (it can happen in some cases, e.g. for resource:// URLs)");
   let resguid = Utils.makeGUID();
-  let resuri = Utils.makeURI("unknown://title");
+  let resuri = CommonUtils.makeURI("unknown://title");
   await applyEnsureNoFailures([
     {id: resguid,
      histUri: resuri.spec,
      title: null,
      visits: [{date: TIMESTAMP3,
                type: Ci.nsINavHistoryService.TRANSITION_TYPED}]}
   ]);
   do_check_attribute_count((await store.getAllIDs()), 3);
--- a/services/sync/tests/unit/test_history_tracker.js
+++ b/services/sync/tests/unit/test_history_tracker.js
@@ -1,13 +1,14 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 Cu.import("resource://gre/modules/PlacesDBUtils.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://services-common/utils.js");
 Cu.import("resource://services-sync/engines.js");
 Cu.import("resource://services-sync/constants.js");
 Cu.import("resource://services-sync/engines/history.js");
 Cu.import("resource://services-sync/service.js");
 Cu.import("resource://services-sync/util.js");
 
 let engine;
 let tracker;
@@ -138,17 +139,17 @@ add_task(async function test_start_track
   await cleanup();
 });
 
 add_task(async function test_track_delete() {
   _("Deletions are tracked.");
 
   // This isn't present because we weren't tracking when it was visited.
   await addVisit("track_delete");
-  let uri = Utils.makeURI("http://getfirefox.com/track_delete");
+  let uri = CommonUtils.makeURI("http://getfirefox.com/track_delete");
   let guid = await engine._store.GUIDForUri(uri.spec);
   await verifyTrackerEmpty();
 
   await startTracking();
   let visitRemovedPromise = promiseVisit("removed", uri);
   let scorePromise = promiseOneObserver("weave:engine:score:updated");
   await PlacesUtils.history.remove(uri);
   await Promise.all([scorePromise, visitRemovedPromise]);
--- a/services/sync/tests/unit/test_hmac_error.js
+++ b/services/sync/tests/unit/test_hmac_error.js
@@ -201,17 +201,17 @@ add_task(async function hmac_error_durin
         _("== Second (automatic) sync done.");
         let hasData = rotaryColl.wbo("flying") ||
                       rotaryColl.wbo("scotsman");
         let hasKeys = keysWBO.modified;
         do_check_true(!hasData == !hasKeys);
 
         // Kick off another sync. Can't just call it, because we're inside the
         // lock...
-        Utils.nextTick(function() {
+        CommonUtils.nextTick(function() {
           _("Now a fresh sync will get no HMAC errors.");
           _("Partially resetting client, as if after a restart, and forcing redownload.");
           Service.collectionKeys.clear();
           engine.lastSync = 0;
           hmacErrorCount = 0;
 
           onSyncFinished = function() {
             // Two rotary items, one client record... no errors.
--- a/services/sync/tests/unit/test_httpd_sync_server.js
+++ b/services/sync/tests/unit/test_httpd_sync_server.js
@@ -1,11 +1,12 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
+Cu.import("resource://services-common/utils.js");
 Cu.import("resource://services-sync/util.js");
 
 function run_test() {
   Log.repository.getLogger("Sync.Test.Server").level = Log.Level.Trace;
   initTestLogging();
   run_next_test();
 }
 
@@ -74,22 +75,22 @@ function localRequest(server, path) {
 }
 
 add_test(function test_basic_http() {
   let server = new SyncServer();
   server.registerUser("john", "password");
   do_check_true(server.userExists("john"));
   server.start(null, function() {
     _("Started on " + server.port);
-    Utils.nextTick(function() {
+    CommonUtils.nextTick(function() {
       let req = localRequest(server, "/1.1/john/storage/crypto/keys");
       _("req is " + req);
       req.get(function(err) {
         do_check_eq(null, err);
-        Utils.nextTick(function() {
+        CommonUtils.nextTick(function() {
           server.stop(run_next_test);
         });
       });
     });
   });
 });
 
 add_test(function test_info_collections() {
@@ -99,25 +100,25 @@ add_test(function test_info_collections(
   function responseHasCorrectHeaders(r) {
     do_check_eq(r.status, 200);
     do_check_eq(r.headers["content-type"], "application/json");
     do_check_true("x-weave-timestamp" in r.headers);
   }
 
   server.registerUser("john", "password");
   server.start(null, function() {
-    Utils.nextTick(function() {
+    CommonUtils.nextTick(function() {
       let req = localRequest(server, "/1.1/john/info/collections");
       req.get(function(err) {
         // Initial info/collections fetch is empty.
         do_check_eq(null, err);
         responseHasCorrectHeaders(this.response);
 
         do_check_eq(this.response.body, "{}");
-        Utils.nextTick(function() {
+        CommonUtils.nextTick(function() {
           // When we PUT something to crypto/keys, "crypto" appears in the response.
           function cb(err2) {
             do_check_eq(null, err2);
             responseHasCorrectHeaders(this.response);
             let putResponseBody = this.response.body;
             _("PUT response body: " + JSON.stringify(putResponseBody));
 
             req = localRequest(server, "/1.1/john/info/collections");
@@ -125,17 +126,17 @@ add_test(function test_info_collections(
               do_check_eq(null, err3);
               responseHasCorrectHeaders(this.response);
               let expectedColl = server.getCollection("john", "crypto");
               do_check_true(!!expectedColl);
               let modified = expectedColl.timestamp;
               do_check_true(modified > 0);
               do_check_eq(putResponseBody, modified);
               do_check_eq(JSON.parse(this.response.body).crypto, modified);
-              Utils.nextTick(function() {
+              CommonUtils.nextTick(function() {
                 server.stop(run_next_test);
               });
             });
           }
           let payload = JSON.stringify({foo: "bar"});
           localRequest(server, "/1.1/john/storage/crypto/keys").put(payload, cb);
         });
       });
@@ -164,54 +165,54 @@ add_test(function test_storage_request()
   function retrieveWBONotExists(next) {
     let req = localRequest(server, keysURL);
     req.get(function(err) {
       _("Body is " + this.response.body);
       _("Modified is " + this.response.newModified);
       do_check_eq(null, err);
       do_check_eq(this.response.status, 404);
       do_check_eq(this.response.body, "Not found");
-      Utils.nextTick(next);
+      CommonUtils.nextTick(next);
     });
   }
   function retrieveWBOExists(next) {
     let req = localRequest(server, foosURL);
     req.get(function(err) {
       _("Body is " + this.response.body);
       _("Modified is " + this.response.newModified);
       let parsedBody = JSON.parse(this.response.body);
       do_check_eq(parsedBody.id, "foos");
       do_check_eq(parsedBody.modified, coll.wbo("foos").modified);
       do_check_eq(JSON.parse(parsedBody.payload).foo, "bar");
-      Utils.nextTick(next);
+      CommonUtils.nextTick(next);
     });
   }
   function deleteWBONotExists(next) {
     let req = localRequest(server, keysURL);
     server.callback.onItemDeleted = function(username, collection, wboID) {
       do_throw("onItemDeleted should not have been called.");
     };
 
     req.delete(function(err) {
       _("Body is " + this.response.body);
       _("Modified is " + this.response.newModified);
       do_check_eq(this.response.status, 200);
       delete server.callback.onItemDeleted;
-      Utils.nextTick(next);
+      CommonUtils.nextTick(next);
     });
   }
   function deleteWBOExists(next) {
     let req = localRequest(server, foosURL);
     server.callback.onItemDeleted = function(username, collection, wboID) {
       _("onItemDeleted called for " + collection + "/" + wboID);
       delete server.callback.onItemDeleted;
       do_check_eq(username, "john");
       do_check_eq(collection, "crypto");
       do_check_eq(wboID, "foos");
-      Utils.nextTick(next);
+      CommonUtils.nextTick(next);
     };
 
     req.delete(function(err) {
       _("Body is " + this.response.body);
       _("Modified is " + this.response.newModified);
       do_check_eq(this.response.status, 200);
     });
   }
@@ -221,34 +222,34 @@ add_test(function test_storage_request()
     _("Timestamp: " + now);
     let req = localRequest(server, storageURL);
     req.delete(function(err) {
       _("Body is " + this.response.body);
       _("Modified is " + this.response.newModified);
       let parsedBody = JSON.parse(this.response.body);
       do_check_true(parsedBody >= now);
       do_check_empty(server.users.john.collections);
-      Utils.nextTick(next);
+      CommonUtils.nextTick(next);
     });
   }
   function getStorageFails(next) {
     _("Testing that GET on /storage fails.");
     let req = localRequest(server, storageURL);
     req.get(function(err) {
       do_check_eq(this.response.status, 405);
       do_check_eq(this.response.headers.allow, "DELETE");
-      Utils.nextTick(next);
+      CommonUtils.nextTick(next);
     });
   }
   function getMissingCollectionWBO(next) {
     _("Testing that fetching a WBO from an on-existent collection 404s.");
     let req = localRequest(server, storageURL + "/foobar/baz");
     req.get(function(err) {
       do_check_eq(this.response.status, 404);
-      Utils.nextTick(next);
+      CommonUtils.nextTick(next);
     });
   }
 
   server.start(null,
     Async.chain(
       retrieveWBONotExists,
       retrieveWBOExists,
       deleteWBOExists,
--- a/services/sync/tests/unit/test_interval_triggers.js
+++ b/services/sync/tests/unit/test_interval_triggers.js
@@ -1,11 +1,12 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
+Cu.import("resource://services-common/utils.js");
 Cu.import("resource://services-sync/constants.js");
 Cu.import("resource://services-sync/engines.js");
 Cu.import("resource://services-sync/engines/clients.js");
 Cu.import("resource://services-sync/util.js");
 Cu.import("resource://testing-common/services/sync/utils.js");
 
 Svc.Prefs.set("registerEngines", "");
 Cu.import("resource://services-sync/service.js");
@@ -380,17 +381,17 @@ add_task(async function test_bug671378_s
 
   // Set nextSync != 0
   // syncInterval still hasn't been set by call to updateClientMode.
   // Explicitly trying to invoke scheduleNextSync during a sync
   // (to immitate a score update that isn't big enough to trigger a sync).
   Svc.Obs.add("weave:service:sync:start", function onSyncStart() {
     // Wait for other sync:start observers to be called so that
     // nextSync is set to 0.
-    Utils.nextTick(function() {
+    CommonUtils.nextTick(function() {
       Svc.Obs.remove("weave:service:sync:start", onSyncStart);
 
       scheduler.scheduleNextSync();
       do_check_neq(scheduler.nextSync, 0);
       do_check_eq(scheduler.syncInterval, scheduler.singleDeviceInterval);
       do_check_eq(scheduler.syncTimer.delay, scheduler.singleDeviceInterval);
     });
   });
--- a/services/sync/tests/unit/test_places_guid_downgrade.js
+++ b/services/sync/tests/unit/test_places_guid_downgrade.js
@@ -1,24 +1,25 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
+Cu.import("resource://services-common/utils.js");
 Cu.import("resource://services-common/async.js");
 Cu.import("resource://services-sync/util.js");
 Cu.import("resource://services-sync/engines.js");
 Cu.import("resource://services-sync/engines/history.js");
 Cu.import("resource://services-sync/engines/bookmarks.js");
 Cu.import("resource://services-sync/service.js");
 
 const kDBName = "places.sqlite";
 const storageSvc = Cc["@mozilla.org/storage/service;1"]
                      .getService(Ci.mozIStorageService);
 
-const fxuri = Utils.makeURI("http://getfirefox.com/");
-const tburi = Utils.makeURI("http://getthunderbird.com/");
+const fxuri = CommonUtils.makeURI("http://getfirefox.com/");
+const tburi = CommonUtils.makeURI("http://getthunderbird.com/");
 
 function setPlacesDatabase(aFileName) {
   removePlacesDatabase();
   _("Copying over places.sqlite.");
   let file = do_get_file(aFileName);
   file.copyTo(gSyncProfile, kDBName);
 }
 
--- a/services/sync/tests/unit/test_resource.js
+++ b/services/sync/tests/unit/test_resource.js
@@ -1,13 +1,14 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 Cu.import("resource://gre/modules/Log.jsm");
 Cu.import("resource://services-common/observers.js");
+Cu.import("resource://services-common/utils.js");
 Cu.import("resource://services-sync/resource.js");
 Cu.import("resource://services-sync/status.js");
 Cu.import("resource://services-sync/util.js");
 Cu.import("resource://services-sync/browserid_identity.js");
 Cu.import("resource://testing-common/services/sync/utils.js");
 
 var fetched = false;
 function server_open(metadata, response) {
@@ -482,16 +483,16 @@ add_task(async function test() {
   _("Testing URI construction.");
   let args = [];
   args.push("newer=" + 1234);
   args.push("limit=" + 1234);
   args.push("sort=" + 1234);
 
   let query = "?" + args.join("&");
 
-  let uri1 = Utils.makeURI("http://foo/" + query)
+  let uri1 = CommonUtils.makeURI("http://foo/" + query)
                   .QueryInterface(Ci.nsIURL);
-  let uri2 = Utils.makeURI("http://foo/")
+  let uri2 = CommonUtils.makeURI("http://foo/")
                   .QueryInterface(Ci.nsIURL);
   uri2.query = query;
   do_check_eq(uri1.query, uri2.query);
   server.stop(do_test_finished);
 });
--- a/services/sync/tests/unit/test_resource_async.js
+++ b/services/sync/tests/unit/test_resource_async.js
@@ -1,13 +1,14 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 Cu.import("resource://gre/modules/Log.jsm");
 Cu.import("resource://services-common/observers.js");
+Cu.import("resource://services-common/utils.js");
 Cu.import("resource://services-sync/resource.js");
 Cu.import("resource://services-sync/util.js");
 Cu.import("resource://services-sync/browserid_identity.js");
 Cu.import("resource://testing-common/services/sync/utils.js");
 
 var logger;
 
 var fetched = false;
@@ -603,19 +604,19 @@ add_test(function test_uri_construction(
   _("Testing URI construction.");
   let args = [];
   args.push("newer=" + 1234);
   args.push("limit=" + 1234);
   args.push("sort=" + 1234);
 
   let query = "?" + args.join("&");
 
-  let uri1 = Utils.makeURI("http://foo/" + query)
+  let uri1 = CommonUtils.makeURI("http://foo/" + query)
                   .QueryInterface(Ci.nsIURL);
-  let uri2 = Utils.makeURI("http://foo/")
+  let uri2 = CommonUtils.makeURI("http://foo/")
                   .QueryInterface(Ci.nsIURL);
   uri2.query = query;
   do_check_eq(uri1.query, uri2.query);
 
   run_next_test();
 });
 
 /**
--- a/services/sync/tests/unit/test_syncstoragerequest.js
+++ b/services/sync/tests/unit/test_syncstoragerequest.js
@@ -1,12 +1,13 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 Cu.import("resource://gre/modules/Log.jsm");
+Cu.import("resource://services-common/utils.js");
 Cu.import("resource://services-sync/constants.js");
 Cu.import("resource://services-sync/rest.js");
 Cu.import("resource://services-sync/service.js");
 Cu.import("resource://services-sync/util.js");
 Cu.import("resource://testing-common/services/sync/utils.js");
 
 var httpProtocolHandler = Cc["@mozilla.org/network/protocol;1?name=http"]
                           .getService(Ci.nsIHttpProtocolHandler);
@@ -201,17 +202,17 @@ add_test(function test_abort() {
   request.abort();
   do_check_eq(request.status, request.ABORTED);
 
   // Aborting an already aborted request is pointless and will throw.
   do_check_throws(function() {
     request.abort();
   });
 
-  Utils.nextTick(function() {
+  CommonUtils.nextTick(function() {
     // Verify that we didn't try to process any of the values.
     do_check_eq(SyncStorageRequest.serverTime, undefined);
 
     Svc.Obs.remove("weave:service:backoff:interval", throwy);
     Svc.Obs.remove("weave:service:quota:remaining", throwy);
 
     server.stop(run_next_test);
   });
--- a/services/sync/tests/unit/test_telemetry.js
+++ b/services/sync/tests/unit/test_telemetry.js
@@ -1,12 +1,13 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 Cu.import("resource://services-common/observers.js");
+Cu.import("resource://services-common/utils.js");
 Cu.import("resource://services-sync/telemetry.js");
 Cu.import("resource://services-sync/service.js");
 Cu.import("resource://services-sync/record.js");
 Cu.import("resource://services-sync/resource.js");
 Cu.import("resource://services-sync/constants.js");
 Cu.import("resource://services-sync/engines.js");
 Cu.import("resource://services-sync/engines/bookmarks.js");
 Cu.import("resource://services-sync/engines/clients.js");
@@ -159,17 +160,17 @@ add_task(async function test_processInco
 add_task(async function test_uploading() {
   let engine = new BookmarksEngine(Service);
   await engine.initialize();
   let store  = engine._store;
   let server = serverForFoo(engine);
   await SyncTestingInfrastructure(server);
 
   let parent = PlacesUtils.toolbarFolderId;
-  let uri = Utils.makeURI("http://getfirefox.com/");
+  let uri = CommonUtils.makeURI("http://getfirefox.com/");
 
   let bmk_id = PlacesUtils.bookmarks.insertBookmark(parent, uri,
     PlacesUtils.bookmarks.DEFAULT_INDEX, "Get Firefox!");
 
   try {
     let ping = await sync_engine_and_validate_telem(engine, false);
     ok(!!ping);
     equal(ping.engines.length, 1);
--- a/services/sync/tps/extensions/tps/resource/tps.jsm
+++ b/services/sync/tps/extensions/tps/resource/tps.jsm
@@ -19,16 +19,17 @@ Cu.import("resource://gre/modules/XPCOMU
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/AppConstants.jsm");
 Cu.import("resource://gre/modules/PlacesUtils.jsm");
 Cu.import("resource://gre/modules/FileUtils.jsm");
 Cu.import("resource://gre/modules/Timer.jsm");
 Cu.import("resource://gre/modules/PromiseUtils.jsm");
 Cu.import("resource://gre/modules/osfile.jsm");
 Cu.import("resource://services-common/async.js");
+Cu.import("resource://services-common/utils.js");
 Cu.import("resource://services-sync/constants.js");
 Cu.import("resource://services-sync/main.js");
 Cu.import("resource://services-sync/util.js");
 Cu.import("resource://services-sync/telemetry.js");
 Cu.import("resource://services-sync/bookmark_validator.js");
 Cu.import("resource://services-sync/engines/passwords.js");
 Cu.import("resource://services-sync/engines/forms.js");
 Cu.import("resource://services-sync/engines/addons.js");
@@ -202,17 +203,17 @@ var TPS = {
           this._syncActive = false;
 
           this.delayAutoSync();
 
           // If this is the first sync error, retry...
           if (this._syncErrors === 0) {
             Logger.logInfo("Sync error; retrying...");
             this._syncErrors++;
-            Utils.nextTick(() => {
+            CommonUtils.nextTick(() => {
               this.RunNextTestAction().catch(err => {
                 this.DumpError("RunNextTestActionFailed", err);
               });
             });
           } else {
             this._triggeredSync = false;
             this.DumpError("Sync error; aborting test");
             return;
@@ -224,17 +225,17 @@ var TPS = {
           this._syncActive = false;
           this._syncErrors = 0;
           this._triggeredSync = false;
 
           this.delayAutoSync();
 
           // Wait a second before continuing, otherwise we can get
           // 'sync not complete' errors.
-          Utils.namedTimer(function() {
+          CommonUtils.namedTimer(function() {
             this.FinishAsyncOperation();
           }, 1000, this, "postsync");
 
           break;
 
         case "weave:service:sync:start":
           // Ensure that the sync operation has been started by TPS
           if (!this._triggeredSync) {
@@ -282,17 +283,17 @@ var TPS = {
     // auth/fxaccounts.jsm calling back into this module). So we just assume
     // the FinishAsyncOperation without a StartAsyncOperation is fine, and works
     // as if a StartAsyncOperation had been called.
     if (this._operations_pending) {
       this._operations_pending--;
     }
     if (!this.operations_pending) {
       this._currentAction++;
-      Utils.nextTick(function() {
+      CommonUtils.nextTick(function() {
         this.RunNextTestAction().catch(err => {
           this.DumpError("RunNextTestActionFailed", err);
         });
       }, this);
     }
   },
 
   quit: function TPS__quit() {
@@ -330,17 +331,17 @@ var TPS = {
           BrowserTabs.Add(tab.uri, function() {
             that._tabsFinished++;
             Logger.logInfo("tab for " + taburi + " finished loading");
             if (that._tabsFinished == that._tabsAdded) {
               Logger.logInfo("all tabs loaded, continuing...");
 
               // Wait some time before continuing to be sure tabs can be synced,
               // otherwise we can get 'error locating tab' (bug 1383832).
-              Utils.namedTimer(function() {
+              CommonUtils.namedTimer(function() {
                 that.FinishAsyncOperation();
               }, 2500, this, "postTabsOpening");
             }
           });
           break;
         case ACTION_VERIFY:
           Logger.AssertTrue(typeof(tab.profile) != "undefined",
             "profile must be defined when verifying tabs");
@@ -584,17 +585,17 @@ var TPS = {
 
   MozmillEndTestListener: function TPS__MozmillEndTestListener(obj) {
     Logger.logInfo("mozmill endTest: " + JSON.stringify(obj));
     if (obj.failed > 0) {
       this.DumpError("mozmill test failed, name: " + obj.name + ", reason: " + JSON.stringify(obj.fails));
     } else if ("skipped" in obj && obj.skipped) {
       this.DumpError("mozmill test failed, name: " + obj.name + ", reason: " + obj.skipped_reason);
     } else {
-      Utils.namedTimer(function() {
+      CommonUtils.namedTimer(function() {
         this.FinishAsyncOperation();
       }, 2000, this, "postmozmilltest");
     }
   },
 
   MozmillSetTestListener: function TPS__MozmillSetTestListener(obj) {
     Logger.logInfo("mozmill setTest: " + obj.name);
   },
--- a/toolkit/components/extensions/ExtensionStorageSync.jsm
+++ b/toolkit/components/extensions/ExtensionStorageSync.jsm
@@ -119,17 +119,17 @@ this.extensionStorageSync = null;
  * @param {KeyBundle} keyBundle  The key bundle to use to compute the HMAC
  * @param {string}    id         The record ID to use when computing the HMAC
  * @param {string}    IV         The IV to use when computing the HMAC
  * @param {string}    ciphertext The ciphertext over which to compute the HMAC
  * @returns {string} The computed HMAC
  */
 function ciphertextHMAC(keyBundle, id, IV, ciphertext) {
   const hasher = keyBundle.sha256HMACHasher;
-  return Utils.bytesAsHex(Utils.digestUTF8(id + IV + ciphertext, hasher));
+  return CommonUtils.bytesAsHex(Utils.digestUTF8(id + IV + ciphertext, hasher));
 }
 
 /**
  * Get the current user's hashed kB.
  *
  * @param {FXAccounts} fxaService  The service to use to get the
  *     current user.
  * @returns {string} sha256 of the user's kB as a hex string
@@ -269,17 +269,17 @@ class KeyRingEncryptionRemoteTransformer
       if (!user) {
         throw new Error("user isn't signed in to FxA; can't sync");
       }
 
       if (!user.kB) {
         throw new Error("user doesn't have kB");
       }
 
-      let kB = Utils.hexToBytes(user.kB);
+      let kB = CommonUtils.hexToBytes(user.kB);
 
       let keyMaterial = CryptoUtils.hkdf(kB, undefined,
                                        "identity.mozilla.com/picl/v1/chrome.storage.sync", 2 * 32);
       let bundle = new BulkKeyBundle();
       // [encryptionKey, hmacKey]
       bundle.keyPair = [keyMaterial.slice(0, 32), keyMaterial.slice(32, 64)];
       return bundle;
     })();