mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 05:41:12 +00:00
Merge autoland to mozilla-central r=merge a=merge
This commit is contained in:
commit
ada131e8c5
@ -78,24 +78,24 @@ MAC_BUNDLE_VERSION = $(shell $(PYTHON) $(srcdir)/macversion.py --version=$(MOZ_A
|
||||
.PHONY: repackage
|
||||
tools repackage:: $(DIST)/bin/$(MOZ_APP_NAME) features
|
||||
rm -rf $(dist_dest)
|
||||
$(MKDIR) -p $(dist_dest)/Contents/MacOS
|
||||
$(MKDIR) -p $(dist_dest)/$(LPROJ)
|
||||
rsync -a --exclude '*.in' $(srcdir)/macbuild/Contents $(dist_dest) --exclude English.lproj
|
||||
rsync -a --exclude '*.in' $(srcdir)/macbuild/Contents/Resources/English.lproj/ $(dist_dest)/$(LPROJ)
|
||||
sed -e 's/%APP_VERSION%/$(MOZ_APP_VERSION)/' -e 's/%MAC_APP_NAME%/$(MAC_APP_NAME)/' -e 's/%MOZ_MACBUNDLE_ID%/$(MOZ_MACBUNDLE_ID)/' -e 's/%MAC_BUNDLE_VERSION%/$(MAC_BUNDLE_VERSION)/' -e 's|%MOZ_DEVELOPER_REPO_PATH%|$(topsrcdir)|' -e 's|%MOZ_DEVELOPER_OBJ_PATH%|$(topobjdir)|' $(srcdir)/macbuild/Contents/Info.plist.in > $(dist_dest)/Contents/Info.plist
|
||||
sed -e 's/%MAC_APP_NAME%/$(MAC_APP_NAME)/' $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | iconv -f UTF-8 -t UTF-16 > $(dist_dest)/$(LPROJ)/InfoPlist.strings
|
||||
rsync -a --exclude-from='$(srcdir)/macbuild/Contents/MacOS-files.in' $(DIST)/bin/ $(dist_dest)/Contents/Resources
|
||||
rsync -a --include-from='$(srcdir)/macbuild/Contents/MacOS-files.in' --exclude '*' $(DIST)/bin/ $(dist_dest)/Contents/MacOS
|
||||
$(RM) $(dist_dest)/Contents/MacOS/$(MOZ_APP_NAME)
|
||||
rsync -aL $(DIST)/bin/$(MOZ_APP_NAME) $(dist_dest)/Contents/MacOS
|
||||
cp -RL $(DIST)/branding/firefox.icns $(dist_dest)/Contents/Resources/firefox.icns
|
||||
cp -RL $(DIST)/branding/document.icns $(dist_dest)/Contents/Resources/document.icns
|
||||
$(MKDIR) -p $(dist_dest)/Contents/Library/LaunchServices
|
||||
$(MKDIR) -p '$(dist_dest)/Contents/MacOS'
|
||||
$(MKDIR) -p '$(dist_dest)/$(LPROJ)'
|
||||
rsync -a --exclude '*.in' $(srcdir)/macbuild/Contents '$(dist_dest)' --exclude English.lproj
|
||||
rsync -a --exclude '*.in' $(srcdir)/macbuild/Contents/Resources/English.lproj/ '$(dist_dest)/$(LPROJ)'
|
||||
sed -e 's/%APP_VERSION%/$(MOZ_APP_VERSION)/' -e 's/%MAC_APP_NAME%/$(MAC_APP_NAME)/' -e 's/%MOZ_MACBUNDLE_ID%/$(MOZ_MACBUNDLE_ID)/' -e 's/%MAC_BUNDLE_VERSION%/$(MAC_BUNDLE_VERSION)/' -e 's|%MOZ_DEVELOPER_REPO_PATH%|$(topsrcdir)|' -e 's|%MOZ_DEVELOPER_OBJ_PATH%|$(topobjdir)|' $(srcdir)/macbuild/Contents/Info.plist.in > '$(dist_dest)/Contents/Info.plist'
|
||||
sed -e 's/%MAC_APP_NAME%/$(MAC_APP_NAME)/' $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | iconv -f UTF-8 -t UTF-16 > '$(dist_dest)/$(LPROJ)/InfoPlist.strings'
|
||||
rsync -a --exclude-from='$(srcdir)/macbuild/Contents/MacOS-files.in' $(DIST)/bin/ '$(dist_dest)/Contents/Resources'
|
||||
rsync -a --include-from='$(srcdir)/macbuild/Contents/MacOS-files.in' --exclude '*' $(DIST)/bin/ '$(dist_dest)/Contents/MacOS'
|
||||
$(RM) '$(dist_dest)/Contents/MacOS/$(MOZ_APP_NAME)'
|
||||
rsync -aL $(DIST)/bin/$(MOZ_APP_NAME) '$(dist_dest)/Contents/MacOS'
|
||||
cp -RL $(DIST)/branding/firefox.icns '$(dist_dest)/Contents/Resources/firefox.icns'
|
||||
cp -RL $(DIST)/branding/document.icns '$(dist_dest)/Contents/Resources/document.icns'
|
||||
$(MKDIR) -p '$(dist_dest)/Contents/Library/LaunchServices'
|
||||
ifdef MOZ_UPDATER
|
||||
mv -f $(dist_dest)/Contents/MacOS/updater.app/Contents/MacOS/org.mozilla.updater $(dist_dest)/Contents/Library/LaunchServices
|
||||
ln -s ../../../../Library/LaunchServices/org.mozilla.updater $(dist_dest)/Contents/MacOS/updater.app/Contents/MacOS/org.mozilla.updater
|
||||
mv -f '$(dist_dest)/Contents/MacOS/updater.app/Contents/MacOS/org.mozilla.updater' '$(dist_dest)/Contents/Library/LaunchServices'
|
||||
ln -s ../../../../Library/LaunchServices/org.mozilla.updater '$(dist_dest)/Contents/MacOS/updater.app/Contents/MacOS/org.mozilla.updater'
|
||||
endif
|
||||
printf APPLMOZB > $(dist_dest)/Contents/PkgInfo
|
||||
printf APPLMOZB > '$(dist_dest)/Contents/PkgInfo'
|
||||
endif
|
||||
|
||||
.PHONY: features
|
||||
|
@ -49,6 +49,7 @@ let AddressDataLoader = {
|
||||
country: false,
|
||||
level1: new Set(),
|
||||
},
|
||||
|
||||
/**
|
||||
* Load address data and extension script into a sandbox from different paths.
|
||||
* @param {string} path
|
||||
@ -77,11 +78,38 @@ let AddressDataLoader = {
|
||||
}
|
||||
return sandbox;
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert certain properties' string value into array. We should make sure
|
||||
* the cached data is parsed.
|
||||
* @param {object} data Original metadata from addressReferences.
|
||||
* @returns {object} parsed metadata with property value that converts to array.
|
||||
*/
|
||||
_parse(data) {
|
||||
if (!data) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const properties = ["languages", "sub_keys", "sub_names", "sub_lnames"];
|
||||
for (let key of properties) {
|
||||
if (!data[key]) {
|
||||
continue;
|
||||
}
|
||||
// No need to normalize data if the value is array already.
|
||||
if (Array.isArray(data[key])) {
|
||||
return data;
|
||||
}
|
||||
|
||||
data[key] = data[key].split("~");
|
||||
}
|
||||
return data;
|
||||
},
|
||||
|
||||
/**
|
||||
* We'll cache addressData in the loader once the data loaded from scripts.
|
||||
* It'll become the example below after loading addressReferences with extension:
|
||||
* addressData: {
|
||||
"data/US": {"lang": "en", ...// Data defined in libaddressinput metadata
|
||||
* "data/US": {"lang": ["en"], ...// Data defined in libaddressinput metadata
|
||||
* "alternative_names": ... // Data defined in extension }
|
||||
* "data/CA": {} // Other supported country metadata
|
||||
* "data/TW": {} // Other supported country metadata
|
||||
@ -89,16 +117,16 @@ let AddressDataLoader = {
|
||||
* }
|
||||
* @param {string} country
|
||||
* @param {string} level1
|
||||
* @returns {object}
|
||||
* @returns {object} Default locale metadata
|
||||
*/
|
||||
getData(country, level1 = null) {
|
||||
_loadData(country, level1 = null) {
|
||||
// Load the addressData if needed
|
||||
if (!this._dataLoaded.country) {
|
||||
this._addressData = this._loadScripts(ADDRESS_METADATA_PATH).addressData;
|
||||
this._dataLoaded.country = true;
|
||||
}
|
||||
if (!level1) {
|
||||
return this._addressData[`data/${country}`];
|
||||
return this._parse(this._addressData[`data/${country}`]);
|
||||
}
|
||||
// If level1 is set, load addressReferences under country folder with specific
|
||||
// country/level 1 for level 2 information.
|
||||
@ -107,7 +135,30 @@ let AddressDataLoader = {
|
||||
this._loadScripts(`${ADDRESS_METADATA_PATH}${country}/`).addressData);
|
||||
this._dataLoaded.level1.add(country);
|
||||
}
|
||||
return this._addressData[`data/${country}/${level1}`];
|
||||
return this._parse(this._addressData[`data/${country}/${level1}`]);
|
||||
},
|
||||
|
||||
/**
|
||||
* Return the region metadata with default locale and other locales (if exists).
|
||||
* @param {string} country
|
||||
* @param {string} level1
|
||||
* @returns {object} Return default locale and other locales metadata.
|
||||
*/
|
||||
getData(country, level1) {
|
||||
let defaultLocale = this._loadData(country, level1);
|
||||
if (!defaultLocale) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let countryData = this._parse(this._addressData[`data/${country}`]);
|
||||
let locales = [];
|
||||
// TODO: Should be able to support multi-locale level 1/ level 2 metadata query
|
||||
// in Bug 1421886
|
||||
if (countryData.languages) {
|
||||
let list = countryData.languages.filter(key => key !== countryData.lang);
|
||||
locales = list.map(key => this._parse(this._addressData[`${defaultLocale.id}--${key}`]));
|
||||
}
|
||||
return {defaultLocale, locales};
|
||||
},
|
||||
};
|
||||
|
||||
@ -289,16 +340,18 @@ this.FormAutofillUtils = {
|
||||
|
||||
/**
|
||||
* Get country address data and fallback to US if not found.
|
||||
* See AddressDataLoader.getData for more details of addressData structure.
|
||||
* See AddressDataLoader._loadData for more details of addressData structure.
|
||||
* @param {string} [country=FormAutofillUtils.DEFAULT_REGION]
|
||||
* The country code for requesting specific country's metadata. It'll be
|
||||
* default region if parameter is not set.
|
||||
* @param {string} [level1=null]
|
||||
* Retrun address level 1/level 2 metadata if parameter is set.
|
||||
* @returns {object}
|
||||
* Return the metadata of specific region.
|
||||
* @returns {object|null}
|
||||
* Return metadata of specific region with default locale and other supported
|
||||
* locales. We need to return a deafult country metadata for layout format
|
||||
* and collator, but for sub-region metadata we'll just return null if not found.
|
||||
*/
|
||||
getCountryAddressData(country = FormAutofillUtils.DEFAULT_REGION, level1 = null) {
|
||||
getCountryAddressRawData(country = FormAutofillUtils.DEFAULT_REGION, level1 = null) {
|
||||
let metadata = AddressDataLoader.getData(country, level1);
|
||||
if (!metadata) {
|
||||
if (level1) {
|
||||
@ -310,8 +363,35 @@ this.FormAutofillUtils = {
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to US if we couldn't get data from default region.
|
||||
return metadata || AddressDataLoader.getData("US");
|
||||
// TODO: Now we fallback to US if we couldn't get data from default region,
|
||||
// but it could be removed in bug 1423464 if it's not necessary.
|
||||
if (!metadata) {
|
||||
metadata = AddressDataLoader.getData("US");
|
||||
}
|
||||
return metadata;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get country address data with default locale.
|
||||
* @param {string} country
|
||||
* @param {string} level1
|
||||
* @returns {object|null} Return metadata of specific region with default locale.
|
||||
*/
|
||||
getCountryAddressData(country, level1) {
|
||||
let metadata = this.getCountryAddressRawData(country, level1);
|
||||
return metadata && metadata.defaultLocale;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get country address data with all locales.
|
||||
* @param {string} country
|
||||
* @param {string} level1
|
||||
* @returns {array<object>|null}
|
||||
* Return metadata of specific region with all the locales.
|
||||
*/
|
||||
getCountryAddressDataWithLocales(country, level1) {
|
||||
let metadata = this.getCountryAddressRawData(country, level1);
|
||||
return metadata && [metadata.defaultLocale, ...metadata.locales];
|
||||
},
|
||||
|
||||
/**
|
||||
@ -327,7 +407,7 @@ this.FormAutofillUtils = {
|
||||
|
||||
if (!this._collators[country]) {
|
||||
let dataset = this.getCountryAddressData(country);
|
||||
let languages = dataset.languages ? dataset.languages.split("~") : [dataset.lang];
|
||||
let languages = dataset.languages || [dataset.lang];
|
||||
this._collators[country] = languages.map(lang => new Intl.Collator(lang, {sensitivity: "base", ignorePunctuation: true}));
|
||||
}
|
||||
return this._collators[country];
|
||||
@ -438,33 +518,33 @@ this.FormAutofillUtils = {
|
||||
let values = Array.isArray(subregionValues) ? subregionValues : [subregionValues];
|
||||
|
||||
let collators = this.getCollators(country);
|
||||
let {sub_keys: subKeys, sub_names: subNames} = this.getCountryAddressData(country);
|
||||
for (let metadata of this.getCountryAddressDataWithLocales(country)) {
|
||||
let {sub_keys: subKeys, sub_names: subNames, sub_lnames: subLnames} = metadata;
|
||||
// Apply sub_lnames if sub_names does not exist
|
||||
subNames = subNames || subLnames;
|
||||
|
||||
if (!Array.isArray(subKeys)) {
|
||||
subKeys = subKeys.split("~");
|
||||
}
|
||||
if (!Array.isArray(subNames)) {
|
||||
subNames = subNames.split("~");
|
||||
}
|
||||
let speculatedSubIndexes = [];
|
||||
for (const val of values) {
|
||||
let identifiedValue = this.identifyValue(subKeys, subNames, val, collators);
|
||||
if (identifiedValue) {
|
||||
return identifiedValue;
|
||||
}
|
||||
|
||||
let speculatedSubIndexes = [];
|
||||
for (const val of values) {
|
||||
let identifiedValue = this.identifyValue(subKeys, subNames, val, collators);
|
||||
if (identifiedValue) {
|
||||
return identifiedValue;
|
||||
// Predict the possible state by partial-matching if no exact match.
|
||||
[subKeys, subNames].forEach(sub => {
|
||||
speculatedSubIndexes.push(sub.findIndex(token => {
|
||||
let pattern = new RegExp("\\b" + this.escapeRegExp(token) + "\\b");
|
||||
|
||||
return pattern.test(val);
|
||||
}));
|
||||
});
|
||||
}
|
||||
let subKey = subKeys[speculatedSubIndexes.find(i => !!~i)];
|
||||
if (subKey) {
|
||||
return subKey;
|
||||
}
|
||||
|
||||
// Predict the possible state by partial-matching if no exact match.
|
||||
[subKeys, subNames].forEach(sub => {
|
||||
speculatedSubIndexes.push(sub.findIndex(token => {
|
||||
let pattern = new RegExp("\\b" + this.escapeRegExp(token) + "\\b");
|
||||
|
||||
return pattern.test(val);
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
return subKeys[speculatedSubIndexes.find(i => !!~i)] || null;
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -484,7 +564,6 @@ this.FormAutofillUtils = {
|
||||
return null;
|
||||
}
|
||||
|
||||
let dataset = this.getCountryAddressData(address.country);
|
||||
let collators = this.getCollators(address.country);
|
||||
|
||||
for (let option of selectEl.options) {
|
||||
@ -496,29 +575,26 @@ this.FormAutofillUtils = {
|
||||
|
||||
switch (fieldName) {
|
||||
case "address-level1": {
|
||||
if (!Array.isArray(dataset.sub_keys)) {
|
||||
dataset.sub_keys = dataset.sub_keys.split("~");
|
||||
}
|
||||
if (!Array.isArray(dataset.sub_names)) {
|
||||
dataset.sub_names = dataset.sub_names.split("~");
|
||||
}
|
||||
let keys = dataset.sub_keys;
|
||||
let names = dataset.sub_names;
|
||||
let identifiedValue = this.identifyValue(keys, names, value, collators);
|
||||
|
||||
// No point going any further if we cannot identify value from address
|
||||
let {country} = address;
|
||||
let identifiedValue = this.getAbbreviatedSubregionName([value], country);
|
||||
// No point going any further if we cannot identify value from address level 1
|
||||
if (!identifiedValue) {
|
||||
return null;
|
||||
}
|
||||
for (let dataset of this.getCountryAddressDataWithLocales(country)) {
|
||||
let keys = dataset.sub_keys;
|
||||
// Apply sub_lnames if sub_names does not exist
|
||||
let names = dataset.sub_names || dataset.sub_lnames;
|
||||
|
||||
// Go through options one by one to find a match.
|
||||
// Also check if any option contain the address-level1 key.
|
||||
let pattern = new RegExp("\\b" + this.escapeRegExp(identifiedValue) + "\\b", "i");
|
||||
for (let option of selectEl.options) {
|
||||
let optionValue = this.identifyValue(keys, names, option.value, collators);
|
||||
let optionText = this.identifyValue(keys, names, option.text, collators);
|
||||
if (identifiedValue === optionValue || identifiedValue === optionText || pattern.test(option.value)) {
|
||||
return option;
|
||||
// Go through options one by one to find a match.
|
||||
// Also check if any option contain the address-level1 key.
|
||||
let pattern = new RegExp("\\b" + this.escapeRegExp(identifiedValue) + "\\b", "i");
|
||||
for (let option of selectEl.options) {
|
||||
let optionValue = this.identifyValue(keys, names, option.value, collators);
|
||||
let optionText = this.identifyValue(keys, names, option.text, collators);
|
||||
if (identifiedValue === optionValue || identifiedValue === optionText || pattern.test(option.value)) {
|
||||
return option;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -16,5 +16,6 @@ scheme=https
|
||||
scheme=https
|
||||
[test_form_changes.html]
|
||||
[test_formautofill_preview_highlight.html]
|
||||
[test_multi_locale_CA_address_form.html]
|
||||
[test_multiple_forms.html]
|
||||
[test_on_address_submission.html]
|
||||
|
@ -0,0 +1,201 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test basic autofill</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
|
||||
<script type="text/javascript" src="formautofill_common.js"></script>
|
||||
<script type="text/javascript" src="satchel_common.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
Form autofill test: simple form address autofill
|
||||
|
||||
<script>
|
||||
/* import-globals-from ../../../../../testing/mochitest/tests/SimpleTest/SpawnTask.js */
|
||||
/* import-globals-from ../../../../../toolkit/components/satchel/test/satchel_common.js */
|
||||
/* import-globals-from formautofill_common.js */
|
||||
|
||||
"use strict";
|
||||
|
||||
let MOCK_STORAGE = [{
|
||||
organization: "Mozilla Vancouver",
|
||||
"street-address": "163 W Hastings St.\n#209\n3-line",
|
||||
tel: "+17787851540",
|
||||
country: "CA",
|
||||
"address-level1": "BC",
|
||||
}, {
|
||||
organization: "Mozilla Toronto",
|
||||
"street-address": "366 Adelaide St.\nW Suite 500\n3-line",
|
||||
tel: "+14168483114",
|
||||
country: "CA",
|
||||
"address-level1": "ON",
|
||||
}, {
|
||||
organization: "Prince of Wales Northern Heritage",
|
||||
"street-address": "4750 48 St.\nYellowknife\n3-line",
|
||||
tel: "+18677679347",
|
||||
country: "CA",
|
||||
"address-level1": "Northwest Territories",
|
||||
}, {
|
||||
organization: "ExpoCité",
|
||||
"street-address": "250 Boulevard Wilfrid-Hamel\nVille de Québec\n3-line",
|
||||
tel: "+14186917110",
|
||||
country: "CA",
|
||||
"address-level1": "Québec",
|
||||
}];
|
||||
|
||||
function checkElementFilled(element, expectedvalue) {
|
||||
return [
|
||||
new Promise(resolve => {
|
||||
element.addEventListener("input", function onInput() {
|
||||
ok(true, "Checking " + element.name + " field fires input event");
|
||||
resolve();
|
||||
}, {once: true});
|
||||
}),
|
||||
new Promise(resolve => {
|
||||
element.addEventListener("change", function onChange() {
|
||||
ok(true, "Checking " + element.name + " field fires change event");
|
||||
is(element.value, expectedvalue, "Checking " + element.name + " field");
|
||||
resolve();
|
||||
}, {once: true});
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
function checkAutoCompleteInputFilled(element, expectedvalue) {
|
||||
return new Promise(resolve => {
|
||||
element.addEventListener("DOMAutoComplete", function onChange() {
|
||||
is(element.value, expectedvalue, "Checking " + element.name + " field");
|
||||
resolve();
|
||||
}, {once: true});
|
||||
});
|
||||
}
|
||||
|
||||
function checkFormFilled(selector, address) {
|
||||
info("expecting form filled");
|
||||
let promises = [];
|
||||
let form = document.querySelector(selector);
|
||||
for (let prop in address) {
|
||||
let element = form.querySelector(`[name=${prop}]`);
|
||||
if (document.activeElement == element) {
|
||||
promises.push(checkAutoCompleteInputFilled(element, address[prop]));
|
||||
} else {
|
||||
let converted = address[prop];
|
||||
if (prop == "street-address") {
|
||||
converted = FormAutofillUtils.toOneLineAddress(converted);
|
||||
}
|
||||
promises.push(...checkElementFilled(element, converted));
|
||||
}
|
||||
}
|
||||
doKey("return");
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
async function setupAddressStorage() {
|
||||
for (let address of MOCK_STORAGE) {
|
||||
await addAddress(address);
|
||||
}
|
||||
}
|
||||
|
||||
initPopupListener();
|
||||
|
||||
// Autofill the address with address level 1 code.
|
||||
add_task(async function autofill_with_level1_code() {
|
||||
await setupAddressStorage();
|
||||
|
||||
await setInput("#organization-en", "Mozilla Toronto");
|
||||
doKey("down");
|
||||
await expectPopup();
|
||||
|
||||
doKey("down");
|
||||
// Replace address level 1 code with full name in English for test result
|
||||
let result = Object.assign({}, MOCK_STORAGE[1], {"address-level1": "Ontario"});
|
||||
await checkFormFilled("#form-en", result);
|
||||
|
||||
await setInput("#organization-fr", "Mozilla Vancouver");
|
||||
doKey("down");
|
||||
await expectPopup();
|
||||
|
||||
doKey("down");
|
||||
// Replace address level 1 code with full name in French for test result
|
||||
result = Object.assign({}, MOCK_STORAGE[0], {"address-level1": "Colombie-Britannique"});
|
||||
await checkFormFilled("#form-fr", result);
|
||||
document.querySelector("#form-en").reset();
|
||||
document.querySelector("#form-fr").reset();
|
||||
});
|
||||
|
||||
// Autofill the address with address level 1 full name.
|
||||
add_task(async function autofill_with_level1_full_name() {
|
||||
await setInput("#organization-en", "ExpoCité");
|
||||
doKey("down");
|
||||
await expectPopup();
|
||||
|
||||
doKey("down");
|
||||
// Replace address level 1 code with full name in French for test result
|
||||
let result = Object.assign({}, MOCK_STORAGE[3], {"address-level1": "Quebec"});
|
||||
await checkFormFilled("#form-en", result);
|
||||
|
||||
await setInput("#organization-fr", "Prince of Wales Northern Heritage");
|
||||
doKey("down");
|
||||
await expectPopup();
|
||||
|
||||
doKey("down");
|
||||
// Replace address level 1 code with full name in English for test result
|
||||
result = Object.assign({}, MOCK_STORAGE[2], {"address-level1": "Territoires du Nord-Ouest"});
|
||||
await checkFormFilled("#form-fr", result);
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="content">
|
||||
|
||||
<form id="form-en">
|
||||
<p>This is a basic CA form with en address level 1 select.</p>
|
||||
<p><label>organization: <input id="organization-en" name="organization" autocomplete="organization" type="text"></label></p>
|
||||
<p><label>streetAddress: <input id="street-address-en" name="street-address" autocomplete="street-address" type="text"></label></p>
|
||||
<p><label>address-line1: <input id="address-line1-en" name="address-line1" autocomplete="address-line1" type="text"></label></p>
|
||||
<p><label>tel: <input id="tel-en" name="tel" autocomplete="tel" type="text"></label></p>
|
||||
<p><label>email: <input id="email-en" name="email" autocomplete="email" type="text"></label></p>
|
||||
<p><label>country: <select id="country-en" name="country" autocomplete="country">
|
||||
<option/>
|
||||
<option value="US">United States</option>
|
||||
<option value="CA">Canada</option>
|
||||
</select></label></p>
|
||||
<p><label>states: <select id="address-level1-en" name="address-level1" autocomplete="address-level1">
|
||||
<option/>
|
||||
<option value="British Columbia">British Columbia</option>
|
||||
<option value="Ontario">Ontario</option>
|
||||
<option value="Northwest Territories">Northwest Territories</option>
|
||||
<option value="Quebec">Quebec</option>
|
||||
</select></label></p>
|
||||
</form>
|
||||
|
||||
<form id="form-fr">
|
||||
<p>This is a basic CA form with fr address level 1 select.</p>
|
||||
<p><label>organization: <input id="organization-fr" name="organization" autocomplete="organization" type="text"></label></p>
|
||||
<p><label>streetAddress: <input id="street-address-fr" name="street-address" autocomplete="street-address" type="text"></label></p>
|
||||
<p><label>address-line1: <input id="address-line1-fr" name="address-line1" autocomplete="address-line1" type="text"></label></p>
|
||||
<p><label>tel: <input id="tel-fr" name="tel" autocomplete="tel" type="text"></label></p>
|
||||
<p><label>email: <input id="email-fr" name="email" autocomplete="email" type="text"></label></p>
|
||||
<p><label>country: <select id="country-fr" name="country" autocomplete="country">
|
||||
<option/>
|
||||
<option value="US">United States</option>
|
||||
<option value="CA">Canada</option>
|
||||
</select></label></p>
|
||||
<p><label>states: <select id="address-level1-fr" name="address-level1" autocomplete="address-level1">
|
||||
<option/>
|
||||
<option value="Colombie-Britannique">Colombie-Britannique</option>
|
||||
<option value="Ontario">Ontario</option>
|
||||
<option value="Territoires du Nord-Ouest">Territoires du Nord-Ouest</option>
|
||||
<option value="Québec">Québec</option>
|
||||
</select></label></p>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
<pre id="test"></pre>
|
||||
</body>
|
||||
</html>
|
@ -69,5 +69,13 @@ SUPPORT_COUNTRIES_TESTCASES.forEach(testcase => {
|
||||
let metadata = FormAutofillUtils.getCountryAddressData(testcase.country);
|
||||
Assert.ok(testcase.properties.every(key => metadata[key]),
|
||||
"These properties should exist: " + testcase.properties);
|
||||
// Verify the multi-locale country
|
||||
if (metadata.languages && metadata.languages.length > 1) {
|
||||
let locales = FormAutofillUtils.getCountryAddressDataWithLocales(testcase.country);
|
||||
Assert.equal(metadata.languages.length, locales.length, "Total supported locales should be matched");
|
||||
metadata.languages.forEach((lang, index) => {
|
||||
Assert.equal(lang, locales[index].lang, `Should support ${lang}`);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -110,19 +110,19 @@ include $(topsrcdir)/toolkit/mozapps/installer/packager.mk
|
||||
|
||||
ifeq (bundle, $(MOZ_FS_LAYOUT))
|
||||
BINPATH = $(_BINPATH)
|
||||
DEFINES += -DAPPNAME=$(_APPNAME)
|
||||
DEFINES += -DAPPNAME='$(_APPNAME)'
|
||||
else
|
||||
# Every other platform just winds up in dist/bin
|
||||
BINPATH = bin
|
||||
endif
|
||||
DEFINES += -DBINPATH=$(BINPATH)
|
||||
DEFINES += -DBINPATH='$(BINPATH)'
|
||||
|
||||
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
|
||||
RESPATH = $(_APPNAME)/Contents/Resources
|
||||
else
|
||||
RESPATH = $(BINPATH)
|
||||
endif
|
||||
DEFINES += -DRESPATH=$(RESPATH)
|
||||
DEFINES += -DRESPATH="$(RESPATH)"
|
||||
|
||||
LPROJ_ROOT = $(firstword $(subst -, ,$(AB_CD)))
|
||||
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
|
||||
|
@ -155,10 +155,10 @@ endif
|
||||
ident:
|
||||
@printf 'fx_revision '
|
||||
@$(PYTHON) $(topsrcdir)/config/printconfigsetting.py \
|
||||
$(STAGEDIST)/application.ini App SourceStamp
|
||||
'$(STAGEDIST)'/application.ini App SourceStamp
|
||||
@printf 'buildid '
|
||||
@$(PYTHON) $(topsrcdir)/config/printconfigsetting.py \
|
||||
$(STAGEDIST)/application.ini App BuildID
|
||||
'$(STAGEDIST)'/application.ini App BuildID
|
||||
|
||||
# test target, depends on make package
|
||||
# try to repack x-test, with just toolkit/defines.inc being there
|
||||
|
@ -717,7 +717,7 @@ html|span.ac-emphasize-text-url {
|
||||
:root[tabsintitlebar] > #titlebar:-moz-lwtheme {
|
||||
visibility: hidden;
|
||||
}
|
||||
:root[tabsintitlebar] > #titlebar-content:-moz-lwtheme {
|
||||
:root[tabsintitlebar] #titlebar-content:-moz-lwtheme {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
|
@ -13,35 +13,43 @@
|
||||
* See devtools/client/framework/toolbox.js:setIframeVisible().
|
||||
*/
|
||||
|
||||
const {
|
||||
createClass,
|
||||
} = require("devtools/client/shared/vendor/react");
|
||||
const { Component } = require("devtools/client/shared/vendor/react");
|
||||
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
|
||||
|
||||
const VisibilityHandler = createClass({
|
||||
class VisibilityHandler extends Component {
|
||||
static get propTypes() {
|
||||
return {
|
||||
children: PropTypes.element.isRequired
|
||||
};
|
||||
}
|
||||
|
||||
displayName: "VisiblityHandler",
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.onVisibilityChange = this.onVisibilityChange.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
window.addEventListener("visibilitychange", this.onVisibilityChange);
|
||||
}
|
||||
|
||||
shouldComponentUpdate() {
|
||||
return document.visibilityState == "visible";
|
||||
},
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener("visibilitychange", this.onVisibilityChange);
|
||||
}
|
||||
|
||||
onVisibilityChange() {
|
||||
if (document.visibilityState == "visible") {
|
||||
this.forceUpdate();
|
||||
}
|
||||
},
|
||||
|
||||
componentDidMount() {
|
||||
window.addEventListener("visibilitychange", this.onVisibilityChange);
|
||||
},
|
||||
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener("visibilitychange", this.onVisibilityChange);
|
||||
},
|
||||
}
|
||||
|
||||
render() {
|
||||
return this.props.children;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = VisibilityHandler;
|
||||
|
@ -259,8 +259,6 @@ skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32
|
||||
subsuite = clipboard
|
||||
[browser_webconsole_context_menu_open_url.js]
|
||||
[browser_webconsole_context_menu_store_as_global.js]
|
||||
[browser_webconsole_copy_link_location.js]
|
||||
skip-if = true # Bug 1401944
|
||||
[browser_webconsole_csp_ignore_reflected_xss_message.js]
|
||||
skip-if = (e10s && debug) || (e10s && os == 'win') # Bug 1221499 enabled these on windows
|
||||
[browser_webconsole_cspro.js]
|
||||
|
@ -22,14 +22,15 @@ add_task(async function() {
|
||||
info("Test Copy URL menu item for text log");
|
||||
|
||||
info("Logging a text message in the content window");
|
||||
let onLogMessage = waitForMessage(hud, "simple text message");
|
||||
await ContentTask.spawn(gBrowser.selectedBrowser, null, () => {
|
||||
content.wrappedJSObject.console.log("simple text message");
|
||||
});
|
||||
let message = await waitFor(() => findMessage(hud, "simple text message"));
|
||||
let message = await onLogMessage;
|
||||
ok(message, "Text log found in the console");
|
||||
|
||||
info("Open and check the context menu for the logged text message");
|
||||
let menuPopup = await openContextMenu(hud, message);
|
||||
let menuPopup = await openContextMenu(hud, message.node);
|
||||
let copyURLItem = menuPopup.querySelector(CONTEXT_MENU_ID);
|
||||
ok(!copyURLItem, "Copy URL menu item is hidden for a simple text message");
|
||||
|
||||
@ -39,15 +40,16 @@ add_task(async function() {
|
||||
info("Test Copy URL menu item for network log");
|
||||
|
||||
info("Reload the content window to produce a network log");
|
||||
let onNetworkMessage = waitForMessage(hud, "test-console.html");
|
||||
await ContentTask.spawn(gBrowser.selectedBrowser, null, () => {
|
||||
content.wrappedJSObject.location.reload();
|
||||
});
|
||||
|
||||
message = await waitFor(() => findMessage(hud, "test-console.html"));
|
||||
message = await onNetworkMessage;
|
||||
ok(message, "Network log found in the console");
|
||||
|
||||
info("Open and check the context menu for the logged network message");
|
||||
menuPopup = await openContextMenu(hud, message);
|
||||
menuPopup = await openContextMenu(hud, message.node);
|
||||
copyURLItem = menuPopup.querySelector(CONTEXT_MENU_ID);
|
||||
ok(copyURLItem, "Copy url menu item is available in context menu");
|
||||
|
||||
|
@ -1,107 +0,0 @@
|
||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Test for the "Copy link location" context menu item shown when you right
|
||||
// click network requests in the output. See Bug 638949.
|
||||
|
||||
"use strict";
|
||||
|
||||
add_task(function* () {
|
||||
const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
|
||||
"test/test-console.html?_date=" + Date.now();
|
||||
const COMMAND_NAME = "consoleCmd_copyURL";
|
||||
const CONTEXT_MENU_ID = "#menu_copyURL";
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
Services.prefs.clearUserPref("devtools.webconsole.filter.networkinfo");
|
||||
});
|
||||
|
||||
Services.prefs.setBoolPref("devtools.webconsole.filter.networkinfo", true);
|
||||
|
||||
yield loadTab(TEST_URI);
|
||||
let hud = yield openConsole();
|
||||
let output = hud.outputNode;
|
||||
let menu = hud.iframeWindow.document.getElementById("output-contextmenu");
|
||||
|
||||
hud.jsterm.clearOutput();
|
||||
content.console.log("bug 638949");
|
||||
|
||||
// Test that the "Copy Link Location" command is disabled for non-network
|
||||
// messages.
|
||||
let [result] = yield waitForMessages({
|
||||
webconsole: hud,
|
||||
messages: [{
|
||||
text: "bug 638949",
|
||||
category: CATEGORY_WEBDEV,
|
||||
severity: SEVERITY_LOG,
|
||||
}],
|
||||
});
|
||||
|
||||
output.focus();
|
||||
let message = [...result.matched][0];
|
||||
|
||||
goUpdateCommand(COMMAND_NAME);
|
||||
ok(!isEnabled(), COMMAND_NAME + " is disabled");
|
||||
|
||||
// Test that the "Copy Link Location" menu item is hidden for non-network
|
||||
// messages.
|
||||
yield waitForContextMenu(menu, message, () => {
|
||||
let isHidden = menu.querySelector(CONTEXT_MENU_ID).hidden;
|
||||
ok(isHidden, CONTEXT_MENU_ID + " is hidden");
|
||||
});
|
||||
|
||||
hud.jsterm.clearOutput();
|
||||
// Reloading will produce network logging
|
||||
content.location.reload();
|
||||
|
||||
// Test that the "Copy Link Location" command is enabled and works
|
||||
// as expected for any network-related message.
|
||||
// This command should copy only the URL.
|
||||
[result] = yield waitForMessages({
|
||||
webconsole: hud,
|
||||
messages: [{
|
||||
text: "test-console.html",
|
||||
category: CATEGORY_NETWORK,
|
||||
severity: SEVERITY_LOG,
|
||||
}],
|
||||
});
|
||||
|
||||
output.focus();
|
||||
message = [...result.matched][0];
|
||||
hud.ui.output.selectMessage(message);
|
||||
|
||||
goUpdateCommand(COMMAND_NAME);
|
||||
ok(isEnabled(), COMMAND_NAME + " is enabled");
|
||||
|
||||
info("expected clipboard value: " + message.url);
|
||||
|
||||
let deferred = defer();
|
||||
|
||||
waitForClipboard((aData) => {
|
||||
return aData.trim() == message.url;
|
||||
}, () => {
|
||||
goDoCommand(COMMAND_NAME);
|
||||
}, () => {
|
||||
deferred.resolve(null);
|
||||
}, () => {
|
||||
deferred.reject(null);
|
||||
});
|
||||
|
||||
yield deferred.promise;
|
||||
|
||||
// Test that the "Copy Link Location" menu item is visible for network-related
|
||||
// messages.
|
||||
yield waitForContextMenu(menu, message, () => {
|
||||
let isVisible = !menu.querySelector(CONTEXT_MENU_ID).hidden;
|
||||
ok(isVisible, CONTEXT_MENU_ID + " is visible");
|
||||
});
|
||||
|
||||
// Return whether "Copy Link Location" command is enabled or not.
|
||||
function isEnabled() {
|
||||
let controller = top.document.commandDispatcher
|
||||
.getControllerForCommand(COMMAND_NAME);
|
||||
return controller && controller.isCommandEnabled(COMMAND_NAME);
|
||||
}
|
||||
});
|
@ -2467,7 +2467,6 @@ BuildTextRunsScanner::SetupLineBreakerContext(gfxTextRun *aTextRun)
|
||||
|
||||
gfxSkipChars skipChars;
|
||||
|
||||
AutoTArray<int32_t,50> textBreakPoints;
|
||||
TextRunUserData dummyData;
|
||||
TextRunMappedFlow dummyMappedFlow;
|
||||
TextRunMappedFlow* userMappedFlows;
|
||||
@ -2488,9 +2487,6 @@ BuildTextRunsScanner::SetupLineBreakerContext(gfxTextRun *aTextRun)
|
||||
userDataToDestroy = userData;
|
||||
}
|
||||
|
||||
uint32_t nextBreakIndex = 0;
|
||||
nsTextFrame* nextBreakBeforeFrame = GetNextBreakBeforeFrame(&nextBreakIndex);
|
||||
|
||||
const nsStyleText* textStyle = nullptr;
|
||||
for (uint32_t i = 0; i < mMappedFlows.Length(); ++i) {
|
||||
MappedFlow* mappedFlow = &mMappedFlows[i];
|
||||
@ -2513,12 +2509,6 @@ BuildTextRunsScanner::SetupLineBreakerContext(gfxTextRun *aTextRun)
|
||||
mappedFlow->mStartFrame->GetContentOffset();
|
||||
newFlow->mContentLength = contentLength;
|
||||
|
||||
while (nextBreakBeforeFrame && nextBreakBeforeFrame->GetContent() == content) {
|
||||
textBreakPoints.AppendElement(
|
||||
nextBreakBeforeFrame->GetContentOffset() + newFlow->mDOMOffsetToBeforeTransformOffset);
|
||||
nextBreakBeforeFrame = GetNextBreakBeforeFrame(&nextBreakIndex);
|
||||
}
|
||||
|
||||
nsTextFrameUtils::Flags analysisFlags;
|
||||
if (frag->Is2b()) {
|
||||
NS_ASSERTION(mDoubleByteText, "Wrong buffer char size!");
|
||||
|
@ -59,22 +59,16 @@ MOZ_MEMORY_API char *strndup_impl(const char *, size_t);
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include "mozilla/mozalloc.h"
|
||||
#include "mozilla/mozalloc_oom.h" // for mozalloc_handle_oom
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define LIKELY(x) (__builtin_expect(!!(x), 1))
|
||||
#define UNLIKELY(x) (__builtin_expect(!!(x), 0))
|
||||
#else
|
||||
#define LIKELY(x) (x)
|
||||
#define UNLIKELY(x) (x)
|
||||
#endif
|
||||
|
||||
void*
|
||||
moz_xmalloc(size_t size)
|
||||
{
|
||||
void* ptr = malloc_impl(size);
|
||||
if (UNLIKELY(!ptr && size)) {
|
||||
if (MOZ_UNLIKELY(!ptr && size)) {
|
||||
mozalloc_handle_oom(size);
|
||||
return moz_xmalloc(size);
|
||||
}
|
||||
@ -85,8 +79,9 @@ void*
|
||||
moz_xcalloc(size_t nmemb, size_t size)
|
||||
{
|
||||
void* ptr = calloc_impl(nmemb, size);
|
||||
if (UNLIKELY(!ptr && nmemb && size)) {
|
||||
mozalloc_handle_oom(size);
|
||||
if (MOZ_UNLIKELY(!ptr && nmemb && size)) {
|
||||
mozilla::CheckedInt<size_t> totalSize = mozilla::CheckedInt<size_t>(nmemb) * size;
|
||||
mozalloc_handle_oom(totalSize.isValid() ? totalSize.value() : SIZE_MAX);
|
||||
return moz_xcalloc(nmemb, size);
|
||||
}
|
||||
return ptr;
|
||||
@ -96,7 +91,7 @@ void*
|
||||
moz_xrealloc(void* ptr, size_t size)
|
||||
{
|
||||
void* newptr = realloc_impl(ptr, size);
|
||||
if (UNLIKELY(!newptr && size)) {
|
||||
if (MOZ_UNLIKELY(!newptr && size)) {
|
||||
mozalloc_handle_oom(size);
|
||||
return moz_xrealloc(ptr, size);
|
||||
}
|
||||
@ -107,7 +102,7 @@ char*
|
||||
moz_xstrdup(const char* str)
|
||||
{
|
||||
char* dup = strdup_impl(str);
|
||||
if (UNLIKELY(!dup)) {
|
||||
if (MOZ_UNLIKELY(!dup)) {
|
||||
mozalloc_handle_oom(0);
|
||||
return moz_xstrdup(str);
|
||||
}
|
||||
@ -119,7 +114,7 @@ char*
|
||||
moz_xstrndup(const char* str, size_t strsize)
|
||||
{
|
||||
char* dup = strndup_impl(str, strsize);
|
||||
if (UNLIKELY(!dup)) {
|
||||
if (MOZ_UNLIKELY(!dup)) {
|
||||
mozalloc_handle_oom(strsize);
|
||||
return moz_xstrndup(str, strsize);
|
||||
}
|
||||
@ -137,7 +132,7 @@ void*
|
||||
moz_xmemalign(size_t boundary, size_t size)
|
||||
{
|
||||
void* ptr = memalign_impl(boundary, size);
|
||||
if (UNLIKELY(!ptr && EINVAL != errno)) {
|
||||
if (MOZ_UNLIKELY(!ptr && EINVAL != errno)) {
|
||||
mozalloc_handle_oom(size);
|
||||
return moz_xmemalign(boundary, size);
|
||||
}
|
||||
|
@ -33,14 +33,6 @@
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Types.h"
|
||||
|
||||
#if defined(MOZ_ALWAYS_INLINE_EVEN_DEBUG)
|
||||
# define MOZALLOC_INLINE MOZ_ALWAYS_INLINE_EVEN_DEBUG
|
||||
#elif defined(HAVE_FORCEINLINE)
|
||||
# define MOZALLOC_INLINE __forceinline
|
||||
#else
|
||||
# define MOZALLOC_INLINE inline
|
||||
#endif
|
||||
|
||||
MOZ_BEGIN_EXTERN_C
|
||||
|
||||
/*
|
||||
@ -133,16 +125,7 @@ MOZ_END_EXTERN_C
|
||||
# define MOZALLOC_EXPORT_NEW
|
||||
#endif
|
||||
|
||||
#if defined(ANDROID)
|
||||
/*
|
||||
* It's important to always specify 'throw()' in GCC because it's used to tell
|
||||
* GCC that 'new' may return null. That makes GCC null-check the result before
|
||||
* potentially initializing the memory to zero.
|
||||
* Also, the Android minimalistic headers don't include std::bad_alloc.
|
||||
*/
|
||||
#define MOZALLOC_THROW_IF_HAS_EXCEPTIONS throw()
|
||||
#define MOZALLOC_THROW_BAD_ALLOC_IF_HAS_EXCEPTIONS
|
||||
#elif defined(_MSC_VER)
|
||||
#if defined(_MSC_VER)
|
||||
/*
|
||||
* Suppress build warning spam (bug 578546).
|
||||
*/
|
||||
@ -166,50 +149,50 @@ MOZALLOC_EXPORT_NEW
|
||||
/* gcc's asan somehow doesn't like always_inline on this function. */
|
||||
__attribute__((gnu_inline)) inline
|
||||
#else
|
||||
MOZALLOC_INLINE
|
||||
MOZ_ALWAYS_INLINE_EVEN_DEBUG
|
||||
#endif
|
||||
void* operator new(size_t size) MOZALLOC_THROW_BAD_ALLOC
|
||||
{
|
||||
return moz_xmalloc(size);
|
||||
}
|
||||
|
||||
MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
|
||||
MOZALLOC_EXPORT_NEW MOZ_ALWAYS_INLINE_EVEN_DEBUG
|
||||
void* operator new(size_t size, const std::nothrow_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
|
||||
{
|
||||
return malloc_impl(size);
|
||||
}
|
||||
|
||||
MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
|
||||
MOZALLOC_EXPORT_NEW MOZ_ALWAYS_INLINE_EVEN_DEBUG
|
||||
void* operator new[](size_t size) MOZALLOC_THROW_BAD_ALLOC
|
||||
{
|
||||
return moz_xmalloc(size);
|
||||
}
|
||||
|
||||
MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
|
||||
MOZALLOC_EXPORT_NEW MOZ_ALWAYS_INLINE_EVEN_DEBUG
|
||||
void* operator new[](size_t size, const std::nothrow_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
|
||||
{
|
||||
return malloc_impl(size);
|
||||
}
|
||||
|
||||
MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
|
||||
MOZALLOC_EXPORT_NEW MOZ_ALWAYS_INLINE_EVEN_DEBUG
|
||||
void operator delete(void* ptr) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
|
||||
{
|
||||
return free_impl(ptr);
|
||||
}
|
||||
|
||||
MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
|
||||
MOZALLOC_EXPORT_NEW MOZ_ALWAYS_INLINE_EVEN_DEBUG
|
||||
void operator delete(void* ptr, const std::nothrow_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
|
||||
{
|
||||
return free_impl(ptr);
|
||||
}
|
||||
|
||||
MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
|
||||
MOZALLOC_EXPORT_NEW MOZ_ALWAYS_INLINE_EVEN_DEBUG
|
||||
void operator delete[](void* ptr) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
|
||||
{
|
||||
return free_impl(ptr);
|
||||
}
|
||||
|
||||
MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
|
||||
MOZALLOC_EXPORT_NEW MOZ_ALWAYS_INLINE_EVEN_DEBUG
|
||||
void operator delete[](void* ptr, const std::nothrow_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
|
||||
{
|
||||
return free_impl(ptr);
|
||||
@ -235,25 +218,25 @@ void operator delete[](void* ptr, const std::nothrow_t&) MOZALLOC_THROW_IF_HAS_E
|
||||
* (4) the matching system |operator delete(void*) throw(std::bad_alloc)|
|
||||
*/
|
||||
|
||||
MOZALLOC_INLINE
|
||||
MOZ_ALWAYS_INLINE_EVEN_DEBUG
|
||||
void* operator new(size_t size, const mozilla::fallible_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
|
||||
{
|
||||
return malloc_impl(size);
|
||||
}
|
||||
|
||||
MOZALLOC_INLINE
|
||||
MOZ_ALWAYS_INLINE_EVEN_DEBUG
|
||||
void* operator new[](size_t size, const mozilla::fallible_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
|
||||
{
|
||||
return malloc_impl(size);
|
||||
}
|
||||
|
||||
MOZALLOC_INLINE
|
||||
MOZ_ALWAYS_INLINE_EVEN_DEBUG
|
||||
void operator delete(void* ptr, const mozilla::fallible_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
|
||||
{
|
||||
free_impl(ptr);
|
||||
}
|
||||
|
||||
MOZALLOC_INLINE
|
||||
MOZ_ALWAYS_INLINE_EVEN_DEBUG
|
||||
void operator delete[](void* ptr, const mozilla::fallible_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
|
||||
{
|
||||
free_impl(ptr);
|
||||
|
@ -50,6 +50,7 @@ public final class HardwareCodecCapabilityUtils {
|
||||
"SGH-I337", // S4
|
||||
"SPH-L720", // S4 (Sprint)
|
||||
"SAMSUNG-SGH-I337", // S4
|
||||
"GT-I9195", // S4 Mini
|
||||
"300E5EV/300E4EV/270E5EV/270E4EV/2470EV/2470EE",
|
||||
"LG-D605" // LG Optimus L9 II
|
||||
};
|
||||
|
@ -4537,13 +4537,13 @@ MOZ_ARG_WITH_STRING(macbundlename-prefix,
|
||||
Prefix for MOZ_MACBUNDLE_NAME],
|
||||
[ MOZ_MACBUNDLE_NAME_PREFIX="$withval"])
|
||||
|
||||
MOZ_MACBUNDLE_NAME=`echo $MOZ_APP_DISPLAYNAME | tr -d ' '`
|
||||
MOZ_MACBUNDLE_NAME=$MOZ_APP_DISPLAYNAME
|
||||
if test "$MOZ_MACBUNDLE_NAME_PREFIX"; then
|
||||
MOZ_MACBUNDLE_NAME="${MOZ_MACBUNDLE_NAME_PREFIX}${MOZ_MACBUNDLE_NAME}"
|
||||
MOZ_MACBUNDLE_NAME="${MOZ_MACBUNDLE_NAME_PREFIX} ${MOZ_MACBUNDLE_NAME}"
|
||||
fi
|
||||
|
||||
if test "$MOZ_DEBUG"; then
|
||||
MOZ_MACBUNDLE_NAME=${MOZ_MACBUNDLE_NAME}Debug.app
|
||||
MOZ_MACBUNDLE_NAME="${MOZ_MACBUNDLE_NAME} Debug.app"
|
||||
else
|
||||
MOZ_MACBUNDLE_NAME=${MOZ_MACBUNDLE_NAME}.app
|
||||
fi
|
||||
|
@ -7,40 +7,60 @@ CertPassPrompt=Please enter the master password for the %S.
|
||||
|
||||
CertPassPromptDefault=Please enter your master password.
|
||||
|
||||
# the following strings have special requirements:
|
||||
# they must fit in a 32 or 64 byte buffer after being translated
|
||||
# to UTF8. Note to translator. It's not easy for you to figure
|
||||
# whether the escaped unicode string you produce will fit in
|
||||
# the space allocated.
|
||||
# The following strings have special requirements: they must fit in a 32 or 64
|
||||
# bytes buffer after being encoded to UTF-8.
|
||||
#
|
||||
# 64 bytes long after conversion to UTF8
|
||||
# It's possible to verify the length of a translation using the Browser Console
|
||||
# in Firefox and evaluating the following code:
|
||||
#
|
||||
# (new TextEncoder('utf-8').encode('YOURSTRING')).length
|
||||
#
|
||||
# Simply replace YOURSTRING with your translation.
|
||||
#
|
||||
# If it's not possible to produce an understandable translation withing these
|
||||
# limits, keeping the English text is an acceptable workaround.
|
||||
|
||||
# LOCALIZATION NOTE (RootCertModuleName): string limit is 64 bytes after
|
||||
# conversion to UTF-8.
|
||||
# length_limit = 64 bytes
|
||||
RootCertModuleName=Builtin Roots Module
|
||||
#
|
||||
# 32 bytes long after conversion to UTF8
|
||||
# LOCALIZATION NOTE (ManufacturerID): string limit is 32 bytes after conversion
|
||||
# to UTF-8.
|
||||
# length_limit = 32 bytes
|
||||
ManufacturerID=Mozilla.org
|
||||
#
|
||||
# 32 bytes long after conversion to UTF8
|
||||
# LOCALIZATION NOTE (LibraryDescription): string limit is 32 bytes after
|
||||
# conversion to UTF-8.
|
||||
# length_limit = 32 bytes
|
||||
LibraryDescription=PSM Internal Crypto Services
|
||||
#
|
||||
# 32 bytes long after conversion to UTF8
|
||||
# LOCALIZATION NOTE (TokenDescription): string limit is 32 bytes after
|
||||
# conversion to UTF-8.
|
||||
# length_limit = 32 bytes
|
||||
TokenDescription=Generic Crypto Services
|
||||
#
|
||||
# 32 bytes long after conversion to UTF8
|
||||
# LOCALIZATION NOTE (PrivateTokenDescription): string limit is 32 bytes after
|
||||
# conversion to UTF-8.
|
||||
# length_limit = 32 bytes
|
||||
PrivateTokenDescription=Software Security Device
|
||||
#
|
||||
# 64 bytes long after conversion to UTF8
|
||||
# LOCALIZATION NOTE (SlotDescription): string limit is 64 bytes after conversion
|
||||
# to UTF-8.
|
||||
# length_limit = 64 bytes
|
||||
SlotDescription=PSM Internal Cryptographic Services
|
||||
#
|
||||
# 64 bytes long after conversion to UTF8
|
||||
# LOCALIZATION NOTE (PrivateSlotDescription): string limit is 64 bytes after
|
||||
# conversion to UTF-8.
|
||||
# length_limit = 64 bytes
|
||||
PrivateSlotDescription=PSM Private Keys
|
||||
#
|
||||
# 32
|
||||
# LOCALIZATION NOTE (Fips140TokenDescription): string limit is 32 bytes after
|
||||
# conversion to UTF-8.
|
||||
# length_limit = 32 bytes
|
||||
Fips140TokenDescription=Software Security Device (FIPS)
|
||||
# 64
|
||||
# LOCALIZATION NOTE (Fips140SlotDescription): string limit is 64 bytes after
|
||||
# conversion to UTF-8.
|
||||
# length_limit = 64 bytes
|
||||
Fips140SlotDescription=FIPS 140 Cryptographic, Key and Certificate Services
|
||||
# 32
|
||||
# LOCALIZATION NOTE (InternalToken): string limit is 32 bytes after conversion
|
||||
# to UTF-8.
|
||||
# length_limit = 32 bytes
|
||||
InternalToken=Software Security Device
|
||||
# End of size restriction.
|
||||
|
||||
VerifySSLClient=SSL Client Certificate
|
||||
VerifySSLServer=SSL Server Certificate
|
||||
VerifySSLCA=SSL Certificate Authority
|
||||
|
@ -29,12 +29,14 @@ trait Recover<Q: ?Sized> {
|
||||
#[derive(Debug)]
|
||||
pub struct FailedAllocationError {
|
||||
reason: &'static str,
|
||||
/// The size we are allocating, if needed.
|
||||
allocation_size: Option<usize>,
|
||||
}
|
||||
|
||||
impl FailedAllocationError {
|
||||
#[inline]
|
||||
pub fn new(reason: &'static str) -> Self {
|
||||
Self { reason }
|
||||
Self { reason, allocation_size: None }
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,6 +48,9 @@ impl error::Error for FailedAllocationError {
|
||||
|
||||
impl fmt::Display for FailedAllocationError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.reason.fmt(f)
|
||||
match self.allocation_size {
|
||||
Some(size) => write!(f, "{}, allocation size: {}", self.reason, size),
|
||||
None => self.reason.fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -757,7 +757,7 @@ impl<K, V> RawTable<K, V> {
|
||||
align_of::<(K, V)>());
|
||||
|
||||
if oflo {
|
||||
return Err(FailedAllocationError { reason: "capacity overflow when allocating RawTable" });
|
||||
return Err(FailedAllocationError::new("capacity overflow when allocating RawTable" ));
|
||||
}
|
||||
|
||||
// One check for overflow that covers calculation and rounding of size.
|
||||
@ -767,21 +767,21 @@ impl<K, V> RawTable<K, V> {
|
||||
|
||||
if let Some(cap_bytes) = cap_bytes {
|
||||
if size < cap_bytes {
|
||||
return Err(FailedAllocationError { reason: "capacity overflow when allocating RawTable" });
|
||||
return Err(FailedAllocationError::new("capacity overflow when allocating RawTable"));
|
||||
}
|
||||
} else {
|
||||
|
||||
return Err(FailedAllocationError { reason: "capacity overflow when allocating RawTable" });
|
||||
return Err(FailedAllocationError::new("capacity overflow when allocating RawTable"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
// FORK NOTE: Uses alloc shim instead of Heap.alloc
|
||||
let buffer = alloc(size, alignment);
|
||||
|
||||
|
||||
if buffer.is_null() {
|
||||
|
||||
return Err(FailedAllocationError { reason: "out of memory when allocating RawTable" });
|
||||
return Err(FailedAllocationError {
|
||||
reason: "out of memory when allocating RawTable",
|
||||
allocation_size: Some(size),
|
||||
});
|
||||
}
|
||||
|
||||
let hashes = buffer.offset(hash_offset as isize) as *mut HashUint;
|
||||
|
@ -150,11 +150,6 @@ this.GeckoDriver = function(appId, server) {
|
||||
this.sandboxes = new Sandboxes(() => this.getCurrentWindow());
|
||||
this.legacyactions = new legacyaction.Chain();
|
||||
|
||||
this.timer = null;
|
||||
this.inactivityTimer = null;
|
||||
|
||||
this.testName = null;
|
||||
|
||||
this.capabilities = new session.Capabilities();
|
||||
|
||||
this.mm = globalMessageManager;
|
||||
@ -298,24 +293,6 @@ GeckoDriver.prototype.globalModalDialogHandler = function(subject, topic) {
|
||||
this.dialog = new modal.Dialog(() => this.curBrowser, winr);
|
||||
};
|
||||
|
||||
/**
|
||||
* Switches to the global ChromeMessageBroadcaster, potentially replacing
|
||||
* a frame-specific ChromeMessageSender. Has no effect if the global
|
||||
* ChromeMessageBroadcaster is already in use. If this replaces a
|
||||
* frame-specific ChromeMessageSender, it removes the message listeners
|
||||
* from that sender, and then puts the corresponding frame script "to
|
||||
* sleep", which removes most of the message listeners from it as well.
|
||||
*/
|
||||
GeckoDriver.prototype.switchToGlobalMessageManager = function() {
|
||||
if (this.curBrowser &&
|
||||
this.curBrowser.frameManager.currentRemoteFrame !== null) {
|
||||
this.curBrowser.frameManager.removeMessageManagerListeners(this.mm);
|
||||
this.sendAsync("sleepSession");
|
||||
this.curBrowser.frameManager.currentRemoteFrame = null;
|
||||
}
|
||||
this.mm = globalMessageManager;
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper method to send async messages to the content listener.
|
||||
* Correct usage is to pass in the name of a function in listener.js,
|
||||
@ -433,7 +410,6 @@ GeckoDriver.prototype.addFrameCloseListener = function(action) {
|
||||
this.mozBrowserClose = e => {
|
||||
if (e.target.id == this.oopFrameId) {
|
||||
win.removeEventListener("mozbrowserclose", this.mozBrowserClose, true);
|
||||
this.switchToGlobalMessageManager();
|
||||
throw new NoSuchWindowError("The window closed during action: " + action);
|
||||
}
|
||||
};
|
||||
@ -815,11 +791,9 @@ GeckoDriver.prototype.newSession = async function(cmd) {
|
||||
let win = this.getCurrentWindow();
|
||||
this.addBrowser(win);
|
||||
this.whenBrowserStarted(win, false);
|
||||
this.mm.broadcastAsyncMessage("Marionette:restart", {});
|
||||
} else {
|
||||
throw new WebDriverError("Session already running");
|
||||
}
|
||||
this.switchToGlobalMessageManager();
|
||||
|
||||
await registerBrowsers;
|
||||
await browserListening;
|
||||
@ -1886,15 +1860,6 @@ GeckoDriver.prototype.switchToFrame = async function(cmd) {
|
||||
}
|
||||
|
||||
} else if (this.context == Context.Content) {
|
||||
if (!id && !byFrame &&
|
||||
this.curBrowser.frameManager.currentRemoteFrame !== null) {
|
||||
// We're currently using a ChromeMessageSender for a remote frame,
|
||||
// so this request indicates we need to switch back to the top-level
|
||||
// (parent) frame. We'll first switch to the parent's (global)
|
||||
// ChromeMessageBroadcaster, so we send the message to the right
|
||||
// listener.
|
||||
this.switchToGlobalMessageManager();
|
||||
}
|
||||
cmd.commandID = cmd.id;
|
||||
|
||||
let res = await this.listener.switchToFrame(cmd.parameters);
|
||||
@ -2829,10 +2794,6 @@ GeckoDriver.prototype.close = async function() {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (this.mm != globalMessageManager) {
|
||||
this.mm.removeDelayedFrameScript(FRAME_SCRIPT);
|
||||
}
|
||||
|
||||
await this.curBrowser.closeTab();
|
||||
return this.windowHandles.map(String);
|
||||
};
|
||||
@ -2868,10 +2829,6 @@ GeckoDriver.prototype.closeChromeWindow = async function() {
|
||||
// reset frame to the top-most frame
|
||||
this.curFrame = null;
|
||||
|
||||
if (this.mm != globalMessageManager) {
|
||||
this.mm.removeDelayedFrameScript(FRAME_SCRIPT);
|
||||
}
|
||||
|
||||
await this.curBrowser.closeWindow();
|
||||
return this.chromeWindowHandles.map(String);
|
||||
};
|
||||
@ -2904,8 +2861,6 @@ GeckoDriver.prototype.deleteSession = function() {
|
||||
globalMessageManager);
|
||||
}
|
||||
|
||||
this.switchToGlobalMessageManager();
|
||||
|
||||
// reset frame to the top-most frame
|
||||
this.curFrame = null;
|
||||
if (this.mainFrame) {
|
||||
|
@ -164,7 +164,6 @@ frame.Manager = class {
|
||||
this.currentRemoteFrame = f;
|
||||
this.addMessageManagerListeners(mm);
|
||||
|
||||
mm.sendAsyncMessage("Marionette:restart");
|
||||
return oopFrame.id;
|
||||
}
|
||||
}
|
||||
|
@ -2,36 +2,42 @@
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
import urllib
|
||||
|
||||
from marionette_driver.by import By
|
||||
from marionette_driver.errors import MoveTargetOutOfBoundsException
|
||||
|
||||
from marionette_harness import MarionetteTestCase, skip, skip_if_mobile
|
||||
from marionette_harness import MarionetteTestCase, skip_if_mobile
|
||||
|
||||
|
||||
def inline(doc):
|
||||
return "data:text/html;charset=utf-8,{}".format(urllib.quote(doc))
|
||||
|
||||
|
||||
class TestClickScrolling(MarionetteTestCase):
|
||||
|
||||
|
||||
def test_clicking_on_anchor_scrolls_page(self):
|
||||
scrollScript = """
|
||||
var pageY;
|
||||
if (typeof(window.pageYOffset) == 'number') {
|
||||
pageY = window.pageYOffset;
|
||||
} else {
|
||||
pageY = document.documentElement.scrollTop;
|
||||
}
|
||||
return pageY;"""
|
||||
|
||||
test_html = self.marionette.absolute_url("macbeth.html")
|
||||
self.marionette.navigate(test_html)
|
||||
|
||||
self.marionette.find_element(By.PARTIAL_LINK_TEXT, "last speech").click()
|
||||
y_offset = self.marionette.execute_script(scrollScript)
|
||||
self.marionette.navigate(inline("""
|
||||
<a href="#content">Link to content</a>
|
||||
<div id="content" style="margin-top: 205vh;">Text</div>
|
||||
"""))
|
||||
|
||||
# Focusing on to click, but not actually following,
|
||||
# the link will scroll it in to view, which is a few
|
||||
# pixels further than 0
|
||||
self.marionette.find_element(By.CSS_SELECTOR, "a").click()
|
||||
|
||||
self.assertTrue(y_offset > 300)
|
||||
y_offset = self.marionette.execute_script("""
|
||||
var pageY;
|
||||
if (typeof(window.pageYOffset) == 'number') {
|
||||
pageY = window.pageYOffset;
|
||||
} else {
|
||||
pageY = document.documentElement.scrollTop;
|
||||
}
|
||||
return pageY;
|
||||
""")
|
||||
|
||||
self.assertGreater(y_offset, 300)
|
||||
|
||||
def test_should_scroll_to_click_on_an_element_hidden_by_overflow(self):
|
||||
test_html = self.marionette.absolute_url("click_out_of_bounds_overflow.html")
|
||||
@ -43,45 +49,6 @@ class TestClickScrolling(MarionetteTestCase):
|
||||
except MoveTargetOutOfBoundsException:
|
||||
self.fail("Should not be out of bounds")
|
||||
|
||||
@skip("Bug 1200197 - Cannot interact with elements hidden inside overflow:scroll")
|
||||
def test_should_be_able_to_click_on_an_element_hidden_by_overflow(self):
|
||||
test_html = self.marionette.absolute_url("scroll.html")
|
||||
self.marionette.navigate(test_html)
|
||||
|
||||
link = self.marionette.find_element(By.ID, "line8")
|
||||
link.click()
|
||||
self.assertEqual("line8", self.marionette.find_element(By.ID, "clicked").text)
|
||||
|
||||
def test_should_not_scroll_overflow_elements_which_are_visible(self):
|
||||
test_html = self.marionette.absolute_url("scroll2.html")
|
||||
self.marionette.navigate(test_html)
|
||||
|
||||
list_el = self.marionette.find_element(By.TAG_NAME, "ul")
|
||||
item = list_el.find_element(By.ID, "desired")
|
||||
item.click()
|
||||
y_offset = self.marionette.execute_script("return arguments[0].scrollTop;", script_args=[list_el])
|
||||
self.assertEqual(0, y_offset)
|
||||
|
||||
def test_should_not_scroll_if_already_scrolled_and_element_is_in_view(self):
|
||||
test_html = self.marionette.absolute_url("scroll3.html")
|
||||
self.marionette.navigate(test_html)
|
||||
|
||||
button1 = self.marionette.find_element(By.ID, "button1")
|
||||
button2 = self.marionette.find_element(By.ID, "button2")
|
||||
|
||||
button2.click()
|
||||
scroll_top = self.marionette.execute_script("return document.body.scrollTop;")
|
||||
button1.click()
|
||||
|
||||
self.assertEqual(scroll_top, self.marionette.execute_script("return document.body.scrollTop;"))
|
||||
|
||||
def test_should_be_able_to_click_radio_button_scrolled_into_view(self):
|
||||
test_html = self.marionette.absolute_url("scroll4.html")
|
||||
self.marionette.navigate(test_html)
|
||||
|
||||
# If we dont throw we are good
|
||||
self.marionette.find_element(By.ID, "radio").click()
|
||||
|
||||
@skip_if_mobile("Bug 1293855 - Lists differ: [70, 70] != [70, 120]")
|
||||
def test_should_not_scroll_elements_if_click_point_is_in_view(self):
|
||||
test_html = self.marionette.absolute_url("element_outside_viewport.html")
|
||||
@ -91,12 +58,76 @@ class TestClickScrolling(MarionetteTestCase):
|
||||
self.marionette.navigate(test_html)
|
||||
scroll = self.marionette.execute_script("return [window.scrollX, window.scrollY];")
|
||||
self.marionette.find_element(By.ID, "{0}-{1}".format(s, p)).click()
|
||||
self.assertEqual(scroll, self.marionette.execute_script("return [window.scrollX, window.scrollY];"))
|
||||
self.assertEqual(scroll, self.marionette.execute_script(
|
||||
"return [window.scrollX, window.scrollY];"))
|
||||
|
||||
@skip("Bug 1003687")
|
||||
def test_should_scroll_overflow_elements_if_click_point_is_out_of_view_but_element_is_in_view(self):
|
||||
test_html = self.marionette.absolute_url("scroll5.html")
|
||||
self.marionette.navigate(test_html)
|
||||
def test_do_not_scroll_again_if_element_is_already_in_view(self):
|
||||
self.marionette.navigate(inline("""
|
||||
<div style="height: 200vh;">
|
||||
<button id="button1" style="margin-top: 105vh">Button1</button>
|
||||
<button id="button2" style="position: relative; top: 5em">Button2</button>
|
||||
</div>
|
||||
"""))
|
||||
button1 = self.marionette.find_element(By.ID, "button1")
|
||||
button2 = self.marionette.find_element(By.ID, "button2")
|
||||
|
||||
button2.click()
|
||||
scroll_top = self.marionette.execute_script("return document.body.scrollTop;")
|
||||
button1.click()
|
||||
|
||||
self.assertEqual(scroll_top, self.marionette.execute_script(
|
||||
"return document.body.scrollTop;"))
|
||||
|
||||
def test_scroll_radio_button_into_view(self):
|
||||
self.marionette.navigate(inline("""
|
||||
<input type="radio" id="radio" style="margin-top: 105vh;">
|
||||
"""))
|
||||
self.marionette.find_element(By.ID, "radio").click()
|
||||
|
||||
def test_overflow_scroll_do_not_scroll_elements_which_are_visible(self):
|
||||
self.marionette.navigate(inline("""
|
||||
<ul style='overflow: scroll; height: 8em; line-height: 3em'>
|
||||
<li></li>
|
||||
<li id="desired">Text</li>
|
||||
<li></li>
|
||||
<li></li>
|
||||
</ul>
|
||||
"""))
|
||||
|
||||
list_el = self.marionette.find_element(By.TAG_NAME, "ul")
|
||||
expected_y_offset = self.marionette.execute_script(
|
||||
"return arguments[0].scrollTop;", script_args=(list_el,))
|
||||
|
||||
item = list_el.find_element(By.ID, "desired")
|
||||
item.click()
|
||||
|
||||
y_offset = self.marionette.execute_script("return arguments[0].scrollTop;",
|
||||
script_args=(list_el,))
|
||||
self.assertEqual(expected_y_offset, y_offset)
|
||||
|
||||
def test_overflow_scroll_click_on_hidden_element(self):
|
||||
self.marionette.navigate(inline("""
|
||||
Result: <span id="result"></span>
|
||||
<ul style='overflow: scroll; width: 150px; height: 8em; line-height: 4em'
|
||||
onclick="document.getElementById('result').innerText = event.target.id;">
|
||||
<li>line1</li>
|
||||
<li>line2</li>
|
||||
<li>line3</li>
|
||||
<li id="line4">line4</li>
|
||||
</ul>
|
||||
"""))
|
||||
|
||||
self.marionette.find_element(By.ID, "line4").click()
|
||||
self.assertEqual("line4", self.marionette.find_element(By.ID, "result").text)
|
||||
|
||||
def test_overflow_scroll_vertically_for_click_point_outside_of_viewport(self):
|
||||
self.marionette.navigate(inline("""
|
||||
Result: <span id="result"></span>
|
||||
<div style='overflow: scroll; width: 100px; height: 100px; background-color: yellow;'>
|
||||
<div id="inner" style="width: 100px; height: 300px; background-color: green;"
|
||||
onclick="document.getElementById('result').innerText = event.type" ></div>
|
||||
</div>
|
||||
"""))
|
||||
|
||||
self.marionette.find_element(By.ID, "inner").click()
|
||||
self.assertEqual("clicked", self.marionette.find_element(By.ID, "clicked").text)
|
||||
self.assertEqual("click", self.marionette.find_element(By.ID, "result").text)
|
||||
|
@ -26,13 +26,8 @@ class MockMozCrash(object):
|
||||
|
||||
with self.marionette.using_context('chrome'):
|
||||
self.crash_reporter_enabled = self.marionette.execute_script("""
|
||||
try {
|
||||
Components.classes["@mozilla.org/toolkit/crash-reporter;1"].
|
||||
getService(Components.interfaces.nsICrashReporter);
|
||||
return true;
|
||||
} catch (exc) {
|
||||
return false;
|
||||
}
|
||||
Cu.import("resource://gre/modules/AppConstants.jsm");
|
||||
return AppConstants.MOZ_CRASHREPORTER;
|
||||
""")
|
||||
|
||||
def check_for_crashes(self, dump_directory, *args, **kwargs):
|
||||
|
@ -755,6 +755,7 @@ class TestPageLoadStrategy(BaseNavigationTestCase):
|
||||
self.assertEqual("complete", self.ready_state)
|
||||
self.marionette.find_element(By.ID, "slow")
|
||||
|
||||
@skip("Bug 1422741 - Causes following tests to fail in loading remote browser")
|
||||
@run_if_e10s("Requires e10s mode enabled")
|
||||
def test_strategy_after_remoteness_change(self):
|
||||
"""Bug 1378191 - Reset of capabilities after listener reload"""
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,30 +0,0 @@
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<html>
|
||||
<head></head>
|
||||
<body>
|
||||
<script>
|
||||
function dump(event) {
|
||||
var elt = event.target || event.srcElement;
|
||||
document.getElementById('clicked').innerHTML = elt.innerHTML;
|
||||
}
|
||||
</script>
|
||||
<div style='height: 150px'></div>
|
||||
<ul style='overflow: scroll; width: 150px; height: 80px; background-color: yellow' onclick="dump(event)">
|
||||
<li id='line1'>line1</li>
|
||||
<li id='line2'>line2</li>
|
||||
<li id='line3'>line3</li>
|
||||
<li id='line4'>line4</li>
|
||||
<li id='line5'>line5</li>
|
||||
<li id='line6'>line6</li>
|
||||
<li id='line7'>line7</li>
|
||||
<li id='line8'>line8</li>
|
||||
<li id='line9'>line9</li>
|
||||
</ul>
|
||||
<div>
|
||||
Clicked: <span id='clicked'></span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,24 +0,0 @@
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<html>
|
||||
<head></head>
|
||||
<body>
|
||||
<ul style='overflow: scroll; height: 100px;'>
|
||||
<li></li>
|
||||
<li></li>
|
||||
<li id="desired">Text</li>
|
||||
<li></li>
|
||||
<li></li>
|
||||
<li></li>
|
||||
<li></li>
|
||||
<li></li>
|
||||
<li></li>
|
||||
<li></li>
|
||||
<li></li>
|
||||
<li></li>
|
||||
<li></li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
@ -1,18 +0,0 @@
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
|
||||
<style type="text/css"></style>
|
||||
</head>
|
||||
<body>
|
||||
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
|
||||
<button id="button1">Button1</button>
|
||||
<br><br><br><br>
|
||||
|
||||
<button id="button2">Button2</button>
|
||||
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
|
||||
</body>
|
||||
</html>
|
@ -1,15 +0,0 @@
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
|
||||
<style type="text/css"></style>
|
||||
</head>
|
||||
<body>
|
||||
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
|
||||
<input type="radio" id="radio">
|
||||
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
|
||||
</body>
|
||||
</html>
|
@ -1,20 +0,0 @@
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<html>
|
||||
<head></head>
|
||||
<body>
|
||||
<script>
|
||||
function dump(text) {
|
||||
document.getElementById('clicked').innerHTML = text;
|
||||
}
|
||||
</script>
|
||||
<div style='overflow: scroll; width: 150px; height: 200px; background-color: yellow' id="outer">
|
||||
<div style="width: 150px; height: 5000px; background-color: red;" onclick="dump('clicked')" id="inner"></div>
|
||||
</div>
|
||||
<div>
|
||||
Clicked: <span id='clicked'></span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -574,7 +574,6 @@ function startListeners() {
|
||||
addMessageListenerId("Marionette:switchToParentFrame", switchToParentFrame);
|
||||
addMessageListenerId("Marionette:switchToShadowRoot", switchToShadowRootFn);
|
||||
addMessageListenerId("Marionette:deleteSession", deleteSession);
|
||||
addMessageListenerId("Marionette:sleepSession", sleepSession);
|
||||
addMessageListenerId("Marionette:takeScreenshot", takeScreenshotFn);
|
||||
addMessageListenerId("Marionette:reftestWait", reftestWaitFn);
|
||||
addMessageListener("Marionette:DOM:AddEventListener", domAddEventListener);
|
||||
@ -590,23 +589,6 @@ function newSession(msg) {
|
||||
resetValues();
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the current session to sleep, so all listeners are removed except
|
||||
* for the 'restart' listener.
|
||||
*/
|
||||
function sleepSession() {
|
||||
deleteSession();
|
||||
addMessageListener("Marionette:restart", restart);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restarts all our listeners after this listener was put to sleep
|
||||
*/
|
||||
function restart() {
|
||||
removeMessageListener("Marionette:restart", restart);
|
||||
registerSelf();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all listeners
|
||||
*/
|
||||
@ -658,7 +640,6 @@ function deleteSession() {
|
||||
removeMessageListenerId(
|
||||
"Marionette:switchToShadowRoot", switchToShadowRootFn);
|
||||
removeMessageListenerId("Marionette:deleteSession", deleteSession);
|
||||
removeMessageListenerId("Marionette:sleepSession", sleepSession);
|
||||
removeMessageListenerId("Marionette:takeScreenshot", takeScreenshotFn);
|
||||
|
||||
seenEls.clear();
|
||||
|
@ -273,6 +273,16 @@ config = {
|
||||
'halt_on_failure': True,
|
||||
'enabled': ADJUST_MOUSE_AND_SCREEN
|
||||
},
|
||||
{
|
||||
'name': 'disable windows security and maintenance notifications',
|
||||
'cmd': [
|
||||
'powershell', '-command',
|
||||
'"&{$p=\'HKCU:SOFTWARE\Microsoft\Windows\CurrentVersion\Notifications\Settings\Windows.SystemToast.SecurityAndMaintenance\';if(!(Test-Path -Path $p)){&New-Item -Path $p -Force}&Set-ItemProperty -Path $p -Name Enabled -Value 0}"'
|
||||
],
|
||||
'architectures': ['32bit', '64bit'],
|
||||
'halt_on_failure': True,
|
||||
'enabled': (platform.release() == 10)
|
||||
},
|
||||
{
|
||||
'name': 'set windows VisualFX',
|
||||
'cmd': [
|
||||
|
@ -113,21 +113,21 @@ MOZDEPTH ?= $(DEPTH)
|
||||
|
||||
repackage-zip: UNPACKAGE='$(ZIP_IN)'
|
||||
repackage-zip:
|
||||
$(PYTHON) $(MOZILLA_DIR)/toolkit/mozapps/installer/l10n-repack.py $(STAGEDIST) $(DIST)/xpi-stage/locale-$(AB_CD) \
|
||||
$(PYTHON) $(MOZILLA_DIR)/toolkit/mozapps/installer/l10n-repack.py '$(STAGEDIST)' $(DIST)/xpi-stage/locale-$(AB_CD) \
|
||||
$(MOZ_PKG_EXTRAL10N) \
|
||||
$(if $(filter omni,$(MOZ_PACKAGER_FORMAT)),$(if $(NON_OMNIJAR_FILES),--non-resource $(NON_OMNIJAR_FILES)))
|
||||
|
||||
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
|
||||
ifneq (en,$(LPROJ_ROOT))
|
||||
mv $(STAGEDIST)/en.lproj $(STAGEDIST)/$(LPROJ_ROOT).lproj
|
||||
mv '$(STAGEDIST)'/en.lproj '$(STAGEDIST)'/$(LPROJ_ROOT).lproj
|
||||
endif
|
||||
ifdef MOZ_CRASHREPORTER
|
||||
# On Mac OS X, the crashreporter.ini file needs to be moved from under the
|
||||
# application bundle's Resources directory where all other l10n files are
|
||||
# located to the crash reporter bundle's Resources directory.
|
||||
mv $(STAGEDIST)/crashreporter.app/Contents/Resources/crashreporter.ini \
|
||||
$(STAGEDIST)/../MacOS/crashreporter.app/Contents/Resources/crashreporter.ini
|
||||
$(RM) -rf $(STAGEDIST)/crashreporter.app
|
||||
mv '$(STAGEDIST)'/crashreporter.app/Contents/Resources/crashreporter.ini \
|
||||
'$(STAGEDIST)'/../MacOS/crashreporter.app/Contents/Resources/crashreporter.ini
|
||||
$(RM) -rf '$(STAGEDIST)'/crashreporter.app
|
||||
endif
|
||||
endif
|
||||
|
||||
@ -141,7 +141,7 @@ endif
|
||||
# packaging done, undo l10n stuff
|
||||
ifneq (en,$(LPROJ_ROOT))
|
||||
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
|
||||
mv $(STAGEDIST)/$(LPROJ_ROOT).lproj $(STAGEDIST)/en.lproj
|
||||
mv '$(STAGEDIST)'/$(LPROJ_ROOT).lproj '$(STAGEDIST)'/en.lproj
|
||||
endif
|
||||
endif
|
||||
$(NSINSTALL) -D $(DIST)/$(PKG_PATH)
|
||||
@ -247,7 +247,7 @@ endif
|
||||
generate-snippet-%:
|
||||
$(PYTHON) $(MOZILLA_DIR)/tools/update-packaging/generatesnippet.py \
|
||||
--mar-path=$(ABS_DIST)/update \
|
||||
--application-ini-file=$(STAGEDIST)/application.ini \
|
||||
--application-ini-file='$(STAGEDIST)'/application.ini \
|
||||
--locale=$* \
|
||||
--product=$(MOZ_PKG_APPNAME) \
|
||||
--platform=$(MOZ_PKG_PLATFORM) \
|
||||
|
@ -46,7 +46,7 @@ stage-package: multilocale.json locale-manifest.in $(MOZ_PKG_MANIFEST) $(MOZ_PKG
|
||||
$(if $(JARLOG_DIR),$(addprefix --jarlog ,$(wildcard $(JARLOG_FILE_AB_CD)))) \
|
||||
$(if $(OPTIMIZEJARS),--optimizejars) \
|
||||
$(addprefix --compress ,$(JAR_COMPRESSION)) \
|
||||
$(MOZ_PKG_MANIFEST) $(DIST) $(DIST)/$(MOZ_PKG_DIR)$(if $(MOZ_PKG_MANIFEST),,$(_BINPATH)) \
|
||||
$(MOZ_PKG_MANIFEST) '$(DIST)' '$(DIST)'/$(MOZ_PKG_DIR)$(if $(MOZ_PKG_MANIFEST),,$(_BINPATH)) \
|
||||
$(if $(filter omni,$(MOZ_PACKAGER_FORMAT)),$(if $(NON_OMNIJAR_FILES),--non-resource $(NON_OMNIJAR_FILES)))
|
||||
$(PYTHON) $(MOZILLA_DIR)/toolkit/mozapps/installer/find-dupes.py $(DEFINES) $(ACDEFINES) $(MOZ_PKG_DUPEFLAGS) $(DIST)/$(MOZ_PKG_DIR)
|
||||
ifndef MOZ_IS_COMM_TOPDIR
|
||||
|
@ -83,15 +83,15 @@ make_add_instruction() {
|
||||
# before performing this add instruction.
|
||||
testdir=$(echo "$f" | sed 's/\(.*distribution\/extensions\/[^\/]*\)\/.*/\1/')
|
||||
notice " add-if \"$testdir\" \"$f\""
|
||||
echo "add-if \"$testdir\" \"$f\"" >> $filev2
|
||||
echo "add-if \"$testdir\" \"$f\"" >> "$filev2"
|
||||
if [ ! $filev3 = "" ]; then
|
||||
echo "add-if \"$testdir\" \"$f\"" >> $filev3
|
||||
echo "add-if \"$testdir\" \"$f\"" >> "$filev3"
|
||||
fi
|
||||
else
|
||||
notice " add \"$f\"$forced"
|
||||
echo "add \"$f\"" >> $filev2
|
||||
echo "add \"$f\"" >> "$filev2"
|
||||
if [ ! $filev3 = "" ]; then
|
||||
echo "add \"$f\"" >> $filev3
|
||||
echo "add \"$f\"" >> "$filev3"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
@ -138,12 +138,12 @@ make_patch_instruction() {
|
||||
# before performing this add instruction.
|
||||
testdir=$(echo "$f" | sed 's/\(.*distribution\/extensions\/[^\/]*\)\/.*/\1/')
|
||||
notice " patch-if \"$testdir\" \"$f.patch\" \"$f\""
|
||||
echo "patch-if \"$testdir\" \"$f.patch\" \"$f\"" >> $filev2
|
||||
echo "patch-if \"$testdir\" \"$f.patch\" \"$f\"" >> $filev3
|
||||
echo "patch-if \"$testdir\" \"$f.patch\" \"$f\"" >> "$filev2"
|
||||
echo "patch-if \"$testdir\" \"$f.patch\" \"$f\"" >> "$filev3"
|
||||
else
|
||||
notice " patch \"$f.patch\" \"$f\""
|
||||
echo "patch \"$f.patch\" \"$f\"" >> $filev2
|
||||
echo "patch \"$f.patch\" \"$f\"" >> $filev3
|
||||
echo "patch \"$f.patch\" \"$f\"" >> "$filev2"
|
||||
echo "patch \"$f.patch\" \"$f\"" >> "$filev3"
|
||||
fi
|
||||
}
|
||||
|
||||
@ -172,18 +172,18 @@ append_remove_instructions() {
|
||||
if [ ! $(echo "$f" | grep -c '^#') = 1 ]; then
|
||||
if [ $(echo "$f" | grep -c '\/$') = 1 ]; then
|
||||
notice " rmdir \"$f\""
|
||||
echo "rmdir \"$f\"" >> $filev2
|
||||
echo "rmdir \"$f\"" >> $filev3
|
||||
echo "rmdir \"$f\"" >> "$filev2"
|
||||
echo "rmdir \"$f\"" >> "$filev3"
|
||||
elif [ $(echo "$f" | grep -c '\/\*$') = 1 ]; then
|
||||
# Remove the *
|
||||
f=$(echo "$f" | sed -e 's:\*$::')
|
||||
notice " rmrfdir \"$f\""
|
||||
echo "rmrfdir \"$f\"" >> $filev2
|
||||
echo "rmrfdir \"$f\"" >> $filev3
|
||||
echo "rmrfdir \"$f\"" >> "$filev2"
|
||||
echo "rmrfdir \"$f\"" >> "$filev3"
|
||||
else
|
||||
notice " remove \"$f\""
|
||||
echo "remove \"$f\"" >> $filev2
|
||||
echo "remove \"$f\"" >> $filev3
|
||||
echo "remove \"$f\"" >> "$filev2"
|
||||
echo "remove \"$f\"" >> "$filev3"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
@ -67,13 +67,13 @@ list_files files
|
||||
popd
|
||||
|
||||
# Add the type of update to the beginning of the update manifests.
|
||||
> $updatemanifestv2
|
||||
> $updatemanifestv3
|
||||
> "$updatemanifestv2"
|
||||
> "$updatemanifestv3"
|
||||
notice ""
|
||||
notice "Adding type instruction to update manifests"
|
||||
notice " type complete"
|
||||
echo "type \"complete\"" >> $updatemanifestv2
|
||||
echo "type \"complete\"" >> $updatemanifestv3
|
||||
echo "type \"complete\"" >> "$updatemanifestv2"
|
||||
echo "type \"complete\"" >> "$updatemanifestv3"
|
||||
|
||||
notice ""
|
||||
notice "Adding file add instructions to update manifests"
|
||||
|
@ -438,6 +438,8 @@ STUB(gtk_widget_get_has_window)
|
||||
STUB(gtk_widget_get_mapped)
|
||||
STUB(gtk_widget_get_parent)
|
||||
STUB(gtk_widget_get_parent_window)
|
||||
STUB(gtk_widget_get_preferred_width)
|
||||
STUB(gtk_widget_get_preferred_height)
|
||||
STUB(gtk_widget_get_realized)
|
||||
STUB(gtk_widget_get_screen)
|
||||
STUB(gtk_widget_get_settings)
|
||||
@ -479,6 +481,7 @@ STUB(gtk_widget_show_all)
|
||||
STUB(gtk_widget_size_allocate)
|
||||
STUB(gtk_widget_style_get)
|
||||
STUB(gtk_widget_unparent)
|
||||
STUB(gtk_widget_unrealize)
|
||||
STUB(gtk_window_deiconify)
|
||||
STUB(gtk_window_fullscreen)
|
||||
STUB(gtk_window_get_group)
|
||||
|
@ -3790,12 +3790,13 @@ nsWindow::Create(nsIWidget* aParent,
|
||||
* 1) We're running on Gtk+ without client side decorations.
|
||||
* Content is rendered to mShell window and we listen
|
||||
* to the Gtk+ events on mShell
|
||||
* 2) We're running on Gtk+ > 3.20 and client side decorations
|
||||
* 2) We're running on Gtk+ and client side decorations
|
||||
* are drawn by Gtk+ to mShell. Content is rendered to mContainer
|
||||
* and we listen to the Gtk+ events on mContainer.
|
||||
*/
|
||||
GtkStyleContext* style = gtk_widget_get_style_context(mShell);
|
||||
drawToContainer = gtk_style_context_has_class(style, "csd");
|
||||
drawToContainer = mIsCSDAvailable ||
|
||||
gtk_style_context_has_class(style, "csd");
|
||||
#endif
|
||||
eventWidget = (drawToContainer) ? container : mShell;
|
||||
|
||||
@ -5077,7 +5078,7 @@ nsWindow::MakeFullScreen(bool aFullScreen, nsIScreen* aTargetScreen)
|
||||
}
|
||||
|
||||
void
|
||||
nsWindow::HideWindowChrome(bool aShouldHide)
|
||||
nsWindow::SetWindowDecoration(nsBorderStyle aStyle)
|
||||
{
|
||||
if (!mShell) {
|
||||
// Pass the request to the toplevel window
|
||||
@ -5089,7 +5090,7 @@ nsWindow::HideWindowChrome(bool aShouldHide)
|
||||
if (!topWindow)
|
||||
return;
|
||||
|
||||
topWindow->HideWindowChrome(aShouldHide);
|
||||
topWindow->SetWindowDecoration(aStyle);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -5102,12 +5103,7 @@ nsWindow::HideWindowChrome(bool aShouldHide)
|
||||
wasVisible = true;
|
||||
}
|
||||
|
||||
gint wmd;
|
||||
if (aShouldHide)
|
||||
wmd = 0;
|
||||
else
|
||||
wmd = ConvertBorderStyles(mBorderStyle);
|
||||
|
||||
gint wmd = ConvertBorderStyles(aStyle);
|
||||
if (wmd != -1)
|
||||
gdk_window_set_decorations(mGdkWindow, (GdkWMDecoration) wmd);
|
||||
|
||||
@ -5126,6 +5122,12 @@ nsWindow::HideWindowChrome(bool aShouldHide)
|
||||
#endif /* MOZ_X11 */
|
||||
}
|
||||
|
||||
void
|
||||
nsWindow::HideWindowChrome(bool aShouldHide)
|
||||
{
|
||||
SetWindowDecoration(aShouldHide ? eBorderStyle_none : mBorderStyle);
|
||||
}
|
||||
|
||||
bool
|
||||
nsWindow::CheckForRollup(gdouble aMouseX, gdouble aMouseY,
|
||||
bool aIsWheel, bool aAlwaysRollup)
|
||||
@ -6646,14 +6648,66 @@ nsWindow::SetDrawsInTitlebar(bool aState)
|
||||
return;
|
||||
|
||||
if (mShell) {
|
||||
gint wmd;
|
||||
if (aState) {
|
||||
wmd = GetCSDSupportLevel() == CSD_SUPPORT_FULL ? GDK_DECOR_BORDER : 0;
|
||||
} else {
|
||||
wmd = ConvertBorderStyles(mBorderStyle);
|
||||
if (GetCSDSupportLevel() == CSD_SUPPORT_FULL) {
|
||||
SetWindowDecoration(aState ? eBorderStyle_border : mBorderStyle);
|
||||
}
|
||||
else {
|
||||
/* Window manager does not support GDK_DECOR_BORDER,
|
||||
* emulate it by CSD.
|
||||
*
|
||||
* gtk_window_set_titlebar() works on unrealized widgets only,
|
||||
* we need to handle mShell carefully here.
|
||||
* When CSD is enabled mGdkWindow is owned by mContainer which is good
|
||||
* as we can't delete our mGdkWindow. To make mShell unrealized while
|
||||
* mContainer is preserved we temporary reparent mContainer to an
|
||||
* invisible GtkWindow.
|
||||
*/
|
||||
NativeShow(false);
|
||||
|
||||
// Using GTK_WINDOW_POPUP rather than
|
||||
// GTK_WINDOW_TOPLEVEL in the hope that POPUP results in less
|
||||
// initialization and window manager interaction.
|
||||
GtkWidget* tmpWindow = gtk_window_new(GTK_WINDOW_POPUP);
|
||||
gtk_widget_realize(tmpWindow);
|
||||
|
||||
gtk_widget_reparent(GTK_WIDGET(mContainer), tmpWindow);
|
||||
gtk_widget_unrealize(GTK_WIDGET(mShell));
|
||||
|
||||
// Available as of GTK 3.10+
|
||||
static auto sGtkWindowSetTitlebar = (void (*)(GtkWindow*, GtkWidget*))
|
||||
dlsym(RTLD_DEFAULT, "gtk_window_set_titlebar");
|
||||
MOZ_ASSERT(sGtkWindowSetTitlebar,
|
||||
"Missing gtk_window_set_titlebar(), old Gtk+ library?");
|
||||
|
||||
if (aState) {
|
||||
// Add a hidden titlebar widget to trigger CSD, but disable the default
|
||||
// titlebar. GtkFixed is a somewhat random choice for a simple unused
|
||||
// widget. gtk_window_set_titlebar() takes ownership of the titlebar
|
||||
// widget.
|
||||
sGtkWindowSetTitlebar(GTK_WINDOW(mShell), gtk_fixed_new());
|
||||
} else {
|
||||
sGtkWindowSetTitlebar(GTK_WINDOW(mShell), nullptr);
|
||||
}
|
||||
|
||||
/* A workaround for https://bugzilla.gnome.org/show_bug.cgi?id=791081
|
||||
* gtk_widget_realize() throws:
|
||||
* "In pixman_region32_init_rect: Invalid rectangle passed"
|
||||
* when mShell has default 1x1 size.
|
||||
*/
|
||||
GtkAllocation allocation = {0, 0, 0, 0};
|
||||
gtk_widget_get_preferred_width(GTK_WIDGET(mShell), nullptr,
|
||||
&allocation.width);
|
||||
gtk_widget_get_preferred_height(GTK_WIDGET(mShell), nullptr,
|
||||
&allocation.height);
|
||||
gtk_widget_size_allocate(GTK_WIDGET(mShell), &allocation);
|
||||
|
||||
gtk_widget_realize(GTK_WIDGET(mShell));
|
||||
gtk_widget_reparent(GTK_WIDGET(mContainer), GTK_WIDGET(mShell));
|
||||
mNeedsShow = true;
|
||||
NativeResize();
|
||||
|
||||
gtk_widget_destroy(tmpWindow);
|
||||
}
|
||||
gdk_window_set_decorations(gtk_widget_get_window(mShell),
|
||||
(GdkWMDecoration) wmd);
|
||||
}
|
||||
|
||||
mIsCSDEnabled = aState;
|
||||
|
@ -435,6 +435,7 @@ private:
|
||||
nsWindow *GetContainerWindow();
|
||||
void SetUrgencyHint(GtkWidget *top_window, bool state);
|
||||
void SetDefaultIcon(void);
|
||||
void SetWindowDecoration(nsBorderStyle aStyle);
|
||||
void InitButtonEvent(mozilla::WidgetMouseEvent& aEvent,
|
||||
GdkEventButton* aGdkEvent);
|
||||
bool DispatchCommandEvent(nsAtom* aCommand);
|
||||
@ -453,7 +454,6 @@ private:
|
||||
nsIWidgetListener* GetListener();
|
||||
bool IsComposited() const;
|
||||
|
||||
|
||||
GtkWidget *mShell;
|
||||
MozContainer *mContainer;
|
||||
GdkWindow *mGdkWindow;
|
||||
|
Loading…
Reference in New Issue
Block a user