Bug 1298211 - Implement chrome.topSites, r=aswan
MozReview-Commit-ID: I043WQoDbrf
new file mode 100644
--- /dev/null
+++ b/toolkit/components/extensions/ext-topSites.js
@@ -0,0 +1,24 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+XPCOMUtils.defineLazyModuleGetter(this, "NewTabUtils",
+ "resource://gre/modules/NewTabUtils.jsm");
+
+extensions.registerSchemaAPI("topSites", "addon_parent", context => {
+ return {
+ topSites: {
+ get: function() {
+ let urls = NewTabUtils.links.getLinks()
+ .filter(link => !!link)
+ .map(link => {
+ return {
+ url: link.url,
+ title: link.title
+ };
+ });
+ return Promise.resolve(urls);
+ },
+ },
+ };
+});
--- a/toolkit/components/extensions/extensions-toolkit.manifest
+++ b/toolkit/components/extensions/extensions-toolkit.manifest
@@ -8,16 +8,17 @@ category webextension-scripts notificati
category webextension-scripts i18n chrome://extensions/content/ext-i18n.js
category webextension-scripts idle chrome://extensions/content/ext-idle.js
category webextension-scripts webRequest chrome://extensions/content/ext-webRequest.js
category webextension-scripts webNavigation chrome://extensions/content/ext-webNavigation.js
category webextension-scripts runtime chrome://extensions/content/ext-runtime.js
category webextension-scripts extension chrome://extensions/content/ext-extension.js
category webextension-scripts storage chrome://extensions/content/ext-storage.js
category webextension-scripts test chrome://extensions/content/ext-test.js
+category webextension-scripts topSites chrome://extensions/content/ext-topSites.js
# scripts specific for content process.
category webextension-scripts-content extension chrome://extensions/content/ext-c-extension.js
category webextension-scripts-content i18n chrome://extensions/content/ext-i18n.js
category webextension-scripts-content runtime chrome://extensions/content/ext-c-runtime.js
# scripts that must run in the same process as addon code.
category webextension-scripts-addon extension chrome://extensions/content/ext-c-extension.js
@@ -34,10 +35,11 @@ category webextension-schemas extension_
category webextension-schemas i18n chrome://extensions/content/schemas/i18n.json
category webextension-schemas idle chrome://extensions/content/schemas/idle.json
category webextension-schemas management chrome://extensions/content/schemas/management.json
category webextension-schemas native_host_manifest chrome://extensions/content/schemas/native_host_manifest.json
category webextension-schemas notifications chrome://extensions/content/schemas/notifications.json
category webextension-schemas runtime chrome://extensions/content/schemas/runtime.json
category webextension-schemas storage chrome://extensions/content/schemas/storage.json
category webextension-schemas test chrome://extensions/content/schemas/test.json
+category webextension-schemas top_sites chrome://extensions/content/schemas/top_sites.json
category webextension-schemas web_navigation chrome://extensions/content/schemas/web_navigation.json
category webextension-schemas web_request chrome://extensions/content/schemas/web_request.json
--- a/toolkit/components/extensions/jar.mn
+++ b/toolkit/components/extensions/jar.mn
@@ -13,10 +13,11 @@ toolkit.jar:
content/extensions/ext-i18n.js
content/extensions/ext-idle.js
content/extensions/ext-webRequest.js
content/extensions/ext-webNavigation.js
content/extensions/ext-runtime.js
content/extensions/ext-extension.js
content/extensions/ext-storage.js
content/extensions/ext-test.js
+ content/extensions/ext-topSites.js
content/extensions/ext-c-extension.js
content/extensions/ext-c-runtime.js
--- a/toolkit/components/extensions/schemas/jar.mn
+++ b/toolkit/components/extensions/schemas/jar.mn
@@ -15,10 +15,11 @@ toolkit.jar:
content/extensions/schemas/idle.json
content/extensions/schemas/management.json
content/extensions/schemas/manifest.json
content/extensions/schemas/native_host_manifest.json
content/extensions/schemas/notifications.json
content/extensions/schemas/runtime.json
content/extensions/schemas/storage.json
content/extensions/schemas/test.json
+ content/extensions/schemas/top_sites.json
content/extensions/schemas/web_navigation.json
content/extensions/schemas/web_request.json
new file mode 100644
--- /dev/null
+++ b/toolkit/components/extensions/schemas/top_sites.json
@@ -0,0 +1,66 @@
+/* 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/. */
+
+[
+ {
+ "namespace": "manifest",
+ "types": [
+ {
+ "$extend": "Permission",
+ "choices": [{
+ "type": "string",
+ "enum": [
+ "topSites"
+ ]
+ }]
+ }
+ ]
+ },
+ {
+ "namespace": "topSites",
+ "description": "Use the chrome.topSites API to access the top sites that are displayed on the new tab page. ",
+ "permissions": ["topSites"],
+ "types": [
+ {
+ "id": "MostVisitedURL",
+ "type": "object",
+ "description": "An object encapsulating a most visited URL, such as the URLs on the new tab page.",
+ "properties": {
+ "url": {
+ "type": "string",
+ "description": "The most visited URL."
+ },
+ "title": {
+ "type": "string",
+ "optional": true,
+ "description": "The title of the page."
+ }
+ }
+ }
+ ],
+ "functions": [
+ {
+ "name": "get",
+ "type": "function",
+ "description": "Gets a list of top sites.",
+ "async": "callback",
+ "parameters": [
+ {
+ "name": "callback",
+ "type": "function",
+ "parameters": [
+ {
+ "name": "results",
+ "type": "array",
+ "items": {
+ "$ref": "MostVisitedURL"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+]
new file mode 100644
--- /dev/null
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_topSites.js
@@ -0,0 +1,82 @@
+Cu.import("resource://gre/modules/NewTabUtils.jsm");
+
+
+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 (observerMethodName, ...args) {
+ args.unshift(this);
+ for (let obs of this._observers) {
+ if (obs[observerMethodName])
+ obs[observerMethodName].apply(NewTabUtils.links, args);
+ }
+ },
+};
+
+function makeLinks(links) {
+ // Important: To avoid test failures due to clock jitter on Windows XP, call
+ // Date.now() once here, not each time through the loop.
+ let frecency = 0;
+ let now = Date.now() * 1000;
+ let places = [];
+ links.map((link, i) => {
+ places.push({
+ url: link.url,
+ title: link.title,
+ lastVisitDate: now - i,
+ frecency: frecency++
+ });
+ });
+ return places;
+}
+
+add_task(function* test_topSites() {
+ let expect = [{url: "http://example.com/", title: "site#-1"},
+ {url: "http://example0.com/", title: "site#0"},
+ {url: "http://example1.com/", title: "site#1"},
+ {url: "http://example2.com/", title: "site#2"},
+ {url: "http://example3.com/", title: "site#3"}];
+
+ let extension = ExtensionTestUtils.loadExtension({
+ manifest: {
+ "permissions": [
+ "topSites"
+ ]
+ },
+ background() {
+ browser.topSites.get(result => {
+ browser.test.sendMessage("done", result);
+ });
+ }
+ });
+
+
+ let expectedLinks = makeLinks(expect);
+ let provider = new TestProvider(done => done(expectedLinks));
+
+ NewTabUtils.initWithoutProviders();
+ NewTabUtils.links.addProvider(provider);
+
+ yield NewTabUtils.links.populateCache();
+
+ yield extension.startup();
+
+ let result = yield extension.awaitMessage("done");
+ Assert.deepEqual(expect, result, "got topSites");
+
+ yield extension.unload();
+
+ NewTabUtils.links.removeProvider(provider);
+});
--- a/toolkit/components/extensions/test/xpcshell/xpcshell.ini
+++ b/toolkit/components/extensions/test/xpcshell/xpcshell.ini
@@ -50,15 +50,16 @@ skip-if = release_or_beta
[test_ext_runtime_sendMessage_errors.js]
[test_ext_runtime_sendMessage_no_receiver.js]
[test_ext_runtime_sendMessage_self.js]
[test_ext_schemas.js]
[test_ext_schemas_api_injection.js]
[test_ext_schemas_allowed_contexts.js]
[test_ext_simple.js]
[test_ext_storage.js]
+[test_ext_topSites.js]
[test_getAPILevelForWindow.js]
[test_ext_legacy_extension_context.js]
[test_ext_legacy_extension_embedding.js]
[test_locale_converter.js]
[test_locale_data.js]
[test_native_messaging.js]
skip-if = os == "android"