Bug 645325 - Part 4: Handle null listener when xhr callbacks are called after WifiGeoPositionProvider shutdown. r=garvank r?jdm draft
authorChris Peterson <cpeterson@mozilla.com>
Fri, 09 Mar 2018 22:20:50 -0800
changeset 791841 51011f4dd992111920b4d25a8ba38e9269789246
parent 791840 82066999ffe10b90eea6d38dea9e255cdb597c19
child 791842 034532dd527567d8c54103b73134b259e758f306
push id108905
push usercpeterson@mozilla.com
push dateSun, 06 May 2018 06:27:00 +0000
reviewersgarvank, jdm
bugs645325
milestone61.0a1
Bug 645325 - Part 4: Handle null listener when xhr callbacks are called after WifiGeoPositionProvider shutdown. r=garvank r?jdm I hit this error when testing geolocation with Wi-Fi disabled. There is a race where the WifiGeoPositionProvider gets shut down (settting this.listener to null) but the xhr request is still alive (and the xhr callback later hits the null this.listener). MozReview-Commit-ID: E3jCFM3om5A
dom/system/NetworkGeolocationProvider.js
--- a/dom/system/NetworkGeolocationProvider.js
+++ b/dom/system/NetworkGeolocationProvider.js
@@ -378,45 +378,53 @@ WifiGeoPositionProvider.prototype = {
     let url = Services.urlFormatter.formatURLPref("geo.wifi.uri");
     LOG("Sending request");
 
     let xhr = new XMLHttpRequest();
     try {
       xhr.open("POST", url, true);
       xhr.channel.loadFlags = Ci.nsIChannel.LOAD_ANONYMOUS;
     } catch (e) {
-      this.listener.notifyError(POSITION_UNAVAILABLE);
+      notifyPositionUnavailable(this.listener);
       return;
     }
     xhr.setRequestHeader("Content-Type", "application/json; charset=UTF-8");
     xhr.responseType = "json";
     xhr.mozBackgroundRequest = true;
     xhr.timeout = Services.prefs.getIntPref("geo.wifi.xhr.timeout");
     xhr.ontimeout = () => {
       LOG("Location request XHR timed out.")
-      this.listener.notifyError(POSITION_UNAVAILABLE);
+      notifyPositionUnavailable(this.listener);
     };
     xhr.onerror = () => {
-      this.listener.notifyError(POSITION_UNAVAILABLE);
+      notifyPositionUnavailable(this.listener);
     };
     xhr.onload = () => {
       LOG("server returned status: " + xhr.status + " --> " +  JSON.stringify(xhr.response));
       if ((xhr.channel instanceof Ci.nsIHttpChannel && xhr.status != 200) ||
           !xhr.response || !xhr.response.location) {
-        this.listener.notifyError(POSITION_UNAVAILABLE);
+        notifyPositionUnavailable(this.listener);
         return;
       }
 
       let newLocation = new WifiGeoPositionObject(xhr.response.location.lat,
                                                   xhr.response.location.lng,
                                                   xhr.response.accuracy);
 
-      this.listener.update(newLocation);
+      if (this.listener) {
+        this.listener.update(newLocation);
+      }
       gCachedRequest = new CachedRequest(newLocation, data.cellTowers, data.wifiAccessPoints);
     };
 
     var requestData = JSON.stringify(data);
     LOG("sending " + requestData);
     xhr.send(requestData);
+
+    function notifyPositionUnavailable(listener) {
+      if (listener) {
+        listener.notifyError(POSITION_UNAVAILABLE);
+      }
+    }
   }
 };
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([WifiGeoPositionProvider]);