Bug 1157258: Fix null type comparisons in driver.js draft
authorAndreas Tolfsen <ato@mozilla.com>
Fri, 24 Apr 2015 13:55:52 +0100
changeset 259329 9e828854e4a794aba9807ced38532eefafe8531f
parent 259327 86d3308ec8888fae794772b04f4c8aef59574402
child 506292 47ed59bd9b6aa2a87a189685115e37ed41bbf166
push id1724
push useratolfsen@mozilla.com
push dateFri, 24 Apr 2015 16:11:19 +0000
bugs1157258
milestone40.0a1
Bug 1157258: Fix null type comparisons in driver.js r=davehunt
testing/marionette/driver.js
--- a/testing/marionette/driver.js
+++ b/testing/marionette/driver.js
@@ -351,18 +351,18 @@ GeckoDriver.prototype.sendAsync = functi
 
 /**
  * Gets the current active window.
  *
  * @return {nsIDOMWindow}
  */
 GeckoDriver.prototype.getCurrentWindow = function() {
   let typ = null;
-  if (this.curFrame == null) {
-    if (this.curBrowser == null) {
+  if (this.curFrame === null) {
+    if (this.curBrowser === null) {
       if (this.context == Context.CONTENT) {
         typ = 'navigator:browser';
       }
       return Services.wm.getMostRecentWindow(typ);
     } else {
       return this.curBrowser.window;
     }
   } else {
@@ -454,17 +454,17 @@ GeckoDriver.prototype.whenBrowserStarted
   try {
     let mm = win.window.messageManager;
     if (!isNewSession) {
       // Loading the frame script corresponds to a situation we need to
       // return to the server. If the messageManager is a message broadcaster
       // with no children, we don't have a hope of coming back from this call,
       // so send the ack here. Otherwise, make a note of how many child scripts
       // will be loaded so we known when it's safe to return.
-      if (mm.childCount != 0) {
+      if (mm.childCount !== 0) {
         this.curBrowser.frameRegsPending = mm.childCount;
       }
     }
 
     if (!Services.prefs.getBoolPref("marionette.contentListener") || !isNewSession) {
       mm.loadFrameScript(FRAME_SCRIPT, true, true);
       Services.prefs.setBoolPref("marionette.contentListener", true);
     }
@@ -513,17 +513,17 @@ GeckoDriver.prototype.deleteFile = funct
   }
 };
 
 /**
  * Handles registration of new content listener browsers.  Depending on
  * their type they are either accepted or ignored.
  */
 GeckoDriver.prototype.registerBrowser = function(id, be) {
-  let nullPrevious = this.curBrowser.curFrameId == null;
+  let nullPrevious = this.curBrowser.curFrameId === null;
   let listenerWindow = Services.wm.getOuterWindowWithId(id);
 
   // go in here if we're already in a remote frame
   if (this.curBrowser.frameManager.currentRemoteFrame !== null &&
       (!listenerWindow || this.mm == this.curBrowser.frameManager
           .currentRemoteFrame.messageManager.get())) {
     // The outerWindowID from an OOP frame will not be meaningful to
     // the parent process here, since each process maintains its own
@@ -537,34 +537,33 @@ GeckoDriver.prototype.registerBrowser = 
     // TODO: Should have a better way of determining that this message
     // is from a remote frame.
     this.curBrowser.frameManager.currentRemoteFrame.targetFrameId =
         this.generateFrameId(id);
   }
 
   let reg = {};
   // this will be sent to tell the content process if it is the main content
-  let mainContent = this.curBrowser.mainContentId == null;
+  let mainContent = this.curBrowser.mainContentId === null;
   if (be.getAttribute("type") != "content") {
     // curBrowser holds all the registered frames in knownFrames
     let uid = this.generateFrameId(id);
     reg.id = uid;
     reg.remotenessChange = this.curBrowser.register(uid, be);
   }
 
   // set to true if we updated mainContentId
-  mainContent = mainContent == true &&
-      this.curBrowser.mainContentId != null;
+  mainContent = mainContent && this.curBrowser.mainContentId !== null;
   if (mainContent) {
     this.mainContentFrameId = this.curBrowser.curFrameId;
   }
 
   this.curBrowser.elementManager.seenItems[reg.id] =
       Cu.getWeakReference(listenerWindow);
-  if (nullPrevious && (this.curBrowser.curFrameId != null)) {
+  if (nullPrevious && (this.curBrowser.curFrameId !== null)) {
     this.sendAsync("newSession",
         {
           B2G: (this.appName == "B2G"),
           raisesAccessibilityExceptions:
               this.sessionCapabilities.raisesAccessibilityExceptions
         },
         this.newSessionCommandId);
     if (this.curBrowser.isNewSession) {
@@ -583,17 +582,17 @@ GeckoDriver.prototype.registerPromise = 
       let wid = msg.json.value;
       let be = msg.target;
       let rv = this.registerBrowser(wid, be);
 
       if (this.curBrowser.frameRegsPending > 0) {
         this.curBrowser.frameRegsPending--;
       }
 
-      if (this.curBrowser.frameRegsPending == 0) {
+      if (this.curBrowser.frameRegsPending === 0) {
         this.mm.removeMessageListener(li, cb);
         resolve();
       }
 
       // this is a sync message and listeners expect the ID back
       return rv;
     }.bind(this));
   });
@@ -748,17 +747,17 @@ GeckoDriver.prototype.setSessionCapabili
             errors[caps] = from[key][caps] + " does not equal " +
                 this.sessionCapabilities[caps];
           }
         }
       }
       to[key] = from[key];
     }
 
-    if (Object.keys(errors).length == 0) {
+    if (Object.keys(errors).length === 0) {
       return to;
     }
 
     throw new SessionNotCreatedError(
         `Not all requiredCapabilities could be met: ${JSON.stringify(errors)}`);
   };
 
   // clone, overwrite, and set
@@ -878,33 +877,33 @@ GeckoDriver.prototype.applyArgumentsToSa
  */
 GeckoDriver.prototype.executeScriptInSandbox = function(
     resp,
     sandbox,
     script,
     directInject,
     async,
     timeout) {
-  if (directInject && async && (timeout == null || timeout == 0)) {
+  if (directInject && async && (timeout === null || timeout === 0)) {
     throw new TimeoutError("Please set a timeout");
   }
 
   if (this.importedScripts.exists()) {
     let stream = Cc["@mozilla.org/network/file-input-stream;1"]
         .createInstance(Ci.nsIFileInputStream);
     stream.init(this.importedScripts, -1, 0, 0);
     let data = NetUtil.readInputStreamToString(stream, stream.available());
     stream.close();
     script = data + script;
   }
 
   let res = Cu.evalInSandbox(script, sandbox, "1.8", "dummy file", 0);
 
   if (directInject && !async &&
-      (res == undefined || res.passed == undefined)) {
+      (typeof res == "undefined" || typeof res.passed == "undefined")) {
     throw new WebDriverError("finish() not called");
   }
 
   if (!async) {
     // It's fine to pass on and modify resp here because
     // executeScriptInSandbox is the last function to be called
     // in execute and executeWithCallback respectively.
     resp.value = this.curBrowser.elementManager.wrapValue(res);
@@ -948,17 +947,17 @@ GeckoDriver.prototype.execute = function
     return;
   }
 
   // handle the inactivity timeout
   let that = this;
   if (inactivityTimeout) {
     let setTimer = function() {
       that.inactivityTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
-      if (that.inactivityTimer != null) {
+      if (that.inactivityTimer !== null) {
         that.inactivityTimer.initWithCallback(function() {
           throw new ScriptTimeoutError("timed out due to inactivity");
         }, inactivityTimeout, Ci.nsITimer.TYPE_ONE_SHOT);
       }
     };
     setTimer();
     this.heartbeatCallback = function() {
       that.inactivityTimer.cancel();
@@ -983,17 +982,17 @@ GeckoDriver.prototype.execute = function
     if (!this.sandbox) {
       return;
     }
   }
   this.applyArgumentsToSandbox(win, this.sandbox, args);
 
   try {
     this.sandbox.finish = () => {
-      if (this.inactivityTimer != null) {
+      if (this.inactivityTimer !== null) {
         this.inactivityTimer.cancel();
       }
       return this.sandbox.generate_results();
     };
 
     if (!directInject) {
       script = `let func = function() { ${script} }; func.apply(null, __marionetteParams);`;
     }
@@ -1109,25 +1108,25 @@ GeckoDriver.prototype.executeWithCallbac
     });
     return;
   }
 
   // handle the inactivity timeout
   let that = this;
   if (inactivityTimeout) {
     this.inactivityTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
-    if (this.inactivityTimer != null) {
+    if (this.inactivityTimer !== null) {
       this.inactivityTimer.initWithCallback(function() {
        chromeAsyncReturnFunc(new ScriptTimeoutError("timed out due to inactivity"));
       }, inactivityTimeout, Ci.nsITimer.TYPE_ONE_SHOT);
     }
     this.heartbeatCallback = function resetInactivityTimer() {
       that.inactivityTimer.cancel();
       that.inactivityTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
-      if (that.inactivityTimer != null) {
+      if (that.inactivityTimer !== null) {
         that.inactivityTimer.initWithCallback(function() {
           chromeAsyncReturnFunc(new ScriptTimeoutError("timed out due to inactivity"));
         }, inactivityTimeout, Ci.nsITimer.TYPE_ONE_SHOT);
       }
     };
   }
 
   let win = this.getCurrentWindow();
@@ -1137,31 +1136,31 @@ GeckoDriver.prototype.executeWithCallbac
   let res = yield new Promise(function(resolve, reject) {
     let chromeAsyncReturnFunc = function(val) {
       if (that.emulator.cbs.length > 0) {
         that.emulator.cbs = [];
         throw new WebDriverError("Emulator callback still pending when finish() called");
       }
 
       if (cmd.id == that.sandbox.command_id) {
-        if (that.timer != null) {
+        if (that.timer !== null) {
           that.timer.cancel();
           that.timer = null;
         }
 
         win.onerror = origOnError;
 
         if (error.isError(val)) {
           reject(val);
         } else {
           resolve(val);
         }
       }
 
-      if (that.inactivityTimer != null) {
+      if (that.inactivityTimer !== null) {
         that.inactivityTimer.cancel();
       }
     };
 
     let chromeAsyncFinish = function() {
       let res = that.sandbox.generate_results();
       chromeAsyncReturnFunc(res);
     };
@@ -1211,17 +1210,17 @@ GeckoDriver.prototype.executeWithCallbac
         let err = new JavaScriptError(`${msg} at: ${url} line: ${line}`);
         chromeAsyncReturnFunc(err);
         return true;
       };
     }
 
     try {
       this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
-      if (this.timer != null) {
+      if (this.timer !== null) {
         this.timer.initWithCallback(function() {
           chromeAsyncReturnFunc(new ScriptTimeoutError("timed out"));
         }, that.timeout, Ci.nsITimer.TYPE_ONE_SHOT);
       }
 
       this.sandbox.returnFunc = chromeAsyncReturnFunc;
       this.sandbox.finish = chromeAsyncFinish;
 
@@ -1312,17 +1311,17 @@ GeckoDriver.prototype.pageLoadPromise = 
   let checkTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
   let start = new Date().getTime();
   let end = null;
 
   return new Promise((resolve) => {
     let checkLoad = function() {
       end = new Date().getTime();
       let elapse = end - start;
-      if (timeout == null || elapse <= timeout) {
+      if (timeout === null || elapse <= timeout) {
         if (win.document.readyState == "complete") {
           resolve();
         } else {
           checkTimer.initWithCallback(checkLoad, 100, Ci.nsITimer.TYPE_ONE_SHOT);
         }
       } else {
         throw new UnknownError("Error loading page");
       }
@@ -1700,25 +1699,29 @@ GeckoDriver.prototype.switchToFrame = fu
       throw new UnknownError("Error loading page");
     }
 
     checkTimer.initWithCallback(checkLoad.bind(this), 100, Ci.nsITimer.TYPE_ONE_SHOT);
   };
 
   if (this.context == Context.CHROME) {
     let foundFrame = null;
-    if ((cmd.parameters.id == null) && (cmd.parameters.element == null)) {
+    
+    // Bug 1158219: Python client sends id when it shouldn't,
+    // but we know that if it's null it wants us to switch to default
+    if (cmd.parameters.id === null && !cmd.parameters.hasOwnProperty("element")) {
       this.curFrame = null;
       if (cmd.parameters.focus) {
         this.mainFrame.focus();
       }
       checkTimer.initWithCallback(checkLoad.bind(this), 100, Ci.nsITimer.TYPE_ONE_SHOT);
       return;
     }
-    if (cmd.parameters.element != undefined) {
+
+    if (typeof cmd.parameters.element != "undefined") {
       if (this.curBrowser.elementManager.seenItems[cmd.parameters.element]) {
         // HTMLIFrameElement
         let wantedFrame = this.curBrowser.elementManager
             .getKnownElement(cmd.parameters.element, curWindow);
         // Deal with an embedded xul:browser case
         if (wantedFrame.tagName == "xul:browser" || wantedFrame.tagName == "browser") {
           curWindow = wantedFrame.contentWindow;
           this.curFrame = curWindow;
@@ -1751,33 +1754,33 @@ GeckoDriver.prototype.switchToFrame = fu
       let numFrames = frames.length;
       for (let i = 0; i < numFrames; i++) {
         //give precedence to name
         let frame = frames[i];
         if (frame.getAttribute("name") == cmd.parameters.id) {
           foundFrame = i;
           curWindow = frame.contentWindow;
           break;
-        } else if ((foundById == null) && (frame.id == cmd.parameters.id)) {
+        } else if ((foundById === null) && (frame.id == cmd.parameters.id)) {
           foundById = i;
         }
       }
-      if ((foundFrame == null) && (foundById != null)) {
+      if ((foundFrame === null) && (foundById !== null)) {
         foundFrame = foundById;
         curWindow = frames[foundById].contentWindow;
       }
       break;
     case "number":
-      if (curWindow.frames[cmd.parameters.id] != undefined) {
+      if (typeof curWindow.frames[cmd.parameters.id] != "undefined") {
         foundFrame = cmd.parameters.id;
         curWindow = curWindow.frames[foundFrame].frameElement.contentWindow;
       }
       break;
     }
-    if (foundFrame != null) {
+    if (foundFrame !== null) {
       this.curFrame = curWindow;
       if (cmd.parameters.focus) {
         this.curFrame.focus();
       }
       checkTimer.initWithCallback(checkLoad.bind(this), 100, Ci.nsITimer.TYPE_ONE_SHOT);
     } else {
       throw new NoSuchFrameError(
           `Unable to locate frame: ${cmd.parameters.id}`);
@@ -1889,17 +1892,17 @@ GeckoDriver.prototype.actionChain = func
         // be conservative until this has a use case and is established
         // to work as expected on b2g/fennec
         throw new WebDriverError(
             "Command 'actionChain' is not available in chrome context");
       }
 
       let cbs = {};
       cbs.onSuccess = val => resp.value = val;
-      cbs.onError = err => { throw err };
+      cbs.onError = err => { throw err; };
 
       let win = this.getCurrentWindow();
       let elm = this.curBrowser.elementManager;
       this.actions.dispatchActions(chain, nextId, win, elm, cbs);
       break;
 
     case Context.CONTENT:
       this.addFrameCloseListener("action chain");
@@ -2520,17 +2523,17 @@ GeckoDriver.prototype.closeChromeWindow 
  * If it is a desktop environment, it will close all listeners.
  *
  * If it is a B2G environment, it will make the main content listener
  * sleep, and close all other listeners.  The main content listener
  * persists after disconnect (it's the homescreen), and can safely
  * be reused.
  */
 GeckoDriver.prototype.sessionTearDown = function(cmd, resp) {
-  if (this.curBrowser != null) {
+  if (this.curBrowser !== null) {
     if (this.appName == "B2G") {
       globalMessageManager.broadcastAsyncMessage(
           "Marionette:sleepSession" + this.curBrowser.mainContentId, {});
       this.curBrowser.knownFrames.splice(
           this.curBrowser.knownFrames.indexOf(this.curBrowser.mainContentId), 1);
     } else {
       // don't set this pref for B2G since the framescript can be safely reused
       Services.prefs.setBoolPref("marionette.contentListener", false);
@@ -3226,17 +3229,17 @@ BrowserObj.prototype.setBrowser = functi
 BrowserObj.prototype.startSession = function(newSession, win, callback) {
   callback(win, newSession);
 };
 
 /** Closes current tab. */
 BrowserObj.prototype.closeTab = function() {
   if (this.browser &&
       this.browser.removeTab &&
-      this.tab != null && (this.driver.appName != "B2G")) {
+      this.tab !== null && (this.driver.appName != "B2G")) {
     this.browser.removeTab(this.tab);
   }
 };
 
 /**
  * Opens a tab with given URI.
  *
  * @param {string} uri