Index: ext/background.js |
=================================================================== |
--- a/ext/background.js |
+++ b/ext/background.js |
@@ -14,64 +14,67 @@ |
* You should have received a copy of the GNU General Public License |
* along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. |
*/ |
"use strict"; |
(function() |
{ |
- let nonEmptyPageMaps = Object.create(null); |
- let pageMapCounter = 0; |
+ let nonEmptyPageMaps = new Set(); |
let PageMap = ext.PageMap = function() |
{ |
- this._map = Object.create(null); |
- this._id = ++pageMapCounter; |
+ this._map = new Map(); |
}; |
PageMap.prototype = { |
_delete(id) |
{ |
- delete this._map[id]; |
- |
- if (Object.keys(this._map).length == 0) |
- delete nonEmptyPageMaps[this._id]; |
+ if (this._map.delete(id) && this._map.size == 0) |
+ nonEmptyPageMaps.delete(this); |
}, |
keys() |
{ |
- return Object.keys(this._map).map(ext.getPage); |
+ return this._map.keys(); |
}, |
get(page) |
{ |
- return this._map[page.id]; |
+ return this._map.get(page.id); |
}, |
set(page, value) |
{ |
- this._map[page.id] = value; |
- nonEmptyPageMaps[this._id] = this; |
+ let prevSize = this._map.size; |
+ |
+ this._map.set(page.id, value); |
+ |
+ if (prevSize == 0) |
+ nonEmptyPageMaps.add(this); |
}, |
has(page) |
{ |
- return page.id in this._map; |
+ return this._map.has(page.id); |
}, |
clear() |
{ |
- for (let id in this._map) |
- this._delete(id); |
+ if (this._map.size == 0) |
+ return; |
+ |
+ this._map.clear(); |
+ nonEmptyPageMaps.delete(this); |
}, |
delete(page) |
{ |
this._delete(page.id); |
} |
}; |
ext._removeFromAllPageMaps = pageId => |
{ |
- for (let pageMapId in nonEmptyPageMaps) |
- nonEmptyPageMaps[pageMapId]._delete(pageId); |
+ for (let pageMap of nonEmptyPageMaps) |
+ pageMap._delete(pageId); |
}; |
/* Pages */ |
let Page = ext.Page = function(tab) |
{ |
this.id = tab.id; |
this._url = tab.url && new URL(tab.url); |
@@ -85,20 +88,20 @@ |
// usually our Page objects are created from Chrome's Tab objects, which |
// provide the url. So we can return the url given in the constructor. |
if (this._url) |
return this._url; |
// but sometimes we only have the tab id when we create a Page object. |
// In that case we get the url from top frame of the tab, recorded by |
// the onBeforeRequest handler. |
- let frames = framesOfTabs[this.id]; |
+ let frames = framesOfTabs.get(this.id); |
if (frames) |
{ |
- let frame = frames[0]; |
+ let frame = frames.get(0); |
if (frame) |
return frame.url; |
} |
}, |
sendMessage(message, responseCallback) |
{ |
chrome.tabs.sendMessage(this.id, message, responseCallback); |
} |
@@ -153,23 +156,29 @@ |
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => |
{ |
if (changeInfo.status == "loading") |
ext.pages.onLoading._dispatch(new Page(tab)); |
}); |
function createFrame(tabId, frameId) |
{ |
- let frames = framesOfTabs[tabId]; |
+ let frames = framesOfTabs.get(tabId); |
if (!frames) |
- frames = framesOfTabs[tabId] = Object.create(null); |
+ { |
+ frames = new Map(); |
+ framesOfTabs.set(tabId, frames); |
+ } |
- let frame = frames[frameId]; |
+ let frame = frames.get(frameId); |
if (!frame) |
- frame = frames[frameId] = {}; |
+ { |
+ frame = {}; |
+ frames.set(frameId, frame); |
+ } |
return frame; |
} |
function updatePageFrameStructure(frameId, tabId, url, parentFrameId) |
{ |
if (frameId == 0) |
{ |
@@ -185,20 +194,23 @@ |
// 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) |
ext.pages.onLoading._dispatch(page); |
}); |
} |
- // Update frame parent and URL in frame structure |
+ // Update frame URL and parent in frame structure |
let frame = createFrame(tabId, frameId); |
frame.url = new URL(url); |
- frame.parent = framesOfTabs[tabId][parentFrameId] || null; |
+ |
+ let parentFrame = framesOfTabs.get(tabId).get(parentFrameId); |
+ if (parentFrame) |
+ frame.parent = parentFrame; |
} |
chrome.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 |
@@ -287,17 +299,17 @@ |
} |
}); |
function forgetTab(tabId) |
{ |
ext.pages.onRemoved._dispatch(tabId); |
ext._removeFromAllPageMaps(tabId); |
- delete framesOfTabs[tabId]; |
+ framesOfTabs.delete(tabId); |
} |
chrome.tabs.onReplaced.addListener((addedTabId, removedTabId) => |
{ |
forgetTab(removedTabId); |
}); |
chrome.tabs.onRemoved.addListener(forgetTab); |
@@ -485,21 +497,22 @@ |
{ |
if (windowId != chrome.windows.WINDOW_ID_NONE) |
updateContextMenu(); |
}); |
/* Web requests */ |
- let framesOfTabs = Object.create(null); |
+ let framesOfTabs = new Map(); |
ext.getFrame = (tabId, frameId) => |
{ |
- return (framesOfTabs[tabId] || {})[frameId]; |
+ let frames = framesOfTabs.get(tabId); |
+ return frames && frames.get(frameId); |
}; |
let handlerBehaviorChangedQuota = |
chrome.webRequest.MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES; |
function propagateHandlerBehaviorChange() |
{ |
// Make sure to not call handlerBehaviorChanged() more often than allowed |
@@ -534,32 +547,28 @@ |
chrome.tabs.query({}, tabs => |
{ |
tabs.forEach(tab => |
{ |
chrome.webNavigation.getAllFrames({tabId: tab.id}, details => |
{ |
if (details && details.length > 0) |
{ |
- let frames = framesOfTabs[tab.id] = Object.create(null); |
+ let frames = new Map(); |
+ framesOfTabs.set(tab.id, frames); |
- for (let i = 0; i < details.length; i++) |
+ for (let detail of details) |
+ frames.set(detail.frameId, {url: new URL(detail.url)}); |
+ |
+ for (let detail of details) |
{ |
- frames[details[i].frameId] = { |
- url: new URL(details[i].url), |
- parent: null |
- }; |
- } |
- |
- for (let i = 0; i < details.length; i++) |
- { |
- let {parentFrameId} = details[i]; |
+ let {parentFrameId} = detail; |
if (parentFrameId != -1) |
- frames[details[i].frameId].parent = frames[parentFrameId]; |
+ frames.get(detail.frameId).parent = frames.get(parentFrameId); |
} |
} |
}); |
}); |
}); |
chrome.webRequest.onBeforeRequest.addListener(details => |
{ |
@@ -606,26 +615,26 @@ |
// If sent by popup or the background page itself, there is no "tab". |
if ("tab" in rawSender) |
{ |
sender.page = new Page(rawSender.tab); |
sender.frame = { |
url: new URL(rawSender.url), |
get parent() |
{ |
- let frames = framesOfTabs[rawSender.tab.id]; |
+ let frames = framesOfTabs.get(rawSender.tab.id); |
if (!frames) |
return null; |
- let frame = frames[rawSender.frameId]; |
+ let frame = frames.get(rawSender.frameId); |
if (frame) |
- return frame.parent; |
+ return frame.parent || null; |
- return frames[0]; |
+ return frames.get(0) || null; |
} |
}; |
} |
return ext.onMessage._dispatch( |
message, sender, sendResponse |
).indexOf(true) != -1; |
}); |