diff --git a/browser/base/content/remote-newtab/newTab.css b/browser/base/content/remote-newtab/newTab.css
deleted file mode 100644
index 303cafddc5e2..000000000000
--- a/browser/base/content/remote-newtab/newTab.css
+++ /dev/null
@@ -1,23 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-html {
- width: 100%;
- height: 100%;
-}
-
-body {
- width: 100%;
- height: 100%;
- padding: 0;
- margin: 0;
- position: relative;
-}
-
-#remotedoc {
- width: 100%;
- height: 100%;
- border: none;
- position: absolute;
-}
diff --git a/browser/base/content/remote-newtab/newTab.js b/browser/base/content/remote-newtab/newTab.js
deleted file mode 100644
index 920830c96767..000000000000
--- a/browser/base/content/remote-newtab/newTab.js
+++ /dev/null
@@ -1,126 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-/*globals XPCOMUtils, Components, sendAsyncMessage, addMessageListener, removeMessageListener,
- Services, PrivateBrowsingUtils*/
-"use strict";
-
-const {utils: Cu, interfaces: Ci} = Components;
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
- "resource://gre/modules/PrivateBrowsingUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Services",
- "resource://gre/modules/Services.jsm");
-
-(function() {
- let remoteNewTabLocation;
- let remoteIFrame;
-
- /**
- * Attempts to handle commands sent from the remote IFrame within this content frame.
- * Expected commands below, with data types explained.
- *
- * @returns {Boolean} whether or not the command was handled
- * @param {String} command
- * The command passed from the remote IFrame
- * @param {Object} data
- * Parameters to the command
- */
- function handleCommand(command, data) {
- let commandHandled = true;
- switch (command) {
- case "NewTab:UpdateTelemetryProbe":
- /**
- * Update a given Telemetry histogram
- *
- * @param {String} data.probe
- * Probe name to update
- * @param {Number} data.value
- * Value to update histogram by
- */
- Services.telemetry.getHistogramById(data.probe).add(data.value);
- break;
- case "NewTab:Register":
- registerEvent(data.type);
- break;
- case "NewTab:GetInitialState":
- getInitialState();
- break;
- default:
- commandHandled = false;
- }
- return commandHandled;
- }
-
- function initRemotePage(initData) {
- // Messages that the iframe sends the browser will be passed onto
- // the privileged parent process
- remoteNewTabLocation = initData;
- remoteIFrame = document.querySelector("#remotedoc");
-
- let loadHandler = () => {
- if (remoteIFrame.src !== remoteNewTabLocation.href) {
- return;
- }
-
- remoteIFrame.removeEventListener("load", loadHandler);
-
- remoteIFrame.contentDocument.addEventListener("NewTabCommand", (e) => {
- // If the commands are not handled within this content frame, the command will be
- // passed on to main process, in RemoteAboutNewTab.jsm
- let handled = handleCommand(e.detail.command, e.detail.data);
- if (!handled) {
- sendAsyncMessage(e.detail.command, e.detail.data);
- }
- });
- registerEvent("NewTab:Observe");
- let ev = new CustomEvent("NewTabCommandReady");
- remoteIFrame.contentDocument.dispatchEvent(ev);
- };
-
- remoteIFrame.src = remoteNewTabLocation.href;
- remoteIFrame.addEventListener("load", loadHandler);
- }
-
- /**
- * Allows the content IFrame to register a listener to an event sent by
- * the privileged parent process, in RemoteAboutNewTab.jsm
- *
- * @param {String} eventName
- * Event name to listen to
- */
- function registerEvent(eventName) {
- addMessageListener(eventName, (message) => {
- remoteIFrame.contentWindow.postMessage(message, remoteNewTabLocation.origin);
- });
- }
-
- /**
- * Sends the initial data payload to a content IFrame so it can bootstrap
- */
- function getInitialState() {
- let prefs = Services.prefs;
- let isPrivate = PrivateBrowsingUtils.isContentWindowPrivate(window);
- let state = {
- enabled: prefs.getBoolPref("browser.newtabpage.enabled"),
- enhanced: prefs.getBoolPref("browser.newtabpage.enhanced"),
- rows: prefs.getIntPref("browser.newtabpage.rows"),
- columns: prefs.getIntPref("browser.newtabpage.columns"),
- introShown: prefs.getBoolPref("browser.newtabpage.introShown"),
- windowID: window.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDOMWindowUtils).outerWindowID,
- privateBrowsingMode: isPrivate
- };
- remoteIFrame.contentWindow.postMessage({
- name: "NewTab:State",
- data: state
- }, remoteNewTabLocation.origin);
- }
-
- addMessageListener("NewTabFrame:Init", function loadHandler(message) {
- // Everything is loaded. Initialize the New Tab Page.
- removeMessageListener("NewTabFrame:Init", loadHandler);
- initRemotePage(message.data);
- });
- sendAsyncMessage("NewTabFrame:GetInit");
-}());
diff --git a/browser/base/content/remote-newtab/newTab.xhtml b/browser/base/content/remote-newtab/newTab.xhtml
deleted file mode 100644
index 1ae754eedbfd..000000000000
--- a/browser/base/content/remote-newtab/newTab.xhtml
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
-
- %newTabDTD;
-]>
-
-
-
- &newtab.pageTitle;
-
-
-
-
-
-
-
-
diff --git a/browser/base/jar.mn b/browser/base/jar.mn
index 175d50f9b826..ee66ea3a842e 100644
--- a/browser/base/jar.mn
+++ b/browser/base/jar.mn
@@ -136,9 +136,6 @@ browser.jar:
* content/browser/newtab/newTab.js (content/newtab/newTab.js)
content/browser/newtab/newTab.css (content/newtab/newTab.css)
content/browser/newtab/newTab.inadjacent.json (content/newtab/newTab.inadjacent.json)
- content/browser/remote-newtab/newTab.xhtml (content/remote-newtab/newTab.xhtml)
- content/browser/remote-newtab/newTab.js (content/remote-newtab/newTab.js)
- content/browser/remote-newtab/newTab.css (content/remote-newtab/newTab.css)
* content/browser/pageinfo/pageInfo.xul (content/pageinfo/pageInfo.xul)
content/browser/pageinfo/pageInfo.js (content/pageinfo/pageInfo.js)
content/browser/pageinfo/pageInfo.css (content/pageinfo/pageInfo.css)
diff --git a/browser/components/about/AboutRedirector.cpp b/browser/components/about/AboutRedirector.cpp
index d83d9a46c063..184875fe132c 100644
--- a/browser/components/about/AboutRedirector.cpp
+++ b/browser/components/about/AboutRedirector.cpp
@@ -89,11 +89,6 @@ static RedirEntry kRedirMap[] = {
// the newtab's actual URL will be determined when the channel is created
{ "newtab", "about:blank",
nsIAboutModule::ALLOW_SCRIPT },
-#ifndef RELEASE_BUILD
- { "remote-newtab", "chrome://browser/content/remote-newtab/newTab.xhtml",
- nsIAboutModule::URI_MUST_LOAD_IN_CHILD |
- nsIAboutModule::ALLOW_SCRIPT },
-#endif
{ "preferences", "chrome://browser/content/preferences/in-content/preferences.xul",
nsIAboutModule::ALLOW_SCRIPT },
{ "downloads", "chrome://browser/content/downloads/contentAreaDownloadsView.xul",
diff --git a/browser/components/newtab/RemoteAboutNewTab.jsm b/browser/components/newtab/RemoteAboutNewTab.jsm
deleted file mode 100644
index c6b9fff973bb..000000000000
--- a/browser/components/newtab/RemoteAboutNewTab.jsm
+++ /dev/null
@@ -1,302 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-/* globals Services, XPCOMUtils, RemotePages, RemoteNewTabUtils, Task, aboutNewTabService */
-/* globals BackgroundPageThumbs, PageThumbs, DirectoryLinksProvider, PlacesProvider, NewTabPrefsProvider */
-/* exported RemoteAboutNewTab */
-
-"use strict";
-
-let Ci = Components.interfaces;
-let Cu = Components.utils;
-const XHTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
-
-this.EXPORTED_SYMBOLS = ["RemoteAboutNewTab"];
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Task.jsm");
-Cu.importGlobalProperties(["URL"]);
-
-XPCOMUtils.defineLazyModuleGetter(this, "RemotePages",
- "resource://gre/modules/RemotePageManager.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "RemoteNewTabUtils",
- "resource:///modules/RemoteNewTabUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "BackgroundPageThumbs",
- "resource://gre/modules/BackgroundPageThumbs.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "PageThumbs",
- "resource://gre/modules/PageThumbs.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "DirectoryLinksProvider",
- "resource:///modules/DirectoryLinksProvider.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "PlacesProvider",
- "resource:///modules/PlacesProvider.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "NewTabPrefsProvider",
- "resource:///modules/NewTabPrefsProvider.jsm");
-XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService",
- "@mozilla.org/browser/aboutnewtab-service;1",
- "nsIAboutNewTabService");
-
-let RemoteAboutNewTab = {
-
- pageListener: null,
- remoteURL: null,
-
- /**
- * Initialize the RemotePageManager and add all message listeners for this page
- */
- init: function() {
- this.remoteURL = new URL(aboutNewTabService.generateRemoteURL());
- this.pageListener = new RemotePages(this.remoteURL.href);
- this.pageListener.addMessageListener("NewTab:InitializeGrid", this.initializeGrid.bind(this));
- this.pageListener.addMessageListener("NewTab:UpdateGrid", this.updateGrid.bind(this));
- this.pageListener.addMessageListener("NewTab:Customize", this.customize.bind(this));
- this.pageListener.addMessageListener("NewTab:CaptureBackgroundPageThumbs",
- this.captureBackgroundPageThumb.bind(this));
- this.pageListener.addMessageListener("NewTab:PageThumbs", this.createPageThumb.bind(this));
- this.pageListener.addMessageListener("NewTabFrame:GetInit", this.initContentFrame.bind(this));
-
- this._addObservers();
- },
-
- customize: function(message) {
- if (message.data.enabled !== undefined) {
- Services.prefs.setBoolPref("browser.newtabpage.enabled", message.data.enabled);
- }
- if (message.data.enhanced !== undefined) {
- Services.prefs.setBoolPref("browser.newtabpage.enhanced", message.data.enhanced);
- }
- },
-
- /**
- * Notifies when history is cleared
- */
- placesClearHistory: function() {
- this.pageListener.sendAsyncMessage("NewTab:PlacesClearHistory");
- },
-
- /**
- * Notifies when a link has changed
- */
- placesLinkChanged: function(name, data) { // jshint ignore:line
- this.pageListener.sendAsyncMessage("NewTab:PlacesLinkChanged", data);
- },
-
- /**
- * Notifies when many links have changed
- */
- placesManyLinksChanged: function() {
- this.pageListener.sendAsyncMessage("NewTab:PlacesManyLinksChanged");
- },
-
- /**
- * Notifies when one URL has been deleted
- */
- placesDeleteURI: function(name, data) { // jshint ignore:line
- this.pageListener.sendAsyncMessage("NewTab:PlacesDeleteURI", data.url);
- },
-
- /**
- * Initializes the grid for the first time when the page loads.
- * Fetch all the links and send them down to the child to populate
- * the grid with.
- *
- * @param {Object} message
- * A RemotePageManager message.
- */
- initializeGrid: function(message) {
- RemoteNewTabUtils.links.populateCache(() => {
- message.target.sendAsyncMessage("NewTab:InitializeLinks", {
- links: RemoteNewTabUtils.links.getLinks(),
- enhancedLinks: this.getEnhancedLinks(),
- });
- });
- },
-
- /**
- * Inits the content iframe with the newtab location
- */
- initContentFrame: function(message) {
- message.target.sendAsyncMessage("NewTabFrame:Init", {
- href: this.remoteURL.href,
- origin: this.remoteURL.origin
- });
- },
-
- /**
- * Updates the grid by getting a new set of links.
- *
- * @param {Object} message
- * A RemotePageManager message.
- */
- updateGrid: function(message) {
- message.target.sendAsyncMessage("NewTab:UpdateLinks", {
- links: RemoteNewTabUtils.links.getLinks(),
- enhancedLinks: this.getEnhancedLinks(),
- });
- },
-
- /**
- * Captures the site's thumbnail in the background, then attemps to show the thumbnail.
- *
- * @param {Object} message
- * A RemotePageManager message with the following data:
- *
- * link (Object):
- * A link object that contains:
- *
- * baseDomain (String)
- * blockState (Boolean)
- * frecency (Integer)
- * lastVisiteDate (Integer)
- * pinState (Boolean)
- * title (String)
- * type (String)
- * url (String)
- */
- captureBackgroundPageThumb: Task.async(function* (message) {
- try {
- yield BackgroundPageThumbs.captureIfMissing(message.data.link.url);
- this.createPageThumb(message);
- } catch (err) {
- Cu.reportError("error: " + err);
- }
- }),
-
- /**
- * Creates the thumbnail to display for each site based on the unique URL
- * of the site and it's type (regular or enhanced). If the thumbnail is of
- * type "regular", we create a blob and send that down to the child. If the
- * thumbnail is of type "enhanced", get the file path for the URL and create
- * and enhanced URI that will be sent down to the child.
- *
- * @param {Object} message
- * A RemotePageManager message with the following data:
- *
- * link (Object):
- * A link object that contains:
- *
- * baseDomain (String)
- * blockState (Boolean)
- * frecency (Integer)
- * lastVisiteDate (Integer)
- * pinState (Boolean)
- * title (String)
- * type (String)
- * url (String)
- */
- createPageThumb: function(message) {
- let imgSrc = PageThumbs.getThumbnailURL(message.data.link.url);
- let doc = Services.appShell.hiddenDOMWindow.document;
- let img = doc.createElementNS(XHTML_NAMESPACE, "img");
- let canvas = doc.createElementNS(XHTML_NAMESPACE, "canvas");
- let enhanced = Services.prefs.getBoolPref("browser.newtabpage.enhanced");
-
- img.onload = function(e) { // jshint ignore:line
- canvas.width = img.naturalWidth;
- canvas.height = img.naturalHeight;
- var ctx = canvas.getContext("2d");
- ctx.drawImage(this, 0, 0, this.naturalWidth, this.naturalHeight);
- canvas.toBlob(function(blob) {
- let host = new URL(message.data.link.url).host;
- RemoteAboutNewTab.pageListener.sendAsyncMessage("NewTab:RegularThumbnailURI", {
- thumbPath: "/pagethumbs/" + host,
- enhanced,
- url: message.data.link.url,
- blob,
- });
- });
- };
- img.src = imgSrc;
- },
-
- /**
- * Get the set of enhanced links (if any) from the Directory Links Provider.
- */
- getEnhancedLinks: function() {
- let enhancedLinks = [];
- for (let link of RemoteNewTabUtils.links.getLinks()) {
- if (link) {
- enhancedLinks.push(DirectoryLinksProvider.getEnhancedLink(link));
- }
- }
- return enhancedLinks;
- },
-
- /**
- * Listens for a preference change or session purge for all pages and sends
- * a message to update the pages that are open. If a session purge occured,
- * also clear the links cache and update the set of links to display, as they
- * may have changed, then proceed with the page update.
- */
- observe: function(aSubject, aTopic, aData) { // jshint ignore:line
- let extraData;
- if (aTopic === "browser:purge-session-history") {
- RemoteNewTabUtils.links.resetCache();
- RemoteNewTabUtils.links.populateCache(() => {
- this.pageListener.sendAsyncMessage("NewTab:UpdateLinks", {
- links: RemoteNewTabUtils.links.getLinks(),
- enhancedLinks: this.getEnhancedLinks(),
- });
- });
- }
-
- if (extraData !== undefined || aTopic === "page-thumbnail:create") {
- if (aTopic !== "page-thumbnail:create") {
- // Change the topic for enhanced and enabled observers.
- aTopic = aData;
- }
- this.pageListener.sendAsyncMessage("NewTab:Observe", {topic: aTopic, data: extraData});
- }
- },
-
- setEnabled: function(name, data) { // jshint ignore:line
- this.pageListener.sendAsyncMessage("NewTab:setEnabled", data);
- },
-
- setEnhanced: function(name, data) { // jshint ignore:line
- this.pageListener.sendAsyncMessage("NewTab:setEnhanced", data);
- },
-
- setPinned: function(name, data) { // jshint ignore:line
- this.pageListener.sendAsyncMessage("NewTab:setPinnedLinks", data);
- },
-
- /**
- * Add all observers that about:newtab page must listen for.
- */
- _addObservers: function() {
- Services.obs.addObserver(this, "page-thumbnail:create", true);
- Services.obs.addObserver(this, "browser:purge-session-history", true);
- PlacesProvider.links.on("deleteURI", this.placesDeleteURI.bind(this));
- PlacesProvider.links.on("clearHistory", this.placesClearHistory.bind(this));
- PlacesProvider.links.on("linkChanged", this.placesLinkChanged.bind(this));
- PlacesProvider.links.on("manyLinksChanged", this.placesManyLinksChanged.bind(this));
- NewTabPrefsProvider.prefs.on("browser.newtabpage.enabled", this.setEnabled.bind(this));
- NewTabPrefsProvider.prefs.on("browser.newtabpage.enhanced", this.setEnhanced.bind(this));
- NewTabPrefsProvider.prefs.on("browser.newtabpage.pinned", this.setPinned.bind(this));
- },
-
- /**
- * Remove all observers on the page.
- */
- _removeObservers: function() {
- Services.obs.removeObserver(this, "page-thumbnail:create");
- Services.obs.removeObserver(this, "browser:purge-session-history");
- PlacesProvider.links.off("deleteURI", this.placesDeleteURI);
- PlacesProvider.links.off("clearHistory", this.placesClearHistory);
- PlacesProvider.links.off("linkChanged", this.placesLinkChanged);
- PlacesProvider.links.off("manyLinksChanged", this.placesManyLinksChanged);
- NewTabPrefsProvider.prefs.off("browser.newtabpage.enabled", this.setEnabled.bind(this));
- NewTabPrefsProvider.prefs.off("browser.newtabpage.enhanced", this.setEnhanced.bind(this));
- NewTabPrefsProvider.prefs.off("browser.newtabpage.pinned", this.setPinned.bind(this));
- },
-
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
- Ci.nsISupportsWeakReference]),
-
- uninit: function() {
- this._removeObservers();
- this.pageListener.destroy();
- this.pageListener = null;
- },
-};
diff --git a/browser/components/newtab/RemoteNewTabUtils.jsm b/browser/components/newtab/RemoteNewTabUtils.jsm
deleted file mode 100644
index 8baa63c3341d..000000000000
--- a/browser/components/newtab/RemoteNewTabUtils.jsm
+++ /dev/null
@@ -1,766 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-this.EXPORTED_SYMBOLS = ["RemoteNewTabUtils"];
-
-const Ci = Components.interfaces;
-const Cc = Components.classes;
-const Cu = Components.utils;
-
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Task.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
- "resource://gre/modules/PlacesUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "PageThumbs",
- "resource://gre/modules/PageThumbs.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "BinarySearch",
- "resource://gre/modules/BinarySearch.jsm");
-
-XPCOMUtils.defineLazyGetter(this, "gPrincipal", function () {
- let uri = Services.io.newURI("about:newtab", null, null);
- return Services.scriptSecurityManager.createCodebasePrincipal(uri, {});
-});
-
-// The maximum number of results PlacesProvider retrieves from history.
-const HISTORY_RESULTS_LIMIT = 100;
-
-// The maximum number of links Links.getLinks will return.
-const LINKS_GET_LINKS_LIMIT = 100;
-
-/**
- * Singleton that serves as the default link provider for the grid. It queries
- * the history to retrieve the most frequently visited sites.
- */
-let PlacesProvider = {
- /**
- * A count of how many batch updates are under way (batches may be nested, so
- * we keep a counter instead of a simple bool).
- **/
- _batchProcessingDepth: 0,
-
- /**
- * A flag that tracks whether onFrecencyChanged was notified while a batch
- * operation was in progress, to tell us whether to take special action after
- * the batch operation completes.
- **/
- _batchCalledFrecencyChanged: false,
-
- /**
- * Set this to change the maximum number of links the provider will provide.
- */
- maxNumLinks: HISTORY_RESULTS_LIMIT,
-
- /**
- * Must be called before the provider is used.
- */
- init: function PlacesProvider_init() {
- PlacesUtils.history.addObserver(this, true);
- },
-
- /**
- * Gets the current set of links delivered by this provider.
- * @param aCallback The function that the array of links is passed to.
- */
- getLinks: function PlacesProvider_getLinks(aCallback) {
- let options = PlacesUtils.history.getNewQueryOptions();
- options.maxResults = this.maxNumLinks;
-
- // Sort by frecency, descending.
- options.sortingMode = Ci.nsINavHistoryQueryOptions.SORT_BY_FRECENCY_DESCENDING
-
- let links = [];
-
- let callback = {
- handleResult: function (aResultSet) {
- let row;
-
- while ((row = aResultSet.getNextRow())) {
- let url = row.getResultByIndex(1);
- if (LinkChecker.checkLoadURI(url)) {
- let title = row.getResultByIndex(2);
- let frecency = row.getResultByIndex(12);
- let lastVisitDate = row.getResultByIndex(5);
- links.push({
- url: url,
- title: title,
- frecency: frecency,
- lastVisitDate: lastVisitDate,
- type: "history",
- });
- }
- }
- },
-
- handleError: function (aError) {
- // Should we somehow handle this error?
- aCallback([]);
- },
-
- handleCompletion: function (aReason) {
- // The Places query breaks ties in frecency by place ID descending, but
- // that's different from how Links.compareLinks breaks ties, because
- // compareLinks doesn't have access to place IDs. It's very important
- // that the initial list of links is sorted in the same order imposed by
- // compareLinks, because Links uses compareLinks to perform binary
- // searches on the list. So, ensure the list is so ordered.
- let i = 1;
- let outOfOrder = [];
- while (i < links.length) {
- if (Links.compareLinks(links[i - 1], links[i]) > 0)
- outOfOrder.push(links.splice(i, 1)[0]);
- else
- i++;
- }
- for (let link of outOfOrder) {
- i = BinarySearch.insertionIndexOf(Links.compareLinks, links, link);
- links.splice(i, 0, link);
- }
-
- aCallback(links);
- }
- };
-
- // Execute the query.
- let query = PlacesUtils.history.getNewQuery();
- let db = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase);
- db.asyncExecuteLegacyQueries([query], 1, options, callback);
- },
-
- /**
- * Registers an object that will be notified when the provider's links change.
- * @param aObserver An object with the following optional properties:
- * * onLinkChanged: A function that's called when a single link
- * changes. It's passed the provider and the link object. Only the
- * link's `url` property is guaranteed to be present. If its `title`
- * property is present, then its title has changed, and the
- * property's value is the new title. If any sort properties are
- * present, then its position within the provider's list of links may
- * have changed, and the properties' values are the new sort-related
- * values. Note that this link may not necessarily have been present
- * in the lists returned from any previous calls to getLinks.
- * * onManyLinksChanged: A function that's called when many links
- * change at once. It's passed the provider. You should call
- * getLinks to get the provider's new list of links.
- */
- addObserver: function PlacesProvider_addObserver(aObserver) {
- this._observers.push(aObserver);
- },
-
- _observers: [],
-
- /**
- * Called by the history service.
- */
- onBeginUpdateBatch: function() {
- this._batchProcessingDepth += 1;
- },
-
- onEndUpdateBatch: function() {
- this._batchProcessingDepth -= 1;
- if (this._batchProcessingDepth == 0 && this._batchCalledFrecencyChanged) {
- this.onManyFrecenciesChanged();
- this._batchCalledFrecencyChanged = false;
- }
- },
-
- onDeleteURI: function PlacesProvider_onDeleteURI(aURI, aGUID, aReason) {
- // let observers remove sensetive data associated with deleted visit
- this._callObservers("onDeleteURI", {
- url: aURI.spec,
- });
- },
-
- onClearHistory: function() {
- this._callObservers("onClearHistory")
- },
-
- /**
- * Called by the history service.
- */
- onFrecencyChanged: function PlacesProvider_onFrecencyChanged(aURI, aNewFrecency, aGUID, aHidden, aLastVisitDate) {
- // If something is doing a batch update of history entries we don't want
- // to do lots of work for each record. So we just track the fact we need
- // to call onManyFrecenciesChanged() once the batch is complete.
- if (this._batchProcessingDepth > 0) {
- this._batchCalledFrecencyChanged = true;
- return;
- }
- // The implementation of the query in getLinks excludes hidden and
- // unvisited pages, so it's important to exclude them here, too.
- if (!aHidden && aLastVisitDate) {
- this._callObservers("onLinkChanged", {
- url: aURI.spec,
- frecency: aNewFrecency,
- lastVisitDate: aLastVisitDate,
- type: "history",
- });
- }
- },
-
- /**
- * Called by the history service.
- */
- onManyFrecenciesChanged: function PlacesProvider_onManyFrecenciesChanged() {
- this._callObservers("onManyLinksChanged");
- },
-
- /**
- * Called by the history service.
- */
- onTitleChanged: function PlacesProvider_onTitleChanged(aURI, aNewTitle, aGUID) {
- this._callObservers("onLinkChanged", {
- url: aURI.spec,
- title: aNewTitle
- });
- },
-
- _callObservers: function PlacesProvider__callObservers(aMethodName, aArg) {
- for (let obs of this._observers) {
- if (obs[aMethodName]) {
- try {
- obs[aMethodName](this, aArg);
- } catch (err) {
- Cu.reportError(err);
- }
- }
- }
- },
-
- QueryInterface: XPCOMUtils.generateQI([Ci.nsINavHistoryObserver,
- Ci.nsISupportsWeakReference]),
-};
-
-/**
- * Singleton that provides access to all links contained in the grid (including
- * the ones that don't fit on the grid). A link is a plain object that looks
- * like this:
- *
- * {
- * url: "http://www.mozilla.org/",
- * title: "Mozilla",
- * frecency: 1337,
- * lastVisitDate: 1394678824766431,
- * }
- */
-let Links = {
- /**
- * The maximum number of links returned by getLinks.
- */
- maxNumLinks: LINKS_GET_LINKS_LIMIT,
-
- /**
- * A mapping from each provider to an object { sortedLinks, siteMap, linkMap }.
- * sortedLinks is the cached, sorted array of links for the provider.
- * siteMap is a mapping from base domains to URL count associated with the domain.
- * siteMap is used to look up a user's top sites that can be targeted
- * with a suggested tile.
- * linkMap is a Map from link URLs to link objects.
- */
- _providers: new Map(),
-
- /**
- * The properties of link objects used to sort them.
- */
- _sortProperties: [
- "frecency",
- "lastVisitDate",
- "url",
- ],
-
- /**
- * List of callbacks waiting for the cache to be populated.
- */
- _populateCallbacks: [],
-
- /**
- * A list of objects that are observing links updates.
- */
- _observers: [],
-
- /**
- * Registers an object that will be notified when links updates.
- */
- addObserver: function (aObserver) {
- this._observers.push(aObserver);
- },
-
- /**
- * Adds a link provider.
- * @param aProvider The link provider.
- */
- addProvider: function Links_addProvider(aProvider) {
- this._providers.set(aProvider, null);
- aProvider.addObserver(this);
- },
-
- /**
- * Removes a link provider.
- * @param aProvider The link provider.
- */
- removeProvider: function Links_removeProvider(aProvider) {
- if (!this._providers.delete(aProvider))
- throw new Error("Unknown provider");
- },
-
- /**
- * Populates the cache with fresh links from the providers.
- * @param aCallback The callback to call when finished (optional).
- * @param aForce When true, populates the cache even when it's already filled.
- */
- populateCache: function Links_populateCache(aCallback, aForce) {
- let callbacks = this._populateCallbacks;
-
- // Enqueue the current callback.
- callbacks.push(aCallback);
-
- // There was a callback waiting already, thus the cache has not yet been
- // populated.
- if (callbacks.length > 1)
- return;
-
- function executeCallbacks() {
- while (callbacks.length) {
- let callback = callbacks.shift();
- if (callback) {
- try {
- callback();
- } catch (e) {
- // We want to proceed even if a callback fails.
- }
- }
- }
- }
-
- let numProvidersRemaining = this._providers.size;
- for (let [provider, links] of this._providers) {
- this._populateProviderCache(provider, () => {
- if (--numProvidersRemaining == 0)
- executeCallbacks();
- }, aForce);
- }
- },
-
- /**
- * Gets the current set of links contained in the grid.
- * @return The links in the grid.
- */
- getLinks: function Links_getLinks() {
- let links = this._getMergedProviderLinks();
-
- let sites = new Set();
-
- // Filter duplicate base domains.
- links = links.filter(function (link) {
- let site = RemoteNewTabUtils.extractSite(link.url);
- link.baseDomain = site;
- if (site == null || sites.has(site))
- return false;
- sites.add(site);
-
- return true;
- });
-
- return links;
- },
-
- /**
- * Resets the links cache.
- */
- resetCache: function Links_resetCache() {
- for (let provider of this._providers.keys()) {
- this._providers.set(provider, null);
- }
- },
-
- /**
- * Compares two links.
- * @param aLink1 The first link.
- * @param aLink2 The second link.
- * @return A negative number if aLink1 is ordered before aLink2, zero if
- * aLink1 and aLink2 have the same ordering, or a positive number if
- * aLink1 is ordered after aLink2.
- *
- * @note compareLinks's this object is bound to Links below.
- */
- compareLinks: function Links_compareLinks(aLink1, aLink2) {
- for (let prop of this._sortProperties) {
- if (!(prop in aLink1) || !(prop in aLink2))
- throw new Error("Comparable link missing required property: " + prop);
- }
- return aLink2.frecency - aLink1.frecency ||
- aLink2.lastVisitDate - aLink1.lastVisitDate ||
- aLink1.url.localeCompare(aLink2.url);
- },
-
- _incrementSiteMap: function(map, link) {
- let site = RemoteNewTabUtils.extractSite(link.url);
- map.set(site, (map.get(site) || 0) + 1);
- },
-
- _decrementSiteMap: function(map, link) {
- let site = RemoteNewTabUtils.extractSite(link.url);
- let previousURLCount = map.get(site);
- if (previousURLCount === 1) {
- map.delete(site);
- } else {
- map.set(site, previousURLCount - 1);
- }
- },
-
- /**
- * Update the siteMap cache based on the link given and whether we need
- * to increment or decrement it. We do this by iterating over all stored providers
- * to find which provider this link already exists in. For providers that
- * have this link, we will adjust siteMap for them accordingly.
- *
- * @param aLink The link that will affect siteMap
- * @param increment A boolean for whether to increment or decrement siteMap
- */
- _adjustSiteMapAndNotify: function(aLink, increment=true) {
- for (let [provider, cache] of this._providers) {
- // We only update siteMap if aLink is already stored in linkMap.
- if (cache.linkMap.get(aLink.url)) {
- if (increment) {
- this._incrementSiteMap(cache.siteMap, aLink);
- continue;
- }
- this._decrementSiteMap(cache.siteMap, aLink);
- }
- }
- this._callObservers("onLinkChanged", aLink);
- },
-
- populateProviderCache: function(provider, callback) {
- if (!this._providers.has(provider)) {
- throw new Error("Can only populate provider cache for existing provider.");
- }
-
- return this._populateProviderCache(provider, callback, false);
- },
-
- /**
- * Calls getLinks on the given provider and populates our cache for it.
- * @param aProvider The provider whose cache will be populated.
- * @param aCallback The callback to call when finished.
- * @param aForce When true, populates the provider's cache even when it's
- * already filled.
- */
- _populateProviderCache: function (aProvider, aCallback, aForce) {
- let cache = this._providers.get(aProvider);
- let createCache = !cache;
- if (createCache) {
- cache = {
- // Start with a resolved promise.
- populatePromise: new Promise(resolve => resolve()),
- };
- this._providers.set(aProvider, cache);
- }
- // Chain the populatePromise so that calls are effectively queued.
- cache.populatePromise = cache.populatePromise.then(() => {
- return new Promise(resolve => {
- if (!createCache && !aForce) {
- aCallback();
- resolve();
- return;
- }
- aProvider.getLinks(links => {
- // Filter out null and undefined links so we don't have to deal with
- // them in getLinks when merging links from providers.
- links = links.filter((link) => !!link);
- cache.sortedLinks = links;
- cache.siteMap = links.reduce((map, link) => {
- this._incrementSiteMap(map, link);
- return map;
- }, new Map());
- cache.linkMap = links.reduce((map, link) => {
- map.set(link.url, link);
- return map;
- }, new Map());
- aCallback();
- resolve();
- });
- });
- });
- },
-
- /**
- * Merges the cached lists of links from all providers whose lists are cached.
- * @return The merged list.
- */
- _getMergedProviderLinks: function Links__getMergedProviderLinks() {
- // Build a list containing a copy of each provider's sortedLinks list.
- let linkLists = [];
- for (let provider of this._providers.keys()) {
- let links = this._providers.get(provider);
- if (links && links.sortedLinks) {
- linkLists.push(links.sortedLinks.slice());
- }
- }
-
- function getNextLink() {
- let minLinks = null;
- for (let links of linkLists) {
- if (links.length &&
- (!minLinks || Links.compareLinks(links[0], minLinks[0]) < 0))
- minLinks = links;
- }
- return minLinks ? minLinks.shift() : null;
- }
-
- let finalLinks = [];
- for (let nextLink = getNextLink();
- nextLink && finalLinks.length < this.maxNumLinks;
- nextLink = getNextLink()) {
- finalLinks.push(nextLink);
- }
-
- return finalLinks;
- },
-
- /**
- * Called by a provider to notify us when a single link changes.
- * @param aProvider The provider whose link changed.
- * @param aLink The link that changed. If the link is new, it must have all
- * of the _sortProperties. Otherwise, it may have as few or as
- * many as is convenient.
- * @param aIndex The current index of the changed link in the sortedLinks
- cache in _providers. Defaults to -1 if the provider doesn't know the index
- * @param aDeleted Boolean indicating if the provider has deleted the link.
- */
- onLinkChanged: function Links_onLinkChanged(aProvider, aLink, aIndex=-1, aDeleted=false) {
- if (!("url" in aLink))
- throw new Error("Changed links must have a url property");
-
- let links = this._providers.get(aProvider);
- if (!links)
- // This is not an error, it just means that between the time the provider
- // was added and the future time we call getLinks on it, it notified us of
- // a change.
- return;
-
- let { sortedLinks, siteMap, linkMap } = links;
- let existingLink = linkMap.get(aLink.url);
- let insertionLink = null;
-
- if (existingLink) {
- // Update our copy's position in O(lg n) by first removing it from its
- // list. It's important to do this before modifying its properties.
- if (this._sortProperties.some(prop => prop in aLink)) {
- let idx = aIndex;
- if (idx < 0) {
- idx = this._indexOf(sortedLinks, existingLink);
- } else if (this.compareLinks(aLink, sortedLinks[idx]) != 0) {
- throw new Error("aLink should be the same as sortedLinks[idx]");
- }
-
- if (idx < 0) {
- throw new Error("Link should be in _sortedLinks if in _linkMap");
- }
- sortedLinks.splice(idx, 1);
-
- if (aDeleted) {
- linkMap.delete(existingLink.url);
- this._decrementSiteMap(siteMap, existingLink);
- } else {
- // Update our copy's properties.
- Object.assign(existingLink, aLink);
-
- // Finally, reinsert our copy below.
- insertionLink = existingLink;
- }
- }
- // Update our copy's title in O(1).
- if ("title" in aLink && aLink.title != existingLink.title) {
- existingLink.title = aLink.title;
- }
- }
- else if (this._sortProperties.every(prop => prop in aLink)) {
- // Before doing the O(lg n) insertion below, do an O(1) check for the
- // common case where the new link is too low-ranked to be in the list.
- if (sortedLinks.length && sortedLinks.length == aProvider.maxNumLinks) {
- let lastLink = sortedLinks[sortedLinks.length - 1];
- if (this.compareLinks(lastLink, aLink) < 0) {
- return;
- }
- }
- // Copy the link object so that changes later made to it by the caller
- // don't affect our copy.
- insertionLink = {};
- for (let prop in aLink) {
- insertionLink[prop] = aLink[prop];
- }
- linkMap.set(aLink.url, insertionLink);
- this._incrementSiteMap(siteMap, aLink);
- }
-
- if (insertionLink) {
- let idx = this._insertionIndexOf(sortedLinks, insertionLink);
- sortedLinks.splice(idx, 0, insertionLink);
- if (sortedLinks.length > aProvider.maxNumLinks) {
- let lastLink = sortedLinks.pop();
- linkMap.delete(lastLink.url);
- this._decrementSiteMap(siteMap, lastLink);
- }
- }
- },
-
- /**
- * Called by a provider to notify us when many links change.
- */
- onManyLinksChanged: function Links_onManyLinksChanged(aProvider) {
- this._populateProviderCache(aProvider, () => {}, true);
- },
-
- _indexOf: function Links__indexOf(aArray, aLink) {
- return this._binsearch(aArray, aLink, "indexOf");
- },
-
- _insertionIndexOf: function Links__insertionIndexOf(aArray, aLink) {
- return this._binsearch(aArray, aLink, "insertionIndexOf");
- },
-
- _binsearch: function Links__binsearch(aArray, aLink, aMethod) {
- return BinarySearch[aMethod](this.compareLinks, aArray, aLink);
- },
-
- _callObservers(methodName, ...args) {
- for (let obs of this._observers) {
- if (typeof(obs[methodName]) == "function") {
- try {
- obs[methodName](this, ...args);
- } catch (err) {
- Cu.reportError(err);
- }
- }
- }
- },
-};
-
-Links.compareLinks = Links.compareLinks.bind(Links);
-
-/**
- * Singleton that checks if a given link should be displayed on about:newtab
- * or if we should rather not do it for security reasons. URIs that inherit
- * their caller's principal will be filtered.
- */
-let LinkChecker = {
- _cache: {},
-
- get flags() {
- return Ci.nsIScriptSecurityManager.DISALLOW_INHERIT_PRINCIPAL |
- Ci.nsIScriptSecurityManager.DONT_REPORT_ERRORS;
- },
-
- checkLoadURI: function LinkChecker_checkLoadURI(aURI) {
- if (!(aURI in this._cache))
- this._cache[aURI] = this._doCheckLoadURI(aURI);
-
- return this._cache[aURI];
- },
-
- _doCheckLoadURI: function Links_doCheckLoadURI(aURI) {
- try {
- Services.scriptSecurityManager.
- checkLoadURIStrWithPrincipal(gPrincipal, aURI, this.flags);
- return true;
- } catch (e) {
- // We got a weird URI or one that would inherit the caller's principal.
- return false;
- }
- }
-};
-
-let ExpirationFilter = {
- init: function ExpirationFilter_init() {
- PageThumbs.addExpirationFilter(this);
- },
-
- filterForThumbnailExpiration:
- function ExpirationFilter_filterForThumbnailExpiration(aCallback) {
- Links.populateCache(function () {
- let urls = [];
-
- // Add all URLs to the list that we want to keep thumbnails for.
- for (let link of Links.getLinks().slice(0, 25)) {
- if (link && link.url)
- urls.push(link.url);
- }
-
- aCallback(urls);
- });
- }
-};
-
-/**
- * Singleton that provides the public API of this JSM.
- */
-this.RemoteNewTabUtils = {
- _initialized: false,
-
- /**
- * Extract a "site" from a url in a way that multiple urls of a "site" returns
- * the same "site."
- * @param aUrl Url spec string
- * @return The "site" string or null
- */
- extractSite: function Links_extractSite(url) {
- let host;
- try {
- // Note that nsIURI.asciiHost throws NS_ERROR_FAILURE for some types of
- // URIs, including jar and moz-icon URIs.
- host = Services.io.newURI(url, null, null).asciiHost;
- } catch (ex) {
- return null;
- }
-
- // Strip off common subdomains of the same site (e.g., www, load balancer)
- return host.replace(/^(m|mobile|www\d*)\./, "");
- },
-
- init: function RemoteNewTabUtils_init() {
- if (this.initWithoutProviders()) {
- PlacesProvider.init();
- Links.addProvider(PlacesProvider);
- }
- },
-
- initWithoutProviders: function RemoteNewTabUtils_initWithoutProviders() {
- if (!this._initialized) {
- this._initialized = true;
- ExpirationFilter.init();
- return true;
- }
- return false;
- },
-
- getProviderLinks: function(aProvider) {
- let cache = Links._providers.get(aProvider);
- if (cache && cache.sortedLinks) {
- return cache.sortedLinks;
- }
- return [];
- },
-
- isTopSiteGivenProvider: function(aSite, aProvider) {
- let cache = Links._providers.get(aProvider);
- if (cache && cache.siteMap) {
- return cache.siteMap.has(aSite);
- }
- return false;
- },
-
- isTopPlacesSite: function(aSite) {
- return this.isTopSiteGivenProvider(aSite, PlacesProvider);
- },
-
- links: Links,
- linkChecker: LinkChecker,
- placesProvider: PlacesProvider
-};
diff --git a/browser/components/newtab/moz.build b/browser/components/newtab/moz.build
index 7144ced30b07..15e8ace6f286 100644
--- a/browser/components/newtab/moz.build
+++ b/browser/components/newtab/moz.build
@@ -15,8 +15,6 @@ if not CONFIG['RELEASE_BUILD']:
'NewTabPrefsProvider.jsm',
'NewTabURL.jsm',
'PlacesProvider.jsm',
- 'RemoteAboutNewTab.jsm',
- 'RemoteNewTabUtils.jsm',
]
XPIDL_SOURCES += [
diff --git a/browser/components/newtab/tests/xpcshell/test_RemoteNewTabUtils.js b/browser/components/newtab/tests/xpcshell/test_RemoteNewTabUtils.js
deleted file mode 100644
index 66a7c9eef13a..000000000000
--- a/browser/components/newtab/tests/xpcshell/test_RemoteNewTabUtils.js
+++ /dev/null
@@ -1,375 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ */
-
-// See also browser/base/content/test/newtab/.
-
-const { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
-Cu.import("resource:///modules/RemoteNewTabUtils.jsm");
-Cu.import("resource://gre/modules/Promise.jsm");
-Cu.import("resource://gre/modules/Task.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-
-function run_test() {
- run_next_test();
-}
-
-add_task(function* validCacheMidPopulation() {
- let expectedLinks = makeLinks(0, 3, 1);
-
- let provider = new TestProvider(done => done(expectedLinks));
- provider.maxNumLinks = expectedLinks.length;
-
- RemoteNewTabUtils.initWithoutProviders();
- RemoteNewTabUtils.links.addProvider(provider);
- let promise = new Promise(resolve => RemoteNewTabUtils.links.populateCache(resolve));
-
- // isTopSiteGivenProvider() and getProviderLinks() should still return results
- // even when cache is empty or being populated.
- do_check_false(RemoteNewTabUtils.isTopSiteGivenProvider("example1.com", provider));
- do_check_links(RemoteNewTabUtils.getProviderLinks(provider), []);
-
- yield promise;
-
- // Once the cache is populated, we get the expected results
- do_check_true(RemoteNewTabUtils.isTopSiteGivenProvider("example1.com", provider));
- do_check_links(RemoteNewTabUtils.getProviderLinks(provider), expectedLinks);
- RemoteNewTabUtils.links.removeProvider(provider);
-});
-
-add_task(function* notifyLinkDelete() {
- let expectedLinks = makeLinks(0, 3, 1);
-
- let provider = new TestProvider(done => done(expectedLinks));
- provider.maxNumLinks = expectedLinks.length;
-
- RemoteNewTabUtils.initWithoutProviders();
- RemoteNewTabUtils.links.addProvider(provider);
- yield new Promise(resolve => RemoteNewTabUtils.links.populateCache(resolve));
-
- do_check_links(RemoteNewTabUtils.links.getLinks(), expectedLinks);
-
- // Remove a link.
- let removedLink = expectedLinks[2];
- provider.notifyLinkChanged(removedLink, 2, true);
- let links = RemoteNewTabUtils.links._providers.get(provider);
-
- // Check that sortedLinks is correctly updated.
- do_check_links(RemoteNewTabUtils.links.getLinks(), expectedLinks.slice(0, 2));
-
- // Check that linkMap is accurately updated.
- do_check_eq(links.linkMap.size, 2);
- do_check_true(links.linkMap.get(expectedLinks[0].url));
- do_check_true(links.linkMap.get(expectedLinks[1].url));
- do_check_false(links.linkMap.get(removedLink.url));
-
- // Check that siteMap is correctly updated.
- do_check_eq(links.siteMap.size, 2);
- do_check_true(links.siteMap.has(RemoteNewTabUtils.extractSite(expectedLinks[0].url)));
- do_check_true(links.siteMap.has(RemoteNewTabUtils.extractSite(expectedLinks[1].url)));
- do_check_false(links.siteMap.has(RemoteNewTabUtils.extractSite(removedLink.url)));
-
- RemoteNewTabUtils.links.removeProvider(provider);
-});
-
-add_task(function populatePromise() {
- let count = 0;
- let expectedLinks = makeLinks(0, 10, 2);
-
- let getLinksFcn = Task.async(function* (callback) {
- //Should not be calling getLinksFcn twice
- count++;
- do_check_eq(count, 1);
- yield Promise.resolve();
- callback(expectedLinks);
- });
-
- let provider = new TestProvider(getLinksFcn);
-
- RemoteNewTabUtils.initWithoutProviders();
- RemoteNewTabUtils.links.addProvider(provider);
-
- RemoteNewTabUtils.links.populateProviderCache(provider, () => {});
- RemoteNewTabUtils.links.populateProviderCache(provider, () => {
- do_check_links(RemoteNewTabUtils.links.getLinks(), expectedLinks);
- RemoteNewTabUtils.links.removeProvider(provider);
- });
-});
-
-add_task(function* isTopSiteGivenProvider() {
- let expectedLinks = makeLinks(0, 10, 2);
-
- // The lowest 2 frecencies have the same base domain.
- expectedLinks[expectedLinks.length - 2].url = expectedLinks[expectedLinks.length - 1].url + "Test";
-
- let provider = new TestProvider(done => done(expectedLinks));
- provider.maxNumLinks = expectedLinks.length;
-
- RemoteNewTabUtils.initWithoutProviders();
- RemoteNewTabUtils.links.addProvider(provider);
- yield new Promise(resolve => RemoteNewTabUtils.links.populateCache(resolve));
-
- do_check_eq(RemoteNewTabUtils.isTopSiteGivenProvider("example2.com", provider), true);
- do_check_eq(RemoteNewTabUtils.isTopSiteGivenProvider("example1.com", provider), false);
-
- // Push out frecency 2 because the maxNumLinks is reached when adding frecency 3
- let newLink = makeLink(3);
- provider.notifyLinkChanged(newLink);
-
- // There is still a frecent url with example2 domain, so it's still frecent.
- do_check_eq(RemoteNewTabUtils.isTopSiteGivenProvider("example3.com", provider), true);
- do_check_eq(RemoteNewTabUtils.isTopSiteGivenProvider("example2.com", provider), true);
-
- // Push out frecency 3
- newLink = makeLink(5);
- provider.notifyLinkChanged(newLink);
-
- // Push out frecency 4
- newLink = makeLink(9);
- provider.notifyLinkChanged(newLink);
-
- // Our count reached 0 for the example2.com domain so it's no longer a frecent site.
- do_check_eq(RemoteNewTabUtils.isTopSiteGivenProvider("example5.com", provider), true);
- do_check_eq(RemoteNewTabUtils.isTopSiteGivenProvider("example2.com", provider), false);
-
- RemoteNewTabUtils.links.removeProvider(provider);
-});
-
-add_task(function* multipleProviders() {
- // Make each provider generate RemoteNewTabUtils.links.maxNumLinks links to check
- // that no more than maxNumLinks are actually returned in the merged list.
- let evenLinks = makeLinks(0, 2 * RemoteNewTabUtils.links.maxNumLinks, 2);
- let evenProvider = new TestProvider(done => done(evenLinks));
- let oddLinks = makeLinks(0, 2 * RemoteNewTabUtils.links.maxNumLinks - 1, 2);
- let oddProvider = new TestProvider(done => done(oddLinks));
-
- RemoteNewTabUtils.initWithoutProviders();
- RemoteNewTabUtils.links.addProvider(evenProvider);
- RemoteNewTabUtils.links.addProvider(oddProvider);
-
- yield new Promise(resolve => RemoteNewTabUtils.links.populateCache(resolve));
-
- let links = RemoteNewTabUtils.links.getLinks();
- let expectedLinks = makeLinks(RemoteNewTabUtils.links.maxNumLinks,
- 2 * RemoteNewTabUtils.links.maxNumLinks,
- 1);
- do_check_eq(links.length, RemoteNewTabUtils.links.maxNumLinks);
- do_check_links(links, expectedLinks);
-
- RemoteNewTabUtils.links.removeProvider(evenProvider);
- RemoteNewTabUtils.links.removeProvider(oddProvider);
-});
-
-add_task(function* changeLinks() {
- let expectedLinks = makeLinks(0, 20, 2);
- let provider = new TestProvider(done => done(expectedLinks));
-
- RemoteNewTabUtils.initWithoutProviders();
- RemoteNewTabUtils.links.addProvider(provider);
-
- yield new Promise(resolve => RemoteNewTabUtils.links.populateCache(resolve));
-
- do_check_links(RemoteNewTabUtils.links.getLinks(), expectedLinks);
-
- // Notify of a new link.
- let newLink = makeLink(19);
- expectedLinks.splice(1, 0, newLink);
- provider.notifyLinkChanged(newLink);
- do_check_links(RemoteNewTabUtils.links.getLinks(), expectedLinks);
-
- // Notify of a link that's changed sort criteria.
- newLink.frecency = 17;
- expectedLinks.splice(1, 1);
- expectedLinks.splice(2, 0, newLink);
- provider.notifyLinkChanged({
- url: newLink.url,
- frecency: 17,
- });
- do_check_links(RemoteNewTabUtils.links.getLinks(), expectedLinks);
-
- // Notify of a link that's changed title.
- newLink.title = "My frecency is now 17";
- provider.notifyLinkChanged({
- url: newLink.url,
- title: newLink.title,
- });
- do_check_links(RemoteNewTabUtils.links.getLinks(), expectedLinks);
-
- // Notify of a new link again, but this time make it overflow maxNumLinks.
- provider.maxNumLinks = expectedLinks.length;
- newLink = makeLink(21);
- expectedLinks.unshift(newLink);
- expectedLinks.pop();
- do_check_eq(expectedLinks.length, provider.maxNumLinks); // Sanity check.
- provider.notifyLinkChanged(newLink);
- do_check_links(RemoteNewTabUtils.links.getLinks(), expectedLinks);
-
- // Notify of many links changed.
- expectedLinks = makeLinks(0, 3, 1);
- provider.notifyManyLinksChanged();
-
- // Since _populateProviderCache() is async, we must wait until the provider's
- // populate promise has been resolved.
- yield RemoteNewTabUtils.links._providers.get(provider).populatePromise;
-
- // RemoteNewTabUtils.links will now repopulate its cache
- do_check_links(RemoteNewTabUtils.links.getLinks(), expectedLinks);
-
- RemoteNewTabUtils.links.removeProvider(provider);
-});
-
-add_task(function* oneProviderAlreadyCached() {
- let links1 = makeLinks(0, 10, 1);
- let provider1 = new TestProvider(done => done(links1));
-
- RemoteNewTabUtils.initWithoutProviders();
- RemoteNewTabUtils.links.addProvider(provider1);
-
- yield new Promise(resolve => RemoteNewTabUtils.links.populateCache(resolve));
- do_check_links(RemoteNewTabUtils.links.getLinks(), links1);
-
- let links2 = makeLinks(10, 20, 1);
- let provider2 = new TestProvider(done => done(links2));
- RemoteNewTabUtils.links.addProvider(provider2);
-
- yield new Promise(resolve => RemoteNewTabUtils.links.populateCache(resolve));
- do_check_links(RemoteNewTabUtils.links.getLinks(), links2.concat(links1));
-
- RemoteNewTabUtils.links.removeProvider(provider1);
- RemoteNewTabUtils.links.removeProvider(provider2);
-});
-
-add_task(function* newLowRankedLink() {
- // Init a provider with 10 links and make its maximum number also 10.
- let links = makeLinks(0, 10, 1);
- let provider = new TestProvider(done => done(links));
- provider.maxNumLinks = links.length;
-
- RemoteNewTabUtils.initWithoutProviders();
- RemoteNewTabUtils.links.addProvider(provider);
-
- yield new Promise(resolve => RemoteNewTabUtils.links.populateCache(resolve));
- do_check_links(RemoteNewTabUtils.links.getLinks(), links);
-
- // Notify of a new link that's low-ranked enough not to make the list.
- let newLink = makeLink(0);
- provider.notifyLinkChanged(newLink);
- do_check_links(RemoteNewTabUtils.links.getLinks(), links);
-
- // Notify about the new link's title change.
- provider.notifyLinkChanged({
- url: newLink.url,
- title: "a new title",
- });
- do_check_links(RemoteNewTabUtils.links.getLinks(), links);
-
- RemoteNewTabUtils.links.removeProvider(provider);
-});
-
-add_task(function extractSite() {
- // All these should extract to the same site
- [ "mozilla.org",
- "m.mozilla.org",
- "mobile.mozilla.org",
- "www.mozilla.org",
- "www3.mozilla.org",
- ].forEach(host => {
- let url = "http://" + host;
- do_check_eq(RemoteNewTabUtils.extractSite(url), "mozilla.org", "extracted same " + host);
- });
-
- // All these should extract to the same subdomain
- [ "bugzilla.mozilla.org",
- "www.bugzilla.mozilla.org",
- ].forEach(host => {
- let url = "http://" + host;
- do_check_eq(RemoteNewTabUtils.extractSite(url), "bugzilla.mozilla.org", "extracted eTLD+2 " + host);
- });
-
- // All these should not extract to the same site
- [ "bugzilla.mozilla.org",
- "bug123.bugzilla.mozilla.org",
- "too.many.levels.bugzilla.mozilla.org",
- "m2.mozilla.org",
- "mobile30.mozilla.org",
- "ww.mozilla.org",
- "ww2.mozilla.org",
- "wwwww.mozilla.org",
- "wwwww50.mozilla.org",
- "wwws.mozilla.org",
- "secure.mozilla.org",
- "secure10.mozilla.org",
- "many.levels.deep.mozilla.org",
- "just.check.in",
- "192.168.0.1",
- "localhost",
- ].forEach(host => {
- let url = "http://" + host;
- do_check_neq(RemoteNewTabUtils.extractSite(url), "mozilla.org", "extracted diff " + host);
- });
-
- // All these should not extract to the same site
- [ "about:blank",
- "file:///Users/user/file",
- "chrome://browser/something",
- "ftp://ftp.mozilla.org/",
- ].forEach(url => {
- do_check_neq(RemoteNewTabUtils.extractSite(url), "mozilla.org", "extracted diff url " + url);
- });
-});
-
-function TestProvider(getLinksFn) {
- this.getLinks = getLinksFn;
- this._observers = new Set();
-}
-
-TestProvider.prototype = {
- addObserver: function (observer) {
- this._observers.add(observer);
- },
- notifyLinkChanged: function (link, index=-1, deleted=false) {
- this._notifyObservers("onLinkChanged", link, index, deleted);
- },
- notifyManyLinksChanged: function () {
- this._notifyObservers("onManyLinksChanged");
- },
- _notifyObservers: function () {
- let observerMethodName = arguments[0];
- let args = Array.prototype.slice.call(arguments, 1);
- args.unshift(this);
- for (let obs of this._observers) {
- if (obs[observerMethodName])
- obs[observerMethodName].apply(RemoteNewTabUtils.links, args);
- }
- },
-};
-
-function do_check_links(actualLinks, expectedLinks) {
- do_check_true(Array.isArray(actualLinks));
- do_check_eq(actualLinks.length, expectedLinks.length);
- for (let i = 0; i < expectedLinks.length; i++) {
- let expected = expectedLinks[i];
- let actual = actualLinks[i];
- do_check_eq(actual.url, expected.url);
- do_check_eq(actual.title, expected.title);
- do_check_eq(actual.frecency, expected.frecency);
- do_check_eq(actual.lastVisitDate, expected.lastVisitDate);
- }
-}
-
-function makeLinks(frecRangeStart, frecRangeEnd, step) {
- let links = [];
- // Remember, links are ordered by frecency descending.
- for (let i = frecRangeEnd; i > frecRangeStart; i -= step) {
- links.push(makeLink(i));
- }
- return links;
-}
-
-function makeLink(frecency) {
- return {
- url: "http://example" + frecency + ".com/",
- title: "My frecency is " + frecency,
- frecency: frecency,
- lastVisitDate: 0,
- };
-}
diff --git a/browser/components/newtab/tests/xpcshell/xpcshell.ini b/browser/components/newtab/tests/xpcshell/xpcshell.ini
index 736a4eef5c33..7487608bba63 100644
--- a/browser/components/newtab/tests/xpcshell/xpcshell.ini
+++ b/browser/components/newtab/tests/xpcshell/xpcshell.ini
@@ -8,4 +8,3 @@ skip-if = toolkit == 'android' || toolkit == 'gonk'
[test_NewTabPrefsProvider.js]
[test_NewTabURL.js]
[test_PlacesProvider.js]
-[test_RemoteNewTabUtils.js]
diff --git a/browser/components/nsBrowserGlue.js b/browser/components/nsBrowserGlue.js
index 2542089771e2..8a92cd05186e 100644
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -29,12 +29,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "NewTabUtils",
"resource://gre/modules/NewTabUtils.jsm");
if(!AppConstants.RELEASE_BUILD) {
- XPCOMUtils.defineLazyModuleGetter(this, "RemoteAboutNewTab",
- "resource:///modules/RemoteAboutNewTab.jsm");
-
- XPCOMUtils.defineLazyModuleGetter(this, "RemoteNewTabUtils",
- "resource:///modules/RemoteNewTabUtils.jsm");
-
XPCOMUtils.defineLazyModuleGetter(this, "NewTabPrefsProvider",
"resource:///modules/NewTabPrefsProvider.jsm");
}
@@ -777,9 +771,6 @@ BrowserGlue.prototype = {
AboutNewTab.init();
if(!AppConstants.RELEASE_BUILD) {
- RemoteNewTabUtils.init();
- RemoteNewTabUtils.links.addProvider(DirectoryLinksProvider);
- RemoteAboutNewTab.init();
NewTabPrefsProvider.prefs.init();
}
@@ -1098,10 +1089,7 @@ BrowserGlue.prototype = {
CustomizationTabPreloader.uninit();
WebappManager.uninit();
- if (!AppConstants.RELEASE_BUILD) {
- RemoteAboutNewTab.uninit();
- NewTabPrefsProvider.prefs.uninit();
- }
+ NewTabPrefsProvider.prefs.uninit();
AboutNewTab.uninit();
#ifdef NIGHTLY_BUILD
if (Services.prefs.getBoolPref("dom.identity.enabled")) {
diff --git a/browser/modules/DirectoryLinksProvider.jsm b/browser/modules/DirectoryLinksProvider.jsm
index 422d1f3d8d88..afff26509ac6 100644
--- a/browser/modules/DirectoryLinksProvider.jsm
+++ b/browser/modules/DirectoryLinksProvider.jsm
@@ -32,13 +32,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "UpdateUtils",
XPCOMUtils.defineLazyServiceGetter(this, "eTLD",
"@mozilla.org/network/effective-tld-service;1",
"nsIEffectiveTLDService");
-
-// ensure remote new tab doesn't go beyond aurora
-if (!AppConstants.RELEASE_BUILD) {
- XPCOMUtils.defineLazyModuleGetter(this, "RemoteNewTabUtils",
- "resource:///modules/RemoteNewTabUtils.jsm");
-}
-
XPCOMUtils.defineLazyGetter(this, "gTextDecoder", () => {
return new TextDecoder();
});