forked from mirrors/gecko-dev
Right now, a lot of test code relies on side-effects of SpecialPowers being loaded into frame script globals. In particular: - It forces permissive COWs from those scopes, which allows frame scripts to pass objects from those scopes to unprivileged content that they otherwise wouldn't. - It imports a bunch of helper modules and WebIDL globals which would otherwise not be available. Fortunately, this seems to only impact test code at this point. But there's a real down-the-road risk of it impacting shipping code, which ends up working in automation due to the side-effects of SpecialPowers, but failing in real world use. MozReview-Commit-ID: G27eSSOHymX --HG-- extra : rebase_source : 1702e63fed719fc92def2bdbbb8a7c53572432db extra : source : 41bedc526dd6ec6b7e8c7be1c832ac60c81d6263
168 lines
5.9 KiB
JavaScript
168 lines
5.9 KiB
JavaScript
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
"use strict";
|
|
|
|
/*
|
|
* This test validates that an OTF font installed in a directory not
|
|
* accessible to content processes is rendered correctly by checking that
|
|
* content displayed never uses the OS fallback font "LastResort". When
|
|
* a content process renders a page with the fallback font, that is an
|
|
* indication the content process failed to read or load the computed font.
|
|
* The test uses a version of the Fira Sans font and depends on the font
|
|
* not being already installed and enabled.
|
|
*/
|
|
|
|
ChromeUtils.import("resource://gre/modules/FileUtils.jsm");
|
|
|
|
const kPageURL =
|
|
"http://example.com/browser/security/sandbox/test/bug1393259.html";
|
|
|
|
const environment = Cc["@mozilla.org/process/environment;1"]
|
|
.getService(Ci.nsIEnvironment);
|
|
|
|
// Parameters for running the python script that registers/unregisters fonts.
|
|
const kPythonPath = "/usr/bin/python";
|
|
const kFontInstallerPath = "browser/security/sandbox/test/mac_register_font.py";
|
|
const kUninstallFlag = "-u";
|
|
const kVerboseFlag = "-v";
|
|
|
|
// Where to find the font in the test environment.
|
|
const kRepoFontPath = "browser/security/sandbox/test/FiraSans-Regular.otf";
|
|
|
|
// Font name strings to check for.
|
|
const kLastResortFontName = "LastResort";
|
|
const kTestFontName = "Fira Sans";
|
|
|
|
// Home-relative path to install a private font. Where a private font is
|
|
// a font at a location not readable by content processes.
|
|
const kPrivateFontSubPath = "/FiraSans-Regular.otf";
|
|
|
|
add_task(async function() {
|
|
await new Promise(resolve => waitForFocus(resolve, window));
|
|
|
|
await BrowserTestUtils.withNewTab({
|
|
gBrowser,
|
|
url: kPageURL
|
|
}, async function(aBrowser) {
|
|
function runProcess(aCmd, aArgs, blocking = true) {
|
|
let cmdFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
|
|
cmdFile.initWithPath(aCmd);
|
|
|
|
let process = Cc["@mozilla.org/process/util;1"]
|
|
.createInstance(Ci.nsIProcess);
|
|
process.init(cmdFile);
|
|
process.run(blocking, aArgs, aArgs.length);
|
|
return process.exitValue;
|
|
}
|
|
|
|
// Register the font at path |fontPath| and wait
|
|
// for the brower to detect the change.
|
|
async function registerFont(fontPath) {
|
|
let fontRegistered = getFontNotificationPromise();
|
|
let exitCode = runProcess(kPythonPath, [kFontInstallerPath, kVerboseFlag,
|
|
fontPath]);
|
|
Assert.ok(exitCode == 0, "registering font" + fontPath);
|
|
if (exitCode == 0) {
|
|
// Wait for the font registration to be detected by the browser.
|
|
await fontRegistered;
|
|
}
|
|
}
|
|
|
|
// Unregister the font at path |fontPath|. If |waitForUnreg| is true,
|
|
// don't wait for the browser to detect the change and don't use
|
|
// the verbose arg for the unregister command.
|
|
async function unregisterFont(fontPath, waitForUnreg = true) {
|
|
let args = [kFontInstallerPath, kUninstallFlag];
|
|
let fontUnregistered;
|
|
|
|
if (waitForUnreg) {
|
|
args.push(kVerboseFlag);
|
|
fontUnregistered = getFontNotificationPromise();
|
|
}
|
|
|
|
let exitCode = runProcess(kPythonPath, args.concat(fontPath));
|
|
if (waitForUnreg) {
|
|
Assert.ok(exitCode == 0, "unregistering font" + fontPath);
|
|
if (exitCode == 0) {
|
|
await fontUnregistered;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Pref "font.internaluseonly.changed" is updated when system
|
|
// fonts change. We use it to wait for changes to be detected
|
|
// in the browser.
|
|
let prefBranch =
|
|
Services.prefs.getBranch("font.internaluseonly.");
|
|
|
|
// Returns a promise that resolves when the pref is changed
|
|
let getFontNotificationPromise = () => new Promise(resolve => {
|
|
let prefObserver = {
|
|
QueryInterface: ChromeUtils.generateQI([Ci.nsIObserver]),
|
|
observe() {
|
|
prefBranch.removeObserver("changed", prefObserver);
|
|
resolve();
|
|
},
|
|
};
|
|
prefBranch.addObserver("changed", prefObserver);
|
|
});
|
|
|
|
let homeDir = Services.dirsvc.get("Home", Ci.nsIFile);
|
|
let privateFontPath = homeDir.path + kPrivateFontSubPath;
|
|
|
|
registerCleanupFunction(function() {
|
|
unregisterFont(privateFontPath, /* waitForUnreg = */ false);
|
|
runProcess("/bin/rm", [privateFontPath], /* blocking = */ false);
|
|
});
|
|
|
|
// Copy the font file to the private path.
|
|
runProcess("/bin/cp", [kRepoFontPath, privateFontPath]);
|
|
|
|
// Cleanup previous aborted tests.
|
|
unregisterFont(privateFontPath, /* waitForUnreg = */ false);
|
|
|
|
await registerFont(privateFontPath);
|
|
|
|
// Get a list of fonts being used to display the web content.
|
|
let fontList = await ContentTask.spawn(aBrowser, {}, async function() {
|
|
Cu.importGlobalProperties(["InspectorUtils"]);
|
|
|
|
let window = content.window.wrappedJSObject;
|
|
let range = window.document.createRange();
|
|
let contentDiv = window.document.getElementById("content");
|
|
range.selectNode(contentDiv);
|
|
let fonts = InspectorUtils.getUsedFontFaces(range);
|
|
|
|
let fontList = [];
|
|
for (let i = 0; i < fonts.length; i++) {
|
|
fontList.push({name: fonts[i].name});
|
|
}
|
|
return fontList;
|
|
});
|
|
|
|
let lastResortFontUsed = false;
|
|
let testFontUsed = false;
|
|
|
|
for (let font of fontList) {
|
|
// Did we fall back to the "LastResort" font?
|
|
if (!lastResortFontUsed && font.name.includes(kLastResortFontName)) {
|
|
lastResortFontUsed = true;
|
|
continue;
|
|
}
|
|
// Did we render using our test font as expected?
|
|
if (!testFontUsed && font.name.includes(kTestFontName)) {
|
|
testFontUsed = true;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
Assert.ok(!lastResortFontUsed,
|
|
`The ${kLastResortFontName} fallback font was not used`);
|
|
|
|
Assert.ok(testFontUsed,
|
|
`The test font "${kTestFontName}" was used`);
|
|
|
|
await unregisterFont(privateFontPath);
|
|
});
|
|
});
|