зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
001136fb24
Коммит
13c718e2f2
|
@ -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();
|
// Doom the old cache entry, so we can start writing to a new one.
|
||||||
|
this.log.trace("Populating the cache. Dooming old entry.");
|
||||||
|
this._cacheEntry = this._cacheEntry.recreate();
|
||||||
|
|
||||||
await new Promise((resolve, reject) => {
|
this.log.trace("Opening the page output stream.");
|
||||||
// Doom the old cache entry, so we can start writing to a new one.
|
let pageOutputStream = this._cacheEntry.openOutputStream(0, -1);
|
||||||
this.log.trace("Populating the cache. Dooming old entry.");
|
|
||||||
this.clearCache();
|
|
||||||
|
|
||||||
this.log.trace("Opening the page output stream.");
|
this.log.info("Writing the page cache.");
|
||||||
let pageOutputStream;
|
NetUtil.asyncCopy(pageInputStream, pageOutputStream, () => {
|
||||||
try {
|
this.log.trace(
|
||||||
pageOutputStream = this._cacheEntry.openOutputStream(0, -1);
|
"Writing the page data is complete. Now opening the " +
|
||||||
} catch (e) {
|
"script output stream."
|
||||||
reject(e);
|
);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.log.info("Writing the page cache.");
|
let scriptOutputStream = this._cacheEntry.openAlternativeOutputStream(
|
||||||
NetUtil.asyncCopy(pageInputStream, pageOutputStream, pageResult => {
|
"script",
|
||||||
if (!Components.isSuccessCode(pageResult)) {
|
-1
|
||||||
this.log.error("Failed to write page. Result: " + pageResult);
|
);
|
||||||
reject(new Error(pageResult));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.log.trace(
|
this.log.info("Writing the script cache.");
|
||||||
"Writing the page data is complete. Now opening the " +
|
NetUtil.asyncCopy(scriptInputStream, scriptOutputStream, () => {
|
||||||
"script output stream."
|
this.log.trace("Writing the script cache is done. Setting version.");
|
||||||
);
|
this._cacheEntry.setMetaDataElement(
|
||||||
|
"version",
|
||||||
let scriptOutputStream;
|
String(this.CACHE_VERSION)
|
||||||
try {
|
|
||||||
scriptOutputStream = this._cacheEntry.openAlternativeOutputStream(
|
|
||||||
"script",
|
|
||||||
-1
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
reject(e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.log.info("Writing the script cache.");
|
|
||||||
NetUtil.asyncCopy(
|
|
||||||
scriptInputStream,
|
|
||||||
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(
|
|
||||||
"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.info("Caching of page and script is done.");
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
this.log.trace(`Version is set to ${this.CACHE_VERSION}.`);
|
||||||
|
this.log.info("Caching of page and script is done.");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* 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()
|
||||||
|
|
Загрузка…
Ссылка в новой задаче