Merge mozilla-central to mozilla-inbound. a=merge on a CLOSED TREE

This commit is contained in:
Andreea Pavel 2018-04-11 17:40:37 +03:00
commit 29ba7b4974
86 changed files with 2520 additions and 3670 deletions

View File

@ -97,10 +97,6 @@ add_task(async function startup() {
min: 20,
max: 55,
},
// This seems to get called frequently only on infra.
"network.jar.block-remote-files": {
max: 500,
},
};
let startupRecorder = Cc["@mozilla.org/test/startuprecorder;1"].getService().wrappedJSObject;
@ -161,8 +157,6 @@ add_task(async function open_10_tabs() {
min: 5,
max: 20,
},
// This seems to get called frequently only on infra.
"network.jar.block-remote-files": { },
};
Services.prefs.resetStats();

View File

@ -240,3 +240,132 @@ add_task(async function paste_from_different_instance() {
await PlacesUtils.bookmarks.remove(tree.children[0].guid);
});
add_task(async function paste_separator_from_different_instance() {
let xferable = Cc["@mozilla.org/widget/transferable;1"]
.createInstance(Ci.nsITransferable);
xferable.init(null);
// Fake data on the clipboard to pretend this is from a different instance
// of Firefox.
let data = {
"title": "test",
"id": 32,
"instanceId": "FAKEFAKEFAKE",
"itemGuid": "ZBf_TYkrYGvW",
"parent": 452,
"dateAdded": 1464866275853000,
"lastModified": 1507638113352000,
"type": PlacesUtils.TYPE_X_MOZ_PLACE_SEPARATOR
};
data = JSON.stringify(data);
xferable.addDataFlavor(PlacesUtils.TYPE_X_MOZ_PLACE);
xferable.setTransferData(PlacesUtils.TYPE_X_MOZ_PLACE,
PlacesUtils.toISupportsString(data),
data.length * 2);
Services.clipboard.setData(xferable, null, Ci.nsIClipboard.kGlobalClipboard);
info("Selecting UnfiledBookmarks in the left pane");
PlacesOrganizer.selectLeftPaneBuiltIn("UnfiledBookmarks");
info("Pasting clipboard");
await ContentTree.view.controller.paste();
let tree = await PlacesUtils.promiseBookmarksTree(PlacesUtils.bookmarks.unfiledGuid);
Assert.equal(tree.children.length, 1,
"Should be one bookmark in the unfiled folder.");
Assert.equal(tree.children[0].type, PlacesUtils.TYPE_X_MOZ_PLACE_SEPARATOR,
"Should have the correct type");
await PlacesUtils.bookmarks.remove(tree.children[0].guid);
});
add_task(async function paste_copy_check_indexes() {
info("Selecting BookmarksToolbar in the left pane");
PlacesOrganizer.selectLeftPaneBuiltIn("BookmarksToolbar");
let copyChildren = [];
let targetChildren = [];
for (let i = 0; i < 10; i++) {
copyChildren.push({
url: `${TEST_URL}${i}`,
title: `Copy ${i}`
});
targetChildren.push({
url: `${TEST_URL1}${i}`,
title: `Target ${i}`
});
}
let copyBookmarks = await PlacesUtils.bookmarks.insertTree({
guid: PlacesUtils.bookmarks.toolbarGuid,
children: copyChildren
});
let targetBookmarks = await PlacesUtils.bookmarks.insertTree({
guid: PlacesUtils.bookmarks.unfiledGuid,
children: targetChildren
});
ContentTree.view.selectItems([
copyBookmarks[0].guid,
copyBookmarks[3].guid,
copyBookmarks[6].guid,
copyBookmarks[9].guid,
]);
await promiseClipboard(() => {
info("Cutting multiple selection");
ContentTree.view.controller.copy();
}, PlacesUtils.TYPE_X_MOZ_PLACE);
info("Selecting UnfiledBookmarks in the left pane");
PlacesOrganizer.selectLeftPaneBuiltIn("UnfiledBookmarks");
ContentTree.view.selectItems([targetBookmarks[4].guid]);
info("Pasting clipboard");
await ContentTree.view.controller.paste();
let tree = await PlacesUtils.promiseBookmarksTree(PlacesUtils.bookmarks.unfiledGuid);
const expectedBookmarkOrder = [
targetBookmarks[0].guid,
targetBookmarks[1].guid,
targetBookmarks[2].guid,
targetBookmarks[3].guid,
0,
3,
6,
9,
targetBookmarks[4].guid,
targetBookmarks[5].guid,
targetBookmarks[6].guid,
targetBookmarks[7].guid,
targetBookmarks[8].guid,
targetBookmarks[9].guid,
];
Assert.equal(tree.children.length, expectedBookmarkOrder.length,
"Should be the expected amount of bookmarks in the unfiled folder.");
for (let i = 0; i < expectedBookmarkOrder.length; ++i) {
if (i > 3 && i <= 7) {
// Items 4 - 7 are copies of the original, so we need to compare data, rather
// than their guids.
Assert.equal(tree.children[i].title, copyChildren[expectedBookmarkOrder[i]].title,
`Should have the correct bookmark title at index ${i}`);
Assert.equal(tree.children[i].uri, copyChildren[expectedBookmarkOrder[i]].url,
`Should have the correct bookmark URL at index ${i}`);
} else {
Assert.equal(tree.children[i].guid, expectedBookmarkOrder[i],
`Should be the expected item at index ${i}`);
}
}
await PlacesUtils.bookmarks.eraseEverything();
});

View File

@ -51,8 +51,6 @@ var gLanguagesDialog = {
// ab = language
// cd = region
var bundleAccepted = document.getElementById("bundleAccepted");
var bundleRegions = document.getElementById("bundleRegions");
var bundleLanguages = document.getElementById("bundleLanguages");
var bundlePreferences = document.getElementById("bundlePreferences");
function LanguageInfo(aName, aABCD, aIsVisible) {
@ -63,6 +61,9 @@ var gLanguagesDialog = {
// 1) Read the available languages out of language.properties
var strings = bundleAccepted.strings;
let localeCodes = [];
let localeValues = [];
while (strings.hasMoreElements()) {
var currString = strings.getNext();
if (!(currString instanceof Ci.nsIPropertyElement))
@ -70,41 +71,23 @@ var gLanguagesDialog = {
var property = currString.key.split("."); // ab[-cd].accept
if (property[1] == "accept") {
var abCD = property[0];
var abCDPairs = abCD.split("-"); // ab[-cd]
var useABCDFormat = abCDPairs.length > 1;
var ab = useABCDFormat ? abCDPairs[0] : abCD;
var cd = useABCDFormat ? abCDPairs[1] : "";
if (ab) {
var language = "";
try {
language = bundleLanguages.getString(ab);
} catch (e) { continue; }
var region = "";
if (useABCDFormat) {
try {
region = bundleRegions.getString(cd);
} catch (e) { continue; }
}
var name = "";
if (useABCDFormat)
name = bundlePreferences.getFormattedString("languageRegionCodeFormat",
[language, region, abCD]);
else
name = bundlePreferences.getFormattedString("languageCodeFormat",
[language, abCD]);
if (name && abCD) {
var isVisible = currString.value == "true" &&
(!(abCD in this._acceptLanguages) || !this._acceptLanguages[abCD]);
var li = new LanguageInfo(name, abCD, isVisible);
this._availableLanguagesList.push(li);
}
}
localeCodes.push(property[0]);
localeValues.push(currString.value);
}
}
let localeNames = Services.intl.getLocaleDisplayNames(undefined, localeCodes);
for (let i in localeCodes) {
let isVisible = localeValues[i] == "true" &&
(!(localeCodes[i] in this._acceptLanguages) || !this._acceptLanguages[localeCodes[i]]);
let name = bundlePreferences.getFormattedString("languageCodeFormat",
[localeNames[i], localeCodes[i]]);
let li = new LanguageInfo(name, localeCodes[i], isVisible);
this._availableLanguagesList.push(li);
}
this._buildAvailableLanguageList();
},

View File

@ -37,8 +37,6 @@
<vbox id="LanguagesDialogPane" class="prefpane largeDialogContainer">
<stringbundleset id="languageSet">
<stringbundle id="bundleRegions" src="chrome://global/locale/regionNames.properties"/>
<stringbundle id="bundleLanguages" src="chrome://global/locale/languageNames.properties"/>
<stringbundle id="bundlePreferences" src="chrome://browser/locale/preferences/preferences.properties"/>
<stringbundle id="bundleAccepted" src="resource://gre/res/language.properties"/>
</stringbundleset>

View File

@ -8,9 +8,6 @@
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
ChromeUtils.import("resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyGetter(this, "gLangBundle", () =>
Services.strings.createBundle("chrome://global/locale/languageNames.properties"));
const kPermissionType = "translate";
const kLanguagesPref = "browser.translation.neverForLanguages";
@ -76,9 +73,9 @@ Tree.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsITreeView])
};
function Lang(aCode) {
function Lang(aCode, label) {
this.langCode = aCode;
this._label = gLangBundle.GetStringFromName(aCode);
this._label = label;
}
Lang.prototype = {
@ -123,7 +120,9 @@ var gTranslationExceptions = {
if (!langs)
return [];
let result = langs.split(",").map(code => new Lang(code));
let langArr = langs.split(",");
let displayNames = Services.intl.getLanguageDisplayNames(undefined, langArr);
let result = langArr.map((lang, i) => new Lang(lang, displayNames[i]));
result.sort();
return result;

View File

@ -182,9 +182,10 @@
<body>
<![CDATA[
this.translation = aTranslation;
let bundle = Services.strings.createBundle("chrome://global/locale/languageNames.properties");
let sortByLocalizedName = function(aList) {
return aList.map(code => [code, bundle.GetStringFromName(code)])
let names = Services.intl.getLanguageDisplayNames(undefined, aList);
return aList.map((code, i) => [code, names[i]])
.sort((a, b) => a[1].localeCompare(b[1]));
};
@ -355,9 +356,7 @@
lang = this.translation.detectedLanguage;
}
let langBundle =
Services.strings.createBundle("chrome://global/locale/languageNames.properties");
let langName = langBundle.GetStringFromName(lang);
let langName = Services.intl.getLanguageDisplayNames(undefined, [lang])[0];
// Set the label and accesskey on the menuitem.
let bundle =

View File

@ -142,16 +142,6 @@ XPCOMUtils.defineLazyServiceGetter(this, "gUUIDGenerator",
"@mozilla.org/uuid-generator;1",
"nsIUUIDGenerator");
XPCOMUtils.defineLazyGetter(this, "REGION_NAMES", function() {
let regionNames = {};
let countries = Services.strings.createBundle("chrome://global/locale/regionNames.properties").getSimpleEnumeration();
while (countries.hasMoreElements()) {
let country = countries.getNext().QueryInterface(Ci.nsIPropertyElement);
regionNames[country.key.toUpperCase()] = country.value;
}
return regionNames;
});
const CryptoHash = Components.Constructor("@mozilla.org/security/hash;1",
"nsICryptoHash", "initWithString");
@ -1272,8 +1262,12 @@ class Addresses extends AutofillRecords {
// Compute country name
if (!("country-name" in address)) {
if (address.country && REGION_NAMES[address.country]) {
address["country-name"] = REGION_NAMES[address.country];
if (address.country) {
try {
address["country-name"] = Services.intl.getRegionDisplayNames(undefined, [address.country]);
} catch (e) {
address["country-name"] = "";
}
} else {
address["country-name"] = "";
}
@ -1370,7 +1364,13 @@ class Addresses extends AutofillRecords {
}
// Only values included in the region list will be saved.
if (country && REGION_NAMES[country]) {
let hasLocalizedName = false;
try {
let localizedName = Services.intl.getRegionDisplayNames(undefined, [country]);
hasLocalizedName = localizedName != country;
} catch (e) {}
if (country && hasLocalizedName) {
address.country = country;
} else {
delete address.country;

View File

@ -833,22 +833,22 @@ this.FormAutofillUtils = {
* @param {string} attributeName
*/
localizeAttributeForElement(element, attributeName) {
let bundle = null;
switch (attributeName) {
case "data-localization": {
bundle = this.stringBundle;
element.textContent =
this.stringBundle.GetStringFromName(element.getAttribute(attributeName));
element.removeAttribute(attributeName);
break;
}
case "data-localization-region": {
bundle = this.regionsBundle;
break;
let regionCode = element.getAttribute(attributeName);
element.textContent = Services.intl.getRegionDisplayNames(undefined, [regionCode]);
element.removeAttribute(attributeName);
return;
}
default:
throw new Error("Unexpected attributeName");
}
element.textContent = bundle.GetStringFromName(element.getAttribute(attributeName));
element.removeAttribute(attributeName);
},
/**
@ -875,10 +875,6 @@ XPCOMUtils.defineLazyGetter(FormAutofillUtils, "stringBundle", function() {
return Services.strings.createBundle("chrome://formautofill/locale/formautofill.properties");
});
XPCOMUtils.defineLazyGetter(FormAutofillUtils, "regionsBundle", function() {
return Services.strings.createBundle("chrome://global/locale/regionNames.properties");
});
XPCOMUtils.defineLazyGetter(FormAutofillUtils, "brandBundle", function() {
return Services.strings.createBundle("chrome://branding/locale/brand.properties");
});

View File

@ -75,12 +75,11 @@ pw_change_failed_title=Password Change Failed
#### Fonts
# LOCALIZATION NOTE: Next two strings are for language name representations with
# and without the region.
# e.g. languageRegionCodeFormat : "French/Canada [fr-ca]" languageCodeFormat : "French [fr]"
# %1$S = language name, %2$S = region name, %3$S = language-region code
languageRegionCodeFormat=%1$S/%2$S [%3$S]
# %1$S = language name, %2$S = language-region code
# LOCALIZATION NOTE: The string represents a localized locale name
# followed by the BCP47 locale code.
#
# Example: "French (Canada) [fr-ca]"
# %1$S = locale name, %2$S = locale code
languageCodeFormat=%1$S [%2$S]
#### Downloads

View File

@ -537,12 +537,12 @@
*/
/* Lightweight theme on tabs */
:root[lwtheme-image] #tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background[selected=true] {
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background[selected=true]:-moz-lwtheme {
background-attachment: scroll, scroll, fixed;
background-color: transparent;
background-image: linear-gradient(var(--lwt-selected-tab-background-color, transparent), var(--lwt-selected-tab-background-color, transparent)),
linear-gradient(var(--toolbar-bgcolor), var(--toolbar-bgcolor)),
var(--lwt-header-image);
var(--lwt-header-image, none);
background-position: 0 0, 0 0, right top;
background-repeat: repeat-x, repeat-x, no-repeat;
background-size: auto 100%, auto 100%, auto auto;
@ -747,4 +747,3 @@
.alltabs-endimage[activemedia-blocked] {
list-style-image: url(chrome://browser/skin/tabbrowser/tab-audio-blocked.svg);
}

View File

@ -177,6 +177,12 @@ add_task(async function testSidebarDOMNodeHighlighting() {
// Wait the DOM node to be rendered inside the component.
await waitForObjectInspector(sidebarPanelContent, "node");
// Wait for the object to be expanded so we only target the "body" property node, and
// not the root object element.
await ContentTaskUtils.waitForCondition(
() => sidebarPanelContent.querySelectorAll(".object-inspector .tree-node").length > 1
);
// Get and verify the DOMNode and the "open inspector"" icon
// rendered inside the ObjectInspector.
assertObjectInspector(sidebarPanelContent, {

View File

@ -15,7 +15,6 @@
--node-color: var(--theme-highlight-purple);
--reference-color: var(--theme-highlight-blue);
--comment-node-color: var(--theme-comment);
--stack-function-color: var(--theme-highlight-red);
}
/******************************************************************************/
@ -65,11 +64,14 @@
}
.objectBox-function,
.objectBox-stackTrace,
.objectBox-profile {
color: var(--object-color);
}
.objectBox-stackTrace {
color: var(--error-color);
}
.objectBox-stackTrace-grid {
display: inline-grid;
grid-template-columns: auto auto;
@ -78,14 +80,34 @@
.objectBox-stackTrace-fn::before {
content: "\3BB"; /* The "lambda" symbol */
color: var(--theme-body-color);
display: inline-block;
margin: 0 0.3em;
}
.objectBox-stackTrace-fn {
color: var(--stack-function-color);
color: var(--console-output-color);
padding-inline-start: 17px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-inline-end: 5px;
}
.objectBox-stackTrace-location {
color: var(--frame-link-source, currentColor);
direction: rtl;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
text-align: end;
}
.objectBox-stackTrace-location:hover {
text-decoration: underline;
}
.objectBox-stackTrace-location {
cursor: pointer;
}
.objectBox-Location,

File diff suppressed because it is too large Load Diff

View File

@ -1611,24 +1611,6 @@ nsDocShell::GetParentCharset(const Encoding*& aCharset,
NS_IF_ADDREF(*aPrincipal = mParentCharsetPrincipal);
}
NS_IMETHODIMP
nsDocShell::GetChannelIsUnsafe(bool* aUnsafe)
{
*aUnsafe = false;
nsIChannel* channel = GetCurrentDocChannel();
if (!channel) {
return NS_OK;
}
nsCOMPtr<nsIJARChannel> jarChannel = do_QueryInterface(channel);
if (!jarChannel) {
return NS_OK;
}
return jarChannel->GetIsUnsafe(aUnsafe);
}
NS_IMETHODIMP
nsDocShell::GetHasMixedActiveContentLoaded(bool* aHasMixedActiveContentLoaded)
{
@ -1687,12 +1669,6 @@ nsDocShell::GetAllowPlugins(bool* aAllowPlugins)
NS_ENSURE_ARG_POINTER(aAllowPlugins);
*aAllowPlugins = mAllowPlugins;
if (!mAllowPlugins) {
return NS_OK;
}
bool unsafe;
*aAllowPlugins = NS_SUCCEEDED(GetChannelIsUnsafe(&unsafe)) && !unsafe;
return NS_OK;
}
@ -1906,12 +1882,6 @@ nsDocShell::GetAllowMetaRedirects(bool* aReturn)
NS_ENSURE_ARG_POINTER(aReturn);
*aReturn = mAllowMetaRedirects;
if (!mAllowMetaRedirects) {
return NS_OK;
}
bool unsafe;
*aReturn = NS_SUCCEEDED(GetChannelIsUnsafe(&unsafe)) && !unsafe;
return NS_OK;
}
@ -9545,34 +9515,6 @@ nsDocShell::InternalLoad(nsIURI* aURI,
}
}
// Don't allow loads that would inherit our security context
// if this document came from an unsafe channel.
{
bool willInherit;
// This condition needs to match the one in
// nsContentUtils::ChannelShouldInheritPrincipal.
// Except we reverse the rv check to be safe in case
// nsContentUtils::URIInheritsSecurityContext fails here and
// succeeds there.
rv = nsContentUtils::URIInheritsSecurityContext(aURI, &willInherit);
if (NS_FAILED(rv) || willInherit || NS_IsAboutBlank(aURI)) {
nsCOMPtr<nsIDocShellTreeItem> treeItem = this;
do {
nsCOMPtr<nsIDocShell> itemDocShell = do_QueryInterface(treeItem);
bool isUnsafe;
if (itemDocShell &&
NS_SUCCEEDED(itemDocShell->GetChannelIsUnsafe(&isUnsafe)) &&
isUnsafe) {
return NS_ERROR_DOM_SECURITY_ERR;
}
nsCOMPtr<nsIDocShellTreeItem> parent;
treeItem->GetSameTypeParent(getter_AddRefs(parent));
parent.swap(treeItem);
} while (treeItem);
}
}
nsIDocument* doc = mContentViewer ? mContentViewer->GetDocument()
: nullptr;

View File

@ -582,13 +582,6 @@ interface nsIDocShell : nsIDocShellTreeItem
*/
readonly attribute boolean isInUnload;
/**
* Find out if the currently loaded document came from a suspicious channel
* (such as a JAR channel where the server-returned content type isn't a
* known JAR type).
*/
readonly attribute boolean channelIsUnsafe;
/**
* This attribute determines whether Mixed Active Content is loaded on the
* document. When it is true, mixed active content was not blocked and has

View File

@ -1,8 +1,6 @@
[DEFAULT]
support-files =
bug123696-subframe.html
bug369814.jar
bug369814.zip
bug404548-subframe.html
bug404548-subframe_window.html
bug413310-post.sjs
@ -16,7 +14,6 @@ support-files =
file_anchor_scroll_after_document_open.html
file_bfcache_plus_hash_1.html
file_bfcache_plus_hash_2.html
file_bug369814.html
file_bug385434_1.html
file_bug385434_2.html
file_bug385434_3.html
@ -57,7 +54,6 @@ support-files =
[test_anchor_scroll_after_document_open.html]
[test_bfcache_plus_hash.html]
[test_bug123696.html]
[test_bug369814.html]
[test_bug384014.html]
[test_bug385434.html]
[test_bug387979.html]

View File

@ -1,211 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=369814
-->
<head>
<title>Test for Bug 369814</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=384014">Mozilla Bug 369814</a>
<p>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Tests for Bug 369814 **/
SimpleTest.waitForExplicitFinish();
// Because child scripts won't be able to run to tell us they're done,
// we need to just wait for them. Wait this many event loop spins before
// checking the results.
const gLoadEventLoopCount = 100;
var gCurrentTest;
var gTargetWindow;
var gNumPokes;
var gTestFrame;
/**
* Called by documents loaded from jar files to indicate that they can access
* this document.
*/
function poke(description) {
ok(false, gCurrentTest['name'] + ": got unexpected poke: " + description);
gNumPokes++;
}
function loadEvent(window, callback)
{
var fn = function() {
window.removeEventListener("load", fn);
callback();
};
window.addEventListener("load", fn);
}
function loadTestTarget(callback)
{
gTargetWindow = window.open("http://mochi.test:8888", "bug369814target");
loadEvent(gTargetWindow, callback);
}
function closeTestTarget()
{
gTargetWindow.close();
gTargetWindow = null;
}
function loadErrorTest(test)
{
// Give the frame a chance to fail at loading.
// How do detect failure to load? Error pages don't fire load
// events. But we can load another page before the error page and
// then use its unload handler to know when the error page is just
// about loaded; at that point a single trip through the event loop
// should do the trick.
loadEvent(gTestFrame, function() {
gTestFrame.src = test['url'];
});
gTestFrame.unloading = function() {
gTestFrame.unloading = null;
// Go out to the event loop once so that unload processing finishes and
// the new document is set up.
setTimeout(function() {
// XXX: There doesn't seem to be a reliable check for "got an error,"
// but reaching in to an error document will throw an exception
var errorPage;
try {
var item = gTestFrame.contentDocument.getElementById(gCurrentTest['data-iframe']);
errorPage = false;
} catch (e) {
errorPage = true;
}
ok(errorPage, gCurrentTest["name"] + ": should block a suspicious JAR load.");
finishTest();
}, 0);
}
var unloadDetector = "file_bug369814.html";
gTestFrame.src = unloadDetector;
}
function iframeTest(test) {
gTestFrame.src = test['url'];
loadEvent(gTestFrame, function() {
finishTest();
});
}
function hitEventLoop(func, times) {
if (times > 0) {
SimpleTest.executeSoon(function() { hitEventLoop(func, times-1); });
} else {
SimpleTest.executeSoon(func);
}
}
function refreshTest(test) {
gTestFrame.src = test['url'];
loadEvent(gTestFrame, function() {
// Wait for the frame to try and refresh
// XXX: a "blocked redirect" signal would be needed to get rid of
// this timeout.
hitEventLoop(function() {
finishTest();
}, gLoadEventLoopCount);
});
}
function anchorTest(test) {
loadTestTarget(function() {
gTestFrame.src = test['url'];
loadEvent(gTestFrame, function() {
sendMouseEvent({type:'click'}, 'target', gTestFrame.contentWindow);
sendMouseEvent({type:'click'}, 'notarget', gTestFrame.contentWindow);
// Give the clicks a chance to load
hitEventLoop(function() {
closeTestTarget();
finishTest();
}, gLoadEventLoopCount);
});
});
}
var gTests = [
{ "name" : "iframes.html loaded from non-jar type, pref disabled",
"url" : "jar:http://mochi.test:8888/tests/docshell/test/bug369814.zip!/iframes.html",
"pref" : false,
"pokes" : { },
"func" : loadErrorTest,
},
{ "name" : "refresh.html loaded from non-jar type, pref enabled",
"url" : "jar:http://mochi.test:8888/tests/docshell/test/bug369814.zip!/refresh.html",
"pref" : true,
"pokes" : { },
"func" : refreshTest,
},
{ "name" : "iframes.html loaded from non-jar type, pref enabled",
"url" : "jar:http://mochi.test:8888/tests/docshell/test/bug369814.zip!/iframes.html",
"pref" : true,
"pokes" : { },
"func" : iframeTest,
},
{ "name" : "anchors.html loaded from non-jar type, pref enabled",
"url" : "jar:http://mochi.test:8888/tests/docshell/test/bug369814.zip!/anchors.html",
"pref" : true,
"pokes" : { },
"func" : anchorTest,
},
];
var gNextTest = 0;
function runNextTest()
{
if (gNextTest < gTests.length) {
gCurrentTest = gTests[gNextTest++];
gNumPokes = 0;
SpecialPowers.pushPrefEnv({"set": [["network.jar.block-remote-files", false],
["network.jar.open-unsafe-types", gCurrentTest['pref']]]}, function() {
// Create a new frame each time, so our restictions on loads in a
// jar:-loaded iframe don't interfere with the test.
if (gTestFrame) {
document.body.removeChild(gTestFrame);
}
gTestFrame = document.createElement("iframe");
document.body.insertBefore(gTestFrame, $("test"));
gCurrentTest['func'](gCurrentTest);
});
} else {
SimpleTest.finish();
}
}
function finishTest()
{
SpecialPowers.pushPrefEnv({"set": [["network.jar.open-unsafe-types", false]]}, function() {
if (gNumPokes == 0) {
ok(true, gCurrentTest["name"] + ": no unexpected pokes");
}
runNextTest();
});
}
addLoadEvent(runNextTest);
</script>
</pre>
</body>
</html>

View File

@ -65,6 +65,9 @@ class nsDOMStringMap;
namespace mozilla {
class DeclarationBlock;
class TextEditor;
namespace css {
struct URLValue;
} // namespace css
namespace dom {
struct AnimationFilter;
struct ScrollIntoViewOptions;

View File

@ -30,11 +30,6 @@
#include "nsIDocument.h"
#include <algorithm>
#ifdef LoadImage
// Undefine LoadImage to prevent naming conflict with Windows.
#undef LoadImage
#endif
using namespace mozilla;
#define MISC_STR_PTR(_cont) \
@ -305,11 +300,6 @@ nsAttrValue::SetTo(const nsAttrValue& aOther)
NS_ADDREF(cont->mValue.mURL = otherCont->mValue.mURL);
break;
}
case eImage:
{
NS_ADDREF(cont->mValue.mImage = otherCont->mValue.mImage);
break;
}
case eAtomArray:
{
if (!EnsureEmptyAtomArray() ||
@ -416,7 +406,7 @@ nsAttrValue::SetTo(already_AddRefed<DeclarationBlock> aValue,
}
void
nsAttrValue::SetTo(css::URLValue* aValue, const nsAString* aSerialized)
nsAttrValue::SetTo(nsIURI* aValue, const nsAString* aSerialized)
{
MiscContainer* cont = EnsureEmptyMiscContainer();
NS_ADDREF(cont->mValue.mURL = aValue);
@ -878,10 +868,7 @@ nsAttrValue::HashValue() const
{
return NS_PTR_TO_INT32(cont->mValue.mCSSDeclaration);
}
// Intentionally identical, so that loading the image does not change the
// hash code.
case eURL:
case eImage:
{
nsString str;
ToString(str);
@ -992,10 +979,6 @@ nsAttrValue::Equals(const nsAttrValue& aOther) const
{
return thisCont->mValue.mURL == otherCont->mValue.mURL;
}
case eImage:
{
return thisCont->mValue.mImage == otherCont->mValue.mImage;
}
case eAtomArray:
{
// For classlists we could be insensitive to order, however
@ -1681,28 +1664,6 @@ nsAttrValue::ParseIntMarginValue(const nsAString& aString)
return true;
}
void
nsAttrValue::LoadImage(nsIDocument* aDocument)
{
NS_ASSERTION(Type() == eURL, "wrong type");
MiscContainer* cont = GetMiscContainer();
mozilla::css::URLValue* url = cont->mValue.mURL;
NS_ASSERTION(!url->IsStringEmpty(),
"How did we end up with an empty string for eURL");
mozilla::css::ImageValue* image =
mozilla::css::ImageValue::CreateFromURLValue(url,
aDocument,
mozilla::CORSMode::CORS_NONE);
NS_ADDREF(image);
cont->mValue.mImage = image;
NS_RELEASE(url);
cont->mType = eImage;
}
bool
nsAttrValue::ParseStyleAttribute(const nsAString& aString,
nsIPrincipal* aMaybeScriptedPrincipal,
@ -1869,11 +1830,6 @@ nsAttrValue::ClearMiscContainer()
NS_RELEASE(cont->mValue.mURL);
break;
}
case eImage:
{
NS_RELEASE(cont->mValue.mImage);
break;
}
case eAtomArray:
{
delete cont->mValue.mAtomArray;

View File

@ -30,19 +30,13 @@
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/EnumTypeTraits.h"
// Undefine LoadImage to prevent naming conflict with Windows.
#undef LoadImage
class nsIDocument;
class nsIURI;
class nsStyledElement;
struct MiscContainer;
namespace mozilla {
class DeclarationBlock;
namespace css {
struct URLValue;
struct ImageValue;
} // namespace css
} // namespace mozilla
#define NS_ATTRVALUE_MAX_STRINGLENGTH_ATOM 12
@ -150,7 +144,7 @@ public:
void SetTo(double aValue, const nsAString* aSerialized);
void SetTo(already_AddRefed<mozilla::DeclarationBlock> aValue,
const nsAString* aSerialized);
void SetTo(mozilla::css::URLValue* aValue, const nsAString* aSerialized);
void SetTo(nsIURI* aValue, const nsAString* aSerialized);
void SetTo(const nsIntMargin& aValue);
void SetTo(const nsSVGAngle& aValue, const nsAString* aSerialized);
void SetTo(const nsSVGIntegerPair& aValue, const nsAString* aSerialized);
@ -201,8 +195,7 @@ public:
inline float GetPercentValue() const;
inline mozilla::AtomArray* GetAtomArrayValue() const;
inline mozilla::DeclarationBlock* GetCSSDeclarationValue() const;
inline mozilla::css::URLValue* GetURLValue() const;
inline mozilla::css::ImageValue* GetImageValue() const;
inline nsIURI* GetURLValue() const;
inline double GetDoubleValue() const;
bool GetIntMarginValue(nsIntMargin& aMargin) const;
@ -421,13 +414,6 @@ public:
*/
bool ParseIntMarginValue(const nsAString& aString);
/**
* Convert a URL nsAttrValue to an Image nsAttrValue.
*
* @param aDocument the document this nsAttrValue belongs to.
*/
void LoadImage(nsIDocument* aDocument);
/**
* Parse a string into a CSS style rule.
*

View File

@ -42,8 +42,7 @@ struct MiscContainer final
uint32_t mEnumValue;
int32_t mPercent;
mozilla::DeclarationBlock* mCSSDeclaration;
mozilla::css::URLValue* mURL;
mozilla::css::ImageValue* mImage;
nsIURI* mURL;
mozilla::AtomArray* mAtomArray;
nsIntMargin* mIntMargin;
const nsSVGAngle* mSVGAngle;
@ -172,20 +171,13 @@ nsAttrValue::GetCSSDeclarationValue() const
return GetMiscContainer()->mValue.mCSSDeclaration;
}
inline mozilla::css::URLValue*
inline nsIURI*
nsAttrValue::GetURLValue() const
{
NS_PRECONDITION(Type() == eURL, "wrong type");
return GetMiscContainer()->mValue.mURL;
}
inline mozilla::css::ImageValue*
nsAttrValue::GetImageValue() const
{
NS_PRECONDITION(Type() == eImage, "wrong type");
return GetMiscContainer()->mValue.mImage;
}
inline double
nsAttrValue::GetDoubleValue() const
{

View File

@ -2005,14 +2005,6 @@ nsGlobalWindowOuter::SetNewDocument(nsIDocument* aDocument,
NS_ENSURE_SUCCESS(rv, rv);
}
// If the document comes from a JAR, check if the channel was determined
// to be unsafe. If so, permanently disable script on the compartment by
// calling Block() and throwing away the key.
nsCOMPtr<nsIJARChannel> jarChannel = do_QueryInterface(aDocument->GetChannel());
if (jarChannel && jarChannel->GetIsUnsafe()) {
xpc::Scriptability::Get(newInnerGlobal).Block();
}
if (mArguments) {
newInnerWindow->DefineArgumentsProperty(mArguments);
mArguments = nullptr;

Binary file not shown.

View File

@ -121,7 +121,6 @@ support-files =
file_bug769117.html
file_bug782342.txt
file_bug787778.sjs
file_bug804395.jar
file_bug869432.eventsource
file_bug869432.eventsource^headers^
file_bug907892.html
@ -545,7 +544,6 @@ skip-if = toolkit == 'android' #bug 687032
[test_bug787778.html]
[test_bug789315.html]
[test_bug789856.html]
[test_bug804395.html]
[test_bug809003.html]
[test_bug810494.html]
[test_bug811701.html]

View File

@ -1,74 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=804395
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 804395</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=804395">Mozilla Bug 804395</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
function test200() {
var xhr = new XMLHttpRequest({mozAnon: true, mozSystem: true});
xhr.open('GET', 'jar:http://example.org/tests/dom/base/test/file_bug804395.jar!/foo.bar', true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
ok(xhr.status == 200, "Existing file must have Status 200!");
runTests();
}
}
xhr.send(null);
}
function test404() {
var xhr = new XMLHttpRequest({mozAnon: true, mozSystem: true});
xhr.open('GET', 'jar:http://example.org/tests/dom/base/test/file_bug804395.jar!/foo.do_not_exist', true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
ok(xhr.status == 404, "Non existing file must have Status 404!");
runTests();
}
}
xhr.send(null);
}
function test0() {
var xhr = new XMLHttpRequest({mozAnon: true, mozSystem: true});
xhr.open('GET', 'jar:http://example.org/tests/dom/base/test/file_bug804395.jar!/foo.bar', true);
ok(xhr.status == 0, "Not Sent request must have status 0");
runTests();
}
var tests = [ test200, test404, test0 ];
function runTests() {
if (!tests.length) {
SimpleTest.finish();
return;
}
var test = tests.shift();
test();
}
/** Test for Bug 804395 **/
SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
SpecialPowers.pushPrefEnv({"set": [["network.jar.block-remote-files", false]]}, function() {
SpecialPowers.pushPermissions([{'type': 'systemXHR', 'allow': true, 'context': document}], runTests);
});
});
</script>
</pre>
</body>
</html>

View File

@ -921,11 +921,7 @@ nsGenericHTMLElement::ParseBackgroundAttribute(int32_t aNamespaceID,
if (NS_FAILED(rv)) {
return false;
}
mozilla::css::URLValue *url =
new mozilla::css::URLValue(uri, aValue, baseURI, doc->GetDocumentURI(),
NodePrincipal());
aResult.SetTo(url, &aValue);
aResult.SetTo(uri, &aValue);
return true;
}

Binary file not shown.

View File

@ -19,8 +19,6 @@ support-files =
bug340800_iframe.txt
bug369370-popup.png
bug372098-link-target.html
bug392567.jar
bug392567.jar^headers^
bug441930_iframe.html
bug445004-inner.html
bug445004-inner.js
@ -251,7 +249,6 @@ skip-if = toolkit == 'android' #TIMED_OUT
[test_bug389797.html]
[test_bug390975.html]
[test_bug391994.html]
[test_bug392567.html]
[test_bug394700.html]
[test_bug395107.html]
[test_bug401160.xhtml]

View File

@ -1,86 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=392567
-->
<head>
<title>Test for Bug 392567</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=392567">Mozilla Bug 392567</a>
<p id="display"><iframe name="testFrame" id="testFrame" style="visibility: hidden;"></iframe></p>
<div id="content" style="display: none">
<form name="testForm" target="testFrame">
<input type="text" name="key" />
</form>
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for Bug 392567 **/
SimpleTest.waitForExplicitFinish();
function runTests()
{
if (window.location.search.match(/\?key=value/)) {
return;
}
var dataUrl = "http://mochi.test:8888/tests/dom/html/test/bug392567.jar";
var jarUrl = "jar:" + dataUrl + "!/index.html";
var httpUrl = location.href.replace(/\.html.*/, "_404");
var previousDir = location.href.replace(/test\/[^\/]*$/, "");
var documentURL = location.href.replace(/\.html.*/, "\.html");
var form = document.forms.testForm;
var frame = frames.testFrame;
document.getElementById("testFrame").onload = processTestResult;
// List of tests to run, each test consists of form action URL and expected result URL
var tests = [
[jarUrl, jarUrl + "?$PARAMS"],
[jarUrl + "?jarTest1=jarTest2", jarUrl + "?$PARAMS"],
[jarUrl + "?jarTest3=jarTest4#jarTest5", jarUrl + "?$PARAMS#jarTest5"],
[httpUrl, httpUrl + "?$PARAMS"],
[httpUrl + "?httpTest1=httpTest2", httpUrl + "?$PARAMS"],
[httpUrl + "?httpTest3=httpTest4#httpTest5", httpUrl + "?$PARAMS#httpTest5"],
["", documentURL + "?$PARAMS"],
[" ", documentURL + "?$PARAMS"],
["../", previousDir + "?$PARAMS"],
];
var currentTest = -1;
runNextTest();
function runNextTest() {
currentTest++;
if (currentTest >= tests.length) {
SimpleTest.finish();
return;
}
form.setAttribute("action", tests[currentTest][0]);
form.key.value = "value" + currentTest;
form.submit();
}
function processTestResult() {
var expected = tests[currentTest][1].replace(/\$PARAMS/, "key=value" + currentTest);
is(frame.location.href, expected, "Submitting to " + tests[currentTest][0]);
setTimeout(runNextTest, 0);
}
}
addLoadEvent(function() {
SpecialPowers.pushPrefEnv({"set": [["network.jar.block-remote-files", false]]}, runTests);
});
</script>
</pre>
</body>
</html>

View File

@ -2,7 +2,6 @@
support-files =
file_CrossSiteXHR_cache_server.sjs
file_CrossSiteXHR_inner.html
file_CrossSiteXHR_inner.jar
file_CrossSiteXHR_inner_data.sjs
file_CrossSiteXHR_server.sjs

View File

@ -39,9 +39,6 @@ var origins =
{ server: 'http://\u03c0\u03b1\u03c1\u03ac\u03b4\u03b5\u03b9\u03b3\u03bc\u03b1.\u03b4\u03bf\u03ba\u03b9\u03bc\u03ae',
origin: 'http://xn--hxajbheg2az3al.xn--jxalpdlp'
},
{ origin: 'http://example.org',
file: 'jar:http://example.org/tests/dom/security/test/cors/file_CrossSiteXHR_inner.jar!/file_CrossSiteXHR_inner.html'
},
{ origin: 'null',
file: 'http://example.org/tests/dom/security/test/cors/file_CrossSiteXHR_inner_data.sjs'
},
@ -162,9 +159,7 @@ function* runTest() {
}
addLoadEvent(function() {
SpecialPowers.pushPrefEnv({"set": [["network.jar.block-remote-files", false]]}, function() {
gen.next();
});
gen.next();
});
</script>
</pre>

View File

@ -6,8 +6,6 @@ support-files =
postMessage_hash.html
postMessage_helper.html
postMessage_idn_helper.html
postMessage.jar
postMessage.jar^headers^
postMessage_joined_helper2.html
postMessage_joined_helper.html
postMessage_onOther.html
@ -29,7 +27,6 @@ skip-if = toolkit == 'android' #bug 894914 - wrong data - got FAIL, expected mes
[test_postMessage_hash.html]
[test_postMessage.html]
[test_postMessage_idn.xhtml]
[test_postMessage_jar.html]
[test_postMessage_joined.html]
[test_postMessage_onOther.html]
[test_postMessage_origin.xhtml]

View File

@ -1 +0,0 @@
Content-Type: application/java-archive

View File

@ -1,52 +0,0 @@
<!DOCTYPE html>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=430251
-->
<head>
<title>postMessage's interaction with pages at jar: URIs</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="browserFu.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<base href="http://mochi.test:8888/" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=430251">Mozilla Bug 430251</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
<script class="testbody" type="application/javascript">
/** Test for Bug 430251 **/
SimpleTest.waitForExplicitFinish();
function receiveMessage(evt)
{
is(evt.origin, "http://mochi.test:8888", "wrong sender");
ok(evt.source === window.frames.kid, "wrong source");
is(evt.data, "finish-test", "wrong data");
is(evt.lastEventId, "", "wrong lastEventId");
SimpleTest.finish();
}
window.addEventListener("message", receiveMessage);
addLoadEvent(function() {
SpecialPowers.pushPrefEnv({"set": [["network.jar.block-remote-files", false]]}, function() {
var iframe = document.createElement('iframe');
iframe.setAttribute('src', 'jar:http://mochi.test:8888/tests/dom/tests/mochitest/whatwg/postMessage.jar!/postMessage_jar.html');
iframe.setAttribute('name', 'kid');
document.getElementById("content").appendChild(iframe);
iframe.onload = function() {
window.frames.kid.postMessage("start-test", "http://mochi.test:8888");
}
});
});
</script>
</pre>
</body>
</html>

View File

@ -5,7 +5,6 @@ support-files =
frame_script.js
head.js
!/dom/base/test/file_empty.html
!/dom/base/test/file_bug945152.jar
[browser_bug1047663.js]
[browser_bug1104623.js]

View File

@ -0,0 +1,6 @@
function handleRequest(request, response) {
response.processAsync();
response.write("Hello");
setTimeout(function() { response.finish(); }, 100000); // wait 100 seconds.
}

View File

@ -3,7 +3,7 @@
* http://creativecommons.org/publicdomain/zero/1.0/
*/
var gJar = "jar:http://example.org/tests/dom/base/test/file_bug945152.jar!/data_big.txt";
var gURL = "http://example.org/tests/dom/workers/test/bug1063538.sjs";
var xhr = new XMLHttpRequest({mozAnon: true, mozSystem: true});
var progressFired = false;
@ -20,6 +20,6 @@ xhr.onprogress = function(e) {
};
onmessage = function(e) {
xhr.open("GET", gJar, true);
xhr.open("GET", gURL, true);
xhr.send();
}

View File

@ -94,7 +94,6 @@ support-files =
script_createFile.js
worker_suspended.js
window_suspended.html
!/dom/base/test/file_bug945152.jar
!/dom/notification/test/mochitest/MockServices.js
!/dom/notification/test/mochitest/NotificationTest.js
!/dom/xhr/tests/relativeLoad_import.js

View File

@ -38,9 +38,7 @@ function runTest() {
SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
SpecialPowers.pushPrefEnv({"set": [["network.jar.block-remote-files", false]]}, function() {
SpecialPowers.pushPermissions([{'type': 'systemXHR', 'allow': true, 'context': document}], runTest);
});
SpecialPowers.pushPermissions([{'type': 'systemXHR', 'allow': true, 'context': document}], runTest);
});
</script>

View File

@ -2349,52 +2349,9 @@ nsDocumentViewer::CreateStyleSet(nsIDocument* aDocument)
}
// Append chrome sheets (scrollbars + forms).
bool shouldOverride = false;
// We don't want a docshell here for external resource docs, so just
// look at mContainer.
nsCOMPtr<nsIDocShell> ds(mContainer);
nsCOMPtr<nsIDOMEventTarget> chromeHandler;
nsCOMPtr<nsIURI> uri;
RefPtr<StyleSheet> chromeSheet;
if (ds) {
ds->GetChromeEventHandler(getter_AddRefs(chromeHandler));
}
if (chromeHandler) {
nsCOMPtr<Element> elt(do_QueryInterface(chromeHandler));
if (elt) {
nsCOMPtr<nsIURI> baseURI = elt->GetBaseURI();
nsAutoString sheets;
elt->GetAttribute(NS_LITERAL_STRING("usechromesheets"), sheets);
if (!sheets.IsEmpty() && baseURI) {
RefPtr<css::Loader> cssLoader =
new css::Loader(aDocument->GetDocGroup());
char *str = ToNewCString(sheets);
char *newStr = str;
char *token;
while ( (token = nsCRT::strtok(newStr, ", ", &newStr)) ) {
NS_NewURI(getter_AddRefs(uri), nsDependentCString(token), nullptr,
baseURI);
if (!uri) continue;
cssLoader->LoadSheetSync(uri, &chromeSheet);
if (!chromeSheet) continue;
styleSet->PrependStyleSheet(SheetType::Agent, chromeSheet->AsServo());
shouldOverride = true;
}
free(str);
}
}
}
if (!shouldOverride) {
sheet = cache->ScrollbarsSheet();
if (sheet) {
styleSet->PrependStyleSheet(SheetType::Agent, sheet->AsServo());
}
sheet = cache->ScrollbarsSheet();
if (sheet) {
styleSet->PrependStyleSheet(SheetType::Agent, sheet->AsServo());
}
if (!aDocument->IsSVGDocument()) {

View File

@ -294,8 +294,6 @@ whitelist-types = [
"nsFont",
"nsAtom",
"nsDynamicAtom",
"nsMainThreadPtrHandle",
"nsMainThreadPtrHolder",
"nsMargin",
"nsMediaFeature",
"nsMediaFeatures",

View File

@ -111,8 +111,7 @@ ServoSpecifiedValues::SetTextDecorationColorOverride()
void
ServoSpecifiedValues::SetBackgroundImage(nsAttrValue& aValue)
{
if (aValue.Type() != nsAttrValue::eURL &&
aValue.Type() != nsAttrValue::eImage) {
if (aValue.Type() != nsAttrValue::eURL) {
return;
}
nsAutoString str;

View File

@ -698,19 +698,6 @@ nsCSSValue::GetCalcValue() const
return result;
}
void nsCSSValue::StartImageLoad(nsIDocument* aDocument,
mozilla::CORSMode aCORSMode) const
{
MOZ_ASSERT(eCSSUnit_URL == mUnit, "Not a URL value!");
mozilla::css::ImageValue* image =
mozilla::css::ImageValue::CreateFromURLValue(mValue.mURL,
aDocument,
aCORSMode);
nsCSSValue* writable = const_cast<nsCSSValue*>(this);
writable->SetImageValue(image);
}
nsCSSValue::Array*
nsCSSValue::InitFunction(nsCSSKeyword aFunctionId, uint32_t aNumArgs)
{
@ -1152,38 +1139,13 @@ nsCSSValue::Array::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) cons
return n;
}
css::URLValueData::URLValueData(already_AddRefed<PtrHolder<nsIURI>> aURI,
const nsAString& aString,
already_AddRefed<URLExtraData> aExtraData)
: mURI(Move(aURI))
, mExtraData(Move(aExtraData))
, mURIResolved(true)
, mStrings(aString)
, mUsingRustString(false)
{
MOZ_ASSERT(mExtraData);
MOZ_ASSERT(mExtraData->GetPrincipal());
}
css::URLValueData::URLValueData(already_AddRefed<PtrHolder<nsIURI>> aURI,
css::URLValueData::URLValueData(already_AddRefed<nsIURI> aURI,
ServoRawOffsetArc<RustString> aString,
already_AddRefed<URLExtraData> aExtraData)
: mURI(Move(aURI))
, mExtraData(Move(aExtraData))
, mURIResolved(true)
, mStrings(aString)
, mUsingRustString(true)
{
MOZ_ASSERT(mExtraData);
MOZ_ASSERT(mExtraData->GetPrincipal());
}
css::URLValueData::URLValueData(const nsAString& aString,
already_AddRefed<URLExtraData> aExtraData)
: mExtraData(Move(aExtraData))
, mURIResolved(false)
, mStrings(aString)
, mUsingRustString(false)
, mString(aString)
{
MOZ_ASSERT(mExtraData);
MOZ_ASSERT(mExtraData->GetPrincipal());
@ -1193,8 +1155,7 @@ css::URLValueData::URLValueData(ServoRawOffsetArc<RustString> aString,
already_AddRefed<URLExtraData> aExtraData)
: mExtraData(Move(aExtraData))
, mURIResolved(false)
, mStrings(aString)
, mUsingRustString(true)
, mString(aString)
{
MOZ_ASSERT(mExtraData);
MOZ_ASSERT(mExtraData->GetPrincipal());
@ -1202,11 +1163,7 @@ css::URLValueData::URLValueData(ServoRawOffsetArc<RustString> aString,
css::URLValueData::~URLValueData()
{
if (mUsingRustString) {
Servo_ReleaseArcStringData(&mStrings.mRustString);
} else {
mStrings.mString.~nsString();
}
Servo_ReleaseArcStringData(&mString);
}
bool
@ -1217,13 +1174,7 @@ css::URLValueData::Equals(const URLValueData& aOther) const
bool eq;
const URLExtraData* self = mExtraData;
const URLExtraData* other = aOther.mExtraData;
bool stringsEqual;
if (mUsingRustString && aOther.mUsingRustString) {
stringsEqual = GetRustString() == aOther.GetRustString();
} else {
stringsEqual = GetUTF16String() == aOther.GetUTF16String();
}
return stringsEqual &&
return GetString() == aOther.GetString() &&
(GetURI() == aOther.GetURI() || // handles null == null
(mURI && aOther.mURI &&
NS_SUCCEEDED(mURI->Equals(aOther.mURI, &eq)) &&
@ -1242,10 +1193,7 @@ css::URLValueData::DefinitelyEqualURIs(const URLValueData& aOther) const
if (mExtraData->BaseURI() != aOther.mExtraData->BaseURI()) {
return false;
}
if (mUsingRustString && aOther.mUsingRustString) {
return GetRustString() == aOther.GetRustString();
}
return GetUTF16StringForAnyThread() == aOther.GetUTF16StringForAnyThread();
return GetString() == aOther.GetString();
}
bool
@ -1257,48 +1205,14 @@ css::URLValueData::DefinitelyEqualURIsAndPrincipal(
}
nsDependentCSubstring
css::URLValueData::GetRustString() const
css::URLValueData::GetString() const
{
const uint8_t* chars;
uint32_t len;
Servo_GetArcStringData(mStrings.mRustString.mPtr, &chars, &len);
Servo_GetArcStringData(mString.mPtr, &chars, &len);
return nsDependentCSubstring(reinterpret_cast<const char*>(chars), len);
}
bool
css::URLValueData::IsStringEmpty() const
{
if (mUsingRustString) {
return GetRustString().IsEmpty();
}
return mStrings.mString.IsEmpty();
}
const nsString&
css::URLValueData::GetUTF16String() const
{
MOZ_ASSERT(NS_IsMainThread());
if (mUsingRustString) {
nsDependentCSubstring rust = GetRustString();
nsString converted = NS_ConvertUTF8toUTF16(rust);
Servo_ReleaseArcStringData(&mStrings.mRustString);
new (&mStrings) RustOrGeckoString(converted);
mUsingRustString = false;
}
return mStrings.mString;
}
nsString
css::URLValueData::GetUTF16StringForAnyThread() const
{
if (!mUsingRustString) {
return mStrings.mString;
}
nsDependentCSubstring rust = GetRustString();
return NS_ConvertUTF8toUTF16(rust);
}
nsIURI*
css::URLValueData::GetURI() const
{
@ -1307,16 +1221,10 @@ css::URLValueData::GetURI() const
if (!mURIResolved) {
MOZ_ASSERT(!mURI);
nsCOMPtr<nsIURI> newURI;
if (!mUsingRustString) {
NS_NewURI(getter_AddRefs(newURI),
NS_ConvertUTF16toUTF8(mStrings.mString),
nullptr, mExtraData->BaseURI());
} else {
NS_NewURI(getter_AddRefs(newURI),
GetRustString(),
nullptr, mExtraData->BaseURI());
}
mURI = new PtrHolder<nsIURI>("URLValueData::mURI", newURI.forget());
NS_NewURI(getter_AddRefs(newURI),
GetString(),
nullptr, mExtraData->BaseURI());
mURI = newURI.forget();
mURIResolved = true;
}
@ -1328,13 +1236,8 @@ css::URLValueData::IsLocalRef() const
{
if (mIsLocalRef.isNothing()) {
// IsLocalRefURL is O(N), use it only when IsLocalRef is called.
if (mUsingRustString) {
mIsLocalRef.emplace(nsContentUtils::IsLocalRefURL(GetRustString()));
} else {
mIsLocalRef.emplace(nsContentUtils::IsLocalRefURL(mStrings.mString));
}
mIsLocalRef.emplace(nsContentUtils::IsLocalRefURL(GetString()));
}
return mIsLocalRef.value();
}
@ -1364,9 +1267,7 @@ bool
css::URLValueData::MightHaveRef() const
{
if (mMightHaveRef.isNothing()) {
bool result = mUsingRustString ?
::MightHaveRef(GetRustString()) :
::MightHaveRef(mStrings.mString);
bool result = ::MightHaveRef(GetString());
if (!ServoStyleSet::IsInServoTraversal()) {
// Can only cache the result if we're not on a style worker thread.
mMightHaveRef.emplace(result);
@ -1448,34 +1349,12 @@ css::URLValueData::EqualsExceptRef(nsIURI* aURI) const
size_t
css::URLValueData::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
{
size_t n = 0;
if (!mUsingRustString) {
n += mStrings.mString.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
}
// Measurement of the following members may be added later if DMD finds it
// is worthwhile:
// - mURI
// - mString
// - mExtraData
return n;
}
URLValue::URLValue(const nsAString& aString, nsIURI* aBaseURI, nsIURI* aReferrer,
nsIPrincipal* aOriginPrincipal)
: URLValueData(aString, do_AddRef(new URLExtraData(aBaseURI, aReferrer,
aOriginPrincipal)))
{
MOZ_ASSERT(NS_IsMainThread());
}
URLValue::URLValue(nsIURI* aURI, const nsAString& aString, nsIURI* aBaseURI,
nsIURI* aReferrer, nsIPrincipal* aOriginPrincipal)
: URLValueData(do_AddRef(new PtrHolder<nsIURI>("URLValueData::mURI", aURI)),
aString,
do_AddRef(new URLExtraData(aBaseURI, aReferrer,
aOriginPrincipal)))
{
MOZ_ASSERT(NS_IsMainThread());
return 0;
}
size_t
@ -1490,36 +1369,17 @@ css::URLValue::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
return n;
}
css::ImageValue::ImageValue(nsIURI* aURI, const nsAString& aString,
css::ImageValue::ImageValue(nsIURI* aURI,
ServoRawOffsetArc<RustString> aString,
already_AddRefed<URLExtraData> aExtraData,
nsIDocument* aDocument,
CORSMode aCORSMode)
: URLValueData(do_AddRef(new PtrHolder<nsIURI>("URLValueData::mURI", aURI)),
aString, Move(aExtraData))
: URLValueData(do_AddRef(aURI), aString, Move(aExtraData))
{
mCORSMode = aCORSMode;
Initialize(aDocument);
}
css::ImageValue::ImageValue(nsIURI* aURI, ServoRawOffsetArc<RustString> aString,
already_AddRefed<URLExtraData> aExtraData,
nsIDocument* aDocument,
CORSMode aCORSMode)
: URLValueData(do_AddRef(new PtrHolder<nsIURI>("URLValueData::mURI", aURI)),
aString, Move(aExtraData))
{
mCORSMode = aCORSMode;
Initialize(aDocument);
}
css::ImageValue::ImageValue(const nsAString& aString,
already_AddRefed<URLExtraData> aExtraData,
CORSMode aCORSMode)
: URLValueData(aString, Move(aExtraData))
{
mCORSMode = aCORSMode;
}
css::ImageValue::ImageValue(ServoRawOffsetArc<RustString> aString,
already_AddRefed<URLExtraData> aExtraData,
CORSMode aCORSMode)
@ -1528,23 +1388,17 @@ css::ImageValue::ImageValue(ServoRawOffsetArc<RustString> aString,
mCORSMode = aCORSMode;
}
/*static*/ css::ImageValue*
/*static*/ already_AddRefed<css::ImageValue>
css::ImageValue::CreateFromURLValue(URLValue* aUrl,
nsIDocument* aDocument,
CORSMode aCORSMode)
{
if (aUrl->mUsingRustString) {
return new css::ImageValue(aUrl->GetURI(),
Servo_CloneArcStringData(&aUrl->mStrings.mRustString),
do_AddRef(aUrl->mExtraData),
aDocument,
aCORSMode);
}
return new css::ImageValue(aUrl->GetURI(),
aUrl->mStrings.mString,
do_AddRef(aUrl->mExtraData),
aDocument,
aCORSMode);
return do_AddRef(
new css::ImageValue(aUrl->GetURI(),
Servo_CloneArcStringData(&aUrl->mString),
do_AddRef(aUrl->mExtraData),
aDocument,
aCORSMode));
}
void

View File

@ -100,19 +100,14 @@ protected:
// caps, which leads to REQUIRES hell, since this header is included all
// over.
// For both constructors aString must not be null.
// For both constructors principal of aExtraData must not be null.
// aString must not be null.
// principal of aExtraData must not be null.
// Construct with a base URI; this will create the actual URI lazily from
// aString and aExtraData.
URLValueData(const nsAString& aString,
already_AddRefed<URLExtraData> aExtraData);
URLValueData(ServoRawOffsetArc<RustString> aString,
already_AddRefed<URLExtraData> aExtraData);
// Construct with the actual URI.
URLValueData(already_AddRefed<PtrHolder<nsIURI>> aURI,
const nsAString& aString,
already_AddRefed<URLExtraData> aExtraData);
URLValueData(already_AddRefed<PtrHolder<nsIURI>> aURI,
URLValueData(already_AddRefed<nsIURI> aURI,
ServoRawOffsetArc<RustString> aString,
already_AddRefed<URLExtraData> aExtraData);
@ -163,40 +158,29 @@ public:
bool EqualsExceptRef(nsIURI* aURI) const;
// Can only be called from the main thread. Returns this URL's UTF-16 representation,
// converting and caching its value if necessary.
const nsString& GetUTF16String() const;
// Returns this URL's UTF-16 representation, converting if necessary.
nsString GetUTF16StringForAnyThread() const;
bool IsStringEmpty() const
{
return GetString().IsEmpty();
}
bool IsStringEmpty() const;
nsDependentCSubstring GetString() const;
private:
// mURI stores the lazily resolved URI. This may be null if the URI is
// invalid, even once resolved.
mutable PtrHandle<nsIURI> mURI;
mutable nsCOMPtr<nsIURI> mURI;
public:
RefPtr<URLExtraData> mExtraData;
private:
// Returns a substring based on mStrings.mRustString which should not be exposed
// to external consumers.
nsDependentCSubstring GetRustString() const;
private:
mutable bool mURIResolved;
// mIsLocalRef is set when url starts with a U+0023 number sign(#) character.
mutable Maybe<bool> mIsLocalRef;
mutable Maybe<bool> mMightHaveRef;
mutable union RustOrGeckoString {
explicit RustOrGeckoString(const nsAString& aString)
: mString(aString) {}
explicit RustOrGeckoString(ServoRawOffsetArc<RustString> aString)
: mRustString(aString) {}
~RustOrGeckoString() {}
nsString mString;
mozilla::ServoRawOffsetArc<RustString> mRustString;
} mStrings;
mutable bool mUsingRustString;
mozilla::ServoRawOffsetArc<RustString> mString;
protected:
// Only used by ImageValue. Declared up here because otherwise bindgen gets
@ -223,16 +207,10 @@ private:
struct URLValue final : public URLValueData
{
// These two constructors are safe to call only on the main thread.
URLValue(const nsAString& aString, nsIURI* aBaseURI, nsIURI* aReferrer,
nsIPrincipal* aOriginPrincipal);
URLValue(nsIURI* aURI, const nsAString& aString, nsIURI* aBaseURI,
nsIURI* aReferrer, nsIPrincipal* aOriginPrincipal);
// This constructor is safe to call from any thread.
URLValue(ServoRawOffsetArc<RustString> aString,
already_AddRefed<URLExtraData> aExtraData)
: URLValueData(aString, Move(aExtraData)) {}
: URLValueData(aString, Move(aExtraData))
{ }
URLValue(const URLValue&) = delete;
URLValue& operator=(const URLValue&) = delete;
@ -242,9 +220,8 @@ struct URLValue final : public URLValueData
struct ImageValue final : public URLValueData
{
static ImageValue* CreateFromURLValue(URLValue* url,
nsIDocument* aDocument,
CORSMode aCORSMode);
static already_AddRefed<ImageValue>
CreateFromURLValue(URLValue*, nsIDocument*, CORSMode);
// Not making the constructor and destructor inline because that would
// force us to include imgIRequest.h, which leads to REQUIRES hell, since
@ -686,15 +663,6 @@ public:
return mValue.mGridTemplateAreas;
}
const char16_t* GetOriginalURLValue() const
{
MOZ_ASSERT(mUnit == eCSSUnit_URL || mUnit == eCSSUnit_Image,
"not a URL value");
return mUnit == eCSSUnit_URL ?
mValue.mURL->GetUTF16String().get() :
mValue.mImage->GetUTF16String().get();
}
// Not making this inline because that would force us to include
// imgIRequest.h, which leads to REQUIRES hell, since this header is included
// all over.

View File

@ -623,8 +623,8 @@ nsStyleUtil::AppendSerializedFontSrc(const nsCSSValue& aValue,
if (sources[i].GetUnit() == eCSSUnit_URL) {
aResult.AppendLiteral("url(");
nsDependentString url(sources[i].GetOriginalURLValue());
nsStyleUtil::AppendEscapedCSSString(url, aResult);
nsDependentCSubstring url(sources[i].GetURLStructValue()->GetString());
nsStyleUtil::AppendEscapedCSSString(NS_ConvertUTF8toUTF16(url), aResult);
aResult.Append(')');
} else if (sources[i].GetUnit() == eCSSUnit_Local_Font) {
aResult.AppendLiteral("local(");

View File

@ -11,14 +11,6 @@ interface nsIZipEntry;
[scriptable, builtinclass, uuid(e72b179b-d5df-4d87-b5de-fd73a65c60f6)]
interface nsIJARChannel : nsIChannel
{
/**
* Returns TRUE if the JAR file is not safe (if the content type reported
* by the server for a remote JAR is not of an expected type). Scripting,
* redirects, and plugins should be disabled when loading from this
* channel.
*/
[infallible] readonly attribute boolean isUnsafe;
/**
* Returns the JAR file. May be null if the jar is remote.
* Setting the JAR file is optional and overrides the JAR

View File

@ -194,19 +194,14 @@ nsJARInputThunk::IsNonBlocking(bool *nonBlocking)
nsJARChannel::nsJARChannel()
: mOpened(false)
, mContentDisposition(0)
, mContentLength(-1)
, mLoadFlags(LOAD_NORMAL)
, mStatus(NS_OK)
, mIsPending(false)
, mEnableOMT(true)
, mPendingEvent()
, mIsUnsafe(true)
, mBlockRemoteFiles(false)
{
LOG(("nsJARChannel::nsJARChannel [this=%p]\n", this));
mBlockRemoteFiles = Preferences::GetBool("network.jar.block-remote-files", false);
// hold an owning reference to the jar handler
mJarHandler = gJarHandler;
}
@ -268,7 +263,7 @@ nsJARChannel::CreateJarInput(nsIZipReaderCache *jarCache, nsJARInputThunk **resu
{
LOG(("nsJARChannel::CreateJarInput [this=%p]\n", this));
MOZ_ASSERT(resultInput);
MOZ_ASSERT(mJarFile || mTempMem);
MOZ_ASSERT(mJarFile);
// important to pass a clone of the file since the nsIFile impl is not
// necessarily MT-safe
@ -284,7 +279,6 @@ nsJARChannel::CreateJarInput(nsIZipReaderCache *jarCache, nsJARInputThunk **resu
if (mPreCachedJarReader) {
reader = mPreCachedJarReader;
} else if (jarCache) {
MOZ_ASSERT(mJarFile);
if (mInnerJarEntry.IsEmpty())
rv = jarCache->GetZip(clonedFile, getter_AddRefs(reader));
else
@ -296,12 +290,7 @@ nsJARChannel::CreateJarInput(nsIZipReaderCache *jarCache, nsJARInputThunk **resu
if (NS_FAILED(rv))
return rv;
if (mJarFile) {
rv = outerReader->Open(clonedFile);
} else {
rv = outerReader->OpenMemory(mTempMem->Elements(),
mTempMem->Length());
}
rv = outerReader->Open(clonedFile);
if (NS_FAILED(rv))
return rv;
@ -444,9 +433,6 @@ nsJARChannel::OpenLocalFile()
MOZ_ASSERT(mIsPending);
MOZ_ASSERT(mJarFile);
// Local files are always considered safe.
mIsUnsafe = false;
nsresult rv;
// Set mLoadGroup and mOpened before AsyncOpen return, and set back if
@ -899,11 +885,7 @@ nsJARChannel::SetContentCharset(const nsACString &aContentCharset)
NS_IMETHODIMP
nsJARChannel::GetContentDisposition(uint32_t *aContentDisposition)
{
if (mContentDispositionHeader.IsEmpty())
return NS_ERROR_NOT_AVAILABLE;
*aContentDisposition = mContentDisposition;
return NS_OK;
return NS_ERROR_NOT_AVAILABLE;
}
NS_IMETHODIMP
@ -927,11 +909,7 @@ nsJARChannel::SetContentDispositionFilename(const nsAString &aContentDisposition
NS_IMETHODIMP
nsJARChannel::GetContentDispositionHeader(nsACString &aContentDispositionHeader)
{
if (mContentDispositionHeader.IsEmpty())
return NS_ERROR_NOT_AVAILABLE;
aContentDispositionHeader = mContentDispositionHeader;
return NS_OK;
return NS_ERROR_NOT_AVAILABLE;
}
NS_IMETHODIMP
@ -958,15 +936,14 @@ nsJARChannel::Open(nsIInputStream **stream)
NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
mJarFile = nullptr;
mIsUnsafe = true;
nsresult rv = LookupFile();
if (NS_FAILED(rv))
return rv;
// If mJarInput was not set by LookupFile, the JAR is a remote jar.
// If mJarFile was not set by LookupFile, we can't open a channel.
if (!mJarFile) {
NS_NOTREACHED("need sync downloader");
NS_NOTREACHED("only file-backed jars are supported");
return NS_ERROR_NOT_IMPLEMENTED;
}
@ -977,8 +954,6 @@ nsJARChannel::Open(nsIInputStream **stream)
input.forget(stream);
mOpened = true;
// local files are always considered safe
mIsUnsafe = false;
return NS_OK;
}
@ -1003,14 +978,11 @@ nsJARChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctx)
nsContentUtils::IsSystemPrincipal(mLoadInfo->LoadingPrincipal())),
"security flags in loadInfo but asyncOpen2() not called");
LOG(("nsJARChannel::AsyncOpen [this=%p]\n", this));
NS_ENSURE_ARG_POINTER(listener);
NS_ENSURE_TRUE(!mOpened, NS_ERROR_IN_PROGRESS);
NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
mJarFile = nullptr;
mIsUnsafe = true;
// Initialize mProgressSink
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, mProgressSink);
@ -1020,65 +992,17 @@ nsJARChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctx)
mIsPending = true;
nsresult rv = LookupFile();
if (NS_FAILED(rv)) {
mIsPending = false;
mListenerContext = nullptr;
mListener = nullptr;
mCallbacks = nullptr;
mProgressSink = nullptr;
return rv;
}
nsCOMPtr<nsIChannel> channel;
if (!mJarFile) {
if (NS_FAILED(rv) || !mJarFile) {
// Not a local file...
// Check preferences to see if all remote jar support should be disabled
if (mBlockRemoteFiles) {
mIsUnsafe = true;
mIsPending = false;
mListenerContext = nullptr;
mListener = nullptr;
mCallbacks = nullptr;
mProgressSink = nullptr;
return NS_ERROR_UNSAFE_CONTENT_TYPE;
}
// kick off an async download of the base URI...
nsCOMPtr<nsIStreamListener> downloader = new MemoryDownloader(this);
uint32_t loadFlags =
mLoadFlags & ~(LOAD_DOCUMENT_URI | LOAD_CALL_CONTENT_SNIFFERS);
rv = NS_NewChannelInternal(getter_AddRefs(channel),
mJarBaseURI,
mLoadInfo,
nullptr, // PerformanceStorage
mLoadGroup,
mCallbacks,
loadFlags);
if (NS_FAILED(rv)) {
mIsPending = false;
mListenerContext = nullptr;
mListener = nullptr;
mCallbacks = nullptr;
mProgressSink = nullptr;
return rv;
}
if (mLoadInfo && mLoadInfo->GetEnforceSecurity()) {
rv = channel->AsyncOpen2(downloader);
}
else {
rv = channel->AsyncOpen(downloader, nullptr);
}
}
else {
rv = OpenLocalFile();
if (NS_SUCCEEDED(rv)) {
return NS_OK;
}
mIsPending = false;
mListenerContext = nullptr;
mListener = nullptr;
mCallbacks = nullptr;
mProgressSink = nullptr;
return mJarFile ? rv : NS_ERROR_UNSAFE_CONTENT_TYPE;
}
rv = OpenLocalFile();
if (NS_FAILED(rv)) {
mIsPending = false;
mListenerContext = nullptr;
@ -1088,11 +1012,6 @@ nsJARChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctx)
return rv;
}
if (mLoadGroup)
mLoadGroup->AddRequest(this, nullptr);
mOpened = true;
LOG(("nsJARChannel::AsyncOpen [this=%p] 8\n", this));
return NS_OK;
}
@ -1100,30 +1019,23 @@ NS_IMETHODIMP
nsJARChannel::AsyncOpen2(nsIStreamListener *aListener)
{
LOG(("nsJARChannel::AsyncOpen2 [this=%p]\n", this));
nsCOMPtr<nsIStreamListener> listener = aListener;
nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
if (NS_FAILED(rv)) {
mIsPending = false;
mListenerContext = nullptr;
mListener = nullptr;
mCallbacks = nullptr;
mProgressSink = nullptr;
return rv;
}
nsCOMPtr<nsIStreamListener> listener = aListener;
nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
if (NS_FAILED(rv)) {
mIsPending = false;
mListenerContext = nullptr;
mListener = nullptr;
mCallbacks = nullptr;
mProgressSink = nullptr;
return rv;
}
return AsyncOpen(listener, nullptr);
return AsyncOpen(listener, nullptr);
}
//-----------------------------------------------------------------------------
// nsIJARChannel
//-----------------------------------------------------------------------------
NS_IMETHODIMP
nsJARChannel::GetIsUnsafe(bool *isUnsafe)
{
*isUnsafe = mIsUnsafe;
return NS_OK;
}
NS_IMETHODIMP
nsJARChannel::GetJarFile(nsIFile **aFile)
{
@ -1210,116 +1122,6 @@ nsJARChannel::GetZipEntry(nsIZipEntry **aZipEntry)
return reader->GetEntry(mJarEntry, aZipEntry);
}
//-----------------------------------------------------------------------------
// mozilla::net::MemoryDownloader::IObserver
//-----------------------------------------------------------------------------
void
nsJARChannel::OnDownloadComplete(MemoryDownloader* aDownloader,
nsIRequest *request,
nsISupports *context,
nsresult status,
MemoryDownloader::Data aData)
{
nsresult rv;
nsCOMPtr<nsIChannel> channel(do_QueryInterface(request));
if (channel) {
uint32_t loadFlags;
channel->GetLoadFlags(&loadFlags);
if (loadFlags & LOAD_REPLACE) {
// Update our URI to reflect any redirects that happen during
// the HTTP request.
if (!mOriginalURI) {
SetOriginalURI(mJarURI);
}
nsCOMPtr<nsIURI> innerURI;
rv = channel->GetURI(getter_AddRefs(innerURI));
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIJARURI> newURI;
rv = mJarURI->CloneWithJARFile(innerURI,
getter_AddRefs(newURI));
if (NS_SUCCEEDED(rv)) {
mJarURI = newURI;
}
}
if (NS_SUCCEEDED(status)) {
status = rv;
}
}
}
if (NS_SUCCEEDED(status) && channel) {
// In case the load info object has changed during a redirect,
// grab it from the target channel.
channel->GetLoadInfo(getter_AddRefs(mLoadInfo));
// Grab the security info from our base channel
channel->GetSecurityInfo(getter_AddRefs(mSecurityInfo));
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
if (httpChannel) {
// We only want to run scripts if the server really intended to
// send us a JAR file. Check the server-supplied content type for
// a JAR type.
nsAutoCString header;
Unused << httpChannel->GetResponseHeader(
NS_LITERAL_CSTRING("Content-Type"), header);
nsAutoCString contentType;
nsAutoCString charset;
NS_ParseResponseContentType(header, contentType, charset);
nsAutoCString channelContentType;
channel->GetContentType(channelContentType);
mIsUnsafe = !(contentType.Equals(channelContentType) &&
(contentType.EqualsLiteral("application/java-archive") ||
contentType.EqualsLiteral("application/x-jar")));
} else {
nsCOMPtr<nsIJARChannel> innerJARChannel(do_QueryInterface(channel));
if (innerJARChannel) {
mIsUnsafe = innerJARChannel->GetIsUnsafe();
}
}
channel->GetContentDispositionHeader(mContentDispositionHeader);
mContentDisposition = NS_GetContentDispositionFromHeader(mContentDispositionHeader, this);
}
// This is a defense-in-depth check for the preferences to see if all remote jar
// support should be disabled. This check may not be needed.
MOZ_RELEASE_ASSERT(!mBlockRemoteFiles);
if (NS_SUCCEEDED(status) && mIsUnsafe &&
!Preferences::GetBool("network.jar.open-unsafe-types", false)) {
status = NS_ERROR_UNSAFE_CONTENT_TYPE;
}
if (NS_SUCCEEDED(status)) {
// Refuse to unpack view-source: jars even if open-unsafe-types is set.
nsCOMPtr<nsIViewSourceChannel> viewSource = do_QueryInterface(channel);
if (viewSource) {
status = NS_ERROR_UNSAFE_CONTENT_TYPE;
}
}
if (NS_SUCCEEDED(status)) {
mTempMem = Move(aData);
RefPtr<nsJARInputThunk> input;
rv = CreateJarInput(nullptr, getter_AddRefs(input));
if (NS_SUCCEEDED(rv)) {
// create input stream pump
rv = NS_NewInputStreamPump(getter_AddRefs(mPump), input.forget());
if (NS_SUCCEEDED(rv))
rv = mPump->AsyncRead(this, nullptr);
}
status = rv;
}
if (NS_FAILED(status)) {
NotifyError(status);
}
}
//-----------------------------------------------------------------------------
// nsIStreamListener
//-----------------------------------------------------------------------------

View File

@ -33,7 +33,6 @@ class nsInputStreamPump;
//-----------------------------------------------------------------------------
class nsJARChannel final : public nsIJARChannel
, public mozilla::net::MemoryDownloader::IObserver
, public nsIStreamListener
, public nsIThreadRetargetableRequest
, public nsIThreadRetargetableStreamListener
@ -66,12 +65,6 @@ private:
nsresult CheckPendingEvents();
void NotifyError(nsresult aError);
void FireOnProgress(uint64_t aProgress);
virtual void OnDownloadComplete(mozilla::net::MemoryDownloader* aDownloader,
nsIRequest* aRequest,
nsISupports* aCtxt,
nsresult aStatus,
mozilla::net::MemoryDownloader::Data aData)
override;
nsCString mSpec;
@ -90,10 +83,6 @@ private:
nsCOMPtr<nsISupports> mListenerContext;
nsCString mContentType;
nsCString mContentCharset;
nsCString mContentDispositionHeader;
/* mContentDisposition is uninitialized if mContentDispositionHeader is
* empty */
uint32_t mContentDisposition;
int64_t mContentLength;
uint32_t mLoadFlags;
nsresult mStatus;
@ -106,9 +95,6 @@ private:
uint32_t suspendCount;
} mPendingEvent;
bool mIsUnsafe;
mozilla::net::MemoryDownloader::Data mTempMem;
nsCOMPtr<nsIInputStreamPump> mPump;
// mRequest is only non-null during OnStartRequest, so we'll have a pointer
// to the request if we get called back via RetargetDeliveryTo.
@ -122,9 +108,6 @@ private:
// use StreamTransportService as background thread
nsCOMPtr<nsIEventTarget> mWorker;
// True if this channel should not download any remote files.
bool mBlockRemoteFiles;
};
#endif // nsJARChannel_h__

View File

@ -1 +0,0 @@
Content-Type: application/java-archive

View File

@ -1,11 +1,5 @@
[DEFAULT]
support-files =
bug403331.zip
bug403331.zip^headers^
openredirect.sjs
!/dom/base/test/file_bug945152.jar
[test_bug403331.html]
[test_bug1034143_mapped.html]
run-if = os == 'linux'
[test_bug1173171.html]
[test_bug1173171.html]
support-files =
bug1173171.zip
bug1173171.zip^headers^

View File

@ -1,5 +0,0 @@
function handleRequest(request, response)
{
response.setStatusLine(request.httpVersion, 301, "Moved Permanently");
response.setHeader("Location", request.queryString, false);
}

View File

@ -1,53 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1034143
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 945152</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1034143">Mozilla Bug 1034143</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
// Ensure that XMLHttpRequest's memory-mapping code can handle a case
// where the nsIJARChannel's jarFile property is null, but which is
// otherwise eligible for bug 945152's memory-mapping optimization.
function runTest() {
const jarURL = "jar:http://example.org/tests/dom/base/test/file_bug945152.jar!/data_1.txt";
let xhr = new XMLHttpRequest({ mozAnon: true, mozSystem: true });
xhr.open("GET", jarURL);
xhr.onerror = function onerror(e) {
ok(false, "JAR XHR failed: " + e.status);
SimpleTest.finish();
};
xhr.onload = function onload(e) {
ok(xhr.status == 200, "Status is 200");
let ct = xhr.getResponseHeader("Content-Type");
ok(!ct.includes("mem-mapped"), "Data is not memory-mapped");
SimpleTest.finish();
};
xhr.responseType = 'arraybuffer';
xhr.send();
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
SpecialPowers.pushPrefEnv({"set": [["dom.mapped_arraybuffer.enabled", true],
["network.jar.block-remote-files", false]]}, function() {
SpecialPowers.pushPermissions([{'type': 'systemXHR', 'allow': true, 'context': document}], runTest);
});
});
</script>
</pre>
</body>
</html>

View File

@ -18,15 +18,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1173171
/** Test for Bug 1173171 **/
// __setPref(key, value)__.
// Set a pref value asynchronously, returning a prmoise that resolves
// when it succeeds.
let pushPref = function (key, value) {
return new Promise(function(resolve, reject) {
SpecialPowers.pushPrefEnv({"set": [[key, value]]}, resolve);
});
};
// __xhr(method, url, responseType__.
// A simple async XMLHttpRequest call.
// Returns a promise with the response.
@ -49,12 +40,9 @@ let jarURL = "jar:http://mochi.test:8888/tests/modules/libjar/test/mochitest/bug
// Test behavior when blocking is deactivated and activated.
add_task(async function() {
for (let shouldBlock of [false, true]) {
await pushPref("network.jar.block-remote-files", shouldBlock);
let response = await xhr("GET", jarURL, "document");
ok(shouldBlock === (response === null),
"Remote jars should be blocked if and only if the 'network.jar.block-remote-files' pref is active.");
}
let shouldBlock = true;
let response = await xhr("GET", jarURL, "document");
is(response, null, "Remote jars should be blocked.");
});
</script>

View File

@ -1,47 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=403331
-->
<head>
<title>Test for Bug 403331</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<iframe id="testFrame"></iframe>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for Bug 403331 **/
SimpleTest.waitForExplicitFinish();
function runTest() {
var testFrame = document.getElementById('testFrame');
// Try a redirected load from another domain to this one.
testFrame.onload = function() {
// If properly redirected, we'll be able to access elements in the loaded
// document.
var item = testFrame.contentDocument.getElementById('testitem');
is(item.textContent, "testcontents", "Should be able to access the child document");
SimpleTest.finish();
}
testFrame.src = "jar:http://example.org:80/tests/modules/libjar/test/mochitest/openredirect.sjs?http://mochi.test:8888/tests/modules/libjar/test/mochitest/bug403331.zip!/test.html";
}
addLoadEvent(function() {
SpecialPowers.pushPrefEnv({"set": [["network.jar.block-remote-files", false]]}, runTest);
});
</script>
</pre>
</body>
</html>

View File

@ -1,39 +0,0 @@
// Regression test for bug 407303 - A failed channel should not be checked
// for an unsafe content type.
ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
// XXX: NS_ERROR_UNKNOWN_HOST is not in Components.results
const NS_ERROR_UNKNOWN_HOST = 0x804B001E;
var listener = {
QueryInterface: function(iid) {
if (iid.equals(Ci.nsISupports) ||
iid.equals(Ci.nsIRequestObserver))
return this;
throw Cr.NS_ERROR_NO_INTERFACE;
},
onStartRequest: function(request, context) {
},
onDataAvailable: function(request, context, stream, offset, count) {
do_throw("shouldn't get data!");
},
onStopRequest: function(request, context, status) {
Assert.equal(status, NS_ERROR_UNKNOWN_HOST);
do_test_finished();
}
};
function run_test() {
Services.prefs.setBoolPref("network.jar.block-remote-files", false);
var channel = NetUtil.newChannel({
uri: "jar:http://test.invalid/test.jar!/index.html",
loadUsingSystemPrincipal: true}
);
channel.asyncOpen2(listener);
do_test_pending();
}

View File

@ -25,7 +25,6 @@ skip-if = os == "mac"
[test_bug336691.js]
[test_bug370103.js]
[test_bug379841.js]
[test_bug407303.js]
[test_bug453254.js]
[test_bug458158.js]
[test_bug589292.js]

View File

@ -1892,13 +1892,6 @@ pref("network.websocket.delay-failed-reconnects", true);
// Equal to the DEFAULT_RECONNECTION_TIME_VALUE value in nsEventSource.cpp
pref("dom.server-events.default-reconnection-time", 5000); // in milliseconds
// If false, remote JAR files that are served with a content type other than
// application/java-archive or application/x-jar will not be opened
// by the jar channel.
pref("network.jar.open-unsafe-types", false);
// If true, loading remote JAR files using the jar: protocol will be prevented.
pref("network.jar.block-remote-files", true);
// This preference, if true, causes all UTF-8 domain names to be normalized to
// punycode. The intention is to allow UTF-8 domain names as input, but never
// generate them from punycode.

File diff suppressed because it is too large Load Diff

View File

@ -56,14 +56,10 @@ impl CssUrl {
/// Convert from URLValueData to SpecifiedUrl.
unsafe fn from_url_value_data(url: &URLValueData) -> Result<Self, ()> {
let arc_type =
&url.mString as *const _ as *const RawOffsetArc<String>;
Ok(CssUrl {
serialization: if url.mUsingRustString {
let arc_type =
url.mStrings.mRustString.as_ref() as *const _ as *const RawOffsetArc<String>;
Arc::from_raw_offset((*arc_type).clone())
} else {
Arc::new(url.mStrings.mString.as_ref().to_string())
},
serialization: Arc::from_raw_offset((*arc_type).clone()),
extra_data: url.mExtraData.to_safe(),
})
}

View File

@ -4,7 +4,7 @@
from __future__ import absolute_import
__version__ = '2.5.0'
__version__ = '2.6.0'
from marionette_driver import (
addons,

View File

@ -1706,16 +1706,15 @@ class Marionette(object):
args = self._to_json(script_args)
stack = traceback.extract_stack()
frame = stack[-2:-1][0] # grab the second-to-last frame
body = {"script": script,
filename = frame[0] if sys.platform == "win32" else os.path.relpath(frame[0])
body = {"script": script.strip(),
"args": args,
"newSandbox": new_sandbox,
"sandbox": sandbox,
"scriptTimeout": script_timeout,
"line": int(frame[1]),
"filename": os.path.basename(frame[0])}
rv = self._send_message("WebDriver:ExecuteScript",
body, key="value")
"filename": filename}
rv = self._send_message("WebDriver:ExecuteScript", body, key="value")
return self._from_json(rv)
def execute_async_script(self, script, script_args=(), new_sandbox=True,
@ -1756,13 +1755,14 @@ class Marionette(object):
args = self._to_json(script_args)
stack = traceback.extract_stack()
frame = stack[-2:-1][0] # grab the second-to-last frame
body = {"script": script,
filename = frame[0] if sys.platform == "win32" else os.path.relpath(frame[0])
body = {"script": script.strip(),
"args": args,
"newSandbox": new_sandbox,
"sandbox": sandbox,
"scriptTimeout": script_timeout,
"line": int(frame[1]),
"filename": os.path.basename(frame[0]),
"filename": filename,
"debug_script": debug_script}
rv = self._send_message("WebDriver:ExecuteAsyncScript",

View File

@ -1,3 +1,3 @@
mozrunner >= 6.13
mozrunner >= 6.15
mozversion >= 1.1
six

View File

@ -857,8 +857,6 @@ GeckoDriver.prototype.getContext = function() {
* @param {boolean=} debug_script
* Attach an <code>onerror</code> event handler on the {@link Window}
* object. It does not differentiate content errors from chrome errors.
* @param {boolean=} directInject
* Evaluate the script without wrapping it in a function.
*
* @return {(string|boolean|number|object|WebElement)}
* Return value from the script, or null which signifies either the
@ -931,8 +929,6 @@ GeckoDriver.prototype.executeScript = async function(cmd, resp) {
* @param {boolean=} debug_script
* Attach an <code>onerror</code> event handler on the {@link Window}
* object. It does not differentiate content errors from chrome errors.
* @param {boolean=} directInject
* Evaluate the script without wrapping it in a function.
*
* @return {(string|boolean|number|object|WebElement)}
* Return value from the script, or null which signifies either the

View File

@ -349,57 +349,11 @@ class InvalidSessionIDError extends WebDriverError {
}
}
/**
* An error occurred while executing JavaScript supplied by the user.
*
* Creates a richly annotated error for an error situation that occurred
* whilst evaluating injected scripts.
*/
/** An error occurred whilst executing JavaScript supplied by the user. */
class JavaScriptError extends WebDriverError {
/**
* @param {(string|Error)} x
* An Error object instance or a string describing the error
* situation.
* @param {string=} fnName
* Name of the function to use in the stack trace message.
* @param {string=} file
* Filename of the test file on the client.
* @param {number=} line
* Line number of |file|.
* @param {string=} script
* Script being executed, in text form.
*/
constructor(x,
{fnName = null, file = null, line = null, script = null} = {}) {
let msg = String(x);
let trace = "";
if (fnName !== null) {
trace += fnName;
if (file !== null) {
trace += ` @${file}`;
if (line !== null) {
trace += `, line ${line}`;
}
}
}
if (error.isError(x)) {
let jsStack = x.stack.split("\n");
let match = jsStack[0].match(/:(\d+):\d+$/);
let jsLine = match ? parseInt(match[1]) : 0;
if (script !== null) {
let src = script.split("\n")[jsLine];
trace += "\n" +
`inline javascript, line ${jsLine}\n` +
`src: "${src}"`;
}
trace += "\nStack:\n" + x.stack;
}
super(msg);
constructor(x) {
super(x);
this.status = "javascript error";
this.stack = trace;
}
}

View File

@ -36,37 +36,29 @@ this.evaluate = {};
/**
* Evaluate a script in given sandbox.
*
* If the option var>directInject</var> is not specified, the script
* will be executed as a function with the <var>args</var> argument
* applied.
* The the provided `script` will be wrapped in an anonymous function
* with the `args` argument applied.
*
* The arguments provided by the <var>args</var> argument are exposed
* through the <code>arguments</code> object available in the script
* context, and if the script is executed asynchronously with the
* <var>async</var> option, an additional last argument that is synonymous
* to the <code>marionetteScriptFinished</code> global is appended, and
* can be accessed through <code>arguments[arguments.length - 1]</code>.
* The arguments provided by the `args<` argument are exposed
* through the `arguments` object available in the script context,
* and if the script is executed asynchronously with the `async`
* option, an additional last argument that is synonymous to the
* `marionetteScriptFinished` global is appended, and can be accessed
* through `arguments[arguments.length - 1]`.
*
* The <var>timeout</var> option specifies the duration for how long
* the script should be allowed to run before it is interrupted and aborted.
* The `timeout` option specifies the duration for how long the
* script should be allowed to run before it is interrupted and aborted.
* An interrupted script will cause a {@link ScriptTimeoutError} to occur.
*
* The <var>async</var> option indicates that the script will
* not return until the <code>marionetteScriptFinished</code> global
* callback is invoked, which is analogous to the last argument of the
* <code>arguments</code> object.
* The `async` option indicates that the script will not return
* until the `marionetteScriptFinished` global callback is invoked,
* which is analogous to the last argument of the `arguments` object.
*
* The option <var>directInject</var> causes the script to be evaluated
* without being wrapped in a function and the provided arguments will
* be disregarded. This will cause such things as root scope return
* statements to throw errors because they are not used inside a function.
* The `file` option is used in error messages to provide information
* on the origin script file in the local end.
*
* The <var>file</var> option is used in error messages to provide
* information on the origin script file in the local end.
*
* The <var>line</var> option is used in error messages, along with
* <var>filename</var>, to provide the line number in the origin script
* file on the local end.
* The `line` option is used in error messages, along with `filename`,
* to provide the line number in the origin script file on the local end.
*
* @param {nsISandbox} sb
* Sandbox the script will be evaluted in.
@ -103,7 +95,6 @@ evaluate.sandbox = function(sb, script, args = [],
{
async = false,
debug = false,
directInject = false,
file = "dummy file",
line = 0,
sandboxName = null,
@ -119,28 +110,25 @@ evaluate.sandbox = function(sb, script, args = [],
() => reject(new JavaScriptError("Document was unloaded")),
sb);
// wrap in function
if (!directInject) {
if (async) {
sb[CALLBACK] = sb[COMPLETE];
}
sb[ARGUMENTS] = sandbox.cloneInto(args, sb);
if (async) {
sb[CALLBACK] = sb[COMPLETE];
}
sb[ARGUMENTS] = sandbox.cloneInto(args, sb);
// callback function made private
// so that introspection is possible
// on the arguments object
if (async) {
sb[CALLBACK] = sb[COMPLETE];
src += `${ARGUMENTS}.push(rv => ${CALLBACK}(rv));`;
}
// callback function made private
// so that introspection is possible
// on the arguments object
if (async) {
sb[CALLBACK] = sb[COMPLETE];
src += `${ARGUMENTS}.push(rv => ${CALLBACK}(rv));`;
}
src += `(function() { ${script} }).apply(null, ${ARGUMENTS})`;
src += `(function() { ${script} }).apply(null, ${ARGUMENTS})`;
// marionetteScriptFinished is not WebDriver conformant,
// hence it is only exposed to immutable sandboxes
if (sandboxName) {
sb[MARIONETTE_SCRIPT_FINISHED] = sb[CALLBACK];
}
// marionetteScriptFinished is not WebDriver conformant,
// hence it is only exposed to immutable sandboxes
if (sandboxName) {
sb[MARIONETTE_SCRIPT_FINISHED] = sb[CALLBACK];
}
// onerror is not hooked on by default because of the inability to
@ -160,15 +148,9 @@ evaluate.sandbox = function(sb, script, args = [],
let res;
try {
res = Cu.evalInSandbox(src, sb, "1.8", file, 0);
res = Cu.evalInSandbox(src, sb, "1.8", file, line);
} catch (e) {
let err = new JavaScriptError(e, {
fnName: "execute_script",
file,
line,
script,
});
reject(err);
reject(new JavaScriptError(e));
}
if (!async) {

View File

@ -4,7 +4,7 @@
from __future__ import absolute_import
__version__ = '4.3.0'
__version__ = '4.4.0'
from .marionette_test import (
CommonTestCase,

View File

@ -1,5 +1,7 @@
from __future__ import absolute_import
import os
from marionette_driver.errors import (
JavascriptException,
ScriptTimeoutException,
@ -61,16 +63,21 @@ class TestExecuteAsyncContent(MarionetteTestCase):
let a = 1;
foo(bar);
""")
self.assertFalse(True)
except JavascriptException as inst:
self.assertTrue('foo(bar)' in inst.stacktrace)
self.fail()
except JavascriptException as e:
self.assertIsNotNone(e.stacktrace)
self.assertIn(os.path.relpath(__file__.replace(".pyc", ".py")), e.stacktrace)
def test_execute_async_js_exception(self):
self.assertRaises(JavascriptException,
self.marionette.execute_async_script, """
var callback = arguments[arguments.length - 1];
callback(foo());
try:
self.marionette.execute_async_script("""
let [resolve] = arguments;
resolve(foo());
""")
self.fail()
except JavascriptException as e:
self.assertIsNotNone(e.stacktrace)
self.assertIn(os.path.relpath(__file__.replace(".pyc", ".py")), e.stacktrace)
def test_script_finished(self):
self.assertTrue(self.marionette.execute_async_script("""

View File

@ -163,10 +163,8 @@ class TestExecuteContent(MarionetteTestCase):
self.marionette.execute_script("return b")
# by default execute_script pass the name of the python file
self.assertIn(os.path.basename(__file__.replace(".pyc", ".py")),
cm.exception.stacktrace)
self.assertIn(os.path.relpath(__file__.replace(".pyc", ".py")), cm.exception.stacktrace)
self.assertIn("b is not defined", cm.exception.message)
self.assertIn("return b", cm.exception.stacktrace)
def test_permission(self):
for sandbox in ["default", None]:

View File

@ -1,6 +1,6 @@
browsermob-proxy >= 0.6.0
manifestparser >= 1.1
marionette-driver >= 2.5.0
marionette-driver >= 2.6.0
mozcrash >= 0.5
mozdevice >= 0.44
mozinfo >= 0.8
@ -8,7 +8,7 @@ mozlog >= 3.0
moznetwork >= 0.21
mozprocess >= 0.9
mozprofile >= 0.7
mozrunner >= 6.13
mozrunner >= 6.15
moztest >= 0.8
mozversion >= 1.1
six

View File

@ -135,17 +135,10 @@ add_test(function test_toJSON() {
equal(e1s.message, e1.message);
equal(e1s.stacktrace, e1.stack);
let e2 = new JavaScriptError("first", {
fnName: "second",
file: "third",
line: "fourth",
});
let e2 = new JavaScriptError("foo");
let e2s = e2.toJSON();
equal(e2.status, e2s.error);
equal(e2.message, e2s.message);
ok(e2s.stacktrace.match(/second/));
ok(e2s.stacktrace.match(/third/));
ok(e2s.stacktrace.match(/fourth/));
run_next_test();
});
@ -188,9 +181,11 @@ add_test(function test_fromJSON() {
equal(e3r.stack, e3j.stacktrace);
// parity with toJSON
let e4 = new JavaScriptError("first", "second", "third", "fourth");
let e4s = e4.toJSON();
deepEqual(e4, WebDriverError.fromJSON(e4s));
let e4j = new JavaScriptError("foo").toJSON();
let e4 = WebDriverError.fromJSON(e4j);
equal(e4j.error, e4.status);
equal(e4j.message, e4.message);
equal(e4j.stacktrace, e4.stack);
run_next_test();
});
@ -322,13 +317,12 @@ add_test(function test_JavaScriptError() {
equal("javascript error", err.status);
ok(err instanceof WebDriverError);
equal("undefined", new JavaScriptError(undefined).message);
// TODO(ato): Bug 1240550
//equal("funcname @file", new JavaScriptError("message", {fnName: "funcname", file: "file"}).stack);
equal("funcname @file, line line",
new JavaScriptError("message", {fnName: "funcname", file: "file", line: "line"}).stack);
equal("", new JavaScriptError(undefined).message);
// TODO(ato): More exhaustive tests for JS stack computation
let superErr = new RangeError("foo");
let inheritedErr = new JavaScriptError(superErr);
equal("RangeError: foo", inheritedErr.message);
equal(superErr.stack, inheritedErr.stack);
run_next_test();
});

View File

@ -29,8 +29,10 @@ module.exports = async function() {
messageManager.loadFrameScript("data:,(" + encodeURIComponent(
`function () {
addMessageListener("do-dir", function () {
content.console.dir(Array.from({length:1000}).reduce((res, _, i)=> {
res["item_" + i] = i;
content.console.dir(Array.from({length:333}).reduce((res, _, i)=> {
res["item_" + i] = "alphanum-indexed-" + i;
res[i] = "num-indexed-" + i;
res[Symbol(i)] = "symbol-indexed-" + i;
return res;
}, {}));
});

View File

@ -367,6 +367,9 @@ class Session(object):
self.alert = UserPrompt(self)
self.actions = Actions(self)
def __repr__(self):
return "<%s %s>" % (self.__class__.__name__, self.session_id or "(disconnected)")
def __eq__(self, other):
return (self.session_id is not None and isinstance(other, Session) and
self.session_id == other.session_id)
@ -628,6 +631,9 @@ class Element(object):
assert id not in self.session._element_cache
self.session._element_cache[self.id] = self
def __repr__(self):
return "<%s %s>" % (self.__class__.__name__, self.id)
def __eq__(self, other):
return (isinstance(other, Element) and self.id == other.id and
self.session == other.session)

View File

@ -8,9 +8,6 @@ add_task(async function test_tab_background_color_property() {
let extension = ExtensionTestUtils.loadExtension({
manifest: {
"theme": {
"images": {
"headerURL": "image1.png",
},
"colors": {
"accentcolor": ACCENT_COLOR,
"textcolor": TEXT_COLOR,
@ -18,9 +15,6 @@ add_task(async function test_tab_background_color_property() {
},
},
},
files: {
"image1.png": BACKGROUND,
},
});
await extension.startup();

View File

@ -41,6 +41,33 @@ interface mozIMozIntl : nsISupports
jsval getDisplayNames([optional] in jsval locales, [optional] in jsval options);
jsval getLocaleInfo([optional] in jsval locales);
/**
* Returns a list of language names formatted for display.
*
* Example:
* let langs = getLanguageDisplayNames(["pl"], ["fr", "de", "en"]);
* langs === ["Francuski", "Niemiecki", "Angielski"]
*/
jsval getLanguageDisplayNames(in jsval locales, in jsval langCodes);
/**
* Returns a list of region names formatted for display.
*
* Example:
* let regs = getLanguageDisplayNames(["pl"], ["US", "CA", "MX"]);
* regs === ["Stany Zjednoczone", "Kanada", "Meksyk"]
*/
jsval getRegionDisplayNames(in jsval locales, in jsval regionCodes);
/**
* Returns a list of locale names formatted for display.
*
* Example:
* let locs = getLanguageDisplayNames(["pl"], ["sr-RU", "es-MX", "fr-CA"]);
* locs === ["Serbski (Rosja)", "Hiszpański (Meksyk)", "Francuski (Kanada)"]
*/
jsval getLocaleDisplayNames(in jsval locales, in jsval localeCodes);
readonly attribute jsval DateTimeFormat;
readonly attribute jsval NumberFormat;
readonly attribute jsval Collator;

View File

@ -10,6 +10,11 @@ const mozIntlHelper =
const osPrefs =
Cc["@mozilla.org/intl/ospreferences;1"].getService(Ci.mozIOSPreferences);
/**
* RegExp used to parse a BCP47 language tag (ex: en-US, sr-Cyrl-RU etc.)
*/
const languageTagMatch = /^([a-z]{2,3}|[a-z]{4}|[a-z]{5,8})(?:[-_]([a-z]{4}))?(?:[-_]([A-Z]{2}|[0-9]{3}))?((?:[-_](?:[a-z0-9]{5,8}|[0-9][a-z0-9]{3}))*)(?:[-_][a-wy-z0-9](?:[-_][a-z0-9]{2,8})+)*(?:[-_]x(?:[-_][a-z0-9]{1,8})+)?$/i;
/**
* This helper function retrives currently used app locales, allowing
* all mozIntl APIs to use the current regional prefs locales unless
@ -175,6 +180,101 @@ class MozIntl {
return this._cache.getLocaleInfo(getLocales(locales), ...args);
}
getLanguageDisplayNames(locales, langCodes) {
if (locales !== undefined) {
throw new Error("First argument support not implemented yet");
}
const languageBundle = Services.strings.createBundle(
"chrome://global/locale/languageNames.properties");
return langCodes.map(langCode => {
if (typeof langCode !== "string") {
throw new TypeError("All language codes must be strings.");
}
try {
return languageBundle.GetStringFromName(langCode.toLowerCase());
} catch (e) {
return langCode.toLowerCase(); // Fall back to raw language subtag.
}
});
}
getRegionDisplayNames(locales, regionCodes) {
if (locales !== undefined) {
throw new Error("First argument support not implemented yet");
}
const regionBundle = Services.strings.createBundle(
"chrome://global/locale/regionNames.properties");
return regionCodes.map(regionCode => {
if (typeof regionCode !== "string") {
throw new TypeError("All region codes must be strings.");
}
try {
return regionBundle.GetStringFromName(regionCode.toLowerCase());
} catch (e) {
return regionCode.toUpperCase(); // Fall back to raw region subtag.
}
});
}
getLocaleDisplayNames(locales, localeCodes) {
if (locales !== undefined) {
throw new Error("First argument support not implemented yet");
}
// Patterns hardcoded from CLDR 33 english.
// We can later look into fetching them from CLDR directly.
const localePattern = "{0} ({1})";
const localeSeparator = ", ";
return localeCodes.map(localeCode => {
if (typeof localeCode !== "string") {
throw new TypeError("All locale codes must be strings.");
}
// Get the display name for this dictionary.
// XXX: To be replaced with Intl.Locale once it lands - bug 1433303.
const match = localeCode.match(languageTagMatch);
if (match === null) {
return localeCode;
}
const [
/* languageTag */,
languageSubtag,
scriptSubtag,
regionSubtag,
variantSubtags
] = match;
const displayName = [
this.getLanguageDisplayNames(locales, [languageSubtag])[0]
];
if (scriptSubtag) {
displayName.push(scriptSubtag);
}
if (regionSubtag) {
displayName.push(this.getRegionDisplayNames(locales, [regionSubtag])[0]);
}
if (variantSubtags) {
displayName.push(...variantSubtags.substr(1).split(/[-_]/)); // Collapse multiple variants.
}
let modifiers;
if (displayName.length === 1) {
return displayName[0];
} else if (displayName.length > 2) {
modifiers = displayName.slice(1).join(localeSeparator);
} else {
modifiers = displayName[1];
}
return localePattern.replace("{0}", displayName[0]).replace("{1}", modifiers);
});
}
get DateTimeFormat() {
if (!this._cache.hasOwnProperty("DateTimeFormat")) {
mozIntlHelper.addDateTimeFormatConstructor(this._cache);

View File

@ -16,12 +16,14 @@ function test_methods_presence() {
equal(Services.intl.getCalendarInfo instanceof Function, true);
equal(Services.intl.getDisplayNames instanceof Function, true);
equal(Services.intl.getLocaleInfo instanceof Function, true);
equal(Services.intl.getLocaleDisplayNames instanceof Function, true);
}
function test_methods_calling() {
Services.intl.getCalendarInfo("pl");
Services.intl.getDisplayNames("ar");
Services.intl.getLocaleInfo("de");
Services.intl.getLocaleDisplayNames(undefined, ["en-US", "sr-Cyrl-RU"]);
new Services.intl.DateTimeFormat("fr");
new Services.intl.RelativeTimeFormat("fr");
ok(true);

View File

@ -0,0 +1,83 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
ChromeUtils.import("resource://gre/modules/Services.jsm");
const gLangDN = Services.intl.getLanguageDisplayNames.bind(Services.intl, undefined);
const gRegDN = Services.intl.getRegionDisplayNames.bind(Services.intl, undefined);
const gLocDN = Services.intl.getLocaleDisplayNames.bind(Services.intl, undefined);
add_test(function test_valid_language_tag() {
deepEqual(gLocDN([]), []);
deepEqual(gLocDN(["en"]), ["English"]);
deepEqual(gLocDN(["und"]), ["und"]);
run_next_test();
});
add_test(function test_valid_region_tag() {
deepEqual(gLocDN(["en-US"]), ["English (United States)"]);
deepEqual(gLocDN(["en-XY"]), ["English (XY)"]);
run_next_test();
});
add_test(function test_valid_script_tag() {
deepEqual(gLocDN(["en-Cyrl"]), ["English (Cyrl)"]);
deepEqual(gLocDN(["en-Cyrl-RU"]), ["English (Cyrl, Russia)"]);
run_next_test();
});
add_test(function test_valid_variants_tag() {
deepEqual(gLocDN(["en-Cyrl-macos"]), ["English (Cyrl, macos)"]);
deepEqual(gLocDN(["en-Cyrl-RU-macos"]), ["English (Cyrl, Russia, macos)"]);
deepEqual(gLocDN(["en-Cyrl-RU-macos-modern"]), ["English (Cyrl, Russia, macos, modern)"]);
run_next_test();
});
add_test(function test_other_subtags_ignored() {
deepEqual(gLocDN(["en-x-ignore"]), ["English"]);
deepEqual(gLocDN(["en-t-en-latn"]), ["English"]);
deepEqual(gLocDN(["en-u-hc-h24"]), ["English"]);
run_next_test();
});
add_test(function test_invalid_locales() {
deepEqual(gLocDN(["2"]), ["2"]);
deepEqual(gLocDN([""]), [""]);
Assert.throws(() => gLocDN([2]));
Assert.throws(() => gLocDN([{}]));
Assert.throws(() => gLocDN([true]));
run_next_test();
});
add_test(function test_language_only() {
deepEqual(gLangDN([]), []);
deepEqual(gLangDN(["en"]), ["English"]);
deepEqual(gLangDN(["und"]), ["und"]);
run_next_test();
});
add_test(function test_invalid_languages() {
deepEqual(gLangDN(["2"]), ["2"]);
deepEqual(gLangDN([""]), [""]);
Assert.throws(() => gLangDN([2]));
Assert.throws(() => gLangDN([{}]));
Assert.throws(() => gLangDN([true]));
run_next_test();
});
add_test(function test_region_only() {
deepEqual(gRegDN([]), []);
deepEqual(gRegDN(["US"]), ["United States"]);
deepEqual(gRegDN(["und"]), ["UND"]);
run_next_test();
});
add_test(function test_invalid_regions() {
deepEqual(gRegDN(["2"]), ["2"]);
deepEqual(gRegDN([""]), [""]);
Assert.throws(() => gRegDN([2]));
Assert.throws(() => gRegDN([{}]));
Assert.throws(() => gRegDN([true]));
run_next_test();
});

View File

@ -2,4 +2,5 @@
head =
[test_mozintl.js]
[test_mozintl_getLocaleDisplayNames.js]
[test_mozintlhelper.js]

View File

@ -248,14 +248,12 @@ NarrateControls.prototype = {
},
_getLanguageName(lang) {
if (!this._langStrings) {
this._langStrings = Services.strings.createBundle(
"chrome://global/locale/languageNames.properties ");
}
try {
// language tags will be lower case ascii between 2 and 3 characters long.
return this._langStrings.GetStringFromName(lang.match(/^[a-z]{2,3}/)[0]);
// This may throw if the lang doesn't match.
// XXX: Replace with Intl.Locale once bug 1433303 lands.
let langCode = lang.match(/^[a-z]{2,3}/)[0];
return Services.intl.getLanguageDisplayNames(undefined, [langCode]);
} catch (e) {
return "";
}

View File

@ -1102,6 +1102,7 @@
{ transform: "scale(1)", opacity: 0.55 }
],
options: {
easing: "ease",
duration: 400
}
},
@ -1111,6 +1112,7 @@
{ opacity: 1 }
],
options: {
easing: "ease",
duration: 200
}
},

View File

@ -4,8 +4,6 @@
var EXPORTED_SYMBOLS = [ "InlineSpellChecker",
"SpellCheckHelper" ];
var gLanguageBundle;
var gRegionBundle;
const MAX_UNDO_STACK_DEPTH = 1;
ChromeUtils.import("resource://gre/modules/Services.jsm");
@ -170,9 +168,10 @@ InlineSpellChecker.prototype = {
sortDictionaryList(list) {
var sortedList = [];
var names = Services.intl.getLocaleDisplayNames(undefined, list);
for (var i = 0; i < list.length; i++) {
sortedList.push({"id": list[i],
"label": this.getDictionaryDisplayName(list[i])});
"label": names[i]});
}
sortedList.sort(function(a, b) {
if (a.label < b.label)
@ -243,63 +242,6 @@ InlineSpellChecker.prototype = {
return list.length;
},
// Formats a valid BCP 47 language tag based on available localized names.
getDictionaryDisplayName(dictionaryName) {
try {
// Get the display name for this dictionary.
let languageTagMatch = /^([a-z]{2,3}|[a-z]{4}|[a-z]{5,8})(?:[-_]([a-z]{4}))?(?:[-_]([A-Z]{2}|[0-9]{3}))?((?:[-_](?:[a-z0-9]{5,8}|[0-9][a-z0-9]{3}))*)(?:[-_][a-wy-z0-9](?:[-_][a-z0-9]{2,8})+)*(?:[-_]x(?:[-_][a-z0-9]{1,8})+)?$/i;
var [/* languageTag */, languageSubtag, scriptSubtag, regionSubtag, variantSubtags] = dictionaryName.match(languageTagMatch);
} catch (e) {
// If we weren't given a valid language tag, just use the raw dictionary name.
return dictionaryName;
}
if (!gLanguageBundle) {
// Create the bundles for language and region names.
gLanguageBundle = Services.strings.createBundle(
"chrome://global/locale/languageNames.properties");
gRegionBundle = Services.strings.createBundle(
"chrome://global/locale/regionNames.properties");
}
var displayName = "";
// Language subtag will normally be 2 or 3 letters, but could be up to 8.
try {
displayName += gLanguageBundle.GetStringFromName(languageSubtag.toLowerCase());
} catch (e) {
displayName += languageSubtag.toLowerCase(); // Fall back to raw language subtag.
}
// Region subtag will be 2 letters or 3 digits.
if (regionSubtag) {
displayName += " (";
try {
displayName += gRegionBundle.GetStringFromName(regionSubtag.toLowerCase());
} catch (e) {
displayName += regionSubtag.toUpperCase(); // Fall back to raw region subtag.
}
displayName += ")";
}
// Script subtag will be 4 letters.
if (scriptSubtag) {
displayName += " / ";
// XXX: See bug 666662 and bug 666731 for full implementation.
displayName += scriptSubtag; // Fall back to raw script subtag.
}
// Each variant subtag will be 4 to 8 chars.
if (variantSubtags)
// XXX: See bug 666662 and bug 666731 for full implementation.
displayName += " (" + variantSubtags.substr(1).split(/[-_]/).join(" / ") + ")"; // Collapse multiple variants.
return displayName;
},
// undoes the work of addDictionaryListToMenu for the menu
// (call on popup hiding)
clearDictionaryListFromMenu() {

View File

@ -14,115 +14,6 @@ function test() {
}
var tests = {
// Test various possible dictionary name to ensure they display as expected.
// XXX: This only works for the 'en-US' locale, as the testing involves localized output.
testDictionaryDisplayNames() {
let isc = new InlineSpellChecker();
// Check non-well-formed language tag.
is(isc.getDictionaryDisplayName("-invalid-"), "-invalid-", "'-invalid-' should display as '-invalid-'");
// XXX: It isn't clear how we'd ideally want to display variant subtags.
// Check valid language subtag.
is(isc.getDictionaryDisplayName("en"), "English", "'en' should display as 'English'");
is(isc.getDictionaryDisplayName("en-fonipa"), "English (fonipa)", "'en-fonipa' should display as 'English (fonipa)'");
is(isc.getDictionaryDisplayName("en-qxqaaaaz"), "English (qxqaaaaz)", "'en-qxqaaaaz' should display as 'English (qxqaaaaz)'");
// Check valid language subtag and valid region subtag.
is(isc.getDictionaryDisplayName("en-US"), "English (United States)", "'en-US' should display as 'English (United States)'");
is(isc.getDictionaryDisplayName("en-US-fonipa"), "English (United States) (fonipa)", "'en-US-fonipa' should display as 'English (United States) (fonipa)'");
is(isc.getDictionaryDisplayName("en-US-qxqaaaaz"), "English (United States) (qxqaaaaz)", "'en-US-qxqaaaaz' should display as 'English (United States) (qxqaaaaz)'");
// Check valid language subtag and invalid but well-formed region subtag.
is(isc.getDictionaryDisplayName("en-WO"), "English (WO)", "'en-WO' should display as 'English (WO)'");
is(isc.getDictionaryDisplayName("en-WO-fonipa"), "English (WO) (fonipa)", "'en-WO-fonipa' should display as 'English (WO) (fonipa)'");
is(isc.getDictionaryDisplayName("en-WO-qxqaaaaz"), "English (WO) (qxqaaaaz)", "'en-WO-qxqaaaaz' should display as 'English (WO) (qxqaaaaz)'");
// Check valid language subtag and valid script subtag.
todo_is(isc.getDictionaryDisplayName("en-Cyrl"), "English / Cyrillic", "'en-Cyrl' should display as 'English / Cyrillic'");
todo_is(isc.getDictionaryDisplayName("en-Cyrl-fonipa"), "English / Cyrillic (fonipa)", "'en-Cyrl-fonipa' should display as 'English / Cyrillic (fonipa)'");
todo_is(isc.getDictionaryDisplayName("en-Cyrl-qxqaaaaz"), "English / Cyrillic (qxqaaaaz)", "'en-Cyrl-qxqaaaaz' should display as 'English / Cyrillic (qxqaaaaz)'");
todo_is(isc.getDictionaryDisplayName("en-Cyrl-US"), "English (United States) / Cyrillic", "'en-Cyrl-US' should display as 'English (United States) / Cyrillic'");
todo_is(isc.getDictionaryDisplayName("en-Cyrl-US-fonipa"), "English (United States) / Cyrillic (fonipa)", "'en-Cyrl-US-fonipa' should display as 'English (United States) / Cyrillic (fonipa)'");
todo_is(isc.getDictionaryDisplayName("en-Cyrl-US-qxqaaaaz"), "English (United States) / Cyrillic (qxqaaaaz)", "'en-Cyrl-US-qxqaaaaz' should display as 'English (United States) / Cyrillic (qxqaaaaz)'");
todo_is(isc.getDictionaryDisplayName("en-Cyrl-WO"), "English (WO) / Cyrillic", "'en-Cyrl-WO' should display as 'English (WO) / Cyrillic'");
todo_is(isc.getDictionaryDisplayName("en-Cyrl-WO-fonipa"), "English (WO) / Cyrillic (fonipa)", "'en-Cyrl-WO-fonipa' should display as 'English (WO) / Cyrillic (fonipa)'");
todo_is(isc.getDictionaryDisplayName("en-Cyrl-WO-qxqaaaaz"), "English (WO) / Cyrillic (qxqaaaaz)", "'en-Cyrl-WO-qxqaaaaz' should display as 'English (WO) / Cyrillic (qxqaaaaz)'");
// Check valid language subtag and invalid but well-formed script subtag.
is(isc.getDictionaryDisplayName("en-Qaaz"), "English / Qaaz", "'en-Qaaz' should display as 'English / Qaaz'");
is(isc.getDictionaryDisplayName("en-Qaaz-fonipa"), "English / Qaaz (fonipa)", "'en-Qaaz-fonipa' should display as 'English / Qaaz (fonipa)'");
is(isc.getDictionaryDisplayName("en-Qaaz-qxqaaaaz"), "English / Qaaz (qxqaaaaz)", "'en-Qaaz-qxqaaaaz' should display as 'English / Qaaz (qxqaaaaz)'");
is(isc.getDictionaryDisplayName("en-Qaaz-US"), "English (United States) / Qaaz", "'en-Qaaz-US' should display as 'English (United States) / Qaaz'");
is(isc.getDictionaryDisplayName("en-Qaaz-US-fonipa"), "English (United States) / Qaaz (fonipa)", "'en-Qaaz-US-fonipa' should display as 'English (United States) / Qaaz (fonipa)'");
is(isc.getDictionaryDisplayName("en-Qaaz-US-qxqaaaaz"), "English (United States) / Qaaz (qxqaaaaz)", "'en-Qaaz-US-qxqaaaaz' should display as 'English (United States) / Qaaz (qxqaaaaz)'");
is(isc.getDictionaryDisplayName("en-Qaaz-WO"), "English (WO) / Qaaz", "'en-Qaaz-WO' should display as 'English (WO) / Qaaz'");
is(isc.getDictionaryDisplayName("en-Qaaz-WO-fonipa"), "English (WO) / Qaaz (fonipa)", "'en-Qaaz-WO-fonipa' should display as 'English (WO) / Qaaz (fonipa)'");
is(isc.getDictionaryDisplayName("en-Qaaz-WO-qxqaaaaz"), "English (WO) / Qaaz (qxqaaaaz)", "'en-Qaaz-WO-qxqaaaaz' should display as 'English (WO) / Qaaz (qxqaaaaz)'");
// Check invalid but well-formed language subtag.
is(isc.getDictionaryDisplayName("qaz"), "qaz", "'qaz' should display as 'qaz'");
is(isc.getDictionaryDisplayName("qaz-fonipa"), "qaz (fonipa)", "'qaz-fonipa' should display as 'qaz (fonipa)'");
is(isc.getDictionaryDisplayName("qaz-qxqaaaaz"), "qaz (qxqaaaaz)", "'qaz-qxqaaaaz' should display as 'qaz (qxqaaaaz)'");
// Check invalid but well-formed language subtag and valid region subtag.
is(isc.getDictionaryDisplayName("qaz-US"), "qaz (United States)", "'qaz-US' should display as 'qaz (United States)'");
is(isc.getDictionaryDisplayName("qaz-US-fonipa"), "qaz (United States) (fonipa)", "'qaz-US-fonipa' should display as 'qaz (United States) (fonipa)'");
is(isc.getDictionaryDisplayName("qaz-US-qxqaaaaz"), "qaz (United States) (qxqaaaaz)", "'qaz-US-qxqaaaaz' should display as 'qaz (United States) (qxqaaaaz)'");
// Check invalid but well-formed language subtag and invalid but well-formed region subtag.
is(isc.getDictionaryDisplayName("qaz-WO"), "qaz (WO)", "'qaz-WO' should display as 'qaz (WO)'");
is(isc.getDictionaryDisplayName("qaz-WO-fonipa"), "qaz (WO) (fonipa)", "'qaz-WO-fonipa' should display as 'qaz (WO) (fonipa)'");
is(isc.getDictionaryDisplayName("qaz-WO-qxqaaaaz"), "qaz (WO) (qxqaaaaz)", "'qaz-WO-qxqaaaaz' should display as 'qaz (WO) (qxqaaaaz)'");
// Check invalid but well-formed language subtag and valid script subtag.
todo_is(isc.getDictionaryDisplayName("qaz-Cyrl"), "qaz / Cyrillic", "'qaz-Cyrl' should display as 'qaz / Cyrillic'");
todo_is(isc.getDictionaryDisplayName("qaz-Cyrl-fonipa"), "qaz / Cyrillic (fonipa)", "'qaz-Cyrl-fonipa' should display as 'qaz / Cyrillic (fonipa)'");
todo_is(isc.getDictionaryDisplayName("qaz-Cyrl-qxqaaaaz"), "qaz / Cyrillic (qxqaaaaz)", "'qaz-Cyrl-qxqaaaaz' should display as 'qaz / Cyrillic (qxqaaaaz)'");
todo_is(isc.getDictionaryDisplayName("qaz-Cyrl-US"), "qaz (United States) / Cyrillic", "'qaz-Cyrl-US' should display as 'qaz (United States) / Cyrillic'");
todo_is(isc.getDictionaryDisplayName("qaz-Cyrl-US-fonipa"), "qaz (United States) / Cyrillic (fonipa)", "'qaz-Cyrl-US-fonipa' should display as 'qaz (United States) / Cyrillic (fonipa)'");
todo_is(isc.getDictionaryDisplayName("qaz-Cyrl-US-qxqaaaaz"), "qaz (United States) / Cyrillic (qxqaaaaz)", "'qaz-Cyrl-US-qxqaaaaz' should display as 'qaz (United States) / Cyrillic (qxqaaaaz)'");
todo_is(isc.getDictionaryDisplayName("qaz-Cyrl-WO"), "qaz (WO) / Cyrillic", "'qaz-Cyrl-WO' should display as 'qaz (WO) / Cyrillic'");
todo_is(isc.getDictionaryDisplayName("qaz-Cyrl-WO-fonipa"), "qaz (WO) / Cyrillic (fonipa)", "'qaz-Cyrl-WO-fonipa' should display as 'qaz (WO) / Cyrillic (fonipa)'");
todo_is(isc.getDictionaryDisplayName("qaz-Cyrl-WO-qxqaaaaz"), "qaz (WO) / Cyrillic (qxqaaaaz)", "'qaz-Cyrl-WO-qxqaaaaz' should display as 'qaz (WO) / Cyrillic (qxqaaaaz)'");
// Check invalid but well-formed language subtag and invalid but well-formed script subtag.
is(isc.getDictionaryDisplayName("qaz-Qaaz"), "qaz / Qaaz", "'qaz-Qaaz' should display as 'qaz / Qaaz'");
is(isc.getDictionaryDisplayName("qaz-Qaaz-fonipa"), "qaz / Qaaz (fonipa)", "'qaz-Qaaz-fonipa' should display as 'qaz / Qaaz (fonipa)'");
is(isc.getDictionaryDisplayName("qaz-Qaaz-qxqaaaaz"), "qaz / Qaaz (qxqaaaaz)", "'qaz-Qaaz-qxqaaaaz' should display as 'qaz / Qaaz (qxqaaaaz)'");
is(isc.getDictionaryDisplayName("qaz-Qaaz-US"), "qaz (United States) / Qaaz", "'qaz-Qaaz-US' should display as 'qaz (United States) / Qaaz'");
is(isc.getDictionaryDisplayName("qaz-Qaaz-US-fonipa"), "qaz (United States) / Qaaz (fonipa)", "'qaz-Qaaz-US-fonipa' should display as 'qaz (United States) / Qaaz (fonipa)'");
is(isc.getDictionaryDisplayName("qaz-Qaaz-US-qxqaaaaz"), "qaz (United States) / Qaaz (qxqaaaaz)", "'qaz-Qaaz-US-qxqaaaaz' should display as 'qaz (United States) / Qaaz (qxqaaaaz)'");
is(isc.getDictionaryDisplayName("qaz-Qaaz-WO"), "qaz (WO) / Qaaz", "'qaz-Qaaz-WO' should display as 'qaz (WO) / Qaaz'");
is(isc.getDictionaryDisplayName("qaz-Qaaz-WO-fonipa"), "qaz (WO) / Qaaz (fonipa)", "'qaz-Qaaz-WO-fonipa' should display as 'qaz (WO) / Qaaz (fonipa)'");
is(isc.getDictionaryDisplayName("qaz-Qaaz-WO-qxqaaaaz"), "qaz (WO) / Qaaz (qxqaaaaz)", "'qaz-Qaaz-WO-qxqaaaaz' should display as 'qaz (WO) / Qaaz (qxqaaaaz)'");
// Check multiple variant subtags.
todo_is(isc.getDictionaryDisplayName("en-Cyrl-US-fonipa-fonxsamp"), "English (United States) / Cyrillic (fonipa / fonxsamp)", "'en-Cyrl-US-fonipa-fonxsamp' should display as 'English (United States) / Cyrillic (fonipa / fonxsamp)'");
todo_is(isc.getDictionaryDisplayName("en-Cyrl-US-fonipa-qxqaaaaz"), "English (United States) / Cyrillic (fonipa / qxqaaaaz)", "'en-Cyrl-US-fonipa-qxqaaaaz' should display as 'English (United States) / Cyrillic (fonipa / qxqaaaaz)'");
todo_is(isc.getDictionaryDisplayName("en-Cyrl-US-fonipa-fonxsamp-qxqaaaaz"), "English (United States) / Cyrillic (fonipa / fonxsamp / qxqaaaaz)", "'en-Cyrl-US-fonipa-fonxsamp-qxqaaaaz' should display as 'English (United States) / Cyrillic (fonipa / fonxsamp / qxqaaaaz)'");
is(isc.getDictionaryDisplayName("qaz-Qaaz-WO-fonipa-fonxsamp"), "qaz (WO) / Qaaz (fonipa / fonxsamp)", "'qaz-Qaaz-WO-fonipa-fonxsamp' should display as 'qaz (WO) / Qaaz (fonipa / fonxsamp)'");
is(isc.getDictionaryDisplayName("qaz-Qaaz-WO-fonipa-qxqaaaaz"), "qaz (WO) / Qaaz (fonipa / qxqaaaaz)", "'qaz-Qaaz-WO-fonipa-qxqaaaaz' should display as 'qaz (WO) / Qaaz (fonipa / qxqaaaaz)'");
is(isc.getDictionaryDisplayName("qaz-Qaaz-WO-fonipa-fonxsamp-qxqaaaaz"), "qaz (WO) / Qaaz (fonipa / fonxsamp / qxqaaaaz)", "'qaz-Qaaz-WO-fonipa-fonxsamp-qxqaaaaz' should display as 'qaz (WO) / Qaaz (fonipa / fonxsamp / qxqaaaaz)'");
// Check numeric region subtag.
todo_is(isc.getDictionaryDisplayName("es-419"), "Spanish (Latin America and the Caribbean)", "'es-419' should display as 'Spanish (Latin America and the Caribbean)'");
// Check that extension subtags are ignored.
todo_is(isc.getDictionaryDisplayName("en-Cyrl-t-en-latn-m0-ungegn-2007"), "English / Cyrillic", "'en-Cyrl-t-en-latn-m0-ungegn-2007' should display as 'English / Cyrillic'");
// Check that privateuse subtags are ignored.
is(isc.getDictionaryDisplayName("en-x-ignore"), "English", "'en-x-ignore' should display as 'English'");
is(isc.getDictionaryDisplayName("en-x-ignore-this"), "English", "'en-x-ignore-this' should display as 'English'");
is(isc.getDictionaryDisplayName("en-x-ignore-this-subtag"), "English", "'en-x-ignore-this-subtag' should display as 'English'");
// Check that both extension and privateuse subtags are ignored.
todo_is(isc.getDictionaryDisplayName("en-Cyrl-t-en-latn-m0-ungegn-2007-x-ignore-this-subtag"), "English / Cyrillic", "'en-Cyrl-t-en-latn-m0-ungegn-2007-x-ignore-this-subtag' should display as 'English / Cyrillic'");
// XXX: Check grandfathered tags.
},
testFlagsForInputs() {
const HTML_NS = "http://www.w3.org/1999/xhtml";
const {

View File

@ -23,11 +23,8 @@ menubar {
}
toolbarseparator {
-moz-appearance: none;
-moz-appearance: separator;
margin: 3px 4px;
background-color: ThreeDShadow;
padding: 0;
width: 1px !important;
}
/* ::::: toolbarpaletteitem ::::: */
@ -56,4 +53,3 @@ toolbarpaletteitem[dragover="left"] {
toolbarpaletteitem[dragover="right"] {
border-right-color: #000000;
}