зеркало из https://github.com/mozilla/gecko-dev.git
Bug 418986 - Resist fingerprinting by preventing exposure of screen and system info. r=mrbkap, r=heycam
This commit is contained in:
Родитель
920f2ea28a
Коммит
8b3f3fad35
|
@ -253,6 +253,7 @@ bool nsContentUtils::sIsResourceTimingEnabled = false;
|
|||
bool nsContentUtils::sIsUserTimingLoggingEnabled = false;
|
||||
bool nsContentUtils::sIsExperimentalAutocompleteEnabled = false;
|
||||
bool nsContentUtils::sEncodeDecodeURLHash = false;
|
||||
bool nsContentUtils::sPrivacyResistFingerprinting = false;
|
||||
|
||||
uint32_t nsContentUtils::sHandlingInputTimeout = 1000;
|
||||
|
||||
|
@ -533,6 +534,9 @@ nsContentUtils::Init()
|
|||
Preferences::AddBoolVarCache(&sEncodeDecodeURLHash,
|
||||
"dom.url.encode_decode_hash", false);
|
||||
|
||||
Preferences::AddBoolVarCache(&sPrivacyResistFingerprinting,
|
||||
"privacy.resistFingerprinting", false);
|
||||
|
||||
Preferences::AddUintVarCache(&sHandlingInputTimeout,
|
||||
"dom.event.handling-user-input-time-limit",
|
||||
1000);
|
||||
|
@ -1989,6 +1993,16 @@ nsContentUtils::IsCallerChrome()
|
|||
return xpc::IsUniversalXPConnectEnabled(GetCurrentJSContext());
|
||||
}
|
||||
|
||||
bool
|
||||
nsContentUtils::ShouldResistFingerprinting(nsIDocShell* aDocShell)
|
||||
{
|
||||
if (!aDocShell) {
|
||||
return false;
|
||||
}
|
||||
bool isChrome = nsContentUtils::IsChromeDoc(aDocShell->GetDocument());
|
||||
return !isChrome && sPrivacyResistFingerprinting;
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace workers {
|
||||
|
|
|
@ -199,6 +199,9 @@ public:
|
|||
JS::Handle<jsid> aId,
|
||||
JS::MutableHandle<JSPropertyDescriptor> aDesc);
|
||||
|
||||
// Check whether we should avoid leaking distinguishing information to JS/CSS.
|
||||
static bool ShouldResistFingerprinting(nsIDocShell* aDocShell);
|
||||
|
||||
/**
|
||||
* Returns the parent node of aChild crossing document boundaries.
|
||||
* Uses the parent node in the composed document.
|
||||
|
@ -1913,6 +1916,16 @@ public:
|
|||
return sEncodeDecodeURLHash;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if the browser should attempt to prevent content scripts
|
||||
* from collecting distinctive information about the browser that could
|
||||
* be used to "fingerprint" and track the user across websites.
|
||||
*/
|
||||
static bool ResistFingerprinting()
|
||||
{
|
||||
return sPrivacyResistFingerprinting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the doc tree branch which contains aDoc contains any
|
||||
* plugins which we don't control event dispatch for, i.e. do any plugins
|
||||
|
@ -2453,6 +2466,7 @@ private:
|
|||
static bool sIsUserTimingLoggingEnabled;
|
||||
static bool sIsExperimentalAutocompleteEnabled;
|
||||
static bool sEncodeDecodeURLHash;
|
||||
static bool sPrivacyResistFingerprinting;
|
||||
|
||||
static nsHtml5StringParser* sHTMLFragmentParser;
|
||||
static nsIParser* sXMLFragmentParser;
|
||||
|
|
|
@ -5003,6 +5003,12 @@ nsGlobalWindow::GetOuterSize(ErrorResult& aError)
|
|||
{
|
||||
MOZ_ASSERT(IsOuterWindow());
|
||||
|
||||
if (nsContentUtils::ShouldResistFingerprinting(mDocShell)) {
|
||||
CSSIntSize size;
|
||||
aError = GetInnerSize(size);
|
||||
return nsIntSize(size.width, size.height);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
|
||||
if (!treeOwnerAsWin) {
|
||||
aError.Throw(NS_ERROR_FAILURE);
|
||||
|
@ -5167,6 +5173,11 @@ nsGlobalWindow::GetScreenXY(ErrorResult& aError)
|
|||
{
|
||||
MOZ_ASSERT(IsOuterWindow());
|
||||
|
||||
// When resisting fingerprinting, always return (0,0)
|
||||
if (nsContentUtils::ShouldResistFingerprinting(mDocShell)) {
|
||||
return nsIntPoint(0, 0);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
|
||||
if (!treeOwnerAsWin) {
|
||||
aError.Throw(NS_ERROR_FAILURE);
|
||||
|
@ -5240,6 +5251,11 @@ nsGlobalWindow::GetMozInnerScreenX(ErrorResult& aError)
|
|||
{
|
||||
FORWARD_TO_OUTER_OR_THROW(GetMozInnerScreenX, (aError), aError, 0);
|
||||
|
||||
// When resisting fingerprinting, always return 0.
|
||||
if (nsContentUtils::ShouldResistFingerprinting(mDocShell)) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
nsRect r = GetInnerScreenRect();
|
||||
return nsPresContext::AppUnitsToFloatCSSPixels(r.x);
|
||||
}
|
||||
|
@ -5258,6 +5274,11 @@ nsGlobalWindow::GetMozInnerScreenY(ErrorResult& aError)
|
|||
{
|
||||
FORWARD_TO_OUTER_OR_THROW(GetMozInnerScreenY, (aError), aError, 0);
|
||||
|
||||
// Return 0 to prevent fingerprinting.
|
||||
if (nsContentUtils::ShouldResistFingerprinting(mDocShell)) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
nsRect r = GetInnerScreenRect();
|
||||
return nsPresContext::AppUnitsToFloatCSSPixels(r.y);
|
||||
}
|
||||
|
@ -5286,6 +5307,10 @@ nsGlobalWindow::GetDevicePixelRatio(ErrorResult& aError)
|
|||
return 1.0;
|
||||
}
|
||||
|
||||
if (nsContentUtils::ShouldResistFingerprinting(mDocShell)) {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
return float(nsPresContext::AppUnitsPerCSSPixel())/
|
||||
presContext->AppUnitsPerDevPixel();
|
||||
}
|
||||
|
|
|
@ -1059,6 +1059,8 @@ public:
|
|||
bool aShowDialog, mozilla::ErrorResult& aError);
|
||||
uint64_t GetMozPaintCount(mozilla::ErrorResult& aError);
|
||||
|
||||
bool ShouldResistFingerprinting();
|
||||
|
||||
mozilla::dom::MozSelfSupport* GetMozSelfSupport(mozilla::ErrorResult& aError);
|
||||
|
||||
already_AddRefed<nsIDOMWindow> OpenDialog(JSContext* aCx,
|
||||
|
|
|
@ -68,6 +68,11 @@ NS_IMPL_RELEASE_INHERITED(nsScreen, DOMEventTargetHelper)
|
|||
int32_t
|
||||
nsScreen::GetPixelDepth(ErrorResult& aRv)
|
||||
{
|
||||
// Return 24 to prevent fingerprinting.
|
||||
if (ShouldResistFingerprinting()) {
|
||||
return 24;
|
||||
}
|
||||
|
||||
nsDeviceContext* context = GetDeviceContext();
|
||||
|
||||
if (!context) {
|
||||
|
@ -111,6 +116,11 @@ nsScreen::GetDeviceContext()
|
|||
nsresult
|
||||
nsScreen::GetRect(nsRect& aRect)
|
||||
{
|
||||
// Return window inner rect to prevent fingerprinting.
|
||||
if (ShouldResistFingerprinting()) {
|
||||
return GetWindowInnerRect(aRect);
|
||||
}
|
||||
|
||||
nsDeviceContext *context = GetDeviceContext();
|
||||
|
||||
if (!context) {
|
||||
|
@ -130,6 +140,11 @@ nsScreen::GetRect(nsRect& aRect)
|
|||
nsresult
|
||||
nsScreen::GetAvailRect(nsRect& aRect)
|
||||
{
|
||||
// Return window inner rect to prevent fingerprinting.
|
||||
if (ShouldResistFingerprinting()) {
|
||||
return GetWindowInnerRect(aRect);
|
||||
}
|
||||
|
||||
nsDeviceContext *context = GetDeviceContext();
|
||||
|
||||
if (!context) {
|
||||
|
@ -166,22 +181,26 @@ nsScreen::Notify(const hal::ScreenConfiguration& aConfiguration)
|
|||
void
|
||||
nsScreen::GetMozOrientation(nsString& aOrientation)
|
||||
{
|
||||
switch (mOrientation) {
|
||||
case eScreenOrientation_PortraitPrimary:
|
||||
aOrientation.AssignLiteral("portrait-primary");
|
||||
break;
|
||||
case eScreenOrientation_PortraitSecondary:
|
||||
aOrientation.AssignLiteral("portrait-secondary");
|
||||
break;
|
||||
case eScreenOrientation_LandscapePrimary:
|
||||
if (ShouldResistFingerprinting()) {
|
||||
aOrientation.AssignLiteral("landscape-primary");
|
||||
break;
|
||||
case eScreenOrientation_LandscapeSecondary:
|
||||
aOrientation.AssignLiteral("landscape-secondary");
|
||||
break;
|
||||
case eScreenOrientation_None:
|
||||
default:
|
||||
MOZ_CRASH("Unacceptable mOrientation value");
|
||||
} else {
|
||||
switch (mOrientation) {
|
||||
case eScreenOrientation_PortraitPrimary:
|
||||
aOrientation.AssignLiteral("portrait-primary");
|
||||
break;
|
||||
case eScreenOrientation_PortraitSecondary:
|
||||
aOrientation.AssignLiteral("portrait-secondary");
|
||||
break;
|
||||
case eScreenOrientation_LandscapePrimary:
|
||||
aOrientation.AssignLiteral("landscape-primary");
|
||||
break;
|
||||
case eScreenOrientation_LandscapeSecondary:
|
||||
aOrientation.AssignLiteral("landscape-secondary");
|
||||
break;
|
||||
case eScreenOrientation_None:
|
||||
default:
|
||||
MOZ_CRASH("Unacceptable mOrientation value");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -373,3 +392,27 @@ nsScreen::FullScreenEventListener::HandleEvent(nsIDOMEvent* aEvent)
|
|||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsScreen::GetWindowInnerRect(nsRect& aRect)
|
||||
{
|
||||
aRect.x = 0;
|
||||
aRect.y = 0;
|
||||
nsCOMPtr<nsIDOMWindow> win = GetOwner();
|
||||
if (!win) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
nsresult rv = win->GetInnerWidth(&aRect.width);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return win->GetInnerHeight(&aRect.height);
|
||||
}
|
||||
|
||||
bool nsScreen::ShouldResistFingerprinting() const
|
||||
{
|
||||
bool resist = false;
|
||||
nsCOMPtr<nsPIDOMWindow> owner = GetOwner();
|
||||
if (owner) {
|
||||
resist = nsContentUtils::ShouldResistFingerprinting(owner->GetDocShell());
|
||||
}
|
||||
return resist;
|
||||
}
|
||||
|
|
|
@ -131,6 +131,7 @@ protected:
|
|||
nsDeviceContext* GetDeviceContext();
|
||||
nsresult GetRect(nsRect& aRect);
|
||||
nsresult GetAvailRect(nsRect& aRect);
|
||||
nsresult GetWindowInnerRect(nsRect& aRect);
|
||||
|
||||
mozilla::dom::ScreenOrientation mOrientation;
|
||||
|
||||
|
@ -158,6 +159,8 @@ private:
|
|||
|
||||
bool IsDeviceSizePageSize();
|
||||
|
||||
bool ShouldResistFingerprinting() const;
|
||||
|
||||
nsRefPtr<FullScreenEventListener> mEventListener;
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
// The main test function.
|
||||
let test = function (isContent) {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
let { ww } = SpecialPowers.Services;
|
||||
window.chromeWindow = ww.activeWindow;
|
||||
|
||||
// The pairs of values expected to be the same when
|
||||
// fingerprinting resistance is enabled.
|
||||
let pairs = [
|
||||
["screenX", 0],
|
||||
["screenY", 0],
|
||||
["mozInnerScreenX", 0],
|
||||
["mozInnerScreenY", 0],
|
||||
["screen.pixelDepth", 24],
|
||||
["screen.colorDepth", 24],
|
||||
["screen.availWidth", "innerWidth"],
|
||||
["screen.availHeight", "innerHeight"],
|
||||
["screen.left", 0],
|
||||
["screen.top", 0],
|
||||
["screen.availLeft", 0],
|
||||
["screen.availTop", 0],
|
||||
["screen.width", "innerWidth"],
|
||||
["screen.height", "innerHeight"],
|
||||
["screen.mozOrientation", "'landscape-primary'"],
|
||||
["devicePixelRatio", 1]
|
||||
];
|
||||
|
||||
// checkPair: tests if members of pair [a, b] are equal when evaluated.
|
||||
let checkPair = function (a, b) {
|
||||
is(eval(a), eval(b), a + " should be equal to " + b);
|
||||
};
|
||||
|
||||
// Returns generator object that iterates through pref values.
|
||||
let prefVals = (for (prefVal of [false, true]) prefVal);
|
||||
|
||||
// The main test function, runs until all pref values are exhausted.
|
||||
let nextTest = function () {
|
||||
let {value : prefValue, done} = prefVals.next();
|
||||
if (done) {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
SpecialPowers.pushPrefEnv({set : [["privacy.resistFingerprinting", prefValue]]},
|
||||
function () {
|
||||
// We will be resisting fingerprinting if the pref is enabled,
|
||||
// and we are in a content script (not chrome).
|
||||
let resisting = prefValue && isContent;
|
||||
// Check each of the pairs.
|
||||
pairs.map(function ([item, onVal]) {
|
||||
if (resisting) {
|
||||
checkPair("window." + item, onVal);
|
||||
} else {
|
||||
if (!item.startsWith("moz")) {
|
||||
checkPair("window." + item, "chromeWindow." + item);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (!resisting) {
|
||||
// Hard to predict these values, but we can enforce constraints:
|
||||
ok(window.mozInnerScreenX >= chromeWindow.mozInnerScreenX,
|
||||
"mozInnerScreenX");
|
||||
ok(window.mozInnerScreenY >= chromeWindow.mozInnerScreenY,
|
||||
"mozInnerScreenY");
|
||||
}
|
||||
nextTest();
|
||||
});
|
||||
}
|
||||
|
||||
nextTest();
|
||||
}
|
|
@ -3,6 +3,7 @@ skip-if = buildapp == 'b2g'
|
|||
support-files =
|
||||
blockNoPlugins.xml
|
||||
blockPluginHard.xml
|
||||
bug418986-1.js
|
||||
cpows_child.js
|
||||
cpows_parent.xul
|
||||
file_bug391728.html
|
||||
|
@ -31,6 +32,7 @@ support-files =
|
|||
[test_bug380418.html^headers^]
|
||||
[test_bug383430.html]
|
||||
[test_bug391728.html]
|
||||
[test_bug418986-1.xul]
|
||||
[test_bug421622.xul]
|
||||
[test_bug429785.xul]
|
||||
[test_bug430050.xul]
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
|
||||
type="text/css"?>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=418986-1
|
||||
-->
|
||||
<window title="Mozilla Bug 418986 (Part 1)"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
|
||||
<!-- test results are displayed in the html:body -->
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=418986-1"
|
||||
target="_blank">Mozilla Bug 418986 (Part 1)</a>
|
||||
|
||||
<script type="application/javascript;version=1.7" src="bug418986-1.js"></script>
|
||||
<!-- test code goes here -->
|
||||
<script type="application/javascript"><![CDATA[
|
||||
window.onload = function() {
|
||||
test(false);
|
||||
};
|
||||
]]></script>
|
||||
</body>
|
||||
</window>
|
|
@ -56,6 +56,7 @@ support-files =
|
|||
bug704320.sjs
|
||||
bug704320_counter.sjs
|
||||
bug819051.sjs
|
||||
chrome/bug418986-1.js
|
||||
copypaste.js
|
||||
delayedServerEvents.sjs
|
||||
echo.sjs
|
||||
|
@ -453,6 +454,7 @@ support-files = test_bug402150.html^headers^
|
|||
[test_bug417255.html]
|
||||
[test_bug417384.html]
|
||||
[test_bug418214.html]
|
||||
[test_bug418986-1.html]
|
||||
[test_bug419132.html]
|
||||
[test_bug419527.xhtml]
|
||||
[test_bug420609.xhtml]
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=418986
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test 1/3 for Bug 418986 - Resist fingerprinting by preventing exposure of screen and system info</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript;version=1.7" src="chrome/bug418986-1.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=418986">Bug 418986</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test"></pre>
|
||||
<script>
|
||||
window.onload = function() {
|
||||
test(true);
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -890,6 +890,13 @@ Event::GetScreenCoords(nsPresContext* aPresContext,
|
|||
WidgetEvent* aEvent,
|
||||
LayoutDeviceIntPoint aPoint)
|
||||
{
|
||||
if (!nsContentUtils::IsCallerChrome() &&
|
||||
nsContentUtils::ResistFingerprinting()) {
|
||||
// When resisting fingerprinting, return client coordinates instead.
|
||||
CSSIntPoint clientCoords = GetClientCoords(aPresContext, aEvent, aPoint, CSSIntPoint(0, 0));
|
||||
return LayoutDeviceIntPoint(clientCoords.x, clientCoords.y);
|
||||
}
|
||||
|
||||
if (EventStateManager::sIsPointerLocked) {
|
||||
return EventStateManager::sLastScreenPoint;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// The main testing function.
|
||||
let test = function (isContent) {
|
||||
// Each definition is [eventType, prefSetting]
|
||||
// Where we are setting the "privacy.resistFingerprinting" pref.
|
||||
let eventDefs = [["mousedown", true],
|
||||
["mouseup", true],
|
||||
["mousedown", false],
|
||||
["mouseup", false]];
|
||||
|
||||
let testCounter = 0;
|
||||
|
||||
// Declare ahead of time.
|
||||
let setup;
|
||||
|
||||
// This function is called when the event handler fires.
|
||||
let handleEvent = function (event, prefVal) {
|
||||
let resisting = prefVal && isContent;
|
||||
if (resisting) {
|
||||
is(event.screenX, event.clientX, "event.screenX and event.clientX should be the same");
|
||||
is(event.screenY, event.clientY, "event.screenY and event.clientY should be the same");
|
||||
} else {
|
||||
// We can't be sure about X coordinates not being equal, but we can test Y.
|
||||
isnot(event.screenY, event.clientY, "event.screenY !== event.clientY");
|
||||
}
|
||||
++testCounter;
|
||||
if (testCounter < eventDefs.length) {
|
||||
nextTest();
|
||||
} else {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
};
|
||||
|
||||
// In this function, we set up the nth div and event handler,
|
||||
// and then synthesize a mouse event in the div, to test
|
||||
// whether the resulting events resist fingerprinting by
|
||||
// suppressing absolute screen coordinates.
|
||||
nextTest = function () {
|
||||
let [eventType, prefVal] = eventDefs[testCounter];
|
||||
SpecialPowers.pushPrefEnv({set:[["privacy.resistFingerprinting", prefVal]]},
|
||||
function () {
|
||||
// The following code creates a new div for each event in eventDefs,
|
||||
// attaches a listener to listen for the event, and then generates
|
||||
// a fake event at the center of the div.
|
||||
let div = document.createElement("div");
|
||||
div.style.width = "10px";
|
||||
div.style.height = "10px";
|
||||
div.style.backgroundColor = "red";
|
||||
// Name the div after the event we're listening for.
|
||||
div.id = eventType;
|
||||
document.getElementById("body").appendChild(div);
|
||||
// Seems we can't add an event listener in chrome unless we run
|
||||
// it in a later task.
|
||||
window.setTimeout(function() {
|
||||
div.addEventListener(eventType, event => handleEvent(event, prefVal), false);
|
||||
// For some reason, the following synthesizeMouseAtCenter call only seems to run if we
|
||||
// wrap it in a window.setTimeout(..., 0).
|
||||
window.setTimeout(function () {
|
||||
synthesizeMouseAtCenter(div, {type : eventType});
|
||||
}, 0);
|
||||
}, 0);
|
||||
});
|
||||
};
|
||||
|
||||
// Now run by starting with the 0th event.
|
||||
nextTest();
|
||||
|
||||
};
|
|
@ -3,6 +3,7 @@ skip-if = buildapp == 'b2g'
|
|||
support-files =
|
||||
bug415498-doc1.html
|
||||
bug415498-doc2.html
|
||||
bug418986-3.js
|
||||
bug591249_iframe.xul
|
||||
bug602962.xul
|
||||
file_bug679494.html
|
||||
|
@ -12,6 +13,7 @@ support-files =
|
|||
[test_bug336682_2.xul]
|
||||
[test_bug368835.html]
|
||||
[test_bug415498.xul]
|
||||
[test_bug418986-3.xul]
|
||||
[test_bug524674.xul]
|
||||
[test_bug586961.xul]
|
||||
[test_bug591249.xul]
|
||||
|
|
|
@ -7,6 +7,7 @@ support-files =
|
|||
bug426082.html
|
||||
bug648573.html
|
||||
bug656379-1.html
|
||||
bug418986-3.js
|
||||
error_event_worker.js
|
||||
empty.js
|
||||
window_bug493251.html
|
||||
|
@ -38,6 +39,9 @@ support-files = test_bug336682.js
|
|||
[test_bug409604.html]
|
||||
skip-if = buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT
|
||||
[test_bug412567.html]
|
||||
[test_bug418986-3.html]
|
||||
# Sometimes fails to finish after tests pass on 'B2G ICS Emulator'.
|
||||
skip-if = (os == 'b2g')
|
||||
[test_bug422132.html]
|
||||
skip-if = buildapp == 'b2g' || e10s # b2g(2 failures out of 8, mousewheel test) b2g-debug(2 failures out of 8, mousewheel test) b2g-desktop(2 failures out of 8, mousewheel test)
|
||||
[test_bug426082.html]
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=418986
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test 3/3 for Bug 418986 - Resist fingerprinting by preventing exposure of screen and system info</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body id="body">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=418986">Bug 418986</a>
|
||||
<p id="display"></p>
|
||||
<pre id="test"></pre>
|
||||
<script type="application/javascript;version=1.7" src="bug418986-3.js"></script>
|
||||
<script type="application/javascript;version=1.7">
|
||||
// This test produces fake mouse events and checks that the screenX and screenY
|
||||
// properties of the received event objects provide client window coordinates.
|
||||
// Run the test once the window has loaded.
|
||||
window.onload = () => test(true);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
|
||||
<!--
|
||||
Bug 418986
|
||||
-->
|
||||
<window title="Mozilla Bug 418986"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
|
||||
<body id="body" xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=418986">
|
||||
Mozilla Bug 418986</a>
|
||||
</body>
|
||||
|
||||
<script type="application/javascript;version=1.7" src="bug418986-3.js"></script>
|
||||
<script type="application/javascript;version=1.7"><![CDATA[
|
||||
// This test produces fake mouse events and checks that the screenX and screenY
|
||||
// properties of the received event objects provide client window coordinates.
|
||||
// Run the test once the window has loaded.
|
||||
test(false);
|
||||
]]></script>
|
||||
|
||||
</window>
|
|
@ -1450,6 +1450,10 @@ nsComputedDOMStyle::DoGetFontSizeAdjust()
|
|||
CSSValue*
|
||||
nsComputedDOMStyle::DoGetOsxFontSmoothing()
|
||||
{
|
||||
if (nsContentUtils::ShouldResistFingerprinting(
|
||||
mPresShell->GetPresContext()->GetDocShell()))
|
||||
return nullptr;
|
||||
|
||||
nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
|
||||
val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleFont()->mFont.smoothing,
|
||||
nsCSSProps::kFontSmoothingKTable));
|
||||
|
|
|
@ -109,13 +109,19 @@ GetDeviceContextFor(nsPresContext* aPresContext)
|
|||
return aPresContext->DeviceContext();
|
||||
}
|
||||
|
||||
static bool
|
||||
ShouldResistFingerprinting(nsPresContext* aPresContext)
|
||||
{
|
||||
return nsContentUtils::ShouldResistFingerprinting(aPresContext->GetDocShell());
|
||||
}
|
||||
|
||||
// A helper for three features below.
|
||||
static nsSize
|
||||
GetDeviceSize(nsPresContext* aPresContext)
|
||||
{
|
||||
nsSize size;
|
||||
|
||||
if (aPresContext->IsDeviceSizePageSize()) {
|
||||
if (ShouldResistFingerprinting(aPresContext) || aPresContext->IsDeviceSizePageSize()) {
|
||||
size = GetSize(aPresContext);
|
||||
} else if (aPresContext->IsRootPaginatedDocument()) {
|
||||
// We want the page size, including unprintable areas and margins.
|
||||
|
@ -223,13 +229,17 @@ static nsresult
|
|||
GetColor(nsPresContext* aPresContext, const nsMediaFeature*,
|
||||
nsCSSValue& aResult)
|
||||
{
|
||||
// FIXME: This implementation is bogus. nsDeviceContext
|
||||
// doesn't provide reliable information (should be fixed in bug
|
||||
// 424386).
|
||||
// FIXME: On a monochrome device, return 0!
|
||||
nsDeviceContext *dx = GetDeviceContextFor(aPresContext);
|
||||
uint32_t depth;
|
||||
dx->GetDepth(depth);
|
||||
uint32_t depth = 24; // Use depth of 24 when resisting fingerprinting.
|
||||
|
||||
if (!ShouldResistFingerprinting(aPresContext)) {
|
||||
// FIXME: This implementation is bogus. nsDeviceContext
|
||||
// doesn't provide reliable information (should be fixed in bug
|
||||
// 424386).
|
||||
// FIXME: On a monochrome device, return 0!
|
||||
nsDeviceContext *dx = GetDeviceContextFor(aPresContext);
|
||||
dx->GetDepth(depth);
|
||||
}
|
||||
|
||||
// The spec says to use bits *per color component*, so divide by 3,
|
||||
// and round down, since the spec says to use the smallest when the
|
||||
// color components differ.
|
||||
|
@ -267,10 +277,15 @@ static nsresult
|
|||
GetResolution(nsPresContext* aPresContext, const nsMediaFeature*,
|
||||
nsCSSValue& aResult)
|
||||
{
|
||||
// Resolution measures device pixels per CSS (inch/cm/pixel). We
|
||||
// return it in device pixels per CSS inches.
|
||||
float dpi = float(nsPresContext::AppUnitsPerCSSInch()) /
|
||||
float(aPresContext->AppUnitsPerDevPixel());
|
||||
float dpi = 96; // Use 96 when resisting fingerprinting.
|
||||
|
||||
if (!ShouldResistFingerprinting(aPresContext)) {
|
||||
// Resolution measures device pixels per CSS (inch/cm/pixel). We
|
||||
// return it in device pixels per CSS inches.
|
||||
dpi = float(nsPresContext::AppUnitsPerCSSInch()) /
|
||||
float(aPresContext->AppUnitsPerDevPixel());
|
||||
}
|
||||
|
||||
aResult.SetFloatValue(dpi, eCSSUnit_Inch);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -299,15 +314,26 @@ static nsresult
|
|||
GetDevicePixelRatio(nsPresContext* aPresContext, const nsMediaFeature*,
|
||||
nsCSSValue& aResult)
|
||||
{
|
||||
float ratio = aPresContext->CSSPixelsToDevPixels(1.0f);
|
||||
aResult.SetFloatValue(ratio, eCSSUnit_Number);
|
||||
return NS_OK;
|
||||
if (!ShouldResistFingerprinting(aPresContext)) {
|
||||
float ratio = aPresContext->CSSPixelsToDevPixels(1.0f);
|
||||
aResult.SetFloatValue(ratio, eCSSUnit_Number);
|
||||
} else {
|
||||
aResult.SetFloatValue(1.0, eCSSUnit_Number);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static nsresult
|
||||
GetSystemMetric(nsPresContext* aPresContext, const nsMediaFeature* aFeature,
|
||||
nsCSSValue& aResult)
|
||||
{
|
||||
aResult.Reset();
|
||||
if (ShouldResistFingerprinting(aPresContext)) {
|
||||
// If "privacy.resistFingerprinting" is enabled, then we simply don't
|
||||
// return any system-backed media feature values. (No spoofed values returned.)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(aFeature->mValueType == nsMediaFeature::eBoolInteger,
|
||||
"unexpected type");
|
||||
nsIAtom *metricAtom = *aFeature->mData.mMetric;
|
||||
|
@ -321,6 +347,10 @@ GetWindowsTheme(nsPresContext* aPresContext, const nsMediaFeature* aFeature,
|
|||
nsCSSValue& aResult)
|
||||
{
|
||||
aResult.Reset();
|
||||
if (ShouldResistFingerprinting(aPresContext)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
uint8_t windowsThemeId =
|
||||
nsCSSRuleProcessor::GetWindowsThemeIdentifier();
|
||||
|
@ -346,6 +376,10 @@ GetOperatinSystemVersion(nsPresContext* aPresContext, const nsMediaFeature* aFea
|
|||
nsCSSValue& aResult)
|
||||
{
|
||||
aResult.Reset();
|
||||
if (ShouldResistFingerprinting(aPresContext)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
int32_t metricResult;
|
||||
if (NS_SUCCEEDED(
|
||||
|
|
|
@ -0,0 +1,274 @@
|
|||
// # Bug 418986, part 2.
|
||||
|
||||
/* jshint esnext:true */
|
||||
/* jshint loopfunc:true */
|
||||
/* global window, screen, ok, SpecialPowers, matchMedia */
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// Expected values. Format: [name, pref_off_value, pref_on_value]
|
||||
// If pref_*_value is an array with two values, then we will match
|
||||
// any value in between those two values. If a value is null, then
|
||||
// we skip the media query.
|
||||
let expected_values = [
|
||||
["color", null, 8],
|
||||
["color-index", null, 0],
|
||||
["aspect-ratio", null, window.innerWidth + "/" + window.innerHeight],
|
||||
["device-aspect-ratio", screen.width + "/" + screen.height,
|
||||
window.innerWidth + "/" + window.innerHeight],
|
||||
["device-height", screen.height + "px", window.innerHeight + "px"],
|
||||
["device-width", screen.width + "px", window.innerWidth + "px"],
|
||||
["grid", null, 0],
|
||||
["height", window.innerHeight + "px", window.innerHeight + "px"],
|
||||
["monochrome", null, 0],
|
||||
// Square is defined as portrait:
|
||||
["orientation", null,
|
||||
window.innerWidth > window.innerHeight ?
|
||||
"landscape" : "portrait"],
|
||||
["resolution", null, "96dpi"],
|
||||
["resolution", [0.999 * window.devicePixelRatio + "dppx",
|
||||
1.001 * window.devicePixelRatio + "dppx"], "1dppx"],
|
||||
["width", window.innerWidth + "px", window.innerWidth + "px"],
|
||||
["-moz-device-pixel-ratio", window.devicePixelRatio, 1],
|
||||
["-moz-device-orientation", screen.width > screen.height ?
|
||||
"landscape" : "portrait",
|
||||
window.innerWidth > window.innerHeight ?
|
||||
"landscape" : "portrait"]
|
||||
];
|
||||
|
||||
// These media queries return value 0 or 1 when the pref is off.
|
||||
// When the pref is on, they should not match.
|
||||
let suppressed_toggles = [
|
||||
"-moz-images-in-menus",
|
||||
"-moz-mac-graphite-theme",
|
||||
// Not available on most OSs.
|
||||
// "-moz-maemo-classic",
|
||||
"-moz-scrollbar-end-backward",
|
||||
"-moz-scrollbar-end-forward",
|
||||
"-moz-scrollbar-start-backward",
|
||||
"-moz-scrollbar-start-forward",
|
||||
"-moz-scrollbar-thumb-proportional",
|
||||
"-moz-touch-enabled",
|
||||
"-moz-windows-compositor",
|
||||
"-moz-windows-default-theme",
|
||||
"-moz-windows-glass",
|
||||
];
|
||||
|
||||
// Possible values for '-moz-os-version'
|
||||
let windows_versions = [
|
||||
"windows-xp",
|
||||
"windows-vista",
|
||||
"windows-win7",
|
||||
"windows-win8"];
|
||||
|
||||
// Possible values for '-moz-windows-theme'
|
||||
let windows_themes = [
|
||||
"aero",
|
||||
"luna-blue",
|
||||
"luna-olive",
|
||||
"luna-silver",
|
||||
"royale",
|
||||
"generic",
|
||||
"zune"
|
||||
];
|
||||
|
||||
// Read the current OS.
|
||||
let OS = SpecialPowers.Services.appinfo.OS;
|
||||
|
||||
// If we are using Windows, add an extra toggle only
|
||||
// available on that OS.
|
||||
if (OS === "WINNT") {
|
||||
suppressed_toggles.push("-moz-windows-classic");
|
||||
}
|
||||
|
||||
// __keyValMatches(key, val)__.
|
||||
// Runs a media query and returns true if key matches to val.
|
||||
let keyValMatches = (key, val) => matchMedia("(" + key + ":" + val +")").matches;
|
||||
|
||||
// __testMatch(key, val)__.
|
||||
// Attempts to run a media query match for the given key and value.
|
||||
// If value is an array of two elements [min max], then matches any
|
||||
// value in-between.
|
||||
let testMatch = function (key, val) {
|
||||
if (val === null) {
|
||||
return;
|
||||
} else if (Array.isArray(val)) {
|
||||
ok(keyValMatches("min-" + key, val[0]) && keyValMatches("max-" + key, val[1]),
|
||||
"Expected " + key + " between " + val[0] + " and " + val[1]);
|
||||
} else {
|
||||
ok(keyValMatches(key, val), "Expected " + key + ":" + val);
|
||||
}
|
||||
};
|
||||
|
||||
// __testToggles(resisting)__.
|
||||
// Test whether we are able to match the "toggle" media queries.
|
||||
let testToggles = function (resisting) {
|
||||
suppressed_toggles.forEach(
|
||||
function (key) {
|
||||
var exists = keyValMatches(key, 0) || keyValMatches(key, 1);
|
||||
if (resisting) {
|
||||
ok(!exists, key + " should not exist.");
|
||||
} else {
|
||||
ok(exists, key + " should exist.");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// __testWindowsSpecific__.
|
||||
// Runs a media query on the queryName with the given possible matching values.
|
||||
let testWindowsSpecific = function (resisting, queryName, possibleValues) {
|
||||
let found = false;
|
||||
possibleValues.forEach(function (val) {
|
||||
found = found || keyValMatches(queryName, val);
|
||||
});
|
||||
if (resisting) {
|
||||
ok(!found, queryName + " should have no match");
|
||||
} else {
|
||||
ok(found, queryName + " should match");
|
||||
}
|
||||
};
|
||||
|
||||
// __generateHtmlLines(resisting)__.
|
||||
// Create a series of div elements that look like:
|
||||
// `<div class='spoof' id='resolution'>resolution</div>`,
|
||||
// where each line corresponds to a different media query.
|
||||
let generateHtmlLines = function (resisting) {
|
||||
let lines = "";
|
||||
expected_values.forEach(
|
||||
function ([key, offVal, onVal]) {
|
||||
let val = resisting ? onVal : offVal;
|
||||
if (val) {
|
||||
lines += "<div class='spoof' id='" + key + "'>" + key + "</div>\n";
|
||||
}
|
||||
});
|
||||
suppressed_toggles.forEach(
|
||||
function (key) {
|
||||
lines += "<div class='suppress' id='" + key + "'>" + key + "</div>\n";
|
||||
});
|
||||
if (OS === "WINNT") {
|
||||
lines += "<div class='windows' id='-moz-os-version'>-moz-os-version</div>";
|
||||
lines += "<div class='windows' id='-moz-windows-theme'>-moz-windows-theme</div>";
|
||||
}
|
||||
return lines;
|
||||
};
|
||||
|
||||
// __cssLine__.
|
||||
// Creates a line of css that looks something like
|
||||
// `@media (resolution: 1ppx) { .spoof#resolution { background-color: green; } }`.
|
||||
let cssLine = function (query, clazz, id, color) {
|
||||
return "@media " + query + " { ." + clazz + "#" + id +
|
||||
" { background-color: " + color + "; } }\n";
|
||||
};
|
||||
|
||||
// __mediaQueryCSSLine(key, val, color)__.
|
||||
// Creates a line containing a CSS media query and a CSS expression.
|
||||
let mediaQueryCSSLine = function (key, val, color) {
|
||||
if (val === null) {
|
||||
return "";
|
||||
}
|
||||
let query;
|
||||
if (Array.isArray(val)) {
|
||||
query = "(min-" + key + ": " + val[0] + ") and (max-" + key + ": " + val[1] + ")";
|
||||
} else {
|
||||
query = "(" + key + ": " + val + ")";
|
||||
}
|
||||
return cssLine(query, "spoof", key, color);
|
||||
};
|
||||
|
||||
// __suppressedMediaQueryCSSLine(key, color)__.
|
||||
// Creates a CSS line that matches the existence of a
|
||||
// media query that is supposed to be suppressed.
|
||||
let suppressedMediaQueryCSSLine = function (key, color, suppressed) {
|
||||
let query = "(" + key + ": 0), (" + key + ": 1)";
|
||||
return cssLine(query, "suppress", key, color);
|
||||
};
|
||||
|
||||
// __generateCSSLines(resisting)__.
|
||||
// Creates a series of lines of CSS, each of which corresponds to
|
||||
// a different media query. If the query produces a match to the
|
||||
// expected value, then the element will be colored green.
|
||||
let generateCSSLines = function (resisting) {
|
||||
let lines = ".spoof { background-color: red;}\n";
|
||||
expected_values.forEach(
|
||||
function ([key, offVal, onVal]) {
|
||||
lines += mediaQueryCSSLine(key, resisting ? onVal : offVal, "green");
|
||||
});
|
||||
lines += ".suppress { background-color: " + (resisting ? "green" : "red") + ";}\n";
|
||||
suppressed_toggles.forEach(
|
||||
function (key) {
|
||||
lines += suppressedMediaQueryCSSLine(key, resisting ? "red" : "green");
|
||||
});
|
||||
if (OS === "WINNT") {
|
||||
lines += ".windows { background-color: " + (resisting ? "green" : "red") + ";}\n";
|
||||
lines += windows_versions.map(val => "(-moz-os-version: " + val + ")").join(", ") +
|
||||
" { #-moz-os-version { background-color: " + (resisting ? "red" : "green") + ";} }\n";
|
||||
lines += windows_themes.map(val => "(-moz-windows-theme: " + val + ")").join(",") +
|
||||
" { #-moz-windows-theme { background-color: " + (resisting ? "red" : "green") + ";} }\n";
|
||||
}
|
||||
return lines;
|
||||
};
|
||||
|
||||
// __green__.
|
||||
// Returns the computed color style corresponding to green.
|
||||
let green = (function () {
|
||||
let temp = document.createElement("span");
|
||||
temp.style.backgroundColor = "green";
|
||||
return getComputedStyle(temp).backgroundColor;
|
||||
})();
|
||||
|
||||
// __testCSS(resisting)__.
|
||||
// Creates a series of divs and CSS using media queries to set their
|
||||
// background color. If all media queries match as expected, then
|
||||
// all divs should have a green background color.
|
||||
let testCSS = function (resisting) {
|
||||
document.getElementById("display").innerHTML = generateHtmlLines(resisting);
|
||||
document.getElementById("test-css").innerHTML = generateCSSLines(resisting);
|
||||
let cssTestDivs = document.querySelectorAll(".spoof,.suppress");
|
||||
for (let div of cssTestDivs) {
|
||||
let color = window.getComputedStyle(div).backgroundColor;
|
||||
ok(color === green, "CSS for '" + div.id + "'");
|
||||
}
|
||||
};
|
||||
|
||||
// __testOSXFontSmoothing(resisting)__.
|
||||
// When fingerprinting resistance is enabled, the `getComputedStyle`
|
||||
// should always return `undefined` for `MozOSXFontSmoothing`.
|
||||
let testOSXFontSmoothing = function (resisting) {
|
||||
let div = document.createElement("div");
|
||||
div.style.MozOsxFontSmoothing = "unset";
|
||||
let readBack = window.getComputedStyle(div).MozOsxFontSmoothing;
|
||||
let smoothingPref = SpecialPowers.getBoolPref("layout.css.osx-font-smoothing.enabled", false);
|
||||
is(readBack, resisting ? "" : (smoothingPref ? "auto" : ""),
|
||||
"-moz-osx-font-smoothing");
|
||||
};
|
||||
|
||||
// An iterator yielding pref values for two consecutive tests.
|
||||
let prefVals = (for (prefVal of [false, true]) prefVal);
|
||||
|
||||
// __test(isContent)__.
|
||||
// Run all tests.
|
||||
let test = function(isContent) {
|
||||
let {value: prefValue, done} = prefVals.next();
|
||||
if (done) {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
SpecialPowers.pushPrefEnv({set: [["privacy.resistFingerprinting", prefValue]]},
|
||||
function () {
|
||||
let resisting = prefValue && isContent;
|
||||
expected_values.forEach(
|
||||
function ([key, offVal, onVal]) {
|
||||
testMatch(key, resisting ? onVal : offVal);
|
||||
});
|
||||
testToggles(resisting);
|
||||
if (OS === "WINNT") {
|
||||
testWindowsSpecific(resisting, "-moz-os-version", windows_versions);
|
||||
testWindowsSpecific(resisting, "-moz-windows-theme", windows_themes);
|
||||
}
|
||||
testCSS(resisting);
|
||||
if (OS === "Darwin") {
|
||||
testOSXFontSmoothing(resisting);
|
||||
}
|
||||
test(isContent);
|
||||
});
|
||||
};
|
|
@ -1,6 +1,7 @@
|
|||
[DEFAULT]
|
||||
skip-if = buildapp == 'b2g'
|
||||
support-files =
|
||||
bug418986-2.js
|
||||
bug535806-css.css
|
||||
bug535806-html.html
|
||||
bug535806-xul.xul
|
||||
|
@ -9,6 +10,7 @@ support-files =
|
|||
[test_addSheet.html]
|
||||
[test_additional_sheets.html]
|
||||
[test_author_specified_style.html]
|
||||
[test_bug418986-2.xul]
|
||||
[test_bug1157097.html]
|
||||
[test_bug1160724.xul]
|
||||
[test_bug535806.xul]
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=418986
|
||||
-->
|
||||
<window title="Mozilla Bug 418986"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||
<!-- test results are displayed in the html:body -->
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<style id="test-css" scoped="true"></style>
|
||||
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=418986"
|
||||
target="_blank">Mozilla Bug 418986</a>
|
||||
<p id="display"></p>
|
||||
|
||||
</body>
|
||||
|
||||
<script type="text/javascript;version=1.7" src="bug418986-2.js"></script>
|
||||
<!-- test code goes here -->
|
||||
<script type="text/javascript;version=1.7">
|
||||
// Run all tests now.
|
||||
window.onload = function () {
|
||||
test(false);
|
||||
};
|
||||
</script>
|
||||
</window>
|
|
@ -5,6 +5,7 @@ support-files =
|
|||
ccd.sjs
|
||||
ccd-standards.html
|
||||
css_properties.js
|
||||
chrome/bug418986-2.js
|
||||
descriptor_database.js
|
||||
empty.html
|
||||
media_queries_dynamic_xbl_binding.xml
|
||||
|
@ -75,6 +76,7 @@ skip-if = true # Bug 701060
|
|||
[test_bug412901.html]
|
||||
skip-if = android_version == '18' # bug 1147986
|
||||
[test_bug413958.html]
|
||||
[test_bug418986-2.html]
|
||||
[test_bug437915.html]
|
||||
[test_bug450191.html]
|
||||
[test_bug453896_deck.html]
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=418986
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test 2/3 for Bug #418986: Resist fingerprinting by preventing exposure of screen and system info</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<style id="test-css"></style>
|
||||
<script type="text/javascript;version=1.7" src="chrome/bug418986-2.js"></script>
|
||||
<script type="text/javascript;version=1.7">
|
||||
// Run all tests now.
|
||||
window.onload = function () {
|
||||
test(true);
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=418986">Bug 418986</a>
|
||||
<p id="display">TEST</p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
Загрузка…
Ссылка в новой задаче