Bug 1073027 - Control MozLoopService logging with a preference. r=jaws
authorMatthew Noorenberghe <mozilla@noorenberghe.ca>
Thu, 25 Sep 2014 09:00:32 -0700
changeset 207318 f5a053aaba52e9f6b86ea0cbfa679410931de1c6
parent 207317 bcd0d2b817a849aafb3081c0e0081ec9a102d3a4
child 207319 06a1582f7d5f04cbdff8565001574ef73261c65a
push id8996
push usermozilla@noorenberghe.ca
push dateThu, 25 Sep 2014 21:34:45 +0000
treeherderfx-team@06a1582f7d5f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjaws
bugs1073027
milestone35.0a1
Bug 1073027 - Control MozLoopService logging with a preference. r=jaws
browser/app/profile/firefox.js
browser/components/loop/MozLoopService.jsm
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1608,16 +1608,17 @@ pref("loop.seenToS", "unseen");
 pref("loop.legal.ToS_url", "https://call.mozilla.com/legal/terms/");
 pref("loop.legal.privacy_url", "https://www.mozilla.org/privacy/");
 pref("loop.do_not_disturb", false);
 pref("loop.ringtone", "chrome://browser/content/loop/shared/sounds/Firefox-Long.ogg");
 pref("loop.retry_delay.start", 60000);
 pref("loop.retry_delay.limit", 300000);
 pref("loop.feedback.baseUrl", "https://input.mozilla.org/api/v1/feedback");
 pref("loop.feedback.product", "Loop");
+pref("loop.debug.loglevel", "Error");
 pref("loop.debug.websocket", false);
 pref("loop.debug.sdk", false);
 
 // serverURL to be assigned by services team
 pref("services.push.serverURL", "wss://push.services.mozilla.com/");
 
 pref("social.sidebar.unload_timeout_ms", 10000);
 
--- a/browser/components/loop/MozLoopService.jsm
+++ b/browser/components/loop/MozLoopService.jsm
@@ -15,29 +15,29 @@ const INVALID_AUTH_TOKEN = 110;
 // serving" number of 2^24 - 1 is greater than it.
 const MAX_SOFT_START_TICKET_NUMBER = 16777214;
 
 const LOOP_SESSION_TYPE = {
   GUEST: 1,
   FXA: 2,
 };
 
+// See LOG_LEVELS in Console.jsm. Common examples: "All", "Info", "Warn", & "Error".
+const PREF_LOG_LEVEL = "loop.debug.loglevel";
+
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Promise.jsm");
 Cu.import("resource://gre/modules/osfile.jsm", this);
 Cu.import("resource://gre/modules/Task.jsm");
 Cu.import("resource://gre/modules/FxAccountsOAuthClient.jsm");
 Cu.importGlobalProperties(["URL"]);
 
 this.EXPORTED_SYMBOLS = ["MozLoopService", "LOOP_SESSION_TYPE"];
 
-XPCOMUtils.defineLazyModuleGetter(this, "console",
-  "resource://gre/modules/devtools/Console.jsm");
-
 XPCOMUtils.defineLazyModuleGetter(this, "injectLoopAPI",
   "resource:///modules/loop/MozLoopAPI.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "convertToRTCStatsReport",
   "resource://gre/modules/media/RTCStatsReport.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "Chat", "resource:///modules/Chat.jsm");
 
@@ -62,16 +62,25 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 XPCOMUtils.defineLazyServiceGetter(this, "uuidgen",
                                    "@mozilla.org/uuid-generator;1",
                                    "nsIUUIDGenerator");
 
 XPCOMUtils.defineLazyServiceGetter(this, "gDNSService",
                                    "@mozilla.org/network/dns-service;1",
                                    "nsIDNSService");
 
+// Create a new instance of the ConsoleAPI so we can control the maxLogLevel with a pref.
+XPCOMUtils.defineLazyGetter(this, "log", () => {
+  let ConsoleAPI = Cu.import("resource://gre/modules/devtools/Console.jsm", {}).ConsoleAPI;
+  let consoleOptions = {
+    maxLogLevel: Services.prefs.getCharPref(PREF_LOG_LEVEL).toLowerCase(),
+    prefix: "Loop",
+  };
+  return new ConsoleAPI(consoleOptions);
+});
 
 // The current deferred for the registration process. This is set if in progress
 // or the registration was successful. This is null if a registration attempt was
 // unsuccessful.
 let gRegisteredDeferred = null;
 let gPushHandler = null;
 let gHawkClient = null;
 let gLocalizedStrings =  null;
@@ -107,17 +116,17 @@ CallProgressSocket.prototype = {
    *
    * @param {function} Callback used after a successful handshake
    *                   over the progressUrl.
    * @param {function} Callback used if an error is encountered
    */
   connect: function(onSuccess, onError) {
     this._onSuccess = onSuccess;
     this._onError = onError ||
-      (reason => {console.warn("MozLoopService::callProgessSocket - ", reason);});
+      (reason => {log.warn("MozLoopService::callProgessSocket - ", reason);});
 
     if (!onSuccess) {
       this._onError("missing onSuccess argument");
       return;
     }
 
     if (Services.io.offline) {
       this._onError("IO offline");
@@ -188,17 +197,17 @@ CallProgressSocket.prototype = {
    * @param {String} aMsg The message data
    */
   onMessageAvailable: function(aContext, aMsg) {
     let msg = {};
     try {
       msg = JSON.parse(aMsg);
     }
     catch (error) {
-      console.error("MozLoopService: error parsing progress message - ", error);
+      log.error("MozLoopService: error parsing progress message - ", error);
       return;
     }
 
     if (msg.messageType && msg.messageType === 'hello') {
       this._handshakeComplete = true;
       this._onSuccess();
     }
   },
@@ -206,17 +215,17 @@ CallProgressSocket.prototype = {
 
   /**
    * Create a JSON message payload and send on websocket.
    *
    * @param {Object} aMsg Message to send.
    */
   _send: function(aMsg) {
     if (!this._handshakeComplete) {
-      console.warn("MozLoopService::_send error - handshake not complete");
+      log.warn("MozLoopService::_send error - handshake not complete");
       return;
     }
 
     try {
       this._websocket.sendMsg(JSON.stringify(aMsg));
     }
     catch (error) {
       this._onError(error);
@@ -407,17 +416,17 @@ let MozLoopServiceInternal = {
   /**
    * Generic hawkRequest onError handler for the hawkRequest promise.
    *
    * @param {Object} error - error reporting object
    *
    */
 
   _hawkRequestError: function(error) {
-    console.error("Loop hawkRequest error:", error);
+    log.error("Loop hawkRequest error:", error);
     throw error;
   },
 
   getSessionTokenPrefName: function(sessionType) {
     let suffix;
     switch (sessionType) {
       case LOOP_SESSION_TYPE.GUEST:
         suffix = "";
@@ -444,17 +453,17 @@ let MozLoopServiceInternal = {
   storeSessionToken: function(sessionType, headers) {
     let sessionToken = headers["hawk-session-token"];
     if (sessionToken) {
       // XXX should do more validation here
       if (sessionToken.length === 64) {
         Services.prefs.setCharPref(this.getSessionTokenPrefName(sessionType), sessionToken);
       } else {
         // XXX Bubble the precise details up to the UI somehow (bug 1013248).
-        console.warn("Loop server sent an invalid session token");
+        log.warn("Loop server sent an invalid session token");
         gRegisteredDeferred.reject("session-token-wrong-size");
         gRegisteredDeferred = null;
         return false;
       }
     }
     return true;
   },
 
@@ -489,17 +498,17 @@ let MozLoopServiceInternal = {
       // storeSessionToken could have rejected and nulled the promise if the token was malformed.
       if (!gRegisteredDeferred) {
         return;
       }
       gRegisteredDeferred.resolve();
       // No need to clear the promise here, everything was good, so we don't need
       // to re-register.
     }, (error) => {
-      console.error("Failed to register with Loop server: ", error);
+      log.error("Failed to register with Loop server: ", error);
       gRegisteredDeferred.reject(error.errno);
       gRegisteredDeferred = null;
     });
   },
 
   /**
    * Registers with the Loop server either as a guest or a FxA user.
    *
@@ -531,17 +540,17 @@ let MozLoopServiceInternal = {
           // Authorization failed, invalid token, we need to try again with a new token.
           this.clearSessionToken(sessionType);
           if (retry) {
             return this.registerWithLoopServer(sessionType, pushUrl, false);
           }
         }
 
         // XXX Bubble the precise details up to the UI somehow (bug 1013248).
-        console.error("Failed to register with the loop server. Error: ", error);
+        log.error("Failed to register with the loop server. Error: ", error);
         this.setError("registration", error);
         throw error;
       }
     );
   },
 
   /**
    * Unregisters from the Loop server either as a guest or a FxA user.
@@ -563,17 +572,17 @@ let MozLoopServiceInternal = {
       error => {
         // Always clear the registration token regardless of whether the server acknowledges the logout.
         MozLoopServiceInternal.clearSessionToken(sessionType);
         if (error.code === 401 && error.errno === INVALID_AUTH_TOKEN) {
           // Authorization failed, invalid token. This is fine since it may mean we already logged out.
           return;
         }
 
-        console.error("Failed to unregister with the loop server. Error: ", error);
+        log.error("Failed to unregister with the loop server. Error: ", error);
         throw error;
       });
   },
 
   /**
    * Callback from MozLoopPushHandler - A push notification has been received from
    * the server.
    *
@@ -640,20 +649,20 @@ let MozLoopServiceInternal = {
               null,
               this.localizedStrings["incoming_call_title2"].textContent,
               "about:loopconversation#incoming/" + callData.callId);
           } else {
             this._returnBusy(callData);
           }
         });
       } else {
-        console.warn("Error: missing calls[] in response");
+        log.warn("Error: missing calls[] in response");
       }
     } catch (err) {
-      console.warn("Error parsing calls info", err);
+      log.warn("Error parsing calls info", err);
     }
   },
 
    /**
    * Open call progress websocket and terminate with a reason of busy
    * the server.
    *
    * @param {callData} Must contain the progressURL, callId and websocketToken
@@ -755,17 +764,17 @@ let MozLoopServiceInternal = {
           }
         };
 
         // Send job to worker to do log sanitation, transcoding and saving to
         // disk for pickup by telemetry on next startup, which then uploads it.
 
         let worker = new ChromeWorker("MozLoopWorker.js");
         worker.onmessage = function(e) {
-          console.log(e.data.ok ?
+          log.info(e.data.ok ?
             "Successfully staged loop report for telemetry upload." :
             ("Failed to stage loop report. Error: " + e.data.fail));
         }
         worker.postMessage(job);
       });
     }, pc.id);
   },
 
@@ -893,17 +902,17 @@ let MozLoopServiceInternal = {
   promiseFxAOAuthAuthorization: function() {
     let deferred = Promise.defer();
     this.promiseFxAOAuthClient().then(
       client => {
         client.onComplete = this._fxAOAuthComplete.bind(this, deferred);
         client.launchWebFlow();
       },
       error => {
-        console.error(error);
+        log.error(error);
         deferred.reject(error);
       }
     );
     return deferred.promise;
   },
 
   /**
    * Get the OAuth token using the OAuth code and state.
@@ -1063,17 +1072,17 @@ this.MozLoopService = {
       // Can't use bitwise operations here because JS treats all bitwise
       // operations as 32-bit *signed* integers.
       let now_serving = ((parseInt(address[1]) * 0x10000) +
                          (parseInt(address[2]) * 0x100) +
                          parseInt(address[3]));
 
       if (now_serving > ticket) {
         // Hot diggity! It's our turn! Activate the service.
-        console.log("MozLoopService: Activating Loop via soft-start");
+        log.info("MozLoopService: Activating Loop via soft-start");
         Services.prefs.setBoolPref("loop.throttled", false);
         buttonNode.hidden = false;
         this.initialize();
       }
       if (typeof(doneCb) == "function") {
         doneCb(null);
       }
     };
@@ -1229,17 +1238,17 @@ this.MozLoopService = {
    * @param {String} value The value to set.
    *
    * Any errors thrown by the Mozilla pref API are logged to the console.
    */
   setLoopCharPref: function(prefName, value) {
     try {
       Services.prefs.setCharPref("loop." + prefName, value);
     } catch (ex) {
-      console.log("setLoopCharPref had trouble setting " + prefName +
+      log.error("setLoopCharPref had trouble setting " + prefName +
         "; exception: " + ex);
     }
   },
 
   /**
    * Return any preference under "loop." that's coercible to a character
    * preference.
    *
@@ -1251,17 +1260,17 @@ this.MozLoopService = {
    * not being found.
    *
    * @return {String} on success, null on error
    */
   getLoopCharPref: function(prefName) {
     try {
       return Services.prefs.getCharPref("loop." + prefName);
     } catch (ex) {
-      console.log("getLoopCharPref had trouble getting " + prefName +
+      log.error("getLoopCharPref had trouble getting " + prefName +
         "; exception: " + ex);
       return null;
     }
   },
 
   /**
    * Return any preference under "loop." that's coercible to a character
    * preference.
@@ -1274,17 +1283,17 @@ this.MozLoopService = {
    * not being found.
    *
    * @return {String} on success, null on error
    */
   getLoopBoolPref: function(prefName) {
     try {
       return Services.prefs.getBoolPref("loop." + prefName);
     } catch (ex) {
-      console.log("getLoopBoolPref had trouble getting " + prefName +
+      log.error("getLoopBoolPref had trouble getting " + prefName +
         "; exception: " + ex);
       return null;
     }
   },
 
   /**
    * Start the FxA login flow using the OAuth client and params from the Loop server.
    *
@@ -1315,17 +1324,17 @@ this.MozLoopService = {
       let client = new FxAccountsProfileClient({
         serverURL: gFxAOAuthClient.parameters.profile_uri,
         token: tokenData.access_token
       });
       client.fetchProfile().then(result => {
         gFxAOAuthProfile = result;
         MozLoopServiceInternal.notifyStatusChanged("login");
       }, error => {
-        console.error("Failed to retrieve profile", error);
+        log.error("Failed to retrieve profile", error);
         gFxAOAuthProfile = null;
         MozLoopServiceInternal.notifyStatusChanged();
       });
       return tokenData;
     }).catch(error => {
       gFxAOAuthTokenData = null;
       gFxAOAuthProfile = null;
       throw error;