mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 11:25:00 +00:00
Merge mozilla-central to mozilla-inbound. a=merge on a CLOSED TREE
This commit is contained in:
commit
29ba7b4974
@ -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();
|
||||
|
@ -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();
|
||||
});
|
||||
|
@ -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();
|
||||
},
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
|
@ -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 =
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
});
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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, {
|
||||
|
@ -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
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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]
|
||||
|
@ -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>
|
@ -65,6 +65,9 @@ class nsDOMStringMap;
|
||||
namespace mozilla {
|
||||
class DeclarationBlock;
|
||||
class TextEditor;
|
||||
namespace css {
|
||||
struct URLValue;
|
||||
} // namespace css
|
||||
namespace dom {
|
||||
struct AnimationFilter;
|
||||
struct ScrollIntoViewOptions;
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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.
@ -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]
|
||||
|
@ -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>
|
@ -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.
@ -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]
|
||||
|
@ -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>
|
@ -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
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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]
|
||||
|
Binary file not shown.
@ -1 +0,0 @@
|
||||
Content-Type: application/java-archive
|
@ -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>
|
@ -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]
|
||||
|
6
dom/workers/test/bug1063538.sjs
Normal file
6
dom/workers/test/bug1063538.sjs
Normal file
@ -0,0 +1,6 @@
|
||||
function handleRequest(request, response) {
|
||||
response.processAsync();
|
||||
response.write("Hello");
|
||||
setTimeout(function() { response.finish(); }, 100000); // wait 100 seconds.
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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()) {
|
||||
|
@ -294,8 +294,6 @@ whitelist-types = [
|
||||
"nsFont",
|
||||
"nsAtom",
|
||||
"nsDynamicAtom",
|
||||
"nsMainThreadPtrHandle",
|
||||
"nsMainThreadPtrHolder",
|
||||
"nsMargin",
|
||||
"nsMediaFeature",
|
||||
"nsMediaFeatures",
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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(");
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -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__
|
||||
|
@ -1 +0,0 @@
|
||||
Content-Type: application/java-archive
|
@ -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^
|
@ -1,5 +0,0 @@
|
||||
function handleRequest(request, response)
|
||||
{
|
||||
response.setStatusLine(request.httpVersion, 301, "Moved Permanently");
|
||||
response.setHeader("Location", request.queryString, false);
|
||||
}
|
@ -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>
|
@ -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>
|
||||
|
@ -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>
|
@ -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();
|
||||
}
|
@ -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]
|
||||
|
@ -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
@ -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(),
|
||||
})
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
__version__ = '2.5.0'
|
||||
__version__ = '2.6.0'
|
||||
|
||||
from marionette_driver import (
|
||||
addons,
|
||||
|
@ -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",
|
||||
|
@ -1,3 +1,3 @@
|
||||
mozrunner >= 6.13
|
||||
mozrunner >= 6.15
|
||||
mozversion >= 1.1
|
||||
six
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
__version__ = '4.3.0'
|
||||
__version__ = '4.4.0'
|
||||
|
||||
from .marionette_test import (
|
||||
CommonTestCase,
|
||||
|
@ -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("""
|
||||
|
@ -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]:
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
});
|
||||
|
@ -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;
|
||||
}, {}));
|
||||
});
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
});
|
@ -2,4 +2,5 @@
|
||||
head =
|
||||
|
||||
[test_mozintl.js]
|
||||
[test_mozintl_getLocaleDisplayNames.js]
|
||||
[test_mozintlhelper.js]
|
||||
|
@ -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 "";
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
},
|
||||
|
@ -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() {
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user