| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 | 4 |
| 5 /** | 5 /** |
| 6 * @fileoverview | 6 * @fileoverview |
| 7 * | 7 * |
| 8 * In Chrome Apps, some platform APIs can only be called from the background | 8 * In Chrome Apps, some platform APIs can only be called from the background |
| 9 * page (e.g. reloading a chrome.app.AppWindow). Likewise, some chrome API's | 9 * page (e.g. reloading a chrome.app.AppWindow). Likewise, some chrome API's |
| 10 * must be initiated by user interaction, which can only be called from the | 10 * must be initiated by user interaction, which can only be called from the |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 (function() { | 42 (function() { |
| 43 | 43 |
| 44 'use strict'; | 44 'use strict'; |
| 45 | 45 |
| 46 /** | 46 /** |
| 47 * @constructor | 47 * @constructor |
| 48 * @private | 48 * @private |
| 49 */ | 49 */ |
| 50 base.Ipc = function() { | 50 base.Ipc = function() { |
| 51 console.assert(instance_ === null, 'Duplicate base.Ipc constructor.'); | 51 console.assert(instance_ === null, 'Duplicate base.Ipc constructor.'); |
| 52 /** @private {!Object<Function>} */ | 52 /** @private {!Object<{allowExternal: boolean, method: Function>} */ |
| 53 this.handlers_ = {}; | 53 this.handlers_ = {}; |
| 54 this.onMessageHandler_ = | 54 this.onMessageHandler_ = |
| 55 /** @type {function(*, MessageSender, function (*))} */ ( | 55 /** @type {function(*, MessageSender, function (*))} */ ( |
| 56 this.onMessage_.bind(this)); | 56 this.onMessage_.bind(this)); |
| 57 chrome.runtime.onMessage.addListener(this.onMessageHandler_); | 57 chrome.runtime.onMessage.addListener(this.onMessageHandler_); |
| 58 chrome.runtime.onMessageExternal.addListener(this.onMessageHandler_); |
| 58 }; | 59 }; |
| 59 | 60 |
| 60 /** @private */ | 61 /** @private */ |
| 61 base.Ipc.prototype.dispose_ = function() { | 62 base.Ipc.prototype.dispose_ = function() { |
| 62 chrome.runtime.onMessage.removeListener(this.onMessageHandler_); | 63 chrome.runtime.onMessage.removeListener(this.onMessageHandler_); |
| 64 chrome.runtime.onMessageExternal.removeListener(this.onMessageHandler_); |
| 63 }; | 65 }; |
| 64 | 66 |
| 65 /** | 67 /** |
| 66 * The error strings are only used for debugging purposes and are not localized. | 68 * The error strings are only used for debugging purposes and are not localized. |
| 67 * | 69 * |
| 68 * @enum {string} | 70 * @enum {string} |
| 69 */ | 71 */ |
| 70 base.Ipc.Error = { | 72 base.Ipc.Error = { |
| 71 UNSUPPORTED_REQUEST_TYPE: 'Unsupported method name.', | 73 UNSUPPORTED_REQUEST_TYPE: 'Unsupported method name.', |
| 72 INVALID_REQUEST_ORIGIN: | 74 UNAUTHORIZED_REQUEST_ORIGIN: 'Unauthorized origin.' |
| 73 'base.Ipc only accept incoming requests from the same extension.' | |
| 74 }; | 75 }; |
| 75 | 76 |
| 76 /** | 77 /** |
| 77 * @constructor | 78 * @constructor |
| 78 * @param {string} methodName | 79 * @param {string} methodName |
| 79 * @param {?Array} params | 80 * @param {?Array} params |
| 80 * @struct | 81 * @struct |
| 81 * @private | 82 * @private |
| 82 */ | 83 */ |
| 83 base.Ipc.Request_ = function(methodName, params) { | 84 base.Ipc.Request_ = function(methodName, params) { |
| 84 this.methodName = methodName; | 85 this.methodName = methodName; |
| 85 this.params = params; | 86 this.params = params; |
| 86 }; | 87 }; |
| 87 | 88 |
| 88 | 89 |
| 89 /** | 90 /** |
| 90 * @param {string} methodName | 91 * @param {string} methodName |
| 91 * @param {Function} handler The handler can be invoked by calling | 92 * @param {Function} handler The handler can be invoked by calling |
| 92 * base.Ipc.invoke(|methodName|, arg1, arg2, ...) | 93 * base.Ipc.invoke(|methodName|, arg1, arg2, ...) |
| 93 * Async handlers that return promises are currently not supported. | 94 * @param {boolean=} opt_allowExternal True if the message is permitted from |
| 95 * origins listed in externally_connectable; false or undefined if the |
| 96 * message is only permitted from the same app. |
| 94 * @return {boolean} Whether the handler is successfully registered. | 97 * @return {boolean} Whether the handler is successfully registered. |
| 95 */ | 98 */ |
| 96 base.Ipc.prototype.register = function(methodName, handler) { | 99 base.Ipc.prototype.register = function(methodName, handler, |
| 100 opt_allowExternal) { |
| 97 if (methodName in this.handlers_) { | 101 if (methodName in this.handlers_) { |
| 98 console.error('service ' + methodName + ' is already registered.'); | 102 console.error('service ' + methodName + ' is already registered.'); |
| 99 return false; | 103 return false; |
| 100 } | 104 } |
| 101 this.handlers_[methodName] = handler; | 105 this.handlers_[methodName] = { |
| 106 allowExternal: Boolean(opt_allowExternal), |
| 107 method: handler |
| 108 }; |
| 102 return true; | 109 return true; |
| 103 }; | 110 }; |
| 104 | 111 |
| 105 /** | 112 /** |
| 106 * @param {string} methodName | 113 * @param {string} methodName |
| 107 */ | 114 */ |
| 108 base.Ipc.prototype.unregister = function(methodName) { | 115 base.Ipc.prototype.unregister = function(methodName) { |
| 109 delete this.handlers_[methodName]; | 116 delete this.handlers_[methodName]; |
| 110 }; | 117 }; |
| 111 | 118 |
| 112 /** | 119 /** |
| 113 * @param {base.Ipc.Request_} message | 120 * @param {base.Ipc.Request_} message |
| 114 * @param {!MessageSender} sender | 121 * @param {!MessageSender} sender |
| 115 * @param {function(*): void} sendResponse | 122 * @param {function(*): void} sendResponse |
| 123 * @return {boolean} True if an asynchronous response is pending; false if the |
| 124 * response (if any) has already been sent. |
| 116 */ | 125 */ |
| 117 base.Ipc.prototype.onMessage_ = function(message, sender, sendResponse) { | 126 base.Ipc.prototype.onMessage_ = function(message, sender, sendResponse) { |
| 118 var methodName = message.methodName; | 127 var methodName = message.methodName; |
| 119 if (typeof methodName !== 'string') { | 128 if (typeof methodName !== 'string') { |
| 120 return; | 129 return; |
| 121 } | 130 } |
| 122 | 131 |
| 123 if (sender.id !== chrome.runtime.id) { | 132 var handler = this.handlers_[methodName]; |
| 124 sendResponse({error: base.Ipc.Error.INVALID_REQUEST_ORIGIN}); | 133 if (!handler) { |
| 125 return; | |
| 126 } | |
| 127 | |
| 128 var remoteMethod = | |
| 129 /** @type {function(*):void} */ (this.handlers_[methodName]); | |
| 130 if (!remoteMethod) { | |
| 131 sendResponse({error: base.Ipc.Error.UNSUPPORTED_REQUEST_TYPE}); | 134 sendResponse({error: base.Ipc.Error.UNSUPPORTED_REQUEST_TYPE}); |
| 132 return; | 135 return; |
| 133 } | 136 } |
| 134 | 137 |
| 138 if (!handler.allowExternal && sender.id !== chrome.runtime.id) { |
| 139 sendResponse({error: base.Ipc.Error.UNAUTHORIZED_REQUEST_ORIGIN}); |
| 140 return; |
| 141 } |
| 142 |
| 135 try { | 143 try { |
| 136 sendResponse(remoteMethod.apply(null, message.params)); | 144 var result = handler.method.apply(null, message.params); |
| 145 if (result instanceof Promise) { |
| 146 result. |
| 147 then(function(response) { sendResponse(response); }). |
| 148 catch(function(e) { sendResponse({error: e.message}) }); |
| 149 return true; |
| 150 } else { |
| 151 sendResponse(result); |
| 152 } |
| 137 } catch (/** @type {Error} */ e) { | 153 } catch (/** @type {Error} */ e) { |
| 138 sendResponse({error: e.message}); | 154 sendResponse({error: e.message}); |
| 139 } | 155 } |
| 156 return false; |
| 140 }; | 157 }; |
| 141 | 158 |
| 142 /** | 159 /** |
| 143 * Invokes a method on a remote page | 160 * Invokes a method on another page within this extension. |
| 144 * | 161 * |
| 145 * @param {string} methodName | 162 * @param {string} methodName |
| 146 * @param {...} var_args | 163 * @param {...} var_args |
| 147 * @return {Promise} A Promise that would resolve to the return value of the | 164 * @return {Promise} A Promise that would resolve to the return value of the |
| 148 * handler or reject if the handler throws an exception. | 165 * handler or reject if the handler throws an exception. |
| 149 * @suppress {reportUnknownTypes} | 166 * @suppress {reportUnknownTypes} |
| 150 */ | 167 */ |
| 151 base.Ipc.invoke = function(methodName, var_args) { | 168 base.Ipc.invoke = function(methodName, var_args) { |
| 152 var params = Array.prototype.slice.call(arguments, 1); | 169 var params = Array.prototype.slice.call(arguments, 1); |
| 153 var sendMessage = base.Promise.as( | 170 var sendMessage = base.Promise.as( |
| (...skipping 24 matching lines...) Expand all Loading... |
| 178 }; | 195 }; |
| 179 | 196 |
| 180 base.Ipc.deleteInstance = function() { | 197 base.Ipc.deleteInstance = function() { |
| 181 if (instance_) { | 198 if (instance_) { |
| 182 instance_.dispose_(); | 199 instance_.dispose_(); |
| 183 instance_ = null; | 200 instance_ = null; |
| 184 } | 201 } |
| 185 }; | 202 }; |
| 186 | 203 |
| 187 })(); | 204 })(); |
| OLD | NEW |