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();