mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
Merge autoland to mozilla-central. a=merge
This commit is contained in:
commit
91bc2053a8
@ -1 +0,0 @@
|
||||
PURGECACHES_DIRS = $(DIST)/bin/browser
|
@ -19,6 +19,14 @@ add_task(async function() {
|
||||
Components.interfaces.nsIDOMWindowUtils.MODIFIER_META :
|
||||
Components.interfaces.nsIDOMWindowUtils.MODIFIER_CONTROL;
|
||||
|
||||
function sendKey(message) {
|
||||
BrowserTestUtils.synthesizeKey(message.data.key,
|
||||
{code: message.data.code, accelKey: true},
|
||||
browser);
|
||||
}
|
||||
|
||||
browser.messageManager.addMessageListener("Test:SendKey", sendKey);
|
||||
|
||||
// On windows, HTML clipboard includes extra data.
|
||||
// The values are from widget/windows/nsDataObj.cpp.
|
||||
const htmlPrefix = (navigator.platform.indexOf("Win") >= 0) ? "<html><body>\n<!--StartFragment-->" : "";
|
||||
@ -29,16 +37,6 @@ add_task(async function() {
|
||||
var main = doc.getElementById("main");
|
||||
main.focus();
|
||||
|
||||
const utils = content.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||
|
||||
function sendKey(key) {
|
||||
if (utils.sendKeyEvent("keydown", key, 0, arg.modifier)) {
|
||||
utils.sendKeyEvent("keypress", key, key.charCodeAt(0), arg.modifier);
|
||||
}
|
||||
utils.sendKeyEvent("keyup", key, 0, arg.modifier);
|
||||
}
|
||||
|
||||
// Select an area of the text.
|
||||
let selection = doc.getSelection();
|
||||
selection.modify("move", "left", "line");
|
||||
@ -56,7 +54,7 @@ add_task(async function() {
|
||||
resolve();
|
||||
}, true);
|
||||
|
||||
sendKey("c");
|
||||
sendAsyncMessage("Test:SendKey", { key: "c", code: "KeyC" });
|
||||
});
|
||||
|
||||
selection.modify("move", "right", "line");
|
||||
@ -74,7 +72,8 @@ add_task(async function() {
|
||||
Assert.equal(clipboardData.getData("text/plain"), "t Bold", "text/plain value");
|
||||
resolve();
|
||||
}, true);
|
||||
sendKey("v");
|
||||
|
||||
sendAsyncMessage("Test:SendKey", {key: "v", code: "KeyV"});
|
||||
});
|
||||
|
||||
Assert.equal(main.innerHTML, "Test <b>Bold</b> After Textt <b>Bold</b>", "Copy and paste html");
|
||||
@ -92,7 +91,8 @@ add_task(async function() {
|
||||
event.preventDefault();
|
||||
resolve();
|
||||
}, true);
|
||||
sendKey("x");
|
||||
|
||||
sendAsyncMessage("Test:SendKey", {key: "x", code: "KeyX"});
|
||||
});
|
||||
|
||||
selection.modify("move", "left", "line");
|
||||
@ -110,7 +110,8 @@ add_task(async function() {
|
||||
Assert.equal(clipboardData.getData("text/plain"), "Some text", "text/plain value 2");
|
||||
resolve();
|
||||
}, true);
|
||||
sendKey("v");
|
||||
|
||||
sendAsyncMessage("Test:SendKey", {key: "v", code: "KeyV"});
|
||||
});
|
||||
|
||||
Assert.equal(main.innerHTML, "<i>Italic</i> Test <b>Bold</b> After<b></b>",
|
||||
@ -154,13 +155,7 @@ add_task(async function() {
|
||||
resolve();
|
||||
}, true);
|
||||
|
||||
const utils = content.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||
|
||||
if (utils.sendKeyEvent("keydown", "v", 0, arg.modifier)) {
|
||||
utils.sendKeyEvent("keypress", "v", "v".charCodeAt(0), arg.modifier);
|
||||
}
|
||||
utils.sendKeyEvent("keyup", "v", 0, arg.modifier);
|
||||
sendAsyncMessage("Test:SendKey", {key: "v", code: "KeyV"});
|
||||
});
|
||||
|
||||
// The new content should now include an image.
|
||||
@ -169,6 +164,8 @@ add_task(async function() {
|
||||
"Test <b>Bold</b> After<b></b>", "Paste after copy image");
|
||||
});
|
||||
|
||||
browser.messageManager.removeMessageListener("Test:SendKey", sendKey);
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
|
@ -5,7 +5,17 @@
|
||||
add_task(async function testExecuteScript() {
|
||||
let {MessageChannel} = ChromeUtils.import("resource://gre/modules/MessageChannel.jsm", {});
|
||||
|
||||
let messageManagersSize = MessageChannel.messageManagers.size;
|
||||
// When the first extension is started, ProxyMessenger.init adds MessageChannel
|
||||
// listeners for Services.mm and Services.ppmm, and they are never unsubscribed.
|
||||
// We have to exclude them after the extension has been unloaded to get an accurate
|
||||
// test.
|
||||
function getMessageManagersSize(messageManagers) {
|
||||
return Array.from(messageManagers).filter(([mm]) => {
|
||||
return !([Services.mm, Services.ppmm].includes(mm));
|
||||
}).length;
|
||||
}
|
||||
|
||||
let messageManagersSize = getMessageManagersSize(MessageChannel.messageManagers);
|
||||
let responseManagersSize = MessageChannel.responseManagers.size;
|
||||
|
||||
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "http://mochi.test:8888/", true);
|
||||
@ -31,14 +41,14 @@ add_task(async function testExecuteScript() {
|
||||
},
|
||||
},
|
||||
{
|
||||
background: "rgb(42, 42, 42)",
|
||||
background: "rgb(43, 43, 43)",
|
||||
foreground: "rgb(0, 113, 4)",
|
||||
promise: () => {
|
||||
return browser.tabs.insertCSS({
|
||||
code: "* { background: rgb(100, 100, 100) !important }",
|
||||
cssOrigin: "author",
|
||||
}).then(r => browser.tabs.insertCSS({
|
||||
code: "* { background: rgb(42, 42, 42) !important }",
|
||||
code: "* { background: rgb(43, 43, 43) !important }",
|
||||
cssOrigin: "author",
|
||||
}));
|
||||
},
|
||||
@ -52,7 +62,7 @@ add_task(async function testExecuteScript() {
|
||||
code: "* { background: rgb(100, 100, 100) !important }",
|
||||
cssOrigin: "user",
|
||||
}).then(r => browser.tabs.insertCSS({
|
||||
code: "* { background: rgb(42, 42, 42) !important }",
|
||||
code: "* { background: rgb(44, 44, 44) !important }",
|
||||
cssOrigin: "author",
|
||||
}));
|
||||
},
|
||||
@ -81,7 +91,7 @@ add_task(async function testExecuteScript() {
|
||||
browser.test.notifyPass("insertCSS");
|
||||
} catch (e) {
|
||||
browser.test.fail(`Error: ${e} :: ${e.stack}`);
|
||||
browser.test.notifyFailure("insertCSS");
|
||||
browser.test.notifyFail("insertCSS");
|
||||
}
|
||||
}
|
||||
|
||||
@ -107,7 +117,52 @@ add_task(async function testExecuteScript() {
|
||||
|
||||
// Make sure that we're not holding on to references to closed message
|
||||
// managers.
|
||||
is(MessageChannel.messageManagers.size, messageManagersSize, "Message manager count");
|
||||
is(getMessageManagersSize(MessageChannel.messageManagers), messageManagersSize,
|
||||
"Message manager count");
|
||||
is(MessageChannel.responseManagers.size, responseManagersSize, "Response manager count");
|
||||
is(MessageChannel.pendingResponses.size, 0, "Pending response count");
|
||||
});
|
||||
|
||||
add_task(async function testInsertCSS_cleanup() {
|
||||
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "http://mochi.test:8888/", true);
|
||||
|
||||
async function background() {
|
||||
await browser.tabs.insertCSS({code: "* { background: rgb(42, 42, 42) }"});
|
||||
await browser.tabs.insertCSS({file: "customize_fg_color.css"});
|
||||
|
||||
browser.test.notifyPass("insertCSS");
|
||||
}
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
"permissions": ["http://mochi.test/"],
|
||||
},
|
||||
background,
|
||||
files: {
|
||||
"customize_fg_color.css": `* { color: rgb(255, 0, 0) }`,
|
||||
},
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
|
||||
await extension.awaitFinish("insertCSS");
|
||||
|
||||
const getTabContentComputedStyle = async () => {
|
||||
let computedStyle = content.getComputedStyle(content.document.body);
|
||||
return [computedStyle.backgroundColor, computedStyle.color];
|
||||
};
|
||||
|
||||
const appliedStyles = await ContentTask.spawn(tab.linkedBrowser, null, getTabContentComputedStyle);
|
||||
|
||||
is(appliedStyles[0], "rgb(42, 42, 42)", "The injected CSS code has been applied as expected");
|
||||
is(appliedStyles[1], "rgb(255, 0, 0)", "The injected CSS file has been applied as expected");
|
||||
|
||||
await extension.unload();
|
||||
|
||||
const unloadedStyles = await ContentTask.spawn(tab.linkedBrowser, null, getTabContentComputedStyle);
|
||||
|
||||
is(unloadedStyles[0], "rgba(0, 0, 0, 0)", "The injected CSS code has been removed as expected");
|
||||
is(unloadedStyles[1], "rgb(0, 0, 0)", "The injected CSS file has been removed as expected");
|
||||
|
||||
await BrowserTestUtils.removeTab(tab);
|
||||
});
|
||||
|
@ -91,7 +91,7 @@ add_task(async function testExecuteScript() {
|
||||
browser.test.notifyPass("removeCSS");
|
||||
} catch (e) {
|
||||
browser.test.fail(`Error: ${e} :: ${e.stack}`);
|
||||
browser.test.notifyFailure("removeCSS");
|
||||
browser.test.notifyFail("removeCSS");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,8 @@ ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
|
||||
|
||||
Cu.importGlobalProperties(["fetch"]);
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "WindowsUIUtils", "@mozilla.org/windows-ui-utils;1", "nsIWindowsUIUtils");
|
||||
XPCOMUtils.defineLazyGetter(this, "WeaveService", () =>
|
||||
Cc["@mozilla.org/weave/service;1"].getService().wrappedJSObject
|
||||
|
@ -532,7 +532,8 @@ var PlacesOrganizer = {
|
||||
let fpCallback = function fpCallback_done(aResult) {
|
||||
if (aResult != Ci.nsIFilePicker.returnCancel) {
|
||||
// There is no OS.File version of the filepicker yet (Bug 937812).
|
||||
PlacesBackups.saveBookmarksToJSONFile(fp.file.path);
|
||||
PlacesBackups.saveBookmarksToJSONFile(fp.file.path)
|
||||
.catch(Cu.reportError);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -103,7 +103,7 @@ add_task(async function test_nested() {
|
||||
|
||||
const FORM_DATA = {
|
||||
children: [{
|
||||
xpath: {"/xhtml:html/xhtml:body/xhtml:input": "M"},
|
||||
xpath: {"/xhtml:html/xhtml:body/xhtml:input": "m"},
|
||||
url: "data:text/html;charset=utf-8,<input%20autofocus=true>"
|
||||
}]
|
||||
};
|
||||
@ -114,7 +114,7 @@ add_task(async function test_nested() {
|
||||
await promiseBrowserLoaded(browser);
|
||||
|
||||
// Modify the input field's value.
|
||||
await sendMessage(browser, "ss-test:sendKeyEvent", {key: "m", frame: 0});
|
||||
await BrowserTestUtils.synthesizeKey("m", {code: "KeyM"}, browser);
|
||||
|
||||
// Remove the tab and check that we stored form data correctly.
|
||||
await promiseRemoveTab(tab);
|
||||
@ -151,7 +151,7 @@ add_task(async function test_design_mode() {
|
||||
await promiseBrowserLoaded(browser);
|
||||
|
||||
// Modify the document content.
|
||||
await sendMessage(browser, "ss-test:sendKeyEvent", {key: "m"});
|
||||
await BrowserTestUtils.synthesizeKey("m", {code: "KeyM"}, browser);
|
||||
|
||||
// Close and restore the tab.
|
||||
await promiseRemoveTab(tab);
|
||||
@ -161,7 +161,7 @@ add_task(async function test_design_mode() {
|
||||
|
||||
// Check that the innerHTML value was restored.
|
||||
let html = await getInnerHTML(browser);
|
||||
let expected = "<h1>Mmozilla</h1><script>document.designMode='on'</script>";
|
||||
let expected = "<h1>mmozilla</h1><script>document.designMode='on'</script>";
|
||||
is(html, expected, "editable document has been restored correctly");
|
||||
|
||||
// Close and restore the tab.
|
||||
@ -172,7 +172,7 @@ add_task(async function test_design_mode() {
|
||||
|
||||
// Check that the innerHTML value was restored.
|
||||
html = await getInnerHTML(browser);
|
||||
expected = "<h1>Mmozilla</h1><script>document.designMode='on'</script>";
|
||||
expected = "<h1>mmozilla</h1><script>document.designMode='on'</script>";
|
||||
is(html, expected, "editable document has been restored correctly");
|
||||
|
||||
// Cleanup.
|
||||
|
@ -50,23 +50,6 @@ function defineListener(type, cb) {
|
||||
});
|
||||
}
|
||||
|
||||
defineListener("sendKeyEvent", function(data) {
|
||||
let frame = content;
|
||||
if (data.hasOwnProperty("frame")) {
|
||||
frame = content.frames[data.frame];
|
||||
}
|
||||
|
||||
let ifreq = frame.QueryInterface(Ci.nsIInterfaceRequestor);
|
||||
let utils = ifreq.getInterface(Ci.nsIDOMWindowUtils);
|
||||
|
||||
let keyCode = data.key.charCodeAt(0);
|
||||
let charCode = Ci.nsIDOMKeyEvent.DOM_VK_A + keyCode - "a".charCodeAt(0);
|
||||
|
||||
utils.sendKeyEvent("keydown", keyCode, charCode, null);
|
||||
utils.sendKeyEvent("keypress", keyCode, charCode, null);
|
||||
utils.sendKeyEvent("keyup", keyCode, charCode, null);
|
||||
});
|
||||
|
||||
defineListener("getInnerHTML", function(data) {
|
||||
return queryElement(data).innerHTML;
|
||||
});
|
||||
|
@ -1,4 +1,5 @@
|
||||
/* import-globals-from ../../../../../testing/mochitest/tests/SimpleTest/SimpleTest.js */
|
||||
/* import-globals-from ../../../../../testing/mochitest/tests/SimpleTest/EventUtils.js */
|
||||
/* import-globals-from ../../../../../toolkit/components/satchel/test/satchel_common.js */
|
||||
/* eslint-disable no-unused-vars */
|
||||
|
||||
@ -117,8 +118,8 @@ function triggerAutofillAndCheckProfile(profile) {
|
||||
|
||||
promises.push(checkFieldAutofilled);
|
||||
}
|
||||
// Press return key and trigger form autofill.
|
||||
doKey("return");
|
||||
// Press Enter key and trigger form autofill.
|
||||
synthesizeKey("KEY_Enter", {code: "Enter"});
|
||||
|
||||
return Promise.all(promises);
|
||||
}
|
||||
@ -242,10 +243,10 @@ function initPopupListener() {
|
||||
|
||||
async function triggerPopupAndHoverItem(fieldSelector, selectIndex) {
|
||||
await focusAndWaitForFieldsIdentified(fieldSelector);
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
for (let i = 0; i <= selectIndex; i++) {
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
}
|
||||
await notifySelectedIndex(selectIndex);
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
<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/EventUtils.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>
|
||||
@ -38,7 +39,7 @@ async function setupAddressStorage() {
|
||||
|
||||
add_task(async function check_autocomplete_on_autofocus_field() {
|
||||
await setupAddressStorage();
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
checkMenuEntries(MOCK_STORAGE.map(address =>
|
||||
JSON.stringify({primary: address.organization, secondary: address["street-address"]})
|
||||
|
@ -4,6 +4,7 @@
|
||||
<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/EventUtils.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>
|
||||
@ -53,7 +54,7 @@ add_task(async function history_only_menu_checking() {
|
||||
await setupFormHistory();
|
||||
|
||||
await setInput("#tel", "");
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
checkMenuEntries(["+1234567890"], false);
|
||||
});
|
||||
@ -66,7 +67,7 @@ add_task(async function all_saved_fields_less_than_threshold() {
|
||||
});
|
||||
|
||||
await setInput("#email", "");
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
checkMenuEntries(["foo@mozilla.com"], false);
|
||||
|
||||
@ -78,7 +79,7 @@ add_task(async function check_menu_when_both_existed() {
|
||||
await setupAddressStorage();
|
||||
|
||||
await setInput("#organization", "");
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
checkMenuEntries(MOCK_STORAGE.map(address =>
|
||||
JSON.stringify({
|
||||
@ -88,7 +89,7 @@ add_task(async function check_menu_when_both_existed() {
|
||||
));
|
||||
|
||||
await setInput("#street-address", "");
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
checkMenuEntries(MOCK_STORAGE.map(address =>
|
||||
JSON.stringify({
|
||||
@ -98,7 +99,7 @@ add_task(async function check_menu_when_both_existed() {
|
||||
));
|
||||
|
||||
await setInput("#tel", "");
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
checkMenuEntries(MOCK_STORAGE.map(address =>
|
||||
JSON.stringify({
|
||||
@ -108,7 +109,7 @@ add_task(async function check_menu_when_both_existed() {
|
||||
));
|
||||
|
||||
await setInput("#address-line1", "");
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
checkMenuEntries(MOCK_STORAGE.map(address =>
|
||||
JSON.stringify({
|
||||
@ -121,7 +122,7 @@ add_task(async function check_menu_when_both_existed() {
|
||||
// Display history search result if no matched data in addresses.
|
||||
add_task(async function check_fallback_for_mismatched_field() {
|
||||
await setInput("#email", "");
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
checkMenuEntries(["foo@mozilla.com"], false);
|
||||
});
|
||||
@ -133,7 +134,7 @@ add_task(async function check_search_result_for_pref_off() {
|
||||
});
|
||||
|
||||
await setInput("#tel", "");
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
checkMenuEntries(["+1234567890"], false);
|
||||
|
||||
@ -143,7 +144,7 @@ add_task(async function check_search_result_for_pref_off() {
|
||||
// Autofill the address from dropdown menu.
|
||||
add_task(async function check_fields_after_form_autofill() {
|
||||
const focusedInput = await setInput("#organization", "Moz");
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
checkMenuEntries(MOCK_STORAGE.map(address =>
|
||||
JSON.stringify({
|
||||
@ -151,16 +152,16 @@ add_task(async function check_fields_after_form_autofill() {
|
||||
secondary: FormAutofillUtils.toOneLineAddress(address["street-address"]),
|
||||
})
|
||||
).slice(1));
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await triggerAutofillAndCheckProfile(MOCK_STORAGE[1]);
|
||||
doKey("escape");
|
||||
synthesizeKey("KEY_Escape", {code: "Escape"});
|
||||
is(focusedInput.value, "Mozilla", "Filled field shouldn't be reverted by ESC key");
|
||||
});
|
||||
|
||||
// Fallback to history search after autofill address.
|
||||
add_task(async function check_fallback_after_form_autofill() {
|
||||
await setInput("#tel", "", true);
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
checkMenuEntries(["+1234567890"], false);
|
||||
});
|
||||
@ -170,7 +171,7 @@ add_task(async function check_form_autofill_resume() {
|
||||
document.querySelector("#tel").blur();
|
||||
document.querySelector("#form1").reset();
|
||||
await setInput("#tel", "");
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
checkMenuEntries(MOCK_STORAGE.map(address =>
|
||||
JSON.stringify({
|
||||
|
@ -4,6 +4,7 @@
|
||||
<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/EventUtils.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>
|
||||
@ -61,7 +62,7 @@ add_task(async function history_only_menu_checking() {
|
||||
await setupFormHistory();
|
||||
|
||||
await setInput("#cc-exp-year", "");
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
checkMenuEntries(["2023"], false);
|
||||
});
|
||||
@ -71,7 +72,7 @@ add_task(async function all_saved_fields_less_than_threshold() {
|
||||
await addCreditCard(reducedMockRecord);
|
||||
|
||||
await setInput("#cc-name", "");
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
checkMenuEntries([reducedMockRecord].map(patchRecordCCNumber).map(cc => JSON.stringify({
|
||||
primary: cc["cc-name"],
|
||||
@ -86,7 +87,7 @@ add_task(async function check_menu_when_both_existed() {
|
||||
await setupCreditCardStorage();
|
||||
|
||||
await setInput("#cc-number", "");
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
checkMenuEntries(MOCK_STORAGE.map(patchRecordCCNumber).map(cc => JSON.stringify({
|
||||
primaryAffix: cc.ccNumberFmt.affix,
|
||||
@ -95,7 +96,7 @@ add_task(async function check_menu_when_both_existed() {
|
||||
})));
|
||||
|
||||
await setInput("#cc-name", "");
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
checkMenuEntries(MOCK_STORAGE.map(patchRecordCCNumber).map(cc => JSON.stringify({
|
||||
primary: cc["cc-name"],
|
||||
@ -103,7 +104,7 @@ add_task(async function check_menu_when_both_existed() {
|
||||
})));
|
||||
|
||||
await setInput("#cc-exp-year", "");
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
checkMenuEntries(MOCK_STORAGE.map(patchRecordCCNumber).map(cc => JSON.stringify({
|
||||
primary: cc["cc-exp-year"],
|
||||
@ -111,7 +112,7 @@ add_task(async function check_menu_when_both_existed() {
|
||||
})));
|
||||
|
||||
await setInput("#cc-exp-month", "");
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
checkMenuEntries(MOCK_STORAGE.map(patchRecordCCNumber).map(cc => JSON.stringify({
|
||||
primary: cc["cc-exp-month"],
|
||||
@ -126,7 +127,7 @@ add_task(async function check_fallback_for_mismatched_field() {
|
||||
await addCreditCard(reducedMockRecord);
|
||||
|
||||
await setInput("#cc-exp-year", "");
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
checkMenuEntries(["2023"], false);
|
||||
|
||||
@ -142,7 +143,7 @@ add_task(async function check_search_result_for_pref_off() {
|
||||
});
|
||||
|
||||
await setInput("#cc-name", "");
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
checkMenuEntries(["John Smith"], false);
|
||||
|
||||
@ -153,21 +154,21 @@ add_task(async function check_search_result_for_pref_off() {
|
||||
add_task(async function check_fields_after_form_autofill() {
|
||||
await setInput("#cc-exp-year", 202);
|
||||
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
checkMenuEntries(MOCK_STORAGE.slice(1).map(patchRecordCCNumber).map(cc => JSON.stringify({
|
||||
primary: cc["cc-exp-year"],
|
||||
secondary: cc.ccNumberFmt.affix + cc.ccNumberFmt.label,
|
||||
})));
|
||||
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await triggerAutofillAndCheckProfile(MOCK_STORAGE[1]);
|
||||
});
|
||||
|
||||
// Fallback to history search after autofill address.
|
||||
add_task(async function check_fallback_after_form_autofill() {
|
||||
await setInput("#cc-name", "", true);
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
checkMenuEntries(["John Smith"], false);
|
||||
});
|
||||
@ -178,7 +179,7 @@ add_task(async function check_form_autofill_resume() {
|
||||
document.querySelector("#form1").reset();
|
||||
|
||||
await setInput("#cc-name", "");
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
checkMenuEntries(MOCK_STORAGE.map(patchRecordCCNumber).map(cc => JSON.stringify({
|
||||
primary: cc["cc-name"],
|
||||
|
@ -4,6 +4,7 @@
|
||||
<meta charset="utf-8">
|
||||
<title>Test form autofill - clear form button</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.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>
|
||||
@ -70,7 +71,7 @@ add_task(async function simple_clear() {
|
||||
await triggerAutofillAndCheckProfile(MOCK_ADDR_STORAGE[0]);
|
||||
|
||||
await triggerPopupAndHoverItem("#tel", 0);
|
||||
doKey("return");
|
||||
synthesizeKey("KEY_Enter", {code: "Enter"});
|
||||
checkIsFormCleared();
|
||||
});
|
||||
|
||||
@ -79,7 +80,7 @@ add_task(async function clear_adapted_record() {
|
||||
await triggerAutofillAndCheckProfile(MOCK_ADDR_STORAGE[0]);
|
||||
|
||||
await triggerPopupAndHoverItem("#street-address", 0);
|
||||
doKey("return");
|
||||
synthesizeKey("KEY_Enter", {code: "Enter"});
|
||||
checkIsFormCleared();
|
||||
});
|
||||
|
||||
@ -90,7 +91,7 @@ add_task(async function clear_modified_form() {
|
||||
await setInput("#tel", "+1111111111", true);
|
||||
|
||||
await triggerPopupAndHoverItem("#street-address", 0);
|
||||
doKey("return");
|
||||
synthesizeKey("KEY_Enter", {code: "Enter"});
|
||||
checkIsFormCleared({tel: "+1111111111"});
|
||||
});
|
||||
|
||||
@ -102,7 +103,7 @@ add_task(async function clear_distinct_section() {
|
||||
await triggerPopupAndHoverItem("#organization", 0);
|
||||
await triggerAutofillAndCheckProfile(MOCK_ADDR_STORAGE[0]);
|
||||
await triggerPopupAndHoverItem("#street-address", 0);
|
||||
doKey("return");
|
||||
synthesizeKey("KEY_Enter", {code: "Enter"});
|
||||
|
||||
for (const [id, val] of Object.entries(MOCK_CC_STORAGE[0])) {
|
||||
const element = document.getElementById(id);
|
||||
@ -114,7 +115,7 @@ add_task(async function clear_distinct_section() {
|
||||
}
|
||||
|
||||
await triggerPopupAndHoverItem("#cc-name", 0);
|
||||
doKey("return");
|
||||
synthesizeKey("KEY_Enter", {code: "Enter"});
|
||||
checkIsFormCleared();
|
||||
});
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
<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/EventUtils.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>
|
||||
@ -50,12 +51,12 @@ add_task(async function history_only_menu_checking() {
|
||||
await setupFormHistory();
|
||||
|
||||
await setInput("#cc-number", "");
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
checkMenuEntries(["1234000056780000"], false);
|
||||
|
||||
await setInput("#cc-name", "");
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await notExpectPopup();
|
||||
});
|
||||
|
||||
@ -64,7 +65,7 @@ add_task(async function check_menu_when_both_with_autocomplete_off() {
|
||||
await setupCreditCardStorage();
|
||||
|
||||
await setInput("#cc-number", "");
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
checkMenuEntries(MOCK_STORAGE.map(patchRecordCCNumber).map(cc => JSON.stringify({
|
||||
primaryAffix: cc.ccNumberFmt.affix,
|
||||
@ -73,7 +74,7 @@ add_task(async function check_menu_when_both_with_autocomplete_off() {
|
||||
})));
|
||||
|
||||
await setInput("#cc-name", "");
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
checkMenuEntries(MOCK_STORAGE.map(patchRecordCCNumber).map(cc => JSON.stringify({
|
||||
primary: cc["cc-name"],
|
||||
|
@ -4,6 +4,7 @@
|
||||
<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/EventUtils.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>
|
||||
@ -49,7 +50,7 @@ function addInputField(form, className) {
|
||||
async function checkFormChangeHappened(formId) {
|
||||
info("expecting form changed");
|
||||
await focusAndWaitForFieldsIdentified(`#${formId} input[name=tel]`);
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
checkMenuEntries(MOCK_STORAGE.map(address =>
|
||||
JSON.stringify({primary: address.tel, secondary: address.name})
|
||||
@ -59,7 +60,7 @@ async function checkFormChangeHappened(formId) {
|
||||
addInputField(document.querySelector(`#${formId}`), "address-level2");
|
||||
|
||||
await focusAndWaitForFieldsIdentified(`#${formId} input[name=name]`);
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
checkMenuEntries(MOCK_STORAGE.map(address =>
|
||||
JSON.stringify({primary: address.name, secondary: address["address-level2"]})
|
||||
@ -70,7 +71,7 @@ async function checkFormChangeHappened(formId) {
|
||||
addInputField(document.querySelector(`#${formId}`), "address-level2");
|
||||
|
||||
await focusAndWaitForFieldsIdentified(`#${formId} input[name=address-level2]`, true);
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
checkMenuEntries(MOCK_STORAGE.map(address =>
|
||||
JSON.stringify({primary: address["address-level2"], secondary: address.name})
|
||||
|
@ -4,6 +4,7 @@
|
||||
<meta charset="utf-8">
|
||||
<title>Test form autofill - preview and highlight</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.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>
|
||||
@ -54,22 +55,22 @@ add_task(async function setup_storage() {
|
||||
add_task(async function check_preview() {
|
||||
const focusedInput = await setInput("#organization", "");
|
||||
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
checkFormFieldsStyle(null);
|
||||
|
||||
for (let i = 0; i < MOCK_STORAGE.length; i++) {
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await notifySelectedIndex(i);
|
||||
checkFormFieldsStyle(MOCK_STORAGE[i]);
|
||||
}
|
||||
|
||||
// Navigate to the footer
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await notifySelectedIndex(MOCK_STORAGE.length);
|
||||
checkFormFieldsStyle(null);
|
||||
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await notifySelectedIndex(-1);
|
||||
checkFormFieldsStyle(null);
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
<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/EventUtils.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>
|
||||
@ -88,7 +89,7 @@ function checkFormFilled(selector, address) {
|
||||
promises.push(...checkElementFilled(element, converted));
|
||||
}
|
||||
}
|
||||
doKey("return");
|
||||
synthesizeKey("KEY_Enter", {code: "Enter"});
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
@ -105,19 +106,19 @@ add_task(async function autofill_with_level1_code() {
|
||||
await setupAddressStorage();
|
||||
|
||||
await setInput("#organization-en", "Mozilla Toronto");
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
// 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");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
// 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);
|
||||
@ -128,19 +129,19 @@ add_task(async function autofill_with_level1_code() {
|
||||
// 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");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
// 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");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
// 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);
|
||||
|
@ -33,19 +33,19 @@ add_task(async function setupStorage() {
|
||||
|
||||
add_task(async function check_switch_form_popup() {
|
||||
await setInput("#additional-name", "");
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
|
||||
// We need an intentional wait here before switching form.
|
||||
await sleep();
|
||||
await setInput("#organization", "");
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
const {open: popupOpen} = await getPopupState();
|
||||
is(popupOpen, false);
|
||||
|
||||
await sleep();
|
||||
await setInput("#given-name", "");
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
});
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
<meta charset="utf-8">
|
||||
<title>Test autofill submit</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.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>
|
||||
@ -72,7 +73,7 @@ add_task(async function check_storage_after_another_address_submitted() {
|
||||
ok(matching, "New address saved as expected");
|
||||
|
||||
await setInput("#organization", "");
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
checkMenuEntries(addressesInMenu.map(address =>
|
||||
JSON.stringify({primary: address.organization, secondary: address["street-address"]})
|
||||
@ -107,10 +108,10 @@ add_task(async function check_storage_after_form_submitted() {
|
||||
TEST_ADDRESSES[1].country = "US";
|
||||
|
||||
await setInput("#organization", "Moz");
|
||||
doKey("down");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
await expectPopup();
|
||||
doKey("down");
|
||||
doKey("return");
|
||||
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
|
||||
synthesizeKey("KEY_Enter", {code: "Enter"});
|
||||
clickOnElement("input[type=submit]");
|
||||
|
||||
let expectedAddresses = TEST_ADDRESSES.slice(0);
|
||||
|
@ -694,7 +694,6 @@
|
||||
#endif
|
||||
@RESPATH@/res/fonts/*
|
||||
@RESPATH@/res/dtd/*
|
||||
@RESPATH@/res/html/*
|
||||
@RESPATH@/res/language.properties
|
||||
#ifdef XP_MACOSX
|
||||
@RESPATH@/res/MainMenu.nib/
|
||||
|
@ -119,6 +119,8 @@ this.SchedulePressure = {
|
||||
map.delete(window);
|
||||
}
|
||||
}
|
||||
|
||||
TelemetryStopwatch.cancel("FX_SCHEDULE_PRESSURE_IDLE_SAMPLE_MS", window);
|
||||
removeFromMapAndCancelTimeout(this._setTimeoutWeakMap, window.clearTimeout);
|
||||
removeFromMapAndCancelTimeout(this._idleCallbackWeakMap, window.cancelIdleCallback);
|
||||
removeFromMapAndCancelTimeout(this._telemetryCallbackWeakMap, window.cancelIdleCallback);
|
||||
|
@ -56,8 +56,10 @@
|
||||
#cookiesChildren::-moz-tree-image(domainCol) {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin: 0px 2px;
|
||||
margin: 0 2px;
|
||||
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.svg");
|
||||
-moz-context-properties: fill;
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
#linksOpenInBox {
|
||||
|
@ -81,6 +81,8 @@ treechildren::-moz-tree-image(noicon) {
|
||||
|
||||
treechildren::-moz-tree-image(noicon) {
|
||||
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.svg");
|
||||
-moz-context-properties: fill;
|
||||
fill: currentColor;
|
||||
}
|
||||
treechildren::-moz-tree-image(container, noicon) {
|
||||
list-style-image: url("chrome://browser/skin/aboutSessionRestore-window-icon.png");
|
||||
|
@ -27,6 +27,8 @@ treechildren::-moz-tree-image(noicon) {
|
||||
|
||||
treechildren::-moz-tree-image(noicon) {
|
||||
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.svg");
|
||||
-moz-context-properties: fill;
|
||||
fill: currentColor;
|
||||
}
|
||||
treechildren::-moz-tree-image(container, noicon) {
|
||||
list-style-image: url("chrome://browser/skin/aboutSessionRestore-window-icon.png");
|
||||
|
@ -1121,6 +1121,8 @@ menuitem.panel-subview-footer@menuStateActive@,
|
||||
#PanelUI-remotetabs-tabslist > toolbarbutton[itemtype="tab"],
|
||||
#PanelUI-historyItems > toolbarbutton {
|
||||
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.svg");
|
||||
-moz-context-properties: fill;
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
#appMenu-fxa-avatar,
|
||||
|
@ -2,6 +2,12 @@
|
||||
* 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/. */
|
||||
|
||||
treechildren:-moz-tree-image {
|
||||
-moz-context-properties: fill, fill-opacity;
|
||||
fill: -moz-FieldText;
|
||||
fill-opacity: 0.7;
|
||||
}
|
||||
|
||||
treechildren::-moz-tree-image(title) {
|
||||
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.svg");
|
||||
padding-inline-end: 2px;
|
||||
@ -10,12 +16,6 @@ treechildren::-moz-tree-image(title) {
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
treechildren:-moz-tree-image {
|
||||
-moz-context-properties: fill, fill-opacity;
|
||||
fill: -moz-FieldText;
|
||||
fill-opacity: 0.7;
|
||||
}
|
||||
|
||||
treechildren::-moz-tree-image(title, livemarkItem) {
|
||||
list-style-image: url("chrome://browser/skin/places/livemark-item.png");
|
||||
-moz-image-region: rect(0px, 16px, 16px, 0px);
|
||||
|
@ -6,6 +6,8 @@
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.svg");
|
||||
-moz-context-properties: fill;
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -110,6 +110,8 @@ body {
|
||||
|
||||
.item.tab > .item-title-container > .item-icon-container {
|
||||
background-image: url("chrome://mozapps/skin/places/defaultFavicon.svg");
|
||||
-moz-context-properties: fill;
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
.item-icon-container {
|
||||
|
@ -233,9 +233,6 @@ tabbrowser {
|
||||
|
||||
.tab-icon-image {
|
||||
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.svg");
|
||||
}
|
||||
|
||||
.tab-icon-image[src^="chrome://"] {
|
||||
-moz-context-properties: fill;
|
||||
fill: currentColor;
|
||||
}
|
||||
@ -703,6 +700,8 @@ tabbrowser {
|
||||
|
||||
.alltabs-item > .menu-iconic-left > .menu-iconic-icon {
|
||||
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.svg");
|
||||
-moz-context-properties: fill;
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
.alltabs-item[busy] > .menu-iconic-left > .menu-iconic-icon {
|
||||
|
@ -63,11 +63,13 @@
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin: 0 2px;
|
||||
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.svg") !important;
|
||||
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.svg");
|
||||
-moz-context-properties: fill;
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
#cookiesChildren::-moz-tree-image(domainCol, container) {
|
||||
list-style-image: url("chrome://global/skin/icons/folder-item.png") !important;
|
||||
list-style-image: url("chrome://global/skin/icons/folder-item.png");
|
||||
-moz-image-region: rect(0, 32px, 16px, 16px);
|
||||
}
|
||||
|
||||
|
@ -179,12 +179,6 @@ endif
|
||||
|
||||
TAR_CREATE_FLAGS = -chf
|
||||
|
||||
#
|
||||
# Personal makefile customizations go in these optional make include files.
|
||||
#
|
||||
MY_CONFIG := $(DEPTH)/config/myconfig.mk
|
||||
MY_RULES := $(DEPTH)/config/myrules.mk
|
||||
|
||||
#
|
||||
# Default command macros; can be overridden in <arch>.mk.
|
||||
#
|
||||
@ -296,11 +290,7 @@ endif
|
||||
endif
|
||||
endif
|
||||
|
||||
#
|
||||
# Include any personal overrides the user might think are needed.
|
||||
#
|
||||
-include $(topsrcdir)/$(MOZ_BUILD_APP)/app-config.mk
|
||||
-include $(MY_CONFIG)
|
||||
|
||||
######################################################################
|
||||
|
||||
|
@ -1341,23 +1341,6 @@ ifneq (,$(MDDEPEND_FILES))
|
||||
-include $(MDDEPEND_FILES)
|
||||
endif
|
||||
|
||||
#############################################################################
|
||||
|
||||
-include $(topsrcdir)/$(MOZ_BUILD_APP)/app-rules.mk
|
||||
-include $(MY_RULES)
|
||||
|
||||
#
|
||||
# Generate Emacs tags in a file named TAGS if ETAGS was set in $(MY_CONFIG)
|
||||
# or in $(MY_RULES)
|
||||
#
|
||||
ifdef ETAGS
|
||||
ifneq ($(CSRCS)$(CPPSRCS)$(HEADERS),)
|
||||
all:: TAGS
|
||||
TAGS:: $(CSRCS) $(CPPSRCS) $(HEADERS)
|
||||
$(ETAGS) $(CSRCS) $(CPPSRCS) $(HEADERS)
|
||||
endif
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
# Install/copy rules
|
||||
#
|
||||
@ -1586,15 +1569,6 @@ CHECK_FROZEN_VARIABLES = $(foreach var,$(FREEZE_VARIABLES), \
|
||||
libs export::
|
||||
$(CHECK_FROZEN_VARIABLES)
|
||||
|
||||
PURGECACHES_DIRS ?= $(DIST)/bin
|
||||
|
||||
PURGECACHES_FILES = $(addsuffix /.purgecaches,$(PURGECACHES_DIRS))
|
||||
|
||||
default all:: $(PURGECACHES_FILES)
|
||||
|
||||
$(PURGECACHES_FILES):
|
||||
if test -d $(@D) ; then touch $@ ; fi
|
||||
|
||||
.DEFAULT_GOAL := $(or $(OVERRIDE_DEFAULT_GOAL),default)
|
||||
|
||||
#############################################################################
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -123,9 +123,9 @@ extern "C" {
|
||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||
** [sqlite_version()] and [sqlite_source_id()].
|
||||
*/
|
||||
#define SQLITE_VERSION "3.21.0"
|
||||
#define SQLITE_VERSION_NUMBER 3021000
|
||||
#define SQLITE_SOURCE_ID "2017-10-24 18:55:49 1a584e499906b5c87ec7d43d4abce641fdf017c42125b083109bc77c4de48827"
|
||||
#define SQLITE_VERSION "3.22.0"
|
||||
#define SQLITE_VERSION_NUMBER 3022000
|
||||
#define SQLITE_SOURCE_ID "2018-01-22 18:45:57 0c55d179733b46d8d0ba4d88e01a25e10677046ee3da1d5b1581e86726f2171d"
|
||||
|
||||
/*
|
||||
** CAPI3REF: Run-Time Library Version Numbers
|
||||
@ -470,6 +470,8 @@ SQLITE_API int sqlite3_exec(
|
||||
** the most recent error can be obtained using
|
||||
** [sqlite3_extended_errcode()].
|
||||
*/
|
||||
#define SQLITE_ERROR_MISSING_COLLSEQ (SQLITE_ERROR | (1<<8))
|
||||
#define SQLITE_ERROR_RETRY (SQLITE_ERROR | (2<<8))
|
||||
#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8))
|
||||
#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8))
|
||||
#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8))
|
||||
@ -513,6 +515,8 @@ SQLITE_API int sqlite3_exec(
|
||||
#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
|
||||
#define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8))
|
||||
#define SQLITE_READONLY_DBMOVED (SQLITE_READONLY | (4<<8))
|
||||
#define SQLITE_READONLY_CANTINIT (SQLITE_READONLY | (5<<8))
|
||||
#define SQLITE_READONLY_DIRECTORY (SQLITE_READONLY | (6<<8))
|
||||
#define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8))
|
||||
#define SQLITE_CONSTRAINT_CHECK (SQLITE_CONSTRAINT | (1<<8))
|
||||
#define SQLITE_CONSTRAINT_COMMITHOOK (SQLITE_CONSTRAINT | (2<<8))
|
||||
@ -1131,12 +1135,18 @@ typedef struct sqlite3_api_routines sqlite3_api_routines;
|
||||
** in the name of the object stands for "virtual file system". See
|
||||
** the [VFS | VFS documentation] for further information.
|
||||
**
|
||||
** The value of the iVersion field is initially 1 but may be larger in
|
||||
** future versions of SQLite. Additional fields may be appended to this
|
||||
** object when the iVersion value is increased. Note that the structure
|
||||
** of the sqlite3_vfs object changes in the transaction between
|
||||
** SQLite version 3.5.9 and 3.6.0 and yet the iVersion field was not
|
||||
** modified.
|
||||
** The VFS interface is sometimes extended by adding new methods onto
|
||||
** the end. Each time such an extension occurs, the iVersion field
|
||||
** is incremented. The iVersion value started out as 1 in
|
||||
** SQLite [version 3.5.0] on [dateof:3.5.0], then increased to 2
|
||||
** with SQLite [version 3.7.0] on [dateof:3.7.0], and then increased
|
||||
** to 3 with SQLite [version 3.7.6] on [dateof:3.7.6]. Additional fields
|
||||
** may be appended to the sqlite3_vfs object and the iVersion value
|
||||
** may increase again in future versions of SQLite.
|
||||
** Note that the structure
|
||||
** of the sqlite3_vfs object changes in the transition from
|
||||
** SQLite [version 3.5.9] to [version 3.6.0] on [dateof:3.6.0]
|
||||
** and yet the iVersion field was not modified.
|
||||
**
|
||||
** The szOsFile field is the size of the subclassed [sqlite3_file]
|
||||
** structure used by this VFS. mxPathname is the maximum length of
|
||||
@ -2049,7 +2059,6 @@ struct sqlite3_mem_methods {
|
||||
** into which is written 0 or 1 to indicate whether checkpoints-on-close
|
||||
** have been disabled - 0 if they are not disabled, 1 if they are.
|
||||
** </dd>
|
||||
**
|
||||
** <dt>SQLITE_DBCONFIG_ENABLE_QPSG</dt>
|
||||
** <dd>^(The SQLITE_DBCONFIG_ENABLE_QPSG option activates or deactivates
|
||||
** the [query planner stability guarantee] (QPSG). When the QPSG is active,
|
||||
@ -2060,7 +2069,16 @@ struct sqlite3_mem_methods {
|
||||
** the QPSG active, SQLite will always use the same query plan in the field as
|
||||
** was used during testing in the lab.
|
||||
** </dd>
|
||||
**
|
||||
** <dt>SQLITE_DBCONFIG_TRIGGER_EQP</dt>
|
||||
** <dd> By default, the output of EXPLAIN QUERY PLAN commands does not
|
||||
** include output for any operations performed by trigger programs. This
|
||||
** option is used to set or clear (the default) a flag that governs this
|
||||
** behavior. The first parameter passed to this operation is an integer -
|
||||
** non-zero to enable output for trigger programs, or zero to disable it.
|
||||
** The second parameter is a pointer to an integer into which is written
|
||||
** 0 or 1 to indicate whether output-for-triggers has been disabled - 0 if
|
||||
** it is not disabled, 1 if it is.
|
||||
** </dd>
|
||||
** </dl>
|
||||
*/
|
||||
#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */
|
||||
@ -2071,7 +2089,8 @@ struct sqlite3_mem_methods {
|
||||
#define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */
|
||||
#define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */
|
||||
#define SQLITE_DBCONFIG_ENABLE_QPSG 1007 /* int int* */
|
||||
|
||||
#define SQLITE_DBCONFIG_TRIGGER_EQP 1008 /* int int* */
|
||||
#define SQLITE_DBCONFIG_MAX 1008 /* Largest DBCONFIG */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Enable Or Disable Extended Result Codes
|
||||
@ -2932,8 +2951,8 @@ SQLITE_API SQLITE_DEPRECATED void *sqlite3_profile(sqlite3*,
|
||||
** KEYWORDS: SQLITE_TRACE
|
||||
**
|
||||
** These constants identify classes of events that can be monitored
|
||||
** using the [sqlite3_trace_v2()] tracing logic. The third argument
|
||||
** to [sqlite3_trace_v2()] is an OR-ed combination of one or more of
|
||||
** using the [sqlite3_trace_v2()] tracing logic. The M argument
|
||||
** to [sqlite3_trace_v2(D,M,X,P)] is an OR-ed combination of one or more of
|
||||
** the following constants. ^The first argument to the trace callback
|
||||
** is one of the following constants.
|
||||
**
|
||||
@ -4779,6 +4798,9 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
|
||||
** datatype of the value
|
||||
** <tr><td><b>sqlite3_value_numeric_type </b>
|
||||
** <td>→ <td>Best numeric datatype of the value
|
||||
** <tr><td><b>sqlite3_value_nochange </b>
|
||||
** <td>→ <td>True if the column is unchanged in an UPDATE
|
||||
** against a virtual table.
|
||||
** </table></blockquote>
|
||||
**
|
||||
** <b>Details:</b>
|
||||
@ -4827,6 +4849,19 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
|
||||
** then the conversion is performed. Otherwise no conversion occurs.
|
||||
** The [SQLITE_INTEGER | datatype] after conversion is returned.)^
|
||||
**
|
||||
** ^Within the [xUpdate] method of a [virtual table], the
|
||||
** sqlite3_value_nochange(X) interface returns true if and only if
|
||||
** the column corresponding to X is unchanged by the UPDATE operation
|
||||
** that the xUpdate method call was invoked to implement and if
|
||||
** and the prior [xColumn] method call that was invoked to extracted
|
||||
** the value for that column returned without setting a result (probably
|
||||
** because it queried [sqlite3_vtab_nochange()] and found that the column
|
||||
** was unchanging). ^Within an [xUpdate] method, any value for which
|
||||
** sqlite3_value_nochange(X) is true will in all other respects appear
|
||||
** to be a NULL value. If sqlite3_value_nochange(X) is invoked anywhere other
|
||||
** than within an [xUpdate] method call for an UPDATE statement, then
|
||||
** the return value is arbitrary and meaningless.
|
||||
**
|
||||
** Please pay particular attention to the fact that the pointer returned
|
||||
** from [sqlite3_value_blob()], [sqlite3_value_text()], or
|
||||
** [sqlite3_value_text16()] can be invalidated by a subsequent call to
|
||||
@ -4849,6 +4884,7 @@ SQLITE_API int sqlite3_value_bytes(sqlite3_value*);
|
||||
SQLITE_API int sqlite3_value_bytes16(sqlite3_value*);
|
||||
SQLITE_API int sqlite3_value_type(sqlite3_value*);
|
||||
SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*);
|
||||
SQLITE_API int sqlite3_value_nochange(sqlite3_value*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Finding The Subtype Of SQL Values
|
||||
@ -6951,9 +6987,9 @@ SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*);
|
||||
** the xFileControl method. ^The return value of the xFileControl
|
||||
** method becomes the return value of this routine.
|
||||
**
|
||||
** ^The SQLITE_FCNTL_FILE_POINTER value for the op parameter causes
|
||||
** ^The [SQLITE_FCNTL_FILE_POINTER] value for the op parameter causes
|
||||
** a pointer to the underlying [sqlite3_file] object to be written into
|
||||
** the space pointed to by the 4th parameter. ^The SQLITE_FCNTL_FILE_POINTER
|
||||
** the space pointed to by the 4th parameter. ^The [SQLITE_FCNTL_FILE_POINTER]
|
||||
** case is a short-circuit path which does not actually invoke the
|
||||
** underlying sqlite3_io_methods.xFileControl method.
|
||||
**
|
||||
@ -6965,7 +7001,7 @@ SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*);
|
||||
** an incorrect zDbName and an SQLITE_ERROR return from the underlying
|
||||
** xFileControl method.
|
||||
**
|
||||
** See also: [SQLITE_FCNTL_LOCKSTATE]
|
||||
** See also: [file control opcodes]
|
||||
*/
|
||||
SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*);
|
||||
|
||||
@ -7022,7 +7058,8 @@ SQLITE_API int sqlite3_test_control(int op, ...);
|
||||
#define SQLITE_TESTCTRL_ISINIT 23
|
||||
#define SQLITE_TESTCTRL_SORTER_MMAP 24
|
||||
#define SQLITE_TESTCTRL_IMPOSTER 25
|
||||
#define SQLITE_TESTCTRL_LAST 25
|
||||
#define SQLITE_TESTCTRL_PARSER_COVERAGE 26
|
||||
#define SQLITE_TESTCTRL_LAST 26 /* Largest TESTCTRL */
|
||||
|
||||
/*
|
||||
** CAPI3REF: SQLite Runtime Status
|
||||
@ -8276,6 +8313,40 @@ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
|
||||
*/
|
||||
SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Determine If Virtual Table Column Access Is For UPDATE
|
||||
**
|
||||
** If the sqlite3_vtab_nochange(X) routine is called within the [xColumn]
|
||||
** method of a [virtual table], then it returns true if and only if the
|
||||
** column is being fetched as part of an UPDATE operation during which the
|
||||
** column value will not change. Applications might use this to substitute
|
||||
** a lighter-weight value to return that the corresponding [xUpdate] method
|
||||
** understands as a "no-change" value.
|
||||
**
|
||||
** If the [xColumn] method calls sqlite3_vtab_nochange() and finds that
|
||||
** the column is not changed by the UPDATE statement, they the xColumn
|
||||
** method can optionally return without setting a result, without calling
|
||||
** any of the [sqlite3_result_int|sqlite3_result_xxxxx() interfaces].
|
||||
** In that case, [sqlite3_value_nochange(X)] will return true for the
|
||||
** same column in the [xUpdate] method.
|
||||
*/
|
||||
SQLITE_API int sqlite3_vtab_nochange(sqlite3_context*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Determine The Collation For a Virtual Table Constraint
|
||||
**
|
||||
** This function may only be called from within a call to the [xBestIndex]
|
||||
** method of a [virtual table].
|
||||
**
|
||||
** The first argument must be the sqlite3_index_info object that is the
|
||||
** first parameter to the xBestIndex() method. The second argument must be
|
||||
** an index into the aConstraint[] array belonging to the sqlite3_index_info
|
||||
** structure passed to xBestIndex. This function returns a pointer to a buffer
|
||||
** containing the name of the collation sequence for the corresponding
|
||||
** constraint.
|
||||
*/
|
||||
SQLITE_API SQLITE_EXPERIMENTAL const char *sqlite3_vtab_collation(sqlite3_index_info*,int);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Conflict resolution modes
|
||||
** KEYWORDS: {conflict resolution mode}
|
||||
@ -9003,6 +9074,35 @@ SQLITE_API int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect)
|
||||
**
|
||||
** SQLITE_OK is returned if the call completes without error. Or, if an error
|
||||
** occurs, an SQLite error code (e.g. SQLITE_NOMEM) is returned.
|
||||
**
|
||||
** <h3>Special sqlite_stat1 Handling</h3>
|
||||
**
|
||||
** As of SQLite version 3.22.0, the "sqlite_stat1" table is an exception to
|
||||
** some of the rules above. In SQLite, the schema of sqlite_stat1 is:
|
||||
** <pre>
|
||||
** CREATE TABLE sqlite_stat1(tbl,idx,stat)
|
||||
** </pre>
|
||||
**
|
||||
** Even though sqlite_stat1 does not have a PRIMARY KEY, changes are
|
||||
** recorded for it as if the PRIMARY KEY is (tbl,idx). Additionally, changes
|
||||
** are recorded for rows for which (idx IS NULL) is true. However, for such
|
||||
** rows a zero-length blob (SQL value X'') is stored in the changeset or
|
||||
** patchset instead of a NULL value. This allows such changesets to be
|
||||
** manipulated by legacy implementations of sqlite3changeset_invert(),
|
||||
** concat() and similar.
|
||||
**
|
||||
** The sqlite3changeset_apply() function automatically converts the
|
||||
** zero-length blob back to a NULL value when updating the sqlite_stat1
|
||||
** table. However, if the application calls sqlite3changeset_new(),
|
||||
** sqlite3changeset_old() or sqlite3changeset_conflict on a changeset
|
||||
** iterator directly (including on a changeset iterator passed to a
|
||||
** conflict-handler callback) then the X'' value is returned. The application
|
||||
** must translate X'' to NULL itself if required.
|
||||
**
|
||||
** Legacy (older than 3.22.0) versions of the sessions module cannot capture
|
||||
** changes made to the sqlite_stat1 table. Legacy versions of the
|
||||
** sqlite3changeset_apply() function silently ignore any modifications to the
|
||||
** sqlite_stat1 table that are part of a changeset or patchset.
|
||||
*/
|
||||
SQLITE_API int sqlite3session_attach(
|
||||
sqlite3_session *pSession, /* Session object */
|
||||
|
@ -2579,18 +2579,6 @@ Toolbox.prototype = {
|
||||
// in the initialization process can throw errors.
|
||||
yield this._initInspector;
|
||||
|
||||
// Releasing the walker (if it has been created)
|
||||
// This can fail, but in any case, we want to continue destroying the
|
||||
// inspector/highlighter/selection
|
||||
// FF42+: Inspector actor starts managing Walker actor and auto destroy it.
|
||||
if (this._walker && !this.walker.traits.autoReleased) {
|
||||
try {
|
||||
yield this._walker.release();
|
||||
} catch (e) {
|
||||
// Do nothing;
|
||||
}
|
||||
}
|
||||
|
||||
yield this.highlighterUtils.stopPicker();
|
||||
yield this._inspector.destroy();
|
||||
if (this._highlighter) {
|
||||
|
@ -186,6 +186,7 @@ skip-if = e10s # Bug 1036409 - The last selected node isn't reselected
|
||||
[browser_markup_toggle_01.js]
|
||||
[browser_markup_toggle_02.js]
|
||||
[browser_markup_toggle_03.js]
|
||||
[browser_markup_toggle_closing_tag_line.js]
|
||||
[browser_markup_update-on-navigtion.js]
|
||||
[browser_markup_void_elements_html.js]
|
||||
[browser_markup_void_elements_xhtml.js]
|
||||
|
@ -0,0 +1,45 @@
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that a closing tag line is displayed when expanding an element container.
|
||||
// Also check that no closing tag line is displayed for readonly containers (document,
|
||||
// roots...).
|
||||
|
||||
const TEST_URL = `data:text/html;charset=utf8,
|
||||
<div class="outer-div"><span>test</span></div>
|
||||
<iframe src="data:text/html;charset=utf8,<div>test</div>"></iframe>`;
|
||||
|
||||
add_task(async function () {
|
||||
let {inspector} = await openInspectorForURL(TEST_URL);
|
||||
|
||||
info("Getting the container for .outer-div parent element");
|
||||
let container = await getContainerForSelector(".outer-div", inspector);
|
||||
await expandContainer(inspector, container);
|
||||
|
||||
let closeTagLine = container.closeTagLine;
|
||||
ok(closeTagLine && closeTagLine.textContent.includes("div"),
|
||||
"DIV has a close tag-line with the correct content");
|
||||
|
||||
info("Expand the iframe element");
|
||||
container = await getContainerForSelector("iframe", inspector);
|
||||
await expandContainer(inspector, container);
|
||||
ok(container.expanded, "iframe is expanded");
|
||||
closeTagLine = container.closeTagLine;
|
||||
ok(closeTagLine && closeTagLine.textContent.includes("iframe"),
|
||||
"IFRAME has a close tag-line with the correct content");
|
||||
|
||||
info("Retrieve the nodefront for the #document root inside the iframe");
|
||||
let iframe = await getNodeFront("iframe", inspector);
|
||||
let {nodes} = await inspector.walker.children(iframe);
|
||||
let documentFront = nodes[0];
|
||||
ok(documentFront.displayName === "#document", "First child of IFRAME is #document");
|
||||
|
||||
info("Expand the iframe's #document node element");
|
||||
container = getContainerForNodeFront(documentFront, inspector);
|
||||
await expandContainer(inspector, container);
|
||||
ok(container.expanded, "#document is expanded");
|
||||
ok(!container.closeTagLine, "readonly (#document) node has no close tag-line");
|
||||
});
|
@ -634,3 +634,16 @@ function* checkDeleteAndSelection(inspector, key, {selector, focusedSelector, ps
|
||||
node = yield getNodeFront(selector, inspector);
|
||||
ok(node, "The node is back");
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand the provided markup container by clicking on the expand arrow and waiting for
|
||||
* inspector and children to update.
|
||||
*/
|
||||
async function expandContainer(inspector, container) {
|
||||
let onChildren = waitForChildrenUpdated(inspector);
|
||||
let onUpdated = inspector.once("inspector-updated");
|
||||
EventUtils.synthesizeMouseAtCenter(container.expander, {},
|
||||
inspector.markup.doc.defaultView);
|
||||
await onChildren;
|
||||
await onUpdated;
|
||||
}
|
||||
|
@ -11,6 +11,12 @@ const {flashElementOn, flashElementOff} =
|
||||
|
||||
const DRAG_DROP_MIN_INITIAL_DISTANCE = 10;
|
||||
|
||||
const TYPES = {
|
||||
TEXT_CONTAINER: "textcontainer",
|
||||
ELEMENT_CONTAINER: "elementcontainer",
|
||||
READ_ONLY_CONTAINER: "readonlycontainer",
|
||||
};
|
||||
|
||||
/**
|
||||
* The main structure for storing a document node in the markup
|
||||
* tree. Manages creation of the editor for the node and
|
||||
@ -40,18 +46,19 @@ MarkupContainer.prototype = {
|
||||
* @param {NodeFront} node
|
||||
* The node to display.
|
||||
* @param {String} type
|
||||
* The type of container to build. This can be either 'textcontainer',
|
||||
* 'readonlycontainer' or 'elementcontainer'.
|
||||
* The type of container to build. One of TYPES.TEXT_CONTAINER,
|
||||
* TYPES.ELEMENT_CONTAINER, TYPES.READ_ONLY_CONTAINER
|
||||
*/
|
||||
initialize: function (markupView, node, type) {
|
||||
this.markup = markupView;
|
||||
this.node = node;
|
||||
this.type = type;
|
||||
this.undo = this.markup.undo;
|
||||
this.win = this.markup._frame.contentWindow;
|
||||
this.id = "treeitem-" + markupContainerID++;
|
||||
this.htmlElt = this.win.document.documentElement;
|
||||
|
||||
this.buildMarkup(type);
|
||||
this.buildMarkup();
|
||||
|
||||
this.elt.container = this;
|
||||
|
||||
@ -70,7 +77,7 @@ MarkupContainer.prototype = {
|
||||
this.updateIsDisplayed();
|
||||
},
|
||||
|
||||
buildMarkup: function (type) {
|
||||
buildMarkup: function () {
|
||||
this.elt = this.win.document.createElement("li");
|
||||
this.elt.classList.add("child", "collapsed");
|
||||
this.elt.setAttribute("role", "presentation");
|
||||
@ -88,7 +95,7 @@ MarkupContainer.prototype = {
|
||||
this.tagState.setAttribute("role", "presentation");
|
||||
this.tagLine.appendChild(this.tagState);
|
||||
|
||||
if (type !== "textcontainer") {
|
||||
if (this.type !== TYPES.TEXT_CONTAINER) {
|
||||
this.expander = this.win.document.createElement("span");
|
||||
this.expander.classList.add("theme-twisty", "expander");
|
||||
this.expander.setAttribute("role", "presentation");
|
||||
@ -303,51 +310,79 @@ MarkupContainer.prototype = {
|
||||
if (!this.canExpand) {
|
||||
value = false;
|
||||
}
|
||||
|
||||
if (this.mustExpand) {
|
||||
value = true;
|
||||
}
|
||||
|
||||
if (value && this.elt.classList.contains("collapsed")) {
|
||||
// Expanding a node means cloning its "inline" closing tag into a new
|
||||
// tag-line that the user can interact with and showing the children.
|
||||
let closingTag = this.elt.querySelector(".close");
|
||||
if (closingTag) {
|
||||
if (!this.closeTagLine) {
|
||||
let line = this.markup.doc.createElement("div");
|
||||
line.classList.add("tag-line");
|
||||
// Closing tag is not important for accessibility.
|
||||
line.setAttribute("role", "presentation");
|
||||
|
||||
let tagState = this.markup.doc.createElement("div");
|
||||
tagState.classList.add("tag-state");
|
||||
line.appendChild(tagState);
|
||||
|
||||
line.appendChild(closingTag.cloneNode(true));
|
||||
|
||||
flashElementOff(line);
|
||||
this.closeTagLine = line;
|
||||
}
|
||||
this.elt.appendChild(this.closeTagLine);
|
||||
}
|
||||
this.showCloseTagLine();
|
||||
|
||||
this.elt.classList.remove("collapsed");
|
||||
this.expander.setAttribute("open", "");
|
||||
this.hovered = false;
|
||||
this.markup.emit("expanded");
|
||||
} else if (!value) {
|
||||
if (this.closeTagLine) {
|
||||
this.elt.removeChild(this.closeTagLine);
|
||||
this.closeTagLine = undefined;
|
||||
}
|
||||
this.hideCloseTagLine();
|
||||
|
||||
this.elt.classList.add("collapsed");
|
||||
this.expander.removeAttribute("open");
|
||||
this.markup.emit("collapsed");
|
||||
}
|
||||
|
||||
if (this.showExpander) {
|
||||
this.tagLine.setAttribute("aria-expanded", this.expanded);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Expanding a node means cloning its "inline" closing tag into a new
|
||||
* tag-line that the user can interact with and showing the children.
|
||||
*/
|
||||
showCloseTagLine: function () {
|
||||
// Only element containers display a closing tag line. #document has no closing line.
|
||||
if (this.type !== TYPES.ELEMENT_CONTAINER) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Retrieve the closest .close node for this container.
|
||||
let closingTag = this.elt.querySelector(".close");
|
||||
if (!closingTag) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the closing tag-line element if not already created.
|
||||
if (!this.closeTagLine) {
|
||||
let line = this.markup.doc.createElement("div");
|
||||
line.classList.add("tag-line");
|
||||
// Closing tag is not important for accessibility.
|
||||
line.setAttribute("role", "presentation");
|
||||
|
||||
let tagState = this.markup.doc.createElement("div");
|
||||
tagState.classList.add("tag-state");
|
||||
line.appendChild(tagState);
|
||||
|
||||
line.appendChild(closingTag.cloneNode(true));
|
||||
|
||||
flashElementOff(line);
|
||||
this.closeTagLine = line;
|
||||
}
|
||||
this.elt.appendChild(this.closeTagLine);
|
||||
},
|
||||
|
||||
/**
|
||||
* Hide the closing tag-line element which should only be displayed when the container
|
||||
* is expanded.
|
||||
*/
|
||||
hideCloseTagLine: function () {
|
||||
if (!this.closeTagLine) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.elt.removeChild(this.closeTagLine);
|
||||
this.closeTagLine = undefined;
|
||||
},
|
||||
|
||||
parentContainer: function () {
|
||||
return this.elt.parentNode ? this.elt.parentNode.container : null;
|
||||
},
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
const { Cc, Ci, Cu } = require("chrome");
|
||||
const {
|
||||
getRect, getElementFromPoint, getAdjustedQuads, getWindowDimensions
|
||||
getRect, getAdjustedQuads, getWindowDimensions
|
||||
} = require("devtools/shared/layout/utils");
|
||||
const defer = require("devtools/shared/defer");
|
||||
const {Task} = require("devtools/shared/task");
|
||||
@ -125,16 +125,6 @@ var testSpec = protocol.generateActorSpec({
|
||||
},
|
||||
response: {}
|
||||
},
|
||||
assertElementAtPoint: {
|
||||
request: {
|
||||
x: Arg(0, "number"),
|
||||
y: Arg(1, "number"),
|
||||
selector: Arg(2, "string")
|
||||
},
|
||||
response: {
|
||||
value: RetVal("boolean")
|
||||
}
|
||||
},
|
||||
getAllAdjustedQuads: {
|
||||
request: {
|
||||
selector: Arg(0, "string")
|
||||
@ -473,15 +463,6 @@ var TestActor = exports.TestActor = protocol.ActorClassWithSpec(testSpec, {
|
||||
});
|
||||
},
|
||||
|
||||
assertElementAtPoint: function (x, y, selector) {
|
||||
let elementAtPoint = getElementFromPoint(this.content.document, x, y);
|
||||
if (!elementAtPoint) {
|
||||
throw new Error("Unable to find element at (" + x + ", " + y + ")");
|
||||
}
|
||||
let node = this._querySelector(selector);
|
||||
return node == elementAtPoint;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get all box-model regions' adjusted boxquads for the given element
|
||||
* @param {String} selector The node selector to target a given element
|
||||
|
@ -189,18 +189,7 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
|
||||
return {
|
||||
actor: this.actorID,
|
||||
root: this.rootNode.form(),
|
||||
traits: {
|
||||
// FF42+ Inspector starts managing the Walker, while the inspector also
|
||||
// starts cleaning itself up automatically on client disconnection.
|
||||
// So that there is no need to manually release the walker anymore.
|
||||
autoReleased: true,
|
||||
// XXX: It seems silly that we need to tell the front which capabilities
|
||||
// its actor has in this way when the target can use actorHasMethod. If
|
||||
// this was ported to the protocol (Bug 1157048) we could call that
|
||||
// inside of custom front methods and not need to do traits for this.
|
||||
multiFrameQuerySelectorAll: true,
|
||||
textSearch: true,
|
||||
}
|
||||
traits: {}
|
||||
};
|
||||
},
|
||||
|
||||
@ -342,28 +331,6 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
|
||||
this.emit("resize");
|
||||
},
|
||||
|
||||
/**
|
||||
* This is kept for backward-compatibility reasons with older remote targets.
|
||||
* Targets prior to bug 916443.
|
||||
*
|
||||
* pick/cancelPick are used to pick a node on click on the content
|
||||
* document. But in their implementation prior to bug 916443, they don't allow
|
||||
* highlighting on hover.
|
||||
* The client-side now uses the highlighter actor's pick and cancelPick
|
||||
* methods instead. The client-side uses the the highlightable trait found in
|
||||
* the root actor to determine which version of pick to use.
|
||||
*
|
||||
* As for highlight, the new highlighter actor is used instead of the walker's
|
||||
* highlight method. Same here though, the client-side uses the highlightable
|
||||
* trait to dertermine which to use.
|
||||
*
|
||||
* Keeping these actor methods for now allows newer client-side debuggers to
|
||||
* inspect fxos 1.2 remote targets or older firefox desktop remote targets.
|
||||
*/
|
||||
pick: function () {},
|
||||
cancelPick: function () {},
|
||||
highlight: function (node) {},
|
||||
|
||||
/**
|
||||
* Ensures that the node is attached and it can be accessed from the root.
|
||||
*
|
||||
|
@ -168,38 +168,6 @@ window.onload = function () {
|
||||
runNextTest();
|
||||
});
|
||||
|
||||
addAsyncTest(function* testBackwardsCompat() {
|
||||
info("Simulating a server that doesn't have the new search functionality.");
|
||||
walkerFront.traits.textSearch = false;
|
||||
let front = yield walkerFront.querySelector(walkerFront.rootNode, "h1");
|
||||
|
||||
let results = yield walkerFront.search("h1");
|
||||
isDeeply(results, {
|
||||
node: front,
|
||||
type: "selector",
|
||||
resultsIndex: 0,
|
||||
resultsLength: 1
|
||||
}, "Only querySelectorAll results being returned");
|
||||
|
||||
// Clear search data to remove result state on the front
|
||||
yield walkerFront.search("");
|
||||
|
||||
// Reset the normal textSearch behavior
|
||||
walkerFront.traits.textSearch = true;
|
||||
|
||||
results = yield walkerFront.search("h1");
|
||||
isDeeply(results, {
|
||||
node: front,
|
||||
type: "search",
|
||||
resultsIndex: 0,
|
||||
resultsLength: 3
|
||||
}, "Other results being included");
|
||||
|
||||
// Clear search data to remove result state on the front
|
||||
yield walkerFront.search("");
|
||||
runNextTest();
|
||||
});
|
||||
|
||||
runNextTest();
|
||||
};
|
||||
</script>
|
||||
|
@ -5269,13 +5269,19 @@ exports.CSS_PROPERTIES = {
|
||||
],
|
||||
"values": [
|
||||
"-moz-alt-content",
|
||||
"attr",
|
||||
"close-quote",
|
||||
"counter",
|
||||
"counters",
|
||||
"inherit",
|
||||
"initial",
|
||||
"no-close-quote",
|
||||
"no-open-quote",
|
||||
"none",
|
||||
"normal",
|
||||
"open-quote",
|
||||
"unset"
|
||||
"unset",
|
||||
"url"
|
||||
]
|
||||
},
|
||||
"counter-increment": {
|
||||
|
@ -213,16 +213,9 @@ const WalkerFront = FrontClassWithSpec(walkerSpec, {
|
||||
let searchData = this.searchData = this.searchData || { };
|
||||
let selectorOnly = !!options.selectorOnly;
|
||||
|
||||
// Backwards compat. Use selector only search if the new
|
||||
// search functionality isn't implemented, or if the caller (tests)
|
||||
// want it.
|
||||
if (selectorOnly || !this.traits.textSearch) {
|
||||
if (selectorOnly) {
|
||||
searchType = "selector";
|
||||
if (this.traits.multiFrameQuerySelectorAll) {
|
||||
nodeList = yield this.multiFrameQuerySelectorAll(query);
|
||||
} else {
|
||||
nodeList = yield this.querySelectorAll(this.rootNode, query);
|
||||
}
|
||||
nodeList = yield this.multiFrameQuerySelectorAll(query);
|
||||
} else {
|
||||
searchType = "search";
|
||||
let result = yield this._search(query, options);
|
||||
@ -444,39 +437,6 @@ const WalkerFront = FrontClassWithSpec(walkerSpec, {
|
||||
return !!this.conn._transport._serverConnection;
|
||||
},
|
||||
|
||||
// XXX hack during transition to remote inspector: get a proper NodeFront
|
||||
// for a given local node. Only works locally.
|
||||
frontForRawNode: function (rawNode) {
|
||||
if (!this.isLocal()) {
|
||||
console.warn("Tried to use frontForRawNode on a remote connection.");
|
||||
return null;
|
||||
}
|
||||
const { DebuggerServer } = require("devtools/server/main");
|
||||
let walkerActor = DebuggerServer.searchAllConnectionsForActor(this.actorID);
|
||||
if (!walkerActor) {
|
||||
throw Error("Could not find client side for actor " + this.actorID);
|
||||
}
|
||||
let nodeActor = walkerActor._ref(rawNode);
|
||||
|
||||
// Pass the node through a read/write pair to create the client side actor.
|
||||
let nodeType = types.getType("domnode");
|
||||
let returnNode = nodeType.read(
|
||||
nodeType.write(nodeActor, walkerActor), this);
|
||||
let top = returnNode;
|
||||
let extras = walkerActor.parents(nodeActor, {sameTypeRootTreeItem: true});
|
||||
for (let extraActor of extras) {
|
||||
top = nodeType.read(nodeType.write(extraActor, walkerActor), this);
|
||||
}
|
||||
|
||||
if (top !== this.rootNode) {
|
||||
// Imported an already-orphaned node.
|
||||
this._orphaned.add(top);
|
||||
walkerActor._orphaned
|
||||
.add(DebuggerServer.searchAllConnectionsForActor(top.actorID));
|
||||
}
|
||||
return returnNode;
|
||||
},
|
||||
|
||||
removeNode: custom(Task.async(function* (node) {
|
||||
let previousSibling = yield this.previousSibling(node);
|
||||
let nextSibling = yield this._removeNode(node);
|
||||
|
@ -7,9 +7,8 @@
|
||||
const { Cc, Ci } = require("chrome");
|
||||
const Services = require("Services");
|
||||
const l10n = require("gcli/l10n");
|
||||
const { DevToolsLoader } = require("resource://devtools/shared/Loader.jsm");
|
||||
const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "DevToolsLoader",
|
||||
"resource://devtools/shared/Loader.jsm");
|
||||
|
||||
const BRAND_SHORT_NAME = Cc["@mozilla.org/intl/stringbundle;1"]
|
||||
.getService(Ci.nsIStringBundleService)
|
||||
|
@ -438,47 +438,6 @@ function getFrameContentOffset(frame) {
|
||||
return [borderTop + paddingTop, borderLeft + paddingLeft];
|
||||
}
|
||||
|
||||
/**
|
||||
* Find an element from the given coordinates. This method descends through
|
||||
* frames to find the element the user clicked inside frames.
|
||||
*
|
||||
* @param {DOMDocument} document
|
||||
* The document to look into.
|
||||
* @param {Number} x
|
||||
* @param {Number} y
|
||||
* @return {DOMNode}
|
||||
* the element node found at the given coordinates, or null if no node
|
||||
* was found
|
||||
*/
|
||||
function getElementFromPoint(document, x, y) {
|
||||
let node = document.elementFromPoint(x, y);
|
||||
if (node && node.contentDocument) {
|
||||
if (ChromeUtils.getClassName(node) === "HTMLIFrameElement") {
|
||||
let rect = node.getBoundingClientRect();
|
||||
|
||||
// Gap between the frame and its content window.
|
||||
let [offsetTop, offsetLeft] = getFrameContentOffset(node);
|
||||
|
||||
x -= rect.left + offsetLeft;
|
||||
y -= rect.top + offsetTop;
|
||||
|
||||
if (x < 0 || y < 0) {
|
||||
// Didn't reach the content document, still over the frame.
|
||||
return node;
|
||||
}
|
||||
}
|
||||
if (ChromeUtils.getClassName(node) === "HTMLIFrameElement" ||
|
||||
ChromeUtils.getClassName(node) === "HTMLFrameElement") {
|
||||
let subnode = getElementFromPoint(node.contentDocument, x, y);
|
||||
if (subnode) {
|
||||
node = subnode;
|
||||
}
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
exports.getElementFromPoint = getElementFromPoint;
|
||||
|
||||
/**
|
||||
* Check if a node and its document are still alive
|
||||
* and attached to the window.
|
||||
|
@ -5,6 +5,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=226361
|
||||
<head>
|
||||
<title>Test for Bug 226361</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body id="body1">
|
||||
@ -37,8 +38,7 @@ function setTabFocus() {
|
||||
|
||||
var doc = document;
|
||||
function tab_to(id) {
|
||||
var wu = SpecialPowers.DOMWindowUtils;
|
||||
wu.sendKeyEvent('keypress', 9, 0, 0);
|
||||
synthesizeKey("KEY_Tab", {code: "Tab"});
|
||||
is(doc.activeElement.id, id, "element with id=" + id + " should have focus");
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=238987
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 238987</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<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>
|
||||
@ -20,7 +21,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=238987
|
||||
/** Test for Bug 238987 **/
|
||||
|
||||
var shouldStop = false;
|
||||
var modifier = 0;
|
||||
var activateShift = false;
|
||||
var expectedResult = "i1,i2,i3,i4,i5,i6,i7,i8,number,i9,i10,i11,i12";
|
||||
var forwardFocusArray = expectedResult.split(",");
|
||||
var backwardFocusArray = expectedResult.split(",");
|
||||
@ -33,13 +34,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=238987
|
||||
|
||||
function handleFocus(e) {
|
||||
if (e.target.id == "begin") {
|
||||
// if the modifier is set, the test is coming back from the end.
|
||||
if (modifier) {
|
||||
// if the activateShift is set, the test is coming back from the end.
|
||||
if (activateShift) {
|
||||
shouldStop = true;
|
||||
}
|
||||
} else if (e.target.id == "end") {
|
||||
modifier = Components.interfaces.nsIDOMEvent.SHIFT_MASK;
|
||||
} else if (modifier) {
|
||||
activateShift = true;
|
||||
} else if (activateShift) {
|
||||
var expected = backwardFocusArray.pop();
|
||||
ok(expected == e.target.id,
|
||||
"(focus) Backward tabbing, expected [" +
|
||||
@ -66,7 +67,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=238987
|
||||
function handleBlur(e) {
|
||||
if (e.target.id == "begin" || e.target.id == "end") {
|
||||
return;
|
||||
} else if (modifier) {
|
||||
} else if (activateShift) {
|
||||
var expected = backwardBlurArray.pop();
|
||||
ok(expected == e.target.id,
|
||||
"(blur) backward tabbing, expected [" +
|
||||
@ -90,12 +91,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=238987
|
||||
}
|
||||
|
||||
function tab() {
|
||||
var utils = SpecialPowers.DOMWindowUtils;
|
||||
// Send tab key events.
|
||||
var key = Components.interfaces.nsIDOMKeyEvent.DOM_VK_TAB;
|
||||
utils.sendKeyEvent("keydown", key, 0, modifier);
|
||||
utils.sendKeyEvent("keypress", key, 0, modifier);
|
||||
utils.sendKeyEvent("keyup", key, 0, modifier);
|
||||
synthesizeKey("KEY_Tab", {code: "Tab", shiftKey: activateShift});
|
||||
if (shouldStop) {
|
||||
// Did focus handling succeed
|
||||
is(forwardFocusArray.length, 0,
|
||||
|
@ -5,7 +5,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=409604
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 409604</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<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 id="body">
|
||||
@ -19,8 +20,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=409604
|
||||
|
||||
/** Test for Bug 409604 **/
|
||||
|
||||
var modifier = SpecialPowers.Ci.nsIDOMEvent.ALT_MASK |
|
||||
SpecialPowers.Ci.nsIDOMEvent.SHIFT_MASK;
|
||||
var expectedFocus = "a,c,d,e,f,g,h,i,j,k,l,m,n,p,x,y";
|
||||
// XXX the "map" test is causing trouble, see bug 433089
|
||||
var focusArray = expectedFocus.split(",");
|
||||
@ -120,10 +119,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=409604
|
||||
}
|
||||
|
||||
function pressAccessKey(key) {
|
||||
var utils = SpecialPowers.DOMWindowUtils;
|
||||
utils.sendKeyEvent("keydown", key, key, modifier);
|
||||
utils.sendKeyEvent("keypress", key, key, modifier);
|
||||
utils.sendKeyEvent("keyup", key, key, modifier);
|
||||
synthesizeKey(key.key, {code: key.code, altKey: true, shiftKey: true});
|
||||
}
|
||||
|
||||
function testFocusableElements() {
|
||||
@ -131,7 +127,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=409604
|
||||
// XXX the "map" test is causing trouble, see bug 433089
|
||||
if (code == "b".charCodeAt(0))
|
||||
continue;
|
||||
pressAccessKey(code);
|
||||
var accessChar = String.fromCharCode(code).toUpperCase();
|
||||
pressAccessKey({key: accessChar, code: "Key" + accessChar});
|
||||
}
|
||||
ok(focusArray.length == 0, "(focus) unhandled elements remaining: " + focusArray.join(","));
|
||||
}
|
||||
@ -190,7 +187,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=409604
|
||||
var i, e;
|
||||
for (i = 0; i < unfocusableTags.length; ++ i) {
|
||||
createUnfocusableElement(unfocusableTags[i], "z");
|
||||
pressAccessKey("z".charCodeAt(0));
|
||||
pressAccessKey({key: "Z", code:"KeyZ"});
|
||||
destroyUnfocusableElement();
|
||||
}
|
||||
for (i = 0; i < invalidElements.length; ++ i) {
|
||||
@ -199,7 +196,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=409604
|
||||
e.setAttribute("accesskey", "z");
|
||||
e.setAttribute("onclick", "handleClick(event.target); event.preventDefault();");
|
||||
e.setAttribute("onfocus", "handleInvalid(event.target);");
|
||||
pressAccessKey("z".charCodeAt(0));
|
||||
pressAccessKey({key: "Z", code:"KeyZ"});
|
||||
e.removeAttribute("accesskey");
|
||||
e.removeAttribute("onclick");
|
||||
e.removeAttribute("onfocus");
|
||||
|
@ -5,6 +5,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=450876
|
||||
<head>
|
||||
<title>Test for Bug 450876 - Crash [@ nsEventStateManager::GetNextTabbableMapArea] with img usemap and tabindex</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>
|
||||
@ -24,7 +25,7 @@ function doTest() {
|
||||
document.getElementById('a').focus();
|
||||
is(document.activeElement, document.getElementById('a'), "link should have focus");
|
||||
is(document.hasFocus(), true, "document should be focused");
|
||||
SpecialPowers.DOMWindowUtils.sendKeyEvent('keypress', 9, 0, 0);
|
||||
synthesizeKey("KEY_Tab", {code: "Tab"});
|
||||
is(document.activeElement, document.getElementById('a'), "body element should be focused");
|
||||
is(document.hasFocus(), false, "document should not be focused");
|
||||
|
||||
|
@ -6,6 +6,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=493251
|
||||
<head>
|
||||
<title>Test for Bug 493251</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
@ -36,14 +37,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=493251
|
||||
utils.suppressEventHandling(aSuppress);
|
||||
}
|
||||
|
||||
function dispatchKeyEvent(type) {
|
||||
var utils = SpecialPowers.getDOMWindowUtils(win);
|
||||
ok(true, "Dipatching key event: type=" + type);
|
||||
utils.sendKeyEvent(type,
|
||||
SpecialPowers.Ci.nsIDOMKeyEvent.DOM_VK_A,
|
||||
0, 0);
|
||||
}
|
||||
|
||||
function dispatchMouseEvent(aType, aX, aY, aButton, aClickCount, aModifiers) {
|
||||
var utils = SpecialPowers.getDOMWindowUtils(win);
|
||||
ok(true, "Dipatching mouse event: aType=" + aType + ", aX=" + aX + ", aY" +
|
||||
@ -105,18 +98,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=493251
|
||||
function(e) { dumpEvent(e); ++mouseClick; }, true);
|
||||
|
||||
ok(true, "doTest #1...");
|
||||
dispatchKeyEvent("keydown");
|
||||
dispatchKeyEvent("keypress");
|
||||
dispatchKeyEvent("keyup");
|
||||
synthesizeKey("a", {code: "KeyA"}, win);
|
||||
is(keyDown, 1, "Wrong number events (1)");
|
||||
is(keyPress, 1, "Wrong number events (2)");
|
||||
is(keyUp, 1, "Wrong number events (3)");
|
||||
|
||||
ok(true, "doTest #2...");
|
||||
suppressEventHandling(true);
|
||||
dispatchKeyEvent("keydown");
|
||||
dispatchKeyEvent("keypress");
|
||||
dispatchKeyEvent("keyup");
|
||||
synthesizeKey("a", {code: "KeyA"}, win);
|
||||
is(keyDown, 1, "Wrong number events (4)");
|
||||
is(keyPress, 1, "Wrong number events (5)");
|
||||
is(keyUp, 1, "Wrong number events (6)");
|
||||
@ -130,10 +119,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=493251
|
||||
|
||||
function continueTest1() {
|
||||
ok(true, "continueTest1...");
|
||||
dispatchKeyEvent("keydown");
|
||||
suppressEventHandling(true);
|
||||
dispatchKeyEvent("keypress");
|
||||
dispatchKeyEvent("keyup");
|
||||
win.addEventListener("keydown", () => { suppressEventHandling(true); }, {once: true});
|
||||
synthesizeKey("a", {code: "KeyA"}, win);
|
||||
is(keyDown, 2, "Wrong number events (10)");
|
||||
is(keyPress, 1, "Wrong number events (11)");
|
||||
is(keyUp, 1, "Wrong number events (12)");
|
||||
|
@ -6,6 +6,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=545268
|
||||
<head>
|
||||
<title>Test for Bug 545268</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
@ -33,13 +34,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=545268
|
||||
var keyPress = 0;
|
||||
var keyUp = 0;
|
||||
|
||||
function dispatchKeyEvent(type) {
|
||||
var utils = SpecialPowers.getDOMWindowUtils(subwin);
|
||||
utils.sendKeyEvent(type,
|
||||
SpecialPowers.Ci.nsIDOMKeyEvent.DOM_VK_A,
|
||||
0, 0);
|
||||
}
|
||||
|
||||
function doTest() {
|
||||
var utils = SpecialPowers.getDOMWindowUtils(win);
|
||||
var f = win.document.getElementById("f");
|
||||
@ -52,9 +46,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=545268
|
||||
subwin.addEventListener("mouseup", function(e) { ++mouseUp; }, true);
|
||||
subwin.addEventListener("click", function(e) { ++mouseClick; }, true);
|
||||
|
||||
dispatchKeyEvent("keydown");
|
||||
dispatchKeyEvent("keypress");
|
||||
dispatchKeyEvent("keyup");
|
||||
synthesizeKey("a", {code: "KeyA"}, subwin);
|
||||
is(keyDown, 1, "Wrong number events (1)");
|
||||
is(keyPress, 1, "Wrong number events (2)");
|
||||
is(keyUp, 1, "Wrong number events (3)");
|
||||
@ -62,9 +54,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=545268
|
||||
// Test that suppressing events on the parent window prevents key
|
||||
// events in the subdocument window
|
||||
utils.suppressEventHandling(true);
|
||||
dispatchKeyEvent("keydown");
|
||||
dispatchKeyEvent("keypress");
|
||||
dispatchKeyEvent("keyup");
|
||||
synthesizeKey("a", {code: "KeyA"}, subwin);
|
||||
is(keyDown, 1, "Wrong number events (4)");
|
||||
is(keyPress, 1, "Wrong number events (5)");
|
||||
is(keyUp, 1, "Wrong number events (6)");
|
||||
@ -78,10 +68,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=545268
|
||||
|
||||
function continueTest1() {
|
||||
var utils = SpecialPowers.getDOMWindowUtils(win);
|
||||
dispatchKeyEvent("keydown");
|
||||
utils.suppressEventHandling(true);
|
||||
dispatchKeyEvent("keypress");
|
||||
dispatchKeyEvent("keyup");
|
||||
subwin.addEventListener("keydown", () => { utils.suppressEventHandling(true); }, {once: true});
|
||||
synthesizeKey("a", {code: "KeyA"}, subwin);
|
||||
is(keyDown, 2, "Wrong number events (10)");
|
||||
is(keyPress, 1, "Wrong number events (11)");
|
||||
is(keyUp, 1, "Wrong number events (12)");
|
||||
|
@ -60,10 +60,10 @@ function testRegularEvents() {
|
||||
var timeBeforeEvent = performance.now();
|
||||
addEventListener("load", function(evt) {
|
||||
var timeAfterEvent = performance.now();
|
||||
ok(evt.timeStamp > timeBeforeEvent &&
|
||||
evt.timeStamp < timeAfterEvent,
|
||||
"Event timestamp (" + evt.timeStamp + ") is in expected range: (" +
|
||||
timeBeforeEvent + ", " + timeAfterEvent + ")");
|
||||
ok(evt.timeStamp >= timeBeforeEvent &&
|
||||
evt.timeStamp <= timeAfterEvent,
|
||||
"Event timestamp (" + evt.timeStamp + ") is in expected range: [" +
|
||||
timeBeforeEvent + ", " + timeAfterEvent + "]");
|
||||
testWorkerEvents();
|
||||
});
|
||||
}
|
||||
@ -77,8 +77,8 @@ function testWorkerEvents() {
|
||||
ok(evt.data >= timeBeforeEvent &&
|
||||
evt.data <= timeAfterEvent,
|
||||
"Event timestamp in dedicated worker (" + evt.data +
|
||||
") is in expected range: (" +
|
||||
timeBeforeEvent + ", " + timeAfterEvent + ")");
|
||||
") is in expected range: [" +
|
||||
timeBeforeEvent + ", " + timeAfterEvent + "]");
|
||||
worker.terminate();
|
||||
testSharedWorkerEvents();
|
||||
};
|
||||
|
@ -453,23 +453,43 @@ IDBFactory::Open(JSContext* aCx,
|
||||
{
|
||||
if (!IsChrome() &&
|
||||
aOptions.mStorage.WasPassed()) {
|
||||
switch (aOptions.mStorage.Value()) {
|
||||
case StorageType::Persistent: {
|
||||
Telemetry::ScalarAdd(Telemetry::ScalarID::IDB_TYPE_PERSISTENT_COUNT, 1);
|
||||
break;
|
||||
|
||||
bool ignore = false;
|
||||
// Ignore internal usage on about: pages.
|
||||
if (NS_IsMainThread()) {
|
||||
nsCOMPtr<nsIPrincipal> principal = PrincipalInfoToPrincipal(*mPrincipalInfo);
|
||||
if (principal) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = principal->GetURI(getter_AddRefs(uri));
|
||||
if (NS_SUCCEEDED(rv) && uri) {
|
||||
bool isAbout;
|
||||
rv = uri->SchemeIs("about", &isAbout);
|
||||
if (NS_SUCCEEDED(rv) && isAbout) {
|
||||
ignore = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case StorageType::Temporary: {
|
||||
Telemetry::ScalarAdd(Telemetry::ScalarID::IDB_TYPE_TEMPORARY_COUNT, 1);
|
||||
break;
|
||||
if (!ignore) {
|
||||
switch (aOptions.mStorage.Value()) {
|
||||
case StorageType::Persistent: {
|
||||
Telemetry::ScalarAdd(Telemetry::ScalarID::IDB_TYPE_PERSISTENT_COUNT, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
case StorageType::Temporary: {
|
||||
Telemetry::ScalarAdd(Telemetry::ScalarID::IDB_TYPE_TEMPORARY_COUNT, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
case StorageType::Default:
|
||||
case StorageType::EndGuard_:
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Invalid storage type!");
|
||||
}
|
||||
|
||||
case StorageType::Default:
|
||||
case StorageType::EndGuard_:
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Invalid storage type!");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -158,7 +158,7 @@ APZCTreeManager::CheckerboardFlushObserver::Observe(nsISupports* aSubject,
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mTreeManager.get());
|
||||
|
||||
MutexAutoLock lock(mTreeManager->mTreeLock);
|
||||
RecursiveMutexAutoLock lock(mTreeManager->mTreeLock);
|
||||
if (mTreeManager->mRootNode) {
|
||||
ForEachNode<ReverseIterator>(mTreeManager->mRootNode.get(),
|
||||
[](HitTestingTreeNode* aNode)
|
||||
@ -294,7 +294,7 @@ APZCTreeManager::UpdateHitTestingTreeImpl(uint64_t aRootLayerTreeId,
|
||||
{
|
||||
APZThreadUtils::AssertOnCompositorThread();
|
||||
|
||||
MutexAutoLock lock(mTreeLock);
|
||||
RecursiveMutexAutoLock lock(mTreeLock);
|
||||
|
||||
// For testing purposes, we log some data to the APZTestData associated with
|
||||
// the layers id that originated this update.
|
||||
@ -344,7 +344,7 @@ APZCTreeManager::UpdateHitTestingTreeImpl(uint64_t aRootLayerTreeId,
|
||||
state.mLayersIdsToDestroy.erase(aRootLayerTreeId);
|
||||
|
||||
mApzcTreeLog << "[start]\n";
|
||||
mTreeLock.AssertCurrentThreadOwns();
|
||||
mTreeLock.AssertCurrentThreadIn();
|
||||
|
||||
ForEachNode<ReverseIterator>(aRoot,
|
||||
[&](ScrollNode aLayerMetrics)
|
||||
@ -502,7 +502,7 @@ APZCTreeManager::PushStateToWR(wr::TransactionBuilder& aTxn,
|
||||
{
|
||||
APZThreadUtils::AssertOnCompositorThread();
|
||||
|
||||
MutexAutoLock lock(mTreeLock);
|
||||
RecursiveMutexAutoLock lock(mTreeLock);
|
||||
|
||||
// During the first pass through the tree, we build a cache of guid->HTTN so
|
||||
// that we can find the relevant APZC instances quickly in subsequent passes,
|
||||
@ -778,7 +778,7 @@ APZCTreeManager::PrepareNodeForLayer(const ScrollNode& aLayer,
|
||||
HitTestingTreeNode* aNextSibling,
|
||||
TreeBuildingState& aState)
|
||||
{
|
||||
mTreeLock.AssertCurrentThreadOwns();
|
||||
mTreeLock.AssertCurrentThreadIn();
|
||||
|
||||
bool needsApzc = true;
|
||||
if (!aMetrics.IsScrollable()) {
|
||||
@ -1074,7 +1074,7 @@ APZCTreeManager::ReceiveInputEvent(InputData& aEvent,
|
||||
MOZ_ASSERT(mToolbarAnimator);
|
||||
ScreenPoint scrollOffset;
|
||||
{
|
||||
MutexAutoLock lock(mTreeLock);
|
||||
RecursiveMutexAutoLock lock(mTreeLock);
|
||||
RefPtr<AsyncPanZoomController> apzc = FindRootContentOrRootApzc();
|
||||
if (apzc) {
|
||||
scrollOffset = ViewAs<ScreenPixel>(apzc->GetCurrentAsyncScrollOffset(AsyncPanZoomController::eForHitTesting),
|
||||
@ -1124,7 +1124,7 @@ APZCTreeManager::ReceiveInputEvent(InputData& aEvent,
|
||||
// When the mouse is outside the window we still want to handle dragging
|
||||
// but we won't find an APZC. Fallback to root APZC then.
|
||||
{ // scope lock
|
||||
MutexAutoLock lock(mTreeLock);
|
||||
RecursiveMutexAutoLock lock(mTreeLock);
|
||||
if (!apzc && mRootNode) {
|
||||
apzc = mRootNode->GetApzc();
|
||||
}
|
||||
@ -1739,7 +1739,7 @@ APZCTreeManager::SetupScrollbarDrag(MouseInput& aMouseInput,
|
||||
// due to async scrolling, so look that up and apply it.
|
||||
LayerToParentLayerMatrix4x4 thumbTransform;
|
||||
{
|
||||
MutexAutoLock lock(mTreeLock);
|
||||
RecursiveMutexAutoLock lock(mTreeLock);
|
||||
thumbTransform = ComputeTransformForNode(aScrollThumbNode);
|
||||
}
|
||||
// Only consider the translation, since we do not support both
|
||||
@ -1903,7 +1903,7 @@ void
|
||||
APZCTreeManager::UpdateZoomConstraints(const ScrollableLayerGuid& aGuid,
|
||||
const Maybe<ZoomConstraints>& aConstraints)
|
||||
{
|
||||
MutexAutoLock lock(mTreeLock);
|
||||
RecursiveMutexAutoLock lock(mTreeLock);
|
||||
RefPtr<HitTestingTreeNode> node = GetTargetNode(aGuid, nullptr);
|
||||
MOZ_ASSERT(!node || node->GetApzc()); // any node returned must have an APZC
|
||||
|
||||
@ -1962,8 +1962,7 @@ APZCTreeManager::FlushRepaintsToClearScreenToGeckoTransform()
|
||||
// matched APZCs is the same. It is simplest to ensure that by flushing the
|
||||
// pending repaint requests, which makes all of the untransforms empty (and
|
||||
// therefore equal).
|
||||
MutexAutoLock lock(mTreeLock);
|
||||
mTreeLock.AssertCurrentThreadOwns();
|
||||
RecursiveMutexAutoLock lock(mTreeLock);
|
||||
|
||||
ForEachNode<ReverseIterator>(mRootNode.get(),
|
||||
[](HitTestingTreeNode* aNode)
|
||||
@ -1987,7 +1986,7 @@ APZCTreeManager::CancelAnimation(const ScrollableLayerGuid &aGuid)
|
||||
void
|
||||
APZCTreeManager::AdjustScrollForSurfaceShift(const ScreenPoint& aShift)
|
||||
{
|
||||
MutexAutoLock lock(mTreeLock);
|
||||
RecursiveMutexAutoLock lock(mTreeLock);
|
||||
RefPtr<AsyncPanZoomController> apzc = FindRootContentOrRootApzc();
|
||||
if (apzc) {
|
||||
apzc->AdjustScrollForSurfaceShift(aShift);
|
||||
@ -2003,7 +2002,7 @@ APZCTreeManager::ClearTree()
|
||||
APZThreadUtils::RunOnControllerThread(NewRunnableMethod(
|
||||
"layers::InputQueue::Clear", mInputQueue, &InputQueue::Clear));
|
||||
|
||||
MutexAutoLock lock(mTreeLock);
|
||||
RecursiveMutexAutoLock lock(mTreeLock);
|
||||
|
||||
// Collect the nodes into a list, and then destroy each one.
|
||||
// We can't destroy them as we collect them, because ForEachNode()
|
||||
@ -2032,7 +2031,7 @@ APZCTreeManager::ClearTree()
|
||||
RefPtr<HitTestingTreeNode>
|
||||
APZCTreeManager::GetRootNode() const
|
||||
{
|
||||
MutexAutoLock lock(mTreeLock);
|
||||
RecursiveMutexAutoLock lock(mTreeLock);
|
||||
return mRootNode;
|
||||
}
|
||||
|
||||
@ -2235,7 +2234,7 @@ APZCTreeManager::HitTestAPZC(const ScreenIntPoint& aPoint)
|
||||
already_AddRefed<AsyncPanZoomController>
|
||||
APZCTreeManager::GetTargetAPZC(const ScrollableLayerGuid& aGuid)
|
||||
{
|
||||
MutexAutoLock lock(mTreeLock);
|
||||
RecursiveMutexAutoLock lock(mTreeLock);
|
||||
RefPtr<HitTestingTreeNode> node = GetTargetNode(aGuid, nullptr);
|
||||
MOZ_ASSERT(!node || node->GetApzc()); // any node returned must have an APZC
|
||||
RefPtr<AsyncPanZoomController> apzc = node ? node->GetApzc() : nullptr;
|
||||
@ -2253,7 +2252,7 @@ already_AddRefed<AsyncPanZoomController>
|
||||
APZCTreeManager::GetTargetAPZC(const uint64_t& aLayersId,
|
||||
const FrameMetrics::ViewID& aScrollId)
|
||||
{
|
||||
MutexAutoLock lock(mTreeLock);
|
||||
RecursiveMutexAutoLock lock(mTreeLock);
|
||||
ScrollableLayerGuid guid(aLayersId, 0, aScrollId);
|
||||
RefPtr<HitTestingTreeNode> node = GetTargetNode(guid, &GuidComparatorIgnoringPresShell);
|
||||
MOZ_ASSERT(!node || node->GetApzc()); // any node returned must have an APZC
|
||||
@ -2265,7 +2264,7 @@ already_AddRefed<HitTestingTreeNode>
|
||||
APZCTreeManager::GetTargetNode(const ScrollableLayerGuid& aGuid,
|
||||
GuidComparator aComparator) const
|
||||
{
|
||||
mTreeLock.AssertCurrentThreadOwns();
|
||||
mTreeLock.AssertCurrentThreadIn();
|
||||
RefPtr<HitTestingTreeNode> target = DepthFirstSearchPostOrder<ReverseIterator>(mRootNode.get(),
|
||||
[&aGuid, &aComparator](HitTestingTreeNode* node)
|
||||
{
|
||||
@ -2288,7 +2287,7 @@ APZCTreeManager::GetTargetAPZC(const ScreenPoint& aPoint,
|
||||
CompositorHitTestInfo* aOutHitResult,
|
||||
RefPtr<HitTestingTreeNode>* aOutScrollbarNode)
|
||||
{
|
||||
MutexAutoLock lock(mTreeLock);
|
||||
RecursiveMutexAutoLock lock(mTreeLock);
|
||||
|
||||
CompositorHitTestInfo hitResult = CompositorHitTestInfo::eInvisibleToHitTest;
|
||||
HitTestingTreeNode* scrollbarNode = nullptr;
|
||||
@ -2385,7 +2384,7 @@ APZCTreeManager::BuildOverscrollHandoffChain(const RefPtr<AsyncPanZoomController
|
||||
// order in which scroll will be handed off to them.
|
||||
|
||||
// Grab tree lock since we'll be walking the APZC tree.
|
||||
MutexAutoLock lock(mTreeLock);
|
||||
RecursiveMutexAutoLock lock(mTreeLock);
|
||||
|
||||
// Build the chain. If there is a scroll parent link, we use that. This is
|
||||
// needed to deal with scroll info layers, because they participate in handoff
|
||||
@ -2459,7 +2458,7 @@ APZCTreeManager::SetLongTapEnabled(bool aLongTapEnabled)
|
||||
RefPtr<HitTestingTreeNode>
|
||||
APZCTreeManager::FindScrollThumbNode(const AsyncDragMetrics& aDragMetrics)
|
||||
{
|
||||
MutexAutoLock lock(mTreeLock);
|
||||
RecursiveMutexAutoLock lock(mTreeLock);
|
||||
|
||||
return DepthFirstSearch<ReverseIterator>(mRootNode.get(),
|
||||
[&aDragMetrics](HitTestingTreeNode* aNode) {
|
||||
@ -2493,7 +2492,7 @@ APZCTreeManager::GetAPZCAtPoint(HitTestingTreeNode* aNode,
|
||||
CompositorHitTestInfo* aOutHitResult,
|
||||
HitTestingTreeNode** aOutScrollbarNode)
|
||||
{
|
||||
mTreeLock.AssertCurrentThreadOwns();
|
||||
mTreeLock.AssertCurrentThreadIn();
|
||||
|
||||
// This walks the tree in depth-first, reverse order, so that it encounters
|
||||
// APZCs front-to-back on the screen.
|
||||
@ -2586,7 +2585,7 @@ APZCTreeManager::GetAPZCAtPoint(HitTestingTreeNode* aNode,
|
||||
AsyncPanZoomController*
|
||||
APZCTreeManager::FindRootApzcForLayersId(uint64_t aLayersId) const
|
||||
{
|
||||
mTreeLock.AssertCurrentThreadOwns();
|
||||
mTreeLock.AssertCurrentThreadIn();
|
||||
|
||||
HitTestingTreeNode* resultNode = BreadthFirstSearch<ReverseIterator>(mRootNode.get(),
|
||||
[aLayersId](HitTestingTreeNode* aNode) {
|
||||
@ -2601,7 +2600,7 @@ APZCTreeManager::FindRootApzcForLayersId(uint64_t aLayersId) const
|
||||
AsyncPanZoomController*
|
||||
APZCTreeManager::FindRootContentApzcForLayersId(uint64_t aLayersId) const
|
||||
{
|
||||
mTreeLock.AssertCurrentThreadOwns();
|
||||
mTreeLock.AssertCurrentThreadIn();
|
||||
|
||||
HitTestingTreeNode* resultNode = BreadthFirstSearch<ReverseIterator>(mRootNode.get(),
|
||||
[aLayersId](HitTestingTreeNode* aNode) {
|
||||
@ -2616,7 +2615,7 @@ APZCTreeManager::FindRootContentApzcForLayersId(uint64_t aLayersId) const
|
||||
AsyncPanZoomController*
|
||||
APZCTreeManager::FindRootContentOrRootApzc() const
|
||||
{
|
||||
mTreeLock.AssertCurrentThreadOwns();
|
||||
mTreeLock.AssertCurrentThreadIn();
|
||||
|
||||
// Note: this is intended to find the same "root" that would be found
|
||||
// by AsyncCompositionManager::ApplyAsyncContentTransformToTree inside
|
||||
@ -2738,7 +2737,7 @@ ScreenToParentLayerMatrix4x4
|
||||
APZCTreeManager::GetScreenToApzcTransform(const AsyncPanZoomController *aApzc) const
|
||||
{
|
||||
Matrix4x4 result;
|
||||
MutexAutoLock lock(mTreeLock);
|
||||
RecursiveMutexAutoLock lock(mTreeLock);
|
||||
|
||||
// The comments below assume there is a chain of layers L..R with L and P having APZC instances as
|
||||
// explained in the comment above. This function is called with aApzc at L, and the loop
|
||||
@ -2779,7 +2778,7 @@ ParentLayerToScreenMatrix4x4
|
||||
APZCTreeManager::GetApzcToGeckoTransform(const AsyncPanZoomController *aApzc) const
|
||||
{
|
||||
Matrix4x4 result;
|
||||
MutexAutoLock lock(mTreeLock);
|
||||
RecursiveMutexAutoLock lock(mTreeLock);
|
||||
|
||||
// The comments below assume there is a chain of layers L..R with L and P having APZC instances as
|
||||
// explained in the comment above. This function is called with aApzc at L, and the loop
|
||||
@ -2814,7 +2813,7 @@ APZCTreeManager::GetCurrentMousePosition() const
|
||||
already_AddRefed<AsyncPanZoomController>
|
||||
APZCTreeManager::GetMultitouchTarget(AsyncPanZoomController* aApzc1, AsyncPanZoomController* aApzc2) const
|
||||
{
|
||||
MutexAutoLock lock(mTreeLock);
|
||||
RecursiveMutexAutoLock lock(mTreeLock);
|
||||
RefPtr<AsyncPanZoomController> apzc;
|
||||
// For now, we only ever want to do pinching on the root-content APZC for
|
||||
// a given layers id.
|
||||
@ -2838,7 +2837,7 @@ APZCTreeManager::GetMultitouchTarget(AsyncPanZoomController* aApzc1, AsyncPanZoo
|
||||
already_AddRefed<AsyncPanZoomController>
|
||||
APZCTreeManager::CommonAncestor(AsyncPanZoomController* aApzc1, AsyncPanZoomController* aApzc2) const
|
||||
{
|
||||
mTreeLock.AssertCurrentThreadOwns();
|
||||
mTreeLock.AssertCurrentThreadIn();
|
||||
RefPtr<AsyncPanZoomController> ancestor;
|
||||
|
||||
// If either aApzc1 or aApzc2 is null, min(depth1, depth2) will be 0 and this function
|
||||
@ -2884,7 +2883,7 @@ APZCTreeManager::CommonAncestor(AsyncPanZoomController* aApzc1, AsyncPanZoomCont
|
||||
LayerToParentLayerMatrix4x4
|
||||
APZCTreeManager::ComputeTransformForNode(const HitTestingTreeNode* aNode) const
|
||||
{
|
||||
mTreeLock.AssertCurrentThreadOwns();
|
||||
mTreeLock.AssertCurrentThreadIn();
|
||||
if (AsyncPanZoomController* apzc = aNode->GetApzc()) {
|
||||
// If the node represents scrollable content, apply the async transform
|
||||
// from its APZC.
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include "mozilla/layers/IAPZCTreeManager.h" // for IAPZCTreeManager
|
||||
#include "mozilla/layers/KeyboardMap.h" // for KeyboardMap
|
||||
#include "mozilla/layers/FocusState.h" // for FocusState
|
||||
#include "mozilla/Mutex.h" // for Mutex
|
||||
#include "mozilla/RecursiveMutex.h" // for RecursiveMutex
|
||||
#include "mozilla/RefPtr.h" // for RefPtr
|
||||
#include "mozilla/TimeStamp.h" // for mozilla::TimeStamp
|
||||
#include "nsCOMPtr.h" // for already_AddRefed
|
||||
@ -649,7 +649,7 @@ private:
|
||||
* is considered part of the APZC tree management state.
|
||||
* Finally, the lock needs to be held when accessing mZoomConstraints.
|
||||
* IMPORTANT: See the note about lock ordering at the top of this file. */
|
||||
mutable mozilla::Mutex mTreeLock;
|
||||
mutable mozilla::RecursiveMutex mTreeLock;
|
||||
RefPtr<HitTestingTreeNode> mRootNode;
|
||||
/* Holds the zoom constraints for scrollable layers, as determined by the
|
||||
* the main-thread gecko code. */
|
||||
|
@ -1826,6 +1826,9 @@ PresShell::Initialize(nscoord aWidth, nscoord aHeight)
|
||||
// (Do this in a script runner, since our caller might have a script
|
||||
// blocker on the stack.)
|
||||
nsContentUtils::AddScriptRunner(new XBLConstructorRunner(mDocument));
|
||||
|
||||
// XBLConstructorRunner might destroy us.
|
||||
NS_ENSURE_STATE(!mHaveShutDown);
|
||||
}
|
||||
|
||||
NS_ASSERTION(rootFrame, "How did that happen?");
|
||||
|
@ -7,6 +7,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=348236
|
||||
|
||||
<title>Test for Bug 348236</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" />
|
||||
<style type="text/css">
|
||||
#eSelect {
|
||||
@ -41,25 +42,21 @@ addLoadEvent(function test() {
|
||||
WinUtils = SpecialPowers.getDOMWindowUtils(window),
|
||||
sec = netscape.security,
|
||||
eSelect = $("eSelect"),
|
||||
IDOMEvent = CI.nsIDOMEvent,
|
||||
IDOMKeyEvent = CI.nsIDOMKeyEvent,
|
||||
timeout = 0 // Choose a larger value like 500 ms if you want to see what's happening.
|
||||
|
||||
function keypressOnSelect(key, modifiers) {
|
||||
function keypressOnSelect(key) {
|
||||
WinUtils.focus(eSelect)
|
||||
WinUtils.sendKeyEvent("keyup", key, 0, modifiers)
|
||||
WinUtils.sendKeyEvent("keypress", key, 0, modifiers)
|
||||
WinUtils.sendKeyEvent("keydown", key, 0, modifiers)
|
||||
synthesizeKey(key.key, {code: key.code, altKey: key.altKey});
|
||||
}
|
||||
|
||||
function testKey(key, modifiers, keyString, functionToContinue) {
|
||||
function testKey(key, keyString, functionToContinue) {
|
||||
var selectGotClick
|
||||
function clickListener() { selectGotClick = true }
|
||||
eSelect.selectedIndex = 0
|
||||
eSelect.onchangeCount = 0
|
||||
|
||||
// Drop the SELECT down.
|
||||
keypressOnSelect(key, modifiers)
|
||||
keypressOnSelect(key)
|
||||
// This timeout and the following are necessary to let the sent events take effect.
|
||||
setTimeout(cont1, timeout)
|
||||
function cont1() {
|
||||
@ -69,7 +66,7 @@ addLoadEvent(function test() {
|
||||
}
|
||||
function cont2() {
|
||||
// Close the select.
|
||||
keypressOnSelect(key, modifiers)
|
||||
keypressOnSelect(key)
|
||||
setTimeout(cont3, timeout)
|
||||
}
|
||||
function cont3() {
|
||||
@ -96,19 +93,19 @@ addLoadEvent(function test() {
|
||||
is(eSelect.selectedIndex, 0, "SELECT selectedIndex should be 0 after load.")
|
||||
|
||||
// Check if sending key events works.
|
||||
keypressOnSelect(IDOMKeyEvent.DOM_VK_DOWN, 0)
|
||||
keypressOnSelect({key: "KEY_ArrowDown", code: "ArrowDown"});
|
||||
is(eSelect.value, "2", "SELECT value should be 2 after pressing Down.")
|
||||
|
||||
// Test ALT-Down.
|
||||
testKey(IDOMKeyEvent.DOM_VK_DOWN, IDOMEvent.ALT_MASK, "ALT-Down", nextKey1)
|
||||
testKey({key: "KEY_ArrowDown", code: "ArrowDown", altKey: true}, "ALT-Down", nextKey1)
|
||||
function nextKey1() {
|
||||
// Test ALT-Up.
|
||||
testKey(IDOMKeyEvent.DOM_VK_UP, IDOMEvent.ALT_MASK, "ALT-Up", nextKey2)
|
||||
testKey({key: "KEY_ArrowUp", code: "ArrowUp", altKey: true}, "ALT-Up", nextKey2)
|
||||
}
|
||||
function nextKey2() {
|
||||
// Test the F4 key on OS/2 and Windows.
|
||||
if (/OS\/2|Win/i.test(navigator.platform))
|
||||
testKey(IDOMKeyEvent.DOM_VK_F4, 0, "F4", finished)
|
||||
// Test the F4 key on Windows.
|
||||
if (/Win/i.test(navigator.platform))
|
||||
testKey({key: "KEY_F4", code: "F4"}, "F4", finished)
|
||||
else
|
||||
finished()
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=411236
|
||||
<head>
|
||||
<title>Test for Bug 411236</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>
|
||||
@ -24,21 +25,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=411236
|
||||
window.oTarget = null;
|
||||
window.fileInputGotClick = false;
|
||||
|
||||
function tab() {
|
||||
var utils = SpecialPowers.DOMWindowUtils;
|
||||
// Send tab key events.
|
||||
var key = SpecialPowers.Ci.nsIDOMKeyEvent.DOM_VK_TAB;
|
||||
utils.sendKeyEvent("keydown", key, 0, 0);
|
||||
utils.sendKeyEvent("keypress", key, 0, 0);
|
||||
utils.sendKeyEvent("keyup", key, 0, 0);
|
||||
}
|
||||
|
||||
function test() {
|
||||
// Try to find the 'Browse...' using tabbing.
|
||||
var i = 0;
|
||||
while (!window.oTarget && i < 100) {
|
||||
++i;
|
||||
tab();
|
||||
synthesizeKey("KEY_Tab", {code: "Tab"});
|
||||
}
|
||||
|
||||
if (i >= 100) {
|
||||
|
@ -156,11 +156,6 @@ FontSizeInflationListMarginAdjustment(const nsIFrame* aFrame)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// NOTE: If we ever want to use SizeComputationInput for a flex item or a
|
||||
// grid item, we need to make it take the containing-block block-size as
|
||||
// well as the inline-size, since flex items and grid items resolve
|
||||
// block-direction percent margins and padding against the
|
||||
// containing-block block-size, rather than its inline-size.
|
||||
SizeComputationInput::SizeComputationInput(nsIFrame *aFrame,
|
||||
gfxContext *aRenderingContext,
|
||||
WritingMode aContainingBlockWritingMode,
|
||||
@ -169,16 +164,9 @@ SizeComputationInput::SizeComputationInput(nsIFrame *aFrame,
|
||||
, mRenderingContext(aRenderingContext)
|
||||
, mWritingMode(aFrame->GetWritingMode())
|
||||
{
|
||||
MOZ_ASSERT(!aFrame->IsFlexOrGridItem(),
|
||||
"We're about to resolve percent margin & padding "
|
||||
"values against CB inline size, which is incorrect for "
|
||||
"flex/grid items. "
|
||||
"Additionally for grid items, this path doesn't handle baseline "
|
||||
"padding contribution - see SizeComputationInput::InitOffsets");
|
||||
LogicalSize cbSize(aContainingBlockWritingMode, aContainingBlockISize,
|
||||
aContainingBlockISize);
|
||||
ReflowInputFlags flags;
|
||||
InitOffsets(aContainingBlockWritingMode, cbSize, mFrame->Type(), flags);
|
||||
InitOffsets(aContainingBlockWritingMode, aContainingBlockISize,
|
||||
mFrame->Type(), flags);
|
||||
}
|
||||
|
||||
// Initialize a reflow state for a child frame's reflow. Some state
|
||||
@ -2208,27 +2196,6 @@ IsSideCaption(nsIFrame* aFrame, const nsStyleDisplay* aStyleDisplay,
|
||||
captionSide == NS_STYLE_CAPTION_SIDE_RIGHT;
|
||||
}
|
||||
|
||||
// Flex/grid items resolve block-axis percentage margin & padding against the
|
||||
// containing block block-size (also for abs/fixed-pos child frames).
|
||||
// For everything else: the CSS21 spec requires that margin and padding
|
||||
// percentage values are calculated with respect to the inline-size of the
|
||||
// containing block, even for margin & padding in the block axis.
|
||||
static LogicalSize
|
||||
OffsetPercentBasis(const nsIFrame* aFrame,
|
||||
WritingMode aWM,
|
||||
const LogicalSize& aContainingBlockSize)
|
||||
{
|
||||
LogicalSize offsetPercentBasis = aContainingBlockSize;
|
||||
if (MOZ_LIKELY(!aFrame->GetParent() ||
|
||||
!aFrame->GetParent()->IsFlexOrGridContainer())) {
|
||||
offsetPercentBasis.BSize(aWM) = offsetPercentBasis.ISize(aWM);
|
||||
} else if (offsetPercentBasis.BSize(aWM) == NS_AUTOHEIGHT) {
|
||||
offsetPercentBasis.BSize(aWM) = 0;
|
||||
}
|
||||
|
||||
return offsetPercentBasis;
|
||||
}
|
||||
|
||||
// XXX refactor this code to have methods for each set of properties
|
||||
// we are computing: width,height,line-height; margin; offsets
|
||||
|
||||
@ -2249,7 +2216,7 @@ ReflowInput::InitConstraints(nsPresContext* aPresContext,
|
||||
// height equal to the available space
|
||||
if (nullptr == mParentReflowInput || mFlags.mDummyParentReflowInput) {
|
||||
// XXXldb This doesn't mean what it used to!
|
||||
InitOffsets(wm, OffsetPercentBasis(mFrame, wm, aContainingBlockSize),
|
||||
InitOffsets(wm, aContainingBlockSize.ISize(wm),
|
||||
aFrameType, mFlags, aBorder, aPadding, mStyleDisplay);
|
||||
// Override mComputedMargin since reflow roots start from the
|
||||
// frame's boundary, which is inside the margin.
|
||||
@ -2307,8 +2274,7 @@ ReflowInput::InitConstraints(nsPresContext* aPresContext,
|
||||
// For calculating positioning offsets, margins, borders and
|
||||
// padding, we use the writing mode of the containing block
|
||||
WritingMode cbwm = cbri->GetWritingMode();
|
||||
InitOffsets(cbwm, OffsetPercentBasis(mFrame, cbwm,
|
||||
cbSize.ConvertTo(cbwm, wm)),
|
||||
InitOffsets(cbwm, cbSize.ConvertTo(cbwm, wm).ISize(cbwm),
|
||||
aFrameType, mFlags, aBorder, aPadding, mStyleDisplay);
|
||||
|
||||
// For calculating the size of this box, we use its own writing mode
|
||||
@ -2582,7 +2548,7 @@ UpdateProp(nsIFrame* aFrame,
|
||||
|
||||
void
|
||||
SizeComputationInput::InitOffsets(WritingMode aWM,
|
||||
const LogicalSize& aPercentBasis,
|
||||
nscoord aPercentBasis,
|
||||
LayoutFrameType aFrameType,
|
||||
ReflowInputFlags aFlags,
|
||||
const nsMargin* aBorder,
|
||||
@ -2953,7 +2919,7 @@ ReflowInput::CalcLineHeight(nsIContent* aContent,
|
||||
|
||||
bool
|
||||
SizeComputationInput::ComputeMargin(WritingMode aWM,
|
||||
const LogicalSize& aPercentBasis)
|
||||
nscoord aPercentBasis)
|
||||
{
|
||||
// SVG text frames have no margin.
|
||||
if (nsSVGUtils::IsInSVGTextSubtree(mFrame)) {
|
||||
@ -2970,17 +2936,17 @@ SizeComputationInput::ComputeMargin(WritingMode aWM,
|
||||
// (http://dev.w3.org/csswg/css-writing-modes-3/#orthogonal-flows)
|
||||
LogicalMargin m(aWM);
|
||||
m.IStart(aWM) = nsLayoutUtils::
|
||||
ComputeCBDependentValue(aPercentBasis.ISize(aWM),
|
||||
ComputeCBDependentValue(aPercentBasis,
|
||||
styleMargin->mMargin.GetIStart(aWM));
|
||||
m.IEnd(aWM) = nsLayoutUtils::
|
||||
ComputeCBDependentValue(aPercentBasis.ISize(aWM),
|
||||
ComputeCBDependentValue(aPercentBasis,
|
||||
styleMargin->mMargin.GetIEnd(aWM));
|
||||
|
||||
m.BStart(aWM) = nsLayoutUtils::
|
||||
ComputeCBDependentValue(aPercentBasis.BSize(aWM),
|
||||
ComputeCBDependentValue(aPercentBasis,
|
||||
styleMargin->mMargin.GetBStart(aWM));
|
||||
m.BEnd(aWM) = nsLayoutUtils::
|
||||
ComputeCBDependentValue(aPercentBasis.BSize(aWM),
|
||||
ComputeCBDependentValue(aPercentBasis,
|
||||
styleMargin->mMargin.GetBEnd(aWM));
|
||||
|
||||
SetComputedLogicalMargin(aWM, m);
|
||||
@ -3001,7 +2967,7 @@ SizeComputationInput::ComputeMargin(WritingMode aWM,
|
||||
|
||||
bool
|
||||
SizeComputationInput::ComputePadding(WritingMode aWM,
|
||||
const LogicalSize& aPercentBasis,
|
||||
nscoord aPercentBasis,
|
||||
LayoutFrameType aFrameType)
|
||||
{
|
||||
// If style can provide us the padding directly, then use it.
|
||||
@ -3022,17 +2988,17 @@ SizeComputationInput::ComputePadding(WritingMode aWM,
|
||||
// clamp negative calc() results to 0
|
||||
LogicalMargin p(aWM);
|
||||
p.IStart(aWM) = std::max(0, nsLayoutUtils::
|
||||
ComputeCBDependentValue(aPercentBasis.ISize(aWM),
|
||||
ComputeCBDependentValue(aPercentBasis,
|
||||
stylePadding->mPadding.GetIStart(aWM)));
|
||||
p.IEnd(aWM) = std::max(0, nsLayoutUtils::
|
||||
ComputeCBDependentValue(aPercentBasis.ISize(aWM),
|
||||
ComputeCBDependentValue(aPercentBasis,
|
||||
stylePadding->mPadding.GetIEnd(aWM)));
|
||||
|
||||
p.BStart(aWM) = std::max(0, nsLayoutUtils::
|
||||
ComputeCBDependentValue(aPercentBasis.BSize(aWM),
|
||||
ComputeCBDependentValue(aPercentBasis,
|
||||
stylePadding->mPadding.GetBStart(aWM)));
|
||||
p.BEnd(aWM) = std::max(0, nsLayoutUtils::
|
||||
ComputeCBDependentValue(aPercentBasis.BSize(aWM),
|
||||
ComputeCBDependentValue(aPercentBasis,
|
||||
stylePadding->mPadding.GetBEnd(aWM)));
|
||||
|
||||
SetComputedLogicalPadding(aWM, p);
|
||||
|
@ -247,7 +247,7 @@ public:
|
||||
static void* DisplayInitOffsetsEnter(
|
||||
nsIFrame* aFrame,
|
||||
SizeComputationInput* aState,
|
||||
const mozilla::LogicalSize& aPercentBasis,
|
||||
nscoord aPercentBasis,
|
||||
WritingMode aCBWritingMode,
|
||||
const nsMargin* aBorder,
|
||||
const nsMargin* aPadding);
|
||||
@ -263,19 +263,12 @@ private:
|
||||
*
|
||||
* @param aWM Writing mode of the containing block
|
||||
* @param aPercentBasis
|
||||
* Logical size in the writing mode of the containing block to use
|
||||
* for resolving percentage margin values in the inline and block
|
||||
* axes.
|
||||
* The inline size is usually the containing block inline-size
|
||||
* (width if writing mode is horizontal, and height if vertical).
|
||||
* The block size is usually the containing block inline-size, per
|
||||
* CSS21 sec 8.3 (read in conjunction with CSS Writing Modes sec
|
||||
* 7.2), but may be the containing block block-size, e.g. in CSS3
|
||||
* Flexbox and Grid.
|
||||
* Inline size of the containing block (in its own writing mode), to use
|
||||
* for resolving percentage margin values in the inline and block axes.
|
||||
* @return true if the margin is dependent on the containing block size.
|
||||
*/
|
||||
bool ComputeMargin(mozilla::WritingMode aWM,
|
||||
const mozilla::LogicalSize& aPercentBasis);
|
||||
nscoord aPercentBasis);
|
||||
|
||||
/**
|
||||
* Computes padding values from the specified padding style information, and
|
||||
@ -283,24 +276,17 @@ private:
|
||||
*
|
||||
* @param aWM Writing mode of the containing block
|
||||
* @param aPercentBasis
|
||||
* Logical size in the writing mode of the containing block to use
|
||||
* for resolving percentage padding values in the inline and block
|
||||
* axes.
|
||||
* The inline size is usually the containing block inline-size
|
||||
* (width if writing mode is horizontal, and height if vertical).
|
||||
* The block size is usually the containing block inline-size, per
|
||||
* CSS21 sec 8.3 (read in conjunction with CSS Writing Modes sec
|
||||
* 7.2), but may be the containing block block-size, e.g. in CSS3
|
||||
* Flexbox and Grid.
|
||||
* Inline size of the containing block (in its own writing mode), to use
|
||||
* for resolving percentage padding values in the inline and block axes.
|
||||
* @return true if the padding is dependent on the containing block size.
|
||||
*/
|
||||
bool ComputePadding(mozilla::WritingMode aWM,
|
||||
const mozilla::LogicalSize& aPercentBasis,
|
||||
nscoord aPercentBasis,
|
||||
mozilla::LayoutFrameType aFrameType);
|
||||
|
||||
protected:
|
||||
void InitOffsets(mozilla::WritingMode aWM,
|
||||
const mozilla::LogicalSize& aPercentBasis,
|
||||
nscoord aPercentBasis,
|
||||
mozilla::LayoutFrameType aFrameType,
|
||||
ReflowInputFlags aFlags,
|
||||
const nsMargin* aBorder = nullptr,
|
||||
|
@ -212,7 +212,7 @@ LOCAL_INCLUDES += [
|
||||
|
||||
JAR_MANIFESTS += ['jar.mn']
|
||||
|
||||
RESOURCE_FILES.html = [
|
||||
CONTENT_ACCESSIBLE_FILES.html = [
|
||||
'folder.png',
|
||||
]
|
||||
|
||||
|
@ -11563,7 +11563,7 @@ DR_init_constraints_cookie::~DR_init_constraints_cookie()
|
||||
DR_init_offsets_cookie::DR_init_offsets_cookie(
|
||||
nsIFrame* aFrame,
|
||||
SizeComputationInput* aState,
|
||||
const LogicalSize& aPercentBasis,
|
||||
nscoord aPercentBasis,
|
||||
WritingMode aCBWritingMode,
|
||||
const nsMargin* aMargin,
|
||||
const nsMargin* aPadding)
|
||||
@ -12523,7 +12523,7 @@ ReflowInput::DisplayInitConstraintsExit(nsIFrame* aFrame,
|
||||
/* static */ void*
|
||||
SizeComputationInput::DisplayInitOffsetsEnter(nsIFrame* aFrame,
|
||||
SizeComputationInput* aState,
|
||||
const LogicalSize& aPercentBasis,
|
||||
nscoord aPercentBasis,
|
||||
WritingMode aCBWritingMode,
|
||||
const nsMargin* aBorder,
|
||||
const nsMargin* aPadding)
|
||||
@ -12539,13 +12539,9 @@ SizeComputationInput::DisplayInitOffsetsEnter(nsIFrame* aFrame,
|
||||
if (treeNode && treeNode->mDisplay) {
|
||||
DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent);
|
||||
|
||||
char horizPctBasisStr[16];
|
||||
char vertPctBasisStr[16];
|
||||
DR_state->PrettyUC(aPercentBasis.ISize(aCBWritingMode),
|
||||
horizPctBasisStr, 16);
|
||||
DR_state->PrettyUC(aPercentBasis.BSize(aCBWritingMode),
|
||||
vertPctBasisStr, 16);
|
||||
printf("InitOffsets pct_basis=%s,%s", horizPctBasisStr, vertPctBasisStr);
|
||||
char pctBasisStr[16];
|
||||
DR_state->PrettyUC(aPercentBasis, pctBasisStr, 16);
|
||||
printf("InitOffsets pct_basis=%s", pctBasisStr);
|
||||
|
||||
DR_state->PrintMargin("b", aBorder);
|
||||
DR_state->PrintMargin("p", aPadding);
|
||||
|
@ -835,7 +835,7 @@ public:
|
||||
|
||||
struct DR_init_offsets_cookie {
|
||||
DR_init_offsets_cookie(nsIFrame* aFrame, mozilla::SizeComputationInput* aState,
|
||||
const mozilla::LogicalSize& aPercentBasis,
|
||||
nscoord aPercentBasis,
|
||||
mozilla::WritingMode aCBWritingMode,
|
||||
const nsMargin* aBorder,
|
||||
const nsMargin* aPadding);
|
||||
|
@ -555,6 +555,13 @@ static void GetOtherValuesForProperty(const uint32_t aParserVariant,
|
||||
InsertNoDuplicates(aArray, NS_LITERAL_STRING("-moz-repeating-linear-gradient"));
|
||||
InsertNoDuplicates(aArray, NS_LITERAL_STRING("-moz-repeating-radial-gradient"));
|
||||
}
|
||||
if (aParserVariant & VARIANT_ATTR) {
|
||||
InsertNoDuplicates(aArray, NS_LITERAL_STRING("attr"));
|
||||
}
|
||||
if (aParserVariant & VARIANT_COUNTER) {
|
||||
InsertNoDuplicates(aArray, NS_LITERAL_STRING("counter"));
|
||||
InsertNoDuplicates(aArray, NS_LITERAL_STRING("counters"));
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
@ -691,7 +698,6 @@ PropertySupportsVariant(nsCSSPropertyID aPropertyID, uint32_t aVariant)
|
||||
supported |= VARIANT_LENGTH;
|
||||
break;
|
||||
|
||||
case eCSSProperty_content:
|
||||
case eCSSProperty_cursor:
|
||||
supported |= VARIANT_URL;
|
||||
break;
|
||||
|
@ -208,6 +208,14 @@ function do_test() {
|
||||
var values = InspectorUtils.getCSSValuesForProperty("clip");
|
||||
ok(testValues(values, expected), "property clip's values");
|
||||
|
||||
// Regression test for bug 1255380.
|
||||
var expected = [ "normal", "none", "url", "counter", "counters",
|
||||
"attr", "open-quote", "close-quote", "no-open-quote",
|
||||
"no-close-quote", "inherit", "initial", "unset",
|
||||
"-moz-alt-content" ];
|
||||
var values = InspectorUtils.getCSSValuesForProperty("content");
|
||||
ok(testValues(values, expected), "property counter's values");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
@ -62,40 +62,31 @@ b40 {
|
||||
z-index: 1; position:relative;
|
||||
}
|
||||
|
||||
w {
|
||||
position:absolute;
|
||||
background: lime;
|
||||
border-width: 1px 0 0 3px;
|
||||
border-style: solid;
|
||||
height:48px;
|
||||
width:75px;
|
||||
.h.r {
|
||||
height: 42px;
|
||||
width: 42px;
|
||||
/* This margin-left is 20% of 98px-wide grid area */
|
||||
margin-left: 19.6px;
|
||||
/* This padding-bottom is 10% of 98px wide grid area */
|
||||
/* This padding-left is 30% of 98px wide grid area */
|
||||
padding: 1px 3px 9.8px 29.4px;
|
||||
}
|
||||
.v > w {
|
||||
border-width: 3px 0 0 1px;
|
||||
left:-1px; top:-3px;
|
||||
height:53px;
|
||||
width:61px;
|
||||
}
|
||||
.h.r { margin-left:19px; padding: 1px 15px 37px 30px; }
|
||||
.v .h > w {
|
||||
height:48px;
|
||||
width:45px;
|
||||
}
|
||||
.v.r > w {
|
||||
height:53px;
|
||||
width:61px;
|
||||
}
|
||||
.v .v > w {
|
||||
height:41px;
|
||||
width:45px;
|
||||
.v.r {
|
||||
height: 42px;
|
||||
width: 42px;
|
||||
/* This margin-left is 20% of 54px-wide grid area */
|
||||
margin-left: 10.8px;
|
||||
/* This padding-bottom is 10% of 54px wide grid area */
|
||||
/* This padding-left is 30% of 54px wide grid area */
|
||||
padding: 1px 3px 5.4px 16.2px;
|
||||
}
|
||||
|
||||
.r { position:relative; }
|
||||
|
||||
.t6 { width:46px; }
|
||||
.t8 { width:118px; }
|
||||
.t8 { width:118px; height: 102.5px; }
|
||||
|
||||
xx {
|
||||
xx {
|
||||
display: block;
|
||||
background: lime;
|
||||
padding:32px 32px 16px 32px;
|
||||
@ -114,7 +105,7 @@ xx {
|
||||
<div class="grid"><span class="v"><x></x></span></div>
|
||||
<div class="grid t6"><span class="v bb"><x></x></span></div>
|
||||
<div class="grid"><span class="v"><x></x></span><span class="v"><x></x></span></div>
|
||||
<div class="grid t8"><span class="v r"><w></w><b40></b40></span></div>
|
||||
<div class="grid t8"><span class="v r"><b40></b40></span></div>
|
||||
|
||||
<div class="grid"><xx class="v"></xx></div>
|
||||
<div class="grid v"><xx class="h"></xx></div>
|
||||
|
@ -30,8 +30,8 @@ body,html { color:black; background:white; font-size:16px; padding:0; margin:0;
|
||||
}
|
||||
.p { padding:2px 3px; }
|
||||
.m { margin:2px 3px; }
|
||||
.c1.p,.c2.p { padding:5px 9px; }
|
||||
.c1.m,.c2.m { margin:5px 9px; }
|
||||
.c1.p,.c2.p { padding:6px 9px; }
|
||||
.c1.m,.c2.m { margin:6px 9px; }
|
||||
.b { border:solid black; }
|
||||
|
||||
#t1 { width:50px; height: 20px; }
|
||||
|
@ -48,8 +48,8 @@ body,html { color:black; background:white; font-size:16px; padding:0; margin:0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.p { padding:10% 6%; }
|
||||
.m { margin:10% 6%; }
|
||||
.p { padding:4% 6%; }
|
||||
.m { margin:4% 6%; }
|
||||
.b { border:solid black; }
|
||||
|
||||
</style>
|
||||
|
@ -46,8 +46,8 @@ body,html { color:black; background:white; font-size:16px; padding:0; margin:0;
|
||||
|
||||
.p { padding:2px 3px; }
|
||||
.m { margin:2px 3px; }
|
||||
.c1.p,.c2.p { padding:5px 9px; }
|
||||
.c1.m,.c2.m { margin:5px 9px; }
|
||||
.c1.p,.c2.p { padding:6px 9px; }
|
||||
.c1.m,.c2.m { margin:6px 9px; }
|
||||
.b { border:solid black; }
|
||||
|
||||
</style>
|
||||
|
@ -43,7 +43,7 @@ skip-if(Android) fuzzy-if(winWidget,1,32) == grid-placement-auto-implicit-001.ht
|
||||
== vrl-grid-placement-auto-row-sparse-001.html vrl-grid-placement-auto-row-sparse-001-ref.html
|
||||
== grid-relpos-items-001.html grid-relpos-items-001-ref.html
|
||||
== grid-item-sizing-percent-001.html grid-item-sizing-percent-001-ref.html
|
||||
== grid-item-sizing-percent-002.html grid-item-sizing-percent-002-ref.html
|
||||
fails == grid-item-sizing-percent-002.html grid-item-sizing-percent-002-ref.html # bug 1434397
|
||||
== grid-item-sizing-percent-003.html grid-item-sizing-percent-003-ref.html
|
||||
== grid-item-sizing-percent-004.html grid-item-sizing-percent-004-ref.html
|
||||
== grid-item-sizing-px-001.html grid-item-sizing-percent-001-ref.html
|
||||
|
@ -4,8 +4,7 @@
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!-- Reference case - identical to the testcase, but with with the flex items'
|
||||
vertical margin and padding values set to 0 by default, and then set to
|
||||
specific pixel values for the items that have a 50px percent-basis.
|
||||
margin and padding values set to explicit pixel values.
|
||||
-->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
@ -21,27 +20,11 @@
|
||||
}
|
||||
div.height50 { height: 50px; }
|
||||
|
||||
.marginA { margin: 0 8% 0 4%; }
|
||||
.marginB { margin: 0 10% 0 14%; }
|
||||
.paddingA { padding: 0 6% 0 2%; }
|
||||
.paddingB { padding: 0 8% 0 12%; }
|
||||
.marginA { margin: 20px 16px 12px 8px; }
|
||||
.marginB { margin: 16px 20px 24px 28px; }
|
||||
.paddingA { padding: 16px 12px 8px 4px; }
|
||||
.paddingB { padding: 12px 16px 20px 24px; }
|
||||
|
||||
div.height50 > .marginA {
|
||||
margin-top: 5px;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
div.height50 > .marginB {
|
||||
margin-top: 4px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
div.height50 > .paddingA {
|
||||
padding-top: 4px;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
div.height50 > .paddingB {
|
||||
padding-top: 3px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
div.child1 {
|
||||
flex: none;
|
||||
|
@ -3,19 +3,17 @@
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!-- Testcase with percent-valued padding and/or margin on flex items. The spec
|
||||
says that percentage values on padding/margin-top and -bottom should be
|
||||
resolved against the flex container's height (not its width, as would
|
||||
be the case in a block).
|
||||
<!-- Testcase with percent-valued padding and/or margin on flex items.
|
||||
The spec allows these to be resolved against the flex container's
|
||||
inline size (regardless of which axis the percent padding/margin is in).
|
||||
-->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>CSS Test: Testing percent-valued padding and margin on flex items</title>
|
||||
<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com"/>
|
||||
<link rel="help" href="http://www.w3.org/TR/css-flexbox-1/#layout-algorithm"/>
|
||||
<link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#item-margins"/>
|
||||
<link rel="match" href="flexbox-mbp-horiz-004-ref.xhtml"/>
|
||||
<style>
|
||||
div { border: 0; }
|
||||
div.flexbox {
|
||||
width: 200px;
|
||||
display: flex;
|
||||
@ -52,8 +50,9 @@
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Flex container is auto-height - vertical margin and padding should
|
||||
resolve to 0, since they don't have anything to resolve % against. -->
|
||||
<!-- Flex container is auto-height - this shouldn't impact percent
|
||||
margin/padding resolution, since they resolve against container's
|
||||
inline-size, i.e. its width in this case. -->
|
||||
<div class="flexbox"
|
||||
><div class="child1 paddingA"><div class="filler"/></div
|
||||
><div class="child2 paddingB"><div class="filler"/></div
|
||||
@ -61,8 +60,9 @@
|
||||
><div class="child2 marginB"></div
|
||||
></div>
|
||||
|
||||
<!-- Flex container has height: 50px - vertical margin and padding should
|
||||
resolve % values against that. -->
|
||||
<!-- Flex container has height: 50px - again, this shouldn't impact percent
|
||||
margin/padding resolution, since they resolve against container's
|
||||
inline-size, i.e. its width in this case. -->
|
||||
<div class="flexbox height50"
|
||||
><div class="child1 paddingA"><div class="filler"/></div
|
||||
><div class="child2 paddingB"><div class="filler"/></div
|
||||
|
@ -1037,6 +1037,21 @@ AttrHasSuffix(Implementor* aElement, nsAtom* aNS, nsAtom* aName,
|
||||
return DoMatch(aElement, aNS, aName, match);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether an element contains a class in its class list or not.
|
||||
*/
|
||||
template <typename Implementor>
|
||||
static bool
|
||||
HasClass(Implementor* aElement, nsAtom* aClass, bool aIgnoreCase)
|
||||
{
|
||||
const nsAttrValue* attr = aElement->DoGetClasses();
|
||||
if (!attr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return attr->Contains(aClass, aIgnoreCase ? eIgnoreCase : eCaseMatters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the class or class list (if any) of the implementor. The calling
|
||||
* convention here is rather hairy, and is optimized for getting Servo the
|
||||
@ -1106,53 +1121,58 @@ ClassOrClassList(Implementor* aElement, nsAtom** aClass, nsAtom*** aClassList)
|
||||
}
|
||||
|
||||
#define SERVO_IMPL_ELEMENT_ATTR_MATCHING_FUNCTIONS(prefix_, implementor_) \
|
||||
nsAtom* prefix_##AtomAttrValue(implementor_ aElement, nsAtom* aName) \
|
||||
nsAtom* prefix_##AtomAttrValue(implementor_ aElement, nsAtom* aName) \
|
||||
{ \
|
||||
return AtomAttrValue(aElement, aName); \
|
||||
} \
|
||||
nsAtom* prefix_##LangValue(implementor_ aElement) \
|
||||
nsAtom* prefix_##LangValue(implementor_ aElement) \
|
||||
{ \
|
||||
return LangValue(aElement); \
|
||||
} \
|
||||
bool prefix_##HasAttr(implementor_ aElement, nsAtom* aNS, nsAtom* aName) \
|
||||
bool prefix_##HasAttr(implementor_ aElement, nsAtom* aNS, nsAtom* aName) \
|
||||
{ \
|
||||
return HasAttr(aElement, aNS, aName); \
|
||||
} \
|
||||
bool prefix_##AttrEquals(implementor_ aElement, nsAtom* aNS, \
|
||||
nsAtom* aName, nsAtom* aStr, bool aIgnoreCase) \
|
||||
bool prefix_##AttrEquals(implementor_ aElement, nsAtom* aNS, \
|
||||
nsAtom* aName, nsAtom* aStr, bool aIgnoreCase) \
|
||||
{ \
|
||||
return AttrEquals(aElement, aNS, aName, aStr, aIgnoreCase); \
|
||||
} \
|
||||
bool prefix_##AttrDashEquals(implementor_ aElement, nsAtom* aNS, \
|
||||
nsAtom* aName, nsAtom* aStr, bool aIgnoreCase) \
|
||||
bool prefix_##AttrDashEquals(implementor_ aElement, nsAtom* aNS, \
|
||||
nsAtom* aName, nsAtom* aStr, bool aIgnoreCase) \
|
||||
{ \
|
||||
return AttrDashEquals(aElement, aNS, aName, aStr, aIgnoreCase); \
|
||||
} \
|
||||
bool prefix_##AttrIncludes(implementor_ aElement, nsAtom* aNS, \
|
||||
nsAtom* aName, nsAtom* aStr, bool aIgnoreCase) \
|
||||
bool prefix_##AttrIncludes(implementor_ aElement, nsAtom* aNS, \
|
||||
nsAtom* aName, nsAtom* aStr, bool aIgnoreCase) \
|
||||
{ \
|
||||
return AttrIncludes(aElement, aNS, aName, aStr, aIgnoreCase); \
|
||||
} \
|
||||
bool prefix_##AttrHasSubstring(implementor_ aElement, nsAtom* aNS, \
|
||||
nsAtom* aName, nsAtom* aStr, bool aIgnoreCase)\
|
||||
bool prefix_##AttrHasSubstring(implementor_ aElement, nsAtom* aNS, \
|
||||
nsAtom* aName, nsAtom* aStr, bool aIgnoreCase) \
|
||||
{ \
|
||||
return AttrHasSubstring(aElement, aNS, aName, aStr, aIgnoreCase); \
|
||||
} \
|
||||
bool prefix_##AttrHasPrefix(implementor_ aElement, nsAtom* aNS, \
|
||||
nsAtom* aName, nsAtom* aStr, bool aIgnoreCase) \
|
||||
bool prefix_##AttrHasPrefix(implementor_ aElement, nsAtom* aNS, \
|
||||
nsAtom* aName, nsAtom* aStr, bool aIgnoreCase) \
|
||||
{ \
|
||||
return AttrHasPrefix(aElement, aNS, aName, aStr, aIgnoreCase); \
|
||||
} \
|
||||
bool prefix_##AttrHasSuffix(implementor_ aElement, nsAtom* aNS, \
|
||||
nsAtom* aName, nsAtom* aStr, bool aIgnoreCase) \
|
||||
bool prefix_##AttrHasSuffix(implementor_ aElement, nsAtom* aNS, \
|
||||
nsAtom* aName, nsAtom* aStr, bool aIgnoreCase) \
|
||||
{ \
|
||||
return AttrHasSuffix(aElement, aNS, aName, aStr, aIgnoreCase); \
|
||||
} \
|
||||
uint32_t prefix_##ClassOrClassList(implementor_ aElement, nsAtom** aClass, \
|
||||
nsAtom*** aClassList) \
|
||||
uint32_t prefix_##ClassOrClassList(implementor_ aElement, nsAtom** aClass, \
|
||||
nsAtom*** aClassList) \
|
||||
{ \
|
||||
return ClassOrClassList(aElement, aClass, aClassList); \
|
||||
}
|
||||
} \
|
||||
bool prefix_##HasClass(implementor_ aElement, nsAtom* aClass, bool aIgnoreCase)\
|
||||
{ \
|
||||
return HasClass(aElement, aClass, aIgnoreCase); \
|
||||
} \
|
||||
|
||||
|
||||
SERVO_IMPL_ELEMENT_ATTR_MATCHING_FUNCTIONS(Gecko_, RawGeckoElementBorrowed)
|
||||
SERVO_IMPL_ELEMENT_ATTR_MATCHING_FUNCTIONS(Gecko_Snapshot, const ServoElementSnapshot*)
|
||||
|
@ -196,24 +196,26 @@ nsIDocument::DocumentTheme Gecko_GetDocumentLWTheme(const nsIDocument* aDocument
|
||||
|
||||
// Attributes.
|
||||
#define SERVO_DECLARE_ELEMENT_ATTR_MATCHING_FUNCTIONS(prefix_, implementor_) \
|
||||
nsAtom* prefix_##AtomAttrValue(implementor_ element, nsAtom* attribute); \
|
||||
nsAtom* prefix_##LangValue(implementor_ element); \
|
||||
bool prefix_##HasAttr(implementor_ element, nsAtom* ns, nsAtom* name); \
|
||||
bool prefix_##AttrEquals(implementor_ element, nsAtom* ns, nsAtom* name, \
|
||||
nsAtom* str, bool ignoreCase); \
|
||||
bool prefix_##AttrDashEquals(implementor_ element, nsAtom* ns, \
|
||||
nsAtom* name, nsAtom* str, bool ignore_case);\
|
||||
bool prefix_##AttrIncludes(implementor_ element, nsAtom* ns, \
|
||||
nsAtom* name, nsAtom* str, bool ignore_case); \
|
||||
bool prefix_##AttrHasSubstring(implementor_ element, nsAtom* ns, \
|
||||
nsAtom* name, nsAtom* str, \
|
||||
nsAtom* prefix_##AtomAttrValue(implementor_ element, nsAtom* attribute); \
|
||||
nsAtom* prefix_##LangValue(implementor_ element); \
|
||||
bool prefix_##HasAttr(implementor_ element, nsAtom* ns, nsAtom* name); \
|
||||
bool prefix_##AttrEquals(implementor_ element, nsAtom* ns, nsAtom* name, \
|
||||
nsAtom* str, bool ignoreCase); \
|
||||
bool prefix_##AttrDashEquals(implementor_ element, nsAtom* ns, \
|
||||
nsAtom* name, nsAtom* str, bool ignore_case); \
|
||||
bool prefix_##AttrIncludes(implementor_ element, nsAtom* ns, \
|
||||
nsAtom* name, nsAtom* str, bool ignore_case); \
|
||||
bool prefix_##AttrHasSubstring(implementor_ element, nsAtom* ns, \
|
||||
nsAtom* name, nsAtom* str, \
|
||||
bool ignore_case); \
|
||||
bool prefix_##AttrHasPrefix(implementor_ element, nsAtom* ns, \
|
||||
nsAtom* name, nsAtom* str, bool ignore_case); \
|
||||
bool prefix_##AttrHasSuffix(implementor_ element, nsAtom* ns, \
|
||||
nsAtom* name, nsAtom* str, bool ignore_case); \
|
||||
uint32_t prefix_##ClassOrClassList(implementor_ element, nsAtom** class_, \
|
||||
nsAtom*** classList);
|
||||
bool prefix_##AttrHasPrefix(implementor_ element, nsAtom* ns, \
|
||||
nsAtom* name, nsAtom* str, bool ignore_case); \
|
||||
bool prefix_##AttrHasSuffix(implementor_ element, nsAtom* ns, \
|
||||
nsAtom* name, nsAtom* str, bool ignore_case); \
|
||||
uint32_t prefix_##ClassOrClassList(implementor_ element, nsAtom** class_, \
|
||||
nsAtom*** classList); \
|
||||
bool prefix_##HasClass(implementor_ element, nsAtom* class_, \
|
||||
bool ignore_case);
|
||||
|
||||
SERVO_DECLARE_ELEMENT_ATTR_MATCHING_FUNCTIONS(Gecko_, RawGeckoElementBorrowed)
|
||||
SERVO_DECLARE_ELEMENT_ATTR_MATCHING_FUNCTIONS(Gecko_Snapshot,
|
||||
|
@ -1552,7 +1552,7 @@ CSS_PROP_CONTENT(
|
||||
CSS_PROPERTY_PARSE_FUNCTION |
|
||||
CSS_PROPERTY_START_IMAGE_LOADS,
|
||||
"",
|
||||
0,
|
||||
VARIANT_HMK | VARIANT_NONE | VARIANT_URL | VARIANT_COUNTER | VARIANT_ATTR,
|
||||
kContentKTable,
|
||||
CSS_PROP_NO_OFFSET,
|
||||
eStyleAnimType_Discrete)
|
||||
|
@ -6,6 +6,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=812687
|
||||
<head>
|
||||
<title>Test for Bug 812687: focus order of reordered flex items</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" />
|
||||
<style>
|
||||
.container { display: flex; }
|
||||
@ -42,7 +43,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=812687
|
||||
|
||||
/** Test for Bug 812687 **/
|
||||
|
||||
const gKeyCodeForTab = 9;
|
||||
const gExpectedFocusedIds = [
|
||||
"focus1",
|
||||
"focus2",
|
||||
@ -60,7 +60,7 @@ function doTest() {
|
||||
// And then we advance focus across the focusable things in the flex container
|
||||
// and check that we traverse them in the expected order:
|
||||
for (let expectedId of gExpectedFocusedIds) {
|
||||
SpecialPowers.DOMWindowUtils.sendKeyEvent('keypress', gKeyCodeForTab, 0, 0);
|
||||
synthesizeKey("KEY_Tab", {code: "Tab"});
|
||||
is(document.activeElement, document.getElementById(expectedId),
|
||||
"expecting element '#" + expectedId + "' to be focused");
|
||||
}
|
||||
|
@ -52,6 +52,11 @@ SVGContextPaint::IsAllowedForImageFromURI(nsIURI* aURI)
|
||||
// use this feature because we're not sure that image context paint is a
|
||||
// good mechanism for wider use, or suitable for specification.)
|
||||
//
|
||||
// Because the default favicon used in the browser UI needs context paint, we
|
||||
// also allow it for page-icon:<page-url>. This exposes context paint to
|
||||
// 3rd-party favicons, but only for history and bookmark items. Other places
|
||||
// such as the tab bar don't use the page-icon protocol to load favicons.
|
||||
//
|
||||
// One case that is not covered by chrome:// or resource:// are WebExtensions,
|
||||
// specifically ones that are "ours". WebExtensions are moz-extension://
|
||||
// regardless if the extension is in-tree or not. Since we don't want
|
||||
@ -60,7 +65,9 @@ SVGContextPaint::IsAllowedForImageFromURI(nsIURI* aURI)
|
||||
//
|
||||
nsAutoCString scheme;
|
||||
if (NS_SUCCEEDED(aURI->GetScheme(scheme)) &&
|
||||
(scheme.EqualsLiteral("chrome") || scheme.EqualsLiteral("resource"))) {
|
||||
(scheme.EqualsLiteral("chrome")
|
||||
|| scheme.EqualsLiteral("resource")
|
||||
|| scheme.EqualsLiteral("page-icon"))) {
|
||||
return true;
|
||||
}
|
||||
RefPtr<BasePrincipal> principal = BasePrincipal::CreateCodebasePrincipal(aURI, OriginAttributes());
|
||||
|
@ -4343,8 +4343,9 @@ SVGTextFrame::GetStartPositionOfChar(nsIContent* aContent,
|
||||
// We need to return the start position of the whole glyph.
|
||||
uint32_t startIndex = it.GlyphStartTextElementCharIndex();
|
||||
|
||||
NS_ADDREF(*aResult =
|
||||
new DOMSVGPoint(ToPoint(mPositions[startIndex].mPosition)));
|
||||
RefPtr<DOMSVGPoint> point =
|
||||
new DOMSVGPoint(ToPoint(mPositions[startIndex].mPosition));
|
||||
point.forget(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -4388,7 +4389,8 @@ SVGTextFrame::GetEndPositionOfChar(nsIContent* aContent,
|
||||
Matrix::Translation(ToPoint(mPositions[startIndex].mPosition));
|
||||
Point p = m.TransformPoint(Point(advance / mFontSizeScaleFactor, 0));
|
||||
|
||||
NS_ADDREF(*aResult = new DOMSVGPoint(p));
|
||||
RefPtr<DOMSVGPoint> point = new DOMSVGPoint(p);
|
||||
point.forget(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -4455,7 +4457,8 @@ SVGTextFrame::GetExtentOfChar(nsIContent* aContent,
|
||||
// Transform the glyph's rect into user space.
|
||||
gfxRect r = m.TransformBounds(glyphRect);
|
||||
|
||||
NS_ADDREF(*aResult = new dom::SVGRect(aContent, r.x, r.y, r.width, r.height));
|
||||
RefPtr<dom::SVGRect> rect = new dom::SVGRect(aContent, r.x, r.y, r.width, r.height);
|
||||
rect.forget(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -468,7 +468,6 @@
|
||||
@BINPATH@/res/table-remove-row.gif
|
||||
@BINPATH@/res/grabber.gif
|
||||
@BINPATH@/res/dtd/*
|
||||
@BINPATH@/res/html/*
|
||||
@BINPATH@/res/language.properties
|
||||
|
||||
#ifndef MOZ_ANDROID_EXCLUDE_FONTS
|
||||
|
@ -57,6 +57,17 @@
|
||||
*/
|
||||
#if defined(CHROMIUM_SANDBOX_BUILD) && defined(XP_WIN)
|
||||
#include "base/win/sdkdecls.h"
|
||||
#endif
|
||||
|
||||
#ifdef __MINGW32__
|
||||
/*
|
||||
* MinGW doesn't support __try / __except. There are a few mechanisms available
|
||||
* to hack around it and pseudo-support it, but these are untested in Firefox.
|
||||
* What is tested (and works) is replacing them with if(true) and else.
|
||||
*/
|
||||
#define __try if(true)
|
||||
#define __except(x) else
|
||||
|
||||
#endif /* __MINGW32__ */
|
||||
#endif /* defined(CHROMIUM_SANDBOX_BUILD) && defined(XP_WIN) */
|
||||
|
||||
#endif /* MOZILLA_CONFIG_H */
|
||||
|
@ -351,7 +351,7 @@ nsIndexedToHTML::DoOnStartRequest(nsIRequest* request, nsISupports *aContext,
|
||||
" vertical-align: middle;\n"
|
||||
"}\n"
|
||||
".dir::before {\n"
|
||||
" content: url(resource://gre/res/html/folder.png);\n"
|
||||
" content: url(resource://content-accessible/html/folder.png);\n"
|
||||
"}\n"
|
||||
"</style>\n"
|
||||
"<link rel=\"stylesheet\" media=\"screen, projection\" type=\"text/css\""
|
||||
|
@ -66,7 +66,7 @@ W32API_VERSION=3.14
|
||||
GCONF_VERSION=1.2.1
|
||||
STARTUP_NOTIFICATION_VERSION=0.8
|
||||
DBUS_VERSION=0.60
|
||||
SQLITE_VERSION=3.21.0
|
||||
SQLITE_VERSION=3.22.0
|
||||
|
||||
dnl Set various checks
|
||||
dnl ========================================================
|
||||
|
@ -203,6 +203,65 @@ class BuildBackend(LoggingMixin):
|
||||
"""
|
||||
return None
|
||||
|
||||
def _write_purgecaches(self, config):
|
||||
"""Write .purgecaches sentinels.
|
||||
|
||||
The purgecaches mechanism exists to allow the platform to
|
||||
invalidate the XUL cache (which includes some JS) at application
|
||||
startup-time. The application checks for .purgecaches in the
|
||||
application directory, which varies according to
|
||||
--enable-application. There's a further wrinkle on macOS, where
|
||||
the real application directory is part of a Cocoa bundle
|
||||
produced from the regular application directory by the build
|
||||
system. In this case, we write to both locations, since the
|
||||
build system recreates the Cocoa bundle from the contents of the
|
||||
regular application directory and might remove a sentinel
|
||||
created here.
|
||||
"""
|
||||
|
||||
app = config.substs['MOZ_BUILD_APP']
|
||||
if app == 'mobile/android':
|
||||
# In order to take effect, .purgecaches sentinels would need to be
|
||||
# written to the Android device file system.
|
||||
return
|
||||
|
||||
root = mozpath.join(config.topobjdir, 'dist', 'bin')
|
||||
|
||||
if app == 'browser':
|
||||
root = mozpath.join(config.topobjdir, 'dist', 'bin', 'browser')
|
||||
|
||||
purgecaches_dirs = [root]
|
||||
if app == 'browser' and 'cocoa' == config.substs['MOZ_WIDGET_TOOLKIT']:
|
||||
bundledir = mozpath.join(config.topobjdir, 'dist',
|
||||
config.substs['MOZ_MACBUNDLE_NAME'],
|
||||
'Contents', 'Resources',
|
||||
'browser')
|
||||
purgecaches_dirs.append(bundledir)
|
||||
|
||||
for dir in purgecaches_dirs:
|
||||
with open(mozpath.join(dir, '.purgecaches'), 'wt') as f:
|
||||
f.write('\n')
|
||||
|
||||
def post_build(self, config, output, jobs, verbose, status):
|
||||
"""Called late during 'mach build' execution, after `build(...)` has finished.
|
||||
|
||||
`status` is the status value returned from `build(...)`.
|
||||
|
||||
In the case where `build` returns `None`, this is called after
|
||||
the default `make` command has completed, with the status of
|
||||
that command.
|
||||
|
||||
This should return the status value from `build(...)`, or the
|
||||
status value of a subprocess, where 0 denotes success and any
|
||||
other value is an error code.
|
||||
|
||||
If an exception is raised, |mach build| will fail with a
|
||||
non-zero exit code.
|
||||
"""
|
||||
self._write_purgecaches(config)
|
||||
|
||||
return status
|
||||
|
||||
@contextmanager
|
||||
def _write_file(self, path=None, fh=None, mode='rU'):
|
||||
"""Context manager to write a file.
|
||||
|
@ -1078,6 +1078,23 @@ class BuildDriver(MozbuildObject):
|
||||
{'count': len(monitor.warnings_database)},
|
||||
'{count} compiler warnings present.')
|
||||
|
||||
# Try to run the active build backend's post-build step, if possible.
|
||||
try:
|
||||
config = self.config_environment
|
||||
active_backend = config.substs.get('BUILD_BACKENDS', [None])[0]
|
||||
if active_backend:
|
||||
backend_cls = get_backend_class(active_backend)(config)
|
||||
new_status = backend_cls.post_build(self, output, jobs, verbose, status)
|
||||
status = new_status
|
||||
except Exception as ex:
|
||||
self.log(logging.DEBUG, 'post_build', {'ex': ex},
|
||||
"Unable to run active build backend's post-build step; " +
|
||||
"failing the build due to exception: {ex}.")
|
||||
if not status:
|
||||
# If the underlying build provided a failing status, pass
|
||||
# it through; otherwise, fail.
|
||||
status = 1
|
||||
|
||||
monitor.finish(record_usage=status == 0)
|
||||
|
||||
# Print the collected compiler warnings. This is redundant with
|
||||
|
@ -0,0 +1,51 @@
|
||||
# HG changeset patch
|
||||
# User Tom Ritter <tom@mozilla.com>
|
||||
# Date 1516389982 21600
|
||||
# Fri Jan 19 13:26:22 2018 -0600
|
||||
# Node ID 3ca7306d73ebc1ce47ccdc62ee8cbb69a9bfbb2c
|
||||
# Parent 6aa6c7d894609140ccde2e9e50eba8c25a9caeb5
|
||||
Bug 1431803 Disable a specific __try block on MinGW r?bobowen
|
||||
|
||||
This function is a technique to name a thread for debugging purposes,
|
||||
and it always throws an exception (and then continues). On MinGW
|
||||
we don't want it to throw an exception, so we do nothing.
|
||||
|
||||
This means on MinGW we won't get nice thread naming during debugging,
|
||||
but we'll limp along.
|
||||
|
||||
MozReview-Commit-ID: JRKY4wp7sdu
|
||||
|
||||
diff --git a/security/sandbox/chromium/base/threading/platform_thread_win.cc b/security/sandbox/chromium/base/threading/platform_thread_win.cc
|
||||
--- a/security/sandbox/chromium/base/threading/platform_thread_win.cc
|
||||
+++ b/security/sandbox/chromium/base/threading/platform_thread_win.cc
|
||||
@@ -32,27 +32,30 @@ typedef struct tagTHREADNAME_INFO {
|
||||
} THREADNAME_INFO;
|
||||
|
||||
// The SetThreadDescription API was brought in version 1607 of Windows 10.
|
||||
typedef HRESULT(WINAPI* SetThreadDescription)(HANDLE hThread,
|
||||
PCWSTR lpThreadDescription);
|
||||
|
||||
// This function has try handling, so it is separated out of its caller.
|
||||
void SetNameInternal(PlatformThreadId thread_id, const char* name) {
|
||||
+ //This function is only used for debugging purposes, as you can find by its caller
|
||||
+#ifndef __MINGW32__
|
||||
THREADNAME_INFO info;
|
||||
info.dwType = 0x1000;
|
||||
info.szName = name;
|
||||
info.dwThreadID = thread_id;
|
||||
info.dwFlags = 0;
|
||||
|
||||
__try {
|
||||
RaiseException(kVCThreadNameException, 0, sizeof(info)/sizeof(DWORD),
|
||||
reinterpret_cast<DWORD_PTR*>(&info));
|
||||
} __except(EXCEPTION_CONTINUE_EXECUTION) {
|
||||
}
|
||||
+#endif
|
||||
}
|
||||
|
||||
struct ThreadParams {
|
||||
PlatformThread::Delegate* delegate;
|
||||
bool joinable;
|
||||
ThreadPriority priority;
|
||||
};
|
||||
|
3
security/sandbox/chromium-shim/patches/with_update/patch_order.txt
Normal file → Executable file
3
security/sandbox/chromium-shim/patches/with_update/patch_order.txt
Normal file → Executable file
@ -17,4 +17,5 @@ mingw_msvc_requirement_error.patch
|
||||
mingw_copy_s.patch
|
||||
mingw_operator_new.patch
|
||||
mingw_cast_getprocaddress.patch
|
||||
mingw_capitalization.patch
|
||||
mingw_capitalization.patch
|
||||
mingw_disable_one_try.patch
|
@ -37,6 +37,8 @@ typedef HRESULT(WINAPI* SetThreadDescription)(HANDLE hThread,
|
||||
|
||||
// This function has try handling, so it is separated out of its caller.
|
||||
void SetNameInternal(PlatformThreadId thread_id, const char* name) {
|
||||
//This function is only used for debugging purposes, as you can find by its caller
|
||||
#ifndef __MINGW32__
|
||||
THREADNAME_INFO info;
|
||||
info.dwType = 0x1000;
|
||||
info.szName = name;
|
||||
@ -48,6 +50,7 @@ void SetNameInternal(PlatformThreadId thread_id, const char* name) {
|
||||
reinterpret_cast<DWORD_PTR*>(&info));
|
||||
} __except(EXCEPTION_CONTINUE_EXECUTION) {
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
struct ThreadParams {
|
||||
|
@ -868,35 +868,6 @@ add_task(async function test_async_onItemKeywordDeleted() {
|
||||
}
|
||||
});
|
||||
|
||||
add_task(async function test_onItemPostDataChanged() {
|
||||
_("Post data changes should be tracked");
|
||||
|
||||
try {
|
||||
await stopTracking();
|
||||
|
||||
_("Insert a bookmark");
|
||||
let fx_id = PlacesUtils.bookmarks.insertBookmark(
|
||||
PlacesUtils.bookmarks.bookmarksMenuFolder,
|
||||
CommonUtils.makeURI("http://getfirefox.com"),
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"Get Firefox!");
|
||||
let fx_guid = await PlacesUtils.promiseItemGuid(fx_id);
|
||||
_(`Firefox GUID: ${fx_guid}`);
|
||||
|
||||
await startTracking();
|
||||
|
||||
// PlacesUtils.setPostDataForBookmark is deprecated, but still used by
|
||||
// PlacesTransactions.NewBookmark.
|
||||
_("Post data for the bookmark should be ignored");
|
||||
await PlacesUtils.setPostDataForBookmark(fx_id, "postData");
|
||||
await verifyTrackedItems([]);
|
||||
Assert.equal(tracker.score, 0);
|
||||
} finally {
|
||||
_("Clean up.");
|
||||
await cleanup();
|
||||
}
|
||||
});
|
||||
|
||||
add_task(async function test_onItemAnnoChanged() {
|
||||
_("Item annotations should be tracked");
|
||||
|
||||
|
74
servo/Cargo.lock
generated
74
servo/Cargo.lock
generated
@ -744,31 +744,6 @@ name = "either"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "embedding"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"cocoa 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"compositing 0.0.1",
|
||||
"devtools 0.0.1",
|
||||
"euclid 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glutin_app 0.0.1",
|
||||
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libservo 0.0.1",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"msg 0.0.1",
|
||||
"net_traits 0.0.1",
|
||||
"objc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"script_traits 0.0.1",
|
||||
"servo_config 0.0.1",
|
||||
"servo_geometry 0.0.1",
|
||||
"servo_url 0.0.1",
|
||||
"style_traits 0.0.1",
|
||||
"webrender_api 0.57.0 (git+https://github.com/servo/webrender)",
|
||||
"x11 2.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding_rs"
|
||||
version = "0.7.1"
|
||||
@ -1076,34 +1051,6 @@ name = "glob"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "glutin_app"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"compositing 0.0.1",
|
||||
"euclid 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libservo 0.0.1",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"msg 0.0.1",
|
||||
"net_traits 0.0.1",
|
||||
"osmesa-src 17.3.1-devel (git+https://github.com/servo/osmesa-src)",
|
||||
"osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"script_traits 0.0.1",
|
||||
"servo-egl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"servo-glutin 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"servo_config 0.0.1",
|
||||
"servo_geometry 0.0.1",
|
||||
"servo_url 0.0.1",
|
||||
"style_traits 0.0.1",
|
||||
"user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"webrender_api 0.57.0 (git+https://github.com/servo/webrender)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"x11 2.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glx"
|
||||
version = "0.2.2"
|
||||
@ -2621,11 +2568,30 @@ version = "0.0.1"
|
||||
dependencies = [
|
||||
"android_injected_glue 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"browserhtml 0.1.17 (git+https://github.com/browserhtml/browserhtml?branch=crate)",
|
||||
"glutin_app 0.0.1",
|
||||
"compositing 0.0.1",
|
||||
"euclid 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libservo 0.0.1",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"msg 0.0.1",
|
||||
"net_traits 0.0.1",
|
||||
"osmesa-src 17.3.1-devel (git+https://github.com/servo/osmesa-src)",
|
||||
"osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"script_traits 0.0.1",
|
||||
"servo-egl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"servo-glutin 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"servo_config 0.0.1",
|
||||
"servo_geometry 0.0.1",
|
||||
"servo_url 0.0.1",
|
||||
"sig 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"style_traits 0.0.1",
|
||||
"user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"webrender_api 0.57.0 (git+https://github.com/servo/webrender)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"x11 2.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -5,8 +5,6 @@ members = [
|
||||
|
||||
"ports/geckolib",
|
||||
"ports/geckolib/tests",
|
||||
|
||||
"ports/cef",
|
||||
]
|
||||
default-members = [
|
||||
"ports/servo",
|
||||
|
@ -32,7 +32,7 @@ use dom::mouseevent::MouseEvent;
|
||||
use dom::node::{Node, NodeDamage, UnbindContext};
|
||||
use dom::node::{document_from_node, window_from_node};
|
||||
use dom::nodelist::NodeList;
|
||||
use dom::textcontrol::TextControl;
|
||||
use dom::textcontrol::{TextControlElement, TextControlSelection};
|
||||
use dom::validation::Validatable;
|
||||
use dom::validitystate::ValidationFlags;
|
||||
use dom::virtualmethods::VirtualMethods;
|
||||
@ -400,11 +400,7 @@ impl LayoutHTMLInputElementHelpers for LayoutDom<HTMLInputElement> {
|
||||
}
|
||||
}
|
||||
|
||||
impl TextControl for HTMLInputElement {
|
||||
fn textinput(&self) -> &DomRefCell<TextInput<ScriptToConstellationChan>> {
|
||||
&self.textinput
|
||||
}
|
||||
|
||||
impl TextControlElement for HTMLInputElement {
|
||||
// https://html.spec.whatwg.org/multipage/#concept-input-apply
|
||||
fn selection_api_applies(&self) -> bool {
|
||||
match self.input_type() {
|
||||
@ -715,55 +711,53 @@ impl HTMLInputElementMethods for HTMLInputElement {
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-select
|
||||
fn Select(&self) {
|
||||
self.dom_select(); // defined in TextControl trait
|
||||
self.selection().dom_select();
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionstart
|
||||
fn GetSelectionStart(&self) -> Option<u32> {
|
||||
self.get_dom_selection_start()
|
||||
self.selection().dom_start()
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionstart
|
||||
fn SetSelectionStart(&self, start: Option<u32>) -> ErrorResult {
|
||||
self.set_dom_selection_start(start)
|
||||
self.selection().set_dom_start(start)
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionend
|
||||
fn GetSelectionEnd(&self) -> Option<u32> {
|
||||
self.get_dom_selection_end()
|
||||
self.selection().dom_end()
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionend
|
||||
fn SetSelectionEnd(&self, end: Option<u32>) -> ErrorResult {
|
||||
self.set_dom_selection_end(end)
|
||||
self.selection().set_dom_end(end)
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectiondirection
|
||||
fn GetSelectionDirection(&self) -> Option<DOMString> {
|
||||
self.get_dom_selection_direction()
|
||||
self.selection().dom_direction()
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectiondirection
|
||||
fn SetSelectionDirection(&self, direction: Option<DOMString>) -> ErrorResult {
|
||||
self.set_dom_selection_direction(direction)
|
||||
self.selection().set_dom_direction(direction)
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-setselectionrange
|
||||
fn SetSelectionRange(&self, start: u32, end: u32, direction: Option<DOMString>) -> ErrorResult {
|
||||
self.set_dom_selection_range(start, end, direction)
|
||||
self.selection().set_dom_range(start, end, direction)
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-setrangetext
|
||||
fn SetRangeText(&self, replacement: DOMString) -> ErrorResult {
|
||||
// defined in TextControl trait
|
||||
self.set_dom_range_text(replacement, None, None, Default::default())
|
||||
self.selection().set_dom_range_text(replacement, None, None, Default::default())
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-setrangetext
|
||||
fn SetRangeText_(&self, replacement: DOMString, start: u32, end: u32,
|
||||
selection_mode: SelectionMode) -> ErrorResult {
|
||||
// defined in TextControl trait
|
||||
self.set_dom_range_text(replacement, Some(start), Some(end), selection_mode)
|
||||
self.selection().set_dom_range_text(replacement, Some(start), Some(end), selection_mode)
|
||||
}
|
||||
|
||||
// Select the files based on filepaths passed in,
|
||||
@ -1104,6 +1098,11 @@ impl HTMLInputElement {
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unrooted_must_root)]
|
||||
fn selection(&self) -> TextControlSelection<Self> {
|
||||
TextControlSelection::new(&self, &self.textinput)
|
||||
}
|
||||
}
|
||||
|
||||
impl VirtualMethods for HTMLInputElement {
|
||||
|
@ -25,7 +25,7 @@ use dom::keyboardevent::KeyboardEvent;
|
||||
use dom::node::{ChildrenMutation, Node, NodeDamage, UnbindContext};
|
||||
use dom::node::{document_from_node, window_from_node};
|
||||
use dom::nodelist::NodeList;
|
||||
use dom::textcontrol::TextControl;
|
||||
use dom::textcontrol::{TextControlElement, TextControlSelection};
|
||||
use dom::validation::Validatable;
|
||||
use dom::virtualmethods::VirtualMethods;
|
||||
use dom_struct::dom_struct;
|
||||
@ -145,11 +145,7 @@ impl HTMLTextAreaElement {
|
||||
}
|
||||
}
|
||||
|
||||
impl TextControl for HTMLTextAreaElement {
|
||||
fn textinput(&self) -> &DomRefCell<TextInput<ScriptToConstellationChan>> {
|
||||
&self.textinput
|
||||
}
|
||||
|
||||
impl TextControlElement for HTMLTextAreaElement {
|
||||
fn selection_api_applies(&self) -> bool {
|
||||
true
|
||||
}
|
||||
@ -277,55 +273,53 @@ impl HTMLTextAreaElementMethods for HTMLTextAreaElement {
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-select
|
||||
fn Select(&self) {
|
||||
self.dom_select(); // defined in TextControl trait
|
||||
self.selection().dom_select();
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionstart
|
||||
fn GetSelectionStart(&self) -> Option<u32> {
|
||||
self.get_dom_selection_start()
|
||||
self.selection().dom_start()
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionstart
|
||||
fn SetSelectionStart(&self, start: Option<u32>) -> ErrorResult {
|
||||
self.set_dom_selection_start(start)
|
||||
self.selection().set_dom_start(start)
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionend
|
||||
fn GetSelectionEnd(&self) -> Option<u32> {
|
||||
self.get_dom_selection_end()
|
||||
self.selection().dom_end()
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionend
|
||||
fn SetSelectionEnd(&self, end: Option<u32>) -> ErrorResult {
|
||||
self.set_dom_selection_end(end)
|
||||
self.selection().set_dom_end(end)
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectiondirection
|
||||
fn GetSelectionDirection(&self) -> Option<DOMString> {
|
||||
self.get_dom_selection_direction()
|
||||
self.selection().dom_direction()
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectiondirection
|
||||
fn SetSelectionDirection(&self, direction: Option<DOMString>) -> ErrorResult {
|
||||
self.set_dom_selection_direction(direction)
|
||||
self.selection().set_dom_direction(direction)
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-setselectionrange
|
||||
fn SetSelectionRange(&self, start: u32, end: u32, direction: Option<DOMString>) -> ErrorResult {
|
||||
self.set_dom_selection_range(start, end, direction)
|
||||
self.selection().set_dom_range(start, end, direction)
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-setrangetext
|
||||
fn SetRangeText(&self, replacement: DOMString) -> ErrorResult {
|
||||
// defined in TextControl trait
|
||||
self.set_dom_range_text(replacement, None, None, Default::default())
|
||||
self.selection().set_dom_range_text(replacement, None, None, Default::default())
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-setrangetext
|
||||
fn SetRangeText_(&self, replacement: DOMString, start: u32, end: u32,
|
||||
selection_mode: SelectionMode) -> ErrorResult {
|
||||
// defined in TextControl trait
|
||||
self.set_dom_range_text(replacement, Some(start), Some(end), selection_mode)
|
||||
self.selection().set_dom_range_text(replacement, Some(start), Some(end), selection_mode)
|
||||
}
|
||||
}
|
||||
|
||||
@ -336,6 +330,11 @@ impl HTMLTextAreaElement {
|
||||
self.SetValue(self.DefaultValue());
|
||||
self.value_dirty.set(false);
|
||||
}
|
||||
|
||||
#[allow(unrooted_must_root)]
|
||||
fn selection(&self) -> TextControlSelection<Self> {
|
||||
TextControlSelection::new(&self, &self.textinput)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -2,6 +2,11 @@
|
||||
* 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/. */
|
||||
|
||||
//! This is an abstraction used by `HTMLInputElement` and `HTMLTextAreaElement` to implement the
|
||||
//! text control selection DOM API.
|
||||
//!
|
||||
//! https://html.spec.whatwg.org/multipage/#textFieldSelection
|
||||
|
||||
use dom::bindings::cell::DomRefCell;
|
||||
use dom::bindings::codegen::Bindings::HTMLFormElementBinding::SelectionMode;
|
||||
use dom::bindings::conversions::DerivedFrom;
|
||||
@ -13,43 +18,53 @@ use dom::node::{Node, NodeDamage, window_from_node};
|
||||
use script_traits::ScriptToConstellationChan;
|
||||
use textinput::{SelectionDirection, SelectionState, TextInput};
|
||||
|
||||
pub trait TextControl: DerivedFrom<EventTarget> + DerivedFrom<Node> {
|
||||
fn textinput(&self) -> &DomRefCell<TextInput<ScriptToConstellationChan>>;
|
||||
pub trait TextControlElement: DerivedFrom<EventTarget> + DerivedFrom<Node> {
|
||||
fn selection_api_applies(&self) -> bool;
|
||||
fn has_selectable_text(&self) -> bool;
|
||||
fn set_dirty_value_flag(&self, value: bool);
|
||||
}
|
||||
|
||||
pub struct TextControlSelection<'a, E: TextControlElement> {
|
||||
element: &'a E,
|
||||
textinput: &'a DomRefCell<TextInput<ScriptToConstellationChan>>,
|
||||
}
|
||||
|
||||
impl<'a, E: TextControlElement> TextControlSelection<'a, E> {
|
||||
pub fn new(element: &'a E, textinput: &'a DomRefCell<TextInput<ScriptToConstellationChan>>) -> Self {
|
||||
TextControlSelection { element, textinput }
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-select
|
||||
fn dom_select(&self) {
|
||||
pub fn dom_select(&self) {
|
||||
// Step 1
|
||||
if !self.has_selectable_text() {
|
||||
if !self.element.has_selectable_text() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 2
|
||||
self.set_selection_range(Some(0), Some(u32::max_value()), None, None);
|
||||
self.set_range(Some(0), Some(u32::max_value()), None, None);
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionstart
|
||||
fn get_dom_selection_start(&self) -> Option<u32> {
|
||||
pub fn dom_start(&self) -> Option<u32> {
|
||||
// Step 1
|
||||
if !self.selection_api_applies() {
|
||||
if !self.element.selection_api_applies() {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Steps 2-3
|
||||
Some(self.selection_start())
|
||||
Some(self.start())
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionstart
|
||||
fn set_dom_selection_start(&self, start: Option<u32>) -> ErrorResult {
|
||||
pub fn set_dom_start(&self, start: Option<u32>) -> ErrorResult {
|
||||
// Step 1
|
||||
if !self.selection_api_applies() {
|
||||
if !self.element.selection_api_applies() {
|
||||
return Err(Error::InvalidState);
|
||||
}
|
||||
|
||||
// Step 2
|
||||
let mut end = self.selection_end();
|
||||
let mut end = self.end();
|
||||
|
||||
// Step 3
|
||||
if let Some(s) = start {
|
||||
@ -59,54 +74,54 @@ pub trait TextControl: DerivedFrom<EventTarget> + DerivedFrom<Node> {
|
||||
}
|
||||
|
||||
// Step 4
|
||||
self.set_selection_range(start, Some(end), Some(self.selection_direction()), None);
|
||||
self.set_range(start, Some(end), Some(self.direction()), None);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionend
|
||||
fn get_dom_selection_end(&self) -> Option<u32> {
|
||||
pub fn dom_end(&self) -> Option<u32> {
|
||||
// Step 1
|
||||
if !self.selection_api_applies() {
|
||||
if !self.element.selection_api_applies() {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Steps 2-3
|
||||
Some(self.selection_end())
|
||||
Some(self.end())
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionend
|
||||
fn set_dom_selection_end(&self, end: Option<u32>) -> ErrorResult {
|
||||
pub fn set_dom_end(&self, end: Option<u32>) -> ErrorResult {
|
||||
// Step 1
|
||||
if !self.selection_api_applies() {
|
||||
if !self.element.selection_api_applies() {
|
||||
return Err(Error::InvalidState);
|
||||
}
|
||||
|
||||
// Step 2
|
||||
self.set_selection_range(Some(self.selection_start()), end, Some(self.selection_direction()), None);
|
||||
self.set_range(Some(self.start()), end, Some(self.direction()), None);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectiondirection
|
||||
fn get_dom_selection_direction(&self) -> Option<DOMString> {
|
||||
pub fn dom_direction(&self) -> Option<DOMString> {
|
||||
// Step 1
|
||||
if !self.selection_api_applies() {
|
||||
if !self.element.selection_api_applies() {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(DOMString::from(self.selection_direction()))
|
||||
Some(DOMString::from(self.direction()))
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectiondirection
|
||||
fn set_dom_selection_direction(&self, direction: Option<DOMString>) -> ErrorResult {
|
||||
pub fn set_dom_direction(&self, direction: Option<DOMString>) -> ErrorResult {
|
||||
// Step 1
|
||||
if !self.selection_api_applies() {
|
||||
if !self.element.selection_api_applies() {
|
||||
return Err(Error::InvalidState);
|
||||
}
|
||||
|
||||
// Step 2
|
||||
self.set_selection_range(
|
||||
Some(self.selection_start()),
|
||||
Some(self.selection_end()),
|
||||
self.set_range(
|
||||
Some(self.start()),
|
||||
Some(self.end()),
|
||||
direction.map(|d| SelectionDirection::from(d)),
|
||||
None
|
||||
);
|
||||
@ -114,31 +129,36 @@ pub trait TextControl: DerivedFrom<EventTarget> + DerivedFrom<Node> {
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-setselectionrange
|
||||
fn set_dom_selection_range(&self, start: u32, end: u32, direction: Option<DOMString>) -> ErrorResult {
|
||||
pub fn set_dom_range(&self, start: u32, end: u32, direction: Option<DOMString>) -> ErrorResult {
|
||||
// Step 1
|
||||
if !self.selection_api_applies() {
|
||||
if !self.element.selection_api_applies() {
|
||||
return Err(Error::InvalidState);
|
||||
}
|
||||
|
||||
// Step 2
|
||||
self.set_selection_range(Some(start), Some(end), direction.map(|d| SelectionDirection::from(d)), None);
|
||||
self.set_range(Some(start), Some(end), direction.map(|d| SelectionDirection::from(d)), None);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-setrangetext
|
||||
fn set_dom_range_text(&self, replacement: DOMString, start: Option<u32>, end: Option<u32>,
|
||||
selection_mode: SelectionMode) -> ErrorResult {
|
||||
pub fn set_dom_range_text(
|
||||
&self,
|
||||
replacement: DOMString,
|
||||
start: Option<u32>,
|
||||
end: Option<u32>,
|
||||
selection_mode: SelectionMode
|
||||
) -> ErrorResult {
|
||||
// Step 1
|
||||
if !self.selection_api_applies() {
|
||||
if !self.element.selection_api_applies() {
|
||||
return Err(Error::InvalidState);
|
||||
}
|
||||
|
||||
// Step 2
|
||||
self.set_dirty_value_flag(true);
|
||||
self.element.set_dirty_value_flag(true);
|
||||
|
||||
// Step 3
|
||||
let mut start = start.unwrap_or_else(|| self.selection_start());
|
||||
let mut end = end.unwrap_or_else(|| self.selection_end());
|
||||
let mut start = start.unwrap_or_else(|| self.start());
|
||||
let mut end = end.unwrap_or_else(|| self.end());
|
||||
|
||||
// Step 4
|
||||
if start > end {
|
||||
@ -147,9 +167,9 @@ pub trait TextControl: DerivedFrom<EventTarget> + DerivedFrom<Node> {
|
||||
|
||||
// Save the original selection state to later pass to set_selection_range, because we will
|
||||
// change the selection state in order to replace the text in the range.
|
||||
let original_selection_state = self.textinput().borrow().selection_state();
|
||||
let original_selection_state = self.textinput.borrow().selection_state();
|
||||
|
||||
let content_length = self.textinput().borrow().len() as u32;
|
||||
let content_length = self.textinput.borrow().len() as u32;
|
||||
|
||||
// Step 5
|
||||
if start > content_length {
|
||||
@ -162,10 +182,10 @@ pub trait TextControl: DerivedFrom<EventTarget> + DerivedFrom<Node> {
|
||||
}
|
||||
|
||||
// Step 7
|
||||
let mut selection_start = self.selection_start();
|
||||
let mut selection_start = self.start();
|
||||
|
||||
// Step 8
|
||||
let mut selection_end = self.selection_end();
|
||||
let mut selection_end = self.end();
|
||||
|
||||
// Step 11
|
||||
// Must come before the textinput.replace_selection() call, as replacement gets moved in
|
||||
@ -173,7 +193,7 @@ pub trait TextControl: DerivedFrom<EventTarget> + DerivedFrom<Node> {
|
||||
let new_length = replacement.len() as u32;
|
||||
|
||||
{
|
||||
let mut textinput = self.textinput().borrow_mut();
|
||||
let mut textinput = self.textinput.borrow_mut();
|
||||
|
||||
// Steps 9-10
|
||||
textinput.set_selection_range(start, end, SelectionDirection::None);
|
||||
@ -224,32 +244,31 @@ pub trait TextControl: DerivedFrom<EventTarget> + DerivedFrom<Node> {
|
||||
}
|
||||
|
||||
// Step 14
|
||||
self.set_selection_range(
|
||||
Some(selection_start),
|
||||
Some(selection_end),
|
||||
None,
|
||||
Some(original_selection_state)
|
||||
);
|
||||
|
||||
self.set_range(Some(selection_start), Some(selection_end), None, Some(original_selection_state));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn selection_start(&self) -> u32 {
|
||||
self.textinput().borrow().selection_start_offset() as u32
|
||||
fn start(&self) -> u32 {
|
||||
self.textinput.borrow().selection_start_offset() as u32
|
||||
}
|
||||
|
||||
fn selection_end(&self) -> u32 {
|
||||
self.textinput().borrow().selection_end_offset() as u32
|
||||
fn end(&self) -> u32 {
|
||||
self.textinput.borrow().selection_end_offset() as u32
|
||||
}
|
||||
|
||||
fn selection_direction(&self) -> SelectionDirection {
|
||||
self.textinput().borrow().selection_direction
|
||||
fn direction(&self) -> SelectionDirection {
|
||||
self.textinput.borrow().selection_direction
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#set-the-selection-range
|
||||
fn set_selection_range(&self, start: Option<u32>, end: Option<u32>, direction: Option<SelectionDirection>,
|
||||
original_selection_state: Option<SelectionState>) {
|
||||
let mut textinput = self.textinput().borrow_mut();
|
||||
fn set_range(
|
||||
&self,
|
||||
start: Option<u32>,
|
||||
end: Option<u32>,
|
||||
direction: Option<SelectionDirection>,
|
||||
original_selection_state: Option<SelectionState>
|
||||
) {
|
||||
let mut textinput = self.textinput.borrow_mut();
|
||||
let original_selection_state = original_selection_state.unwrap_or_else(|| textinput.selection_state());
|
||||
|
||||
// Step 1
|
||||
@ -263,15 +282,15 @@ pub trait TextControl: DerivedFrom<EventTarget> + DerivedFrom<Node> {
|
||||
|
||||
// Step 6
|
||||
if textinput.selection_state() != original_selection_state {
|
||||
let window = window_from_node(self);
|
||||
let window = window_from_node(self.element);
|
||||
window.user_interaction_task_source().queue_event(
|
||||
&self.upcast::<EventTarget>(),
|
||||
&self.element.upcast::<EventTarget>(),
|
||||
atom!("select"),
|
||||
EventBubbles::Bubbles,
|
||||
EventCancelable::NotCancelable,
|
||||
&window);
|
||||
}
|
||||
|
||||
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
||||
self.element.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ use style_traits::ParseError;
|
||||
use stylesheets::UrlExtraData;
|
||||
|
||||
/// Errors that can be encountered while parsing CSS.
|
||||
#[derive(Debug)]
|
||||
pub enum ContextualParseError<'a> {
|
||||
/// A property declaration was not recognized.
|
||||
UnsupportedPropertyDeclaration(&'a str, ParseError<'a>),
|
||||
|
@ -724,6 +724,13 @@ extern "C" {
|
||||
classList: *mut *mut *mut nsAtom,
|
||||
) -> u32;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Gecko_HasClass(
|
||||
element: RawGeckoElementBorrowed,
|
||||
class_: *mut nsAtom,
|
||||
ignore_case: bool,
|
||||
) -> bool;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Gecko_SnapshotAtomAttrValue(
|
||||
element: *const ServoElementSnapshot,
|
||||
@ -801,6 +808,13 @@ extern "C" {
|
||||
classList: *mut *mut *mut nsAtom,
|
||||
) -> u32;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Gecko_SnapshotHasClass(
|
||||
element: *const ServoElementSnapshot,
|
||||
class_: *mut nsAtom,
|
||||
ignore_case: bool,
|
||||
) -> bool;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Gecko_GetStyleAttrDeclarationBlock(
|
||||
element: RawGeckoElementBorrowed,
|
||||
|
@ -185,10 +185,12 @@ impl ElementSnapshot for GeckoElementSnapshot {
|
||||
return false;
|
||||
}
|
||||
|
||||
snapshot_helpers::has_class(self.as_ptr(),
|
||||
name,
|
||||
case_sensitivity,
|
||||
bindings::Gecko_SnapshotClassOrClassList)
|
||||
snapshot_helpers::has_class(
|
||||
self.as_ptr(),
|
||||
name,
|
||||
case_sensitivity,
|
||||
bindings::Gecko_SnapshotHasClass,
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -200,9 +202,11 @@ impl ElementSnapshot for GeckoElementSnapshot {
|
||||
return;
|
||||
}
|
||||
|
||||
snapshot_helpers::each_class(self.as_ptr(),
|
||||
callback,
|
||||
bindings::Gecko_SnapshotClassOrClassList)
|
||||
snapshot_helpers::each_class(
|
||||
self.as_ptr(),
|
||||
callback,
|
||||
bindings::Gecko_SnapshotClassOrClassList,
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -4,9 +4,7 @@
|
||||
|
||||
//! Element an snapshot common logic.
|
||||
|
||||
use CaseSensitivityExt;
|
||||
use gecko_bindings::structs::nsAtom;
|
||||
use gecko_string_cache::WeakAtom;
|
||||
use selectors::attr::CaseSensitivity;
|
||||
use std::{ptr, slice};
|
||||
use string_cache::Atom;
|
||||
@ -15,34 +13,27 @@ use string_cache::Atom;
|
||||
/// class or a class list.
|
||||
pub type ClassOrClassList<T> = unsafe extern fn (T, *mut *mut nsAtom, *mut *mut *mut nsAtom) -> u32;
|
||||
|
||||
/// A function to return whether an element of type `T` has a given class.
|
||||
///
|
||||
/// The `bool` argument represents whether it should compare case-insensitively
|
||||
/// or not.
|
||||
pub type HasClass<T> = unsafe extern fn (T, *mut nsAtom, bool) -> bool;
|
||||
|
||||
/// Given an item `T`, a class name, and a getter function, return whether that
|
||||
/// element has the class that `name` represents.
|
||||
#[inline(always)]
|
||||
pub fn has_class<T>(
|
||||
item: T,
|
||||
name: &Atom,
|
||||
case_sensitivity: CaseSensitivity,
|
||||
getter: ClassOrClassList<T>,
|
||||
getter: HasClass<T>,
|
||||
) -> bool {
|
||||
unsafe {
|
||||
let mut class: *mut nsAtom = ptr::null_mut();
|
||||
let mut list: *mut *mut nsAtom = ptr::null_mut();
|
||||
let length = getter(item, &mut class, &mut list);
|
||||
match length {
|
||||
0 => false,
|
||||
1 => case_sensitivity.eq_atom(name, WeakAtom::new(class)),
|
||||
n => {
|
||||
let classes = slice::from_raw_parts(list, n as usize);
|
||||
match case_sensitivity {
|
||||
CaseSensitivity::CaseSensitive => {
|
||||
classes.iter().any(|ptr| &**name == WeakAtom::new(*ptr))
|
||||
}
|
||||
CaseSensitivity::AsciiCaseInsensitive => {
|
||||
classes.iter().any(|ptr| name.eq_ignore_ascii_case(WeakAtom::new(*ptr)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let ignore_case = match case_sensitivity {
|
||||
CaseSensitivity::CaseSensitive => false,
|
||||
CaseSensitivity::AsciiCaseInsensitive => true,
|
||||
};
|
||||
|
||||
unsafe { getter(item, name.as_ptr(), ignore_case) }
|
||||
}
|
||||
|
||||
|
||||
|
@ -2195,7 +2195,7 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
||||
self.0,
|
||||
name,
|
||||
case_sensitivity,
|
||||
Gecko_ClassOrClassList,
|
||||
bindings::Gecko_HasClass,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,6 @@
|
||||
//! [cssparser]: ../cssparser/index.html
|
||||
//! [selectors]: ../selectors/index.html
|
||||
|
||||
#![deny(warnings)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
#![recursion_limit = "500"] // For define_css_keyword_enum! in -moz-appearance
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user