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

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: Ready for Checkin Created 5 years, 10 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/webapp/base/js/base.js ('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 arg1, arg2, ....
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 * @private
49 */
50 base.Ipc = function() {
51 base.debug.assert(instance_ === null);
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 /** @private */
62 base.Ipc.prototype.dispose_ = function() {
63 chrome.runtime.onMessage.removeListener(this.onMessageHandler_);
64 };
65
66 /**
67 * The error strings are only used for debugging purposes and are not localized.
68 *
69 * @enum {string}
70 */
71 base.Ipc.Error = {
72 UNSUPPORTED_REQUEST_TYPE: 'Unsupported method name.',
73 INVALID_REQUEST_ORIGIN:
74 'base.Ipc only accept incoming requests from the same extension.'
75 };
76
77 /**
78 * @constructor
79 * @param {string} methodName
80 * @param {?Array} params
81 * @struct
82 * @private
83 */
84 base.Ipc.Request_ = function(methodName, params) {
85 this.methodName = methodName;
86 this.params = params;
87 };
88
89
90 /**
91 * @param {string} methodName
92 * @param {function(?)} handler The handler can be invoked by calling
93 * base.Ipc.invoke(|methodName|, arg1, arg2, ...)
94 * Async handlers that return promises are currently not supported.
95 * @return {boolean} Whether the handler is successfully registered.
96 */
97 base.Ipc.prototype.register = function(methodName, handler) {
98 if (methodName in this.handlers_) {
99 console.error('service ' + methodName + ' is already registered.');
100 return false;
101 }
102 this.handlers_[methodName] = handler;
103 return true;
104 };
105
106 /**
107 * @param {string} methodName
108 */
109 base.Ipc.prototype.unregister = function(methodName) {
110 delete this.handlers_[methodName];
111 };
112
113 /**
114 * @param {base.Ipc.Request_} message
115 * @param {chrome.runtime.MessageSender} sender
116 * @param {function(*): void} sendResponse
117 */
118 base.Ipc.prototype.onMessage_ = function(message, sender, sendResponse) {
119 var methodName = message.methodName;
120 if (typeof methodName !== 'string') {
121 return;
122 }
123
124 if (sender.id !== chrome.runtime.id) {
125 sendResponse({error: base.Ipc.Error.INVALID_REQUEST_ORIGIN});
126 return;
127 }
128
129 var remoteMethod =
130 /** @type {function(*):void} */ (this.handlers_[methodName]);
131 if (!remoteMethod) {
132 sendResponse({error: base.Ipc.Error.UNSUPPORTED_REQUEST_TYPE});
133 return;
134 }
135
136 try {
137 sendResponse(remoteMethod.apply(null, message.params));
138 } catch (/** @type {Error} */ e) {
139 sendResponse({error: e.message});
140 }
141 };
142
143 /**
144 * Invokes a method on a remote page
145 *
146 * @param {string} methodName
147 * @param {...} var_args
148 * @return A Promise that would resolve to the return value of the handler or
149 * reject if the handler throws an exception.
150 */
151 base.Ipc.invoke = function(methodName, var_args) {
152 var params = Array.prototype.slice.call(arguments, 1);
153 var sendMessage = base.Promise.as(
154 chrome.runtime.sendMessage,
155 [null, new base.Ipc.Request_(methodName, params)]);
156
157 return sendMessage.then(
158 /** @param {?{error: Error}} response */
159 function(response) {
160 if (response && response.error) {
161 return Promise.reject(response.error);
162 } else {
163 return Promise.resolve(response);
164 }
165 });
166 };
167
168
169 /** @type {base.Ipc} */
170 var instance_ = null;
171
172 /** @return {base.Ipc} */
173 base.Ipc.getInstance = function() {
174 if (!instance_) {
175 instance_ = new base.Ipc();
176 }
177 return instance_;
178 };
179
180 base.Ipc.deleteInstance = function() {
181 if (instance_) {
182 instance_.dispose_();
183 instance_ = null;
184 }
185 };
186
187 })();
OLDNEW
« no previous file with comments | « remoting/webapp/base/js/base.js ('k') | remoting/webapp/js_proto/chrome_proto.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698