| Index: ext/common.js |
| =================================================================== |
| --- a/ext/common.js |
| +++ b/ext/common.js |
| @@ -20,16 +20,85 @@ |
| (function() |
| { |
| // Both Edge and Mozilla Web Extensions use the namespace |
| // 'browser' instead of 'chrome'. Edge has chrome namespace defined, |
| // in some cases, but only with one property: 'app'. |
| if (typeof chrome == "undefined" || typeof chrome.extension == "undefined") |
| window.chrome = window.browser; |
| + const asyncAPIs = [ |
|
Manish Jethani
2017/10/11 19:23:51
This is the list of async APIs we actually use.
I
|
| + "contextMenus.removeAll", |
| + "devtools.panels.create", |
| + "notifications.clear", |
| + "notifications.create", |
| + "runtime.openOptionsPage", |
| + "runtime.sendMessage", |
| + "runtime.setUninstallURL", |
| + "storage.local.get", |
| + "storage.local.remove", |
| + "storage.local.set", |
| + "storage.managed.get", |
| + "tabs.create", |
| + "tabs.get", |
| + "tabs.insertCSS", |
| + "tabs.query", |
| + "tabs.reload", |
| + "tabs.sendMessage", |
| + "tabs.update", |
| + "webNavigation.getAllFrames", |
| + "webRequest.handlerBehaviorChanged", |
| + "windows.create", |
| + "windows.update" |
| + ]; |
| + |
| + function wrapAPI(api, object) |
| + { |
| + if (!object) |
| + return; |
| + |
| + let [root, ...subPath] = api.split("."); |
| + |
| + if (subPath.length > 0) |
| + { |
| + wrapAPI(subPath.join("."), object[root]); |
| + return; |
| + } |
| + |
| + let func = object[root]; |
| + object[root] = function(...args) |
| + { |
| + if (typeof args[args.length - 1] == "function") |
| + return func.apply(object, args); |
| + |
| + // If the last argument is undefined, we drop it from the list assuming |
| + // it stands for the optional callback. We must do this, because we have |
| + // to replace it with our own callback. If we simply append our own |
| + // callback to the list, it won't match the signature of the function and |
| + // will cause an exception. |
| + if (typeof args[args.length - 1] == "undefined") |
|
Manish Jethani
2017/10/11 19:23:51
This should work, but if it doesn't we can always
|
| + args.pop(); |
| + |
| + return new Promise((resolve, reject) => |
| + { |
| + func.call(object, ...args, result => |
| + { |
| + let error = chrome.runtime.lastError; |
|
Manish Jethani
2017/10/11 19:23:51
It's OK to refer to chrome directly here. It will
|
| + if (error) |
| + reject(error); |
| + else |
| + resolve(result); |
| + }); |
| + }); |
| + }; |
| + } |
| + |
| + for (let api of asyncAPIs) |
| + wrapAPI(api, chrome); |
| + |
| window.ext = {}; |
| let EventTarget = ext._EventTarget = function() |
| { |
| this._listeners = new Set(); |
| }; |
| EventTarget.prototype = { |
| addListener(listener) |