Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: polyfill.js

Issue 29585594: Issue 4579 - Wrap runtime.onMessage (Closed) Base URL: https://hg.adblockplus.org/adblockpluschrome/
Patch Set: Wrap removeListener and hasListener Created Oct. 23, 2017, 12:13 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>, 2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-present eyeo GmbH 3 * Copyright (C) 2006-present eyeo GmbH
4 * 4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify 5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as 6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8 * 8 *
9 * Adblock Plus is distributed in the hope that it will be useful, 9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
45 ]; 45 ];
46 46
47 // Since we add a callback for all messaging API calls in our wrappers, 47 // Since we add a callback for all messaging API calls in our wrappers,
48 // Chrome assumes we're interested in the response; when there's no response, 48 // Chrome assumes we're interested in the response; when there's no response,
49 // it sets runtime.lastError 49 // it sets runtime.lastError
50 const portClosedBeforeResponseError = 50 const portClosedBeforeResponseError =
51 // Older versions of Chrome have a typo: 51 // Older versions of Chrome have a typo:
52 // https://crrev.com/c33f51726eacdcc1a487b21a13611f7eab580d6d 52 // https://crrev.com/c33f51726eacdcc1a487b21a13611f7eab580d6d
53 /^The message port closed before a res?ponse was received\.$/; 53 /^The message port closed before a res?ponse was received\.$/;
54 54
55 // This is the error Firefox throws when a message listener is not a
56 // function.
57 const invalidMessageListenerError = "Invalid listener for runtime.onMessage.";
58
59 let messageListeners = new WeakMap();
60
55 function wrapAPI(api) 61 function wrapAPI(api)
kzar 2018/01/08 14:35:16 Since we're now wrapping the message APIs as well
Manish Jethani 2018/01/09 09:37:35 Done.
56 { 62 {
57 let object = browser; 63 let object = browser;
58 let path = api.split("."); 64 let path = api.split(".");
59 let name = path.pop(); 65 let name = path.pop();
60 66
61 for (let node of path) 67 for (let node of path)
62 { 68 {
63 object = object[node]; 69 object = object[node];
64 70
65 if (!object) 71 if (!object)
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
103 } 109 }
104 else 110 else
105 { 111 {
106 resolve(result); 112 resolve(result);
107 } 113 }
108 }); 114 });
109 }); 115 });
110 }; 116 };
111 } 117 }
112 118
119 function wrapMessageAPIs()
kzar 2018/01/08 14:35:16 Nit: `wrapRuntimeOnMessage`?
Manish Jethani 2018/01/09 09:37:35 Done.
120 {
121 let {onMessage} = browser.runtime;
122 let {addListener, removeListener, hasListener} = onMessage;
123
124 onMessage.addListener = function(listener)
125 {
126 if (typeof listener != "function")
Manish Jethani 2017/10/23 12:21:04 We must check the type here to be consistent with
kzar 2018/01/08 14:35:16 Acknowledged.
127 throw new Error(invalidMessageListenerError);
128
129 // Don't add the same listener twice or we end up with multiple wrappers.
130 if (messageListeners.has(listener))
131 return;
132
133 let wrapper = (message, sender, sendResponse) =>
134 {
135 let wait = listener(message, sender, sendResponse);
136
137 if (wait instanceof Promise)
138 {
139 wait.then(sendResponse, reason =>
140 {
141 try
142 {
143 sendResponse();
144 }
145 finally
146 {
147 // sendResponse can throw if the internal port is closed; be sure
Manish Jethani 2017/10/23 12:21:04 I haven't verified this, but in any case adding a
kzar 2018/01/08 14:35:16 Acknowledged.
148 // to throw the original error.
149 throw reason;
150 }
151 });
152 }
153
154 return !!wait;
155 };
156
157 addListener.call(onMessage, wrapper);
158 messageListeners.set(listener, wrapper);
159 };
160
161 onMessage.removeListener = function(listener)
162 {
163 if (typeof listener != "function")
164 throw new Error(invalidMessageListenerError);
165
166 let wrapper = messageListeners.get(listener);
167 if (wrapper)
168 {
169 removeListener.call(onMessage, wrapper);
170 messageListeners.delete(listener);
171 }
172 };
173
174 onMessage.hasListener = function(listener)
175 {
176 if (typeof listener != "function")
177 throw new Error(invalidMessageListenerError);
178
179 return messageListeners.has(listener);
180 };
181 }
182
113 function shouldWrapAPIs() 183 function shouldWrapAPIs()
114 { 184 {
115 try 185 try
116 { 186 {
117 return !(browser.storage.local.get([]) instanceof Promise); 187 return !(browser.storage.local.get([]) instanceof Promise);
118 } 188 }
119 catch (error) 189 catch (error)
120 { 190 {
121 } 191 }
122 192
123 return true; 193 return true;
124 } 194 }
125 195
126 if (shouldWrapAPIs()) 196 if (shouldWrapAPIs())
127 { 197 {
128 // Unlike Firefox and Microsoft Edge, Chrome doesn't have a "browser" object , 198 // Unlike Firefox and Microsoft Edge, Chrome doesn't have a "browser"
129 // but provides the extension API through the "chrome" namespace 199 // object, but provides the extension API through the "chrome" namespace
130 // (non-standard). 200 // (non-standard).
131 if (typeof browser == "undefined") 201 if (typeof browser == "undefined")
132 window.browser = chrome; 202 window.browser = chrome;
133 203
134 for (let api of asyncAPIs) 204 for (let api of asyncAPIs)
135 wrapAPI(api); 205 wrapAPI(api);
206
207 wrapMessageAPIs();
136 } 208 }
137 209
138 // Workaround since HTMLCollection, NodeList, StyleSheetList, and CSSRuleList 210 // Workaround since HTMLCollection, NodeList, StyleSheetList, and CSSRuleList
139 // didn't have iterator support before Chrome 51. 211 // didn't have iterator support before Chrome 51.
140 // https://bugs.chromium.org/p/chromium/issues/detail?id=401699 212 // https://bugs.chromium.org/p/chromium/issues/detail?id=401699
141 for (let object of [HTMLCollection, NodeList, StyleSheetList, CSSRuleList]) 213 for (let object of [HTMLCollection, NodeList, StyleSheetList, CSSRuleList])
142 { 214 {
143 if (!(Symbol.iterator in object.prototype)) 215 if (!(Symbol.iterator in object.prototype))
144 object.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator]; 216 object.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
145 } 217 }
146 } 218 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld