Merge mozilla-central to mozilla-inbound

This commit is contained in:
Carsten "Tomcat" Book 2017-03-16 15:39:58 +01:00
commit 023d5aecd1
322 changed files with 5924 additions and 3686 deletions

View File

@ -1,6 +1,8 @@
[{
[
{
"size": 746441603,
"digest": "199236aefecc1657cdc1b791ec38c8184557ab9249aff9c63a74abf73edc1dc0ea36b19b558f34ca3b14f8a511b10bcf37408b19701929522b4dc22dbaddcbe9",
"algorithm": "sha512",
"filename": "emulator.zip"
}]
}
]

View File

@ -162,7 +162,6 @@ pref("extensions.update.background.url", "https://versioncheck-bg.addons.mozilla
pref("extensions.update.interval", 86400); // Check for updates to Extensions and
// Themes every day
// Non-symmetric (not shared by extensions) extension-specific [update] preferences
pref("extensions.dss.enabled", false); // Dynamic Skin Switching
pref("extensions.dss.switchPending", false); // Non-dynamic switch pending after next
// restart.

View File

@ -255,7 +255,7 @@
let learnMoreLink = document.getElementById("learnMoreLink");
// nssFailure2 also gets us other non-overrideable errors. Choose
// a "learn more" link based on description:
if (getDescription().includes("mozilla_pkix_error_key_pinning_failure")) {
if (getDescription().includes("MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE")) {
learnMoreLink.href = "https://support.mozilla.org/kb/certificate-pinning-reports";
}

View File

@ -572,7 +572,7 @@ toolbar:not(#TabsToolbar) > #personal-bookmarks {
transition: none;
}
#DateTimePickerPanel {
#DateTimePickerPanel[active="true"] {
-moz-binding: url("chrome://global/content/bindings/datetimepopup.xml#datetime-popup");
}

View File

@ -0,0 +1,8 @@
[DEFAULT]
support-files =
head.js
[browser_selectpopup.js]
skip-if = os == "linux" # Bug 1329991 - test fails intermittently on Linux builds
[browser_selectpopup_colors.js]
skip-if = os == "linux" # Bug 1329991 - test fails intermittently on Linux builds

View File

@ -79,52 +79,6 @@ const PAGECONTENT_TRANSLATED =
"</iframe>" +
"</div></body></html>";
const PAGECONTENT_COLORS =
"<html><head><style>" +
" .blue { color: #fff; background-color: #00f; }" +
" .green { color: #800080; background-color: green; }" +
" .defaultColor { color: -moz-ComboboxText; }" +
" .defaultBackground { background-color: -moz-Combobox; }" +
"</style>" +
"<body><select id='one'>" +
' <option value="One" style="color: #fff; background-color: #f00;">{"color": "rgb(255, 255, 255)", "backgroundColor": "rgb(255, 0, 0)"}</option>' +
' <option value="Two" class="blue">{"color": "rgb(255, 255, 255)", "backgroundColor": "rgb(0, 0, 255)"}</option>' +
' <option value="Three" class="green">{"color": "rgb(128, 0, 128)", "backgroundColor": "rgb(0, 128, 0)"}</option>' +
' <option value="Four" class="defaultColor defaultBackground">{"color": "-moz-ComboboxText", "backgroundColor": "rgba(0, 0, 0, 0)", "unstyled": "true"}</option>' +
' <option value="Five" class="defaultColor">{"color": "-moz-ComboboxText", "backgroundColor": "rgba(0, 0, 0, 0)", "unstyled": "true"}</option>' +
' <option value="Six" class="defaultBackground">{"color": "-moz-ComboboxText", "backgroundColor": "rgba(0, 0, 0, 0)", "unstyled": "true"}</option>' +
' <option value="Seven" selected="true">{"unstyled": "true"}</option>' +
"</select></body></html>";
const PAGECONTENT_COLORS_ON_SELECT =
"<html><head><style>" +
" #one { background-color: #7E3A3A; color: #fff }" +
"</style>" +
"<body><select id='one'>" +
' <option value="One">{"color": "rgb(255, 255, 255)", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
' <option value="Two">{"color": "rgb(255, 255, 255)", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
' <option value="Three">{"color": "rgb(255, 255, 255)", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
' <option value="Four" selected="true">{"end": "true"}</option>' +
"</select></body></html>";
const TRANSPARENT_SELECT =
"<html><head><style>" +
" #one { background-color: transparent; }" +
"</style>" +
"<body><select id='one'>" +
' <option value="One">{"unstyled": "true"}</option>' +
' <option value="Two" selected="true">{"end": "true"}</option>' +
"</select></body></html>";
const OPTION_COLOR_EQUAL_TO_UABACKGROUND_COLOR_SELECT =
"<html><head><style>" +
" #one { background-color: black; color: white; }" +
"</style>" +
"<body><select id='one'>" +
' <option value="One" style="background-color: white; color: black;">{"color": "rgb(0, 0, 0)", "backgroundColor": "rgb(255, 255, 255)"}</option>' +
' <option value="Two" selected="true">{"end": "true"}</option>' +
"</select></body></html>";
function openSelectPopup(selectPopup, mode = "key", selector = "select", win = window) {
let popupShownPromise = BrowserTestUtils.waitForEvent(selectPopup, "popupshown");
@ -143,24 +97,6 @@ function openSelectPopup(selectPopup, mode = "key", selector = "select", win = w
return popupShownPromise;
}
function hideSelectPopup(selectPopup, mode = "enter", win = window) {
let browser = win.gBrowser.selectedBrowser;
let selectClosedPromise = ContentTask.spawn(browser, null, function*() {
Cu.import("resource://gre/modules/SelectContentHelper.jsm");
return ContentTaskUtils.waitForCondition(() => !SelectContentHelper.open);
});
if (mode == "escape") {
EventUtils.synthesizeKey("KEY_Escape", { code: "Escape" }, win);
} else if (mode == "enter") {
EventUtils.synthesizeKey("KEY_Enter", { code: "Enter" }, win);
} else if (mode == "click") {
EventUtils.synthesizeMouseAtCenter(selectPopup.lastChild, { }, win);
}
return selectClosedPromise;
}
function getInputEvents() {
return ContentTask.spawn(gBrowser.selectedBrowser, {}, function() {
return content.wrappedJSObject.gInputEvents;
@ -179,44 +115,6 @@ function getClickEvents() {
});
}
function getSystemColor(color) {
// Need to convert system color to RGB color.
let textarea = document.createElementNS("http://www.w3.org/1999/xhtml", "textarea");
textarea.style.color = color;
return getComputedStyle(textarea).color;
}
function testOptionColors(index, item, menulist) {
// The label contains a JSON string of the expected colors for
// `color` and `background-color`.
let expected = JSON.parse(item.label);
for (let color of Object.keys(expected)) {
if (color.toLowerCase().includes("color") &&
!expected[color].startsWith("rgb")) {
expected[color] = getSystemColor(expected[color]);
}
}
// Press Down to move the selected item to the next item in the
// list and check the colors of this item when it's not selected.
EventUtils.synthesizeKey("KEY_ArrowDown", { code: "ArrowDown" });
if (expected.end) {
return;
}
if (expected.unstyled) {
ok(!item.hasAttribute("customoptionstyling"),
`Item ${index} should not have any custom option styling`);
} else {
is(getComputedStyle(item).color, expected.color,
"Item " + (index) + " has correct foreground color");
is(getComputedStyle(item).backgroundColor, expected.backgroundColor,
"Item " + (index) + " has correct background color");
}
}
function* doSelectTests(contentType, dtd) {
const pageUrl = "data:" + contentType + "," + escape(dtd + "\n" + PAGECONTENT);
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, pageUrl);
@ -830,101 +728,6 @@ add_task(function* test_somehidden() {
yield BrowserTestUtils.removeTab(tab);
});
// This test checks when a <select> element has styles applied to <option>s within it.
add_task(function* test_colors_applied_to_popup_items() {
const pageUrl = "data:text/html," + escape(PAGECONTENT_COLORS);
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, pageUrl);
let menulist = document.getElementById("ContentSelectDropdown");
let selectPopup = menulist.menupopup;
let popupShownPromise = BrowserTestUtils.waitForEvent(selectPopup, "popupshown");
yield BrowserTestUtils.synthesizeMouseAtCenter("#one", { type: "mousedown" }, gBrowser.selectedBrowser);
yield popupShownPromise;
// The label contains a JSON string of the expected colors for
// `color` and `background-color`.
is(selectPopup.parentNode.itemCount, 7, "Correct number of items");
let child = selectPopup.firstChild;
let idx = 1;
ok(!child.selected, "The first child should not be selected");
while (child) {
testOptionColors(idx, child, menulist);
idx++;
child = child.nextSibling;
}
yield hideSelectPopup(selectPopup, "escape");
yield BrowserTestUtils.removeTab(tab);
});
// This test checks when a <select> element has styles applied to itself.
add_task(function* test_colors_applied_to_popup() {
const pageUrl = "data:text/html," + escape(PAGECONTENT_COLORS_ON_SELECT);
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, pageUrl);
let menulist = document.getElementById("ContentSelectDropdown");
let selectPopup = menulist.menupopup;
let popupShownPromise = BrowserTestUtils.waitForEvent(selectPopup, "popupshown");
yield BrowserTestUtils.synthesizeMouseAtCenter("#one", { type: "mousedown" }, gBrowser.selectedBrowser);
yield popupShownPromise;
is(selectPopup.parentNode.itemCount, 4, "Correct number of items");
let child = selectPopup.firstChild;
let idx = 1;
is(getComputedStyle(selectPopup).color, "rgb(255, 255, 255)",
"popup has expected foreground color");
is(getComputedStyle(selectPopup).backgroundColor, "rgb(126, 58, 58)",
"popup has expected background color");
ok(!child.selected, "The first child should not be selected");
while (child) {
testOptionColors(idx, child, menulist);
idx++;
child = child.nextSibling;
}
yield hideSelectPopup(selectPopup, "escape");
yield BrowserTestUtils.removeTab(tab);
});
// This test checks when a <select> element has a transparent background applied to itself.
add_task(function* test_transparent_applied_to_popup() {
const pageUrl = "data:text/html," + escape(TRANSPARENT_SELECT);
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, pageUrl);
let menulist = document.getElementById("ContentSelectDropdown");
let selectPopup = menulist.menupopup;
let popupShownPromise = BrowserTestUtils.waitForEvent(selectPopup, "popupshown");
yield BrowserTestUtils.synthesizeMouseAtCenter("#one", { type: "mousedown" }, gBrowser.selectedBrowser);
yield popupShownPromise;
is(selectPopup.parentNode.itemCount, 2, "Correct number of items");
let child = selectPopup.firstChild;
let idx = 1;
is(getComputedStyle(selectPopup).color, getSystemColor("-moz-ComboboxText"),
"popup has expected foreground color");
is(getComputedStyle(selectPopup).backgroundColor, getSystemColor("-moz-Combobox"),
"popup has expected background color");
ok(!child.selected, "The first child should not be selected");
while (child) {
testOptionColors(idx, child, menulist);
idx++;
child = child.nextSibling;
}
yield hideSelectPopup(selectPopup, "escape");
yield BrowserTestUtils.removeTab(tab);
});
// This test checks that the popup is closed when the select element is blurred.
add_task(function* test_blur_hides_popup() {
const pageUrl = "data:text/html," + escape(PAGECONTENT_SMALL);
@ -956,41 +759,3 @@ add_task(function* test_blur_hides_popup() {
yield BrowserTestUtils.removeTab(tab);
});
// This test checks when a <select> element has a background set, and the
// options have their own background set which is equal to the default
// user-agent background color, but should be used because the select
// background color has been changed.
add_task(function* test_options_inverted_from_select_background() {
const pageUrl = "data:text/html," + escape(OPTION_COLOR_EQUAL_TO_UABACKGROUND_COLOR_SELECT);
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, pageUrl);
let menulist = document.getElementById("ContentSelectDropdown");
let selectPopup = menulist.menupopup;
let popupShownPromise = BrowserTestUtils.waitForEvent(selectPopup, "popupshown");
yield BrowserTestUtils.synthesizeMouseAtCenter("#one", { type: "mousedown" }, gBrowser.selectedBrowser);
yield popupShownPromise;
is(selectPopup.parentNode.itemCount, 2, "Correct number of items");
let child = selectPopup.firstChild;
let idx = 1;
// The popup has a black background and white text, but the
// options inside of it have flipped the colors.
is(getComputedStyle(selectPopup).color, "rgb(255, 255, 255)",
"popup has expected foreground color");
is(getComputedStyle(selectPopup).backgroundColor, "rgb(0, 0, 0)",
"popup has expected background color");
ok(!child.selected, "The first child should not be selected");
while (child) {
testOptionColors(idx, child, menulist);
idx++;
child = child.nextSibling;
}
yield hideSelectPopup(selectPopup, "escape");
yield BrowserTestUtils.removeTab(tab);
});

View File

@ -0,0 +1,236 @@
const PAGECONTENT_COLORS =
"<html><head><style>" +
" .blue { color: #fff; background-color: #00f; }" +
" .green { color: #800080; background-color: green; }" +
" .defaultColor { color: -moz-ComboboxText; }" +
" .defaultBackground { background-color: -moz-Combobox; }" +
"</style>" +
"<body><select id='one'>" +
' <option value="One" style="color: #fff; background-color: #f00;">{"color": "rgb(255, 255, 255)", "backgroundColor": "rgb(255, 0, 0)"}</option>' +
' <option value="Two" class="blue">{"color": "rgb(255, 255, 255)", "backgroundColor": "rgb(0, 0, 255)"}</option>' +
' <option value="Three" class="green">{"color": "rgb(128, 0, 128)", "backgroundColor": "rgb(0, 128, 0)"}</option>' +
' <option value="Four" class="defaultColor defaultBackground">{"color": "-moz-ComboboxText", "backgroundColor": "rgba(0, 0, 0, 0)", "unstyled": "true"}</option>' +
' <option value="Five" class="defaultColor">{"color": "-moz-ComboboxText", "backgroundColor": "rgba(0, 0, 0, 0)", "unstyled": "true"}</option>' +
' <option value="Six" class="defaultBackground">{"color": "-moz-ComboboxText", "backgroundColor": "rgba(0, 0, 0, 0)", "unstyled": "true"}</option>' +
' <option value="Seven" selected="true">{"unstyled": "true"}</option>' +
"</select></body></html>";
const PAGECONTENT_COLORS_ON_SELECT =
"<html><head><style>" +
" #one { background-color: #7E3A3A; color: #fff }" +
"</style>" +
"<body><select id='one'>" +
' <option value="One">{"color": "rgb(255, 255, 255)", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
' <option value="Two">{"color": "rgb(255, 255, 255)", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
' <option value="Three">{"color": "rgb(255, 255, 255)", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
' <option value="Four" selected="true">{"end": "true"}</option>' +
"</select></body></html>";
const TRANSPARENT_SELECT =
"<html><head><style>" +
" #one { background-color: transparent; }" +
"</style>" +
"<body><select id='one'>" +
' <option value="One">{"unstyled": "true"}</option>' +
' <option value="Two" selected="true">{"end": "true"}</option>' +
"</select></body></html>";
const OPTION_COLOR_EQUAL_TO_UABACKGROUND_COLOR_SELECT =
"<html><head><style>" +
" #one { background-color: black; color: white; }" +
"</style>" +
"<body><select id='one'>" +
' <option value="One" style="background-color: white; color: black;">{"color": "rgb(0, 0, 0)", "backgroundColor": "rgb(255, 255, 255)"}</option>' +
' <option value="Two" selected="true">{"end": "true"}</option>' +
"</select></body></html>";
const GENERIC_OPTION_STYLED_AS_IMPORTANT =
"<html><head><style>" +
" option { background-color: black !important; color: white !important; }" +
"</style>" +
"<body><select id='one'>" +
' <option value="One">{"color": "rgb(255, 255, 255)", "backgroundColor": "rgb(0, 0, 0)"}</option>' +
' <option value="Two" selected="true">{"end": "true"}</option>' +
"</select></body></html>";
const TRANSLUCENT_SELECT_BECOMES_OPAQUE =
"<html><head>" +
"<body><select id='one' style='background-color: rgba(255,255,255,.55);'>" +
' <option value="One">{"color": "rgb(0, 0, 0)", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
' <option value="Two" selected="true">{"end": "true"}</option>' +
"</select></body></html>";
const DISABLED_OPTGROUP_AND_OPTIONS =
"<html><head>" +
"<body><select id='one'>" +
" <optgroup label='{\"color\": \"rgb(0, 0, 0)\", \"backgroundColor\": \"buttonface\"}'>" +
' <option disabled="">{"color": "GrayText", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
' <option>{"color": "rgb(0, 0, 0)", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
' <option disabled="">{"color": "GrayText", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
' <option>{"color": "rgb(0, 0, 0)", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
' <option>{"color": "rgb(0, 0, 0)", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
' <option>{"color": "rgb(0, 0, 0)", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
' <option>{"color": "rgb(0, 0, 0)", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
" </optgroup>" +
" <optgroup label='{\"color\": \"GrayText\", \"backgroundColor\": \"buttonface\"}' disabled=''>" +
' <option>{"color": "GrayText", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
' <option>{"color": "GrayText", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
' <option>{"color": "GrayText", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
' <option>{"color": "GrayText", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
' <option>{"color": "GrayText", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
' <option>{"color": "GrayText", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
' <option>{"color": "GrayText", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
" </optgroup>" +
' <option value="Two" selected="true">{"end": "true"}</option>' +
"</select></body></html>";
function getSystemColor(color) {
// Need to convert system color to RGB color.
let textarea = document.createElementNS("http://www.w3.org/1999/xhtml", "textarea");
textarea.style.color = color;
return getComputedStyle(textarea).color;
}
function testOptionColors(index, item, menulist) {
// The label contains a JSON string of the expected colors for
// `color` and `background-color`.
let expected = JSON.parse(item.label);
for (let color of Object.keys(expected)) {
if (color.toLowerCase().includes("color") &&
!expected[color].startsWith("rgb")) {
expected[color] = getSystemColor(expected[color]);
}
}
// Press Down to move the selected item to the next item in the
// list and check the colors of this item when it's not selected.
EventUtils.synthesizeKey("KEY_ArrowDown", { code: "ArrowDown" });
if (expected.end) {
return;
}
if (expected.unstyled) {
ok(!item.hasAttribute("customoptionstyling"),
`Item ${index} should not have any custom option styling`);
} else {
is(getComputedStyle(item).color, expected.color,
"Item " + (index) + " has correct foreground color");
is(getComputedStyle(item).backgroundColor, expected.backgroundColor,
"Item " + (index) + " has correct background color");
}
}
function* testSelectColors(select, itemCount, options) {
const pageUrl = "data:text/html," + escape(select);
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, pageUrl);
let menulist = document.getElementById("ContentSelectDropdown");
let selectPopup = menulist.menupopup;
let popupShownPromise = BrowserTestUtils.waitForEvent(selectPopup, "popupshown");
yield BrowserTestUtils.synthesizeMouseAtCenter("#one", { type: "mousedown" }, gBrowser.selectedBrowser);
yield popupShownPromise;
is(selectPopup.parentNode.itemCount, itemCount, "Correct number of items");
let child = selectPopup.firstChild;
let idx = 1;
if (!options.skipSelectColorTest) {
is(getComputedStyle(selectPopup).color, options.selectColor,
"popup has expected foreground color");
is(getComputedStyle(selectPopup).backgroundColor, options.selectBgColor,
"popup has expected background color");
}
ok(!child.selected, "The first child should not be selected");
while (child) {
testOptionColors(idx, child, menulist);
idx++;
child = child.nextSibling;
}
yield hideSelectPopup(selectPopup, "escape");
yield BrowserTestUtils.removeTab(tab);
}
add_task(function* setup() {
yield SpecialPowers.pushPrefEnv({
"set": [
["dom.select_popup_in_parent.enabled", true],
["dom.forms.select.customstyling", true]
]
});
});
// This test checks when a <select> element has styles applied to <option>s within it.
add_task(function* test_colors_applied_to_popup_items() {
yield testSelectColors(PAGECONTENT_COLORS, 7,
{skipSelectColorTest: true});
});
// This test checks when a <select> element has styles applied to itself.
add_task(function* test_colors_applied_to_popup() {
let options = {
selectColor: "rgb(255, 255, 255)",
selectBgColor: "rgb(126, 58, 58)"
};
yield testSelectColors(PAGECONTENT_COLORS_ON_SELECT, 4, options);
});
// This test checks when a <select> element has a transparent background applied to itself.
add_task(function* test_transparent_applied_to_popup() {
let options = {
selectColor: getSystemColor("-moz-ComboboxText"),
selectBgColor: getSystemColor("-moz-Combobox")
};
yield testSelectColors(TRANSPARENT_SELECT, 2, options);
});
// This test checks when a <select> element has a background set, and the
// options have their own background set which is equal to the default
// user-agent background color, but should be used because the select
// background color has been changed.
add_task(function* test_options_inverted_from_select_background() {
// The popup has a black background and white text, but the
// options inside of it have flipped the colors.
let options = {
selectColor: "rgb(255, 255, 255)",
selectBgColor: "rgb(0, 0, 0)"
};
yield testSelectColors(OPTION_COLOR_EQUAL_TO_UABACKGROUND_COLOR_SELECT,
2, options);
});
// This test checks when a <select> element has a background set using !important,
// which was affecting how we calculated the user-agent styling.
add_task(function* test_select_background_using_important() {
yield testSelectColors(GENERIC_OPTION_STYLED_AS_IMPORTANT, 2,
{skipSelectColorTest: true});
});
// This test checks when a <select> element has a background set, and the
// options have their own background set which is equal to the default
// user-agent background color, but should be used because the select
// background color has been changed.
add_task(function* test_translucent_select_becomes_opaque() {
// The popup is requested to show a translucent background
// but we force the alpha channel to 1 on the popup.
let options = {
selectColor: "rgb(0, 0, 0)",
selectBgColor: "rgb(255, 255, 255)"
};
yield testSelectColors(TRANSLUCENT_SELECT_BECOMES_OPAQUE, 2, options);
});
add_task(function* test_disabled_optgroup_and_options() {
// The colors used by this test are platform-specific.
if (AppConstants.platform != "win") {
return;
}
yield testSelectColors(DISABLED_OPTGROUP_AND_OPTIONS, 17,
{skipSelectColorTest: true});
});

View File

@ -0,0 +1,19 @@
/* eslint-env mozilla/frame-script */
function hideSelectPopup(selectPopup, mode = "enter", win = window) {
let browser = win.gBrowser.selectedBrowser;
let selectClosedPromise = ContentTask.spawn(browser, null, function*() {
Cu.import("resource://gre/modules/SelectContentHelper.jsm");
return ContentTaskUtils.waitForCondition(() => !SelectContentHelper.open);
});
if (mode == "escape") {
EventUtils.synthesizeKey("KEY_Escape", { code: "Escape" }, win);
} else if (mode == "enter") {
EventUtils.synthesizeKey("KEY_Enter", { code: "Enter" }, win);
} else if (mode == "click") {
EventUtils.synthesizeMouseAtCenter(selectPopup.lastChild, { }, win);
}
return selectClosedPromise;
}

View File

@ -324,8 +324,6 @@ skip-if = e10s && debug && os == "win" # Bug 1280505
support-files =
contentSearchUI.html
contentSearchUI.js
[browser_selectpopup.js]
skip-if = os == "linux" # Bug 1329991 - test fails intermittently on Linux builds
[browser_selectTabAtIndex.js]
[browser_ssl_error_reports.js]
[browser_star_hsts.js]

View File

@ -63,7 +63,7 @@ var successfulPinningPageListener = {
handleEvent() {
gBrowser.selectedBrowser.removeEventListener("load", this, true);
BrowserTestUtils.loadURI(gBrowser.selectedBrowser, "https://" + kBadPinningDomain).then(function() {
return promiseErrorPageLoaded(gBrowser.selectedBrowser);
return BrowserTestUtils.waitForErrorPage(gBrowser.selectedBrowser);
}).then(errorPageLoaded);
}
};

View File

@ -70,48 +70,6 @@ function test_install_lwtheme() {
}
);
});
},
function test_lwtheme_switch_theme() {
is(LightweightThemeManager.currentTheme, null, "Should be no lightweight theme selected");
AddonManager.getAddonByID("theme-xpi@tests.mozilla.org", function(aAddon) {
aAddon.userDisabled = false;
ok(aAddon.isActive, "Theme should have immediately enabled");
Services.prefs.setBoolPref("extensions.dss.enabled", false);
var pm = Services.perms;
pm.add(makeURI("https://example.com/"), "install", pm.ALLOW_ACTION);
gBrowser.selectedTab = gBrowser.addTab("https://example.com/browser/browser/base/content/test/general/bug592338.html");
gBrowser.selectedBrowser.addEventListener("pageshow", function() {
if (gBrowser.contentDocument.location.href == "about:blank")
return;
gBrowser.selectedBrowser.removeEventListener("pageshow", arguments.callee);
executeSoon(function() {
wait_for_notification(function(aPanel) {
is(LightweightThemeManager.currentTheme, null, "Should not have installed the test lwtheme");
ok(aAddon.isActive, "Test theme should still be active");
let notification = aPanel.childNodes[0];
is(notification.button.label, "Restart Now", "Should have seen the right button");
ok(aAddon.userDisabled, "Should be waiting to disable the test theme");
aAddon.userDisabled = false;
Services.prefs.setBoolPref("extensions.dss.enabled", true);
gBrowser.removeTab(gBrowser.selectedTab);
Services.perms.remove(makeURI("http://example.com"), "install");
runNextTest();
});
BrowserTestUtils.synthesizeMouse("#theme-install", 2, 2, {}, gBrowser.selectedBrowser);
});
});
});
}
];
@ -124,7 +82,6 @@ function runNextTest() {
aAddon.uninstall();
Services.prefs.setBoolPref("extensions.logging.enabled", false);
Services.prefs.setBoolPref("extensions.dss.enabled", false);
finish();
});
@ -147,11 +104,6 @@ function test() {
AddonManager.getAddonByID("theme-xpi@tests.mozilla.org", function(aAddon) {
isnot(aAddon, null, "Should have installed the test theme.");
// In order to switch themes while the test is running we turn on dynamic
// theme switching. This means the test isn't exactly correct but should
// do some good
Services.prefs.setBoolPref("extensions.dss.enabled", true);
runNextTest();
});
}

View File

@ -17,6 +17,7 @@ MOCHITEST_CHROME_MANIFESTS += [
BROWSER_CHROME_MANIFESTS += [
'content/test/alerts/browser.ini',
'content/test/captivePortal/browser.ini',
'content/test/forms/browser.ini',
'content/test/general/browser.ini',
'content/test/newtab/browser.ini',
'content/test/pageinfo/browser.ini',

View File

@ -726,9 +726,8 @@ const CustomizableWidgets = [
}
// Register ourselves with the service so we know when the zoom prefs change.
Services.obs.addObserver(updateZoomResetButton, "browser-fullZoom:zoomChange", false);
Services.obs.addObserver(updateZoomResetButton, "browser-fullZoom:zoomReset", false);
Services.obs.addObserver(updateZoomResetButton, "browser-fullZoom:location-change", false);
window.addEventListener("FullZoomChange", updateZoomResetButton);
if (inPanel) {
let panel = aDocument.getElementById(kPanelId);
@ -805,9 +804,8 @@ const CustomizableWidgets = [
return;
CustomizableUI.removeListener(listener);
Services.obs.removeObserver(updateZoomResetButton, "browser-fullZoom:zoomChange");
Services.obs.removeObserver(updateZoomResetButton, "browser-fullZoom:zoomReset");
Services.obs.removeObserver(updateZoomResetButton, "browser-fullZoom:location-change");
window.removeEventListener("FullZoomChange", updateZoomResetButton);
let panel = aDoc.getElementById(kPanelId);
panel.removeEventListener("popupshowing", updateZoomResetButton);
let container = aDoc.defaultView.gBrowser.tabContainer;

View File

@ -93,7 +93,8 @@ AutofillProfileAutoCompleteSearch.prototype = {
this.forceStop = false;
let info = FormAutofillContent.getInputDetails(focusedInput);
if (!FormAutofillContent.savedFieldNames.has(info.fieldName)) {
if (!FormAutofillContent.savedFieldNames.has(info.fieldName) ||
FormAutofillContent.getFormHandler(focusedInput).filledProfileGUID) {
let formHistory = Cc["@mozilla.org/autocomplete/search;1?name=form-history"]
.createInstance(Ci.nsIAutoCompleteSearch);
formHistory.startSearch(searchString, searchParam, previousResult, {

View File

@ -52,6 +52,11 @@ FormAutofillHandler.prototype = {
*/
fieldDetails: null,
/**
* String of the filled profile's guid.
*/
filledProfileGUID: null,
/**
* Set fieldDetails from the form about fields that can be autofilled.
*/
@ -100,6 +105,8 @@ FormAutofillHandler.prototype = {
*/
autofillFormFields(profile, focusedInput) {
log.debug("profile in autofillFormFields:", profile);
this.filledProfileGUID = profile.guid;
for (let fieldDetail of this.fieldDetails) {
// Avoid filling field value in the following cases:
// 1. the focused input which is filled in FormFillController.

View File

@ -41,6 +41,7 @@ const TESTCASES = [
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel", "element": {}},
],
profileData: {
"guid": "123",
"street-address": "2 Harrison St",
"address-level2": "San Francisco",
"country": "US",
@ -74,6 +75,7 @@ const TESTCASES = [
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "tel", "element": {}},
],
profileData: {
"guid": "123",
"street-address": "2 Harrison St",
"address-level2": "San Francisco",
"country": "US",
@ -107,6 +109,7 @@ const TESTCASES = [
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "tel", "element": {}},
],
profileData: {
"guid": "123",
"street-address": "2 Harrison St",
"address-level2": "San Francisco",
"country": "US",
@ -140,6 +143,7 @@ const TESTCASES = [
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "tel", "element": {}},
],
profileData: {
"guid": "123",
"street-address": "",
"address-level2": "",
"country": "",
@ -188,6 +192,9 @@ for (let tc of TESTCASES) {
});
handler.autofillFormFields(testcase.profileData);
Assert.equal(handler.filledProfileGUID, testcase.profileData.guid,
"Check if filledProfileGUID is set correctly");
yield Promise.all(onChangePromises);
});
})();

View File

@ -895,6 +895,9 @@ class Graphics extends PP_Resource {
super.destroy();
}
changeSize(width, height) {
let devicePixelRatio = this.instance.window.devicePixelRatio;
this.canvas.style.width = (width / devicePixelRatio) + "px";
this.canvas.style.height = (height / devicePixelRatio) + "px";
this.canvas.width = width;
this.canvas.height = height;
}
@ -5330,20 +5333,16 @@ dump(`callFromJSON: < ${JSON.stringify(call)}\n`);
* float_t GetDeviceScale([in] PP_Resource resource);
*/
PPB_View_GetDeviceScale: function(json) {
// FIXME Need to figure out how to get the ratio between device pixels
// and DIPs.
let view = PP_Resource.lookup(json.resource);
return 1; //view.instance.window.devicePixelRatio;
return view.instance.window.devicePixelRatio;
},
/**
* float_t GetCSSScale([in] PP_Resource resource);
*/
PPB_View_GetCSSScale: function(json) {
// FIXME Need to figure out how to get the ratio between CSS pixels
// and DIPs.
let view = PP_Resource.lookup(json.resource);
return view.instance.window.devicePixelRatio;
return 1;
},
/**

View File

@ -640,11 +640,11 @@ getUserMedia.allow.accesskey = A
getUserMedia.dontAllow.label = Dont Allow
getUserMedia.dontAllow.accesskey = D
getUserMedia.remember=Remember this decision
# LOCALIZATION NOTE (getUserMedia.reasonForNoPermanentAllow.screen2,
# LOCALIZATION NOTE (getUserMedia.reasonForNoPermanentAllow.screen3,
# getUserMedia.reasonForNoPermanentAllow.audio,
# getUserMedia.reasonForNoPermanentAllow.insecure):
# %S is brandShortName
getUserMedia.reasonForNoPermanentAllow.screen2=%S can not allow permanent access to your screen without asking which one to share.
getUserMedia.reasonForNoPermanentAllow.screen3=%S can not allow permanent access to your screen.
getUserMedia.reasonForNoPermanentAllow.audio=%S can not allow permanent access to your tabs audio without asking which tab to share.
getUserMedia.reasonForNoPermanentAllow.insecure=Your connection to this site is not secure. To protect you, %S will only allow access for this session.

View File

@ -12,13 +12,15 @@ Components.utils.import("resource://gre/modules/Services.jsm");
var URLBarZoom = {
init(aWindow) {
aWindow.addEventListener("EndSwapDocShells", onEndSwapDocShells, true);
aWindow.addEventListener("FullZoomChange", onFullZoomChange);
aWindow.addEventListener("unload", () => {
aWindow.removeEventListener("EndSwapDocShells", onEndSwapDocShells, true);
aWindow.removeEventListener("FullZoomChange", onFullZoomChange);
}, {once: true});
},
}
function fullZoomObserver(aSubject, aTopic) {
function fullZoomLocationChangeObserver(aSubject, aTopic) {
// If the tab was the last one in its window and has been dragged to another
// window, the original browser's window will be unavailable here. Since that
// window is closing, we can just ignore this notification.
@ -26,25 +28,35 @@ function fullZoomObserver(aSubject, aTopic) {
return;
}
let animate = (aTopic != "browser-fullZoom:location-change");
updateZoomButton(aSubject, animate);
updateZoomButton(aSubject, false);
}
function onEndSwapDocShells(event) {
updateZoomButton(event.originalTarget);
}
function onFullZoomChange(event) {
let browser;
if (event.target.nodeType == event.target.DOCUMENT_NODE) {
// In non-e10s, the event is dispatched on the contentDocument
// so we need to jump through some hoops to get to the <xul:browser>.
let gBrowser = event.currentTarget.gBrowser;
let topDoc = event.target.defaultView.top.document;
browser = gBrowser.getBrowserForDocument(topDoc);
} else {
browser = event.originalTarget;
}
updateZoomButton(browser, true);
}
/**
* Updates the zoom button in the location bar.
*
* @param {object} aBrowser The browser that the zoomed content resides in.
* @param {boolean} aAnimate Should be True for all cases unless the zoom
* change is related to tab switching. Optional
* @param {number} aValue The value that should be used for the zoom control.
* If not provided then the value will be read from the window. Useful
* if the data on the window may be stale.
*/
function updateZoomButton(aBrowser, aAnimate = false, aValue = undefined) {
function updateZoomButton(aBrowser, aAnimate = false) {
let win = aBrowser.ownerGlobal;
if (aBrowser != win.gBrowser.selectedBrowser) {
return;
@ -60,12 +72,9 @@ function updateZoomButton(aBrowser, aAnimate = false, aValue = undefined) {
return;
}
let zoomFactor = Math.round((aValue || win.ZoomManager.zoom) * 100);
let zoomFactor = Math.round(win.ZoomManager.zoom * 100);
if (zoomFactor != 100) {
// Check if zoom button is visible and update label if it is
if (zoomResetButton.hidden) {
zoomResetButton.hidden = false;
}
if (aAnimate) {
zoomResetButton.setAttribute("animate", "true");
} else {
@ -79,9 +88,4 @@ function updateZoomButton(aBrowser, aAnimate = false, aValue = undefined) {
}
}
Services.obs.addObserver(fullZoomObserver, "browser-fullZoom:zoomChange", false);
Services.obs.addObserver(fullZoomObserver, "browser-fullZoom:zoomReset", false);
Services.obs.addObserver(fullZoomObserver, "browser-fullZoom:location-change", false);
Services.mm.addMessageListener("SyntheticDocument:ZoomChange", function(aMessage) {
updateZoomButton(aMessage.target, true, aMessage.data.value);
});
Services.obs.addObserver(fullZoomLocationChangeObserver, "browser-fullZoom:location-change", false);

View File

@ -24,14 +24,13 @@ add_task(function* () {
let buttonZoomLevel = parseInt(zoomResetButton.getAttribute("label"), 10);
is(buttonZoomLevel, expectedZoomLevel, ("Button label updated successfully to " + Math.floor(ZoomManager.zoom * 100) + "%"));
let zoomResetPromise = promiseObserverNotification("browser-fullZoom:zoomReset");
let zoomResetPromise = BrowserTestUtils.waitForEvent(window, "FullZoomChange");
zoomResetButton.click();
yield zoomResetPromise;
pageZoomLevel = Math.floor(ZoomManager.zoom * 100);
expectedZoomLevel = 100;
is(pageZoomLevel, expectedZoomLevel, "Clicking zoom button successfully resets browser zoom to 100%");
is(zoomResetButton.hidden, true, "Zoom reset button returns to being hidden");
});
add_task(function* () {
@ -39,7 +38,7 @@ add_task(function* () {
CustomizableUI.addWidgetToArea("zoom-controls", CustomizableUI.AREA_NAVBAR);
let zoomCustomizableWidget = document.getElementById("zoom-reset-button");
let zoomResetButton = document.getElementById("urlbar-zoom-button");
let zoomChangePromise = promiseObserverNotification("browser-fullZoom:zoomChange");
let zoomChangePromise = BrowserTestUtils.waitForEvent(window, "FullZoomChange");
FullZoom.enlarge();
yield zoomChangePromise;
is(zoomResetButton.hidden, true, "URL zoom button remains hidden despite zoom increase");
@ -54,20 +53,4 @@ add_task(function* asyncCleanup() {
CustomizableUI.removeWidgetFromArea("zoom-controls", CustomizableUI.AREA_NAVBAR);
ok(!document.getElementById("zoom-controls"), "Customizable zoom widget removed from toolbar");
}
});
function promiseObserverNotification(aObserver) {
let deferred = Promise.defer();
function notificationCallback(e) {
Services.obs.removeObserver(notificationCallback, aObserver);
clearTimeout(timeoutId);
deferred.resolve();
}
let timeoutId = setTimeout(() => {
Services.obs.removeObserver(notificationCallback, aObserver);
deferred.reject("Notification '" + aObserver + "' did not happen within 20 seconds.");
}, kTimeoutInMS);
Services.obs.addObserver(notificationCallback, aObserver, false);
return deferred.promise;
}

View File

@ -456,7 +456,7 @@ function prompt(aBrowser, aRequest) {
// share without prompting).
let reasonForNoPermanentAllow = "";
if (sharingScreen) {
reasonForNoPermanentAllow = "getUserMedia.reasonForNoPermanentAllow.screen2";
reasonForNoPermanentAllow = "getUserMedia.reasonForNoPermanentAllow.screen3";
} else if (sharingAudio) {
reasonForNoPermanentAllow = "getUserMedia.reasonForNoPermanentAllow.audio";
} else if (!aRequest.secure) {
@ -744,8 +744,8 @@ function prompt(aBrowser, aRequest) {
if (videoDevices.length) {
let listId = "webRTC-select" + (sharingScreen ? "Window" : "Camera") + "-menulist";
let videoDeviceIndex = doc.getElementById(listId).value;
let allowCamera = videoDeviceIndex != "-1";
if (allowCamera) {
let allowVideoDevice = videoDeviceIndex != "-1";
if (allowVideoDevice) {
allowedDevices.push(videoDeviceIndex);
// Session permission will be removed after use
// (it's really one-shot, not for the entire session)
@ -764,9 +764,6 @@ function prompt(aBrowser, aRequest) {
}
if (remember)
SitePermissions.set(uri, "camera", SitePermissions.ALLOW);
} else {
let scope = remember ? SitePermissions.SCOPE_PERSISTENT : SitePermissions.SCOPE_TEMPORARY;
SitePermissions.set(uri, "camera", SitePermissions.BLOCK, scope, aBrowser);
}
}
if (audioDevices.length) {
@ -788,9 +785,6 @@ function prompt(aBrowser, aRequest) {
}
if (remember)
SitePermissions.set(uri, "microphone", SitePermissions.ALLOW);
} else {
let scope = remember ? SitePermissions.SCOPE_PERSISTENT : SitePermissions.SCOPE_TEMPORARY;
SitePermissions.set(uri, "microphone", SitePermissions.BLOCK, scope, aBrowser);
}
} else {
// Only one device possible for audio capture.

View File

@ -18,6 +18,7 @@ ALL_HARNESSES = [
'mozbase',
'web-platform',
'talos',
'awsy',
'gtest',
]
@ -28,6 +29,7 @@ PACKAGE_SPECIFIED_HARNESSES = [
'xpcshell',
'web-platform',
'talos',
'awsy',
]
# These packages are not present for every build configuration.

View File

@ -15,7 +15,7 @@
PR_SetEnv requires its argument to be leaked, but does not appear on stacks. (See bug 793549.)
Memcheck:Leak
...
fun:_ZL13SaveWordToEnvPKcRK19nsACString_internal
fun:_ZL13SaveWordToEnvPKcRK10nsACString
...
}
{
@ -30,8 +30,8 @@
Memcheck:Leak
fun:malloc
...
fun:_Z12ToNewCStringRK19nsACString_internal
fun:_ZN13CrashReporter14SetupExtraDataEP7nsIFileRK19nsACString_internal
fun:_Z12ToNewCStringRK10nsACString
fun:_ZN13CrashReporter14SetupExtraDataEP7nsIFileRK10nsACString
...
}
{

View File

@ -98,3 +98,13 @@ storage.idb.deleteBlocked=Database “%S” will be deleted after all connection
# LOCALIZATION NOTE (storage.idb.deleteError):
# Error notification when IndexedDB database could not be deleted.
storage.idb.deleteError=Database “%S” could not be deleted.
# LOCALIZATION NOTE (storage.expandPane):
# This is the tooltip for the button that collapses the right panel in the
# storage UI when the panel is closed.
storage.expandPane=Expand Pane
# LOCALIZATION NOTE (storage.collapsePane):
# This is the tooltip for the button that collapses the right panel in the
# storage UI when the panel is open.
storage.collapsePane=Collapse Pane

View File

@ -143,6 +143,17 @@ TableWidget.prototype = {
}
},
/**
* Is a row currently selected?
*
* @return {Boolean}
* true or false.
*/
get hasSelectedRow() {
return this.columns.get(this.uniqueId) &&
this.columns.get(this.uniqueId).selectedRow;
},
/**
* Returns the json object corresponding to the selected row.
*/

View File

@ -6,6 +6,7 @@
<?xml-stylesheet href="chrome://devtools/content/shared/widgets/widgets.css" type="text/css"?>
<?xml-stylesheet href="chrome://devtools/skin/widgets.css" type="text/css"?>
<?xml-stylesheet href="chrome://devtools/skin/storage.css" type="text/css"?>
<?xml-stylesheet href="resource://devtools/client/shared/components/sidebar-toggle.css" type="text/css"?>
<!DOCTYPE window [
<!ENTITY % storageDTD SYSTEM "chrome://devtools/locale/storage.dtd">
@ -46,6 +47,8 @@
type="search"
timeout="200"
placeholder="&searchBox.placeholder;"/>
<spacer flex="1"/>
<button class="devtools-button sidebar-toggle" hidden="true"></button>
</hbox>
<vbox id="storage-table" class="theme-sidebar" flex="1"/>
</vbox>

View File

@ -54,5 +54,6 @@ tags = usercontextid
[browser_storage_search_keyboard_trap.js]
[browser_storage_sessionstorage_edit.js]
[browser_storage_sidebar.js]
[browser_storage_sidebar_toggle.js]
[browser_storage_sidebar_update.js]
[browser_storage_values.js]

View File

@ -28,15 +28,15 @@ const testCases = [
},
{
location: getCookieId("cs2", ".example.org", "/"),
sidebarHidden: false
sidebarHidden: true
},
{
location: getCookieId("uc1", ".example.org", "/"),
sidebarHidden: false
sidebarHidden: true
},
{
location: getCookieId("uc1", ".example.org", "/"),
sidebarHidden: false
sidebarHidden: true
},
{
@ -93,7 +93,7 @@ const testCases = [
sendEscape: true
}, {
location: "obj-s2",
sidebarHidden: false
sidebarHidden: true
}
];

View File

@ -0,0 +1,57 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Test to verify that the sidebar toggles when the toggle button is clicked.
"use strict";
const testCases = [
{
location: ["cookies", "https://sectest1.example.org"],
sidebarHidden: true,
toggleButtonVisible: false
},
{
location: getCookieId("cs2", ".example.org", "/"),
sidebarHidden: false,
toggleButtonVisible: true
},
{
clickToggle: true
},
{
location: getCookieId("cs2", ".example.org", "/"),
sidebarHidden: true
}
];
add_task(function* () {
yield openTabAndSetupStorage(MAIN_DOMAIN + "storage-listings.html");
for (let test of testCases) {
let { location, sidebarHidden, clickToggle, toggleButtonVisible } = test;
info("running " + JSON.stringify(test));
if (Array.isArray(location)) {
yield selectTreeItem(location);
} else if (location) {
yield selectTableItem(location);
}
if (clickToggle) {
toggleSidebar();
} else if (typeof toggleButtonHidden !== "undefined") {
is(sidebarToggleVisible(), toggleButtonVisible,
"correct visibility state of toggle button");
} else {
is(gUI.sidebar.hidden, sidebarHidden,
"correct visibility state of sidebar.");
}
info("-".repeat(80));
}
yield finishTests();
});

View File

@ -919,3 +919,11 @@ function setPermission(url, permission) {
.addFromPrincipal(principal, permission,
nsIPermissionManager.ALLOW_ACTION);
}
function toggleSidebar() {
gUI.sidebarToggleBtn.click();
}
function sidebarToggleVisible() {
return !gUI.sidebarToggleBtn.hidden;
}

View File

@ -127,9 +127,9 @@ function StorageUI(front, target, panelWin, toolbox) {
this.view = new VariablesView(this.sidebar.firstChild,
GENERIC_VARIABLES_VIEW_SETTINGS);
this.searchBox = this._panelDoc.getElementById("storage-searchbox");
this.filterItems = this.filterItems.bind(this);
this.searchBox.addEventListener("command", this.filterItems);
this.onPaneToggleButtonClicked = this.onPaneToggleButtonClicked.bind(this);
this.setupToolbar();
let shortcuts = new KeyShortcuts({
window: this._panelDoc.defaultView,
@ -191,6 +191,7 @@ exports.StorageUI = StorageUI;
StorageUI.prototype = {
storageTypes: null,
sidebarToggledOpen: null,
shouldLoadMoreItems: true,
set animationsEnabled(value) {
@ -209,6 +210,9 @@ StorageUI.prototype = {
this.searchBox.removeEventListener("input", this.filterItems);
this.searchBox = null;
this.sidebarToggleBtn.removeEventListener("click", this.onPaneToggleButtonClicked);
this.sidebarToggleBtn = null;
this._treePopup.removeEventListener("popupshowing", this.onTreePopupShowing);
this._treePopupDeleteAll.removeEventListener("command", this.onRemoveAll);
this._treePopupDelete.removeEventListener("command", this.onRemoveTreeItem);
@ -219,13 +223,49 @@ StorageUI.prototype = {
this._tablePopupDeleteAll.removeEventListener("command", this.onRemoveAll);
},
setupToolbar: function () {
this.searchBox = this._panelDoc.getElementById("storage-searchbox");
this.searchBox.addEventListener("command", this.filterItems);
// Setup the sidebar toggle button.
this.sidebarToggleBtn = this._panelDoc.querySelector(".sidebar-toggle");
this.updateSidebarToggleButton();
this.sidebarToggleBtn.addEventListener("click", this.onPaneToggleButtonClicked);
},
onPaneToggleButtonClicked: function () {
if (this.sidebar.hidden && this.table.selectedRow) {
this.sidebar.hidden = false;
this.sidebarToggledOpen = true;
this.updateSidebarToggleButton();
} else {
this.sidebarToggledOpen = false;
this.hideSidebar();
}
},
updateSidebarToggleButton: function () {
let title;
this.sidebarToggleBtn.hidden = !this.table.hasSelectedRow;
if (this.sidebar.hidden) {
this.sidebarToggleBtn.classList.add("pane-collapsed");
title = L10N.getStr("storage.expandPane");
} else {
this.sidebarToggleBtn.classList.remove("pane-collapsed");
title = L10N.getStr("storage.collapsePane");
}
this.sidebarToggleBtn.setAttribute("tooltiptext", title);
},
/**
* Empties and hides the object viewer sidebar
* Hide the object viewer sidebar
*/
hideSidebar: function () {
this.view.empty();
this.sidebar.hidden = true;
this.table.clearSelection();
this.updateSidebarToggleButton();
},
getCurrentActor: function () {
@ -490,6 +530,8 @@ StorageUI.prototype = {
: {};
let storageType = this.storageTypes[type];
this.sidebarToggledOpen = null;
if (reason !== REASON.NEXT_50_ITEMS &&
reason !== REASON.UPDATE &&
reason !== REASON.NEW_ROW &&
@ -581,6 +623,7 @@ StorageUI.prototype = {
if (!item) {
// Make sure that sidebar is hidden and return
this.sidebar.hidden = true;
this.updateSidebarToggleButton();
return;
}
@ -591,7 +634,11 @@ StorageUI.prototype = {
}
// Start updating the UI. Everything is sync beyond this point.
if (this.sidebarToggledOpen === null || this.sidebarToggledOpen === true) {
this.sidebar.hidden = false;
}
this.updateSidebarToggleButton();
this.view.empty();
let mainScope = this.view.addScope(L10N.getStr("storage.data.label"));
mainScope.expanded = true;
@ -898,6 +945,7 @@ StorageUI.prototype = {
if (event.keyCode == KeyCodes.DOM_VK_ESCAPE && !this.sidebar.hidden) {
// Stop Propagation to prevent opening up of split console
this.hideSidebar();
this.sidebarToggledOpen = false;
event.stopPropagation();
event.preventDefault();
}

View File

@ -32,6 +32,14 @@
min-width: 250px;
}
#storage-toolbar .devtools-button {
min-width: unset;
}
#storage-toolbar .sidebar-toggle[hidden] {
display: none;
}
/* Responsive sidebar */
@media (max-width: 700px) {
#storage-tree,

View File

@ -62,6 +62,7 @@ const ConsoleTable = createClass({
GripMessageBody({
grip: item[key],
mode: MODE.SHORT,
useQuotes: false,
})
)
);

View File

@ -37,6 +37,7 @@ GripMessageBody.propTypes = {
createElement: PropTypes.func.isRequired,
}),
userProvidedStyle: PropTypes.string,
useQuotes: PropTypes.bool,
};
GripMessageBody.defaultProps = {
@ -44,7 +45,7 @@ GripMessageBody.defaultProps = {
};
function GripMessageBody(props) {
const { grip, userProvidedStyle, serviceContainer } = props;
const { grip, userProvidedStyle, serviceContainer, useQuotes } = props;
let styleObject;
if (userProvidedStyle && userProvidedStyle !== "") {
@ -63,7 +64,7 @@ function GripMessageBody(props) {
typeof grip === "string"
? StringRep({
object: grip,
useQuotes: false,
useQuotes: useQuotes,
mode: props.mode,
style: styleObject
})

View File

@ -119,7 +119,8 @@ function formatReps(parameters, userProvidedStyles, serviceContainer) {
grip,
key,
userProvidedStyle: userProvidedStyles ? userProvidedStyles[key] : null,
serviceContainer
serviceContainer,
useQuotes: false,
}))
// Interleave spaces.
.reduce((arr, v, i) => {

View File

@ -43,7 +43,7 @@ function EvaluationResult(props) {
if (message.messageText) {
messageBody = message.messageText;
} else {
messageBody = GripMessageBody({grip: parameters, serviceContainer});
messageBody = GripMessageBody({grip: parameters, serviceContainer, useQuotes: true});
}
const topLevelClasses = ["cm-s-mozilla"];

View File

@ -41,5 +41,6 @@ skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32
[browser_webconsole_observer_notifications.js]
[browser_webconsole_stacktrace_location_debugger_link.js]
[browser_webconsole_stacktrace_location_scratchpad_link.js]
[browser_webconsole_string.js]
[browser_webconsole_timestamps.js]
[browser_webconsole_vview_close_on_esc_key.js]

View File

@ -0,0 +1,35 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const TEST_URI = "http://example.com/browser/devtools/client/webconsole/new-console-output/test/mochitest/test-console.html";
add_task(function* () {
let hud = yield openNewTabAndConsole(TEST_URI);
info("console.log with a string argument");
let receievedMessages = waitForMessages({
hud,
messages: [{
// Test that the output does not include quotes.
text: "stringLog",
}],
});
yield ContentTask.spawn(gBrowser.selectedBrowser, {}, function () {
content.wrappedJSObject.stringLog();
});
yield receievedMessages;
info("evaluating a string constant");
let jsterm = hud.jsterm;
yield jsterm.execute("\"string constant\"");
let msg = yield waitFor(() => findMessage(hud, "constant"));
let body = msg.querySelector(".message-body");
// On the other hand, a string constant result should be quoted.
ok(body.textContent.includes("\"string constant\""), "found expected text");
});

View File

@ -7,7 +7,7 @@
<body>
<p>Simple webconsole test page</p>
<script>
/* exported doLogs */
/* exported doLogs, stringLog */
"use strict";
function doLogs(num) {
@ -16,6 +16,10 @@
console.log(i);
}
}
function stringLog() {
console.log("stringLog");
}
</script>
</body>
</html>

View File

@ -1318,22 +1318,7 @@ Animation::PostUpdate()
if (!keyframeEffect) {
return;
}
Maybe<NonOwningAnimationTarget> target = keyframeEffect->GetTarget();
if (!target) {
return;
}
nsPresContext* presContext = keyframeEffect->GetPresContext();
if (!presContext) {
return;
}
presContext->EffectCompositor()
->RequestRestyle(target->mElement,
target->mPseudoType,
EffectCompositor::RestyleType::Layer,
CascadeLevel());
keyframeEffect->RequestRestyle(EffectCompositor::RestyleType::Layer);
}
void

View File

@ -505,9 +505,10 @@ EffectCompositor::GetServoAnimationRule(const dom::Element* aElement,
// If multiple animations affect the same property, animations with higher
// composite order (priority) override or add or animations with lower
// priority.
// stylo: we don't support animations on compositor now, so propertiesToSkip
// is an empty set.
const nsCSSPropertyIDSet propertiesToSkip;
const nsCSSPropertyIDSet propertiesToSkip =
aCascadeLevel == CascadeLevel::Animations
? effectSet->PropertiesForAnimationsLevel().Inverse()
: effectSet->PropertiesForAnimationsLevel();
for (KeyframeEffectReadOnly* effect : sortedEffectList) {
effect->GetAnimation()->ComposeStyle(animRule, propertiesToSkip);
}
@ -685,6 +686,22 @@ EffectCompositor::MaybeUpdateCascadeResults(Element* aElement,
MOZ_ASSERT(!effects->CascadeNeedsUpdate(), "Failed to update cascade state");
}
/* static */ void
EffectCompositor::MaybeUpdateCascadeResults(dom::Element* aElement,
CSSPseudoElementType aPseudoType)
{
EffectSet* effects = EffectSet::GetEffectSet(aElement, aPseudoType);
MOZ_ASSERT(effects);
if (!effects->CascadeNeedsUpdate()) {
return;
}
// FIXME: Implement the rule node traversal for stylo in Bug 1334036.
UpdateCascadeResults(*effects, aElement, aPseudoType, nullptr);
MOZ_ASSERT(!effects->CascadeNeedsUpdate(), "Failed to update cascade state");
}
/* static */ void
EffectCompositor::UpdateCascadeResults(Element* aElement,
CSSPseudoElementType aPseudoType,
@ -764,7 +781,7 @@ EffectCompositor::ComposeAnimationRule(dom::Element* aElement,
// priority except properties in propertiesToSkip.
const nsCSSPropertyIDSet& propertiesToSkip =
aCascadeLevel == CascadeLevel::Animations
? effects->PropertiesForAnimationsLevel().Invert()
? effects->PropertiesForAnimationsLevel().Inverse()
: effects->PropertiesForAnimationsLevel();
for (KeyframeEffectReadOnly* effect : sortedEffectList) {
effect->GetAnimation()->WillComposeStyle();
@ -837,6 +854,10 @@ EffectCompositor::UpdateCascadeResults(EffectSet& aEffectSet,
// cascade applies.
nsCSSPropertyIDSet overriddenProperties;
if (aStyleContext) {
// FIXME: Bug 1334036 (OMTA) will implement a FFI to get the properties
// overriding animation.
MOZ_ASSERT(!aStyleContext->StyleSource().IsServoComputedValues(),
"stylo: Not support get properties overriding animation yet.");
GetOverriddenProperties(aStyleContext, aEffectSet, overriddenProperties);
}
@ -976,6 +997,8 @@ EffectCompositor::PreTraverse()
continue;
}
MaybeUpdateCascadeResults(target.mElement, target.mPseudoType);
for (KeyframeEffectReadOnly* effect : *effects) {
effect->GetAnimation()->WillComposeStyle();
}
@ -996,8 +1019,8 @@ EffectCompositor::PreTraverse(dom::Element* aElement, nsIAtom* aPseudoTagOrNull)
bool found = false;
if (aPseudoTagOrNull &&
aPseudoTagOrNull != nsGkAtoms::cssPseudoElementBeforeProperty &&
aPseudoTagOrNull != nsGkAtoms::cssPseudoElementAfterProperty) {
aPseudoTagOrNull != nsCSSPseudoElements::before &&
aPseudoTagOrNull != nsCSSPseudoElements::after) {
return found;
}
@ -1018,6 +1041,8 @@ EffectCompositor::PreTraverse(dom::Element* aElement, nsIAtom* aPseudoTagOrNull)
EffectSet* effects = EffectSet::GetEffectSet(aElement, pseudoType);
if (effects) {
MaybeUpdateCascadeResults(aElement, pseudoType);
for (KeyframeEffectReadOnly* effect : *effects) {
effect->GetAnimation()->WillComposeStyle();
}

View File

@ -196,6 +196,14 @@ public:
CSSPseudoElementType aPseudoType,
nsStyleContext* aStyleContext);
// Variant of MaybeUpdateCascadeResults for the Servo backend.
// The Servo backend doesn't use an nsStyleContext to get the rule node
// to traverse the style tree to find !important rules and instead
// gets the rule node from |aElement|.
static void
MaybeUpdateCascadeResults(dom::Element* aElement,
CSSPseudoElementType aPseudoType);
// Update the mPropertiesWithImportantRules and
// mPropertiesForAnimationsLevel members of the corresponding EffectSet.
//

View File

@ -195,6 +195,10 @@ public:
{
return mPropertiesForAnimationsLevel;
}
nsCSSPropertyIDSet PropertiesForAnimationsLevel() const
{
return mPropertiesForAnimationsLevel;
}
private:
static nsIAtom* GetEffectSetPropertyAtom(CSSPseudoElementType aPseudoType);

View File

@ -1452,16 +1452,6 @@ KeyframeEffectReadOnly::GetPresShell() const
return doc->GetShell();
}
nsPresContext*
KeyframeEffectReadOnly::GetPresContext() const
{
nsIPresShell* shell = GetPresShell();
if (!shell) {
return nullptr;
}
return shell->GetPresContext();
}
/* static */ bool
KeyframeEffectReadOnly::IsGeometricProperty(
const nsCSSPropertyID aProperty)

View File

@ -34,7 +34,6 @@ class nsIContent;
class nsIDocument;
class nsIFrame;
class nsIPresShell;
class nsPresContext;
namespace mozilla {
@ -211,11 +210,9 @@ public:
{
mEffectOptions.GetSpacingAsString(aRetVal);
}
void NotifyAnimationTimingUpdated();
void RequestRestyle(EffectCompositor::RestyleType aRestyleType);
void SetAnimation(Animation* aAnimation) override;
void SetKeyframes(JSContext* aContext, JS::Handle<JSObject*> aKeyframes,
ErrorResult& aRv);
void SetKeyframes(nsTArray<Keyframe>&& aKeyframes,
@ -297,7 +294,6 @@ public:
}
nsIDocument* GetRenderedDocument() const;
nsPresContext* GetPresContext() const;
nsIPresShell* GetPresShell() const;
// Associates a warning with the animated property on the specified frame
@ -379,8 +375,6 @@ protected:
// Remove the current effect target from its EffectSet.
void UnregisterTarget();
void RequestRestyle(EffectCompositor::RestyleType aRestyleType);
// Update the associated frame state bits so that, if necessary, a stacking
// context will be created and the effect sent to the compositor. We
// typically need to do this when the properties referenced by the keyframe

View File

@ -455,6 +455,7 @@ DOMIntersectionObserver::QueueIntersectionObserverEntry(Element* aTarget,
rootBounds.forget(),
boundingClientRect.forget(),
intersectionRect.forget(),
aIntersectionRect.isSome(),
aTarget, aIntersectionRatio);
mQueuedEntries.AppendElement(entry.forget());
}

View File

@ -30,6 +30,7 @@ public:
RefPtr<DOMRect> aRootBounds,
RefPtr<DOMRect> aBoundingClientRect,
RefPtr<DOMRect> aIntersectionRect,
bool aIsIntersecting,
Element* aTarget,
double aIntersectionRatio)
: mOwner(aOwner),
@ -37,6 +38,7 @@ public:
mRootBounds(aRootBounds),
mBoundingClientRect(aBoundingClientRect),
mIntersectionRect(aIntersectionRect),
mIsIntersecting(aIsIntersecting),
mTarget(aTarget),
mIntersectionRatio(aIntersectionRatio)
{
@ -74,6 +76,11 @@ public:
return mIntersectionRect;
}
bool IsIntersecting()
{
return mIsIntersecting;
}
double IntersectionRatio()
{
return mIntersectionRatio;
@ -90,6 +97,7 @@ protected:
RefPtr<DOMRect> mRootBounds;
RefPtr<DOMRect> mBoundingClientRect;
RefPtr<DOMRect> mIntersectionRect;
bool mIsIntersecting;
RefPtr<Element> mTarget;
double mIntersectionRatio;
};

View File

@ -721,6 +721,7 @@ limitations under the License.
var records = sortRecords(spy.lastCall.args[0]);
expect(records.length).to.be(2);
expect(records[0].intersectionRatio).to.be(0);
expect(records[0].isIntersecting).to.be.ok();
expect(records[0].target).to.be(targetEl1);
expect(records[1].intersectionRatio).to.be(0);
expect(records[1].target).to.be(targetEl2);
@ -753,6 +754,7 @@ limitations under the License.
var records = sortRecords(spy.lastCall.args[0]);
expect(records.length).to.be(2);
expect(records[0].intersectionRatio).to.be(0);
expect(records[0].isIntersecting).to.be.ok();
expect(records[0].target).to.be(targetEl3);
expect(records[1].intersectionRatio).to.be(0);
expect(records[1].target).to.be(targetEl4);
@ -767,17 +769,35 @@ limitations under the License.
it('handles zero-size targets within the root coordinate space',
function(done) {
io = new IntersectionObserver(function(records) {
expect(records.length).to.be(1);
expect(records[0].intersectionRatio).to.be(0);
done();
}, {root: rootEl});
var spy = sinon.spy();
io = new IntersectionObserver(spy, {root: rootEl});
runSequence([
function(done) {
targetEl1.style.top = '0px';
targetEl1.style.left = '0px';
targetEl1.style.width = '0px';
targetEl1.style.height = '0px';
io.observe(targetEl1);
spy.waitForNotification(function() {
var records = sortRecords(spy.lastCall.args[0]);
expect(records.length).to.be(1);
expect(records[0].intersectionRatio).to.be(0);
expect(records[0].isIntersecting).to.be.ok();
done();
}, ASYNC_TIMEOUT);
},
function(done) {
targetEl1.style.top = '-1px';
spy.waitForNotification(function() {
var records = sortRecords(spy.lastCall.args[0]);
expect(records.length).to.be(1);
expect(records[0].intersectionRatio).to.be(0);
expect(records[0].isIntersecting).to.be(false);
done();
}, ASYNC_TIMEOUT);
}
], done);
});

View File

@ -1961,8 +1961,11 @@ MediaFormatReader::HandleDemuxedSamples(
RefPtr<TrackInfoSharedPtr> info = sample->mTrackInfo;
if (info && decoder.mLastStreamSourceID != info->GetID()) {
if (decoder.mNextStreamSourceID.isNothing()
|| decoder.mNextStreamSourceID.ref() != info->GetID()) {
bool recyclable = MediaPrefs::MediaDecoderCheckRecycling()
&& decoder.mDecoder->SupportDecoderRecycling();
if (!recyclable
&& (decoder.mNextStreamSourceID.isNothing()
|| decoder.mNextStreamSourceID.ref() != info->GetID())) {
LOG("%s stream id has changed from:%d to:%d, draining decoder.",
TrackTypeToStr(aTrack), decoder.mLastStreamSourceID,
info->GetID());
@ -1978,8 +1981,7 @@ MediaFormatReader::HandleDemuxedSamples(
decoder.mLastStreamSourceID = info->GetID();
decoder.mNextStreamSourceID.reset();
if (!MediaPrefs::MediaDecoderCheckRecycling()
|| !decoder.mDecoder->SupportDecoderRecycling()) {
if (!recyclable) {
LOG("Decoder does not support recycling, recreate decoder.");
// If flushing is required, it will clear our array of queued samples.
// So make a copy now.

View File

@ -5,7 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/CheckedInt.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/UniquePtrExtensions.h"
#include "mozilla/RefPtr.h"
#include "nsRect.h"
#include "nsSize.h"
@ -37,7 +37,10 @@ public:
// with a U and V plane that are half the size of the Y plane, i.e 8 bit,
// 2x2 subsampled. Have the data pointer of each frame point to the
// first plane, they'll always be zero'd memory anyway.
auto frame = MakeUnique<uint8_t[]>(mFrameWidth * mFrameHeight);
auto frame = MakeUniqueFallible<uint8_t[]>(mFrameWidth * mFrameHeight);
if (!frame) {
return nullptr;
}
memset(frame.get(), 0, mFrameWidth * mFrameHeight);
VideoData::YCbCrBuffer buffer;

View File

@ -332,32 +332,11 @@ H264Converter::CheckForSPSChange(MediaRawData* aSample)
if (CanRecycleDecoder()) {
// Do not recreate the decoder, reuse it.
UpdateConfigFromExtraData(extra_data);
// Ideally we would want to drain the decoder instead of flushing it.
// However the draining operation requires calling Drain and looping several
// times which isn't possible from within the H264Converter. So instead we
// flush the decoder. In practice, this is a no-op as SPS change will only
// be used with MSE. And with MSE, the MediaFormatReader would have drained
// the decoder already.
RefPtr<H264Converter> self = this;
if (!sample->mTrackInfo) {
sample->mTrackInfo = new TrackInfoSharedPtr(mCurrentConfig, 0);
}
mDecoder->Flush()
->Then(AbstractThread::GetCurrent()->AsTaskQueue(),
__func__,
[self, sample, this]() {
mFlushRequest.Complete();
DecodeFirstSample(sample);
},
[self, this](const MediaResult& aError) {
mFlushRequest.Complete();
mDecodePromise.Reject(aError, __func__);
})
->Track(mFlushRequest);
mNeedKeyframe = true;
// This is not really initializing the decoder, but it will do as it
// indicates an operation is pending.
return NS_ERROR_DOM_MEDIA_INITIALIZING_DECODER;
return NS_OK;
}
// The SPS has changed, signal to flush the current decoder and create a

View File

@ -132,13 +132,13 @@ MediaEngineTabVideoSource::DestroyRunnable::Run()
}
void
MediaEngineTabVideoSource::GetName(nsAString_internal& aName) const
MediaEngineTabVideoSource::GetName(nsAString& aName) const
{
aName.AssignLiteral(u"&getUserMedia.videoSource.tabShare;");
}
void
MediaEngineTabVideoSource::GetUUID(nsACString_internal& aUuid) const
MediaEngineTabVideoSource::GetUUID(nsACString& aUuid) const
{
aUuid.AssignLiteral("tab");
}

View File

@ -19,8 +19,8 @@ class MediaEngineTabVideoSource : public MediaEngineVideoSource, nsIDOMEventList
NS_DECL_NSITIMERCALLBACK
MediaEngineTabVideoSource();
void GetName(nsAString_internal&) const override;
void GetUUID(nsACString_internal&) const override;
void GetName(nsAString&) const override;
void GetUUID(nsACString&) const override;
bool GetScary() const override {
return true;

View File

@ -18,6 +18,8 @@ interface IntersectionObserverEntry {
[Constant]
readonly attribute DOMRectReadOnly intersectionRect;
[Constant]
readonly attribute boolean isIntersecting;
[Constant]
readonly attribute double intersectionRatio;
[Constant]
readonly attribute Element target;

View File

@ -12,7 +12,7 @@
#include "mozilla/dom/Element.h" // for Element
#include "mozilla/dom/Selection.h"
#include "mozilla/mozalloc.h" // for operator delete, etc
#include "nsAString.h" // for nsAString_internal::IsEmpty, etc
#include "nsAString.h" // for nsAString::IsEmpty, etc
#include "nsComponentManagerUtils.h" // for do_CreateInstance
#include "nsDebug.h" // for NS_ENSURE_TRUE, etc
#include "nsDependentSubstring.h" // for Substring

View File

@ -6,7 +6,7 @@
#include "mozilla/ChangeStyleTransaction.h"
#include "mozilla/dom/Element.h" // for Element
#include "nsAString.h" // for nsAString_internal::Append, etc.
#include "nsAString.h" // for nsAString::Append, etc.
#include "nsCRT.h" // for nsCRT::IsAsciiSpace
#include "nsDebug.h" // for NS_ENSURE_SUCCESS, etc.
#include "nsError.h" // for NS_ERROR_NULL_POINTER, etc.

View File

@ -40,7 +40,7 @@
#include "mozilla/dom/Text.h"
#include "mozilla/dom/Event.h"
#include "mozilla/mozalloc.h" // for operator new, etc.
#include "nsAString.h" // for nsAString_internal::Length, etc.
#include "nsAString.h" // for nsAString::Length, etc.
#include "nsCCUncollectableMarker.h" // for nsCCUncollectableMarker
#include "nsCaret.h" // for nsCaret
#include "nsCaseTreatment.h"
@ -1586,11 +1586,10 @@ EditorBase::DeleteNode(nsINode* aNode)
}
}
RefPtr<DeleteNodeTransaction> transaction;
nsresult rv = CreateTxnForDeleteNode(aNode, getter_AddRefs(transaction));
if (NS_SUCCEEDED(rv)) {
rv = DoTransaction(transaction);
}
RefPtr<DeleteNodeTransaction> deleteNodeTransaction =
CreateTxnForDeleteNode(aNode);
nsresult rv = deleteNodeTransaction ? DoTransaction(deleteNodeTransaction) :
NS_ERROR_FAILURE;
{
AutoActionListenerArray listeners(mActionListeners);
@ -4062,17 +4061,22 @@ EditorBase::DeleteSelectionImpl(EDirection aAction,
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_STATE(selection);
RefPtr<EditAggregateTransaction> transaction;
RefPtr<EditAggregateTransaction> deleteSelectionTransaction;
nsCOMPtr<nsINode> deleteNode;
int32_t deleteCharOffset = 0, deleteCharLength = 0;
nsresult rv = CreateTxnForDeleteSelection(aAction,
getter_AddRefs(transaction),
if (!selection->Collapsed() || aAction != eNone) {
deleteSelectionTransaction =
CreateTxnForDeleteSelection(aAction,
getter_AddRefs(deleteNode),
&deleteCharOffset,
&deleteCharLength);
nsCOMPtr<nsIDOMCharacterData> deleteCharData(do_QueryInterface(deleteNode));
if (NS_WARN_IF(!deleteSelectionTransaction)) {
return NS_ERROR_FAILURE;
}
}
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIDOMCharacterData> deleteCharData(do_QueryInterface(deleteNode));
AutoRules beginRulesSniffing(this, EditAction::deleteSelection, aAction);
// Notify nsIEditActionListener::WillDelete[Selection|Text|Node]
{
@ -4093,7 +4097,7 @@ EditorBase::DeleteSelectionImpl(EDirection aAction,
}
// Delete the specified amount
rv = DoTransaction(transaction);
nsresult rv = DoTransaction(deleteSelectionTransaction);
// Notify nsIEditActionListener::DidDelete[Selection|Text|Node]
{
@ -4112,7 +4116,6 @@ EditorBase::DeleteSelectionImpl(EDirection aAction,
}
}
}
}
return rv;
}
@ -4291,12 +4294,11 @@ EditorBase::CreateTxnForInsertNode(nsIContent& aNode,
return transaction.forget();
}
nsresult
EditorBase::CreateTxnForDeleteNode(nsINode* aNode,
DeleteNodeTransaction** aTransaction)
already_AddRefed<DeleteNodeTransaction>
EditorBase::CreateTxnForDeleteNode(nsINode* aNode)
{
if (NS_WARN_IF(!aNode)) {
return NS_ERROR_NULL_POINTER;
return nullptr;
}
RefPtr<DeleteNodeTransaction> deleteNodeTransaction =
@ -4304,11 +4306,9 @@ EditorBase::CreateTxnForDeleteNode(nsINode* aNode,
// This should be OK because if currently it cannot delete the node,
// it should never be able to undo/redo.
if (!deleteNodeTransaction->CanDoIt()) {
return NS_ERROR_FAILURE;
return nullptr;
}
deleteNodeTransaction.forget(aTransaction);
return NS_OK;
return deleteNodeTransaction.forget();
}
already_AddRefed<CompositionTransaction>
@ -4343,22 +4343,20 @@ EditorBase::CreateTxnForRemoveStyleSheet(StyleSheet* aSheet)
return transaction.forget();
}
nsresult
already_AddRefed<EditAggregateTransaction>
EditorBase::CreateTxnForDeleteSelection(EDirection aAction,
EditAggregateTransaction** aTransaction,
nsINode** aNode,
nsINode** aRemovingNode,
int32_t* aOffset,
int32_t* aLength)
{
MOZ_ASSERT(aTransaction);
*aTransaction = nullptr;
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_STATE(selection);
if (NS_WARN_IF(!selection)) {
return nullptr;
}
// Check whether the selection is collapsed and we should do nothing:
if (selection->Collapsed() && aAction == eNone) {
return NS_OK;
if (NS_WARN_IF(selection->Collapsed() && aAction == eNone)) {
return nullptr;
}
// allocate the out-param transaction
@ -4367,7 +4365,9 @@ EditorBase::CreateTxnForDeleteSelection(EDirection aAction,
for (uint32_t rangeIdx = 0; rangeIdx < selection->RangeCount(); ++rangeIdx) {
RefPtr<nsRange> range = selection->GetRangeAt(rangeIdx);
NS_ENSURE_STATE(range);
if (NS_WARN_IF(!range)) {
return nullptr;
}
// Same with range as with selection; if it is collapsed and action
// is eNone, do nothing.
@ -4379,16 +4379,22 @@ EditorBase::CreateTxnForDeleteSelection(EDirection aAction,
} else if (aAction != eNone) {
// we have an insertion point. delete the thing in front of it or
// behind it, depending on aAction
nsresult rv = CreateTxnForDeleteInsertionPoint(range, aAction,
aggregateTransaction,
aNode, aOffset, aLength);
NS_ENSURE_SUCCESS(rv, rv);
// XXX Odd, when there are two or more ranges, this returns the last
// range information with aRemovingNode, aOffset and aLength.
RefPtr<EditTransactionBase> deleteRangeTransaction =
CreateTxnForDeleteRange(range, aAction,
aRemovingNode, aOffset, aLength);
// XXX When there are two or more ranges and at least one of them is
// not editable, deleteRangeTransaction may be nullptr.
// In such case, should we stop removing other ranges too?
if (NS_WARN_IF(!deleteRangeTransaction)) {
return nullptr;
}
aggregateTransaction->AppendChild(deleteRangeTransaction);
}
}
aggregateTransaction.forget(aTransaction);
return NS_OK;
return aggregateTransaction.forget();
}
already_AddRefed<DeleteTextTransaction>
@ -4427,22 +4433,22 @@ EditorBase::CreateTxnForDeleteCharacter(nsGenericDOMDataNode& aData,
//XXX: currently, this doesn't handle edge conditions because GetNext/GetPrior
//are not implemented
nsresult
EditorBase::CreateTxnForDeleteInsertionPoint(
nsRange* aRange,
already_AddRefed<EditTransactionBase>
EditorBase::CreateTxnForDeleteRange(nsRange* aRangeToDelete,
EDirection aAction,
EditAggregateTransaction* aTransaction,
nsINode** aNode,
nsINode** aRemovingNode,
int32_t* aOffset,
int32_t* aLength)
{
MOZ_ASSERT(aAction != eNone);
// get the node and offset of the insertion point
nsCOMPtr<nsINode> node = aRange->GetStartParent();
NS_ENSURE_STATE(node);
nsCOMPtr<nsINode> node = aRangeToDelete->GetStartParent();
if (NS_WARN_IF(!node)) {
return nullptr;
}
int32_t offset = aRange->StartOffset();
int32_t offset = aRangeToDelete->StartOffset();
// determine if the insertion point is at the beginning, middle, or end of
// the node
@ -4461,7 +4467,9 @@ EditorBase::CreateTxnForDeleteInsertionPoint(
// we're backspacing from the beginning of the node. Delete the first
// thing to our left
nsCOMPtr<nsIContent> priorNode = GetPriorNode(node, true);
NS_ENSURE_STATE(priorNode);
if (NS_WARN_IF(!priorNode)) {
return nullptr;
}
// there is a priorNode, so delete its last child (if chardata, delete the
// last char). if it has no children, delete it
@ -4470,34 +4478,37 @@ EditorBase::CreateTxnForDeleteInsertionPoint(
static_cast<nsGenericDOMDataNode*>(priorNode.get());
uint32_t length = priorNode->Length();
// Bail out for empty chardata XXX: Do we want to do something else?
NS_ENSURE_STATE(length);
RefPtr<DeleteTextTransaction> transaction =
if (NS_WARN_IF(!length)) {
return nullptr;
}
RefPtr<DeleteTextTransaction> deleteTextTransaction =
CreateTxnForDeleteCharacter(*priorNodeAsCharData, length, ePrevious);
NS_ENSURE_STATE(transaction);
*aOffset = transaction->GetOffset();
*aLength = transaction->GetNumCharsToDelete();
aTransaction->AppendChild(transaction);
} else {
// priorNode is not chardata, so tell its parent to delete it
RefPtr<DeleteNodeTransaction> transaction;
nsresult rv =
CreateTxnForDeleteNode(priorNode, getter_AddRefs(transaction));
NS_ENSURE_SUCCESS(rv, rv);
aTransaction->AppendChild(transaction);
if (NS_WARN_IF(!deleteTextTransaction)) {
return nullptr;
}
*aOffset = deleteTextTransaction->GetOffset();
*aLength = deleteTextTransaction->GetNumCharsToDelete();
priorNode.forget(aRemovingNode);
return deleteTextTransaction.forget();
}
NS_ADDREF(*aNode = priorNode);
return NS_OK;
// priorNode is not chardata, so tell its parent to delete it
RefPtr<DeleteNodeTransaction> deleteNodeTransaction =
CreateTxnForDeleteNode(priorNode);
if (NS_WARN_IF(!deleteNodeTransaction)) {
return nullptr;
}
priorNode.forget(aRemovingNode);
return deleteNodeTransaction.forget();
}
if (aAction == eNext && isLast) {
// we're deleting from the end of the node. Delete the first thing to our
// right
nsCOMPtr<nsIContent> nextNode = GetNextNode(node, true);
NS_ENSURE_STATE(nextNode);
if (NS_WARN_IF(!nextNode)) {
return nullptr;
}
// there is a nextNode, so delete its first child (if chardata, delete the
// first char). if it has no children, delete it
@ -4506,41 +4517,45 @@ EditorBase::CreateTxnForDeleteInsertionPoint(
static_cast<nsGenericDOMDataNode*>(nextNode.get());
uint32_t length = nextNode->Length();
// Bail out for empty chardata XXX: Do we want to do something else?
NS_ENSURE_STATE(length);
RefPtr<DeleteTextTransaction> transaction =
if (NS_WARN_IF(!length)) {
return nullptr;
}
RefPtr<DeleteTextTransaction> deleteTextTransaction =
CreateTxnForDeleteCharacter(*nextNodeAsCharData, 0, eNext);
NS_ENSURE_STATE(transaction);
*aOffset = transaction->GetOffset();
*aLength = transaction->GetNumCharsToDelete();
aTransaction->AppendChild(transaction);
} else {
// nextNode is not chardata, so tell its parent to delete it
RefPtr<DeleteNodeTransaction> transaction;
nsresult rv =
CreateTxnForDeleteNode(nextNode, getter_AddRefs(transaction));
NS_ENSURE_SUCCESS(rv, rv);
aTransaction->AppendChild(transaction);
if (NS_WARN_IF(!deleteTextTransaction)) {
return nullptr;
}
*aOffset = deleteTextTransaction->GetOffset();
*aLength = deleteTextTransaction->GetNumCharsToDelete();
nextNode.forget(aRemovingNode);
return deleteTextTransaction.forget();
}
NS_ADDREF(*aNode = nextNode);
return NS_OK;
// nextNode is not chardata, so tell its parent to delete it
RefPtr<DeleteNodeTransaction> deleteNodeTransaction =
CreateTxnForDeleteNode(nextNode);
if (NS_WARN_IF(!deleteNodeTransaction)) {
return nullptr;
}
nextNode.forget(aRemovingNode);
return deleteNodeTransaction.forget();
}
if (node->IsNodeOfType(nsINode::eDATA_NODE)) {
RefPtr<nsGenericDOMDataNode> nodeAsCharData =
static_cast<nsGenericDOMDataNode*>(node.get());
// we have chardata, so delete a char at the proper offset
RefPtr<DeleteTextTransaction> transaction =
RefPtr<DeleteTextTransaction> deleteTextTransaction =
CreateTxnForDeleteCharacter(*nodeAsCharData, offset, aAction);
NS_ENSURE_STATE(transaction);
if (NS_WARN_IF(!deleteTextTransaction)) {
return nullptr;
}
*aOffset = deleteTextTransaction->GetOffset();
*aLength = deleteTextTransaction->GetNumCharsToDelete();
node.forget(aRemovingNode);
return deleteTextTransaction.forget();
}
aTransaction->AppendChild(transaction);
NS_ADDREF(*aNode = node);
*aOffset = transaction->GetOffset();
*aLength = transaction->GetNumCharsToDelete();
} else {
// we're either deleting a node or chardata, need to dig into the next/prev
// node to find out
nsCOMPtr<nsINode> selectedNode;
@ -4560,7 +4575,10 @@ EditorBase::CreateTxnForDeleteInsertionPoint(
selectedNode = GetNextNode(selectedNode, true);
}
}
NS_ENSURE_STATE(selectedNode);
if (NS_WARN_IF(!selectedNode)) {
return nullptr;
}
if (selectedNode->IsNodeOfType(nsINode::eDATA_NODE)) {
RefPtr<nsGenericDOMDataNode> selectedNodeAsCharData =
@ -4573,26 +4591,22 @@ EditorBase::CreateTxnForDeleteInsertionPoint(
RefPtr<DeleteTextTransaction> deleteTextTransaction =
CreateTxnForDeleteCharacter(*selectedNodeAsCharData, position,
aAction);
NS_ENSURE_TRUE(deleteTextTransaction, NS_ERROR_NULL_POINTER);
aTransaction->AppendChild(deleteTextTransaction);
if (NS_WARN_IF(!deleteTextTransaction)) {
return nullptr;
}
*aOffset = deleteTextTransaction->GetOffset();
*aLength = deleteTextTransaction->GetNumCharsToDelete();
} else {
RefPtr<DeleteNodeTransaction> deleteNodeTransaction;
nsresult rv =
CreateTxnForDeleteNode(selectedNode,
getter_AddRefs(deleteNodeTransaction));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(deleteNodeTransaction, NS_ERROR_NULL_POINTER);
aTransaction->AppendChild(deleteNodeTransaction);
selectedNode.forget(aRemovingNode);
return deleteTextTransaction.forget();
}
NS_ADDREF(*aNode = selectedNode);
RefPtr<DeleteNodeTransaction> deleteNodeTransaction =
CreateTxnForDeleteNode(selectedNode);
if (NS_WARN_IF(!deleteNodeTransaction)) {
return nullptr;
}
return NS_OK;
selectedNode.forget(aRemovingNode);
return deleteNodeTransaction.forget();
}
nsresult

View File

@ -112,6 +112,7 @@ class CreateElementTransaction;
class DeleteNodeTransaction;
class DeleteTextTransaction;
class EditAggregateTransaction;
class EditTransactionBase;
class ErrorResult;
class HTMLEditor;
class InsertNodeTransaction;
@ -313,25 +314,48 @@ protected:
/**
* Create a transaction for removing aNode from its parent.
*/
nsresult CreateTxnForDeleteNode(nsINode* aNode,
DeleteNodeTransaction** aTransaction);
already_AddRefed<DeleteNodeTransaction>
CreateTxnForDeleteNode(nsINode* aNode);
nsresult CreateTxnForDeleteSelection(
EDirection aAction,
EditAggregateTransaction** aTransaction,
/**
* Create an aggregate transaction for delete selection. The result may
* include DeleteNodeTransactions and/or DeleteTextTransactions as its
* children.
*
* @param aAction The action caused removing the selection.
* @param aRemovingNode The node to be removed.
* @param aOffset The start offset of the range in aRemovingNode.
* @param aLength The length of the range in aRemovingNode.
* @return If it can remove the selection, returns an
* aggregate transaction which has some
* DeleteNodeTransactions and/or
* DeleteTextTransactions as its children.
*/
already_AddRefed<EditAggregateTransaction>
CreateTxnForDeleteSelection(EDirection aAction,
nsINode** aNode,
int32_t* aOffset,
int32_t* aLength);
nsresult CreateTxnForDeleteInsertionPoint(
nsRange* aRange,
/**
* Create a transaction for removing the nodes and/or text in aRange.
*
* @param aRangeToDelete The range to be removed.
* @param aAction The action caused removing the range.
* @param aRemovingNode The node to be removed.
* @param aOffset The start offset of the range in aRemovingNode.
* @param aLength The length of the range in aRemovingNode.
* @return The transaction to remove the range. Its type
* is DeleteNodeTransaction or
* DeleteTextTransaction.
*/
already_AddRefed<EditTransactionBase>
CreateTxnForDeleteRange(nsRange* aRangeToDelete,
EDirection aAction,
EditAggregateTransaction* aTransaction,
nsINode** aNode,
nsINode** aRemovingNode,
int32_t* aOffset,
int32_t* aLength);
/**
* Create a transaction for inserting aStringToInsert into aTextNode. Never
* returns null.
@ -938,11 +962,6 @@ public:
virtual nsresult InsertFromDrop(nsIDOMEvent* aDropEvent) = 0;
virtual already_AddRefed<nsIDOMNode> FindUserSelectAllNode(nsIDOMNode* aNode)
{
return nullptr;
}
/**
* GetIMESelectionStartOffsetIn() returns the start offset of IME selection in
* the aTextNode. If there is no IME selection, returns -1.

View File

@ -10,7 +10,7 @@
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc.
#include "mozilla/EditorBase.h" // for EditorBase
#include "mozilla/dom/Element.h" // for Element, nsINode
#include "nsAString.h" // for nsAString_internal::IsEmpty
#include "nsAString.h" // for nsAString::IsEmpty
#include "nsCOMPtr.h" // for nsCOMPtr, operator==, etc.
#include "nsCaseTreatment.h"
#include "nsDebug.h" // for NS_PRECONDITION, etc.

View File

@ -174,17 +174,6 @@ HTMLEditorEventListener::MouseDown(nsIDOMMouseEvent* aMouseEvent)
// Select entire element clicked on if NOT within an existing selection
// and not the entire body, or table-related elements
if (element) {
nsCOMPtr<nsIDOMNode> selectAllNode =
htmlEditor->FindUserSelectAllNode(element);
if (selectAllNode) {
nsCOMPtr<nsIDOMElement> newElement = do_QueryInterface(selectAllNode);
if (newElement) {
node = selectAllNode;
element = newElement;
}
}
if (isContextClick && !HTMLEditUtils::IsImage(node)) {
selection->Collapse(parent, offset);
} else {

View File

@ -8,7 +8,7 @@
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc.
#include "mozilla/EditorUtils.h" // for EditorUtils
#include "mozilla/dom/Selection.h" // for Selection
#include "nsAString.h" // for nsAString_internal::Length
#include "nsAString.h" // for nsAString::Length
#include "nsCycleCollectionParticipant.h"
#include "nsDebug.h" // for NS_ENSURE_TRUE, etc.
#include "nsError.h" // for NS_OK, etc.

View File

@ -229,23 +229,6 @@ TextEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
bool isCollapsed = selection->Collapsed();
// Only the HTMLEditor::FindUserSelectAllNode returns a node.
nsCOMPtr<nsIDOMNode> userSelectNode = FindUserSelectAllNode(newSelectionParent);
if (userSelectNode) {
// The drop is happening over a "-moz-user-select: all"
// subtree so make sure the content we insert goes before
// the root of the subtree.
//
// XXX: Note that inserting before the subtree matches the
// current behavior when dropping on top of an image.
// The decision for dropping before or after the
// subtree should really be done based on coordinates.
newSelectionParent = GetNodeLocation(userSelectNode, &newSelectionOffset);
NS_ENSURE_TRUE(newSelectionParent, NS_ERROR_FAILURE);
}
// Check if mouse is in the selection
// if so, jump through some hoops to determine if mouse is over selection (bail)
// and whether user wants to copy selection or delete it

View File

@ -194,8 +194,7 @@ WSRunObject::InsertBreak(nsCOMPtr<nsINode>* aInOutParent,
// have to (it would still not be significant after br), but it's
// just more aesthetically pleasing to.
nsresult rv = DeleteChars(*aInOutParent, *aInOutOffset,
afterRun->mEndNode, afterRun->mEndOffset,
eOutsideUserSelectAll);
afterRun->mEndNode, afterRun->mEndOffset);
NS_ENSURE_SUCCESS(rv, nullptr);
} else if (afterRun->mType == WSType::normalWS) {
// Need to determine if break at front of non-nbsp run. If so, convert
@ -218,8 +217,7 @@ WSRunObject::InsertBreak(nsCOMPtr<nsINode>* aInOutParent,
// Need to delete the trailing ws that is before insertion point, because it
// would become significant after break inserted.
nsresult rv = DeleteChars(beforeRun->mStartNode, beforeRun->mStartOffset,
*aInOutParent, *aInOutOffset,
eOutsideUserSelectAll);
*aInOutParent, *aInOutOffset);
NS_ENSURE_SUCCESS(rv, nullptr);
} else if (beforeRun->mType == WSType::normalWS) {
// Try to change an nbsp to a space, just to prevent nbsp proliferation
@ -272,7 +270,7 @@ WSRunObject::InsertText(const nsAString& aStringToInsert,
// would become significant after text inserted.
nsresult rv =
DeleteChars(*aInOutParent, *aInOutOffset, afterRun->mEndNode,
afterRun->mEndOffset, eOutsideUserSelectAll);
afterRun->mEndOffset);
NS_ENSURE_SUCCESS(rv, rv);
} else if (afterRun->mType == WSType::normalWS) {
// Try to change an nbsp to a space, if possible, just to prevent nbsp
@ -289,7 +287,7 @@ WSRunObject::InsertText(const nsAString& aStringToInsert,
// it would become significant after text inserted.
nsresult rv =
DeleteChars(beforeRun->mStartNode, beforeRun->mStartOffset,
*aInOutParent, *aInOutOffset, eOutsideUserSelectAll);
*aInOutParent, *aInOutOffset);
NS_ENSURE_SUCCESS(rv, rv);
} else if (beforeRun->mType == WSType::normalWS) {
// Try to change an nbsp to a space, if possible, just to prevent nbsp
@ -1158,8 +1156,7 @@ WSRunObject::PrepareToDeleteRangePriv(WSRunObject* aEndObject)
if (afterRun && (afterRun->mType & WSType::leadingWS)) {
nsresult rv =
aEndObject->DeleteChars(aEndObject->mNode, aEndObject->mOffset,
afterRun->mEndNode, afterRun->mEndOffset,
eOutsideUserSelectAll);
afterRun->mEndNode, afterRun->mEndOffset);
NS_ENSURE_SUCCESS(rv, rv);
}
// adjust normal ws in afterRun if needed
@ -1171,7 +1168,7 @@ WSRunObject::PrepareToDeleteRangePriv(WSRunObject* aEndObject)
WSPoint point = aEndObject->GetCharAfter(aEndObject->mNode,
aEndObject->mOffset);
if (point.mTextNode && nsCRT::IsAsciiSpace(point.mChar)) {
nsresult rv = aEndObject->ConvertToNBSP(point, eOutsideUserSelectAll);
nsresult rv = aEndObject->ConvertToNBSP(point);
NS_ENSURE_SUCCESS(rv, rv);
}
}
@ -1179,7 +1176,7 @@ WSRunObject::PrepareToDeleteRangePriv(WSRunObject* aEndObject)
// trim before run of any trailing ws
if (beforeRun && (beforeRun->mType & WSType::trailingWS)) {
nsresult rv = DeleteChars(beforeRun->mStartNode, beforeRun->mStartOffset,
mNode, mOffset, eOutsideUserSelectAll);
mNode, mOffset);
NS_ENSURE_SUCCESS(rv, rv);
} else if (beforeRun && beforeRun->mType == WSType::normalWS && !mPRE) {
if ((afterRun && (afterRun->mType & WSType::trailingWS)) ||
@ -1195,7 +1192,7 @@ WSRunObject::PrepareToDeleteRangePriv(WSRunObject* aEndObject)
getter_AddRefs(wsEndNode), &wsEndOffset);
point.mTextNode = wsStartNode;
point.mOffset = wsStartOffset;
nsresult rv = ConvertToNBSP(point, eOutsideUserSelectAll);
nsresult rv = ConvertToNBSP(point);
NS_ENSURE_SUCCESS(rv, rv);
}
}
@ -1248,28 +1245,12 @@ nsresult
WSRunObject::DeleteChars(nsINode* aStartNode,
int32_t aStartOffset,
nsINode* aEndNode,
int32_t aEndOffset,
AreaRestriction aAR)
int32_t aEndOffset)
{
// MOOSE: this routine needs to be modified to preserve the integrity of the
// wsFragment info.
NS_ENSURE_TRUE(aStartNode && aEndNode, NS_ERROR_NULL_POINTER);
if (aAR == eOutsideUserSelectAll) {
nsCOMPtr<nsIDOMNode> san =
mHTMLEditor->FindUserSelectAllNode(GetAsDOMNode(aStartNode));
if (san) {
return NS_OK;
}
if (aStartNode != aEndNode) {
san = mHTMLEditor->FindUserSelectAllNode(GetAsDOMNode(aEndNode));
if (san) {
return NS_OK;
}
}
}
if (aStartNode == aEndNode && aStartOffset == aEndOffset) {
// Nothing to delete
return NS_OK;
@ -1436,20 +1417,12 @@ WSRunObject::GetCharBefore(const WSPoint &aPoint)
}
nsresult
WSRunObject::ConvertToNBSP(WSPoint aPoint, AreaRestriction aAR)
WSRunObject::ConvertToNBSP(WSPoint aPoint)
{
// MOOSE: this routine needs to be modified to preserve the integrity of the
// wsFragment info.
NS_ENSURE_TRUE(aPoint.mTextNode, NS_ERROR_NULL_POINTER);
if (aAR == eOutsideUserSelectAll) {
nsCOMPtr<nsIDOMNode> san =
mHTMLEditor->FindUserSelectAllNode(GetAsDOMNode(aPoint.mTextNode));
if (san) {
return NS_OK;
}
}
// First, insert an nbsp
AutoTransactionsConserveSelection dontSpazMySelection(mHTMLEditor);
nsAutoString nbspStr(nbsp);

View File

@ -308,11 +308,6 @@ protected:
{}
};
enum AreaRestriction
{
eAnywhere, eOutsideUserSelectAll
};
/**
* Return the node which we will handle white-space under. This is the
* closest block within the DOM subtree we're editing, or if none is
@ -332,14 +327,12 @@ protected:
nsresult PrepareToDeleteRangePriv(WSRunObject* aEndObject);
nsresult PrepareToSplitAcrossBlocksPriv();
nsresult DeleteChars(nsINode* aStartNode, int32_t aStartOffset,
nsINode* aEndNode, int32_t aEndOffset,
AreaRestriction aAR = eAnywhere);
nsINode* aEndNode, int32_t aEndOffset);
WSPoint GetCharAfter(nsINode* aNode, int32_t aOffset);
WSPoint GetCharBefore(nsINode* aNode, int32_t aOffset);
WSPoint GetCharAfter(const WSPoint& aPoint);
WSPoint GetCharBefore(const WSPoint& aPoint);
nsresult ConvertToNBSP(WSPoint aPoint,
AreaRestriction aAR = eAnywhere);
nsresult ConvertToNBSP(WSPoint aPoint);
void GetAsciiWSBounds(int16_t aDir, nsINode* aNode, int32_t aOffset,
dom::Text** outStartNode, int32_t* outStartOffset,
dom::Text** outEndNode, int32_t* outEndOffset);

View File

@ -8,7 +8,7 @@
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
#include "mozilla/dom/Selection.h"
#include "mozilla/mozalloc.h" // for operator new, etc
#include "nsAString.h" // for nsAString_internal::Length, etc
#include "nsAString.h" // for nsAString::Length, etc
#include "nsContentUtils.h" // for nsContentUtils
#include "nsDebug.h" // for NS_ENSURE_TRUE, etc
#include "nsDependentSubstring.h" // for Substring

View File

@ -156,14 +156,6 @@ AllowedImageSize(int32_t aWidth, int32_t aHeight)
NS_WARNING("width or height too large");
return false;
}
#if defined(XP_MACOSX)
// CoreGraphics is limited to images < 32K in *height*, so clamp all surfaces
// on the Mac to that height
if (MOZ_UNLIKELY(aHeight > SHRT_MAX)) {
NS_WARNING("image too big");
return false;
}
#endif
return true;
}

View File

@ -193,15 +193,15 @@ fuzzy(18,128) == downscale-32px.html?-bmp-in.ico downscale-32px-ref.html
fuzzy(18,128) == downscale-32px.html?-png-in.ico downscale-32px-ref.html
# Test images taller or wider than 32767 pixels.
fails-if(OSX) == huge-1.html?100x32768.png,100,100 huge-1.html?100x100.png,100,100
fails-if(OSX) == huge-1.html?100x32768.png,100,32768 huge-1.html?100x100.png,100,32768
== huge-1.html?100x32768.png,100,100 huge-1.html?100x100.png,100,100
== huge-1.html?100x32768.png,100,32768 huge-1.html?100x100.png,100,32768
== huge-1.html?32768x100.png,100,100 huge-1.html?100x100.png,100,100
== huge-1.html?32768x100.png,32768,100 huge-1.html?100x100.png,32768,100
fails-if(OSX) == huge-1.html?100x32768.gif,100,100 huge-1.html?100x100.gif,100,100
fails-if(OSX) == huge-1.html?100x32768.gif,100,32768 huge-1.html?100x100.gif,100,32768
== huge-1.html?100x32768.gif,100,100 huge-1.html?100x100.gif,100,100
== huge-1.html?100x32768.gif,100,32768 huge-1.html?100x100.gif,100,32768
== huge-1.html?32768x100.gif,100,100 huge-1.html?100x100.gif,100,100
== huge-1.html?32768x100.gif,32768,100 huge-1.html?100x100.gif,32768,100
fails-if(OSX) == huge-1.html?100x32768.jpg,100,100 huge-1.html?100x100.jpg,100,100
fails-if(OSX) == huge-1.html?100x32768.jpg,100,32768 huge-1.html?100x100.jpg,100,32768
== huge-1.html?100x32768.jpg,100,100 huge-1.html?100x100.jpg,100,100
== huge-1.html?100x32768.jpg,100,32768 huge-1.html?100x100.jpg,100,32768
== huge-1.html?32768x100.jpg,100,100 huge-1.html?100x100.jpg,100,100
== huge-1.html?32768x100.jpg,32768,100 huge-1.html?100x100.jpg,32768,100

View File

@ -196,8 +196,7 @@ var ignoreFunctions = {
// The nsScriptNameSpaceManager functions can't actually GC. They
// just use a PLDHashTable which has function pointers, which makes the
// analysis think maybe they can.
"nsGlobalNameStruct* nsScriptNameSpaceManager::LookupNavigatorName(nsAString_internal*)": true,
"nsGlobalNameStruct* nsScriptNameSpaceManager::LookupName(nsAString_internal*, uint16**)": true,
"nsGlobalNameStruct* nsScriptNameSpaceManager::LookupName(nsAString*, uint16**)": true,
// Similar to heap snapshot mock classes, and GTests below. This posts a
// synchronous runnable when a GTest fails, and we are pretty sure that the

View File

@ -972,9 +972,12 @@ class Watchdog
{
AutoLockWatchdog lock(this);
// Gecko uses thread private for accounting and has to clean up at thread exit.
// Therefore, even though we don't have a return value from the watchdog, we need to
// join it on shutdown.
mThread = PR_CreateThread(PR_USER_THREAD, WatchdogMain, this,
PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
PR_UNJOINABLE_THREAD, 0);
PR_JOINABLE_THREAD, 0);
if (!mThread)
NS_RUNTIMEABORT("PR_CreateThread failed!");
@ -997,10 +1000,13 @@ class Watchdog
// Wake up the watchdog, and wait for it to call us back.
PR_NotifyCondVar(mWakeup);
PR_WaitCondVar(mWakeup, PR_INTERVAL_NO_TIMEOUT);
MOZ_ASSERT(!mShuttingDown);
}
PR_JoinThread(mThread);
// The thread sets mShuttingDown to false as it exits.
MOZ_ASSERT(!mShuttingDown);
// Destroy state.
mThread = nullptr;
PR_DestroyCondVar(mWakeup);
@ -1039,7 +1045,6 @@ class Watchdog
{
MOZ_ASSERT(!NS_IsMainThread());
mShuttingDown = false;
PR_NotifyCondVar(mWakeup);
}
int32_t MinScriptRunTimeSeconds()

View File

@ -259,6 +259,13 @@ ServoRestyleManager::ProcessPostTraversal(Element* aElement,
MOZ_ASSERT(pseudoContext, "should have taken the ReconstructFrame path above");
pseudoFrame->SetStyleContext(pseudoContext);
if (pseudoFrame->GetStateBits() & NS_FRAME_OWNS_ANON_BOXES) {
// XXX It really would be good to pass the actual changehint for our
// ::before/::after here, but we never computed it!
pseudoFrame->UpdateStyleOfOwnedAnonBoxes(*aStyleSet, aChangeList,
nsChangeHint_Hints_NotHandledForDescendants);
}
// We only care restyling text nodes, since other type of nodes
// (images), are still not supported. If that eventually changes, we
// may have to write more code here... Or not, I don't think too

View File

@ -3112,6 +3112,8 @@ nsCSSFrameConstructor::ConstructSelectFrame(nsFrameConstructorState& aState,
aState.GetGeometricParent(aStyleDisplay, aParentFrame),
comboboxFrame);
comboboxFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
aState.AddChild(comboboxFrame, aFrameItems, content, styleContext,
aParentFrame);
@ -3279,6 +3281,8 @@ nsCSSFrameConstructor::ConstructFieldSetFrame(nsFrameConstructorState& aState,
aState.GetGeometricParent(aStyleDisplay, aParentFrame),
fieldsetFrame);
fieldsetFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
// Resolve style and initialize the frame
RefPtr<nsStyleContext> fieldsetContentStyle;
fieldsetContentStyle = mPresShell->StyleSet()->
@ -3325,7 +3329,8 @@ nsCSSFrameConstructor::ConstructFieldSetFrame(nsFrameConstructorState& aState,
if (columns->mColumnCount != NS_STYLE_COLUMN_COUNT_AUTO ||
columns->mColumnWidth.GetUnit() != eStyleUnit_Auto) {
columnSetFrame =
NS_NewColumnSetFrame(mPresShell, fieldsetContentStyle, nsFrameState(0));
NS_NewColumnSetFrame(mPresShell, fieldsetContentStyle,
nsFrameState(NS_FRAME_OWNS_ANON_BOXES));
InitAndRestoreFrame(aState, content, parent, columnSetFrame);
innerSC = mPresShell->StyleSet()->
ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::columnContent,
@ -3974,7 +3979,8 @@ nsCSSFrameConstructor::ConstructFrameFromItemInternal(FrameConstructionItem& aIt
if (columns->mColumnCount != NS_STYLE_COLUMN_COUNT_AUTO ||
columns->mColumnWidth.GetUnit() != eStyleUnit_Auto) {
columnSetFrame =
NS_NewColumnSetFrame(mPresShell, outerSC, nsFrameState(0));
NS_NewColumnSetFrame(mPresShell, outerSC,
nsFrameState(NS_FRAME_OWNS_ANON_BOXES));
InitAndRestoreFrame(aState, content, container, columnSetFrame);
innerSC = mPresShell->StyleSet()->
ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::columnContent,
@ -4000,6 +4006,8 @@ nsCSSFrameConstructor::ConstructFrameFromItemInternal(FrameConstructionItem& aIt
SetInitialSingleChild(container, outerFrame);
container->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
// Now figure out whether newFrame or outerFrame should be the
// absolute container.
auto outerDisplay = outerSC->StyleDisplay();
@ -5253,6 +5261,7 @@ nsCSSFrameConstructor::ConstructFrameWithAnonymousChild(
aParentFrame) :
aParentFrame,
newFrame);
newFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
// Create the pseudo SC for the anonymous wrapper child as a child of the SC:
RefPtr<nsStyleContext> scForAnon;
@ -12035,7 +12044,8 @@ nsCSSFrameConstructor::ConstructBlock(nsFrameConstructorState& aState,
if (columns->mColumnCount != NS_STYLE_COLUMN_COUNT_AUTO
|| columns->mColumnWidth.GetUnit() != eStyleUnit_Auto) {
nsContainerFrame* columnSetFrame =
NS_NewColumnSetFrame(mPresShell, aStyleContext, nsFrameState(0));
NS_NewColumnSetFrame(mPresShell, aStyleContext,
nsFrameState(NS_FRAME_OWNS_ANON_BOXES));
InitAndRestoreFrame(aState, aContent, aParentFrame, columnSetFrame);
blockStyle = mPresShell->StyleSet()->

View File

@ -1186,6 +1186,18 @@ nsComboboxControlFrame::GetContentInsertionFrame() {
return mInRedisplayText ? mDisplayFrame : mDropdownFrame->GetContentInsertionFrame();
}
void
nsComboboxControlFrame::DoUpdateStyleOfOwnedAnonBoxes(
ServoStyleSet& aStyleSet,
nsStyleChangeList& aChangeList,
nsChangeHint aHintForThisFrame)
{
UpdateStyleOfChildAnonBox(mDropdownFrame, aStyleSet, aChangeList,
aHintForThisFrame);
UpdateStyleOfChildAnonBox(mDisplayFrame, aStyleSet, aChangeList,
aHintForThisFrame);
}
nsresult
nsComboboxControlFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
{

View File

@ -123,6 +123,11 @@ public:
virtual nsContainerFrame* GetContentInsertionFrame() override;
// Update the style on the block wrappers around our kids.
void DoUpdateStyleOfOwnedAnonBoxes(mozilla::ServoStyleSet& aStyleSet,
nsStyleChangeList& aChangeList,
nsChangeHint aHintForThisFrame) override;
// nsIFormControlFrame
virtual nsresult SetFormProperty(nsIAtom* aName, const nsAString& aValue) override;
/**

View File

@ -671,3 +671,15 @@ nsFieldSetFrame::GetNaturalBaselineBOffset(WritingMode aWM,
}
return true;
}
void
nsFieldSetFrame::DoUpdateStyleOfOwnedAnonBoxes(ServoStyleSet& aStyleSet,
nsStyleChangeList& aChangeList,
nsChangeHint aHintForThisFrame)
{
nsIFrame* kid = GetInner();
if (kid) {
UpdateStyleOfChildAnonBox(kid, aStyleSet, aChangeList, aHintForThisFrame);
}
}

View File

@ -74,6 +74,12 @@ public:
return do_QueryFrame(GetInner());
}
// Update the style on the block wrappers around our kids.
virtual void DoUpdateStyleOfOwnedAnonBoxes(
mozilla::ServoStyleSet& aStyleSet,
nsStyleChangeList& aChangeList,
nsChangeHint aHintForThisFrame) override;
#ifdef ACCESSIBILITY
virtual mozilla::a11y::AccType AccessibleType() override;
#endif
@ -88,7 +94,8 @@ public:
* Return the anonymous frame that contains all descendants except
* the legend frame. This is currently always a block frame with
* pseudo nsCSSAnonBoxes::fieldsetContent -- this may change in the
* future when we add support for CSS overflow for <fieldset>.
* future when we add support for CSS overflow for <fieldset>. This really
* can't return null, though callers seem to feel that it can.
*/
nsIFrame* GetInner() const;

View File

@ -400,6 +400,19 @@ nsHTMLButtonControlFrame::SetAdditionalStyleContext(int32_t aIndex,
mRenderer.SetStyleContext(aIndex, aStyleContext);
}
void
nsHTMLButtonControlFrame::DoUpdateStyleOfOwnedAnonBoxes(
ServoStyleSet& aStyleSet,
nsStyleChangeList& aChangeList,
nsChangeHint aHintForThisFrame)
{
MOZ_ASSERT(mFrames.FirstChild(), "Must have our button-content anon box");
MOZ_ASSERT(!mFrames.FirstChild()->GetNextSibling(),
"Must only have our button-content anon box");
UpdateStyleOfChildAnonBox(mFrames.FirstChild(),
aStyleSet, aChangeList, aHintForThisFrame);
}
#ifdef DEBUG
void
nsHTMLButtonControlFrame::AppendFrames(ChildListID aListID,

View File

@ -97,6 +97,12 @@ public:
~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
}
/**
* Update the style of our ::-moz-button-content anonymous box.
*/
void DoUpdateStyleOfOwnedAnonBoxes(mozilla::ServoStyleSet& aStyleSet,
nsStyleChangeList& aChangeList,
nsChangeHint aHintForThisFrame) override;
protected:
virtual bool IsInput() { return false; }

View File

@ -1139,6 +1139,26 @@ nsColumnSetFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
}
}
void
nsColumnSetFrame::DoUpdateStyleOfOwnedAnonBoxes(
mozilla::ServoStyleSet& aStyleSet,
nsStyleChangeList& aChangeList,
nsChangeHint aHintForThisFrame)
{
// Everything in mFrames is continuations of the first thing in mFrames.
nsIFrame* column = mFrames.FirstChild();
// We might not have any columns, apparently?
if (!column) {
return;
}
MOZ_ASSERT(column->StyleContext()->GetPseudo() ==
nsCSSAnonBoxes::columnContent,
"What sort of child is this?");
UpdateStyleOfChildAnonBox(column, aStyleSet, aChangeList, aHintForThisFrame);
}
#ifdef DEBUG
void
nsColumnSetFrame::SetInitialChildList(ChildListID aListID,

View File

@ -83,6 +83,13 @@ public:
*/
void DrainOverflowColumns();
/**
* Update the style on our column-content frames.
*/
void DoUpdateStyleOfOwnedAnonBoxes(mozilla::ServoStyleSet& aStyleSet,
nsStyleChangeList& aChangeList,
nsChangeHint aHintForThisFrame) override;
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override {
return MakeFrameName(NS_LITERAL_STRING("ColumnSet"), aResult);

View File

@ -10067,6 +10067,8 @@ nsFrame::UpdateStyleOfChildAnonBox(nsIFrame* aChildFrame,
"This should only be used for children!");
MOZ_ASSERT(aChildFrame->GetContent() == GetContent(),
"What content node is it a frame for?");
MOZ_ASSERT(!aChildFrame->GetPrevContinuation(),
"Only first continuations should end up here");
// We could force the caller to pass in the pseudo, since some callers know it
// statically... But this API is a bit nicer.

View File

@ -335,8 +335,7 @@ nsHTMLFramesetFrame::Init(nsIContent* aContent,
for (int blankX = mChildCount; blankX < numCells; blankX++) {
RefPtr<nsStyleContext> pseudoStyleContext;
pseudoStyleContext = shell->StyleSet()->
ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::framesetBlank,
mStyleContext);
ResolveNonInheritingAnonymousBoxStyle(nsCSSAnonBoxes::framesetBlank);
// XXX the blank frame is using the content of its parent - at some point it
// should just have null content, if we support that
@ -912,8 +911,7 @@ nsHTMLFramesetFrame::Reflow(nsPresContext* aPresContext,
RefPtr<nsStyleContext> pseudoStyleContext;
pseudoStyleContext = styleSet->
ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::horizontalFramesetBorder,
mStyleContext);
ResolveNonInheritingAnonymousBoxStyle(nsCSSAnonBoxes::horizontalFramesetBorder);
borderFrame = new (shell) nsHTMLFramesetBorderFrame(pseudoStyleContext,
borderWidth,
@ -942,8 +940,7 @@ nsHTMLFramesetFrame::Reflow(nsPresContext* aPresContext,
RefPtr<nsStyleContext> pseudoStyleContext;
pseudoStyleContext = styleSet->
ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::verticalFramesetBorder,
mStyleContext);
ResolveNonInheritingAnonymousBoxStyle(nsCSSAnonBoxes::verticalFramesetBorder);
borderFrame = new (shell) nsHTMLFramesetBorderFrame(pseudoStyleContext,
borderWidth,

View File

@ -419,6 +419,18 @@ nsHTMLCanvasFrame::GetContinuationOffset(nscoord* aWidth) const
return offset;
}
void
nsHTMLCanvasFrame::DoUpdateStyleOfOwnedAnonBoxes(ServoStyleSet& aStyleSet,
nsStyleChangeList& aChangeList,
nsChangeHint aHintForThisFrame)
{
MOZ_ASSERT(mFrames.FirstChild(), "Must have our canvas content anon box");
MOZ_ASSERT(!mFrames.FirstChild()->GetNextSibling(),
"Must only have our canvas content anon box");
UpdateStyleOfChildAnonBox(mFrames.FirstChild(),
aStyleSet, aChangeList, aHintForThisFrame);
}
#ifdef ACCESSIBILITY
a11y::AccType
nsHTMLCanvasFrame::AccessibleType()

View File

@ -99,6 +99,12 @@ public:
return PrincipalChildList().FirstChild()->GetContentInsertionFrame();
}
/**
* Update the style of our ::-moz-html-canvas-content anonymous box.
*/
void DoUpdateStyleOfOwnedAnonBoxes(mozilla::ServoStyleSet& aStyleSet,
nsStyleChangeList& aChangeList,
nsChangeHint aHintForThisFrame) override;
protected:
virtual ~nsHTMLCanvasFrame();

View File

@ -6185,7 +6185,16 @@ Selection::PostScrollSelectionIntoViewEvent(
RefPtr<ScrollSelectionIntoViewEvent> ev =
new ScrollSelectionIntoViewEvent(this, aRegion, aVertical, aHorizontal,
aFlags);
nsresult rv = NS_DispatchToCurrentThread(ev);
nsresult rv;
nsIDocument* doc = GetParentObject();
if (doc) {
rv = doc->Dispatch("ScrollSelectionIntoViewEvent",
TaskCategory::Other,
ev.forget());
} else {
rv = NS_DispatchToCurrentThread(ev);
}
NS_ENSURE_SUCCESS(rv, rv);
mScrollEvent = ev;

View File

@ -2482,45 +2482,6 @@ void nsDisplayList::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
"How did we forget to pop some elements?");
}
static void Sort(nsDisplayList* aList, int32_t aCount, nsDisplayList::SortLEQ aCmp,
void* aClosure) {
if (aCount < 2)
return;
nsDisplayList list1;
nsDisplayList list2;
int i;
int32_t half = aCount/2;
bool sorted = true;
nsDisplayItem* prev = nullptr;
for (i = 0; i < aCount; ++i) {
nsDisplayItem* item = aList->RemoveBottom();
(i < half ? &list1 : &list2)->AppendToTop(item);
if (sorted && prev && !aCmp(prev, item, aClosure)) {
sorted = false;
}
prev = item;
}
if (sorted) {
aList->AppendToTop(&list1);
aList->AppendToTop(&list2);
return;
}
Sort(&list1, half, aCmp, aClosure);
Sort(&list2, aCount - half, aCmp, aClosure);
for (i = 0; i < aCount; ++i) {
if (list1.GetBottom() &&
(!list2.GetBottom() ||
aCmp(list1.GetBottom(), list2.GetBottom(), aClosure))) {
aList->AppendToTop(list1.RemoveBottom());
} else {
aList->AppendToTop(list2.RemoveBottom());
}
}
}
static nsIContent* FindContentInDocument(nsDisplayItem* aItem, nsIDocument* aDoc) {
nsIFrame* f = aItem->Frame();
while (f) {
@ -2533,41 +2494,55 @@ static nsIContent* FindContentInDocument(nsDisplayItem* aItem, nsIDocument* aDoc
return nullptr;
}
static bool IsContentLEQ(nsDisplayItem* aItem1, nsDisplayItem* aItem2,
void* aClosure) {
nsIContent* commonAncestor = static_cast<nsIContent*>(aClosure);
struct ZSortItem {
nsDisplayItem* item;
int32_t zIndex;
explicit ZSortItem(nsDisplayItem* aItem)
: item(aItem), zIndex(aItem->ZIndex()) {}
operator nsDisplayItem*() {
return item;
}
};
struct ZOrderComparator {
bool operator()(const ZSortItem& aLeft, const ZSortItem& aRight) const {
// Note that we can't just take the difference of the two
// z-indices here, because that might overflow a 32-bit int.
return aLeft.zIndex < aRight.zIndex;
}
};
void nsDisplayList::SortByZOrder() {
Sort<ZSortItem>(ZOrderComparator());
}
struct ContentComparator {
nsIContent* mCommonAncestor;
explicit ContentComparator(nsIContent* aCommonAncestor)
: mCommonAncestor(aCommonAncestor) {}
bool operator()(nsDisplayItem* aLeft, nsDisplayItem* aRight) const {
// It's possible that the nsIContent for aItem1 or aItem2 is in a subdocument
// of commonAncestor, because display items for subdocuments have been
// mixed into the same list. Ensure that we're looking at content
// in commonAncestor's document.
nsIDocument* commonAncestorDoc = commonAncestor->OwnerDoc();
nsIContent* content1 = FindContentInDocument(aItem1, commonAncestorDoc);
nsIContent* content2 = FindContentInDocument(aItem2, commonAncestorDoc);
nsIDocument* commonAncestorDoc = mCommonAncestor->OwnerDoc();
nsIContent* content1 = FindContentInDocument(aLeft, commonAncestorDoc);
nsIContent* content2 = FindContentInDocument(aRight, commonAncestorDoc);
if (!content1 || !content2) {
NS_ERROR("Document trees are mixed up!");
// Something weird going on
return true;
}
return nsLayoutUtils::CompareTreePosition(content1, content2, commonAncestor) <= 0;
}
static bool IsZOrderLEQ(nsDisplayItem* aItem1, nsDisplayItem* aItem2,
void* aClosure) {
// Note that we can't just take the difference of the two
// z-indices here, because that might overflow a 32-bit int.
return aItem1->ZIndex() <= aItem2->ZIndex();
}
void nsDisplayList::SortByZOrder() {
Sort(IsZOrderLEQ, nullptr);
return nsLayoutUtils::CompareTreePosition(content1, content2, mCommonAncestor) < 0;
}
};
void nsDisplayList::SortByContentOrder(nsIContent* aCommonAncestor) {
Sort(IsContentLEQ, aCommonAncestor);
}
void nsDisplayList::Sort(SortLEQ aCmp, void* aClosure) {
::Sort(this, Count(), aCmp, aClosure);
Sort<nsDisplayItem*>(ContentComparator(aCommonAncestor));
}
nsDisplayItem::nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)

View File

@ -2328,14 +2328,26 @@ public:
void SortByContentOrder(nsIContent* aCommonAncestor);
/**
* Generic stable sort. Take care, because some of the items might be nsDisplayLists
* themselves.
* aCmp(item1, item2) should return true if item1 <= item2. We sort the items
* into increasing order.
* Sort the display list using a stable sort. Take care, because some of the
* items might be nsDisplayLists themselves.
* aComparator(Item item1, Item item2) should return true if item1 should go
* before item2.
* We sort the items into increasing order.
*/
typedef bool (* SortLEQ)(nsDisplayItem* aItem1, nsDisplayItem* aItem2,
void* aClosure);
void Sort(SortLEQ aCmp, void* aClosure);
template<typename Item, typename Comparator>
void Sort(const Comparator& aComparator) {
nsTArray<Item> items;
while (nsDisplayItem* item = RemoveBottom()) {
items.AppendElement(Item(item));
}
std::stable_sort(items.begin(), items.end(), aComparator);
for (Item& item : items) {
AppendToTop(item);
}
}
/**
* Compute visiblity for the items in the list.

View File

@ -36,7 +36,7 @@ fuzzy-if(Android,9,134) random-if(layersGPUAccelerated) == logicalmarquee.html l
== mixedChartype-03.html mixedChartype-03.html
== mixedChartype-03-j.html mixedChartype-03-j.html
== unicode-bidi-anonymous-001.html unicode-bidi-anonymous-001.html
fails == unicode-bidi-anonymous-002.html unicode-bidi-anonymous-002.html
== unicode-bidi-anonymous-002.html unicode-bidi-anonymous-002.html
== unicode-bidi-isolate-basic.html unicode-bidi-isolate-basic.html
fails == unicode-bidi-isolate-aharon.html unicode-bidi-isolate-aharon.html
fails == unicode-bidi-plaintext.html unicode-bidi-plaintext.html

View File

@ -10,7 +10,7 @@ fails == tableboxshadow-basic.html tableboxshadow-basic.html
fails == tableboxshadow-trshadow.html tableboxshadow-trshadow.html
fails == tableboxshadow-tdshadow.html tableboxshadow-tdshadow.html
== boxshadow-rounding.html boxshadow-rounding.html
fails == boxshadow-button.html boxshadow-button.html
== boxshadow-button.html boxshadow-button.html
fails == boxshadow-fileupload.html boxshadow-fileupload.html
== boxshadow-inner-basic.html boxshadow-inner-basic.html
random-if(layersGPUAccelerated) == boxshadow-mixed.html boxshadow-mixed.html
@ -24,7 +24,7 @@ fuzzy(2,440) == boxshadow-skiprect.html boxshadow-skiprect.html
== boxshadow-color-rounding.html boxshadow-color-rounding.html
== boxshadow-color-rounding-middle.html boxshadow-color-rounding-middle.html
fuzzy-if(OSX==1010,1,24) fuzzy-if(d2d,16,908) == boxshadow-large-border-radius.html boxshadow-large-border-radius.html
fails == boxshadow-border-radius-int.html boxshadow-border-radius-int.html
== boxshadow-border-radius-int.html boxshadow-border-radius-int.html
== boxshadow-inset-neg-spread.html boxshadow-inset-neg-spread.html
== boxshadow-inset-neg-spread2.html boxshadow-inset-neg-spread2.html
fails == boxshadow-rotated.html boxshadow-rotated.html

View File

@ -90,7 +90,7 @@ fails == 82711-1-ref.html 82711-1-ref.html # Bug 1341697, Bug 1341637
fails == 82711-1-ref.html 82711-1-ref.html # Bug 1341697, Bug 1341637
fails == 82711-2-ref.html 82711-2-ref.html
fails == 84400-1.html 84400-1.html
fails == 84400-2.html 84400-2.html
== 84400-2.html 84400-2.html
== 97777-1.html 97777-1.html
== 97777-2.html 97777-2.html
== 98223-1.html 98223-1.html
@ -196,10 +196,10 @@ fails == 201293-1d.html 201293-1d.html
== 206516-1.html 206516-1.html
== 206631-1.html 206631-1.html
== 206802.html 206802.html
fails == 210094-1a.html 210094-1a.html
fails == 210094-1b.html 210094-1b.html
fails == 210094-1c.html 210094-1c.html
fails == 210876-1.html 210876-1.html
== 210094-1a.html 210094-1a.html
== 210094-1b.html 210094-1b.html
== 210094-1c.html 210094-1c.html
== 210876-1.html 210876-1.html
== 211931-1.html 211931-1.html
fails == 212563-1.html 212563-1.html
== 212563-2.html 212563-2.html
@ -284,11 +284,11 @@ fails == 260406-1.html 260406-1.html
== 262151-1.html 262151-1.html
fails == 262998-1.html 262998-1.html
== 267353-1.html 267353-1.html
fails == 269908-1.html 269908-1.html
fails == 269908-2.html 269908-2.html
fails == 269908-3.html 269908-3.html
fails == 269908-4.html 269908-4.html
fails == 269908-5.html 269908-5.html
== 269908-1.html 269908-1.html
== 269908-2.html 269908-2.html
== 269908-3.html 269908-3.html
== 269908-4.html 269908-4.html
== 269908-5.html 269908-5.html
fails == 271747-1a.html 271747-1a.html
fails == 271747-1b.html 271747-1b.html
== 272646-1.xul 272646-1.xul
@ -452,7 +452,7 @@ fails == 338251-p.html 338251-p.html
fails == 338251-p-oh.html 338251-p-oh.html
fails == 338251-pre.html 338251-pre.html
fails == 338251-pre-oh.html 338251-pre-oh.html
fails == 339289-1.html 339289-1.html
== 339289-1.html 339289-1.html
== 341043-1a.html 341043-1a.html
== 341043-1b.html 341043-1b.html
== 343538-1.html 343538-1.html
@ -528,7 +528,7 @@ fails == 352980-3f.html 352980-3f.html
== 355548-5.xml 355548-5.xml
== 356774-1.html 356774-1.html
== 356775-1.html 356775-1.html
fails == 359869-1.html 359869-1.html
== 359869-1.html 359869-1.html
fails == 359903-1.html 359903-1.html
fails == 359903-2.html 359903-2.html
== 360065-1.html 360065-1.html
@ -544,7 +544,7 @@ asserts-if(stylo,1) == 360746-1.html 360746-1.html # Bug 1341721
== 362594-2b.html 362594-2b.html
== 362594-2b.html 362594-2b.html
== 362594-2c.html 362594-2c.html
fails == 362901-1.html 362901-1.html
== 362901-1.html 362901-1.html
== 363247-1.html 363247-1.html
== 363329-1.html 363329-1.html
fails == 363329-2.html 363329-2.html
@ -743,7 +743,7 @@ fails == 385870-2.html 385870-2.html
== 386014-1a.html 386014-1a.html
== 386014-1b.html 386014-1b.html
== 386014-1c.html 386014-1c.html
fails == 386065-1.html 386065-1.html
== 386065-1.html 386065-1.html
== 386065-2.html 386065-2.html
fails pref(layout.float-fragments-inside-column.enabled,false) == 386147-1.html 386147-1.html # Bug 1341095
fails pref(layout.float-fragments-inside-column.enabled,true) == 386147-1.html 386147-1.html # Bug 1341095
@ -887,14 +887,14 @@ fails == 403656-3.html 403656-3.html
== 403656-4.html 403656-4.html
== 403656-5.html 403656-5.html
== 403657-1.html 403657-1.html
fails == 403733-1.html 403733-1.html
== 403733-1.html 403733-1.html
fails == 403962-1.xhtml 403962-1.xhtml # Bug 1290276
== 404030-1.html 404030-1.html
== 404030-1-notref.html 404030-1-notref.html
== 404030-1-notref2.html 404030-1-notref2.html
fails == 404123-1.html 404123-1.html
fails == 404123-2.html 404123-2.html
fails == 404123-3.html 404123-3.html
== 404123-3.html 404123-3.html
# may fail "randomly" on OS X, doesn't seem to be rendering usefully anyhow - bug 602469
random-if(cocoaWidget) HTTP(..) == 404149-1.xul 404149-1.xul
== 404180-1.html 404180-1.html
@ -907,7 +907,7 @@ fails == 404553-1.html 404553-1.html
== 404666-1.html 404666-1.html
== 404666-2.html 404666-2.html
== 405186-1.xhtml 405186-1.xhtml
fails == 405305-1.html 405305-1.html
== 405305-1.html 405305-1.html
== 405380-1.html 405380-1.html
== 405517-1.xhtml 405517-1.xhtml
== 405577-1.html 405577-1.html
@ -995,7 +995,7 @@ fails asserts(1) == 418574-2.html 418574-2.html
== 418766-1b.html 418766-1b.html
== 419060.html 419060.html
== 419285-1.html 419285-1.html
fails == 419531-1.html 419531-1.html
== 419531-1.html 419531-1.html
== 420069-1.html 420069-1.html
== 420069-2.html 420069-2.html
== 420351-1.html 420351-1.html
@ -1135,7 +1135,7 @@ fails == 430412-1.html 430412-1.html
== 430813-3.html 430813-3.html
== 431341-1.html 431341-1.html
== 431341-2.html 431341-2.html
fails == 431520-1.html 431520-1.html
== 431520-1.html 431520-1.html
== 431948-1.html 431948-1.html
== 433640-1.html 433640-1.html
fails == 433700.html 433700.html
@ -1282,8 +1282,8 @@ fails == 474417-1.html 474417-1.html
== 475986-1-ref.html 475986-1-ref.html
== 475986-2-ref.html 475986-2-ref.html
== 476063-1.html 476063-1.html
fails == 476063-2.html 476063-2.html
fails == 476063-3.html 476063-3.html
== 476063-2.html 476063-2.html
== 476063-3.html 476063-3.html
== 476063-4.xhtml 476063-4.xhtml
== 476357-1.html 476357-1.html
fails == 476598-1a.html 476598-1a.html # Bug 1341785
@ -1388,7 +1388,7 @@ pref(dom.use_xbl_scopes_for_remote_xul,true) == 495385-2f.xhtml 495385-2f.xhtml
== 495385-4.html 495385-4.html
fails == 495385-5.html 495385-5.html
fails == 496032-1.html 496032-1.html
fails == 496840-1.html 496840-1.html
== 496840-1.html 496840-1.html
fuzzy-if(skiaContent,1,17000) == 498228-1.xul 498228-1.xul
fails == 501037.html 501037.html
== 501257-1a.html 501257-1a.html
@ -1434,7 +1434,7 @@ fails HTTP(..) == 518172-2a.html 518172-2a.html
fails == 518172-2b.html 518172-2b.html
== 520421-1.html 520421-1.html
== 520563-1.xhtml 520563-1.xhtml
fails == 521525-1.html 521525-1.html
== 521525-1.html 521525-1.html
== 521525-2.html 521525-2.html
fails == 521539-1.html 521539-1.html
== 521542-1.xhtml 521542-1.xhtml
@ -1596,7 +1596,7 @@ fails == 589615-1b.html 589615-1b.html
fails == 589682-1.html 589682-1.html
== 593243-1.html 593243-1.html
fails == 593243-2.html 593243-2.html
fails == 593544-1.html 593544-1.html
== 593544-1.html 593544-1.html
== 594333-1.html 594333-1.html
== 594624-1.html 594624-1.html
fails == 594737-1.html 594737-1.html
@ -1657,7 +1657,7 @@ fuzzy-if(skiaContent,1,500) == 630835-1.html 630835-1.html
skip-if(Android) random-if(winWidget||OSX==1010) == 632781-verybig.html 632781-verybig.html
== 632781-normalsize.html 632781-normalsize.html
== 633344-1.html 633344-1.html
fails == 634232-1.html 634232-1.html
== 634232-1.html 634232-1.html
skip-if(stylo) == 635302-1.html 635302-1.html # Too intermittent.
== 635373-1.html 635373-1.html
== 635373-2.html 635373-2.html
@ -1699,7 +1699,7 @@ fails == 670467-2.html 670467-2.html
== 691087-1.html 691087-1.html
== 691571-1.html 691571-1.html
== 696307-1.html 696307-1.html
fails == 696739-1.html 696739-1.html
== 696739-1.html 696739-1.html
needs-focus == 703186-1.html 703186-1.html
needs-focus == 703186-2.html 703186-2.html
needs-focus == 703186-1.html 703186-1.html
@ -1783,7 +1783,7 @@ fails == 883987-1c.html 883987-1c.html
fails == 883987-1d.html 883987-1d.html
fails == 883987-1e.html 883987-1e.html
== 883987-1f.html 883987-1f.html
fails == 890495-1.html 890495-1.html
== 890495-1.html 890495-1.html
== 894931-1.html 894931-1.html
fails == 897491-1.html 897491-1.html
fails == 897491-2.html 897491-2.html
@ -1792,7 +1792,7 @@ fails == 897491-2.html 897491-2.html
== 921716-1.html 921716-1.html
== 926155-1.html 926155-1.html
== 928607-1.html 928607-1.html
fails == 931464-1.html 931464-1.html
== 931464-1.html 931464-1.html
== 931853.html 931853.html
== 931853-quirks.html 931853-quirks.html
fails == 933264-1.html 933264-1.html

View File

@ -112,3 +112,6 @@ fails asserts-if(stylo,1) == 1107096-invisibles.html 1107096-invisibles.html # b
fails asserts-if(stylo,1) == 1304353-text-global-alpha-1.html 1304353-text-global-alpha-1.html # bug 1324700
fails asserts-if(stylo,1) == 1304353-text-global-alpha-2.html 1304353-text-global-alpha-2.html # bug 1324700
fails asserts-if(stylo,1) == 1304353-text-global-composite-op-1.html 1304353-text-global-composite-op-1.html # bug 1324700
skip-if(stylo) == text-indent-1a.html text-indent-1a.html # Bug 1347410
== text-indent-1b.html text-indent-1b.html

View File

@ -109,4 +109,7 @@ fuzzy-if(d2d,12,21) fuzzy-if(skiaContent,12,7) fuzzy-if(d2d&&/^Windows\x20NT\x20
fuzzy-if(winWidget,1,14) == 1304353-text-global-alpha-2.html 1304353-text-global-alpha-2-ref.html
fuzzy-if(winWidget,94,1575) fuzzy-if(cocoaWidget,1,24) == 1304353-text-global-composite-op-1.html 1304353-text-global-composite-op-1-ref.html
== text-indent-1a.html text-indent-1-ref.html
== text-indent-1b.html text-indent-1-ref.html
== 1347147-1.html 1347147-1-ref.html

View File

@ -0,0 +1,4 @@
<!DOCTYPE html>
<iframe sandbox
style="width: 400px"
srcdoc="<div style='text-indent: 50vw'>Text</div>"></iframe>

View File

@ -0,0 +1,4 @@
<!DOCTYPE html>
<iframe sandbox
style="width: 400px"
srcdoc="<canvas style='text-indent: 50vw; display: block'>Text</canvas>"></iframe>

View File

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html class="reftest-wait">
<iframe sandbox
style="width: 200px"
srcdoc="<canvas style='text-indent: 50vw; display: block'>Text</canvas>"></iframe>
<script>
onload = function() {
var i = document.querySelector("iframe");
window.w = i.offsetWidth;
i.style.width = "400px";
document.documentElement.className = "";
}
</script>
</html>

View File

@ -0,0 +1,4 @@
<!DOCTYPE html>
<div style="column-count: 2; width: 200px; text-indent: 50px">
This is some text that is too long and it will overflow.
</div>

View File

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html class="reftest-wait">
<div style="column-count: 2; width: 200px;">
This is some text that is too long and it will overflow.
</div>
<script>
onload = function() {
var d = document.querySelector("div");
window.w = d.offsetWidth;
d.style.textIndent = "50px";
document.documentElement.className = "";
}
</script>
</html>

View File

@ -0,0 +1,4 @@
<!DOCTYPE html>
<fieldset style="column-count: 2; width: 200px; border: none; text-indent: 50px">
This is some text that is too long and it will overflow.
</fieldset>

View File

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html class="reftest-wait">
<fieldset style="column-count: 2; width: 200px; border: none">
This is some text that is too long and it will overflow.
</fieldset>
<script>
onload = function() {
var f = document.querySelector("fieldset");
window.w = f.offsetWidth;
f.style.textIndent = "50px";
document.documentElement.className = "";
}
</script>
</html>

View File

@ -37,3 +37,5 @@ fails == column-balancing-nested-001.html column-balancing-nested-001.html
== positioning-transforms-bug1112501.html positioning-transforms-bug1112501.html
== fieldset-columns-001.html fieldset-columns-001.html
== dynamic-change-with-overflow-1.html dynamic-change-with-overflow-1.html
== dynamic-text-indent-1.html dynamic-text-indent-1.html
== dynamic-text-indent-2.html dynamic-text-indent-2.html

View File

@ -36,3 +36,5 @@ HTTP(..) == columnfill-auto-3.html columnfill-auto-2-ref.html
== positioning-transforms-bug1112501.html positioning-transforms-bug1112501-ref.html
fuzzy-if(browserIsRemote&&winWidget,140,276) == fieldset-columns-001.html fieldset-columns-001-ref.html
== dynamic-change-with-overflow-1.html dynamic-change-with-overflow-1-ref.html
== dynamic-text-indent-1.html dynamic-text-indent-1-ref.html
== dynamic-text-indent-2.html dynamic-text-indent-2-ref.html

Some files were not shown because too many files have changed in this diff Show More