| Index: remoting/webapp/base/js/ipc.js
|
| diff --git a/remoting/webapp/base/js/ipc.js b/remoting/webapp/base/js/ipc.js
|
| index 16a34cfc600a2cc625668a87c1bf1c65f288dca8..0be90a7e356e333e9287ef815933b939c7079060 100644
|
| --- a/remoting/webapp/base/js/ipc.js
|
| +++ b/remoting/webapp/base/js/ipc.js
|
| @@ -49,17 +49,19 @@ var base = base || {};
|
| */
|
| base.Ipc = function() {
|
| console.assert(instance_ === null, 'Duplicate base.Ipc constructor.');
|
| - /** @private {!Object<Function>} */
|
| + /** @private {!Object<{allowExternal: boolean, method: Function>} */
|
| this.handlers_ = {};
|
| this.onMessageHandler_ =
|
| /** @type {function(*, MessageSender, function (*))} */ (
|
| this.onMessage_.bind(this));
|
| chrome.runtime.onMessage.addListener(this.onMessageHandler_);
|
| + chrome.runtime.onMessageExternal.addListener(this.onMessageHandler_);
|
| };
|
|
|
| /** @private */
|
| base.Ipc.prototype.dispose_ = function() {
|
| chrome.runtime.onMessage.removeListener(this.onMessageHandler_);
|
| + chrome.runtime.onMessageExternal.removeListener(this.onMessageHandler_);
|
| };
|
|
|
| /**
|
| @@ -69,8 +71,7 @@ base.Ipc.prototype.dispose_ = function() {
|
| */
|
| base.Ipc.Error = {
|
| UNSUPPORTED_REQUEST_TYPE: 'Unsupported method name.',
|
| - INVALID_REQUEST_ORIGIN:
|
| - 'base.Ipc only accept incoming requests from the same extension.'
|
| + UNAUTHORIZED_REQUEST_ORIGIN: 'Unauthorized origin.'
|
| };
|
|
|
| /**
|
| @@ -90,15 +91,21 @@ base.Ipc.Request_ = function(methodName, params) {
|
| * @param {string} methodName
|
| * @param {Function} handler The handler can be invoked by calling
|
| * base.Ipc.invoke(|methodName|, arg1, arg2, ...)
|
| - * Async handlers that return promises are currently not supported.
|
| + * @param {boolean=} opt_allowExternal True if the message is permitted from
|
| + * origins listed in externally_connectable; false or undefined if the
|
| + * message is only permitted from the same app.
|
| * @return {boolean} Whether the handler is successfully registered.
|
| */
|
| -base.Ipc.prototype.register = function(methodName, handler) {
|
| + base.Ipc.prototype.register = function(methodName, handler,
|
| + opt_allowExternal) {
|
| if (methodName in this.handlers_) {
|
| console.error('service ' + methodName + ' is already registered.');
|
| return false;
|
| }
|
| - this.handlers_[methodName] = handler;
|
| + this.handlers_[methodName] = {
|
| + allowExternal: Boolean(opt_allowExternal),
|
| + method: handler
|
| + };
|
| return true;
|
| };
|
|
|
| @@ -113,6 +120,8 @@ base.Ipc.prototype.unregister = function(methodName) {
|
| * @param {base.Ipc.Request_} message
|
| * @param {!MessageSender} sender
|
| * @param {function(*): void} sendResponse
|
| + * @return {boolean} True if an asynchronous response is pending; false if the
|
| + * response (if any) has already been sent.
|
| */
|
| base.Ipc.prototype.onMessage_ = function(message, sender, sendResponse) {
|
| var methodName = message.methodName;
|
| @@ -120,27 +129,35 @@ base.Ipc.prototype.onMessage_ = function(message, sender, sendResponse) {
|
| return;
|
| }
|
|
|
| - if (sender.id !== chrome.runtime.id) {
|
| - sendResponse({error: base.Ipc.Error.INVALID_REQUEST_ORIGIN});
|
| + var handler = this.handlers_[methodName];
|
| + if (!handler) {
|
| + sendResponse({error: base.Ipc.Error.UNSUPPORTED_REQUEST_TYPE});
|
| return;
|
| }
|
|
|
| - var remoteMethod =
|
| - /** @type {function(*):void} */ (this.handlers_[methodName]);
|
| - if (!remoteMethod) {
|
| - sendResponse({error: base.Ipc.Error.UNSUPPORTED_REQUEST_TYPE});
|
| + if (!handler.allowExternal && sender.id !== chrome.runtime.id) {
|
| + sendResponse({error: base.Ipc.Error.UNAUTHORIZED_REQUEST_ORIGIN});
|
| return;
|
| }
|
|
|
| try {
|
| - sendResponse(remoteMethod.apply(null, message.params));
|
| + var result = handler.method.apply(null, message.params);
|
| + if (result instanceof Promise) {
|
| + result.
|
| + then(function(response) { sendResponse(response); }).
|
| + catch(function(e) { sendResponse({error: e.message}) });
|
| + return true;
|
| + } else {
|
| + sendResponse(result);
|
| + }
|
| } catch (/** @type {Error} */ e) {
|
| sendResponse({error: e.message});
|
| }
|
| + return false;
|
| };
|
|
|
| /**
|
| - * Invokes a method on a remote page
|
| + * Invokes a method on another page within this extension.
|
| *
|
| * @param {string} methodName
|
| * @param {...} var_args
|
|
|