toolkit/components/social/test/browser/browser_frameworker.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/toolkit/components/social/test/browser/browser_frameworker.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,387 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +// This file tests message ports and semantics of the frameworker which aren't
     1.9 +// directly related to the sandbox.  See also browser_frameworker_sandbox.js.
    1.10 +
    1.11 +function makeWorkerUrl(runner) {
    1.12 +  let prefix =  "http://example.com/browser/toolkit/components/social/test/browser/echo.sjs?";
    1.13 +  if (typeof runner == "function") {
    1.14 +    runner = "var run=" + runner.toSource() + ";run();";
    1.15 +  }
    1.16 +  return prefix + encodeURI(runner);
    1.17 +}
    1.18 +
    1.19 +var getFrameWorkerHandle;
    1.20 +function test() {
    1.21 +  waitForExplicitFinish();
    1.22 +
    1.23 +  let scope = {};
    1.24 +  Cu.import("resource://gre/modules/FrameWorker.jsm", scope);
    1.25 +  getFrameWorkerHandle = scope.getFrameWorkerHandle;
    1.26 +
    1.27 +  runTests(tests);
    1.28 +}
    1.29 +
    1.30 +let tests = {
    1.31 +  testSimple: function(cbnext) {
    1.32 +    let run = function() {
    1.33 +      onconnect = function(e) {
    1.34 +        let port = e.ports[0];
    1.35 +        port.onmessage = function(e) {
    1.36 +          if (e.data.topic == "ping") {
    1.37 +            port.postMessage({topic: "pong"});
    1.38 +          }
    1.39 +        }
    1.40 +      }
    1.41 +    }
    1.42 +
    1.43 +    let worker = getFrameWorkerHandle(makeWorkerUrl(run), undefined, "testSimple");
    1.44 +
    1.45 +    worker.port.onmessage = function(e) {
    1.46 +      if (e.data.topic == "pong") {
    1.47 +        worker.terminate();
    1.48 +        cbnext();
    1.49 +      }
    1.50 +    }
    1.51 +    worker.port.postMessage({topic: "ping"})
    1.52 +  },
    1.53 +
    1.54 +  // when the client closes early but the worker tries to send anyway...
    1.55 +  // XXX - disabled due to bug 919878 - we close the frameworker before the
    1.56 +  // remote browser has completed initializing, leading to failures.  Given
    1.57 +  // this can realistically only happen in this synthesized test environment,
    1.58 +  // disabling just this test seems OK for now.
    1.59 +/***
    1.60 +  testEarlyClose: function(cbnext) {
    1.61 +    let run = function() {
    1.62 +      onconnect = function(e) {
    1.63 +        let port = e.ports[0];
    1.64 +        port.postMessage({topic: "oh hai"});
    1.65 +      }
    1.66 +    }
    1.67 +
    1.68 +    let worker = getFrameWorkerHandle(makeWorkerUrl(run), undefined, "testEarlyClose");
    1.69 +    worker.port.close();
    1.70 +    worker.terminate();
    1.71 +    cbnext();
    1.72 +  },
    1.73 +***/
    1.74 +
    1.75 +  // Check we do get a social.port-closing message as the port is closed.
    1.76 +  testPortClosingMessage: function(cbnext) {
    1.77 +    // We use 2 ports - we close the first and report success via the second.
    1.78 +    let run = function() {
    1.79 +      let firstPort, secondPort;
    1.80 +      onconnect = function(e) {
    1.81 +        let port = e.ports[0];
    1.82 +        if (firstPort === undefined) {
    1.83 +          firstPort = port;
    1.84 +          port.onmessage = function(e) {
    1.85 +            if (e.data.topic == "social.port-closing") {
    1.86 +              secondPort.postMessage({topic: "got-closing"});
    1.87 +            }
    1.88 +          }
    1.89 +        } else {
    1.90 +          secondPort = port;
    1.91 +          // now both ports are connected we can trigger the client side
    1.92 +          // closing the first.
    1.93 +          secondPort.postMessage({topic: "connected"});
    1.94 +        }
    1.95 +      }
    1.96 +    }
    1.97 +    let workerurl = makeWorkerUrl(run);
    1.98 +    let worker1 = getFrameWorkerHandle(workerurl, undefined, "testPortClosingMessage worker1");
    1.99 +    let worker2 = getFrameWorkerHandle(workerurl, undefined, "testPortClosingMessage worker2");
   1.100 +    worker2.port.onmessage = function(e) {
   1.101 +      if (e.data.topic == "connected") {
   1.102 +        // both ports connected, so close the first.
   1.103 +        worker1.port.close();
   1.104 +      } else if (e.data.topic == "got-closing") {
   1.105 +        worker2.terminate();
   1.106 +        cbnext();
   1.107 +      }
   1.108 +    }
   1.109 +  },
   1.110 +
   1.111 +  // Tests that prototypes added to core objects work with data sent over
   1.112 +  // the message ports.
   1.113 +  testPrototypes: function(cbnext) {
   1.114 +    let run = function() {
   1.115 +      // Modify the Array prototype...
   1.116 +      Array.prototype.customfunction = function() {};
   1.117 +      onconnect = function(e) {
   1.118 +        let port = e.ports[0];
   1.119 +        port.onmessage = function(e) {
   1.120 +          // Check the data we get via the port has the prototype modification
   1.121 +          if (e.data.topic == "hello" && e.data.data.customfunction) {
   1.122 +            port.postMessage({topic: "hello", data: [1,2,3]});
   1.123 +          }
   1.124 +        }
   1.125 +      }
   1.126 +    }
   1.127 +    // hrmph - this kinda sucks as it is really just testing the actual
   1.128 +    // implementation rather than the end result, but is OK for now.
   1.129 +    // Really we are just testing that JSON.parse in the client window
   1.130 +    // is called.
   1.131 +    let fakeWindow = {
   1.132 +      JSON: {
   1.133 +        parse: function(s) {
   1.134 +          let data = JSON.parse(s);
   1.135 +          data.data.somextrafunction = function() {};
   1.136 +          return data;
   1.137 +        }
   1.138 +      }
   1.139 +    }
   1.140 +    let worker = getFrameWorkerHandle(makeWorkerUrl(run), fakeWindow, "testPrototypes");
   1.141 +    worker.port.onmessage = function(e) {
   1.142 +      if (e.data.topic == "hello") {
   1.143 +        ok(e.data.data.somextrafunction, "have someextrafunction")
   1.144 +        worker.terminate();
   1.145 +        cbnext();
   1.146 +      }
   1.147 +    }
   1.148 +    worker.port.postMessage({topic: "hello", data: [1,2,3]});
   1.149 +  },
   1.150 +
   1.151 +  testSameOriginImport: function(cbnext) {
   1.152 +    let run = function() {
   1.153 +      onconnect = function(e) {
   1.154 +        let port = e.ports[0];
   1.155 +        port.onmessage = function(e) {
   1.156 +          if (e.data.topic == "ping") {
   1.157 +            try {
   1.158 +              importScripts("http://mochi.test:8888/error");
   1.159 +            } catch(ex) {
   1.160 +              port.postMessage({topic: "pong", data: ex});
   1.161 +              return;
   1.162 +            }
   1.163 +            port.postMessage({topic: "pong", data: null});
   1.164 +          }
   1.165 +        }
   1.166 +      }
   1.167 +    }
   1.168 +
   1.169 +    let worker = getFrameWorkerHandle(makeWorkerUrl(run), undefined, "testSameOriginImport");
   1.170 +    worker.port.onmessage = function(e) {
   1.171 +      if (e.data.topic == "pong") {
   1.172 +        isnot(e.data.data, null, "check same-origin applied to importScripts");
   1.173 +        worker.terminate();
   1.174 +        cbnext();
   1.175 +      }
   1.176 +    }
   1.177 +    worker.port.postMessage({topic: "ping"})
   1.178 +  },
   1.179 +
   1.180 +  testRelativeImport: function(cbnext) {
   1.181 +    let url = "https://example.com/browser/toolkit/components/social/test/browser/worker_relative.js";
   1.182 +    let worker = getFrameWorkerHandle(url, undefined, "testSameOriginImport");
   1.183 +    worker.port.onmessage = function(e) {
   1.184 +      if (e.data.topic == "done") {
   1.185 +        is(e.data.result, "ok", "check relative url in importScripts");
   1.186 +        worker.terminate();
   1.187 +        cbnext();
   1.188 +      }
   1.189 +    }
   1.190 +  },
   1.191 +
   1.192 +  testNavigator: function(cbnext) {
   1.193 +    let run = function() {
   1.194 +      let port;
   1.195 +      ononline = function() {
   1.196 +        port.postMessage({topic: "ononline", data: navigator.onLine});
   1.197 +      }
   1.198 +      onoffline = function() {
   1.199 +        port.postMessage({topic: "onoffline", data: navigator.onLine});
   1.200 +      }
   1.201 +      onconnect = function(e) {
   1.202 +        port = e.ports[0];
   1.203 +        port.postMessage({topic: "ready",
   1.204 +                          data: {
   1.205 +                            appName: navigator.appName,
   1.206 +                            appVersion: navigator.appVersion,
   1.207 +                            platform: navigator.platform,
   1.208 +                            userAgent: navigator.userAgent,
   1.209 +                          }
   1.210 +                         });
   1.211 +      }
   1.212 +    }
   1.213 +    let ioService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService2);
   1.214 +    let oldManage = ioService.manageOfflineStatus;
   1.215 +    let oldOffline = ioService.offline;
   1.216 +
   1.217 +    ioService.manageOfflineStatus = false;
   1.218 +    let worker = getFrameWorkerHandle(makeWorkerUrl(run), undefined, "testNavigator");
   1.219 +    let expected_topic = "onoffline";
   1.220 +    let expected_data = false;
   1.221 +    worker.port.onmessage = function(e) {
   1.222 +      is(e.data.topic, "ready");
   1.223 +      for each (let attr in ['appName', 'appVersion', 'platform', 'userAgent']) {
   1.224 +        // each attribute must be a string with length > 0.
   1.225 +        is(typeof e.data.data[attr], "string");
   1.226 +        ok(e.data.data[attr].length > 0);
   1.227 +      }
   1.228 +
   1.229 +      worker.port.onmessage = function(e) {
   1.230 +        // a handler specifically for the offline notification.
   1.231 +        is(e.data.topic, "onoffline");
   1.232 +        is(e.data.data, false);
   1.233 +
   1.234 +        // add another handler specifically for the 'online' case.
   1.235 +        worker.port.onmessage = function(e) {
   1.236 +          is(e.data.topic, "ononline");
   1.237 +          is(e.data.data, true);
   1.238 +          // all good!
   1.239 +          ioService.manageOfflineStatus = oldManage;
   1.240 +          ioService.offline = oldOffline;
   1.241 +          worker.terminate();
   1.242 +          cbnext();
   1.243 +        }
   1.244 +        ioService.offline = false;
   1.245 +      }
   1.246 +      ioService.offline = true;
   1.247 +    }
   1.248 +  },
   1.249 +
   1.250 +  testMissingWorker: function(cbnext) {
   1.251 +    // don't ever create this file!  We want a 404.
   1.252 +    let url = "https://example.com/browser/toolkit/components/social/test/browser/worker_is_missing.js";
   1.253 +    let worker = getFrameWorkerHandle(url, undefined, "testMissingWorker");
   1.254 +    Services.obs.addObserver(function handleError(subj, topic, data) {
   1.255 +      Services.obs.removeObserver(handleError, "social:frameworker-error");
   1.256 +      is(data, worker._worker.origin, "social:frameworker-error was handled");
   1.257 +      worker.terminate();
   1.258 +      cbnext();
   1.259 +    }, 'social:frameworker-error', false);
   1.260 +    worker.port.onmessage = function(e) {
   1.261 +      ok(false, "social:frameworker-error was handled");
   1.262 +      cbnext();
   1.263 +    }
   1.264 +  },
   1.265 +
   1.266 +  testNoConnectWorker: function(cbnext) {
   1.267 +    let worker = getFrameWorkerHandle(makeWorkerUrl(function () {}),
   1.268 +                                      undefined, "testNoConnectWorker");
   1.269 +    Services.obs.addObserver(function handleError(subj, topic, data) {
   1.270 +      Services.obs.removeObserver(handleError, "social:frameworker-error");
   1.271 +      is(data, worker._worker.origin, "social:frameworker-error was handled");
   1.272 +      worker.terminate();
   1.273 +      cbnext();
   1.274 +    }, 'social:frameworker-error', false);
   1.275 +    worker.port.onmessage = function(e) {
   1.276 +      ok(false, "social:frameworker-error was handled");
   1.277 +      cbnext();
   1.278 +    }
   1.279 +  },
   1.280 +
   1.281 +  testEmptyWorker: function(cbnext) {
   1.282 +    let worker = getFrameWorkerHandle(makeWorkerUrl(''),
   1.283 +                                      undefined, "testEmptyWorker");
   1.284 +    Services.obs.addObserver(function handleError(subj, topic, data) {
   1.285 +      Services.obs.removeObserver(handleError, "social:frameworker-error");
   1.286 +      is(data, worker._worker.origin, "social:frameworker-error was handled");
   1.287 +      worker.terminate();
   1.288 +      cbnext();
   1.289 +    }, 'social:frameworker-error', false);
   1.290 +    worker.port.onmessage = function(e) {
   1.291 +      ok(false, "social:frameworker-error was handled");
   1.292 +      cbnext();
   1.293 +    }
   1.294 +  },
   1.295 +
   1.296 +  testWorkerConnectError: function(cbnext) {
   1.297 +    let run = function () {
   1.298 +      onconnect = function(e) {
   1.299 +        throw new Error("worker failure");
   1.300 +      }
   1.301 +    }
   1.302 +    let worker = getFrameWorkerHandle(makeWorkerUrl(run),
   1.303 +                                      undefined, "testWorkerConnectError");
   1.304 +    Services.obs.addObserver(function handleError(subj, topic, data) {
   1.305 +      Services.obs.removeObserver(handleError, "social:frameworker-error");
   1.306 +      is(data, worker._worker.origin, "social:frameworker-error was handled");
   1.307 +      worker.terminate();
   1.308 +      cbnext();
   1.309 +    }, 'social:frameworker-error', false);
   1.310 +    worker.port.onmessage = function(e) {
   1.311 +      ok(false, "social:frameworker-error was handled");
   1.312 +      cbnext();
   1.313 +    }
   1.314 +  },
   1.315 +
   1.316 +  // This will create the worker, then send a message to the port, then close
   1.317 +  // the port - all before the worker has actually initialized.
   1.318 +  testCloseFirstSend: function(cbnext) {
   1.319 +    let run = function() {
   1.320 +      let numPings = 0, numCloses = 0;
   1.321 +      onconnect = function(e) {
   1.322 +        let port = e.ports[0];
   1.323 +        port.onmessage = function(e) {
   1.324 +          if (e.data.topic == "ping") {
   1.325 +            numPings += 1;
   1.326 +          } else if (e.data.topic == "social.port-closing") {
   1.327 +            numCloses += 1;
   1.328 +          } else if (e.data.topic == "get-counts") {
   1.329 +            port.postMessage({topic: "result",
   1.330 +                             result: {ping: numPings, close: numCloses}});
   1.331 +          }
   1.332 +        }
   1.333 +      }
   1.334 +    }
   1.335 +
   1.336 +    let worker = getFrameWorkerHandle(makeWorkerUrl(run), undefined, "testSendAndClose");
   1.337 +    worker.port.postMessage({topic: "ping"});
   1.338 +    worker.port.close();
   1.339 +    let newPort = getFrameWorkerHandle(makeWorkerUrl(run), undefined, "testSendAndClose").port;
   1.340 +    newPort.onmessage = function(e) {
   1.341 +      if (e.data.topic == "result") {
   1.342 +        is(e.data.result.ping, 1, "the worker got the ping");
   1.343 +        is(e.data.result.close, 1, "the worker got 1 close message");
   1.344 +        worker.terminate();
   1.345 +        cbnext();
   1.346 +      }
   1.347 +    }
   1.348 +    newPort.postMessage({topic: "get-counts"});
   1.349 +  },
   1.350 +
   1.351 +  // Like testCloseFirstSend, although in this test the worker has already
   1.352 +  // initialized (so the "connect pending ports" part of the worker isn't
   1.353 +  // what needs to handle this case.)
   1.354 +  testCloseAfterInit: function(cbnext) {
   1.355 +    let run = function() {
   1.356 +      let numPings = 0, numCloses = 0;
   1.357 +      onconnect = function(e) {
   1.358 +        let port = e.ports[0];
   1.359 +        port.onmessage = function(e) {
   1.360 +          if (e.data.topic == "ping") {
   1.361 +            numPings += 1;
   1.362 +          } else if (e.data.topic == "social.port-closing") {
   1.363 +            numCloses += 1;
   1.364 +          } else if (e.data.topic == "get-counts") {
   1.365 +            port.postMessage({topic: "result",
   1.366 +                             result: {ping: numPings, close: numCloses}});
   1.367 +          } else if (e.data.topic == "get-ready") {
   1.368 +            port.postMessage({topic: "ready"});
   1.369 +          }
   1.370 +        }
   1.371 +      }
   1.372 +    }
   1.373 +
   1.374 +    let worker = getFrameWorkerHandle(makeWorkerUrl(run), undefined, "testSendAndClose");
   1.375 +    worker.port.onmessage = function(e) {
   1.376 +      if (e.data.topic == "ready") {
   1.377 +        let newPort = getFrameWorkerHandle(makeWorkerUrl(run), undefined, "testSendAndClose").port;
   1.378 +        newPort.postMessage({topic: "ping"});
   1.379 +        newPort.close();
   1.380 +        worker.port.postMessage({topic: "get-counts"});
   1.381 +      } else if (e.data.topic == "result") {
   1.382 +        is(e.data.result.ping, 1, "the worker got the ping");
   1.383 +        is(e.data.result.close, 1, "the worker got 1 close message");
   1.384 +        worker.terminate();
   1.385 +        cbnext();
   1.386 +      }
   1.387 +    }
   1.388 +    worker.port.postMessage({topic: "get-ready"});
   1.389 +  },
   1.390 +}

mercurial