Bug 1478870 - Add component-ified tooling, ordered onboarding and bug fixes to Activity Stream. r=ursula

MozReview-Commit-ID: K14RSdAbVH7

--HG--
extra : rebase_source : f84c082385d46e401bae2ff17a71bb5f54a932cf
This commit is contained in:
Ed Lee 2018-07-27 13:01:36 -07:00
Родитель 6cf31b8253
Коммит 8716065e9c
38 изменённых файлов: 247 добавлений и 204 удалений

Просмотреть файл

@ -20,7 +20,7 @@ const TOPIC_CONTENT_DOCUMENT_INTERACTIVE = "content-document-interactive";
// Automated tests ensure packaged locales are in this list. Copied output of:
// https://github.com/mozilla/activity-stream/blob/master/bin/render-activity-stream-html.js
const ACTIVITY_STREAM_LOCALES = "en-US ach an ar ast az be bg bn-BD bn-IN br bs ca cak crh cs cy da de dsb el en-CA en-GB eo es-AR es-CL es-ES es-MX et eu fa ff fi fr fy-NL ga-IE gd gl gn gu-IN he hi-IN hr hsb hu hy-AM ia id it ja ja-JP-mac ka kab kk km kn ko lij lo lt ltg lv mai mk ml mr ms my nb-NO ne-NP nl nn-NO oc pa-IN pl pt-BR pt-PT rm ro ru si sk sl sq sr sv-SE ta te th tl tr uk ur uz vi zh-CN zh-TW".split(" ");
const ACTIVITY_STREAM_BCP47 = "en-US ach an ar ast az be bg bn-BD bn-IN br bs ca cak crh cs cy da de dsb el en-CA en-GB eo es-AR es-CL es-ES es-MX et eu fa ff fi fr fy-NL ga-IE gd gl gn gu-IN he hi-IN hr hsb hu hy-AM ia id it ja ja-JP-macos ka kab kk km kn ko lij lo lt ltg lv mai mk ml mr ms my nb-NO ne-NP nl nn-NO oc pa-IN pl pt-BR pt-PT rm ro ru si sk sl sq sr sv-SE ta te th tl tr uk ur uz vi zh-CN zh-TW".split(" ");
const ABOUT_URL = "about:newtab";
const BASE_URL = "resource://activity-stream/";
@ -35,7 +35,6 @@ const PREF_SEPARATE_PRIVILEGED_CONTENT_PROCESS = "browser.tabs.remote.separatePr
const PREF_ACTIVITY_STREAM_PRERENDER_ENABLED = "browser.newtabpage.activity-stream.prerender";
const PREF_ACTIVITY_STREAM_DEBUG = "browser.newtabpage.activity-stream.debug";
function AboutNewTabService() {
Services.obs.addObserver(this, TOPIC_APP_QUIT);
Services.obs.addObserver(this, TOPIC_LOCALES_CHANGE);
@ -103,9 +102,7 @@ AboutNewTabService.prototype = {
Ci.nsIAboutNewTabService,
Ci.nsIObserver
]),
_xpcom_categories: [{
service: true
}],
_xpcom_categories: [{service: true}],
observe(subject, topic, data) {
switch (topic) {
@ -121,7 +118,7 @@ AboutNewTabService.prototype = {
this.notifyChange();
}
break;
case TOPIC_CONTENT_DOCUMENT_INTERACTIVE:
case TOPIC_CONTENT_DOCUMENT_INTERACTIVE: {
const win = subject.defaultView;
// It seems like "content-document-interactive" is triggered multiple
@ -178,6 +175,7 @@ AboutNewTabService.prototype = {
};
subject.addEventListener("unload", onUnloaded, {once: true});
break;
}
case TOPIC_APP_QUIT:
this.uninit();
if (IS_MAIN_PROCESS) {
@ -277,17 +275,17 @@ AboutNewTabService.prototype = {
},
set newTabURL(aNewTabURL) {
aNewTabURL = aNewTabURL.trim();
if (aNewTabURL === ABOUT_URL) {
let newTabURL = aNewTabURL.trim();
if (newTabURL === ABOUT_URL) {
// avoid infinite redirects in case one sets the URL to about:newtab
this.resetNewTabURL();
return;
} else if (aNewTabURL === "") {
aNewTabURL = "about:blank";
} else if (newTabURL === "") {
newTabURL = "about:blank";
}
this.toggleActivityStream(false);
this._newTabURL = aNewTabURL;
this._newTabURL = newTabURL;
this._overridden = true;
this.notifyChange();
},
@ -311,11 +309,14 @@ AboutNewTabService.prototype = {
get activityStreamLocale() {
// Pick the best available locale to match the app locales
return Services.locale.negotiateLanguages(
Services.locale.getAppLocalesAsLangTags(),
ACTIVITY_STREAM_LOCALES,
Services.locale.getAppLocalesAsBCP47(),
ACTIVITY_STREAM_BCP47,
// defaultLocale's strings aren't necessarily packaged, but en-US' are
"en-US"
)[0];
"en-US",
Services.locale.langNegStrategyLookup
// Convert the BCP47 to lang tag, which is what is used in our paths, as a
// workaround for bug 1478930 negotiating incorrectly with lang tags
)[0].replace(/^(ja-JP-mac)os$/, "$1");
},
resetNewTabURL() {

Просмотреть файл

@ -26,7 +26,7 @@ else
FIREFOX_PATH=${AS_PINE_TEST_DIR}/mozilla-central
fi
MC_MODULE_PATH="$FIREFOX_PATH/browser/extensions/activity-stream"
MC_MODULE_PATH="$FIREFOX_PATH/browser/components/newtab"
# By default, just use mozilla-central + the export. If ENABLE_MC_AS is set to
# 1, patch on top of mozilla-central + the export to turn on the AS pref and

Просмотреть файл

@ -1,21 +0,0 @@
#! /usr/bin/env node
"use strict";
const MIN_FIREFOX_VERSION = "55.0a1";
/* globals cd, mv, sed */
require("shelljs/global");
cd(process.argv[2]);
// Convert install.rdf.in to install.rdf without substitutions
mv("install.rdf.in", "install.rdf");
sed("-i", /^#filter substitution/, "", "install.rdf");
sed("-i", /(<em:minVersion>).+(<\/em:minVersion>)/, `$1${MIN_FIREFOX_VERSION}$2`, "install.rdf");
sed("-i", /(<em:maxVersion>).+(<\/em:maxVersion>)/, "$1*$2", "install.rdf");
// Convert jar.mn to chrome.manifest with just manifest
mv("jar.mn", "chrome.manifest");
sed("-i", /^[^%].*$/, "", "chrome.manifest");
sed("-i", /^% (content.*) %(.*)$/, "$1 $2", "chrome.manifest");
sed("-i", /^% (resource.*) %.*$/, "$1 .", "chrome.manifest");

Просмотреть файл

@ -245,8 +245,11 @@ function main() { // eslint-disable-line max-statements
console.log("\x1b[33m", `Skipped the following locales because they are not in CENTRAL_LOCALES: ${extraLocales.join(", ")}`, "\x1b[0m");
}
// Convert ja-JP-mac lang tag to ja-JP-macos bcp47 to work around bug 1478930
const bcp47String = localizedLocales.join(" ").replace(/(ja-JP-mac)/, "$1os");
// Provide some help to copy/paste locales if tests are failing
console.log(`\nIf aboutNewTabService tests are failing for unexpected locales, make sure its list is updated:\nconst ACTIVITY_STREAM_LOCALES = "${localizedLocales.join(" ")}".split(" ");`);
console.log(`\nIf aboutNewTabService tests are failing for unexpected locales, make sure its list is updated:\nconst ACTIVITY_STREAM_BCP47 = "${bcp47String}".split(" ");`);
}
main();

Просмотреть файл

@ -1,62 +0,0 @@
#! /usr/bin/env node
/* globals cd, sed */
"use strict";
/**
* Generate update install.rdf.in in the given directory with a version string
* composed of YYYY.MM.DD.${minuteOfDay}-${github_commit_hash}.
*
* @note The github hash is taken from the github repo in the current directory
* the script is run in.
*
* @note The minute of the day was chosen so that the version number is
* (more-or-less) consistently increasing (modulo clock-skew and builds that
* happen within a minute of each other), and although it's UTC, it won't likely
* be confused with something in a readers own time zone.
*
* @example generated version string: 2017.08.28.1217-ebda466c
*/
const process = require("process");
require("shelljs/global");
const simpleGit = require("simple-git")(process.cwd());
const time = new Date();
const minuteOfDay = time.getUTCHours() * 60 + time.getUTCMinutes();
/**
* Return the given string padded with 0s out to the given width.
*
* XXX we should ditch this function in favor of using padStart once
* we start requiring Node 8.
*
* @param {any} s - the string to pad, will be coerced to String first
* @param {Number} width - what's the desired width?
*/
function zeroPadStart(s, width) {
let padded = String(s);
while (padded.length < width) {
padded = `0${padded}`;
}
return padded;
}
// git rev-parse --short HEAD
simpleGit.revparse(["--short", "HEAD"], (err, gitHash) => {
if (err) {
// eslint-disable-next-line no-console
console.error(`SimpleGit.revparse failed: ${err}`);
throw new Error(`SimpleGit.revparse failed: ${err}`);
}
// eslint-disable-next-line prefer-template
let versionString = String(time.getUTCFullYear()) +
"." + zeroPadStart(time.getUTCMonth() + 1, 2) +
"." + zeroPadStart(time.getUTCDate(), 2) +
"." + zeroPadStart(minuteOfDay, 4) +
"-" + gitHash.trim();
cd(process.argv[2]);
sed("-i", /(<em:version>).+(<\/em:version>)$/, `$1${versionString}$2`,
"install.rdf.in");
});

Просмотреть файл

@ -7,6 +7,8 @@ Field name | Type | Required | Description | Example / Note
`publish_start` | `date` | No | When to start showing the message | `1524474850876`
`publish_end` | `date` | No | When to stop showing the message | `1524474850876`
`content` | `object` | Yes | An object containing all variables/props to be rendered in the template. Subset of allowed tags detailed below. | [See example below](#html-subset)
`bundled` | `integer` | No | The number of messages of the same template this one should be shown with | [See example below](#a-bundled-message-example)
`order` | `integer` | No | If bundled with other messages of the same template, which order should this one be placed in? Defaults to 0 if no order is desired | [See example below](#a-bundled-message-example)
`campaign` | `string` | No | Campaign id that the message belongs to | `RustWebAssembly`
`targeting` | `string` `JEXL` | No | A [JEXL expression](http://normandy.readthedocs.io/en/latest/user/filter_expressions.html#jexl-basics) with all targeting information needed in order to decide if the message is shown | Not yet implemented, [Examples](#targeting-attributes)
`trigger` | `string` | No | An event or condition upon which the message will be immediately shown. This can be combined with `targeting`. Messages that define a trigger will not be shown during non-trigger-based passive message rotation.
@ -31,6 +33,35 @@ Field name | Type | Required | Description | Example / Note
}
```
### A Bundled Message example
The following 2 messages have a `bundled` property, indicating that they should be shown together, since they have the same template. The number `2` indicates that this message should be shown in a bundle of 2 messages of the same template. The order property defines that ONBOARDING_2 should be shown after ONBOARDING_3 in the bundle.
```javascript
{
id: "ONBOARDING_2",
template: "onboarding",
bundled: 2,
order: 2,
content: {
title: "Private Browsing",
body: "Browse by yourself. Private Browsing with Tracking Protection blocks online trackers that follow you around the web."
},
targeting: "",
trigger: "firstRun"
}
{
id: "ONBOARDING_3",
template: "onboarding",
bundled: 2,
order: 1,
content: {
title: "Find it faster",
body: "Access all of your favorite search engines with a click. Search the whole Web or just one website from the search box."
},
targeting: "",
trigger: "firstRun"
}
```
### HTML subset
The following tags are allowed in the content of the snippet: `i, b, u, strong, em, br`.

Просмотреть файл

@ -21,6 +21,15 @@
"description": "An id matching an existing Activity Stream Router template",
"enum": ["simple_snippet"]
},
"bundled": {
"type": "integer",
"description": "The number of messages of the same template this one should be shown with (optional)"
},
"order": {
"type": "integer",
"minimum": 0,
"description": "If bundled with other messages of the same template, which order should this one be placed in? (optional - defaults to 0)"
},
"content": {
"type": "object",
"description": "An object containing all variables/props to be rendered in the template. See individual template schemas for details."

Просмотреть файл

@ -18,7 +18,7 @@ and make sure the `browser.newtabpage.activity-stream.enabled` pref is set to `t
## Source code and submitting pull requests
A copy of the code in the [system-addon/](../../system-addon/) subdirectory of this repository
is exported to Mozilla central on a regular basis, which can be found at [browser/extensions/activity-stream](https://searchfox.org/mozilla-central/source/browser/extensions/activity-stream).
is exported to Mozilla central on a regular basis, which can be found at [browser/components/newtab](https://searchfox.org/mozilla-central/source/browser/components/newtab).
Keep in mind that some of these files are generated, so if you intend on editing any files, you should
do so in the Github version.

Просмотреть файл

@ -18,10 +18,11 @@ const ONE_HOUR_IN_MS = 60 * 60 * 1000;
const SNIPPETS_ENDPOINT_PREF = "browser.newtabpage.activity-stream.asrouter.snippetsUrl";
// List of hosts for endpoints that serve router messages.
// Key is allowed host, value is a name for the endpoint host.
const WHITELIST_HOSTS = {
const DEFAULT_WHITELIST_HOSTS = {
"activity-stream-icons.services.mozilla.com": "production",
"snippets-admin.mozilla.org": "preview"
};
const SNIPPETS_ENDPOINT_WHITELIST = "browser.newtab.activity-stream.asrouter.whitelistHosts";
const MessageLoaderUtils = {
/**
@ -229,6 +230,7 @@ class _ASRouter {
this.messageChannel.addMessageListener(INCOMING_MESSAGE_NAME, this.onMessage);
this._addASRouterPrefListener();
this._storage = storage;
this.WHITELIST_HOSTS = this._loadSnippetsWhitelistHosts();
const blockList = await this._storage.get("blockList") || [];
const impressions = await this._storage.get("impressions") || {};
@ -283,8 +285,12 @@ class _ASRouter {
return message;
}
_orderBundle(bundle) {
return bundle.sort((a, b) => a.order - b.order);
}
async _getBundledMessages(originalMessage, target, data, force = false) {
let result = [{content: originalMessage.content, id: originalMessage.id}];
let result = [{content: originalMessage.content, id: originalMessage.id, order: originalMessage.order || 0}];
// First, find all messages of same template. These are potential matching targeting candidates
let bundledMessagesOfSameTemplate = this._getUnblockedMessages()
@ -309,7 +315,7 @@ class _ASRouter {
}
// Only copy the content of the message (that's what the UI cares about)
// Also delete the message we picked so we don't pick it again
result.push({content: message.content, id: message.id});
result.push({content: message.content, id: message.id, order: message.order || 0});
bundledMessagesOfSameTemplate.splice(bundledMessagesOfSameTemplate.findIndex(msg => msg.id === message.id), 1);
// Stop once we have enough messages to fill a bundle
if (result.length === originalMessage.bundled) {
@ -322,7 +328,8 @@ class _ASRouter {
if (result.length < originalMessage.bundled) {
return null;
}
return {bundle: result, provider: originalMessage.provider, template: originalMessage.template};
return {bundle: this._orderBundle(result), provider: originalMessage.provider, template: originalMessage.template};
}
_getUnblockedMessages() {
@ -468,18 +475,42 @@ class _ASRouter {
_validPreviewEndpoint(url) {
try {
const endpoint = new URL(url);
if (!WHITELIST_HOSTS[endpoint.host]) {
if (!this.WHITELIST_HOSTS[endpoint.host]) {
Cu.reportError(`The preview URL host ${endpoint.host} is not in the whitelist.`);
}
if (endpoint.protocol !== "https:") {
Cu.reportError("The URL protocol is not https.");
}
return (endpoint.protocol === "https:" && WHITELIST_HOSTS[endpoint.host]);
return (endpoint.protocol === "https:" && this.WHITELIST_HOSTS[endpoint.host]);
} catch (e) {
return false;
}
}
_loadSnippetsWhitelistHosts() {
let additionalHosts = [];
const whitelistPrefValue = Services.prefs.getStringPref(SNIPPETS_ENDPOINT_WHITELIST, "");
try {
additionalHosts = JSON.parse(whitelistPrefValue);
} catch (e) {
if (whitelistPrefValue) {
Cu.reportError(`Pref ${SNIPPETS_ENDPOINT_WHITELIST} value is not valid JSON`);
}
}
if (!additionalHosts.length) {
return DEFAULT_WHITELIST_HOSTS;
}
// If there are additional hosts we want to whitelist, add them as
// `preview` so that the updateCycle is 0
return additionalHosts.reduce((whitelist_hosts, host) => {
whitelist_hosts[host] = "preview";
Services.console.logStringMessage(`Adding ${host} to whitelist hosts.`);
return whitelist_hosts;
}, {...DEFAULT_WHITELIST_HOSTS});
}
async _addPreviewEndpoint(url) {
const providers = [...this.state.providers];
if (this._validPreviewEndpoint(url) && !providers.find(p => p.url === url)) {

Просмотреть файл

@ -40,6 +40,11 @@ const TopFrecentSitesCache = {
}
resolve(this._topFrecentSites);
});
},
// For testing
expire() {
this._lastUpdated = 0;
this._topFrecentSites = null;
}
};
@ -215,4 +220,6 @@ this.ASRouterTargeting = {
}
};
this.EXPORTED_SYMBOLS = ["ASRouterTargeting", "removeRandomItemFromArray"];
// Export for testing
this.TopFrecentSitesCache = TopFrecentSitesCache;
this.EXPORTED_SYMBOLS = ["ASRouterTargeting", "TopFrecentSitesCache"];

Просмотреть файл

@ -5,6 +5,7 @@
"use strict";
ChromeUtils.import("resource:///modules/AboutNewTab.jsm");
/* globals RemotePages */ // Remove when updating eslint-plugin-mozilla 0.14.0+
ChromeUtils.import("resource://gre/modules/remotepagemanager/RemotePageManagerParent.jsm");
const {actionCreators: ac, actionTypes: at, actionUtils: au} = ChromeUtils.import("resource://activity-stream/common/Actions.jsm", {});

Просмотреть файл

@ -8,6 +8,7 @@ const ONBOARDING_MESSAGES = [
id: "ONBOARDING_1",
template: "onboarding",
bundled: 3,
order: 2,
content: {
title: "Private Browsing",
text: "Browse by yourself. Private Browsing with Tracking Protection blocks online trackers that follow you around the web.",
@ -21,6 +22,7 @@ const ONBOARDING_MESSAGES = [
id: "ONBOARDING_2",
template: "onboarding",
bundled: 3,
order: 3,
content: {
title: "Screenshots",
text: "Take, save and share screenshots - without leaving Firefox. Capture a region or an entire page as you browse. Then save to the web for easy access and sharing.",
@ -35,6 +37,7 @@ const ONBOARDING_MESSAGES = [
id: "ONBOARDING_3",
template: "onboarding",
bundled: 3,
order: 1,
content: {
title: "Add-ons",
text: "Add even more features that make Firefox work harder for you. Compare prices, check the weather or express your personality with a custom theme.",
@ -50,11 +53,12 @@ const ONBOARDING_MESSAGES = [
id: "ONBOARDING_4",
template: "onboarding",
bundled: 3,
order: 1,
content: {
title: "Extensions",
text: "Make browsing faster, smarter, or safer with browser apps. Protect passwords, find deals, download videos, and much more. You can even block annoying ads with extensions like Ghostery.",
title: "Block Ads with Ghostery",
text: "Browse faster, smarter, or safer with extensions like Ghostery, which lets you block annoying ads.",
icon: "gift",
button_label: "Get Ghostery",
button_label: "Try It Now",
button_action: "OPEN_URL",
button_action_params: "https://addons.mozilla.org/en-US/firefox/addon/ghostery/"
},

Просмотреть файл

@ -105,7 +105,7 @@ prefs_highlights_options_visited_label=Baxılmış Səhifələr
prefs_highlights_options_download_label=Son Endirmələr
prefs_highlights_options_pocket_label=Pocket-ə Saxlanılan Səhifələr
prefs_snippets_description=Mozilla və Firefoxdan yeniliklər
settings_pane_button_label=Yeni Vərəq səhifənizi özəlləşdirin
settings_pane_button_label=Yeni Vərəq səhifənizi fərdiləşdirin
settings_pane_topsites_header=Qabaqcıl Saytlar
settings_pane_highlights_header=Seçilmişlər
settings_pane_highlights_options_bookmarks=Əlfəcinlər

Просмотреть файл

@ -206,6 +206,8 @@ firstrun_form_sub_header=for at fortsætte til Firefox Sync.
firstrun_email_input_placeholder=Mailadresse
firstrun_invalid_input=En gyldig mailadresse er påkrævet
# LOCALIZATION NOTE (firstrun_extra_legal_links): {terms} is equal to firstrun_terms_of_service, and
# {privacy} is equal to firstrun_privacy_notice. {terms} and {privacy} are clickable links.
firstrun_extra_legal_links=Ved at fortsætte godkender du vores {terms} og {privacy}.

Просмотреть файл

@ -191,6 +191,7 @@ firstrun_form_sub_header=para acceder a Firefox Sync.
firstrun_email_input_placeholder=Correo electrónico
firstrun_invalid_input=Se requiere un correo válido
# LOCALIZATION NOTE (firstrun_extra_legal_links): {terms} is equal to firstrun_terms_of_service, and
# {privacy} is equal to firstrun_privacy_notice. {terms} and {privacy} are clickable links.

Просмотреть файл

@ -191,6 +191,8 @@ firstrun_form_sub_header=eike hag̃ua Firefox Sync-pe.
firstrun_email_input_placeholder=Ñandutiveve
firstrun_invalid_input=Eikotevẽ peteĩ ñanduti veve oikóva
# LOCALIZATION NOTE (firstrun_extra_legal_links): {terms} is equal to firstrun_terms_of_service, and
# {privacy} is equal to firstrun_privacy_notice. {terms} and {privacy} are clickable links.
firstrun_extra_legal_links=Ejapóva, emoneĩ ko'ã {terms} ha {privacy}.

Просмотреть файл

@ -191,6 +191,8 @@ firstrun_form_sub_header=Firefox Sync の利用を続けるために必要です
firstrun_email_input_placeholder=メールアドレス
firstrun_invalid_input=メールアドレスを正しく入力してください
# LOCALIZATION NOTE (firstrun_extra_legal_links): {terms} is equal to firstrun_terms_of_service, and
# {privacy} is equal to firstrun_privacy_notice. {terms} and {privacy} are clickable links.
firstrun_extra_legal_links=続行すると、{terms} と {privacy} に同意したものとみなします。

Просмотреть файл

@ -191,6 +191,8 @@ firstrun_form_sub_header=Firefox Sync の利用を続けるために必要です
firstrun_email_input_placeholder=メールアドレス
firstrun_invalid_input=メールアドレスを正しく入力してください
# LOCALIZATION NOTE (firstrun_extra_legal_links): {terms} is equal to firstrun_terms_of_service, and
# {privacy} is equal to firstrun_privacy_notice. {terms} and {privacy} are clickable links.
firstrun_extra_legal_links=続行すると、{terms} と {privacy} に同意したものとみなします。

Просмотреть файл

@ -191,6 +191,8 @@ firstrun_form_sub_header=பயர்பாக்சு ஒத்திசைய
firstrun_email_input_placeholder=மின்னஞ்சல்
firstrun_invalid_input=நம்பகரமான மின்னஞ்சல் தேவை
# LOCALIZATION NOTE (firstrun_extra_legal_links): {terms} is equal to firstrun_terms_of_service, and
# {privacy} is equal to firstrun_privacy_notice. {terms} and {privacy} are clickable links.
firstrun_extra_legal_links=தொடர்வதன் மூலம், தாங்கள் {terms} மற்றும் {privacy} ஒப்புக்கொள்கின்றீர்கள்.

Просмотреть файл

@ -40,7 +40,7 @@ confirm_history_delete_p1=您確定要刪除此頁面的所有瀏覽紀錄?
# LOCALIZATION NOTE (confirm_history_delete_notice_p2): this string is displayed in
# the same dialog as confirm_history_delete_p1. "This action" refers to deleting a
# page from history.
confirm_history_delete_notice_p2=無法還原此操作
confirm_history_delete_notice_p2=此動作無法復原
menu_action_save_to_pocket=儲存至 Pocket
menu_action_delete_pocket=從 Pocket 刪除
menu_action_archive_pocket=在 Pocket 裡封存
@ -155,7 +155,7 @@ topstories_empty_state=所有文章都讀完啦!晚點再來,{provider} 將
manual_migration_explanation2=試試將其他瀏覽器的書籤、瀏覽記錄與密碼匯入 Firefox。
# LOCALIZATION NOTE (manual_migration_cancel_button): This message is shown on a button that cancels the
# process of importing another browsers profile into Firefox.
manual_migration_cancel_button=必了
manual_migration_cancel_button=要,謝謝
# LOCALIZATION NOTE (manual_migration_import_button): This message is shown on a button that starts the process
# of importing another browsers profile profile into Firefox.
manual_migration_import_button=立即匯入
@ -187,7 +187,7 @@ firstrun_learn_more_link=了解 Firefox Accounts 的更多資訊
# firstrun_form_sub_header is a continuation of firstrun_form_header, they are one sentence.
# firstrun_form_header is displayed more boldly as the call to action.
firstrun_form_header=輸入您的電子郵件地址
firstrun_form_sub_header=繼續前往 Firefox Sync
firstrun_form_sub_header=繼續前往 Firefox Sync
firstrun_email_input_placeholder=電子郵件

Просмотреть файл

@ -15,7 +15,6 @@ cd /activity-stream && npm install . && npm run buildmc
cd /mozilla-central && ./mach build \
&& ./mach test browser_parsable_css \
&& ./mach lint -l eslint -l codespell browser/components/newtab \
&& ./mach test browser/components/newtab --headless \
&& ./mach test browser/components/newtab/test/browser --headless \
&& ./mach test browser/components/newtab/test/xpcshell \
&& ./mach test browser/components/preferences/in-content/tests/browser_hometab_restore_defaults.js --headless \

Просмотреть файл

@ -90,27 +90,26 @@
"mc_dir": "../mozilla-central"
},
"scripts": {
"mochitest": "(cd $npm_package_config_mc_dir && ./mach mochitest browser/extensions/activity-stream/test/functional/mochitest --headless)",
"mochitest-debug": "(cd $npm_package_config_mc_dir && ./mach mochitest --jsdebugger browser/extensions/activity-stream/test/functional/mochitest)",
"mochitest": "(cd $npm_package_config_mc_dir && ./mach mochitest browser/components/newtab/test/browser --headless)",
"mochitest-debug": "(cd $npm_package_config_mc_dir && ./mach mochitest --jsdebugger browser/components/newtab/test/browser)",
"bundle": "npm-run-all bundle:*",
"bundle:locales": "pontoon-to-json --src locales --dest data",
"bundle:webpack": "webpack --config webpack.system-addon.config.js",
"bundle:css": "node-sass --source-map true --source-map-contents content-src/styles -o css",
"bundle:html": "rimraf prerendered && webpack --config webpack.prerender.config.js && node ./bin/render-activity-stream-html.js",
"buildmc": "npm-run-all buildmc:*",
"prebuildmc": "rimraf $npm_package_config_mc_dir/browser/extensions/activity-stream/",
"prebuildmc": "rimraf $npm_package_config_mc_dir/browser/components/newtab/",
"buildmc:bundle": "npm run bundle",
"buildmc:copy": "rsync --exclude-from .mcignore -a . $npm_package_config_mc_dir/browser/extensions/activity-stream/",
"buildmc:version": "node ./bin/update-version.js $npm_package_config_mc_dir/browser/extensions/activity-stream",
"buildmc:copy": "rsync --exclude-from .mcignore -a . $npm_package_config_mc_dir/browser/components/newtab/",
"buildmc:stringsExport": "cp locales/en-US/strings.properties $npm_package_config_mc_dir/browser/locales/en-US/chrome/browser/activity-stream/newtab.properties",
"buildmc:copyPingCentre": "cpx \"ping-centre/PingCentre.jsm\" $npm_package_config_mc_dir/browser/modules",
"startmc": "npm-run-all --parallel startmc:*",
"prestartmc": "npm run buildmc",
"startmc:copy": "cpx \"{{,.}*,!(node_modules)/**/{,.}*}\" $npm_package_config_mc_dir/browser/extensions/activity-stream/ -w",
"startmc:copy": "cpx \"{{,.}*,!(node_modules)/**/{,.}*}\" $npm_package_config_mc_dir/browser/components/newtab/ -w",
"startmc:copyPingCentre": "npm run buildmc:copyPingCentre -- -w",
"startmc:webpack": "npm run bundle:webpack -- -w",
"startmc:css": "npm run bundle:css && npm run bundle:css -- -w",
"importmc": "rsync --exclude-from .mcignore -a $npm_package_config_mc_dir/browser/extensions/activity-stream/ .",
"importmc": "rsync --exclude-from .mcignore -a $npm_package_config_mc_dir/browser/components/newtab/ .",
"testmc": "npm-run-all testmc:*",
"testmc:lint": "npm run lint",
"testmc:build": "npm run bundle:webpack && npm run bundle:locales",

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -51,7 +51,7 @@ window.gActivityStreamStrings = {
"prefs_highlights_options_download_label": "Son Endirmələr",
"prefs_highlights_options_pocket_label": "Pocket-ə Saxlanılan Səhifələr",
"prefs_snippets_description": "Mozilla və Firefoxdan yeniliklər",
"settings_pane_button_label": "Yeni Vərəq səhifənizi özəlləşdirin",
"settings_pane_button_label": "Yeni Vərəq səhifənizi fərdiləşdirin",
"settings_pane_topsites_header": "Qabaqcıl Saytlar",
"settings_pane_highlights_header": "Seçilmişlər",
"settings_pane_highlights_options_bookmarks": "Əlfəcinlər",

Просмотреть файл

@ -96,7 +96,7 @@ window.gActivityStreamStrings = {
"firstrun_form_header": "Indtast din mailadresse",
"firstrun_form_sub_header": "for at fortsætte til Firefox Sync.",
"firstrun_email_input_placeholder": "Mailadresse",
"firstrun_invalid_input": "Valid email required",
"firstrun_invalid_input": "En gyldig mailadresse er påkrævet",
"firstrun_extra_legal_links": "Ved at fortsætte godkender du vores {terms} og {privacy}.",
"firstrun_terms_of_service": "tjenestevilkår",
"firstrun_privacy_notice": "privatlivspolitik",

Просмотреть файл

@ -96,7 +96,7 @@ window.gActivityStreamStrings = {
"firstrun_form_header": "Emoinge ne ñandutiveve",
"firstrun_form_sub_header": "eike hag̃ua Firefox Sync-pe.",
"firstrun_email_input_placeholder": "Ñandutiveve",
"firstrun_invalid_input": "Valid email required",
"firstrun_invalid_input": "Eikotevẽ peteĩ ñanduti veve oikóva",
"firstrun_extra_legal_links": "Ejapóva, emoneĩ ko'ã {terms} ha {privacy}.",
"firstrun_terms_of_service": "Mba'epytyvõrã ñemboguata",
"firstrun_privacy_notice": "Ñemigua purureko",

Просмотреть файл

@ -96,7 +96,7 @@ window.gActivityStreamStrings = {
"firstrun_form_header": "メールアドレスを入力してください",
"firstrun_form_sub_header": "Firefox Sync の利用を続けるために必要です",
"firstrun_email_input_placeholder": "メールアドレス",
"firstrun_invalid_input": "Valid email required",
"firstrun_invalid_input": "メールアドレスを正しく入力してください",
"firstrun_extra_legal_links": "続行すると、{terms} と {privacy} に同意したものとみなします。",
"firstrun_terms_of_service": "サービス利用規約",
"firstrun_privacy_notice": "プライバシーに関する通知",

Просмотреть файл

@ -96,7 +96,7 @@ window.gActivityStreamStrings = {
"firstrun_form_header": "メールアドレスを入力してください",
"firstrun_form_sub_header": "Firefox Sync の利用を続けるために必要です",
"firstrun_email_input_placeholder": "メールアドレス",
"firstrun_invalid_input": "Valid email required",
"firstrun_invalid_input": "メールアドレスを正しく入力してください",
"firstrun_extra_legal_links": "続行すると、{terms} と {privacy} に同意したものとみなします。",
"firstrun_terms_of_service": "サービス利用規約",
"firstrun_privacy_notice": "プライバシーに関する通知",

Просмотреть файл

@ -96,7 +96,7 @@ window.gActivityStreamStrings = {
"firstrun_form_header": "உங்களின் மின்னஞ்சலை உள்ளிடுக",
"firstrun_form_sub_header": "பயர்பாக்சு ஒத்திசையைத் தொடர.",
"firstrun_email_input_placeholder": "மின்னஞ்சல்",
"firstrun_invalid_input": "Valid email required",
"firstrun_invalid_input": "நம்பகரமான மின்னஞ்சல் தேவை",
"firstrun_extra_legal_links": "தொடர்வதன் மூலம், தாங்கள் {terms} மற்றும் {privacy} ஒப்புக்கொள்கின்றீர்கள்.",
"firstrun_terms_of_service": "சேவையின் விதிமுறைகள்",
"firstrun_privacy_notice": "தனியுரிமை அறிவிப்பு",

Просмотреть файл

@ -20,7 +20,7 @@ window.gActivityStreamStrings = {
"menu_action_pin": "釘選",
"menu_action_unpin": "取消釘選",
"confirm_history_delete_p1": "您確定要刪除此頁面的所有瀏覽紀錄?",
"confirm_history_delete_notice_p2": "無法還原此操作。",
"confirm_history_delete_notice_p2": "此動作無法復原。",
"menu_action_save_to_pocket": "儲存至 Pocket",
"menu_action_delete_pocket": "從 Pocket 刪除",
"menu_action_archive_pocket": "在 Pocket 裡封存",
@ -77,7 +77,7 @@ window.gActivityStreamStrings = {
"highlights_empty_state": "開始上網,我們就會把您在網路上發現的好文章、影片、剛加入書籤的頁面顯示於此。",
"topstories_empty_state": "所有文章都讀完啦!晚點再來,{provider} 將提供更多推薦故事。等不及了?選擇熱門主題,看看 Web 上各式精采資訊。",
"manual_migration_explanation2": "試試將其他瀏覽器的書籤、瀏覽記錄與密碼匯入 Firefox。",
"manual_migration_cancel_button": "不必了",
"manual_migration_cancel_button": "不要,謝謝",
"manual_migration_import_button": "立即匯入",
"error_fallback_default_info": "唉唷,載入內容時發生錯誤。",
"error_fallback_default_refresh_suggestion": "請重新整理頁面再試一次。",
@ -94,7 +94,7 @@ window.gActivityStreamStrings = {
"firstrun_content": "在您的任何裝置上取得書籤、瀏覽紀錄、密碼及其他設定。",
"firstrun_learn_more_link": "了解 Firefox Accounts 的更多資訊",
"firstrun_form_header": "輸入您的電子郵件地址",
"firstrun_form_sub_header": "繼續前往 Firefox Sync",
"firstrun_form_sub_header": "繼續前往 Firefox Sync",
"firstrun_email_input_placeholder": "電子郵件",
"firstrun_invalid_input": "必須輸入有效的電子郵件地址",
"firstrun_extra_legal_links": "若繼續,代表您同意{terms}及{privacy}。",

Просмотреть файл

@ -1,5 +1,7 @@
ChromeUtils.defineModuleGetter(this, "ASRouterTargeting",
"resource://activity-stream/lib/ASRouterTargeting.jsm");
const {ASRouterTargeting, TopFrecentSitesCache} =
ChromeUtils.import("resource://activity-stream/lib/ASRouterTargeting.jsm", {});
const {AddonTestUtils} =
ChromeUtils.import("resource://testing-common/AddonTestUtils.jsm", {});
ChromeUtils.defineModuleGetter(this, "ProfileAge",
"resource://gre/modules/ProfileAge.jsm");
ChromeUtils.defineModuleGetter(this, "AddonManager",
@ -11,8 +13,6 @@ ChromeUtils.defineModuleGetter(this, "NewTabUtils",
ChromeUtils.defineModuleGetter(this, "PlacesTestUtils",
"resource://testing-common/PlacesTestUtils.jsm");
const {AddonTestUtils} = ChromeUtils.import("resource://testing-common/AddonTestUtils.jsm", {});
// ASRouterTargeting.isMatch
add_task(async function should_do_correct_targeting() {
is(await ASRouterTargeting.isMatch("FOO", {}, {FOO: true}), true, "should return true for a matching value");
@ -226,4 +226,8 @@ add_task(async function checkFrecentSites() {
message = {id: "foo", targeting: `(topFrecentSites[.frecency >= 900 && .lastVisitDate >= ${timeDaysAgo(1) - 1}]|mapToProperty('host') intersect ['mozilla3.com', 'mozilla2.com', 'mozilla1.com'])|length > 0`};
is(await ASRouterTargeting.findMatchingMessage({messages: [message], target: {}}), message,
"should select correct item when filtering by frecency and lastVisitDate with multiple candidate domains");
// Cleanup
await clearHistoryAndBookmarks();
TopFrecentSitesCache.expire();
});

Просмотреть файл

@ -7,10 +7,17 @@ XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService",
"@mozilla.org/browser/aboutnewtab-service;1",
"nsIAboutNewTabService");
registerCleanupFunction(function() {
registerCleanupFunction(() => {
aboutNewTabService.resetNewTabURL();
});
function nextChangeNotificationPromise(aNewURL, testMessage) {
return TestUtils.topicObserved("newtab-url-changed", function observer(aSubject, aData) { // jshint unused:false
Assert.equal(aData, aNewURL, testMessage);
return true;
});
}
/*
* Tests that the default newtab page is always returned when one types "about:newtab" in the URL bar,
* even when overridden.
@ -18,7 +25,7 @@ registerCleanupFunction(function() {
add_task(async function redirector_ignores_override() {
let overrides = [
"chrome://browser/content/aboutRobots.xhtml",
"about:home",
"about:home"
];
for (let overrideURL of overrides) {
@ -30,7 +37,7 @@ add_task(async function redirector_ignores_override() {
let tabOptions = {
gBrowser,
url: "about:newtab",
url: "about:newtab"
};
/*
@ -40,8 +47,8 @@ add_task(async function redirector_ignores_override() {
* due to invoking AboutRedirector. A user interacting with the chrome otherwise would lead
* to the overriding URLs.
*/
await BrowserTestUtils.withNewTab(tabOptions, async function(browser) {
await ContentTask.spawn(browser, {}, async function() {
await BrowserTestUtils.withNewTab(tabOptions, async browser => {
await ContentTask.spawn(browser, {}, async () => {
Assert.equal(content.location.href, "about:newtab", "Got right URL");
Assert.equal(content.document.location.href, "about:newtab", "Got right URL");
Assert.notEqual(content.document.nodePrincipal,
@ -59,7 +66,7 @@ add_task(async function override_loads_in_browser() {
let overrides = [
"chrome://browser/content/aboutRobots.xhtml",
"about:home",
" about:home",
" about:home"
];
for (let overrideURL of overrides) {
@ -75,7 +82,7 @@ add_task(async function override_loads_in_browser() {
let browser = gBrowser.selectedBrowser;
await BrowserTestUtils.browserLoaded(browser);
await ContentTask.spawn(browser, {url: overrideURL}, async function(args) {
await ContentTask.spawn(browser, {url: overrideURL}, async args => {
Assert.equal(content.location.href, args.url.trim(), "Got right URL");
Assert.equal(content.document.location.href, args.url.trim(), "Got right URL");
}); // jshint ignore:line
@ -91,7 +98,7 @@ add_task(async function override_blank_loads_in_browser() {
"",
" ",
"\n\t",
" about:blank",
" about:blank"
];
for (let overrideURL of overrides) {
@ -107,17 +114,10 @@ add_task(async function override_blank_loads_in_browser() {
let browser = gBrowser.selectedBrowser;
await BrowserTestUtils.browserLoaded(browser);
await ContentTask.spawn(browser, {}, async function() {
await ContentTask.spawn(browser, {}, async () => {
Assert.equal(content.location.href, "about:blank", "Got right URL");
Assert.equal(content.document.location.href, "about:blank", "Got right URL");
}); // jshint ignore:line
BrowserTestUtils.removeTab(gBrowser.selectedTab);
}
});
function nextChangeNotificationPromise(aNewURL, testMessage) {
return TestUtils.topicObserved("newtab-url-changed", function observer(aSubject, aData) { // jshint unused:false
Assert.equal(aData, aNewURL, testMessage);
return true;
});
}

Просмотреть файл

@ -59,7 +59,7 @@ add_task(async function test_all_packaged_locales() {
const locale = file.replace("/", "");
if (locale !== "static") {
const url = await getUrlForLocale(locale);
Assert[locale === "en-US" ? "equal" : "notEqual"](url, DEFAULT_URL, `can reference "${locale}" files`);
Assert.equal(url, DEFAULT_URL.replace("en-US", locale), `can reference "${locale}" files`);
// Specially remember if we saw an ID locale packaged as it can be
// easily ignored by source control, e.g., .gitignore

Просмотреть файл

@ -128,6 +128,22 @@ describe("ASRouter", () => {
assert.lengthOf(Router.state.providers, length);
assert.isDefined(provider);
});
it("should load additional whitelisted hosts", async () => {
getStringPrefStub.returns("[\"whitelist.com\"]");
await createRouterAndInit();
assert.propertyVal(Router.WHITELIST_HOSTS, "whitelist.com", "preview");
// Should still include the defaults
assert.lengthOf(Object.keys(Router.WHITELIST_HOSTS), 3);
});
it("should fallback to defaults if pref parsing fails", async () => {
getStringPrefStub.returns("err");
await createRouterAndInit();
assert.lengthOf(Object.keys(Router.WHITELIST_HOSTS), 2);
assert.propertyVal(Router.WHITELIST_HOSTS, "snippets-admin.mozilla.org", "preview");
assert.propertyVal(Router.WHITELIST_HOSTS, "activity-stream-icons.services.mozilla.com", "production");
});
});
describe("#loadMessagesFromAllProviders", () => {
@ -143,8 +159,10 @@ describe("ASRouter", () => {
getStringPrefStub.returns("example.com");
await createRouterAndInit();
assert.calledOnce(getStringPrefStub);
// Get snippets endpoint url, get the whitelisted hosts for endpoints
assert.calledTwice(getStringPrefStub);
assert.calledWithExactly(getStringPrefStub, "remotePref", "");
assert.calledWithExactly(getStringPrefStub, "browser.newtab.activity-stream.asrouter.whitelistHosts", "");
assert.isDefined(Router.state.providers.find(p => p.url === "example.com"));
});
it("should not trigger an update if not enough time has passed for a provider", async () => {
@ -248,6 +266,18 @@ describe("ASRouter", () => {
assert.equal(msg.target.sendAsyncMessage.firstCall.args[1].type, "SET_BUNDLED_MESSAGES");
assert.equal(msg.target.sendAsyncMessage.firstCall.args[1].data.bundle[0].content, currentMessage.content);
});
it("should properly order the message's bundle if specified", async () => {
// force the only messages to be a bundled messages so getRandomItemFromArray picks one of them
const firstMessage = {id: "foo2", template: "simple_template", bundled: 2, order: 1, content: {title: "Foo2", body: "Foo123-2"}};
const secondMessage = {id: "foo1", template: "simple_template", bundled: 2, order: 2, content: {title: "Foo1", body: "Foo123-1"}};
await Router.setState({messages: [secondMessage, firstMessage]});
const msg = fakeAsyncMessage({type: "CONNECT_UI_REQUEST"});
await Router.onMessage(msg);
assert.calledWith(msg.target.sendAsyncMessage, PARENT_TO_CHILD_MESSAGE_NAME);
assert.equal(msg.target.sendAsyncMessage.firstCall.args[1].type, "SET_BUNDLED_MESSAGES");
assert.equal(msg.target.sendAsyncMessage.firstCall.args[1].data.bundle[0].content, firstMessage.content);
assert.equal(msg.target.sendAsyncMessage.firstCall.args[1].data.bundle[1].content, secondMessage.content);
});
it("should return a null bundle if we do not have enough messages to fill the bundle", async () => {
// force the only message to be a bundled message that needs 2 messages in the bundle
await Router.setState({messages: [{id: "foo1", template: "simple_template", bundled: 2, content: {title: "Foo1", body: "Foo123-1"}}]});
@ -419,7 +449,7 @@ describe("ASRouter", () => {
const expectedObj = {
template: testMessage1.template,
provider: testMessage1.provider,
bundle: [{content: testMessage1.content, id: testMessage1.id}, {content: testMessage2.content, id: testMessage2.id}]
bundle: [{content: testMessage1.content, id: testMessage1.id, order: 1}, {content: testMessage2.content, id: testMessage2.id}]
};
assert.calledWith(msg.target.sendAsyncMessage, PARENT_TO_CHILD_MESSAGE_NAME, {type: "SET_BUNDLED_MESSAGES", data: expectedObj});
});
@ -434,7 +464,7 @@ describe("ASRouter", () => {
const expectedObj = {
template: testMessage1.template,
provider: testMessage1.provider,
bundle: [{content: testMessage1.content, id: testMessage1.id}, {content: testMessage2.content, id: testMessage2.id}]
bundle: [{content: testMessage1.content, id: testMessage1.id, order: 1}, {content: testMessage2.content, id: testMessage2.id, order: 2}]
};
assert.calledWith(msg.target.sendAsyncMessage, PARENT_TO_CHILD_MESSAGE_NAME, {type: "SET_BUNDLED_MESSAGES", data: expectedObj});
});

Просмотреть файл

@ -4,8 +4,8 @@ export const EXPERIMENT_PREF = "asrouterExperimentEnabled";
export const FAKE_LOCAL_MESSAGES = [
{id: "foo", template: "simple_template", content: {title: "Foo", body: "Foo123"}},
{id: "foo1", template: "simple_template", bundled: 2, content: {title: "Foo1", body: "Foo123-1"}},
{id: "foo2", template: "simple_template", bundled: 2, content: {title: "Foo2", body: "Foo123-2"}},
{id: "foo1", template: "simple_template", bundled: 2, order: 1, content: {title: "Foo1", body: "Foo123-1"}},
{id: "foo2", template: "simple_template", bundled: 2, order: 2, content: {title: "Foo2", body: "Foo123-2"}},
{id: "bar", template: "fancy_template", content: {title: "Foo", body: "Foo123"}},
{id: "baz", content: {title: "Foo", body: "Foo123"}}
];

Просмотреть файл

@ -31,6 +31,38 @@ function cleanup() {
registerCleanupFunction(cleanup);
function nextChangeNotificationPromise(aNewURL, testMessage) {
return new Promise(resolve => {
Services.obs.addObserver(function observer(aSubject, aTopic, aData) { // jshint unused:false
Services.obs.removeObserver(observer, aTopic);
Assert.equal(aData, aNewURL, testMessage);
resolve();
}, "newtab-url-changed");
});
}
function setBoolPrefAndWaitForChange(pref, value, testMessage) {
return new Promise(resolve => {
Services.obs.addObserver(function observer(aSubject, aTopic, aData) { // jshint unused:false
Services.obs.removeObserver(observer, aTopic);
Assert.equal(aData, aboutNewTabService.newTabURL, testMessage);
resolve();
}, "newtab-url-changed");
Services.prefs.setBoolPref(pref, value);
});
}
function setupASPrerendered() {
if (Services.prefs.getBoolPref(ACTIVITY_STREAM_PRERENDER_PREF)) {
return Promise.resolve();
}
let notificationPromise = nextChangeNotificationPromise("about:newtab");
Services.prefs.setBoolPref(ACTIVITY_STREAM_PRERENDER_PREF, true);
return notificationPromise;
}
add_task(async function test_as_and_prerender_initialized() {
Assert.ok(aboutNewTabService.activityStreamEnabled,
".activityStreamEnabled should be set to the correct initial value");
@ -165,10 +197,8 @@ add_task(function test_locale() {
* Tests reponse to updates to prefs
*/
add_task(async function test_updates() {
/*
* Simulates a "cold-boot" situation, with some pref already set before testing a series
* of changes.
*/
// Simulates a "cold-boot" situation, with some pref already set before testing a series
// of changes.
await setupASPrerendered();
aboutNewTabService.resetNewTabURL(); // need to set manually because pref notifs are off
@ -197,36 +227,3 @@ add_task(async function test_updates() {
cleanup();
});
function nextChangeNotificationPromise(aNewURL, testMessage) {
return new Promise(resolve => {
Services.obs.addObserver(function observer(aSubject, aTopic, aData) { // jshint unused:false
Services.obs.removeObserver(observer, aTopic);
Assert.equal(aData, aNewURL, testMessage);
resolve();
}, "newtab-url-changed");
});
}
function setBoolPrefAndWaitForChange(pref, value, testMessage) {
return new Promise(resolve => {
Services.obs.addObserver(function observer(aSubject, aTopic, aData) { // jshint unused:false
Services.obs.removeObserver(observer, aTopic);
Assert.equal(aData, aboutNewTabService.newTabURL, testMessage);
resolve();
}, "newtab-url-changed");
Services.prefs.setBoolPref(pref, value);
});
}
function setupASPrerendered() {
if (Services.prefs.getBoolPref(ACTIVITY_STREAM_PRERENDER_PREF)) {
return Promise.resolve();
}
let notificationPromise = nextChangeNotificationPromise("about:newtab");
Services.prefs.setBoolPref(ACTIVITY_STREAM_PRERENDER_PREF, true);
return notificationPromise;
}

Просмотреть файл

@ -5,12 +5,12 @@
scripts:
# Run the activity-stream mochitests
mochitest: (cd $npm_package_config_mc_dir && ./mach mochitest browser/extensions/activity-stream/test/functional/mochitest --headless)
mochitest: (cd $npm_package_config_mc_dir && ./mach mochitest browser/components/newtab/test/browser --headless)
# Run the activity-stream mochitests with the browser toolbox debugger.
# Often handy in combination with adding a "debugger" statement in your
# mochitest somewhere.
mochitest-debug: (cd $npm_package_config_mc_dir && ./mach mochitest --jsdebugger browser/extensions/activity-stream/test/functional/mochitest)
mochitest-debug: (cd $npm_package_config_mc_dir && ./mach mochitest --jsdebugger browser/components/newtab/test/browser)
# bundle: Build all assets for activity stream
bundle:
@ -21,10 +21,9 @@ scripts:
# buildmc: Export the bootstraped add-on to mozilla central
buildmc:
pre: rimraf $npm_package_config_mc_dir/browser/extensions/activity-stream/
pre: rimraf $npm_package_config_mc_dir/browser/components/newtab/
bundle: => bundle
copy: rsync --exclude-from .mcignore -a . $npm_package_config_mc_dir/browser/extensions/activity-stream/
version: node ./bin/update-version.js $npm_package_config_mc_dir/browser/extensions/activity-stream
copy: rsync --exclude-from .mcignore -a . $npm_package_config_mc_dir/browser/components/newtab/
stringsExport: cp locales/en-US/strings.properties $npm_package_config_mc_dir/browser/locales/en-US/chrome/browser/activity-stream/newtab.properties
copyPingCentre: cpx "ping-centre/PingCentre.jsm" $npm_package_config_mc_dir/browser/modules
@ -33,13 +32,13 @@ scripts:
_parallel: true
pre: =>buildmc
# This copies only the system addon sub-folder; changing anything outside of it will need a full rebuild.
copy: cpx "{{,.}*,!(node_modules)/**/{,.}*}" $npm_package_config_mc_dir/browser/extensions/activity-stream/ -w
copy: cpx "{{,.}*,!(node_modules)/**/{,.}*}" $npm_package_config_mc_dir/browser/components/newtab/ -w
copyPingCentre: =>buildmc:copyPingCentre -- -w
webpack: =>bundle:webpack -- -w
css: =>bundle:css && =>bundle:css -- -w
# importmc: Import changes from mc to github repo
importmc: rsync --exclude-from .mcignore -a $npm_package_config_mc_dir/browser/extensions/activity-stream/ .
importmc: rsync --exclude-from .mcignore -a $npm_package_config_mc_dir/browser/components/newtab/ .
testmc:
lint: =>lint