Index: chrome/ext/background.js
diff --git a/chrome/ext/background.js b/chrome/ext/background.js
index 87a044d3a62c4502066eb47e03fa08109ab21c4f..8cec8296408b0cafb5452c7eb0afb6e67d59035b 100644
--- a/chrome/ext/background.js
+++ b/chrome/ext/background.js
@@ -15,11 +15,12 @@
  * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-(function()
+"use strict";
+
 {
   /* Pages */
 
-  var Page = ext.Page = function(tab)
+  let Page = ext.Page = function(tab)
   {
     this.id = tab.id;
     this._url = tab.url && new URL(tab.url);
@@ -38,30 +39,27 @@
       // 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.
-      var frames = framesOfTabs[this.id];
+      let frames = framesOfTabs[this.id];
       if (frames)
       {
-        var frame = frames[0];
+        let frame = frames[0];
         if (frame)
           return frame.url;
       }
     },
-    sendMessage: function(message, responseCallback)
+    sendMessage(message, responseCallback)
     {
       chrome.tabs.sendMessage(this.id, message, responseCallback);
     }
   };
 
-  ext.getPage = function(id)
-  {
-    return new Page({id: parseInt(id, 10)});
-  };
+  ext.getPage = id => new Page({id: parseInt(id, 10)});
 
   function afterTabLoaded(callback)
   {
-     return function(openedTab)
+     return openedTab =>
      {
-       var onUpdated = function(tabId, changeInfo, tab)
+       let onUpdated = (tabId, changeInfo, tab) =>
        {
          if (tabId == openedTab.id && changeInfo.status == "complete")
          {
@@ -74,14 +72,14 @@
   }
 
   ext.pages = {
-    open: function(url, callback)
+    open(url, callback)
     {
       chrome.tabs.create({url: url}, callback && afterTabLoaded(callback));
     },
-    query: function(info, callback)
+    query(info, callback)
     {
-      var rawInfo = {};
-      for (var property in info)
+      let rawInfo = {};
+      for (let property in info)
       {
         switch (property)
         {
@@ -91,12 +89,9 @@
         }
       }
 
-      chrome.tabs.query(rawInfo, function(tabs)
+      chrome.tabs.query(rawInfo, tabs =>
       {
-        callback(tabs.map(function(tab)
-        {
-          return new Page(tab);
-        }));
+        callback(tabs.map(tab => new Page(tab)));
       });
     },
     onLoading: new ext._EventTarget(),
@@ -104,7 +99,7 @@
     onRemoved: new ext._EventTarget()
   };
 
-  chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab)
+  chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) =>
   {
     if (changeInfo.status == "loading")
       ext.pages.onLoading._dispatch(new Page(tab));
@@ -112,27 +107,27 @@
 
   function createFrame(tabId, frameId)
   {
-    var frames = framesOfTabs[tabId];
+    let frames = framesOfTabs[tabId];
     if (!frames)
       frames = framesOfTabs[tabId] = Object.create(null);
 
-    var frame = frames[frameId];
+    let frame = frames[frameId];
     if (!frame)
       frame = frames[frameId] = {};
 
     return frame;
   }
 
-  chrome.webNavigation.onBeforeNavigate.addListener(function(details)
+  chrome.webNavigation.onBeforeNavigate.addListener(details =>
   {
     // Capture parent frame here because onCommitted doesn't get this info.
-    var frame = createFrame(details.tabId, details.frameId);
+    let frame = createFrame(details.tabId, details.frameId);
     frame.parent = framesOfTabs[details.tabId][details.parentFrameId] || null;
   });
 
-  var eagerlyUpdatedPages = new ext.PageMap();
+  let eagerlyUpdatedPages = new ext.PageMap();
 
-  ext._updatePageFrameStructure = function(frameId, tabId, url, eager)
+  ext._updatePageFrameStructure = (frameId, tabId, url, eager) =>
   {
     if (frameId == 0)
     {
@@ -149,7 +144,7 @@
         if (eager)
           eagerlyUpdatedPages.set(page, url);
 
-        chrome.tabs.get(tabId, function()
+        chrome.tabs.get(tabId, () =>
         {
           // If the tab is prerendered, chrome.tabs.get() sets
           // chrome.runtime.lastError and we have to dispatch the onLoading event,
@@ -164,11 +159,11 @@
     }
 
     // Update frame URL in frame structure
-    var frame = createFrame(tabId, frameId);
+    let frame = createFrame(tabId, frameId);
     frame.url = new URL(url);
   };
 
-  chrome.webNavigation.onCommitted.addListener(function(details)
+  chrome.webNavigation.onCommitted.addListener(details =>
   {
     ext._updatePageFrameStructure(details.frameId, details.tabId, details.url);
   });
@@ -181,14 +176,14 @@
     delete framesOfTabs[tabId];
   }
 
-  chrome.tabs.onReplaced.addListener(function(addedTabId, removedTabId)
+  chrome.tabs.onReplaced.addListener((addedTabId, removedTabId) =>
   {
     forgetTab(removedTabId);
   });
 
   chrome.tabs.onRemoved.addListener(forgetTab);
 
-  chrome.tabs.onActivated.addListener(function(details)
+  chrome.tabs.onActivated.addListener(details =>
   {
     ext.pages.onActivated._dispatch(new Page({id: details.tabId}));
   });
@@ -196,13 +191,13 @@
 
   /* Browser actions */
 
-  var BrowserAction = function(tabId)
+  let BrowserAction = function(tabId)
   {
     this._tabId = tabId;
     this._changes = null;
   };
   BrowserAction.prototype = {
-    _applyChanges: function()
+    _applyChanges()
     {
       if ("iconPath" in this._changes)
       {
@@ -237,7 +232,7 @@
 
       this._changes = null;
     },
-    _queueChanges: function()
+    _queueChanges()
     {
       chrome.tabs.get(this._tabId, function()
       {
@@ -247,14 +242,14 @@
         // prerendered tab. Otherwise chrome.browserAction.set* fails.
         if (chrome.runtime.lastError)
         {
-          var onReplaced = function(addedTabId, removedTabId)
+          let onReplaced = (addedTabId, removedTabId) =>
           {
             if (addedTabId == this._tabId)
             {
               chrome.tabs.onReplaced.removeListener(onReplaced);
               this._applyChanges();
             }
-          }.bind(this);
+          };
           chrome.tabs.onReplaced.addListener(onReplaced);
         }
         else
@@ -263,7 +258,7 @@
         }
       }.bind(this));
     },
-    _addChange: function(name, value)
+    _addChange(name, value)
     {
       if (!this._changes)
       {
@@ -273,11 +268,11 @@
 
       this._changes[name] = value;
     },
-    setIcon: function(path)
+    setIcon(path)
     {
       this._addChange("iconPath", path);
     },
-    setBadge: function(badge)
+    setBadge(badge)
     {
       if (!badge)
       {
@@ -297,36 +292,36 @@
 
   /* Context menus */
 
-  var contextMenuItems = new ext.PageMap();
-  var contextMenuUpdating = false;
+  let contextMenuItems = new ext.PageMap();
+  let contextMenuUpdating = false;
 
-  var updateContextMenu = function()
+  let updateContextMenu = () =>
   {
     if (contextMenuUpdating)
       return;
 
     contextMenuUpdating = true;
 
-    chrome.tabs.query({active: true, lastFocusedWindow: true}, function(tabs)
+    chrome.tabs.query({active: true, lastFocusedWindow: true}, tabs =>
     {
-      chrome.contextMenus.removeAll(function()
+      chrome.contextMenus.removeAll(() =>
       {
         contextMenuUpdating = false;
 
         if (tabs.length == 0)
           return;
 
-        var items = contextMenuItems.get({id: tabs[0].id});
+        let items = contextMenuItems.get({id: tabs[0].id});
 
         if (!items)
           return;
 
-        items.forEach(function(item)
+        items.forEach(item =>
         {
           chrome.contextMenus.create({
             title: item.title,
             contexts: item.contexts,
-            onclick: function(info, tab)
+            onclick(info, tab)
             {
               item.onclick(new Page(tab));
             }
@@ -336,21 +331,21 @@
     });
   };
 
-  var ContextMenus = function(page)
+  let ContextMenus = function(page)
   {
     this._page = page;
   };
   ContextMenus.prototype = {
-    create: function(item)
+    create(item)
     {
-      var items = contextMenuItems.get(this._page);
+      let items = contextMenuItems.get(this._page);
       if (!items)
         contextMenuItems.set(this._page, items = []);
 
       items.push(item);
       updateContextMenu();
     },
-    remove: function(item)
+    remove(item)
     {
       let items = contextMenuItems.get(this._page);
       if (items)
@@ -367,7 +362,7 @@
 
   chrome.tabs.onActivated.addListener(updateContextMenu);
 
-  chrome.windows.onFocusChanged.addListener(function(windowId)
+  chrome.windows.onFocusChanged.addListener(windowId =>
   {
     if (windowId != chrome.windows.WINDOW_ID_NONE)
       updateContextMenu();
@@ -376,14 +371,14 @@
 
   /* Web requests */
 
-  var framesOfTabs = Object.create(null);
+  let framesOfTabs = Object.create(null);
 
-  ext.getFrame = function(tabId, frameId)
+  ext.getFrame = (tabId, frameId) =>
   {
     return (framesOfTabs[tabId] || {})[frameId];
   };
 
-  var handlerBehaviorChangedQuota = chrome.webRequest.MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES;
+  let handlerBehaviorChangedQuota = chrome.webRequest.MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES;
 
   function propagateHandlerBehaviorChange()
   {
@@ -396,40 +391,40 @@
       chrome.webRequest.handlerBehaviorChanged();
 
       handlerBehaviorChangedQuota--;
-      setTimeout(function() { handlerBehaviorChangedQuota++; }, 600000);
+      setTimeout(() => { handlerBehaviorChangedQuota++; }, 600000);
     }
   }
 
   ext.webRequest = {
     onBeforeRequest: new ext._EventTarget(),
-    handlerBehaviorChanged: function()
+    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.
-      var onBeforeNavigate = chrome.webNavigation.onBeforeNavigate;
+      let onBeforeNavigate = chrome.webNavigation.onBeforeNavigate;
       if (!onBeforeNavigate.hasListener(propagateHandlerBehaviorChange))
         onBeforeNavigate.addListener(propagateHandlerBehaviorChange);
     }
   };
 
-  chrome.tabs.query({}, function(tabs)
+  chrome.tabs.query({}, tabs =>
   {
-    tabs.forEach(function(tab)
+    tabs.forEach(tab =>
     {
-      chrome.webNavigation.getAllFrames({tabId: tab.id}, function(details)
+      chrome.webNavigation.getAllFrames({tabId: tab.id}, details =>
       {
         if (details && details.length > 0)
         {
-          var frames = framesOfTabs[tab.id] = Object.create(null);
+          let frames = framesOfTabs[tab.id] = Object.create(null);
 
-          for (var i = 0; i < details.length; i++)
+          for (let i = 0; i < details.length; i++)
             frames[details[i].frameId] = {url: new URL(details[i].url), parent: null};
 
-          for (var i = 0; i < details.length; i++)
+          for (let i = 0; i < details.length; i++)
           {
-            var parentFrameId = details[i].parentFrameId;
+            let parentFrameId = details[i].parentFrameId;
 
             if (parentFrameId != -1)
               frames[details[i].frameId].parent = frames[parentFrameId];
@@ -439,7 +434,7 @@
     });
   });
 
-  chrome.webRequest.onBeforeRequest.addListener(function(details)
+  chrome.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,
@@ -451,8 +446,8 @@
     // has triggered this request. For most requests (e.g. images) we
     // can just use the request's frame ID, but for subdocument requests
     // (e.g. iframes) we must instead use the request's parent frame ID.
-    var frameId;
-    var requestType;
+    let frameId;
+    let requestType;
     if (details.type == "sub_frame")
     {
       frameId = details.parentFrameId;
@@ -464,10 +459,10 @@
       requestType = details.type.toUpperCase();
     }
 
-    var frame = ext.getFrame(details.tabId, frameId);
+    let frame = ext.getFrame(details.tabId, frameId);
     if (frame)
     {
-      var results = ext.webRequest.onBeforeRequest._dispatch(
+      let results = ext.webRequest.onBeforeRequest._dispatch(
         new URL(details.url),
         requestType,
         new Page({id: details.tabId}),
@@ -482,9 +477,9 @@
 
   /* Message passing */
 
-  chrome.runtime.onMessage.addListener(function(message, rawSender, sendResponse)
+  chrome.runtime.onMessage.addListener((message, rawSender, sendResponse) =>
   {
-    var sender = {};
+    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".
@@ -495,12 +490,12 @@
         url: new URL(rawSender.url),
         get parent()
         {
-          var frames = framesOfTabs[rawSender.tab.id];
+          let frames = framesOfTabs[rawSender.tab.id];
 
           if (!frames)
             return null;
 
-          var frame = frames[rawSender.frameId];
+          let frame = frames[rawSender.frameId];
           if (frame)
             return frame.parent;
 
@@ -516,17 +511,17 @@
   /* Storage */
 
   ext.storage = {
-    get: function(keys, callback)
+    get(keys, callback)
     {
       chrome.storage.local.get(keys, callback);
     },
-    set: function(key, value, callback)
+    set(key, value, callback)
     {
       let items = {};
       items[key] = value;
       chrome.storage.local.set(items, callback);
     },
-    remove: function(key, callback)
+    remove(key, callback)
     {
       chrome.storage.local.remove(key, callback);
     },
@@ -537,7 +532,7 @@
 
   if ("openOptionsPage" in chrome.runtime)
   {
-    ext.showOptions = function(callback)
+    ext.showOptions = callback =>
     {
       if (!callback)
       {
@@ -568,12 +563,12 @@
   {
     // Edge does not yet support runtime.openOptionsPage (tested version 38)
     // and so this workaround needs to stay for now.
-    ext.showOptions = function(callback)
+    ext.showOptions = callback =>
     {
-      chrome.windows.getLastFocused(function(win)
+      chrome.windows.getLastFocused(win =>
       {
-        var optionsUrl = chrome.extension.getURL("options.html");
-        var queryInfo = {url: optionsUrl};
+        let optionsUrl = chrome.extension.getURL("options.html");
+        let queryInfo = {url: optionsUrl};
 
         // extension pages can't be accessed in incognito windows. In order to
         // correctly mimic the way in which Chrome opens extension options,
@@ -581,11 +576,11 @@
         if (!win.incognito)
           queryInfo.windowId = win.id;
 
-        chrome.tabs.query(queryInfo, function(tabs)
+        chrome.tabs.query(queryInfo, tabs =>
         {
           if (tabs.length > 0)
           {
-            var tab = tabs[0];
+            let tab = tabs[0];
 
             chrome.windows.update(tab.windowId, {focused: true});
             chrome.tabs.update(tab.id, {active: true});
@@ -604,12 +599,12 @@
 
   /* Windows */
   ext.windows = {
-    create: function(createData, callback)
+    create(createData, callback)
     {
-      chrome.windows.create(createData, function(createdWindow)
+      chrome.windows.create(createData, createdWindow =>
       {
         afterTabLoaded(callback)(createdWindow.tabs[0]);
       });
     }
   };
-})();
+}
