Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 /** | |
| 6 * @fileoverview | |
| 7 * | |
| 8 * In Chrome Apps, some platform APIs can only be called from the background | |
| 9 * page. For example, you can only reload an chrome.app.AppWindow from a | |
| 10 * background page. Likewise, some chrome API's must be initiated by user | |
| 11 * interaction, which can only be called from the foreground. | |
| 12 * | |
| 13 * This class provides helper functions to invoke methods on different pages | |
| 14 * using chrome.runtime.sendMessage. Messages are passed in the following | |
| 15 * format: | |
| 16 * {requestType:{string}, params:{Array}} | |
| 17 * | |
| 18 * chrome.runtime.sendMessage allows multiple handlers to be registered on a | |
| 19 * document, but only one handler can send a response. | |
| 20 * This class uniquely identifies a request with the requestType and enforces | |
| 21 * that only one handler can be registered per requestType in the document. | |
| 22 * | |
| 23 * For example, to call method foo() in the background page from the foreground | |
| 24 * chrome.app.AppWindow, you can do the following. | |
| 25 * In the background page: | |
| 26 * var remoteMethods = new base.remoteMethods(); | |
| 27 * remoteMethods.register('my.service.name', foo); | |
| 28 * | |
| 29 * In the AppWindow document: | |
| 30 * base.remoteMethods.invoke('my.service.name', [arg1, arg2]).then( | |
|
Jamie
2015/01/23 23:33:26
Would it be a lot of work to allow args to be pass
| |
| 31 * function(result) { | |
| 32 * console.log('The result is ' + result); | |
| 33 * }); | |
| 34 * | |
| 35 * This will invoke foo() with the args [arg1, arg2]. | |
| 36 * The return value of foo() will be passed back to the caller in the | |
| 37 * form of a promise. | |
| 38 */ | |
| 39 | |
| 40 /** @suppress {duplicate} */ | |
| 41 var base = base || {}; | |
| 42 | |
| 43 (function() { | |
| 44 | |
| 45 'use strict'; | |
| 46 | |
| 47 /** | |
| 48 * @constructor | |
| 49 * @implements {base.Disposable} | |
| 50 */ | |
| 51 base.RemoteMethods = function() { | |
|
Jamie
2015/01/23 23:33:26
I suggest base.Ipc as a name instead.
Jamie
2015/01/23 23:33:26
With a suitable chrome.runtime.sendMessage mock, I
| |
| 52 /** | |
| 53 * @type {!Object.<Function>} | |
| 54 * @private | |
| 55 */ | |
| 56 this.handlers_ = {}; | |
| 57 this.onMessageHandler_ = this.onMessage_.bind(this); | |
| 58 chrome.runtime.onMessage.addListener(this.onMessageHandler_); | |
| 59 }; | |
| 60 | |
| 61 | |
| 62 /** | |
| 63 * @constructor | |
| 64 * @param {string} requestType | |
| 65 * @param {?Array} params | |
| 66 * @struct | |
| 67 */ | |
| 68 base.RemoteMethods.Request_ = function(requestType, params) { | |
|
Jamie
2015/01/23 23:33:26
If this is a private type, does it need to be expo
| |
| 69 this.requestType = requestType; | |
| 70 this.params = params; | |
| 71 }; | |
| 72 | |
| 73 base.RemoteMethods.prototype.dispose = function() { | |
| 74 chrome.runtime.onMessage.removeListener(this.onMessageHandler_); | |
| 75 }; | |
| 76 | |
| 77 /** | |
| 78 * @param {string} requestType | |
|
Jamie
2015/01/23 23:33:26
Since we're talking about methods, I think methodN
| |
| 79 * @param {Function} handler | |
|
Jamie
2015/01/23 23:33:26
s/Function/function(*):void/
| |
| 80 * @return {boolean} Whether the handler is successfully registered. | |
| 81 */ | |
| 82 base.RemoteMethods.prototype.register = function(requestType, handler) { | |
| 83 if (requestType in this.handlers_) { | |
| 84 console.error('service :' + requestType + ' is already registered.'); | |
| 85 return false; | |
| 86 } | |
| 87 this.handlers_[requestType] = handler; | |
| 88 return true; | |
| 89 }; | |
| 90 | |
| 91 /** | |
| 92 * @param {string} requestType | |
| 93 */ | |
| 94 base.RemoteMethods.prototype.unregister = function(requestType) { | |
| 95 delete this.handlers_[requestType]; | |
| 96 }; | |
| 97 | |
| 98 /** | |
| 99 * @param {base.RemoteMethods.Request_} message | |
| 100 * @param {chrome.runtime.MessageSender} sender | |
| 101 * @param {function(*): void} sendResponse | |
| 102 */ | |
| 103 base.RemoteMethods.prototype.onMessage_ = function(message, sender, | |
| 104 sendResponse) { | |
| 105 if (sender.id !== chrome.runtime.id) { | |
| 106 // We only handle incoming requests from our extension. | |
| 107 return; | |
| 108 } | |
| 109 | |
| 110 var requestType = message.requestType; | |
| 111 if (typeof requestType !== 'string') { | |
| 112 return; | |
| 113 } | |
| 114 | |
| 115 var remoteMethod = | |
| 116 /** @type {function(*):void} */ (this.handlers_[requestType]); | |
| 117 if (!remoteMethod) { | |
| 118 sendResponse({error : 'Unsupported request:= ' + requestType}); | |
|
Jamie
2015/01/23 23:33:26
Nit: s/:=/:/
| |
| 119 return; | |
| 120 } | |
| 121 | |
| 122 try { | |
| 123 sendResponse(remoteMethod.apply(null, message.params)); | |
| 124 } catch (/** @type {Error} */ e) { | |
| 125 sendResponse({error: e.message}); | |
| 126 } | |
| 127 }; | |
| 128 | |
| 129 /** | |
| 130 * Invokes a method on a remote page | |
|
Jamie
2015/01/23 23:33:26
Blank (comment) line after method description.
| |
| 131 * @param {string} requestType | |
| 132 * @param {Array} params | |
|
Jamie
2015/01/23 23:33:26
@return?
| |
| 133 */ | |
| 134 base.RemoteMethods.invoke = function(requestType, params) { | |
| 135 var sendMessage = base.Promise.as( | |
| 136 chrome.runtime.sendMessage, | |
| 137 [null, new base.RemoteMethods.Request_(requestType, params)]); | |
|
Jamie
2015/01/23 23:33:26
I don't think you need the leading null, since the
| |
| 138 | |
| 139 return sendMessage.then( | |
| 140 /** @param {{error: Error}} response */ | |
| 141 function(response) { | |
| 142 if (response.error) { | |
| 143 Promise.reject(response.error); | |
| 144 } else { | |
| 145 Promise.resolve(response); | |
|
Jamie
2015/01/23 23:33:26
Don't these reject/resolves need to be returned?
| |
| 146 } | |
| 147 }); | |
| 148 }; | |
| 149 | |
| 150 })(); | |
|
Jamie
2015/01/23 23:33:26
Although we have too many globals in our code, I t
| |
| OLD | NEW |