| Index: ext/background.js |
| =================================================================== |
| --- a/ext/background.js |
| +++ b/ext/background.js |
| @@ -93,45 +93,45 @@ |
| { |
| let frame = frames.get(0); |
| if (frame) |
| return frame.url; |
| } |
| }, |
| sendMessage(message, responseCallback) |
| { |
| - chrome.tabs.sendMessage(this.id, message, responseCallback); |
| + browser.tabs.sendMessage(this.id, message, responseCallback); |
| } |
| }; |
| ext.getPage = id => new Page({id: parseInt(id, 10)}); |
| function afterTabLoaded(callback) |
| { |
| return openedTab => |
| { |
| let onUpdated = (tabId, changeInfo, tab) => |
| { |
| if (tabId == openedTab.id && changeInfo.status == "complete") |
| { |
| - chrome.tabs.onUpdated.removeListener(onUpdated); |
| + browser.tabs.onUpdated.removeListener(onUpdated); |
| callback(new Page(openedTab)); |
| } |
| }; |
| - chrome.tabs.onUpdated.addListener(onUpdated); |
| + browser.tabs.onUpdated.addListener(onUpdated); |
| }; |
| } |
| ext.pages = { |
| onLoading: new ext._EventTarget(), |
| onActivated: new ext._EventTarget(), |
| onRemoved: new ext._EventTarget() |
| }; |
| - chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => |
| + browser.tabs.onUpdated.addListener((tabId, changeInfo, tab) => |
| { |
| if (changeInfo.status == "loading") |
| ext.pages.onLoading._dispatch(new Page(tab)); |
| }); |
| function createFrame(tabId, frameId) |
| { |
| let frames = framesOfTabs.get(tabId); |
| @@ -154,39 +154,39 @@ |
| function updatePageFrameStructure(frameId, tabId, url, parentFrameId) |
| { |
| if (frameId == 0) |
| { |
| let page = new Page({id: tabId, url}); |
| ext._removeFromAllPageMaps(tabId); |
| - chrome.tabs.get(tabId, () => |
| + browser.tabs.get(tabId, () => |
| { |
| - // If the tab is prerendered, chrome.tabs.get() sets |
| - // chrome.runtime.lastError and we have to dispatch the onLoading event, |
| - // since the onUpdated event isn't dispatched for prerendered tabs. |
| - // However, we have to keep relying on the unUpdated event for tabs that |
| - // are already visible. Otherwise browser action changes get overridden |
| - // when Chrome automatically resets them on navigation. |
| - if (chrome.runtime.lastError) |
| + // If the tab is prerendered, browser.tabs.get() sets |
| + // browser.runtime.lastError and we have to dispatch the onLoading |
| + // event, since the onUpdated event isn't dispatched for prerendered |
| + // tabs. However, we have to keep relying on the onUpdated event for |
| + // tabs that are already visible. Otherwise browser action changes get |
| + // overridden when Chrome automatically resets them on navigation. |
| + if (browser.runtime.lastError) |
| ext.pages.onLoading._dispatch(page); |
| }); |
| } |
| // Update frame URL and parent in frame structure |
| let frame = createFrame(tabId, frameId); |
| frame.url = new URL(url); |
| let parentFrame = framesOfTabs.get(tabId).get(parentFrameId); |
| if (parentFrame) |
| frame.parent = parentFrame; |
| } |
| - chrome.webRequest.onHeadersReceived.addListener(details => |
| + browser.webRequest.onHeadersReceived.addListener(details => |
| { |
| // We have to update the frame structure when switching to a new |
| // document, so that we process any further requests made by that |
| // document in the right context. Unfortunately, we cannot rely |
| // on webNavigation.onCommitted since it isn't guaranteed to fire |
| // before any subresources start downloading[1]. As an |
| // alternative we use webRequest.onHeadersReceived for HTTP(S) |
| // URLs, being careful to ignore any responses that won't cause |
| @@ -254,17 +254,17 @@ |
| } |
| updatePageFrameStructure(details.frameId, details.tabId, details.url, |
| details.parentFrameId); |
| }, |
| {types: ["main_frame", "sub_frame"], urls: ["http://*/*", "https://*/*"]}, |
| ["responseHeaders"]); |
| - chrome.webNavigation.onBeforeNavigate.addListener(details => |
| + browser.webNavigation.onBeforeNavigate.addListener(details => |
| { |
| // Since we can only listen for HTTP(S) responses using |
| // webRequest.onHeadersReceived we must update the page structure here for |
| // other navigations. |
| let url = new URL(details.url); |
| if (url.protocol != "http:" && url.protocol != "https:") |
| { |
| updatePageFrameStructure(details.frameId, details.tabId, details.url, |
| @@ -275,24 +275,24 @@ |
| function forgetTab(tabId) |
| { |
| ext.pages.onRemoved._dispatch(tabId); |
| ext._removeFromAllPageMaps(tabId); |
| framesOfTabs.delete(tabId); |
| } |
| - chrome.tabs.onReplaced.addListener((addedTabId, removedTabId) => |
| + browser.tabs.onReplaced.addListener((addedTabId, removedTabId) => |
| { |
| forgetTab(removedTabId); |
| }); |
| - chrome.tabs.onRemoved.addListener(forgetTab); |
| + browser.tabs.onRemoved.addListener(forgetTab); |
| - chrome.tabs.onActivated.addListener(details => |
| + browser.tabs.onActivated.addListener(details => |
| { |
| ext.pages.onActivated._dispatch(new Page({id: details.tabId})); |
| }); |
| /* Browser actions */ |
| let BrowserAction = function(tabId) |
| @@ -304,87 +304,87 @@ |
| _applyChanges() |
| { |
| if ("iconPath" in this._changes) |
| { |
| // Firefox for Android displays the browser action not as an icon but |
| // as a menu item. There is no icon, but such an option may be added in |
| // the future. |
| // https://bugzilla.mozilla.org/show_bug.cgi?id=1331746 |
| - if ("setIcon" in chrome.browserAction) |
| + if ("setIcon" in browser.browserAction) |
| { |
| let path = { |
| 16: this._changes.iconPath.replace("$size", "16"), |
| 19: this._changes.iconPath.replace("$size", "19"), |
| 20: this._changes.iconPath.replace("$size", "20"), |
| 32: this._changes.iconPath.replace("$size", "32"), |
| 38: this._changes.iconPath.replace("$size", "38"), |
| 40: this._changes.iconPath.replace("$size", "40") |
| }; |
| try |
| { |
| - chrome.browserAction.setIcon({tabId: this._tabId, path}); |
| + browser.browserAction.setIcon({tabId: this._tabId, path}); |
| } |
| catch (e) |
| { |
| // Edge throws if passed icon sizes different than 19,20,38,40px. |
| delete path[16]; |
| delete path[32]; |
| - chrome.browserAction.setIcon({tabId: this._tabId, path}); |
| + browser.browserAction.setIcon({tabId: this._tabId, path}); |
| } |
| } |
| } |
| if ("badgeText" in this._changes) |
| { |
| // There is no badge on Firefox for Android; the browser action is |
| // simply a menu item. |
| - if ("setBadgeText" in chrome.browserAction) |
| + if ("setBadgeText" in browser.browserAction) |
| { |
| - chrome.browserAction.setBadgeText({ |
| + browser.browserAction.setBadgeText({ |
| tabId: this._tabId, |
| text: this._changes.badgeText |
| }); |
| } |
| } |
| if ("badgeColor" in this._changes) |
| { |
| // There is no badge on Firefox for Android; the browser action is |
| // simply a menu item. |
| - if ("setBadgeBackgroundColor" in chrome.browserAction) |
| + if ("setBadgeBackgroundColor" in browser.browserAction) |
| { |
| - chrome.browserAction.setBadgeBackgroundColor({ |
| + browser.browserAction.setBadgeBackgroundColor({ |
| tabId: this._tabId, |
| color: this._changes.badgeColor |
| }); |
| } |
| } |
| this._changes = null; |
| }, |
| _queueChanges() |
| { |
| - chrome.tabs.get(this._tabId, () => |
| + browser.tabs.get(this._tabId, () => |
| { |
| - // If the tab is prerendered, chrome.tabs.get() sets |
| - // chrome.runtime.lastError and we have to delay our changes |
| + // If the tab is prerendered, browser.tabs.get() sets |
| + // browser.runtime.lastError and we have to delay our changes |
| // until the currently visible tab is replaced with the |
| - // prerendered tab. Otherwise chrome.browserAction.set* fails. |
| - if (chrome.runtime.lastError) |
| + // prerendered tab. Otherwise browser.browserAction.set* fails. |
| + if (browser.runtime.lastError) |
| { |
| let onReplaced = (addedTabId, removedTabId) => |
| { |
| if (addedTabId == this._tabId) |
| { |
| - chrome.tabs.onReplaced.removeListener(onReplaced); |
| + browser.tabs.onReplaced.removeListener(onReplaced); |
| this._applyChanges(); |
| } |
| }; |
| - chrome.tabs.onReplaced.addListener(onReplaced); |
| + browser.tabs.onReplaced.addListener(onReplaced); |
| } |
| else |
| { |
| this._applyChanges(); |
| } |
| }); |
| }, |
| _addChange(name, value) |
| @@ -423,38 +423,38 @@ |
| let contextMenuItems = new ext.PageMap(); |
| let contextMenuUpdating = false; |
| let updateContextMenu = () => |
| { |
| // Firefox for Android does not support context menus. |
| // https://bugzilla.mozilla.org/show_bug.cgi?id=1269062 |
| - if (!("contextMenus" in chrome) || contextMenuUpdating) |
| + if (!("contextMenus" in browser) || contextMenuUpdating) |
| return; |
| contextMenuUpdating = true; |
| - chrome.tabs.query({active: true, lastFocusedWindow: true}, tabs => |
| + browser.tabs.query({active: true, lastFocusedWindow: true}, tabs => |
| { |
| - chrome.contextMenus.removeAll(() => |
| + browser.contextMenus.removeAll(() => |
| { |
| contextMenuUpdating = false; |
| if (tabs.length == 0) |
| return; |
| let items = contextMenuItems.get({id: tabs[0].id}); |
| if (!items) |
| return; |
| items.forEach(item => |
| { |
| - chrome.contextMenus.create({ |
| + browser.contextMenus.create({ |
| title: item.title, |
| contexts: item.contexts, |
| onclick(info, tab) |
| { |
| item.onclick(new Page(tab)); |
| } |
| }); |
| }); |
| @@ -486,77 +486,77 @@ |
| { |
| items.splice(index, 1); |
| updateContextMenu(); |
| } |
| } |
| } |
| }; |
| - chrome.tabs.onActivated.addListener(updateContextMenu); |
| + browser.tabs.onActivated.addListener(updateContextMenu); |
| - if ("windows" in chrome) |
| + if ("windows" in browser) |
| { |
| - chrome.windows.onFocusChanged.addListener(windowId => |
| + browser.windows.onFocusChanged.addListener(windowId => |
| { |
| - if (windowId != chrome.windows.WINDOW_ID_NONE) |
| + if (windowId != browser.windows.WINDOW_ID_NONE) |
| updateContextMenu(); |
| }); |
| } |
| /* Web requests */ |
| let framesOfTabs = new Map(); |
| ext.getFrame = (tabId, frameId) => |
| { |
| let frames = framesOfTabs.get(tabId); |
| return frames && frames.get(frameId); |
| }; |
| let handlerBehaviorChangedQuota = |
| - chrome.webRequest.MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES; |
| + browser.webRequest.MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES; |
| function propagateHandlerBehaviorChange() |
| { |
| // Make sure to not call handlerBehaviorChanged() more often than allowed |
| - // by chrome.webRequest.MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES. |
| + // by browser.webRequest.MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES. |
| // Otherwise Chrome notifies the user that this extension is causing issues. |
| if (handlerBehaviorChangedQuota > 0) |
| { |
| - chrome.webNavigation.onBeforeNavigate.removeListener( |
| + browser.webNavigation.onBeforeNavigate.removeListener( |
| propagateHandlerBehaviorChange |
| ); |
| - chrome.webRequest.handlerBehaviorChanged(); |
| + browser.webRequest.handlerBehaviorChanged(); |
| handlerBehaviorChangedQuota--; |
| setTimeout(() => { handlerBehaviorChangedQuota++; }, 600000); |
| } |
| } |
| ext.webRequest = { |
| onBeforeRequest: new ext._EventTarget(), |
| handlerBehaviorChanged() |
| { |
| // Defer handlerBehaviorChanged() until navigation occurs. |
| // There wouldn't be any visible effect when calling it earlier, |
| // but it's an expensive operation and that way we avoid to call |
| // it multiple times, if multiple filters are added/removed. |
| - let {onBeforeNavigate} = chrome.webNavigation; |
| + let {onBeforeNavigate} = browser.webNavigation; |
| if (!onBeforeNavigate.hasListener(propagateHandlerBehaviorChange)) |
| onBeforeNavigate.addListener(propagateHandlerBehaviorChange); |
| } |
| }; |
| - chrome.tabs.query({}, tabs => |
| + browser.tabs.query({}, tabs => |
| { |
| tabs.forEach(tab => |
| { |
| - chrome.webNavigation.getAllFrames({tabId: tab.id}, details => |
| + browser.webNavigation.getAllFrames({tabId: tab.id}, details => |
| { |
| if (details && details.length > 0) |
| { |
| let frames = new Map(); |
| framesOfTabs.set(tab.id, frames); |
| for (let detail of details) |
| { |
| @@ -566,17 +566,17 @@ |
| if (detail.parentFrameId != -1) |
| frame.parent = frames.get(detail.parentFrameId); |
| } |
| } |
| }); |
| }); |
| }); |
| - chrome.webRequest.onBeforeRequest.addListener(details => |
| + browser.webRequest.onBeforeRequest.addListener(details => |
| { |
| // The high-level code isn't interested in requests that aren't |
| // related to a tab or requests loading a top-level document, |
| // those should never be blocked. |
| if (details.type == "main_frame") |
| return; |
| // Filter out requests from non web protocols. Ideally, we'd explicitly |
| @@ -610,17 +610,17 @@ |
| if (ext.webRequest.onBeforeRequest._dispatch( |
| url, type, page, frame).includes(false)) |
| return {cancel: true}; |
| }, {urls: ["<all_urls>"]}, ["blocking"]); |
| /* Message passing */ |
| - chrome.runtime.onMessage.addListener((message, rawSender, sendResponse) => |
| + browser.runtime.onMessage.addListener((message, rawSender, sendResponse) => |
| { |
| let sender = {}; |
| // Add "page" and "frame" if the message was sent by a content script. |
| // If sent by popup or the background page itself, there is no "tab". |
| if ("tab" in rawSender) |
| { |
| sender.page = new Page(rawSender.tab); |
| @@ -651,34 +651,34 @@ |
| }); |
| /* Storage */ |
| ext.storage = { |
| get(keys, callback) |
| { |
| - chrome.storage.local.get(keys, callback); |
| + browser.storage.local.get(keys, callback); |
| }, |
| set(key, value, callback) |
| { |
| let items = {}; |
| items[key] = value; |
| - chrome.storage.local.set(items, callback); |
| + browser.storage.local.set(items, callback); |
| }, |
| remove(key, callback) |
| { |
| - chrome.storage.local.remove(key, callback); |
| + browser.storage.local.remove(key, callback); |
| }, |
| - onChanged: chrome.storage.onChanged |
| + onChanged: browser.storage.onChanged |
| }; |
| /* Windows */ |
| ext.windows = { |
| create(createData, callback) |
| { |
| - chrome.windows.create(createData, createdWindow => |
| + browser.windows.create(createData, createdWindow => |
| { |
| afterTabLoaded(callback)(createdWindow.tabs[0]); |
| }); |
| } |
| }; |
| }()); |