| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | |
| 5 /** | 4 /** |
| 6 * @interface | 5 * @interface |
| 7 */ | 6 */ |
| 8 function Service() { } | 7 function Service() { |
| 8 } |
| 9 | 9 |
| 10 Service.prototype = { | 10 Service.prototype = { |
| 11 /** | 11 /** |
| 12 * @return {!Promise} | 12 * @return {!Promise} |
| 13 */ | 13 */ |
| 14 dispose: function() { }, | 14 dispose: function() {}, |
| 15 | 15 |
| 16 /** | 16 /** |
| 17 * @return {function(string)} | 17 * @return {function(string)} |
| 18 */ | 18 */ |
| 19 setNotify: function(notify) { } | 19 setNotify: function(notify) {} |
| 20 }; | 20 }; |
| 21 | 21 |
| 22 /** | 22 /** |
| 23 * @constructor | 23 * @unrestricted |
| 24 * @param {!ServicePort} port | |
| 25 */ | 24 */ |
| 26 function ServiceDispatcher(port) | 25 var ServiceDispatcher = class { |
| 27 { | 26 /** |
| 27 * @param {!ServicePort} port |
| 28 */ |
| 29 constructor(port) { |
| 28 /** @type {!Map<string, !Object>} */ | 30 /** @type {!Map<string, !Object>} */ |
| 29 this._objects = new Map(); | 31 this._objects = new Map(); |
| 30 this._lastObjectId = 1; | 32 this._lastObjectId = 1; |
| 31 this._port = port; | 33 this._port = port; |
| 32 this._port.setHandlers(this._dispatchMessageWrapped.bind(this), this._connec
tionClosed.bind(this)); | 34 this._port.setHandlers(this._dispatchMessageWrapped.bind(this), this._connec
tionClosed.bind(this)); |
| 33 } | 35 } |
| 34 | 36 |
| 35 ServiceDispatcher.prototype = { | 37 /** |
| 36 /** | 38 * @param {string} data |
| 37 * @param {string} data | 39 */ |
| 38 */ | 40 _dispatchMessageWrapped(data) { |
| 39 _dispatchMessageWrapped: function(data) | 41 try { |
| 40 { | 42 var message = JSON.parse(data); |
| 41 try { | 43 if (!(message instanceof Object)) { |
| 42 var message = JSON.parse(data); | 44 this._sendErrorResponse(message['id'], 'Malformed message'); |
| 43 if (!(message instanceof Object)) { | 45 return; |
| 44 this._sendErrorResponse(message["id"], "Malformed message"); | 46 } |
| 45 return; | 47 this._dispatchMessage(message); |
| 46 } | 48 } catch (e) { |
| 47 this._dispatchMessage(message); | 49 this._sendErrorResponse(message['id'], e.toString()); |
| 48 } catch (e) { | |
| 49 this._sendErrorResponse(message["id"], e.toString()); | |
| 50 } | |
| 51 }, | |
| 52 | |
| 53 /** | |
| 54 * @param {!Object} message | |
| 55 */ | |
| 56 _dispatchMessage: function(message) | |
| 57 { | |
| 58 var domainAndMethod = message["method"].split("."); | |
| 59 var serviceName = domainAndMethod[0]; | |
| 60 var method = domainAndMethod[1]; | |
| 61 | |
| 62 if (method === "create") { | |
| 63 var extensions = self.runtime.extensions(Service).filter(extension =
> extension.descriptor()["name"] === serviceName); | |
| 64 if (!extensions.length) { | |
| 65 this._sendErrorResponse(message["id"], "Could not resolve servic
e '" + serviceName + "'"); | |
| 66 return; | |
| 67 } | |
| 68 extensions[0].instance().then(object => { | |
| 69 var id = String(this._lastObjectId++); | |
| 70 object.setNotify(this._notify.bind(this, id, serviceName)); | |
| 71 this._objects.set(id, object); | |
| 72 this._sendResponse(message["id"], { id: id }); | |
| 73 }); | |
| 74 } else if (method === "dispose") { | |
| 75 var object = this._objects.get(message["params"]["id"]); | |
| 76 if (!object) { | |
| 77 console.error("Could not look up object with id for " + JSON.str
ingify(message)); | |
| 78 return; | |
| 79 } | |
| 80 this._objects.delete(message["params"]["id"]); | |
| 81 object.dispose().then(() => this._sendResponse(message["id"], {})); | |
| 82 } else { | |
| 83 if (!message["params"]) { | |
| 84 console.error("No params in the message: " + JSON.stringify(mess
age)); | |
| 85 return; | |
| 86 } | |
| 87 var object = this._objects.get(message["params"]["id"]); | |
| 88 if (!object) { | |
| 89 console.error("Could not look up object with id for " + JSON.str
ingify(message)); | |
| 90 return; | |
| 91 } | |
| 92 var handler = object[method]; | |
| 93 if (!(handler instanceof Function)) { | |
| 94 console.error("Handler for '" + method + "' is missing."); | |
| 95 return; | |
| 96 } | |
| 97 object[method](message["params"]).then(result => this._sendResponse(
message["id"], result)); | |
| 98 } | |
| 99 }, | |
| 100 | |
| 101 _connectionClosed: function() | |
| 102 { | |
| 103 for (var object of this._objects.values()) | |
| 104 object.dispose(); | |
| 105 this._objects.clear(); | |
| 106 }, | |
| 107 | |
| 108 /** | |
| 109 * @param {string} objectId | |
| 110 * @param {string} serviceName | |
| 111 * @param {string} method | |
| 112 * @param {!Object} params | |
| 113 */ | |
| 114 _notify: function(objectId, serviceName, method, params) | |
| 115 { | |
| 116 params["id"] = objectId; | |
| 117 var message = { method: serviceName + "." + method, params: params }; | |
| 118 this._port.send(JSON.stringify(message)); | |
| 119 }, | |
| 120 | |
| 121 /** | |
| 122 * @param {string} messageId | |
| 123 * @param {!Object} result | |
| 124 */ | |
| 125 _sendResponse: function(messageId, result) | |
| 126 { | |
| 127 var message = { id: messageId, result: result }; | |
| 128 this._port.send(JSON.stringify(message)); | |
| 129 }, | |
| 130 | |
| 131 /** | |
| 132 * @param {string} messageId | |
| 133 * @param {string} error | |
| 134 */ | |
| 135 _sendErrorResponse: function(messageId, error) | |
| 136 { | |
| 137 var message = { id: messageId, error: error }; | |
| 138 this._port.send(JSON.stringify(message)); | |
| 139 } | 50 } |
| 51 } |
| 52 |
| 53 /** |
| 54 * @param {!Object} message |
| 55 */ |
| 56 _dispatchMessage(message) { |
| 57 var domainAndMethod = message['method'].split('.'); |
| 58 var serviceName = domainAndMethod[0]; |
| 59 var method = domainAndMethod[1]; |
| 60 |
| 61 if (method === 'create') { |
| 62 var extensions = |
| 63 self.runtime.extensions(Service).filter(extension => extension.descrip
tor()['name'] === serviceName); |
| 64 if (!extensions.length) { |
| 65 this._sendErrorResponse(message['id'], 'Could not resolve service \'' +
serviceName + '\''); |
| 66 return; |
| 67 } |
| 68 extensions[0].instance().then(object => { |
| 69 var id = String(this._lastObjectId++); |
| 70 object.setNotify(this._notify.bind(this, id, serviceName)); |
| 71 this._objects.set(id, object); |
| 72 this._sendResponse(message['id'], {id: id}); |
| 73 }); |
| 74 } else if (method === 'dispose') { |
| 75 var object = this._objects.get(message['params']['id']); |
| 76 if (!object) { |
| 77 console.error('Could not look up object with id for ' + JSON.stringify(m
essage)); |
| 78 return; |
| 79 } |
| 80 this._objects.delete(message['params']['id']); |
| 81 object.dispose().then(() => this._sendResponse(message['id'], {})); |
| 82 } else { |
| 83 if (!message['params']) { |
| 84 console.error('No params in the message: ' + JSON.stringify(message)); |
| 85 return; |
| 86 } |
| 87 var object = this._objects.get(message['params']['id']); |
| 88 if (!object) { |
| 89 console.error('Could not look up object with id for ' + JSON.stringify(m
essage)); |
| 90 return; |
| 91 } |
| 92 var handler = object[method]; |
| 93 if (!(handler instanceof Function)) { |
| 94 console.error('Handler for \'' + method + '\' is missing.'); |
| 95 return; |
| 96 } |
| 97 object[method](message['params']).then(result => this._sendResponse(messag
e['id'], result)); |
| 98 } |
| 99 } |
| 100 |
| 101 _connectionClosed() { |
| 102 for (var object of this._objects.values()) |
| 103 object.dispose(); |
| 104 this._objects.clear(); |
| 105 } |
| 106 |
| 107 /** |
| 108 * @param {string} objectId |
| 109 * @param {string} serviceName |
| 110 * @param {string} method |
| 111 * @param {!Object} params |
| 112 */ |
| 113 _notify(objectId, serviceName, method, params) { |
| 114 params['id'] = objectId; |
| 115 var message = {method: serviceName + '.' + method, params: params}; |
| 116 this._port.send(JSON.stringify(message)); |
| 117 } |
| 118 |
| 119 /** |
| 120 * @param {string} messageId |
| 121 * @param {!Object} result |
| 122 */ |
| 123 _sendResponse(messageId, result) { |
| 124 var message = {id: messageId, result: result}; |
| 125 this._port.send(JSON.stringify(message)); |
| 126 } |
| 127 |
| 128 /** |
| 129 * @param {string} messageId |
| 130 * @param {string} error |
| 131 */ |
| 132 _sendErrorResponse(messageId, error) { |
| 133 var message = {id: messageId, error: error}; |
| 134 this._port.send(JSON.stringify(message)); |
| 135 } |
| 140 }; | 136 }; |
| 141 | 137 |
| 142 /** | 138 /** |
| 143 * @constructor | |
| 144 * @param {!Port|!Worker} port | |
| 145 * @implements {ServicePort} | 139 * @implements {ServicePort} |
| 140 * @unrestricted |
| 146 */ | 141 */ |
| 147 function WorkerServicePort(port) | 142 var WorkerServicePort = class { |
| 148 { | 143 /** |
| 144 * @param {!Port|!Worker} port |
| 145 */ |
| 146 constructor(port) { |
| 149 this._port = port; | 147 this._port = port; |
| 150 this._port.onmessage = this._onMessage.bind(this); | 148 this._port.onmessage = this._onMessage.bind(this); |
| 151 this._port.onerror = console.error; | 149 this._port.onerror = console.error; |
| 150 } |
| 151 |
| 152 /** |
| 153 * @override |
| 154 * @param {function(string)} messageHandler |
| 155 * @param {function(string)} closeHandler |
| 156 */ |
| 157 setHandlers(messageHandler, closeHandler) { |
| 158 this._messageHandler = messageHandler; |
| 159 this._closeHandler = closeHandler; |
| 160 } |
| 161 |
| 162 /** |
| 163 * @override |
| 164 * @param {string} data |
| 165 * @return {!Promise} |
| 166 */ |
| 167 send(data) { |
| 168 this._port.postMessage(data); |
| 169 return Promise.resolve(); |
| 170 } |
| 171 |
| 172 /** |
| 173 * @override |
| 174 * @return {!Promise} |
| 175 */ |
| 176 close() { |
| 177 return Promise.resolve(); |
| 178 } |
| 179 |
| 180 /** |
| 181 * @param {!MessageEvent} event |
| 182 */ |
| 183 _onMessage(event) { |
| 184 this._messageHandler(event.data); |
| 185 } |
| 186 }; |
| 187 |
| 188 var dispatchers = []; |
| 189 |
| 190 if (self instanceof SharedWorkerGlobalScope) { |
| 191 function onNewPort(port) { |
| 192 var dispatcher = new ServiceDispatcher(new WorkerServicePort(port)); |
| 193 dispatchers.push(dispatcher); |
| 194 } |
| 195 Runtime.setSharedWorkerNewPortCallback(onNewPort); |
| 196 } else { |
| 197 var worker = /** @type {!Object} */ (self); |
| 198 var servicePort = new WorkerServicePort(/** @type {!Worker} */ (worker)); |
| 199 dispatchers.push(new ServiceDispatcher(servicePort)); |
| 152 } | 200 } |
| 153 | |
| 154 WorkerServicePort.prototype = { | |
| 155 /** | |
| 156 * @override | |
| 157 * @param {function(string)} messageHandler | |
| 158 * @param {function(string)} closeHandler | |
| 159 */ | |
| 160 setHandlers: function(messageHandler, closeHandler) | |
| 161 { | |
| 162 this._messageHandler = messageHandler; | |
| 163 this._closeHandler = closeHandler; | |
| 164 }, | |
| 165 | |
| 166 /** | |
| 167 * @override | |
| 168 * @param {string} data | |
| 169 * @return {!Promise} | |
| 170 */ | |
| 171 send: function(data) | |
| 172 { | |
| 173 this._port.postMessage(data); | |
| 174 return Promise.resolve(); | |
| 175 }, | |
| 176 | |
| 177 /** | |
| 178 * @override | |
| 179 * @return {!Promise} | |
| 180 */ | |
| 181 close: function() | |
| 182 { | |
| 183 return Promise.resolve(); | |
| 184 }, | |
| 185 | |
| 186 /** | |
| 187 * @param {!MessageEvent} event | |
| 188 */ | |
| 189 _onMessage: function(event) | |
| 190 { | |
| 191 this._messageHandler(event.data); | |
| 192 } | |
| 193 }; | |
| 194 | |
| 195 var dispatchers = []; | |
| 196 | |
| 197 if (self instanceof SharedWorkerGlobalScope) { | |
| 198 function onNewPort(port) | |
| 199 { | |
| 200 var dispatcher = new ServiceDispatcher(new WorkerServicePort(port)); | |
| 201 dispatchers.push(dispatcher); | |
| 202 } | |
| 203 Runtime.setSharedWorkerNewPortCallback(onNewPort); | |
| 204 } else { | |
| 205 var worker = /** @type {!Object} */(self); | |
| 206 var servicePort = new WorkerServicePort(/** @type {!Worker} */(worker)); | |
| 207 dispatchers.push(new ServiceDispatcher(servicePort)); | |
| 208 } | |
| OLD | NEW |