Bug 773160: expose a reduced 'navigator' object to social frameworker workers. r=gavin
☠☠ backed out by b87902190446 ☠ ☠
authorMark Hammond <mhammond@skippinet.com.au>
Mon, 16 Jul 2012 11:59:37 +1000
changeset 99406 777fbc99f40b42de16f7577c56503b23f0121fd6
parent 99405 27e4b9cbed7438d797e85864ffe2c26fb9f50ec0
child 99407 2220334ff2d0102ab8df6a73b11dd51ca055ea20
child 99408 b879021904462103771a512fe74204774d5e34b1
push id23128
push useremorley@mozilla.com
push dateMon, 16 Jul 2012 14:01:04 +0000
treeherdermozilla-central@00405b1daf05 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgavin
bugs773160
milestone16.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 773160: expose a reduced 'navigator' object to social frameworker workers. r=gavin
toolkit/components/social/FrameWorker.jsm
toolkit/components/social/test/browser/browser_frameworker.js
--- a/toolkit/components/social/FrameWorker.jsm
+++ b/toolkit/components/social/FrameWorker.jsm
@@ -94,26 +94,45 @@ FrameWorker.prototype = {
 
     // copy the window apis onto the sandbox namespace only functions or
     // objects that are naturally a part of an iframe, I'm assuming they are
     // safe to import this way
     let workerAPI = ['MozWebSocket', 'WebSocket', 'localStorage',
                      'atob', 'btoa', 'clearInterval', 'clearTimeout', 'dump',
                      'setInterval', 'setTimeout', 'XMLHttpRequest',
                      'MozBlobBuilder', 'FileReader', 'Blob',
-                     'navigator', 'location'];
+                     'location'];
     workerAPI.forEach(function(fn) {
       try {
         // XXX Need to unwrap for this to work - find out why!
         sandbox[fn] = XPCNativeWrapper.unwrap(workerWindow)[fn];
       }
       catch(e) {
         Cu.reportError("FrameWorker: failed to import API "+fn+"\n"+e+"\n");
       }
     });
+    // the "navigator" object in a worker is a subset of the full navigator;
+    // specifically, just the interfaces 'NavigatorID' and 'NavigatorOnLine'
+    let navigator = {
+      __exposedProps__: {
+        "appName": "r",
+        "appVersion": "r",
+        "platform": "r",
+        "userAgent": "r",
+        "onLine": "r"
+      },
+      // interface NavigatorID
+      appName: workerWindow.navigator.appName,
+      appVersion: workerWindow.navigator.appVersion,
+      platform: workerWindow.navigator.platform,
+      userAgent: workerWindow.navigator.userAgent,
+      // interface NavigatorOnLine
+      get onLine() workerWindow.navigator.onLine
+    };
+    sandbox.navigator = navigator;
 
     // and we delegate ononline and onoffline events to the worker.
     // See http://www.whatwg.org/specs/web-apps/current-work/multipage/workers.html#workerglobalscope
     this.frame.addEventListener('offline', function fw_onoffline(event) {
       Cu.evalInSandbox("onoffline();", sandbox);
     }, false);
     this.frame.addEventListener('online', function fw_ononline(event) {
       Cu.evalInSandbox("ononline();", sandbox);
--- a/toolkit/components/social/test/browser/browser_frameworker.js
+++ b/toolkit/components/social/test/browser/browser_frameworker.js
@@ -400,10 +400,67 @@ let tests = {
     let worker = getFrameWorkerHandle(url, undefined, "testSameOriginImport");
     worker.port.onmessage = function(e) {
       if (e.data.topic == "done") {
         is(e.data.result, "ok", "check relative url in importScripts");
         worker.terminate();
         cbnext();
       }
     }
+  },
+
+  testNavigator: function(cbnext) {
+    let run = function() {
+      let port;
+      ononline = function() {
+        port.postMessage({topic: "ononline", data: navigator.onLine});
+      }
+      onoffline = function() {
+        port.postMessage({topic: "onoffline", data: navigator.onLine});
+      }
+      onconnect = function(e) {
+        port = e.ports[0];
+        port.postMessage({topic: "ready",
+                          data: {
+                            appName: navigator.appName,
+                            appVersion: navigator.appVersion,
+                            platform: navigator.platform,
+                            userAgent: navigator.userAgent,
+                          }
+                         });
+      }
+    }
+    let ioService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService2);
+    let oldManage = ioService.manageOfflineStatus;
+    let oldOffline = ioService.offline;
+    
+    ioService.manageOfflineStatus = false;
+    let worker = getFrameWorkerHandle(makeWorkerUrl(run), undefined, "testNavigator");
+    let expected_topic = "onoffline";
+    let expected_data = false;
+    worker.port.onmessage = function(e) {
+      is(e.data.topic, "ready");
+      for each (let attr in ['appName', 'appVersion', 'platform', 'userAgent']) {
+        // each attribute must be a string with length > 0.
+        is(typeof e.data.data[attr], "string");
+        ok(e.data.data[attr].length > 0);
+      }
+
+      worker.port.onmessage = function(e) {
+        // a handler specifically for the offline notification.
+        is(e.data.topic, "onoffline");
+        is(e.data.data, false);
+
+        // add another handler specifically for the 'online' case.
+        worker.port.onmessage = function(e) {
+          is(e.data.topic, "ononline");
+          is(e.data.data, true);
+          // all good!
+          ioService.manageOfflineStatus = oldManage;
+          ioService.offline = oldOffline;
+          cbnext();
+        }
+        ioService.offline = false;
+      }
+      ioService.offline = true;
+    }
   }
 }