Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(317)

Side by Side Diff: remoting/webapp/base/js/ipc.js

Issue 877993002: Implement base.IPC (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « remoting/remoting_webapp_files.gypi ('k') | remoting/webapp/js_proto/chrome_proto.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 (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
11 * 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 * {methodName:{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 method with the |methodName| and enforces
21 * that only one handler can be registered per |methodName| 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 * base.IPC.getInstance().register('my.service.name', foo);
27 *
28 * In the AppWindow document:
29 * base.IPC.invoke('my.service.name', [arg1, arg2]).then(
30 * function(result) {
31 * console.log('The result is ' + result);
32 * });
33 *
34 * This will invoke foo() with the args [arg1, arg2].
kelvinp 2015/01/27 01:27:22 Jamie: Would it be a lot of work to allow args to
kelvinp 2015/01/27 01:35:00 Done.
35 * The return value of foo() will be passed back to the caller in the
36 * form of a promise.
37 */
38
39 /** @suppress {duplicate} */
40 var base = base || {};
41
42 (function() {
43
44 'use strict';
45
46 /**
47 * @constructor
48 */
49 base.IPC = function() {
kelvinp 2015/01/27 01:27:21 Jamie: I suggest base.Ipc as a name instead.
kelvinp 2015/01/27 01:34:59 I use base.IPC instead as IPC is an abbreviation.
Jamie 2015/01/27 22:52:24 I tend to treat them as if they weren't abbreviati
kelvinp 2015/01/28 01:31:51 Done.
50 base.debug.assert(instance_ === null);
51 /**
52 * @type {!Object.<Function>}
53 * @private
54 */
55 this.handlers_ = {};
56 this.onMessageHandler_ = this.onMessage_.bind(this);
57 chrome.runtime.onMessage.addListener(this.onMessageHandler_);
58 };
59
60 /** @private */
61 base.IPC.prototype.dispose_ = function() {
62 chrome.runtime.onMessage.removeListener(this.onMessageHandler_);
63 };
64
65 /** @enum {string} */
66 base.IPC.Error = {
67 UNSUPPORTED_REQUEST_TYPE: 'Unsupported method name.',
68 INVALID_REQUEST_ORIGIN:
69 'base.IPC only accept incoming requests from the same extension.'
Jamie 2015/01/27 22:52:24 Are these string ever displayed in the UI? If so t
kelvinp 2015/01/28 01:31:51 The are only logged in the console.
70 };
71
72 /**
73 * @constructor
74 * @param {string} methodName
75 * @param {?Array} params
76 * @struct
77 */
78 base.IPC.Request_ = function(methodName, params) {
kelvinp 2015/01/27 01:27:21 Jamie: If this is a private type, does it need to
kelvinp 2015/01/27 01:34:59 JSCompile cannot recognize the type unless I put i
Jamie 2015/01/27 22:52:24 Okay, in that case please annotate it as @private
kelvinp 2015/01/28 01:31:51 JSCompile can understand classes that is attached
79 this.methodName = methodName;
80 this.params = params;
81 };
82
83
84 /**
85 * @param {string} methodName
86 * @param {Function} handler The handler can be invoked by calling
kelvinp 2015/01/27 01:34:59 Jamie: s/Function/function(*):void/
kelvinp 2015/01/27 01:34:59 I think function(*):void is a bit misleading as it
Jamie 2015/01/27 22:52:24 How about function(*) then? I don't think we use F
kelvinp 2015/01/28 01:31:51 Done. Function is the JavaScript type name for all
87 * base.IPC.invoke(|methodName|, arg1, arg2, ...)
88 * Async handlers that return promises are currently not supported.
89 * @return {boolean} Whether the handler is successfully registered.
90 */
91 base.IPC.prototype.register = function(methodName, handler) {
92 if (methodName in this.handlers_) {
93 console.error('service :' + methodName + ' is already registered.');
94 return false;
95 }
96 this.handlers_[methodName] = handler;
97 return true;
98 };
99
100 /**
101 * @param {string} methodName
kelvinp 2015/01/27 01:27:22 Jamie: Since we're talking about methods, I think
kelvinp 2015/01/27 01:35:00 Done.
102 */
103 base.IPC.prototype.unregister = function(methodName) {
104 delete this.handlers_[methodName];
105 };
106
107 /**
108 * @param {base.IPC.Request_} message
109 * @param {chrome.runtime.MessageSender} sender
110 * @param {function(*): void} sendResponse
111 */
112 base.IPC.prototype.onMessage_ = function(message, sender,
113 sendResponse) {
114 var methodName = message.methodName;
115 if (typeof methodName !== 'string') {
116 return;
117 }
118
119 if (sender.id !== chrome.runtime.id) {
120 sendResponse({error : base.IPC.Error.INVALID_REQUEST_ORIGIN});
121 return;
122 }
123
124 var remoteMethod =
125 /** @type {function(*):void} */ (this.handlers_[methodName]);
126 if (!remoteMethod) {
127 sendResponse({error : base.IPC.Error.UNSUPPORTED_REQUEST_TYPE});
128 return;
129 }
130
131 try {
132 sendResponse(remoteMethod.apply(null, message.params));
133 } catch (/** @type {Error} */ e) {
134 sendResponse({error: e.message});
135 }
136 };
137
138 /**
139 * Invokes a method on a remote page
kelvinp 2015/01/27 01:34:59 Done.
kelvinp 2015/01/27 01:34:59 Jamie: Blank (comment) line after method descripti
140 *
141 * @param {string} methodName
142 * @param {...} var_args
143 * @return A Promise that would resolves to the return value of the handler or
kelvinp 2015/01/27 01:27:21 Jamie: @return?
kelvinp 2015/01/27 01:34:59 Done.
144 * rejects if the handler throws an exception.
145 */
146 base.IPC.invoke = function(methodName, var_args) {
147 var params = Array.prototype.slice.call(arguments, 1);
148 var sendMessage = base.Promise.as(
149 chrome.runtime.sendMessage,
150 [null, new base.IPC.Request_(methodName, params)]);
kelvinp 2015/01/27 01:27:21 Jamie: I don't think you need the leading null, si
kelvinp 2015/01/27 01:34:59 Good point. The leading null is there to reduce t
Jamie 2015/01/27 22:52:24 Fair enough, but I worry about the robustness of t
kelvinp 2015/01/28 01:31:51 Done.
151
152 return sendMessage.then(
153 /** @param {?{error: Error}} response */
154 function(response) {
155 if (response && response.error) {
156 return Promise.reject(response.error);
kelvinp 2015/01/27 01:27:22 Jamie: Don't these reject/resolves need to be retu
kelvinp 2015/01/27 01:34:59 Good catch. Done.
157 } else {
158 return Promise.resolve(response);
159 }
160 });
161 };
162
163
164 /** @type {base.IPC} */
165 var instance_ = null;
kelvinp 2015/01/27 01:27:22 Jamie: Although we have too many globals in our co
kelvinp 2015/01/27 01:34:59 Done.
166
167 /** @return {base.IPC} */
168 base.IPC.getInstance = function() {
169 if (!instance_) {
170 instance_ = new base.IPC();
171 }
172 return instance_;
173 };
174
175 base.IPC.deleteInstance = function() {
176 if (instance_) {
177 instance_.dispose_();
178 instance_ = null;
179 }
180 };
181
182 })();
OLDNEW
« no previous file with comments | « remoting/remoting_webapp_files.gypi ('k') | remoting/webapp/js_proto/chrome_proto.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698