Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggestion: identify exhaustive whitelist of promisable functions #28

Open
dlh3 opened this issue Sep 22, 2020 · 2 comments
Open

Suggestion: identify exhaustive whitelist of promisable functions #28

dlh3 opened this issue Sep 22, 2020 · 2 comments

Comments

@dlh3
Copy link
Contributor

dlh3 commented Sep 22, 2020

@KeithHenry I noticed in a comment from last year that you didn't have a way to reliably detect the promiseable functions in the chrome API.

I took a stab at generating something that might help.

I started by collecting all documented permissions:

Array.from(
    document.querySelector("table:not([class])")
        .children[0]
        .children)
            .map(row => row.id)
            .join('", "');

I added those to an extension, then executed this from the background:

apis = {};
Object.keys(chrome)
  .filter(k => typeof chrome[k] === "object")
  .forEach(k => 
      Object.keys(chrome[k])
        .filter(j => typeof chrome[k][j] === "function")
        .forEach(j => {
            try {
                // trollolololol, or pass an unlikely number of arguments
                chrome[k][j](undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined);
            } catch (err) {
                if (err.message.includes("No matching signature.") && err.message.includes("function callback")) {
                    apis[k] = apis[k] || {};
                    apis[k][j] = `chrome.${k}.${j}`;
                }
            }
        }));
console.log(apis);
JSON.stringify(apis);

And that yielded this:

{
    "alarms": {
        "clear": "chrome.alarms.clear",
        "clearAll": "chrome.alarms.clearAll",
        "get": "chrome.alarms.get",
        "getAll": "chrome.alarms.getAll"
    },
    "bookmarks": {
        "create": "chrome.bookmarks.create",
        "get": "chrome.bookmarks.get",
        "getChildren": "chrome.bookmarks.getChildren",
        "getRecent": "chrome.bookmarks.getRecent",
        "getSubTree": "chrome.bookmarks.getSubTree",
        "getTree": "chrome.bookmarks.getTree",
        "move": "chrome.bookmarks.move",
        "remove": "chrome.bookmarks.remove",
        "removeTree": "chrome.bookmarks.removeTree",
        "search": "chrome.bookmarks.search",
        "update": "chrome.bookmarks.update"
    },
    "browserAction": {
        "disable": "chrome.browserAction.disable",
        "enable": "chrome.browserAction.enable",
        "getBadgeBackgroundColor": "chrome.browserAction.getBadgeBackgroundColor",
        "getBadgeText": "chrome.browserAction.getBadgeText",
        "getPopup": "chrome.browserAction.getPopup",
        "getTitle": "chrome.browserAction.getTitle",
        "setBadgeBackgroundColor": "chrome.browserAction.setBadgeBackgroundColor",
        "setBadgeText": "chrome.browserAction.setBadgeText",
        "setIcon": "chrome.browserAction.setIcon",
        "setPopup": "chrome.browserAction.setPopup",
        "setTitle": "chrome.browserAction.setTitle"
    },
    "browsingData": {
        "remove": "chrome.browsingData.remove",
        "removeAppcache": "chrome.browsingData.removeAppcache",
        "removeCache": "chrome.browsingData.removeCache",
        "removeCacheStorage": "chrome.browsingData.removeCacheStorage",
        "removeCookies": "chrome.browsingData.removeCookies",
        "removeDownloads": "chrome.browsingData.removeDownloads",
        "removeFileSystems": "chrome.browsingData.removeFileSystems",
        "removeFormData": "chrome.browsingData.removeFormData",
        "removeHistory": "chrome.browsingData.removeHistory",
        "removeIndexedDB": "chrome.browsingData.removeIndexedDB",
        "removeLocalStorage": "chrome.browsingData.removeLocalStorage",
        "removePasswords": "chrome.browsingData.removePasswords",
        "removePluginData": "chrome.browsingData.removePluginData",
        "removeServiceWorkers": "chrome.browsingData.removeServiceWorkers",
        "removeWebSQL": "chrome.browsingData.removeWebSQL",
        "settings": "chrome.browsingData.settings"
    },
    "clipboard": {
        "setImageData": "chrome.clipboard.setImageData"
    },
    "contextMenus": {
        "create": "chrome.contextMenus.create",
        "remove": "chrome.contextMenus.remove",
        "removeAll": "chrome.contextMenus.removeAll",
        "update": "chrome.contextMenus.update"
    },
    "cookies": {
        "get": "chrome.cookies.get",
        "getAll": "chrome.cookies.getAll",
        "getAllCookieStores": "chrome.cookies.getAllCookieStores",
        "remove": "chrome.cookies.remove",
        "set": "chrome.cookies.set"
    },
    "debugger": {
        "attach": "chrome.debugger.attach",
        "detach": "chrome.debugger.detach",
        "getTargets": "chrome.debugger.getTargets",
        "sendCommand": "chrome.debugger.sendCommand"
    },
    "declarativeNetRequest": {
        "getDynamicRules": "chrome.declarativeNetRequest.getDynamicRules",
        "getEnabledRulesets": "chrome.declarativeNetRequest.getEnabledRulesets",
        "getMatchedRules": "chrome.declarativeNetRequest.getMatchedRules",
        "updateDynamicRules": "chrome.declarativeNetRequest.updateDynamicRules",
        "updateEnabledRulesets": "chrome.declarativeNetRequest.updateEnabledRulesets"
    },
    "desktopCapture": {
        "chooseDesktopMedia": "chrome.desktopCapture.chooseDesktopMedia"
    },
    "downloads": {
        "acceptDanger": "chrome.downloads.acceptDanger",
        "cancel": "chrome.downloads.cancel",
        "download": "chrome.downloads.download",
        "erase": "chrome.downloads.erase",
        "getFileIcon": "chrome.downloads.getFileIcon",
        "pause": "chrome.downloads.pause",
        "removeFile": "chrome.downloads.removeFile",
        "resume": "chrome.downloads.resume",
        "search": "chrome.downloads.search"
    },
    "extension": {
        "isAllowedFileSchemeAccess": "chrome.extension.isAllowedFileSchemeAccess",
        "isAllowedIncognitoAccess": "chrome.extension.isAllowedIncognitoAccess"
    },
    "fontSettings": {
        "clearDefaultFixedFontSize": "chrome.fontSettings.clearDefaultFixedFontSize",
        "clearDefaultFontSize": "chrome.fontSettings.clearDefaultFontSize",
        "clearFont": "chrome.fontSettings.clearFont",
        "clearMinimumFontSize": "chrome.fontSettings.clearMinimumFontSize",
        "getDefaultFixedFontSize": "chrome.fontSettings.getDefaultFixedFontSize",
        "getDefaultFontSize": "chrome.fontSettings.getDefaultFontSize",
        "getFont": "chrome.fontSettings.getFont",
        "getFontList": "chrome.fontSettings.getFontList",
        "getMinimumFontSize": "chrome.fontSettings.getMinimumFontSize",
        "setDefaultFixedFontSize": "chrome.fontSettings.setDefaultFixedFontSize",
        "setDefaultFontSize": "chrome.fontSettings.setDefaultFontSize",
        "setFont": "chrome.fontSettings.setFont",
        "setMinimumFontSize": "chrome.fontSettings.setMinimumFontSize"
    },
    "gcm": {
        "register": "chrome.gcm.register",
        "send": "chrome.gcm.send",
        "unregister": "chrome.gcm.unregister"
    },
    "history": {
        "addUrl": "chrome.history.addUrl",
        "deleteAll": "chrome.history.deleteAll",
        "deleteRange": "chrome.history.deleteRange",
        "deleteUrl": "chrome.history.deleteUrl",
        "getVisits": "chrome.history.getVisits",
        "search": "chrome.history.search"
    },
    "i18n": {
        "detectLanguage": "chrome.i18n.detectLanguage",
        "getAcceptLanguages": "chrome.i18n.getAcceptLanguages"
    },
    "identity": {
        "getAuthToken": "chrome.identity.getAuthToken",
        "getProfileUserInfo": "chrome.identity.getProfileUserInfo",
        "launchWebAuthFlow": "chrome.identity.launchWebAuthFlow",
        "removeCachedAuthToken": "chrome.identity.removeCachedAuthToken"
    },
    "idle": {
        "queryState": "chrome.idle.queryState"
    },
    "instanceID": {
        "deleteID": "chrome.instanceID.deleteID",
        "deleteToken": "chrome.instanceID.deleteToken",
        "getCreationTime": "chrome.instanceID.getCreationTime",
        "getID": "chrome.instanceID.getID",
        "getToken": "chrome.instanceID.getToken"
    },
    "management": {
        "createAppShortcut": "chrome.management.createAppShortcut",
        "generateAppForLink": "chrome.management.generateAppForLink",
        "get": "chrome.management.get",
        "getAll": "chrome.management.getAll",
        "getPermissionWarningsById": "chrome.management.getPermissionWarningsById",
        "getPermissionWarningsByManifest": "chrome.management.getPermissionWarningsByManifest",
        "getSelf": "chrome.management.getSelf",
        "launchApp": "chrome.management.launchApp",
        "setEnabled": "chrome.management.setEnabled",
        "setLaunchType": "chrome.management.setLaunchType",
        "uninstall": "chrome.management.uninstall",
        "uninstallSelf": "chrome.management.uninstallSelf"
    },
    "notifications": {
        "clear": "chrome.notifications.clear",
        "create": "chrome.notifications.create",
        "getAll": "chrome.notifications.getAll",
        "getPermissionLevel": "chrome.notifications.getPermissionLevel",
        "update": "chrome.notifications.update"
    },
    "pageCapture": {
        "saveAsMHTML": "chrome.pageCapture.saveAsMHTML"
    },
    "permissions": {
        "getAll": "chrome.permissions.getAll"
    },
    "runtime": {
        "getBackgroundPage": "chrome.runtime.getBackgroundPage",
        "getPackageDirectoryEntry": "chrome.runtime.getPackageDirectoryEntry",
        "getPlatformInfo": "chrome.runtime.getPlatformInfo",
        "openOptionsPage": "chrome.runtime.openOptionsPage",
        "requestUpdateCheck": "chrome.runtime.requestUpdateCheck",
        "restartAfterDelay": "chrome.runtime.restartAfterDelay",
        "setUninstallURL": "chrome.runtime.setUninstallURL"
    },
    "sessions": {
        "getDevices": "chrome.sessions.getDevices",
        "getRecentlyClosed": "chrome.sessions.getRecentlyClosed",
        "restore": "chrome.sessions.restore"
    },
    "tabCapture": {
        "capture": "chrome.tabCapture.capture",
        "captureOffscreenTab": "chrome.tabCapture.captureOffscreenTab",
        "getCapturedTabs": "chrome.tabCapture.getCapturedTabs",
        "getMediaStreamId": "chrome.tabCapture.getMediaStreamId"
    },
    "tabs": {
        "captureVisibleTab": "chrome.tabs.captureVisibleTab",
        "create": "chrome.tabs.create",
        "detectLanguage": "chrome.tabs.detectLanguage",
        "discard": "chrome.tabs.discard",
        "duplicate": "chrome.tabs.duplicate",
        "executeScript": "chrome.tabs.executeScript",
        "get": "chrome.tabs.get",
        "getAllInWindow": "chrome.tabs.getAllInWindow",
        "getCurrent": "chrome.tabs.getCurrent",
        "getSelected": "chrome.tabs.getSelected",
        "getZoom": "chrome.tabs.getZoom",
        "getZoomSettings": "chrome.tabs.getZoomSettings",
        "goBack": "chrome.tabs.goBack",
        "goForward": "chrome.tabs.goForward",
        "highlight": "chrome.tabs.highlight",
        "insertCSS": "chrome.tabs.insertCSS",
        "move": "chrome.tabs.move",
        "query": "chrome.tabs.query",
        "reload": "chrome.tabs.reload",
        "remove": "chrome.tabs.remove",
        "setZoom": "chrome.tabs.setZoom",
        "setZoomSettings": "chrome.tabs.setZoomSettings",
        "update": "chrome.tabs.update"
    },
    "topSites": {
        "get": "chrome.topSites.get"
    },
    "tts": {
        "getVoices": "chrome.tts.getVoices",
        "isSpeaking": "chrome.tts.isSpeaking",
        "speak": "chrome.tts.speak"
    },
    "webNavigation": {
        "getAllFrames": "chrome.webNavigation.getAllFrames",
        "getFrame": "chrome.webNavigation.getFrame"
    },
    "webRequest": {
        "handlerBehaviorChanged": "chrome.webRequest.handlerBehaviorChanged"
    },
    "windows": {
        "create": "chrome.windows.create",
        "get": "chrome.windows.get",
        "getAll": "chrome.windows.getAll",
        "getCurrent": "chrome.windows.getCurrent",
        "getLastFocused": "chrome.windows.getLastFocused",
        "remove": "chrome.windows.remove",
        "update": "chrome.windows.update"
    }
}

Hope this helps!

@KeithHenry
Copy link
Owner

@dlh3 Cheers. That's a really nice way of programmatically finding all the methods with a callback function.

I think there is a route to a programmatically configured API here, but the current list (while not dynamic) is mostly tested and includes some manual removals (such as #26).

I suspect the risk of breaking existing implementation with this change might be higher than the potential benefit of supporting new or missing APIs.

Next steps would be to compare this generated list to the existing one, and test and manually add missing ones.

@dlh3
Copy link
Contributor Author

dlh3 commented Sep 29, 2020

Happy to help. I agree that a programmatic solution could follow from this, though I believe it would be fairly inefficient. My intent was really to provide a way for generating a list for the purpose of comparing against the currently implemented list.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants