Skip to content
This repository has been archived by the owner on Dec 15, 2018. It is now read-only.

Bug 1210478 - Add Meta URL resolution in RemoteNewTabLocation #39

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
35 changes: 8 additions & 27 deletions browser/base/content/remote-newtab/newTab.js
Expand Up @@ -44,12 +44,15 @@ XPCOMUtils.defineLazyModuleGetter(this, "Services",
registerEvent(data.type);
break;
case "NewTab:GetInitialState":
getInitialState();
break;
data = {};
data.windowID = window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils).outerWindowID;
data.privateBrowsingMode = PrivateBrowsingUtils.isContentWindowPrivate(window);
// Fallthrough - more handling required.
default:
commandHandled = false;
}
return commandHandled;
return {commandHandled, data};
}

function initRemotePage(initData) {
Expand All @@ -68,9 +71,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "Services",
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);
let {handled, data} = handleCommand(e.detail.command, e.detail.data);
if (!handled) {
sendAsyncMessage(e.detail.command, e.detail.data);
sendAsyncMessage(e.detail.command, data);
}
});
registerEvent("NewTab:Observe");
Expand All @@ -95,28 +98,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "Services",
});
}

/**
* 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);
Expand Down
65 changes: 65 additions & 0 deletions browser/components/newtab/NewTabPrefsProvider.jsm
@@ -0,0 +1,65 @@
/* global Services, EventEmitter, XPCOMUtils */
/* exported NewTabPrefsProvider */

"use strict";

this.EXPORTED_SYMBOLS = ["NewTabPrefsProvider"];

const Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");

XPCOMUtils.defineLazyGetter(this, "EventEmitter", function() {
const {EventEmitter} = Cu.import("resource://gre/modules/devtools/event-emitter.js", {});
return EventEmitter;
});

const prefsSet = new Set([
"browser.newtabpage.enabled",
"browser.newtabpage.enhanced",
"browser.newtabpage.pinned",
"intl.locale.matchOS",
"general.useragent.locale",
]);

let PrefsProvider = function PrefsProvider() {
EventEmitter.decorate(this);
};

PrefsProvider.prototype = {

observe(subject, topic, data) { // jshint ignore:line
if (topic === "nsPref:changed") {
if (prefsSet.has(data)) {
this.emit(data);
}
} else {
Cu.reportError(new Error("NewTabPrefsProvider observing unknown topic"));
}
},

get prefs() {
return Array.from(prefsSet);
},

startTracking() {
for (let pref of prefsSet) {
Services.prefs.addObserver(pref, this, false);
}
},

stopTracking() {
for (let pref of prefsSet) {
Services.prefs.removeObserver(pref, this, false);
}
}
};

/**
* Singleton that serves as the default new tab pref provider for the grid.
*/
const gPrefs = new PrefsProvider();

let NewTabPrefsProvider = {
prefs: gPrefs,
};
170 changes: 158 additions & 12 deletions browser/components/newtab/RemoteAboutNewTab.jsm
@@ -1,9 +1,9 @@
/* 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, SearchProvider, RemoteNewTabLocation, RemoteNewTabUtils, Task */
/* globals BackgroundPageThumbs, PageThumbs, DirectoryLinksProvider, PlacesProvider */

/* globals Services, XPCOMUtils, RemotePages, RemoteNewTabLocation, RemoteNewTabUtils, Task */
/* globals BackgroundPageThumbs, PageThumbs, DirectoryLinksProvider */
/* exported RemoteAboutNewTab */

"use strict";
Expand Down Expand Up @@ -31,6 +31,10 @@ XPCOMUtils.defineLazyModuleGetter(this, "DirectoryLinksProvider",
"resource:///modules/DirectoryLinksProvider.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "RemoteNewTabLocation",
"resource:///modules/RemoteNewTabLocation.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "SearchProvider",
"resource:///modules/SearchProvider.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PlacesProvider",
"resource:///modules/PlacesProvider.jsm");

let RemoteAboutNewTab = {

Expand All @@ -44,13 +48,98 @@ let RemoteAboutNewTab = {
this.pageListener.addMessageListener("NewTab:InitializeGrid", this.initializeGrid.bind(this));
this.pageListener.addMessageListener("NewTab:UpdateGrid", this.updateGrid.bind(this));
this.pageListener.addMessageListener("NewTab:CaptureBackgroundPageThumbs",
this.captureBackgroundPageThumb.bind(this));
this.captureBackgroundPageThumb.bind(this));
this.pageListener.addMessageListener("NewTab:PageThumbs", this.createPageThumb.bind(this));
this.pageListener.addMessageListener("NewTab:Search", this.search.bind(this));
this.pageListener.addMessageListener("NewTab:GetState", this.getState.bind(this));
this.pageListener.addMessageListener("NewTab:GetStrings", this.getStrings.bind(this));
this.pageListener.addMessageListener("NewTab:GetSuggestions", this.getSuggestions.bind(this));
this.pageListener.addMessageListener("NewTab:RemoveFormHistoryEntry", this.removeFormHistoryEntry.bind(this));
this.pageListener.addMessageListener("NewTab:ManageEngines", this.manageEngines.bind(this));
this.pageListener.addMessageListener("NewTab:SetCurrentEngine", this.setCurrentEngine.bind(this));
this.pageListener.addMessageListener("NewTabFrame:GetInit", this.initContentFrame.bind(this));
this.pageListener.addMessageListener("NewTab:GetInitialState", this.getInitialState.bind(this));

this._addObservers();
},

search: function(message) {
SearchProvider.performSearch(message.target.browser, message.data);
},

getState: Task.async(function* (message) {
let state = yield SearchProvider.state;
message.target.sendAsyncMessage("NewTab:ContentSearchService", {
state,
name: "State",
});
}),

getStrings: function(message) {
let strings = SearchProvider.searchSuggestionUIStrings;
message.target.sendAsyncMessage("NewTab:ContentSearchService", {
strings,
name: "Strings",
});
},

getSuggestions: Task.async(function* (message) {
try {
let suggestion = yield SearchProvider.getSuggestions(message.target.browser, message.data);

// In the case where there is no suggestion available, do not send a message.
if (suggestion !== null) {
message.target.sendAsyncMessage("NewTab:ContentSearchService", {
suggestion,
name: "Suggestions",
});
}
} catch(e) {
Cu.reportError(e);
}
}),

removeFormHistoryEntry: function(message) {
SearchProvider.removeFormHistoryEntry(message.target.browser, message.data.suggestionStr);
},

manageEngines: function(message) {
let browserWin = message.target.browser.ownerDocument.defaultView;
browserWin.openPreferences("paneSearch");
},

setCurrentEngine: function(message) {
Services.search.currentEngine = Services.search.getEngineByName(message.data.engineName);
},

/**
* Notifies when history is cleared
*/
placesClearHistory: function() {
this.pageListener.sendAsyncMessage("NewTab:PlacesClearHistory");
},

/**
* Notifies when a link has changed
*/
placesLinkChanged: function(link) {
this.pageListener.sendAsyncMessage("NewTab:PlacesLinkChanged", link);
},

/**
* Notifies when many links have changed
*/
placesManyLinksChanged: function() {
this.pageListener.sendAsyncMessage("NewTab:PlacesManyLinksChanged");
},

/**
* Notifies when one URL has been deleted
*/
placesDeleteURI: function(data) {
this.pageListener.sendAsyncMessage("NewTab:PlacesDeleteURI", data);
},

/**
* Initializes the grid for the first time when the page loads.
* Fetch all the links and send them down to the child to populate
Expand All @@ -59,7 +148,7 @@ let RemoteAboutNewTab = {
* @param {Object} message
* A RemotePageManager message.
*/
initializeGrid: function(message) {
initializeGrid(message) {
RemoteNewTabUtils.links.populateCache(() => {
message.target.sendAsyncMessage("NewTab:InitializeLinks", {
links: RemoteNewTabUtils.links.getLinks(),
Expand All @@ -78,6 +167,25 @@ let RemoteAboutNewTab = {
});
},

/**
* Sends the initial data payload to a content IFrame so it can bootstrap
*/
getInitialState: Task.async(function* (message) {
let placesLinks = yield PlacesProvider.links.getLinks();
let prefs = Services.prefs;
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: message.data.windowID,
privateBrowsingMode: message.data.privateBrowsingMode,
placesLinks
};
message.target.sendAsyncMessage("NewTab:State", state);
}),

/**
* Updates the grid by getting a new set of links.
*
Expand Down Expand Up @@ -147,7 +255,7 @@ let RemoteAboutNewTab = {
let canvas = doc.createElementNS(XHTML_NAMESPACE, "canvas");
let enhanced = Services.prefs.getBoolPref("browser.newtabpage.enhanced");

img.onload = function(e) { // jshint ignore:line
img.onload = function() {
canvas.width = img.naturalWidth;
canvas.height = img.naturalHeight;
var ctx = canvas.getContext("2d");
Expand Down Expand Up @@ -179,14 +287,14 @@ let RemoteAboutNewTab = {
},

/**
* 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.
* Listens for a preference change, a session purge for all pages, or if the
* current search engine is modified, 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;
let refreshPage = false;
if (aTopic === "browser:purge-session-history") {
RemoteNewTabUtils.links.resetCache();
RemoteNewTabUtils.links.populateCache(() => {
Expand All @@ -195,14 +303,39 @@ let RemoteAboutNewTab = {
enhancedLinks: this.getEnhancedLinks(),
});
});
} else if (aTopic === "browser-search-engine-modified" && aData === "engine-current") {
Task.spawn(function* () {
try {
let engine = yield SearchProvider.currentEngine;
this.pageListener.sendAsyncMessage("NewTab:ContentSearchService", {
engine, name: "CurrentEngine"
});
} catch (e) {
Cu.reportError(e);
}
}.bind(this));
} else if (aTopic === "nsPref:changed" && aData === "browser.search.hiddenOneOffs") {
Task.spawn(function* () {
try {
let state = yield SearchProvider.state;
this.pageListener.sendAsyncMessage("NewTab:ContentSearchService", {
state, name: "CurrentState"
});
} catch (e) {
Cu.reportError(e);
}
}.bind(this));
}

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});
this.pageListener.sendAsyncMessage("NewTab:Observe", {
topic: aTopic,
data: extraData
});
}
},

Expand All @@ -212,6 +345,12 @@ let RemoteAboutNewTab = {
_addObservers: function() {
Services.obs.addObserver(this, "page-thumbnail:create", true);
Services.obs.addObserver(this, "browser:purge-session-history", true);
Services.prefs.addObserver("browser.search.hiddenOneOffs", this, false);
Services.obs.addObserver(this, "browser-search-engine-modified", 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));
},

/**
Expand All @@ -220,10 +359,17 @@ let RemoteAboutNewTab = {
_removeObservers: function() {
Services.obs.removeObserver(this, "page-thumbnail:create");
Services.obs.removeObserver(this, "browser:purge-session-history");
Services.prefs.removeObserver("browser.search.hiddenOneOffs", this);
Services.obs.removeObserver(this, "browser-search-engine-modified");
PlacesProvider.links.off("deleteURI", this.placesDeleteURI);
PlacesProvider.links.off("clearHistory", this.placesClearHistory);
PlacesProvider.links.off("linkChanged", this.placesLinkChanged);
PlacesProvider.links.off("manyLinksChanged", this.placesManyLinksChanged);
},

QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
Ci.nsISupportsWeakReference]),
Ci.nsISupportsWeakReference
]),

uninit: function() {
this._removeObservers();
Expand Down