fune/browser/base/content/test/about/head.js
Mike de Boer 481ae95c00 Bug 1524593 - nsISearchService (aka nsIBrowserSearchService, previously) refactor to be mostly an asynchronous, in preparation of WebExtension engines. r=daleharvey
This is a rollup of all the patches that have landed on the cedar project branch:

891252fdd0
Bug 1492475 - Part 1: Migrate most, if not all nsSearchService consumers to use async APIs. r=florian

79b2eb2367
Bug 1492475 - Part 2: Move nsIBrowserSearchService.idl to toolkit/components/search/nsISearchService.idl and update references. r=florian

a947d3cdf0
Bug 1492475 - Part 3: The search service init() method should simply return a Promise. r=florian

c1e172dfac
Bug 1492475 - Part 4: Remove the synchronous initialization flow. r=florian

cd41189eac
Bug 1492475 - Part 5: Since async initialization of the search service now is implicit behavior, remove the distinctive verbiage used internally. r=florian

2ae7189dfa
Bug 1492475 - Part 6: Update the cache build task to work with an actual Promise and re-initialize only once at the same time - all to fix race conditions here. r=florian

c8ee92973f
Bug 1492475 - Part 7: Make the region fetch not block the init flow, to ensure it's as fast as possible. r=florian

c44e674e16
Bug 1492475 - Part 8: Introduce an init flag, which can only be used privately, that allows to explicitly skip waiting for the region check process to complete. r=florian

6c79eaf1d3
Bug 1492475 - Part 9: Update unit tests to stop using 'currentEngine', in favor of 'defaultEngine'. r=Standard8

21b3aa17ee
Bug 1492475 - Part 10: Update unit tests to be fully aware of the new, async signatures of the search service API and remove sync init flow tests. r=mkaply,florian

ce5ba69019
Bug 1492475 - Part 11: Repair incorrect usage of the `identifier` property of nsISearchEngine instances. r=florian

fd177a7994
Bug 1518543 - Fix up the Android (Fennec) nsISearchService shim to work with the new asynchronous API. r=florian

3653d8ee22
Bug 1523708 - Change the search service interaction in the show-heartbeat action to use the new async API. r=florian

Differential Revision: https://phabricator.services.mozilla.com/D18355

--HG--
rename : netwerk/base/nsIBrowserSearchService.idl => toolkit/components/search/nsISearchService.idl
extra : moz-landing-system : lando
2019-02-02 11:27:21 +00:00

186 lines
5.7 KiB
JavaScript

/* eslint-env mozilla/frame-script */
XPCOMUtils.defineLazyModuleGetters(this, {
FormHistory: "resource://gre/modules/FormHistory.jsm",
});
function getSecurityInfo(securityInfoAsString) {
const serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
.getService(Ci.nsISerializationHelper);
let securityInfo = serhelper.deserializeObject(securityInfoAsString);
securityInfo.QueryInterface(Ci.nsITransportSecurityInfo);
return securityInfo;
}
function getCertChain(securityInfoAsString) {
let certChain = "";
let securityInfo = getSecurityInfo(securityInfoAsString);
for (let cert of securityInfo.failedCertChain.getEnumerator()) {
certChain += getPEMString(cert);
}
return certChain;
}
function getDERString(cert) {
var length = {};
var derArray = cert.getRawDER(length);
var derString = "";
for (var i = 0; i < derArray.length; i++) {
derString += String.fromCharCode(derArray[i]);
}
return derString;
}
function getPEMString(cert) {
var derb64 = btoa(getDERString(cert));
// Wrap the Base64 string into lines of 64 characters,
// with CRLF line breaks (as specified in RFC 1421).
var wrapped = derb64.replace(/(\S{64}(?!$))/g, "$1\r\n");
return "-----BEGIN CERTIFICATE-----\r\n"
+ wrapped
+ "\r\n-----END CERTIFICATE-----\r\n";
}
function injectErrorPageFrame(tab, src) {
return ContentTask.spawn(tab.linkedBrowser, {frameSrc: src}, async function({frameSrc}) {
let loaded = ContentTaskUtils.waitForEvent(content.wrappedJSObject, "DOMFrameContentLoaded");
let iframe = content.document.createElement("iframe");
iframe.src = frameSrc;
content.document.body.appendChild(iframe);
await loaded;
// We will have race conditions when accessing the frame content after setting a src,
// so we can't wait for AboutNetErrorLoad. Let's wait for the certerror class to
// appear instead (which should happen at the same time as AboutNetErrorLoad).
await ContentTaskUtils.waitForCondition(() =>
iframe.contentDocument.body.classList.contains("certerror"));
});
}
async function openErrorPage(src, useFrame) {
let dummyPage = getRootDirectory(gTestPath).replace("chrome://mochitests/content", "https://example.com") + "dummy_page.html";
let tab;
if (useFrame) {
info("Loading cert error page in an iframe");
tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, dummyPage);
await injectErrorPageFrame(tab, src);
} else {
let certErrorLoaded;
tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, src);
let browser = gBrowser.selectedBrowser;
certErrorLoaded = BrowserTestUtils.waitForErrorPage(browser);
}, false);
info("Loading and waiting for the cert error");
await certErrorLoaded;
}
return tab;
}
function waitForCondition(condition, nextTest, errorMsg, retryTimes) {
retryTimes = typeof retryTimes !== "undefined" ? retryTimes : 30;
var tries = 0;
var interval = setInterval(function() {
if (tries >= retryTimes) {
ok(false, errorMsg);
moveOn();
}
var conditionPassed;
try {
conditionPassed = condition();
} catch (e) {
ok(false, e + "\n" + e.stack);
conditionPassed = false;
}
if (conditionPassed) {
moveOn();
}
tries++;
}, 100);
var moveOn = function() { clearInterval(interval); nextTest(); };
}
function whenTabLoaded(aTab, aCallback) {
promiseTabLoadEvent(aTab).then(aCallback);
}
function promiseTabLoaded(aTab) {
return new Promise(resolve => {
whenTabLoaded(aTab, resolve);
});
}
/**
* Waits for a load (or custom) event to finish in a given tab. If provided
* load an uri into the tab.
*
* @param tab
* The tab to load into.
* @param [optional] url
* The url to load, or the current url.
* @return {Promise} resolved when the event is handled.
* @resolves to the received event
* @rejects if a valid load event is not received within a meaningful interval
*/
function promiseTabLoadEvent(tab, url) {
info("Wait tab event: load");
function handle(loadedUrl) {
if (loadedUrl === "about:blank" || (url && loadedUrl !== url)) {
info(`Skipping spurious load event for ${loadedUrl}`);
return false;
}
info("Tab event received: load");
return true;
}
let loaded = BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, handle);
if (url)
BrowserTestUtils.loadURI(tab.linkedBrowser, url);
return loaded;
}
/**
* Wait for the search engine to change.
*/
function promiseContentSearchChange(browser, newEngineName) {
return ContentTask.spawn(browser, { newEngineName }, async function(args) {
return new Promise(resolve => {
content.addEventListener("ContentSearchService", function listener(aEvent) {
if (aEvent.detail.type == "CurrentState" &&
content.wrappedJSObject.gContentSearchController.defaultEngine.name == args.newEngineName) {
content.removeEventListener("ContentSearchService", listener);
resolve();
}
});
});
});
}
/**
* Wait for the search engine to be added.
*/
async function promiseNewEngine(basename) {
info("Waiting for engine to be added: " + basename);
let url = getRootDirectory(gTestPath) + basename;
let engine;
try {
engine = await Services.search.addEngine(url, "", false);
} catch (errCode) {
ok(false, "addEngine failed with error code " + errCode);
throw errCode;
}
info("Search engine added: " + basename);
registerCleanupFunction(async () => {
try {
await Services.search.removeEngine(engine);
} catch (ex) { /* Can't remove the engine more than once */ }
});
return engine;
}