fune/security/sandbox/test/browser_bug1393259.js
Kris Maglione 25c94b46d8 Bug 1481021: Part 1 - Fix tests that rely on permissive COWs or SpecialPowers side-effects in frame script scopes. r=bz
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
2018-08-07 14:13:06 -07:00

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);
});
});