Backed out 3 changesets (bug 1622088) for XPCshell and Browser-chrome failurs on browser/abouthomecache/browser_process_crash.js. CLOSED TREE

Backed out changeset 238fa307504a (bug 1622088)
Backed out changeset ceaa7857baea (bug 1622088)
Backed out changeset 9c75ae56f50e (bug 1622088)
This commit is contained in:
Dorel Luca 2020-06-08 20:17:42 +03:00
Родитель 001136fb24
Коммит 13c718e2f2
16 изменённых файлов: 28 добавлений и 789 удалений

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

@ -5031,10 +5031,6 @@ var AboutHomeStartupCache = {
Services.obs.addObserver(this, "ipc:content-created"); Services.obs.addObserver(this, "ipc:content-created");
Services.obs.addObserver(this, "ipc:content-shutdown"); Services.obs.addObserver(this, "ipc:content-shutdown");
this._cacheEntryPromise = new Promise(resolve => {
this._cacheEntryResolver = resolve;
});
let lci = Services.loadContextInfo.default; let lci = Services.loadContextInfo.default;
let storage = Services.cache2.diskCacheStorage(lci, false); let storage = Services.cache2.diskCacheStorage(lci, false);
try { try {
@ -5083,9 +5079,6 @@ var AboutHomeStartupCache = {
this._initted = false; this._initted = false;
this._cacheEntry = null; this._cacheEntry = null;
this._hasWrittenThisSession = false; this._hasWrittenThisSession = false;
this._cacheEntryPromise = null;
this._cacheEntryResolver = null;
this.log.trace("Uninitialized."); this.log.trace("Uninitialized.");
this.log.removeAppender(this._appender); this.log.removeAppender(this._appender);
this.log = null; this.log = null;
@ -5143,7 +5136,7 @@ var AboutHomeStartupCache = {
* Resolves when a fresh version of the cache has been written. * Resolves when a fresh version of the cache has been written.
*/ */
async cacheNow() { async cacheNow() {
this.log.trace("Caching now."); this._hasWrittenThisSession = true;
this._cacheProgress = "Getting cache streams"; this._cacheProgress = "Getting cache streams";
let { pageInputStream, scriptInputStream } = await this.requestCache(); let { pageInputStream, scriptInputStream } = await this.requestCache();
@ -5155,8 +5148,6 @@ var AboutHomeStartupCache = {
this._cacheProgress = "Writing to cache"; this._cacheProgress = "Writing to cache";
await this.populateCache(pageInputStream, scriptInputStream); await this.populateCache(pageInputStream, scriptInputStream);
this._cacheProgress = "Done"; this._cacheProgress = "Done";
this.log.trace("Done writing to cache.");
this._hasWrittenThisSession = true;
}, },
/** /**
@ -5274,7 +5265,7 @@ var AboutHomeStartupCache = {
if (parseInt(version, 10) != this.CACHE_VERSION) { if (parseInt(version, 10) != this.CACHE_VERSION) {
this.log.info("Version does not match! Dooming and closing streams.\n"); this.log.info("Version does not match! Dooming and closing streams.\n");
// This cache is no good - doom it, and prepare for a new one. // This cache is no good - doom it, and prepare for a new one.
this.clearCache(); this._cacheEntry = this._cacheEntry.recreate();
this.pagePipe.outputStream.close(); this.pagePipe.outputStream.close();
this.scriptPipe.outputStream.close(); this.scriptPipe.outputStream.close();
return; return;
@ -5375,120 +5366,40 @@ var AboutHomeStartupCache = {
* A stream containing the HTML markup to be saved to the cache. * A stream containing the HTML markup to be saved to the cache.
* @param scriptInputStream (nsIInputStream) * @param scriptInputStream (nsIInputStream)
* A stream containing the JS hydration script to be saved to the cache. * A stream containing the JS hydration script to be saved to the cache.
* @returns Promise
* @resolves undefined
* When the cache has been successfully written to.
* @rejects Error
* Rejects with a JS Error if writing any part of the cache happens to
* fail.
*/ */
async populateCache(pageInputStream, scriptInputStream) { populateCache(pageInputStream, scriptInputStream) {
await this.ensureCacheEntry();
await new Promise((resolve, reject) => {
// Doom the old cache entry, so we can start writing to a new one. // Doom the old cache entry, so we can start writing to a new one.
this.log.trace("Populating the cache. Dooming old entry."); this.log.trace("Populating the cache. Dooming old entry.");
this.clearCache(); this._cacheEntry = this._cacheEntry.recreate();
this.log.trace("Opening the page output stream."); this.log.trace("Opening the page output stream.");
let pageOutputStream; let pageOutputStream = this._cacheEntry.openOutputStream(0, -1);
try {
pageOutputStream = this._cacheEntry.openOutputStream(0, -1);
} catch (e) {
reject(e);
return;
}
this.log.info("Writing the page cache."); this.log.info("Writing the page cache.");
NetUtil.asyncCopy(pageInputStream, pageOutputStream, pageResult => { NetUtil.asyncCopy(pageInputStream, pageOutputStream, () => {
if (!Components.isSuccessCode(pageResult)) {
this.log.error("Failed to write page. Result: " + pageResult);
reject(new Error(pageResult));
return;
}
this.log.trace( this.log.trace(
"Writing the page data is complete. Now opening the " + "Writing the page data is complete. Now opening the " +
"script output stream." "script output stream."
); );
let scriptOutputStream; let scriptOutputStream = this._cacheEntry.openAlternativeOutputStream(
try {
scriptOutputStream = this._cacheEntry.openAlternativeOutputStream(
"script", "script",
-1 -1
); );
} catch (e) {
reject(e);
return;
}
this.log.info("Writing the script cache."); this.log.info("Writing the script cache.");
NetUtil.asyncCopy( NetUtil.asyncCopy(scriptInputStream, scriptOutputStream, () => {
scriptInputStream, this.log.trace("Writing the script cache is done. Setting version.");
scriptOutputStream,
scriptResult => {
if (!Components.isSuccessCode(scriptResult)) {
this.log.error("Failed to write script. Result: " + scriptResult);
reject(new Error(scriptResult));
return;
}
this.log.trace(
"Writing the script cache is done. Setting version."
);
try {
this._cacheEntry.setMetaDataElement( this._cacheEntry.setMetaDataElement(
"version", "version",
String(this.CACHE_VERSION) String(this.CACHE_VERSION)
); );
} catch (e) {
this.log.error("Failed to write version.");
reject(e);
return;
}
this.log.trace(`Version is set to ${this.CACHE_VERSION}.`); this.log.trace(`Version is set to ${this.CACHE_VERSION}.`);
this.log.info("Caching of page and script is done."); this.log.info("Caching of page and script is done.");
resolve();
}
);
}); });
}); });
}, },
/**
* Returns a Promise that resolves once the nsICacheEntry for the cache
* is available to write to and read from.
*
* @returns Promise
* @resolves nsICacheEntry
* Once the cache entry has become available.
* @rejects String
* Rejects with an error message if getting the cache entry is attempted
* before the AboutHomeStartupCache component has been initialized.
*/
ensureCacheEntry() {
if (!this._initted) {
return Promise.reject(
"Cannot ensureCacheEntry - AboutHomeStartupCache is not initted"
);
}
return this._cacheEntryPromise;
},
/**
* Clears the contents of the cache.
*/
clearCache() {
this.log.trace("Clearing the cache.");
this._cacheEntry = this._cacheEntry.recreate();
this._cacheEntryPromise = new Promise(resolve => {
resolve(this._cacheEntry);
});
this._hasWrittenThisSession = false;
},
/** /**
* Called when a content process is created. If this is the "privileged * Called when a content process is created. If this is the "privileged
* about content process", then the cache streams will be sent to it. * about content process", then the cache streams will be sent to it.
@ -5609,7 +5520,5 @@ var AboutHomeStartupCache = {
this._cacheEntry = aEntry; this._cacheEntry = aEntry;
this.makePipes(); this.makePipes();
this.maybeConnectToPipes(); this.maybeConnectToPipes();
this._cacheEntryResolver(this._cacheEntry);
}, },
}; };

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

@ -52,8 +52,6 @@ const { E10SUtils } = ChromeUtils.import(
const PREF_ABOUT_HOME_CACHE_ENABLED = const PREF_ABOUT_HOME_CACHE_ENABLED =
"browser.startup.homepage.abouthome_cache.enabled"; "browser.startup.homepage.abouthome_cache.enabled";
const PREF_ABOUT_HOME_CACHE_TESTING =
"browser.startup.homepage.abouthome_cache.testing";
const PREF_SEPARATE_ABOUT_WELCOME = "browser.aboutwelcome.enabled"; const PREF_SEPARATE_ABOUT_WELCOME = "browser.aboutwelcome.enabled";
const SEPARATE_ABOUT_WELCOME_URL = const SEPARATE_ABOUT_WELCOME_URL =
"resource://activity-stream/aboutwelcome/aboutwelcome.html"; "resource://activity-stream/aboutwelcome/aboutwelcome.html";
@ -122,24 +120,6 @@ const AboutHomeStartupCacheChild = {
this._initted = true; this._initted = true;
}, },
/**
* A function that lets us put the AboutHomeStartupCacheChild back into
* its initial state. This is used by tests to let us simulate the startup
* behaviour of the module without having to manually launch a new privileged
* about content process every time.
*/
uninit() {
if (!Services.prefs.getBoolPref(PREF_ABOUT_HOME_CACHE_TESTING, false)) {
throw new Error(
"Cannot uninit AboutHomeStartupCacheChild unless testing."
);
}
this._pageInputStream = null;
this._scriptInputStream = null;
this._initted = false;
},
/** /**
* A public method called from nsIAboutNewTabService that attempts * A public method called from nsIAboutNewTabService that attempts
* return an nsIChannel for a cached about:home document that we * return an nsIChannel for a cached about:home document that we

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

@ -7,10 +7,7 @@
with Files("**"): with Files("**"):
BUG_COMPONENT = ("Firefox", "New Tab Page") BUG_COMPONENT = ("Firefox", "New Tab Page")
BROWSER_CHROME_MANIFESTS += [ BROWSER_CHROME_MANIFESTS += ['test/browser/browser.ini']
'test/browser/abouthomecache/browser.ini',
'test/browser/browser.ini',
]
SPHINX_TREES['docs'] = 'docs' SPHINX_TREES['docs'] = 'docs'
SPHINX_TREES['content-src/asrouter/docs'] = 'content-src/asrouter/docs' SPHINX_TREES['content-src/asrouter/docs'] = 'content-src/asrouter/docs'

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

@ -1,20 +0,0 @@
[DEFAULT]
support-files =
head.js
prefs =
browser.tabs.remote.separatePrivilegedContentProcess=true
browser.startup.homepage.abouthome_cache.enabled=true
browser.startup.homepage.abouthome_cache.cache_on_shutdown=false
browser.startup.homepage.abouthome_cache.testing=true
browser.startup.page=1
browser.newtabpage.activity-stream.discoverystream.endpoints=data:
browser.newtabpage.activity-stream.feeds.section.topstories=true
browser.newtabpage.activity-stream.feeds.section.topstories.options={"provider_name":""}
browser.newtabpage.activity-stream.telemetry.structuredIngestion=false
[browser_basic_endtoend.js]
[browser_bump_version.js]
[browser_no_cache.js]
[browser_overwrite_cache.js]
[browser_process_crash.js]
skip-if = !e10s || !crashreporter

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

@ -1,22 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/**
* Tests that the about:home cache gets written on shutdown, and read
* from in the subsequent startup.
*/
add_task(async function test_basic_behaviour() {
await BrowserTestUtils.withNewTab("about:home", async browser => {
// First, clear the cache to test the base case.
await clearCache();
await simulateRestart(browser);
await ensureCachedAboutHome(browser);
// Next, test that a subsequent restart also shows the cached
// about:home.
await simulateRestart(browser);
await ensureCachedAboutHome(browser);
});
});

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

@ -1,21 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/**
* Test that if the "version" metadata on the cache entry doesn't match
* the expectation that we ignore the cache and load the dynamic about:home
* document.
*/
add_task(async function test_bump_version() {
await BrowserTestUtils.withNewTab("about:home", async browser => {
// First, ensure that a pre-existing cache exists.
await simulateRestart(browser);
let cacheEntry = await AboutHomeStartupCache.ensureCacheEntry();
cacheEntry.setMetaDataElement("version", "somethingnew");
await simulateRestart(browser, false /* withAutoShutdownWrite */);
await ensureDynamicAboutHome(browser);
});
});

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

@ -1,18 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
requestLongerTimeout(2);
/**
* Test that if there's no cache written, that we load the dynamic
* about:home document on startup.
*/
add_task(async function test_no_cache() {
await BrowserTestUtils.withNewTab("about:home", async browser => {
await clearCache();
await simulateRestart(browser, false /* withAutoShutdownWrite */);
await ensureDynamicAboutHome(browser);
});
});

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

@ -1,37 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/**
* Tests that if a pre-existing about:home cache exists, that it can
* be overwritten with new information.
*/
add_task(async function test_overwrite_cache() {
await BrowserTestUtils.withNewTab("about:home", async browser => {
await simulateRestart(browser);
const TEST_ID = "test_overwrite_cache_h1";
// We need the CSP meta tag in about: pages, otherwise we hit assertions in
// debug builds.
await injectIntoCache(
`
<html>
<head>
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; object-src 'none'; script-src resource: chrome:; connect-src https:; img-src https: data: blob:; style-src 'unsafe-inline';">
</head>
<body>
<h1 id="${TEST_ID}">Something new</h1>
</body>
<script src="about:home?jscache"></script>
</html>`,
"window.__FROM_STARTUP_CACHE__ = true;"
);
await simulateRestart(browser, false /* withAutoShutdownWrite */);
await SpecialPowers.spawn(browser, [TEST_ID], async testID => {
let target = content.document.getElementById(testID);
Assert.ok(target, "Found the target element");
});
});
});

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

@ -1,41 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/**
* Test that if the "privileged about content process" crashes, that it
* drops its internal reference to the "privileged about content process"
* process manager, and that a subsequent restart of that process type
* results in a new cached document load. Also tests that crashing of
* any other content process type doesn't clear the process manager
* reference.
*/
add_task(async function test_bump_version() {
await BrowserTestUtils.withNewTab("about:home", async browser => {
await simulateRestart(browser);
let origProcManager = AboutHomeStartupCache._procManager;
await BrowserTestUtils.crashFrame(browser);
Assert.notEqual(
origProcManager,
AboutHomeStartupCache._procManager,
"Should have dropped the reference to the crashed process"
);
});
let latestProcManager = AboutHomeStartupCache._procManager;
await BrowserTestUtils.withNewTab("about:home", async browser => {
await ensureCachedAboutHome(browser);
});
await BrowserTestUtils.withNewTab("http://example.com", async browser => {
await BrowserTestUtils.crashFrame(browser);
Assert.equal(
latestProcManager,
AboutHomeStartupCache._procManager,
"Should still have the reference to the privileged about process"
);
});
});

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

@ -1,238 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
let { AboutHomeStartupCache } = ChromeUtils.import(
"resource:///modules/BrowserGlue.jsm"
);
/**
* Shuts down the AboutHomeStartupCache components in the parent process
* and privileged about content process, and then restarts them, simulating
* the parent process having restarted.
*
* @param browser (<xul:browser>)
* A <xul:browser> with about:home running in it. This will be reloaded
* after the restart simultion is complete, and that reload will attempt
* to read any about:home cache contents.
* @param options (object, optional)
*
* An object with the following properties:
*
* withAutoShutdownWrite (boolean, optional):
* Whether or not the shutdown part of the simulation should cause the
* shutdown handler to run, which normally causes the cache to be
* written. Setting this to false is handy if the cache has been
* specially prepared for the subsequent startup, and we don't want to
* overwrite it. This defaults to true.
*
* ensureCacheWinsRace (boolean, optional):
* Ensures that the privileged about content process will be able to
* read the bytes from the streams sent down from the HTTP cache. Use
* this to avoid the HTTP cache "losing the race" against reading the
* about:home document from the omni.ja. This defaults to true.
*
* @returns Promise
* @resolves undefined
* Resolves once the restart simulation is complete, and the <xul:browser>
* pointed at about:home finishes reloading.
*/
// eslint-disable-next-line no-unused-vars
async function simulateRestart(
browser,
{ withAutoShutdownWrite, ensureCacheWinsRace } = {
withAutoShutdownWrite: true,
ensureCacheWinsRace: true,
}
) {
info("Simulating restart of the browser");
let processManager = browser.messageManager.processMessageManager;
if (processManager.remoteType !== E10SUtils.PRIVILEGEDABOUT_REMOTE_TYPE) {
throw new Error(
"prepareLoadFromCache should only be called on a browser " +
"loaded in the privileged about content process."
);
}
if (withAutoShutdownWrite) {
info("Simulating shutdown write");
await AboutHomeStartupCache.onShutdown();
info("Shutdown write done");
} else {
info("Intentionally skipping shutdown write");
}
AboutHomeStartupCache.uninit();
info("Waiting for AboutHomeStartupCacheChild to uninit");
await SpecialPowers.spawn(browser, [], async () => {
let { AboutHomeStartupCacheChild } = ChromeUtils.import(
"resource:///modules/AboutNewTabService.jsm"
);
AboutHomeStartupCacheChild.uninit();
});
info("AboutHomeStartupCacheChild uninitted");
AboutHomeStartupCache.init();
AboutHomeStartupCache.sendCacheInputStreams(processManager);
info("Waiting for AboutHomeStartupCache cache entry");
await AboutHomeStartupCache.ensureCacheEntry();
info("Got AboutHomeStartupCache cache entry");
if (ensureCacheWinsRace) {
info("Ensuring cache bytes are available");
await SpecialPowers.spawn(browser, [], async () => {
let { AboutHomeStartupCacheChild } = ChromeUtils.import(
"resource:///modules/AboutNewTabService.jsm"
);
let pageStream = AboutHomeStartupCacheChild._pageInputStream;
let scriptStream = AboutHomeStartupCacheChild._scriptInputStream;
await ContentTaskUtils.waitForCondition(() => {
return pageStream.available() && scriptStream.available();
});
});
}
info("Waiting for about:home to load");
let loaded = BrowserTestUtils.browserLoaded(browser, false, "about:home");
BrowserTestUtils.loadURI(browser, "about:home");
await loaded;
info("about:home loaded");
}
/**
* Writes a page string and a script string into the cache for
* the next about:home load.
*
* @param page (String)
* The HTML content to write into the cache. This cannot be the empty
* string.
* @param script (String)
* The JS content to write into the cache that can be loaded via
* about:home?jscache. This cannot be the empty string.
* @returns Promise
* @resolves undefined
* When the page and script content has been successfully written.
*/
// eslint-disable-next-line no-unused-vars
async function injectIntoCache(page, script) {
if (!page || !script) {
throw new Error("Cannot injectIntoCache with falsey values");
}
await AboutHomeStartupCache.ensureCacheEntry();
let pageInputStream = Cc[
"@mozilla.org/io/string-input-stream;1"
].createInstance(Ci.nsIStringInputStream);
pageInputStream.setUTF8Data(page);
let scriptInputStream = Cc[
"@mozilla.org/io/string-input-stream;1"
].createInstance(Ci.nsIStringInputStream);
scriptInputStream.setUTF8Data(script);
await AboutHomeStartupCache.populateCache(pageInputStream, scriptInputStream);
}
/**
* Clears out any pre-existing about:home cache.
* @returns Promise
* @resolves undefined
* Resolves when the cache is cleared.
*/
// eslint-disable-next-line no-unused-vars
async function clearCache() {
info("Test is clearing the cache");
AboutHomeStartupCache.clearCache();
await AboutHomeStartupCache.ensureCacheEntry();
info("Test has cleared the cache.");
}
/**
* Tests that the about:home document loaded in a passed <xul:browser> was
* one from the cache.
*
* We test for this by looking for some tell-tale signs of the cached
* document:
*
* 1. The about:home?jscache <script> element
* 2. The __FROM_STARTUP_CACHE__ expando on the window
* 3. The "activity-stream" class on the document body
* 4. The top sites section
*
* @returns Promise
* @resolves undefined
* Resolves once the cache entry has been destroyed.
*/
// eslint-disable-next-line no-unused-vars
async function ensureCachedAboutHome(browser) {
await SpecialPowers.spawn(browser, [], async () => {
let scripts = Array.from(content.document.querySelectorAll("script"));
Assert.ok(!!scripts.length, "There should be page scripts.");
let [lastScript] = scripts.reverse();
Assert.equal(
lastScript.src,
"about:home?jscache",
"Found about:home?jscache script tag, indicating the cached doc"
);
Assert.ok(
Cu.waiveXrays(content).__FROM_STARTUP_CACHE__,
"Should have found window.__FROM_STARTUP_CACHE__"
);
Assert.ok(
content.document.body.classList.contains("activity-stream"),
"Should have found activity-stream class on <body> element"
);
Assert.ok(
content.document.querySelector("[data-section-id='topsites']"),
"Should have found the Discovery Stream top sites."
);
});
}
/**
* Tests that the about:home document loaded in a passed <xul:browser> was
* dynamically generated, and _not_ from the cache.
*
* We test for this by looking for some tell-tale signs of the dynamically
* generated document:
*
* 1. No <script> elements (the scripts are loaded from the ScriptPreloader
* via AboutNewTabChild when the "privileged about content process" is
* enabled)
* 2. No __FROM_STARTUP_CACHE__ expando on the window
* 3. The "activity-stream" class on the document body
* 4. The top sites section
*
* @returns Promise
* @resolves undefined
* Resolves once the cache entry has been destroyed.
*/
// eslint-disable-next-line no-unused-vars
async function ensureDynamicAboutHome(browser) {
await SpecialPowers.spawn(browser, [], async () => {
let scripts = Array.from(content.document.querySelectorAll("script"));
Assert.equal(scripts.length, 0, "There should be no page scripts.");
Assert.equal(
Cu.waiveXrays(content).__FROM_STARTUP_CACHE__,
undefined,
"Should not have found window.__FROM_STARTUP_CACHE__"
);
Assert.ok(
content.document.body.classList.contains("activity-stream"),
"Should have found activity-stream class on <body> element"
);
Assert.ok(
content.document.querySelector("[data-section-id='topsites']"),
"Should have found the Discovery Stream top sites."
);
});
}

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

@ -1 +0,0 @@
{"spocs":{"url":"","spocs_per_domain":1},"layout":[{"width":12,"components":[{"type":"TopSites","header":{"title":"Top Sites"},"properties":null},{"type":"Message","header":{"title":"Recommended by Pocket","subtitle":"","link_text":"How it works","link_url":"https:\/\/getpocket.com\/firefox\/new_tab_learn_more","icon":"resource:\/\/activity-stream\/data\/content\/assets\/glyph-pocket-16.svg"},"properties":null,"styles":{".ds-message":"margin-bottom: -20px"}},{"type":"CardGrid","properties":{"items":3},"header":{"title":""},"feed":{"embed_reference":null,"url":"http://example.com/topstories.json"},"spocs":{"probability":1,"positions":[{"index":2}]}},{"type":"Navigation","properties":{"alignment":"left-align","links":[{"name":"Must Reads","url":"https:\/\/getpocket.com\/explore\/must-reads?src=fx_new_tab"},{"name":"Productivity","url":"https:\/\/getpocket.com\/explore\/productivity?src=fx_new_tab"},{"name":"Health","url":"https:\/\/getpocket.com\/explore\/health?src=fx_new_tab"},{"name":"Finance","url":"https:\/\/getpocket.com\/explore\/finance?src=fx_new_tab"},{"name":"Technology","url":"https:\/\/getpocket.com\/explore\/technology?src=fx_new_tab"},{"name":"More Recommendations \u203a","url":"https:\/\/getpocket.com\/explore\/trending?src=fx_new_tab"}]}}]}],"feeds":{},"error":0,"status":1}

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

@ -1,220 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/**
* This test ensures that the about:home startup cache worker
* script can correctly convert a state object from the Activity
* Stream Redux store into an HTML document and script.
*/
const { AddonTestUtils } = ChromeUtils.import(
"resource://testing-common/AddonTestUtils.jsm"
);
const { TestUtils } = ChromeUtils.import(
"resource://testing-common/TestUtils.jsm"
);
AddonTestUtils.init(this);
AddonTestUtils.createAppInfo(
"xpcshell@tests.mozilla.org",
"XPCShell",
"42",
"42"
);
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
const { XPCOMUtils } = ChromeUtils.import(
"resource://gre/modules/XPCOMUtils.jsm"
);
const { AboutNewTab } = ChromeUtils.import(
"resource:///modules/AboutNewTab.jsm"
);
const { PREFS_CONFIG } = ChromeUtils.import(
"resource://activity-stream/lib/ActivityStream.jsm"
);
ChromeUtils.defineModuleGetter(
this,
"BasePromiseWorker",
"resource://gre/modules/PromiseWorker.jsm"
);
XPCOMUtils.defineLazyGlobalGetters(this, ["DOMParser"]);
const CACHE_WORKER_URL = "resource://activity-stream/lib/cache-worker.js";
/**
* In order to make this test less brittle, much of Activity Stream is
* initialized here in order to generate a state object at runtime, rather
* than hard-coding one in. This requires quite a bit of machinery in order
* to work properly. Specifically, we need to launch an HTTP server to serve
* a dynamic layout, and then have that layout point to a local feed rather
* than one from the Pocket CDN.
*/
add_task(async function setup() {
do_get_profile();
// The SearchService is also needed in order to construct the initial state,
// which means that the AddonManager needs to be available.
await AddonTestUtils.promiseStartupManager();
// The example.com domain will be used to host the dynamic layout JSON and
// the top stories JSON.
let server = AddonTestUtils.createHttpServer({ hosts: ["example.com"] });
server.registerDirectory("/", do_get_cwd());
// Top Stories are disabled by default in our testing profiles.
Services.prefs.setBoolPref(
"browser.newtabpage.activity-stream.feeds.section.topstories",
true
);
let defaultDSConfig = JSON.parse(
PREFS_CONFIG.get("discoverystream.config").getValue({
geo: "US",
locale: "en-US",
})
);
let newConfig = Object.assign(defaultDSConfig, {
show_spocs: false,
hardcoded_layout: false,
layout_endpoint: "http://example.com/ds_layout.json",
});
// Configure Activity Stream to query for the layout JSON file that points
// at the local top stories feed.
Services.prefs.setCharPref(
"browser.newtabpage.activity-stream.discoverystream.config",
JSON.stringify(newConfig)
);
// We need to allow example.com as a place to get both the layout and the
// top stories from.
Services.prefs.setCharPref(
"browser.newtabpage.activity-stream.discoverystream.endpoints",
`http://example.com`
);
Services.prefs.setBoolPref(
"browser.newtabpage.activity-stream.telemetry.structuredIngestion",
false
);
Services.prefs.setBoolPref("browser.ping-centre.telemetry", false);
// We need a default search engine set up for rendering the search input.
let engine = await Services.search.addEngineWithDetails("Test engine", {
template: "http://example.com/?s=%S",
alias: "@testengine",
});
Services.search.defaultEngine = engine;
// Initialize Activity Stream, and pretend that a new window has been loaded
// to kick off initializing all of the feeds.
AboutNewTab.init();
AboutNewTab.onBrowserReady();
// Much of Activity Stream initializes asynchronously. This is the easiest way
// I could find to ensure that enough of the feeds had initialized to produce
// a meaningful cached document.
await TestUtils.waitForCondition(() => {
let feed = AboutNewTab.activityStream.store.feeds.get(
"feeds.discoverystreamfeed"
);
return feed.loaded;
});
});
/**
* Gets the Activity Stream Redux state from Activity Stream and sends it
* into an instance of the cache worker to ensure that the resulting markup
* and script makes sense.
*/
add_task(async function test_cache_worker() {
let state = AboutNewTab.activityStream.store.getState();
let cacheWorker = new BasePromiseWorker(CACHE_WORKER_URL);
let { page, script } = await cacheWorker.post("construct", [state]);
ok(!!page.length, "Got page content");
ok(!!script.length, "Got script content");
// The template strings should have been replaced.
equal(
page.indexOf("{{ MARKUP }}"),
-1,
"Page template should have {{ MARKUP }} replaced"
);
equal(
page.indexOf("{{ CACHE_TIME }}"),
-1,
"Page template should have {{ CACHE_TIME }} replaced"
);
equal(
script.indexOf("{{ STATE }}"),
-1,
"Script template should have {{ STATE }} replaced"
);
// Now let's make sure that the generated script makes sense. We'll
// evaluate it in a sandbox to make sure broken JS doesn't break the
// test.
let sandbox = Cu.Sandbox(Cu.getGlobalForObject({}));
let passedState = null;
// window.NewtabRenderUtils.renderCache is the exposed API from
// activity-stream.jsx that the script is expected to call to hydrate
// the pre-rendered markup. We'll implement that, and use that to ensure
// that the passed in state object matches the state we sent into the
// worker.
sandbox.window = {
NewtabRenderUtils: {
renderCache(aState) {
passedState = aState;
},
},
};
Cu.evalInSandbox(script, sandbox);
equal(
sandbox.window.__FROM_STARTUP_CACHE__,
true,
"Should have set __FROM_STARTUP_CACHE__ to true"
);
// The worker is expected to modify the state slightly before running
// it through ReactDOMServer by setting App.isForStartupCache to true.
// This allows React components to change their behaviour if the cache
// is being generated.
state.App.isForStartupCache = true;
// Some of the properties on the state might have values set to undefined.
// There is no way to express a named undefined property on an object in
// JSON, so we filter those out by stringifying and re-parsing.
state = JSON.parse(JSON.stringify(state));
Assert.deepEqual(
passedState,
state,
"Should have called renderCache with the expected state"
);
// Now let's do a quick smoke-test on the markup to ensure that the
// one Top Story from topstories.json is there.
let parser = new DOMParser();
let doc = parser.parseFromString(page, "text/html");
let root = doc.getElementById("root");
ok(root.childElementCount, "There are children on the root node");
// There should be the 1 top story, and 2 placeholders.
equal(
Array.from(root.querySelectorAll(".ds-card")).length,
3,
"There are 3 DSCards"
);
let cardHostname = doc.querySelector("[data-section-id='topstories'] .source")
.innerText;
equal(cardHostname, "bbc.com", "Card hostname is bbc.com");
let placeholders = doc.querySelectorAll(".ds-card.placeholder");
equal(placeholders.length, 2, "There should be 2 placeholders");
});

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

@ -1 +0,0 @@
{"status":1,"settings":{"spocsPerNewTabs":0.5,"domainAffinityParameterSets":{"default":{"recencyFactor":0.5,"frequencyFactor":0.5,"combinedDomainFactor":0.5,"perfectFrequencyVisits":10,"perfectCombinedDomainScore":2,"multiDomainBoost":0,"itemScoreFactor":1},"fully-personalized":{"recencyFactor":0.5,"frequencyFactor":0.5,"combinedDomainFactor":0.5,"perfectFrequencyVisits":10,"perfectCombinedDomainScore":2,"itemScoreFactor":0.01,"multiDomainBoost":0}},"timeSegments":[{"id":"week","startTime":604800,"endTime":0,"weightPosition":1},{"id":"month","startTime":2592000,"endTime":604800,"weightPosition":0.5}],"recsExpireTime":5400,"version":"2c2aa06dac65ddb647d8902aaa60263c8e119ff2"},"spocs":[],"recommendations":[{"id":53093,"url":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAA/UlEQVR4nO3RMQ0AMAzAsPIn3d5DsBw2gkiZJWV+B/AyJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQmAP4K6zWNUjE4wAAAABJRU5ErkJggg==","domain":"bbc.com","title":"Why vegan junk food may be even worse for your health","excerpt":"While we might switch to a plant-based diet with the best intentions, the unseen risks of vegan fast foods might not show up for years.","image_src":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAA/UlEQVR4nO3RMQ0AMAzAsPIn3d5DsBw2gkiZJWV+B/AyJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQGENiDIkxJMaQmAP4K6zWNUjE4wAAAABJRU5ErkJggg==","published_timestamp":"1580277600","engagement":"","parameter_set":"default","domain_affinities":{},"item_score":1}]}

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

@ -3,11 +3,6 @@ head =
firefox-appdir = browser firefox-appdir = browser
skip-if = toolkit == 'android' skip-if = toolkit == 'android'
[test_AboutHomeStartupCacheWorker.js]
support-files =
ds_layout.json
topstories.json
[test_AboutNewTab.js] [test_AboutNewTab.js]
[test_ASRouterTargeting_attribution.js] [test_ASRouterTargeting_attribution.js]
skip-if = toolkit != "cocoa" # osx specific tests skip-if = toolkit != "cocoa" # osx specific tests

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

@ -13,7 +13,7 @@
"tests": ["tart_flex", "ts_paint_flex"] "tests": ["tart_flex", "ts_paint_flex"]
}, },
"other": { "other": {
"tests": ["a11yr", "ts_paint", "twinopen", "sessionrestore", "sessionrestore_no_auto_restore", "tabpaint", "cpstartup", "startup_about_home_paint", "startup_about_home_paint_cached", "pdfpaint"] "tests": ["a11yr", "ts_paint", "twinopen", "sessionrestore", "sessionrestore_no_auto_restore", "tabpaint", "cpstartup", "startup_about_home_paint", "pdfpaint"]
}, },
"sessionrestore-many-windows": { "sessionrestore-many-windows": {
"tests": ["sessionrestore_many_windows"] "tests": ["sessionrestore_many_windows"]

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

@ -187,33 +187,10 @@ class ts_paint_flex(ts_paint):
@register_test() @register_test()
class startup_about_home_paint(ts_paint): class startup_about_home_paint(ts_paint):
"""
Tests loading about:home on startup with the about:home startup cache
disabled, to more accurately simulate startup when the cache does not
exist.
"""
url = None url = None
cycles = 20 cycles = 20
extensions = ['${talos}/startup_test/startup_about_home_paint/addon'] extensions = ['${talos}/startup_test/startup_about_home_paint/addon']
tpmanifest = '${talos}/startup_test/startup_about_home_paint/startup_about_home_paint.manifest' tpmanifest = '${talos}/startup_test/startup_about_home_paint/startup_about_home_paint.manifest'
preferences = {
'browser.startup.homepage.abouthome_cache.enabled': False,
}
@register_test()
class startup_about_home_paint_cached(ts_paint):
"""
Tests loading about:home on startup with the about:home startup cache
enabled.
"""
url = None
cycles = 20
extensions = ['${talos}/startup_test/startup_about_home_paint/addon']
tpmanifest = '${talos}/startup_test/startup_about_home_paint/startup_about_home_paint.manifest'
preferences = {
'browser.startup.homepage.abouthome_cache.enabled': True,
}
@register_test() @register_test()