toolkit/components/social/MessagePortWorker.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/toolkit/components/social/MessagePortWorker.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,110 @@
     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 +// Note: this is never instantiated in chrome - the source is sent across
     1.9 +// to the worker and it is evaluated there and created in response to a
    1.10 +// port-create message we send.
    1.11 +function WorkerPort(portid) {
    1.12 +  AbstractPort.call(this, portid);
    1.13 +}
    1.14 +
    1.15 +WorkerPort.prototype = {
    1.16 +  __proto__: AbstractPort.prototype,
    1.17 +  _portType: "worker",
    1.18 +
    1.19 +  _dopost: function fw_WorkerPort_dopost(data) {
    1.20 +    // postMessage is injected into the sandbox.
    1.21 +    _postMessage(data, "*");
    1.22 +  },
    1.23 +
    1.24 +  _onerror: function fw_WorkerPort_onerror(err) {
    1.25 +    // We throw an object that "derives" from the exception, but with
    1.26 +    // a more detailed message.
    1.27 +    throw {message: "Port " + this + " handler failed: " + err.message, __proto__: err};
    1.28 +  }
    1.29 +}
    1.30 +
    1.31 +function importScripts() {
    1.32 +  for (var i=0; i < arguments.length; i++) {
    1.33 +    // load the url *synchronously*
    1.34 +    var scriptURL = arguments[i];
    1.35 +    var xhr = new XMLHttpRequest();
    1.36 +    xhr.open('GET', scriptURL, false);
    1.37 +    xhr.onreadystatechange = function(aEvt) {
    1.38 +      if (xhr.readyState == 4) {
    1.39 +        if (xhr.status == 200 || xhr.status == 0) {
    1.40 +          _evalInSandbox(xhr.responseText, scriptURL);
    1.41 +        }
    1.42 +        else {
    1.43 +          throw new Error("Unable to importScripts ["+scriptURL+"], status " + xhr.status)
    1.44 +        }
    1.45 +      }
    1.46 +    };
    1.47 +    xhr.send(null);
    1.48 +  }
    1.49 +}
    1.50 +
    1.51 +// This function is magically injected into the sandbox and used there.
    1.52 +// Thus, it is only ever dealing with "worker" ports.
    1.53 +function __initWorkerMessageHandler() {
    1.54 +
    1.55 +  let ports = {}; // all "worker" ports currently alive, keyed by ID.
    1.56 +
    1.57 +  function messageHandler(event) {
    1.58 +    // We will ignore all messages destined for otherType.
    1.59 +    let data = event.data;
    1.60 +    let portid = data.portId;
    1.61 +    let port;
    1.62 +    if (!data.portFromType || data.portFromType === "worker") {
    1.63 +      // this is a message posted by ourself so ignore it.
    1.64 +      return;
    1.65 +    }
    1.66 +    switch (data.portTopic) {
    1.67 +      case "port-create":
    1.68 +        // a new port was created on the "client" side - create a new worker
    1.69 +        // port and store it in the map
    1.70 +        port = new WorkerPort(portid);
    1.71 +        ports[portid] = port;
    1.72 +        // and call the "onconnect" handler.
    1.73 +        try {
    1.74 +          onconnect({ports: [port]});
    1.75 +        } catch(e) {
    1.76 +          // we have a bad worker and cannot continue, we need to signal
    1.77 +          // an error
    1.78 +          port._postControlMessage("port-connection-error", JSON.stringify(e.toString()));
    1.79 +          throw e;
    1.80 +        }
    1.81 +        break;
    1.82 +
    1.83 +      case "port-close":
    1.84 +        // the client side of the port was closed, so close this side too.
    1.85 +        port = ports[portid];
    1.86 +        if (!port) {
    1.87 +          // port already closed (which will happen when we call port.close()
    1.88 +          // below - the client side will send us this message but we've
    1.89 +          // already closed it.)
    1.90 +          return;
    1.91 +        }
    1.92 +        delete ports[portid];
    1.93 +        port.close();
    1.94 +        break;
    1.95 +
    1.96 +      case "port-message":
    1.97 +        // the client posted a message to this worker port.
    1.98 +        port = ports[portid];
    1.99 +        if (!port) {
   1.100 +          // port must be closed - this shouldn't happen!
   1.101 +          return;
   1.102 +        }
   1.103 +        port._onmessage(data.data);
   1.104 +        break;
   1.105 +
   1.106 +      default:
   1.107 +        break;
   1.108 +    }
   1.109 +  }
   1.110 +  // addEventListener is injected into the sandbox.
   1.111 +  _addEventListener('message', messageHandler);
   1.112 +}
   1.113 +__initWorkerMessageHandler();

mercurial