Merge mozilla-central to autoland

This commit is contained in:
Carsten "Tomcat" Book 2016-08-03 17:08:48 +02:00
Родитель d3fb092dbf eeacfbeff0
Коммит 6b13b3cde6
732 изменённых файлов: 16001 добавлений и 7495 удалений

Просмотреть файл

@ -308,6 +308,12 @@ pref("browser.urlbar.suggest.history.onlyTyped", false);
pref("browser.urlbar.formatting.enabled", true);
pref("browser.urlbar.trimURLs", true);
#if defined(NIGHTLY_BUILD)
pref("browser.urlbar.oneOffSearches", true);
#else
pref("browser.urlbar.oneOffSearches", false);
#endif
pref("browser.altClickSave", false);
// Enable logging downloads operations to the Console.

Просмотреть файл

@ -152,14 +152,7 @@
noautofocus="true"
hidden="true"
flip="none"
level="parent">
#ifdef NIGHTLY_BUILD
<hbox id="urlbar-search-footer" flex="1" align="stretch" pack="end">
<button id="urlbar-search-settings" label="&changeSearchSettings.button;"
oncommand="BrowserUITelemetry.countSearchSettingsEvent('urlbar'); openPreferences('paneSearch')"/>
</hbox>
#endif
</panel>
level="parent"/>
<!-- for select dropdowns. The menupopup is what shows the list of options,
and the popuponly menulist makes things like the menuactive attributes

Просмотреть файл

@ -60,16 +60,19 @@ function openSelectPopup(selectPopup, withMouse, selector = "select")
return popupShownPromise;
}
function hideSelectPopup(selectPopup, withEscape)
function hideSelectPopup(selectPopup, mode = "enter")
{
let popupHiddenPromise = BrowserTestUtils.waitForEvent(selectPopup, "popuphidden");
if (withEscape) {
if (mode == "escape") {
EventUtils.synthesizeKey("KEY_Escape", { code: "Escape" });
}
else {
else if (mode == "enter") {
EventUtils.synthesizeKey("KEY_Enter", { code: "Enter" });
}
else if (mode == "click") {
EventUtils.synthesizeMouseAtCenter(selectPopup.lastChild, { });
}
return popupHiddenPromise;
}
@ -148,7 +151,7 @@ function doSelectTests(contentType, dtd)
// Opening and closing the popup without changing the value should not fire a change event.
yield openSelectPopup(selectPopup, true);
yield hideSelectPopup(selectPopup, true);
yield hideSelectPopup(selectPopup, "escape");
is((yield getInputEvents()), 1, "Open and close with no change - number of input events");
is((yield getChangeEvents()), 1, "Open and close with no change - number of change events");
EventUtils.synthesizeKey("VK_TAB", { });
@ -158,7 +161,7 @@ function doSelectTests(contentType, dtd)
yield openSelectPopup(selectPopup, true);
EventUtils.synthesizeKey("KEY_ArrowDown", { code: "ArrowDown" });
yield hideSelectPopup(selectPopup, true);
yield hideSelectPopup(selectPopup, "escape");
is((yield getInputEvents()), isWindows ? 2 : 1, "Open and close with change - number of input events");
is((yield getChangeEvents()), isWindows ? 2 : 1, "Open and close with change - number of change events");
EventUtils.synthesizeKey("VK_TAB", { });
@ -299,59 +302,86 @@ add_task(function* test_event_order() {
let menulist = document.getElementById("ContentSelectDropdown");
let selectPopup = menulist.menupopup;
yield openSelectPopup(selectPopup, true, "#one");
// According to https://html.spec.whatwg.org/#the-select-element,
// we want to fire input, change, and then click events on the
// <select> (in that order) when it has changed.
let expectedEnter = [
{
type: "input",
cancelable: false,
targetIsOption: false,
},
{
type: "change",
cancelable: false,
targetIsOption: false,
},
];
let eventsPromise = ContentTask.spawn(browser, null, function*() {
// According to https://html.spec.whatwg.org/#the-select-element,
// we want to fire input, change, and then click events on the
// <select> (in that order) when it has changed.
let expected = [
{
type: "input",
cancelable: false,
},
{
type: "change",
cancelable: false,
},
{
type: "mousedown",
cancelable: true,
},
{
type: "mouseup",
cancelable: true,
},
{
type: "click",
cancelable: true,
},
];
let expectedClick = [
{
type: "input",
cancelable: false,
targetIsOption: false,
},
{
type: "change",
cancelable: false,
targetIsOption: false,
},
{
type: "mousedown",
cancelable: true,
targetIsOption: true,
},
{
type: "mouseup",
cancelable: true,
targetIsOption: true,
},
{
type: "click",
cancelable: true,
targetIsOption: true,
},
];
return new Promise((resolve) => {
function onEvent(event) {
select.removeEventListener(event.type, onEvent);
let expectation = expected.shift();
Assert.equal(event.type, expectation.type,
"Expected the right event order");
Assert.ok(event.bubbles, "All of these events should bubble");
Assert.equal(event.cancelable, expectation.cancelable,
"Cancellation property should match");
if (!expected.length) {
resolve();
for (let mode of ["enter", "click"]) {
let expected = mode == "enter" ? expectedEnter : expectedClick;
yield openSelectPopup(selectPopup, true, mode == "enter" ? "#one" : "#two");
let eventsPromise = ContentTask.spawn(browser, { mode, expected }, function*(args) {
let expected = args.expected;
return new Promise((resolve) => {
function onEvent(event) {
select.removeEventListener(event.type, onEvent);
Assert.ok(expected.length, "Unexpected event " + event.type);
let expectation = expected.shift();
Assert.equal(event.type, expectation.type,
"Expected the right event order");
Assert.ok(event.bubbles, "All of these events should bubble");
Assert.equal(event.cancelable, expectation.cancelable,
"Cancellation property should match");
Assert.equal(event.target.localName,
expectation.targetIsOption ? "option" : "select",
"Target matches");
if (!expected.length) {
resolve();
}
}
}
let select = content.document.getElementById("one");
for (let expectation of expected) {
select.addEventListener(expectation.type, onEvent);
}
let select = content.document.getElementById(args.mode == "enter" ? "one" : "two");
for (let event of ["input", "change", "mousedown", "mouseup", "click"]) {
select.addEventListener(event, onEvent);
}
});
});
});
EventUtils.synthesizeKey("KEY_ArrowDown", { code: "ArrowDown" });
yield hideSelectPopup(selectPopup, false);
yield eventsPromise;
EventUtils.synthesizeKey("KEY_ArrowDown", { code: "ArrowDown" });
yield hideSelectPopup(selectPopup, mode);
yield eventsPromise;
}
});
});
@ -399,7 +429,7 @@ add_task(function* test_large_popup() {
"Popup scroll at correct position " + bpBottom);
}
yield hideSelectPopup(selectPopup, false);
yield hideSelectPopup(selectPopup);
position = positions.shift();
if (!position) {
@ -416,3 +446,32 @@ add_task(function* test_large_popup() {
yield BrowserTestUtils.removeTab(tab);
});
// This test checks that a mousemove event is fired correctly at the menu and
// not at the browser, ensuring that any mouse capture has been cleared.
add_task(function* test_mousemove_correcttarget() {
const pageUrl = "data:text/html," + escape(PAGECONTENT_SMALL);
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, pageUrl);
let selectPopup = document.getElementById("ContentSelectDropdown").menupopup;
let popupShownPromise = BrowserTestUtils.waitForEvent(selectPopup, "popupshown");
yield BrowserTestUtils.synthesizeMouseAtCenter("#one", { type: "mousedown" }, gBrowser.selectedBrowser);
yield popupShownPromise;
yield new Promise(resolve => {
window.addEventListener("mousemove", function checkForMouseMove(event) {
window.removeEventListener("mousemove", checkForMouseMove, true);
is(event.target.localName.indexOf("menu"), 0, "mouse over menu");
resolve();
}, true);
EventUtils.synthesizeMouseAtCenter(selectPopup.firstChild, { type: "mousemove" });
});
yield BrowserTestUtils.synthesizeMouseAtCenter("#one", { type: "mouseup" }, gBrowser.selectedBrowser);
yield hideSelectPopup(selectPopup);
yield BrowserTestUtils.removeTab(tab);
});

Просмотреть файл

@ -56,6 +56,7 @@ support-files =
skip-if = os == "linux" # Bug 1073339 - Investigate autocomplete test unreliability on Linux/e10s
[browser_urlbarHashChangeProxyState.js]
[browser_urlbarKeepStateAcrossTabSwitches.js]
[browser_urlbarOneOffs.js]
[browser_urlbarPrivateBrowsingWindowChange.js]
[browser_urlbarRevert.js]
[browser_urlbarSearchSingleWordNotification.js]

Просмотреть файл

@ -6,6 +6,21 @@ function repeat(limit, func) {
function is_selected(index) {
is(gURLBar.popup.richlistbox.selectedIndex, index, `Item ${index + 1} should be selected`);
// This is true because although both the listbox and the one-offs can have
// selections, the test doesn't check that.
is(gURLBar.popup.oneOffSearchButtons.selectedButton, null,
"A result is selected, so the one-offs should not have a selection");
}
function is_selected_one_off(index) {
is(gURLBar.popup.oneOffSearchButtons.selectedButtonIndex, index,
"Expected one-off button should be selected");
// This is true because although both the listbox and the one-offs can have
// selections, the test doesn't check that.
is(gURLBar.popup.richlistbox.selectedIndex, -1,
"A one-off is selected, so the listbox should not have a selection");
}
add_task(function*() {
@ -37,12 +52,27 @@ add_task(function*() {
EventUtils.synthesizeKey("VK_DOWN", {});
is_selected(1);
info("Key Down maxResults times should wrap around all the way around");
repeat(maxResults, () => EventUtils.synthesizeKey("VK_DOWN", {}));
info("Key Down maxResults-1 times should select the first one-off");
repeat(maxResults - 1, () => EventUtils.synthesizeKey("VK_DOWN", {}));
is_selected_one_off(0);
info("Key Down numButtons-1 should select the last one-off");
let numButtons =
gURLBar.popup.oneOffSearchButtons.getSelectableButtons(true).length;
repeat(numButtons - 1, () => EventUtils.synthesizeKey("VK_DOWN", {}));
is_selected_one_off(numButtons - 1);
info("Key Down twice more should select the second result");
repeat(2, () => EventUtils.synthesizeKey("VK_DOWN", {}));
is_selected(1);
info("Key Up maxResults times should wrap around the other way");
repeat(maxResults, () => EventUtils.synthesizeKey("VK_UP", {}));
info("Key Down maxResults + numButtons times should wrap around");
repeat(maxResults + numButtons,
() => EventUtils.synthesizeKey("VK_DOWN", {}));
is_selected(1);
info("Key Up maxResults + numButtons times should wrap around the other way");
repeat(maxResults + numButtons, () => EventUtils.synthesizeKey("VK_UP", {}));
is_selected(1);
info("Page Up will go up the list, but not wrap");

Просмотреть файл

@ -31,15 +31,18 @@ add_task(function*() {
EventUtils.synthesizeKey("VK_BACK_SPACE", {});
yield promiseSearchComplete();
let editedValue = gURLBar.value;
let editedValue = gURLBar.textValue;
is(list.selectedIndex, initialIndex, "The initial index is selected again.");
isnot(editedValue, nextValue, "The URL has changed.");
let docLoad = waitForDocLoadAndStopIt("http://" + editedValue);
info("Press return to load edited URL.");
EventUtils.synthesizeKey("VK_RETURN", {});
yield Promise.all([
promisePopupHidden(gURLBar.popup),
waitForDocLoadAndStopIt("http://" + editedValue)]);
docLoad,
]);
gBrowser.removeTab(gBrowser.selectedTab);
});

Просмотреть файл

@ -43,7 +43,7 @@ add_task(function*() {
EventUtils.synthesizeKey("b", {});
yield promiseSearchComplete();
is(gURLBar.value, "keyword ab", "urlbar should have expected input");
is(gURLBar.textValue, "keyword ab", "urlbar should have expected input");
let result = gURLBar.popup.richlistbox.firstChild;
isnot(result, null, "Should have first item");

Просмотреть файл

@ -44,8 +44,8 @@ function continue_test() {
EventUtils.synthesizeKey(aTyped.substr(-1), {});
waitForSearchComplete(function () {
info(`Got value: ${gURLBar.value}`);
is(gURLBar.value, aExpected, "Autofilled value is as expected");
info(`Got value: ${gURLBar.textValue}`);
is(gURLBar.textValue, aExpected, "Autofilled value is as expected");
aCallback();
});
}

Просмотреть файл

@ -0,0 +1,233 @@
const TEST_ENGINE_BASENAME = "searchSuggestionEngine.xml";
let gMaxResults;
add_task(function* init() {
Services.prefs.setBoolPref("browser.urlbar.oneOffSearches", true);
gMaxResults = Services.prefs.getIntPref("browser.urlbar.maxRichResults");
// Add a search suggestion engine and move it to the front so that it appears
// as the first one-off.
let engine = yield promiseNewSearchEngine(TEST_ENGINE_BASENAME);
Services.search.moveEngine(engine, 0);
registerCleanupFunction(function* () {
yield hidePopup();
yield PlacesTestUtils.clearHistory();
});
yield PlacesTestUtils.clearHistory();
let visits = [];
for (let i = 0; i < gMaxResults; i++) {
visits.push({
uri: makeURI("http://example.com/browser_urlbarOneOffs.js/?" + i),
// TYPED so that the visit shows up when the urlbar's drop-down arrow is
// pressed.
transition: Ci.nsINavHistoryService.TRANSITION_TYPED,
});
}
yield PlacesTestUtils.addVisits(visits);
});
// Keys up and down through the history panel, i.e., the panel that's shown when
// there's no text in the textbox.
add_task(function* history() {
gURLBar.focus();
EventUtils.synthesizeKey("VK_DOWN", {})
yield promisePopupShown(gURLBar.popup);
assertState(-1, -1, "");
// Key down through each result.
for (let i = 0; i < gMaxResults; i++) {
EventUtils.synthesizeKey("VK_DOWN", {})
assertState(i, -1,
"example.com/browser_urlbarOneOffs.js/?" + (gMaxResults - i - 1));
}
// Key down through each one-off.
let numButtons =
gURLBar.popup.oneOffSearchButtons.getSelectableButtons(true).length;
for (let i = 0; i < numButtons; i++) {
EventUtils.synthesizeKey("VK_DOWN", {})
assertState(-1, i, "");
}
// Key down once more. Nothing should be selected.
EventUtils.synthesizeKey("VK_DOWN", {})
assertState(-1, -1, "");
// Once more. The first result should be selected.
EventUtils.synthesizeKey("VK_DOWN", {})
assertState(0, -1,
"example.com/browser_urlbarOneOffs.js/?" + (gMaxResults - 1));
// Now key up. Nothing should be selected again.
EventUtils.synthesizeKey("VK_UP", {})
assertState(-1, -1, "");
// Key up through each one-off.
for (let i = numButtons - 1; i >= 0; i--) {
EventUtils.synthesizeKey("VK_UP", {})
assertState(-1, i, "");
}
// Key up through each result.
for (let i = gMaxResults - 1; i >= 0; i--) {
EventUtils.synthesizeKey("VK_UP", {})
assertState(i, -1,
"example.com/browser_urlbarOneOffs.js/?" + (gMaxResults - i - 1));
}
// Key up once more. Nothing should be selected.
EventUtils.synthesizeKey("VK_UP", {})
assertState(-1, -1, "");
yield hidePopup();
});
// Keys up and down through the non-history panel, i.e., the panel that's shown
// when you type something in the textbox.
add_task(function* typedValue() {
// Use a typed value that returns the visits added above but that doesn't
// trigger autofill since that would complicate the test.
let typedValue = "browser_urlbarOneOffs";
yield promiseAutocompleteResultPopup(typedValue, window, true);
assertState(0, -1, typedValue);
// Key down through each result. The first result is already selected, which
// is why gMaxResults - 1 is the correct number of times to do this.
for (let i = 0; i < gMaxResults - 1; i++) {
EventUtils.synthesizeKey("VK_DOWN", {})
// i starts at zero so that the textValue passed to assertState is correct.
// But that means that i + 1 is the expected selected index, since initially
// (when this loop starts) the first result is selected.
assertState(i + 1, -1,
"example.com/browser_urlbarOneOffs.js/?" + (gMaxResults - i - 1));
}
// Key down through each one-off.
let numButtons =
gURLBar.popup.oneOffSearchButtons.getSelectableButtons(true).length;
for (let i = 0; i < numButtons; i++) {
EventUtils.synthesizeKey("VK_DOWN", {})
assertState(-1, i, typedValue);
}
// Key down once more. The selection should wrap around to the first result.
EventUtils.synthesizeKey("VK_DOWN", {})
assertState(0, -1, typedValue);
// Now key up. The selection should wrap back around to the one-offs. Key
// up through all the one-offs.
for (let i = numButtons - 1; i >= 0; i--) {
EventUtils.synthesizeKey("VK_UP", {})
assertState(-1, i, typedValue);
}
// Key up through each non-heuristic result.
for (let i = gMaxResults - 2; i >= 0; i--) {
EventUtils.synthesizeKey("VK_UP", {})
assertState(i + 1, -1,
"example.com/browser_urlbarOneOffs.js/?" + (gMaxResults - i - 1));
}
// Key up once more. The heuristic result should be selected.
EventUtils.synthesizeKey("VK_UP", {})
assertState(0, -1, typedValue);
yield hidePopup();
});
// Checks that "Search with Current Search Engine" items are updated to "Search
// with One-Off Engine" when a one-off is selected.
add_task(function* searchWith() {
let typedValue = "foo";
yield promiseAutocompleteResultPopup(typedValue);
assertState(0, -1, typedValue);
let item = gURLBar.popup.richlistbox.firstChild;
Assert.equal(item._actionText.textContent,
"Search with " + Services.search.currentEngine.name,
"Sanity check: first result's action text");
// Tab to the first one-off. Now the first result and the first one-off
// should both be selected.
EventUtils.synthesizeKey("VK_TAB", {})
assertState(0, 0, typedValue);
let engineName = gURLBar.popup.oneOffSearchButtons.selectedButton.engine.name;
Assert.notEqual(engineName, Services.search.currentEngine.name,
"Sanity check: First one-off engine should not be " +
"the current engine");
Assert.equal(item._actionText.textContent,
"Search with " + engineName,
"First result's action text should be updated");
yield hidePopup();
});
// Clicks a one-off.
add_task(function* oneOffClick() {
gBrowser.selectedTab = gBrowser.addTab();
let typedValue = "foo";
yield promiseAutocompleteResultPopup(typedValue);
assertState(0, -1, typedValue);
let oneOffs = gURLBar.popup.oneOffSearchButtons.getSelectableButtons(true);
let resultsPromise = promiseSearchResultsLoaded();
EventUtils.synthesizeMouseAtCenter(oneOffs[0], {});
yield resultsPromise;
gBrowser.removeTab(gBrowser.selectedTab);
});
// Presses the Return key when a one-off is selected.
add_task(function* oneOffReturn() {
gBrowser.selectedTab = gBrowser.addTab();
let typedValue = "foo";
yield promiseAutocompleteResultPopup(typedValue, window, true);
assertState(0, -1, typedValue);
// Tab to select the first one-off.
EventUtils.synthesizeKey("VK_TAB", {})
assertState(0, 0, typedValue);
let resultsPromise = promiseSearchResultsLoaded();
EventUtils.synthesizeKey("VK_RETURN", {})
yield resultsPromise;
gBrowser.removeTab(gBrowser.selectedTab);
});
function assertState(result, oneOff, textValue = undefined) {
Assert.equal(gURLBar.popup.selectedIndex, result,
"Expected result should be selected");
Assert.equal(gURLBar.popup.oneOffSearchButtons.selectedButtonIndex, oneOff,
"Expected one-off should be selected");
if (textValue !== undefined) {
Assert.equal(gURLBar.textValue, textValue, "Expected textValue");
}
}
function* hidePopup() {
EventUtils.synthesizeKey("VK_ESCAPE", {});
yield promisePopupHidden(gURLBar.popup);
}
function promiseSearchResultsLoaded() {
let tab = gBrowser.selectedTab;
return promiseTabLoadEvent(tab).then(() => {
Assert.equal(tab.linkedBrowser.currentURI.spec,
"http://mochi.test:8888/",
'Expected "search results" page loaded');
});
}

Просмотреть файл

@ -25,7 +25,10 @@ add_task(function* clickSuggestion() {
gBrowser.selectedTab = gBrowser.addTab();
gURLBar.focus();
yield promiseAutocompleteResultPopup("foo");
let [idx, suggestion] = yield promiseFirstSuggestion();
let [idx, suggestion, engineName] = yield promiseFirstSuggestion();
Assert.equal(engineName,
"browser_searchSuggestionEngine%20searchSuggestionEngine.xml",
"Expected suggestion engine");
let item = gURLBar.popup.richlistbox.getItemAtIndex(idx);
let loadPromise = promiseTabLoaded(gBrowser.selectedTab);
item.click();
@ -47,7 +50,7 @@ function getFirstSuggestion() {
let [, type, paramStr] = mozActionMatch;
let params = JSON.parse(paramStr);
if (type == "searchengine" && "searchSuggestion" in params) {
return [i, params.searchSuggestion];
return [i, params.searchSuggestion, params.engineName];
}
}
}
@ -56,10 +59,10 @@ function getFirstSuggestion() {
function promiseFirstSuggestion() {
return new Promise(resolve => {
let pair;
let tuple;
waitForCondition(() => {
pair = getFirstSuggestion();
return pair[0] >= 0;
}, () => resolve(pair));
tuple = getFirstSuggestion();
return tuple[0] >= 0;
}, () => resolve(tuple));
});
}

Просмотреть файл

@ -23,6 +23,12 @@ add_task(function* prepare() {
gURLBar.blur();
Assert.ok(!gURLBar.popup.popupOpen, "popup should be closed");
});
// Move the mouse away from the urlbar one-offs so that a one-off engine is
// not inadvertently selected.
yield new Promise(resolve => {
EventUtils.synthesizeNativeMouseMove(window.document.documentElement, 0, 0,
resolve);
});
});
add_task(function* heuristicResult() {

Просмотреть файл

@ -20,12 +20,11 @@ add_task(function* () {
gBrowser.removeCurrentTab();
});
function typeAndSubmitAndStop(url) {
gBrowser.userTypedValue = url;
URLBarSetURI();
function* typeAndSubmitAndStop(url) {
yield promiseAutocompleteResultPopup(url, window, true);
is(gURLBar.textValue, gURLBar.trimValue(url), "location bar reflects loading page");
let promise = waitForDocLoadAndStopIt(url, gBrowser.selectedBrowser, false);
gURLBar.handleCommand();
return promise;
yield promise;
}

Просмотреть файл

@ -7,13 +7,13 @@ function* test_autocomplete(data) {
info(desc);
yield promiseAutocompleteResultPopup(typed);
is(gURLBar.value, autofilled, "autofilled value is as expected");
is(gURLBar.textValue, autofilled, "autofilled value is as expected");
if (onAutoFill)
onAutoFill()
keys.forEach(key => EventUtils.synthesizeKey(key, {}));
is(gURLBar.value, modified, "backspaced value is as expected");
is(gURLBar.textValue, modified, "backspaced value is as expected");
yield promiseSearchComplete();

Просмотреть файл

@ -327,10 +327,18 @@ function promiseSearchComplete(win = window) {
});
}
function promiseAutocompleteResultPopup(inputText, win = window) {
function promiseAutocompleteResultPopup(inputText,
win = window,
fireInputEvent = false) {
waitForFocus(() => {
win.gURLBar.focus();
win.gURLBar.value = inputText;
if (fireInputEvent) {
// This is necessary to get the urlbar to set gBrowser.userTypedValue.
let event = document.createEvent("Events");
event.initEvent("input", true, true);
win.gURLBar.dispatchEvent(event);
}
win.gURLBar.controller.startSearch(inputText);
}, win);

Просмотреть файл

@ -108,6 +108,8 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
"gURLBar.select(); goDoCommand('cmd_paste'); gURLBar.handleCommand();");
cxmenu.insertBefore(pasteAndGo, insertLocation.nextSibling);
}
this._enableOrDisableOneOffSearches();
]]></constructor>
<destructor><![CDATA[
@ -197,7 +199,11 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
this.popup.selectedIndex = -1;
break;
}
if (this.popup.popupOpen &&
!this.popup.disableKeyNavigation &&
this.popup.handleKeyPress(aEvent)) {
return true;
}
return this.handleKeyPress(aEvent);
]]></body>
</method>
@ -331,135 +337,224 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
]]></body>
</method>
<!--
This is ultimately called by the autocomplete controller as the result
of handleEnter when the Return key is pressed in the textbox. Since
onPopupClick also calls handleEnter, this is also called as a result in
that case.
@param event
The event that triggered the command.
@param openUILinkWhere
Optional. The "where" to pass to openUILinkIn. This method
computes the appropriate "where" given the event, but you can
use this to override it.
@param openUILinkParams
Optional. The parameters to pass to openUILinkIn. As with
"where", this method computes the appropriate parameters, but
any parameters you supply here will override those.
-->
<method name="handleCommand">
<parameter name="aTriggeringEvent"/>
<parameter name="event"/>
<parameter name="openUILinkWhere"/>
<parameter name="openUILinkParams"/>
<body><![CDATA[
if (aTriggeringEvent instanceof MouseEvent && aTriggeringEvent.button == 2)
return; // Do nothing for right clicks
var url = this.value;
var mayInheritPrincipal = false;
var postData = null;
let action = this._parseActionUrl(this._value);
let lastLocationChange = gBrowser.selectedBrowser.lastLocationChange;
let matchLastLocationChange = true;
if (action) {
if (action.type == "switchtab") {
url = action.params.url;
if (this.hasAttribute("actiontype")) {
this.handleRevert();
let prevTab = gBrowser.selectedTab;
if (switchToTabHavingURI(url) && isTabEmpty(prevTab)) {
gBrowser.removeTab(prevTab);
}
return;
}
} else if (action.type == "remotetab") {
url = action.params.url;
} else if (action.type == "keyword") {
url = action.params.url;
} else if (action.type == "searchengine") {
[url, postData] = this._parseAndRecordSearchEngineAction(action);
} else if (action.type == "visiturl") {
url = action.params.url;
}
continueOperation.call(this);
}
else {
this._canonizeURL(aTriggeringEvent, response => {
[url, postData, mayInheritPrincipal] = response;
if (url) {
matchLastLocationChange = (lastLocationChange ==
gBrowser.selectedBrowser.lastLocationChange);
continueOperation.call(this);
}
});
let isMouseEvent = event instanceof MouseEvent;
if (isMouseEvent && event.button == 2) {
// Do nothing for right clicks.
return;
}
function continueOperation()
{
this.value = url;
gBrowser.userTypedValue = url;
if (gInitialPages.includes(url)) {
gBrowser.selectedBrowser.initialPageLoadedFromURLBar = url;
}
try {
addToUrlbarHistory(url);
} catch (ex) {
// Things may go wrong when adding url to session history,
// but don't let that interfere with the loading of the url.
Cu.reportError(ex);
}
// Do the command of the selected one-off if it's not an engine.
let selectedOneOff =
this.popup.oneOffSearchButtons.visuallySelectedButton;
if (selectedOneOff && !selectedOneOff.engine) {
selectedOneOff.doCommand();
return;
}
let loadCurrent = () => {
try {
openUILinkIn(url, "current", {
allowThirdPartyFixup: true,
indicateErrorPageLoad: true,
disallowInheritPrincipal: !mayInheritPrincipal,
allowPinnedTabHostChange: true,
postData: postData,
allowPopups: url.startsWith("javascript:"),
});
} catch (ex) {
// This load can throw an exception in certain cases, which means
// we'll want to replace the URL with the loaded URL:
if (ex.result != Cr.NS_ERROR_LOAD_SHOWED_ERRORPAGE) {
this.handleRevert();
}
}
// Ensure the start of the URL is visible for UX reasons:
this.selectionStart = this.selectionEnd = 0;
};
// Focus the content area before triggering loads, since if the load
// occurs in a new tab, we want focus to be restored to the content
// area when the current tab is re-selected.
gBrowser.selectedBrowser.focus();
let isMouseEvent = aTriggeringEvent instanceof MouseEvent;
// If the current tab is empty, ignore Alt+Enter (just reuse this tab)
let altEnter = !isMouseEvent && aTriggeringEvent &&
aTriggeringEvent.altKey && !isTabEmpty(gBrowser.selectedTab);
if (isMouseEvent || altEnter) {
// Use the standard UI link behaviors for clicks or Alt+Enter
let where = "tab";
if (isMouseEvent)
where = whereToOpenLink(aTriggeringEvent, false, false);
if (where == "current") {
if (matchLastLocationChange) {
loadCurrent();
}
} else {
this.handleRevert();
let params = { allowThirdPartyFixup: true,
postData: postData,
initiatingDoc: document };
openUILinkIn(url, where, params);
}
let where = openUILinkWhere;
if (!where) {
if (isMouseEvent) {
where = whereToOpenLink(event, false, false);
} else {
if (matchLastLocationChange) {
loadCurrent();
}
// If the current tab is empty, ignore Alt+Enter (reuse this tab)
let altEnter = !isMouseEvent &&
event &&
event.altKey &&
!isTabEmpty(gBrowser.selectedTab);
where = altEnter ? "tab" : "current";
}
}
let url = this.value;
let mayInheritPrincipal = false;
let postData = null;
let lastLocationChange = gBrowser.selectedBrowser.lastLocationChange;
let matchLastLocationChange = true;
let action = this._parseActionUrl(url);
if (action) {
switch (action.type) {
case "visiturl":
case "keyword":
case "remotetab":
url = action.params.url;
break;
case "switchtab":
url = action.params.url;
if (this.hasAttribute("actiontype")) {
this.handleRevert();
let prevTab = gBrowser.selectedTab;
if (switchToTabHavingURI(url) && isTabEmpty(prevTab)) {
gBrowser.removeTab(prevTab);
}
return;
}
break;
case "searchengine":
if (selectedOneOff && selectedOneOff.engine) {
// Replace the engine with the selected one-off engine.
action.params.engineName = engine.name;
}
[url, postData] = this._recordSearchEngineLoad(
action.params.engineName,
action.params.searchSuggestion || action.params.searchQuery,
event,
where,
openUILinkParams
);
break;
}
this._loadURL(url, postData, where, openUILinkParams,
matchLastLocationChange, mayInheritPrincipal);
return;
}
// If there's a selected one-off button and the input value is a
// search query (or "keyword" in URI-fixup terminology), then load a
// search using the one-off's engine.
if (selectedOneOff && selectedOneOff.engine) {
// `url` (which is this.value) may be an autofilled string. Search
// only with the portion that the user typed, if any, by preferring
// the autocomplete controller's searchString.
let value = this._searchStringOnHandleEnter ||
this.mController.searchString ||
url;
let fixup;
try {
fixup = Services.uriFixup.getFixupURIInfo(
value,
Services.uriFixup.FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP
);
} catch (ex) {}
if (fixup && fixup.keywordProviderName) {
[url, postData] =
this._recordSearchEngineLoad(selectedOneOff.engine, value,
event, where, openUILinkParams);
this._loadURL(url, postData, where, openUILinkParams,
matchLastLocationChange, mayInheritPrincipal);
return;
}
}
this._canonizeURL(event, response => {
[url, postData, mayInheritPrincipal] = response;
if (url) {
matchLastLocationChange =
lastLocationChange ==
gBrowser.selectedBrowser.lastLocationChange;
this._loadURL(url, postData, where, openUILinkParams,
matchLastLocationChange, mayInheritPrincipal);
}
});
]]></body>
</method>
<method name="_loadURL">
<parameter name="url"/>
<parameter name="postData"/>
<parameter name="openUILinkWhere"/>
<parameter name="openUILinkParams"/>
<parameter name="matchLastLocationChange"/>
<parameter name="mayInheritPrincipal"/>
<body><![CDATA[
this.value = url;
gBrowser.userTypedValue = url;
if (gInitialPages.includes(url)) {
gBrowser.selectedBrowser.initialPageLoadedFromURLBar = url;
}
try {
addToUrlbarHistory(url);
} catch (ex) {
// Things may go wrong when adding url to session history,
// but don't let that interfere with the loading of the url.
Cu.reportError(ex);
}
let params = {
postData: postData,
allowThirdPartyFixup: true,
};
if (openUILinkWhere == "current") {
params.indicateErrorPageLoad = true;
params.allowPinnedTabHostChange = true;
params.disallowInheritPrincipal = !mayInheritPrincipal;
params.allowPopups = url.startsWith("javascript:");
} else {
params.initiatingDoc = document;
}
if (openUILinkParams) {
for (let key in openUILinkParams) {
params[key] = openUILinkParams[key];
}
}
// Focus the content area before triggering loads, since if the load
// occurs in a new tab, we want focus to be restored to the content
// area when the current tab is re-selected.
gBrowser.selectedBrowser.focus();
if (openUILinkWhere == "current" && !matchLastLocationChange) {
return;
}
if (openUILinkWhere != "current") {
this.handleRevert();
}
try {
openUILinkIn(url, openUILinkWhere, params);
} catch (ex) {
// This load can throw an exception in certain cases, which means
// we'll want to replace the URL with the loaded URL:
if (ex.result != Cr.NS_ERROR_LOAD_SHOWED_ERRORPAGE) {
this.handleRevert();
}
}
if (openUILinkWhere == "current") {
// Ensure the start of the URL is visible for usability reasons.
this.selectionStart = this.selectionEnd = 0;
}
]]></body>
</method>
<method name="_parseAndRecordSearchEngineAction">
<parameter name="action"/>
<method name="_recordSearchEngineLoad">
<parameter name="engineOrEngineName"/>
<parameter name="query"/>
<parameter name="event"/>
<parameter name="openUILinkWhere"/>
<parameter name="openUILinkParams"/>
<body><![CDATA[
let engine =
Services.search.getEngineByName(action.params.engineName);
typeof(engineOrEngineName) == "string" ?
Services.search.getEngineByName(engineOrEngineName) :
engineOrEngineName;
BrowserSearch.recordSearchInTelemetry(engine, "urlbar");
let query = action.params.searchSuggestion ||
action.params.searchQuery;
this.popup.oneOffSearchButtons
.maybeRecordTelemetry(event, openUILinkWhere, openUILinkParams);
let submission = engine.getSubmission(query, null, "keyword");
return [submission.uri.spec, submission.postData];
]]></body>
@ -728,11 +823,21 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
case "trimURLs":
this._mayTrimURLs = this._prefs.getBoolPref(aData);
break;
case "oneOffSearches":
this._enableOrDisableOneOffSearches();
break;
}
}
]]></body>
</method>
<method name="_enableOrDisableOneOffSearches">
<body><![CDATA[
let enable = this._prefs.getBoolPref("oneOffSearches");
this.popup.enableOneOffSearches(enable);
]]></body>
</method>
<method name="handleEvent">
<parameter name="aEvent"/>
<body><![CDATA[
@ -903,6 +1008,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
</method>
<method name="handleEnter">
<parameter name="event"/>
<body><![CDATA[
// We need to ensure we're using a selected autocomplete result.
// A result should automatically be selected by default,
@ -919,7 +1025,13 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
// ensure that it corresponds to the current input.
if (this.popup.selectedIndex != 0 || this.gotResultForCurrentQuery) {
return this.mController.handleEnter(false);
// Store the current search string so it can be used in
// handleCommand, which will be called as a result of
// mController.handleEnter(). handleEnter will reset it.
this._searchStringOnHandleEnter = this.mController.searchString;
let rv = this.mController.handleEnter(false, event);
delete this._searchStringOnHandleEnter;
return rv;
}
this.handleEnterWhenGotResult = true;
@ -1100,7 +1212,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
// Check for unmodified left-click, and use default behavior
if (aEvent.button == 0 && !aEvent.shiftKey && !aEvent.ctrlKey &&
!aEvent.altKey && !aEvent.metaKey) {
controller.handleEnter(true);
controller.handleEnter(true, aEvent);
return;
}
@ -1137,6 +1249,11 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
<binding id="urlbar-rich-result-popup" extends="chrome://global/content/bindings/autocomplete.xml#autocomplete-rich-result-popup">
<resources>
<stylesheet src="chrome://browser/content/search/searchbarBindings.css"/>
<stylesheet src="chrome://browser/skin/searchbar.css"/>
</resources>
<content ignorekeys="true" level="top" consumeoutsideclicks="never"
aria-owns="richlistbox">
<xul:hbox anonid="search-suggestions-notification"
@ -1171,6 +1288,10 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
flex="1"/>
<xul:hbox anonid="footer">
<children/>
<xul:vbox anonid="one-off-search-buttons"
class="search-one-offs"
compact="true"
flex="1"/>
</xul:hbox>
</content>
@ -1193,6 +1314,31 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
document.getAnonymousElementByAttribute(this, "anonid", "footer");
</field>
<field name="oneOffSearchButtons" readonly="true">
document.getAnonymousElementByAttribute(this, "anonid",
"one-off-search-buttons");
</field>
<field name="_oneOffSearchesEnabled">false</field>
<method name="enableOneOffSearches">
<parameter name="enable"/>
<body><![CDATA[
this._oneOffSearchesEnabled = enable;
if (enable) {
this.oneOffSearchButtons.style.display = "-moz-box";
this.oneOffSearchButtons.popup = this;
this.oneOffSearchButtons.textbox = this.input;
this.oneOffSearchButtons.telemetryOrigin = "urlbar";
} else {
this.oneOffSearchButtons.style.display = "none";
this.oneOffSearchButtons.popup = null;
this.oneOffSearchButtons.textbox = null;
this.oneOffSearchButtons.telemetryOrigin = null;
}
]]></body>
</method>
<method name="openSearchSuggestionsNotificationLearnMoreURL">
<body><![CDATA[
let url = Services.urlFormatter.formatURL(
@ -1491,62 +1637,68 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
</body>
</method>
<method name="onPopupClick">
<parameter name="aEvent"/>
<body>
<![CDATA[
// Ignore right-clicks
if (aEvent.button == 2)
return;
var controller = this.view.QueryInterface(Components.interfaces.nsIAutoCompleteController);
// Check for unmodified left-click, and use default behavior
if (aEvent.button == 0 && !aEvent.shiftKey && !aEvent.ctrlKey &&
!aEvent.altKey && !aEvent.metaKey) {
controller.handleEnter(true);
return;
}
// Check for middle-click or modified clicks on the URL bar
if (gURLBar && this.mInput == gURLBar) {
var url = controller.getValueAt(this.selectedIndex);
var options = {};
// close the autocomplete popup and revert the entered address
this.closePopup();
controller.handleEscape();
// Check if this is meant to be an action
let action = this.mInput._parseActionUrl(url);
if (action) {
// TODO (bug 1054816): Centralise the implementation of actions
// into a JS module.
switch (action.type) {
case "switchtab": // Fall through.
case "keyword": // Fall through.
case "visiturl": {
url = action.params.url;
break;
}
case "searchengine": {
[url, options.postData] =
this.input._parseAndRecordSearchEngineAction(action);
break;
}
default: {
return;
}
<method name="_visuallySelectedOneOffChanged">
<body><![CDATA[
// Update all searchengine result items to use the newly selected
// engine.
for (let item of this.richlistbox.childNodes) {
if (item.collapsed) {
break;
}
let url = item.getAttribute("url");
if (url) {
let action = item._parseActionUrl(url);
if (action && action.type == "searchengine") {
item._adjustAcItem();
}
}
// respect the usual clicking subtleties
openUILink(url, aEvent, options);
}
]]>
</body>
]]></body>
</method>
<!-- This handles keypress changes to the selection among the one-off
search buttons and between the one-offs and the listbox. It returns
true if the keypress was consumed and false if not. -->
<method name="handleKeyPress">
<parameter name="aEvent"/>
<body><![CDATA[
this.oneOffSearchButtons.handleKeyPress(aEvent, this._matchCount,
!this._isFirstResultHeuristic,
gBrowser.userTypedValue);
return aEvent.defaultPrevented;
]]></body>
</method>
<!-- This is called when a one-off is clicked and when "search in new tab"
is selected from a one-off context menu. -->
<method name="handleOneOffSearch">
<parameter name="event"/>
<parameter name="engine"/>
<parameter name="where"/>
<parameter name="params"/>
<body><![CDATA[
this.input.handleCommand(event, where, params);
]]></body>
</method>
<!-- Result listitems call this to determine which search engine they
should show in their labels and include in their url attributes. -->
<property name="overrideSearchEngineName" readonly="true">
<getter><![CDATA[
// When building the popup, autocomplete reuses an item at index i if
// that item's url attribute matches the controller's value at index
// i, but only if overrideSearchEngineName matches the engine in the
// url attribute. To absolutely avoid reusing items that shouldn't be
// reused, always return a non-null name here by falling back to the
// current engine.
let engine =
(this.oneOffSearchButtons.visuallySelectedButton &&
this.oneOffSearchButtons.visuallySelectedButton.engine) ||
Services.search.currentEngine;
return engine ? engine.name : null;
]]></getter>
</property>
<method name="createResultLabel">
<parameter name="item"/>
<parameter name="proposedLabel"/>
@ -1616,6 +1768,10 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
</implementation>
<handlers>
<handler event="OneOffsVisuallySelectedButtonChanged"><![CDATA[
this._visuallySelectedOneOffChanged();
]]></handler>
<handler event="mousedown"><![CDATA[
// Required to make the xul:label.text-link elements in the search
// suggestions notification work correctly when clicked on Linux.

Просмотреть файл

@ -447,13 +447,15 @@ MenuItem.prototype = {
let targetPattern = this.targetUrlMatchPattern;
if (targetPattern) {
let isMedia = contextData.onImage || contextData.onAudio || contextData.onVideo;
if (!isMedia) {
return false;
let targetUrls = [];
if (contextData.onImage || contextData.onAudio || contextData.onVideo) {
// TODO: double check if srcUrl is always set when we need it
targetUrls.push(contextData.srcUrl);
}
let srcURI = Services.io.newURI(contextData.srcUrl, null, null);
if (!targetPattern.matches(srcURI)) {
// TODO: double check if mediaURL is always set when we need it
if (contextData.onLink) {
targetUrls.push(contextData.linkUrl);
}
if (!targetUrls.some(targetUrl => targetPattern.matches(NetUtil.newURI(targetUrl)))) {
return false;
}
}

Просмотреть файл

@ -15,7 +15,7 @@ add_task(function* () {
// Test menu items using targetUrlPatterns.
browser.contextMenus.create({
title: "targetUrlPatterns-patternMatches-contextAll",
targetUrlPatterns: ["*://*/*ctxmenu-image.png"],
targetUrlPatterns: ["*://*/*ctxmenu-image.png", "*://*/*some-link"],
contexts: ["all"],
});
@ -25,6 +25,12 @@ add_task(function* () {
contexts: ["image"],
});
browser.contextMenus.create({
title: "targetUrlPatterns-patternMatches-contextLink",
targetUrlPatterns: ["*://*/*some-link"],
contexts: ["link"],
});
browser.contextMenus.create({
title: "targetUrlPatterns-patternDoesNotMatch-contextAll",
targetUrlPatterns: ["*://*/does-not-match"],
@ -37,6 +43,12 @@ add_task(function* () {
contexts: ["image"],
});
browser.contextMenus.create({
title: "targetUrlPatterns-patternDoesNotMatch-contextLink",
targetUrlPatterns: ["*://*/does-not-match"],
contexts: ["link"],
});
// Test menu items using documentUrlPatterns.
browser.contextMenus.create({
title: "documentUrlPatterns-patternMatches-contextAll",
@ -50,6 +62,12 @@ add_task(function* () {
contexts: ["image"],
});
browser.contextMenus.create({
title: "documentUrlPatterns-patternMatches-contextLink",
documentUrlPatterns: ["*://*/*context.html", "*://*/does-not-match"],
contexts: ["link"],
});
browser.contextMenus.create({
title: "documentUrlPatterns-patternDoesNotMatch-contextAll",
documentUrlPatterns: ["*://*/does-not-match"],
@ -62,6 +80,12 @@ add_task(function* () {
contexts: ["image"],
});
browser.contextMenus.create({
title: "documentUrlPatterns-patternDoesNotMatch-contextLink",
documentUrlPatterns: ["*://*/does-not-match"],
contexts: ["link"],
});
// Test menu items using both targetUrlPatterns and documentUrlPatterns.
browser.contextMenus.create({
title: "documentUrlPatterns-patternMatches-targetUrlPatterns-patternMatches-contextAll",
@ -141,12 +165,16 @@ add_task(function* () {
let expected = [
["targetUrlPatterns-patternMatches-contextAll", true],
["targetUrlPatterns-patternMatches-contextImage", true],
["targetUrlPatterns-patternMatches-contextLink", false],
["targetUrlPatterns-patternDoesNotMatch-contextAll", false],
["targetUrlPatterns-patternDoesNotMatch-contextImage", false],
["targetUrlPatterns-patternDoesNotMatch-contextLink", false],
["documentUrlPatterns-patternMatches-contextAll", true],
["documentUrlPatterns-patternMatches-contextImage", true],
["documentUrlPatterns-patternMatches-contextLink", false],
["documentUrlPatterns-patternDoesNotMatch-contextAll", false],
["documentUrlPatterns-patternDoesNotMatch-contextImage", false],
["documentUrlPatterns-patternDoesNotMatch-contextLink", false],
["documentUrlPatterns-patternMatches-targetUrlPatterns-patternMatches-contextAll", true],
["documentUrlPatterns-patternDoesNotMatch-targetUrlPatterns-patternMatches-contextAll", false],
["documentUrlPatterns-patternMatches-targetUrlPatterns-patternDoesNotMatch-contextAll", false],
@ -163,12 +191,16 @@ add_task(function* () {
expected = [
["targetUrlPatterns-patternMatches-contextAll", false],
["targetUrlPatterns-patternMatches-contextImage", false],
["targetUrlPatterns-patternMatches-contextLink", false],
["targetUrlPatterns-patternDoesNotMatch-contextAll", false],
["targetUrlPatterns-patternDoesNotMatch-contextImage", false],
["targetUrlPatterns-patternDoesNotMatch-contextLink", false],
["documentUrlPatterns-patternMatches-contextAll", true],
["documentUrlPatterns-patternMatches-contextImage", false],
["documentUrlPatterns-patternMatches-contextLink", false],
["documentUrlPatterns-patternDoesNotMatch-contextAll", false],
["documentUrlPatterns-patternDoesNotMatch-contextImage", false],
["documentUrlPatterns-patternDoesNotMatch-contextLink", false],
["documentUrlPatterns-patternMatches-targetUrlPatterns-patternMatches-contextAll", false],
["documentUrlPatterns-patternDoesNotMatch-targetUrlPatterns-patternMatches-contextAll", false],
["documentUrlPatterns-patternMatches-targetUrlPatterns-patternDoesNotMatch-contextAll", false],
@ -181,6 +213,42 @@ add_task(function* () {
yield confirmContextMenuItems(contextMenu, expected);
yield closeContextMenu();
contextMenu = yield openContextMenu("#link1");
expected = [
["targetUrlPatterns-patternMatches-contextAll", true],
["targetUrlPatterns-patternMatches-contextImage", false],
["targetUrlPatterns-patternMatches-contextLink", true],
["targetUrlPatterns-patternDoesNotMatch-contextAll", false],
["targetUrlPatterns-patternDoesNotMatch-contextImage", false],
["targetUrlPatterns-patternDoesNotMatch-contextLink", false],
["documentUrlPatterns-patternMatches-contextAll", true],
["documentUrlPatterns-patternMatches-contextImage", false],
["documentUrlPatterns-patternMatches-contextLink", true],
["documentUrlPatterns-patternDoesNotMatch-contextAll", false],
["documentUrlPatterns-patternDoesNotMatch-contextImage", false],
["documentUrlPatterns-patternDoesNotMatch-contextLink", false],
];
yield confirmContextMenuItems(contextMenu, expected);
yield closeContextMenu();
contextMenu = yield openContextMenu("#img-wrapped-in-link");
expected = [
["targetUrlPatterns-patternMatches-contextAll", true],
["targetUrlPatterns-patternMatches-contextImage", true],
["targetUrlPatterns-patternMatches-contextLink", true],
["targetUrlPatterns-patternDoesNotMatch-contextAll", false],
["targetUrlPatterns-patternDoesNotMatch-contextImage", false],
["targetUrlPatterns-patternDoesNotMatch-contextLink", false],
["documentUrlPatterns-patternMatches-contextAll", true],
["documentUrlPatterns-patternMatches-contextImage", true],
["documentUrlPatterns-patternMatches-contextLink", true],
["documentUrlPatterns-patternDoesNotMatch-contextAll", false],
["documentUrlPatterns-patternDoesNotMatch-contextImage", false],
["documentUrlPatterns-patternDoesNotMatch-contextLink", false],
];
yield confirmContextMenuItems(contextMenu, expected);
yield closeContextMenu();
yield extension.unload();
yield BrowserTestUtils.removeTab(tab1);
});

Просмотреть файл

@ -4,5 +4,15 @@
<body>
just some text 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
<img src="ctxmenu-image.png" id="img1">
<p>
<a href="some-link" id="link1">Some link</a>
</p>
<p>
<a href="image-around-some-link">
<img src="ctxmenu-image.png" id="img-wrapped-in-link">
</a>
</p>
</body>
</html>

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -7,3 +7,12 @@
.searchbar-textbox {
-moz-binding: url("chrome://browser/content/search/search.xml#searchbar-textbox");
}
.search-one-offs {
-moz-binding: url("chrome://browser/content/search/search.xml#search-one-offs");
}
.search-setting-button[compact=true],
.search-setting-button-compact:not([compact=true]) {
display: none;
}

Просмотреть файл

@ -14,21 +14,6 @@ const diacritic_engine = "Foo \u2661";
var Preferences =
Cu.import("resource://gre/modules/Preferences.jsm", {}).Preferences;
// Get an array of the one-off buttons.
function getOneOffs() {
let oneOffs = [];
let oneOff =
document.getAnonymousElementByAttribute(searchPopup, "anonid",
"search-panel-one-offs");
for (oneOff = oneOff.firstChild; oneOff; oneOff = oneOff.nextSibling) {
if (oneOff.classList.contains("dummy"))
break;
oneOffs.push(oneOff);
}
return oneOffs;
}
add_task(function* init() {
let currentEngine = Services.search.currentEngine;
yield promiseNewEngine("testEngine_diacritics.xml", {setAsCurrent: false});

Просмотреть файл

@ -10,11 +10,15 @@ const textbox = searchbar._textbox;
const searchPopup = document.getElementById("PopupSearchAutoComplete");
const searchIcon = document.getAnonymousElementByAttribute(searchbar, "anonid",
"searchbar-search-button");
const searchSettings =
const oneOffsContainer =
document.getAnonymousElementByAttribute(searchPopup, "anonid",
"search-one-off-buttons");
const searchSettings =
document.getAnonymousElementByAttribute(oneOffsContainer, "anonid",
"search-settings");
var header =
document.getAnonymousElementByAttribute(searchPopup, "anonid",
document.getAnonymousElementByAttribute(oneOffsContainer, "anonid",
"search-panel-one-offs-header");
function getHeaderText() {
let headerChild = header.selectedPanel;
@ -28,21 +32,6 @@ function getHeaderText() {
return headerStrings.join("");
}
// Get an array of the one-off buttons.
function getOneOffs() {
let oneOffs = [];
let oneOff =
document.getAnonymousElementByAttribute(searchPopup, "anonid",
"search-panel-one-offs");
for (oneOff = oneOff.firstChild; oneOff; oneOff = oneOff.nextSibling) {
if (oneOff.classList.contains("dummy"))
break;
oneOffs.push(oneOff);
}
return oneOffs;
}
const msg = isMac ? 5 : 1;
const utils = window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);

Просмотреть файл

@ -3,29 +3,18 @@
const searchbar = document.getElementById("searchbar");
const textbox = searchbar._textbox;
const searchPopup = document.getElementById("PopupSearchAutoComplete");
const oneOffsContainer =
document.getAnonymousElementByAttribute(searchPopup, "anonid",
"search-one-off-buttons");
const kValues = ["foo1", "foo2", "foo3"];
const kUserValue = "foo";
// Get an array of the one-off buttons.
function getOneOffs() {
let oneOffs = [];
let oneOff = document.getAnonymousElementByAttribute(searchPopup, "anonid",
"search-panel-one-offs");
for (oneOff = oneOff.firstChild; oneOff; oneOff = oneOff.nextSibling) {
if (oneOff.classList.contains("dummy"))
break;
oneOffs.push(oneOff);
}
return oneOffs;
}
function getOpenSearchItems() {
let os = [];
let addEngineList =
document.getAnonymousElementByAttribute(searchPopup, "anonid",
document.getAnonymousElementByAttribute(oneOffsContainer, "anonid",
"add-engines");
for (let item = addEngineList.firstChild; item; item = item.nextSibling)
os.push(item);

Просмотреть файл

@ -3,30 +3,19 @@
const searchbar = document.getElementById("searchbar");
const textbox = searchbar._textbox;
const searchPopup = document.getElementById("PopupSearchAutoComplete");
const oneOffsContainer =
document.getAnonymousElementByAttribute(searchPopup, "anonid",
"search-one-off-buttons");
const searchIcon = document.getAnonymousElementByAttribute(searchbar, "anonid",
"searchbar-search-button");
const kValues = ["foo1", "foo2", "foo3"];
// Get an array of the one-off buttons.
function getOneOffs() {
let oneOffs = [];
let oneOff = document.getAnonymousElementByAttribute(searchPopup, "anonid",
"search-panel-one-offs");
for (oneOff = oneOff.firstChild; oneOff; oneOff = oneOff.nextSibling) {
if (oneOff.classList.contains("dummy"))
break;
oneOffs.push(oneOff);
}
return oneOffs;
}
function getOpenSearchItems() {
let os = [];
let addEngineList =
document.getAnonymousElementByAttribute(searchPopup, "anonid",
document.getAnonymousElementByAttribute(oneOffsContainer, "anonid",
"add-engines");
for (let item = addEngineList.firstChild; item; item = item.nextSibling)
os.push(item);

Просмотреть файл

@ -136,3 +136,24 @@ function promiseTabLoadEvent(tab, url)
// timeout promise as well, causing the all promise to resolve.
return Promise.all([deferred.promise, loaded]);
}
// Get an array of the one-off buttons.
function getOneOffs() {
let oneOffs = [];
let searchPopup = document.getElementById("PopupSearchAutoComplete");
let oneOffsContainer =
document.getAnonymousElementByAttribute(searchPopup, "anonid",
"search-one-off-buttons");
let oneOff =
document.getAnonymousElementByAttribute(oneOffsContainer, "anonid",
"search-panel-one-offs");
for (oneOff = oneOff.firstChild; oneOff; oneOff = oneOff.nextSibling) {
if (oneOff.nodeType == Node.ELEMENT_NODE) {
if (oneOff.classList.contains("dummy") ||
oneOff.classList.contains("search-setting-button-compact"))
break;
oneOffs.push(oneOff);
}
}
return oneOffs;
}

Просмотреть файл

@ -13,5 +13,13 @@
"algorithm": "sha512",
"filename": "sccache.tar.bz2",
"unpack": true
},
{
"version": "cctools port from commit hash db1f8d906cb28, ld only",
"size": 634496,
"digest": "037f31fcf29e7bb7fada0d2bdd5e95c7d4cb2692f2a5c98ed6f6a7561b9d81622d015f0d12b291d3667719655f1369e8ce8a0a4a4773aa0ee4753e04a8821173",
"algorithm": "sha512",
"filename": "cctools.tar.bz2",
"unpack": true
}
]

Просмотреть файл

@ -23,6 +23,14 @@
"unpack": true
},
{
"version": "cctools port from commit hash db1f8d906cb28, ld only",
"size": 634496,
"digest": "037f31fcf29e7bb7fada0d2bdd5e95c7d4cb2692f2a5c98ed6f6a7561b9d81622d015f0d12b291d3667719655f1369e8ce8a0a4a4773aa0ee4753e04a8821173",
"algorithm": "sha512",
"filename": "cctools.tar.bz2",
"unpack": true
},
{
"size": 167175,
"digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831",
"algorithm": "sha512",

Просмотреть файл

@ -158,7 +158,7 @@ menuitem[cmd="cmd_clearhistory"][disabled] {
.search-panel-one-offs {
margin: 0 -1px !important;
border-top: 1px solid rgba(0, 0, 0, 0.2);
border-top: 1px solid #ccc;
}
.searchbar-engine-one-off-item {
@ -184,7 +184,15 @@ menuitem[cmd="cmd_clearhistory"][disabled] {
border-bottom: 1px solid rgba(0, 0, 0, 0.2);
}
.searchbar-engine-one-off-item.last-of-row {
.search-setting-button-compact {
border-bottom: none !important;
}
.search-panel-one-offs:not([compact=true]) > .searchbar-engine-one-off-item.last-of-row,
.search-panel-one-offs[compact=true] > .searchbar-engine-one-off-item.last-of-row:not(.dummy),
.search-panel-one-offs[compact=true] > .searchbar-engine-one-off-item.dummy:not(.last-of-row),
.search-panel-one-offs[compact=true] > .searchbar-engine-one-off-item.last-engine,
.search-setting-button-compact {
background-image: none;
}
@ -298,3 +306,11 @@ menuitem[cmd="cmd_clearhistory"][disabled] {
color: HighlightText;
border-top-color: #bdbebe;
}
.search-setting-button-compact {
list-style-image: url("chrome://browser/skin/gear.svg#gear");
}
.search-setting-button-compact[selected] {
list-style-image: url("chrome://browser/skin/gear.svg#gear-inverted");
}

Просмотреть файл

@ -173,7 +173,15 @@
border-bottom: 1px solid #ccc;
}
.searchbar-engine-one-off-item.last-of-row {
.search-setting-button-compact {
border-bottom: none !important;
}
.search-panel-one-offs:not([compact=true]) > .searchbar-engine-one-off-item.last-of-row,
.search-panel-one-offs[compact=true] > .searchbar-engine-one-off-item.last-of-row:not(.dummy),
.search-panel-one-offs[compact=true] > .searchbar-engine-one-off-item.dummy:not(.last-of-row),
.search-panel-one-offs[compact=true] > .searchbar-engine-one-off-item.last-engine,
.search-setting-button-compact {
background-image: none;
}
@ -277,3 +285,11 @@
background-color: #d3d3d3;
border-top-color: #bdbebe;
}
.search-setting-button-compact {
list-style-image: url("chrome://browser/skin/gear.svg#gear");
}
.search-setting-button-compact[selected] {
list-style-image: url("chrome://browser/skin/gear.svg#gear-inverted");
}

Просмотреть файл

@ -98,6 +98,7 @@
skin/classic/browser/search-history-icon.svg (../shared/search/history-icon.svg)
skin/classic/browser/search-indicator-magnifying-glass.svg (../shared/search/search-indicator-magnifying-glass.svg)
skin/classic/browser/search-arrow-go.svg (../shared/search/search-arrow-go.svg)
skin/classic/browser/gear.svg (../shared/search/gear.svg)
skin/classic/browser/social/chat-icons.svg (../shared/social/chat-icons.svg)
skin/classic/browser/social/gear_default.png (../shared/social/gear_default.png)
skin/classic/browser/social/gear_clicked.png (../shared/social/gear_clicked.png)

Просмотреть файл

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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/. -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 32 32">
<style>
use:not(:target) {
display: none;
}
use {
fill: GrayText;
}
use[id$="-inverted"] {
fill: highlighttext;
}
</style>
<defs>
<path id="glyphShape-gear" d="M28,16c0-1.7,0.9-3.1,2-3.3c-0.4-1.5-0.9-2.9-1.7-4.2c-0.9,0.7-2.6,0.3-3.8-0.9c-1.2-1.2-1.6-2.8-0.9-3.8 c-1.3-0.8-2.7-1.4-4.2-1.7c-0.2,1.1-1.6,2-3.3,2S13,3.1,12.8,2c-1.5,0.4-2.9,0.9-4.2,1.7c0.7,0.9,0.3,2.6-0.9,3.8 c-1.4,1.1-3,1.5-4,0.9C2.9,9.7,2.4,11.2,2,12.7c1.1,0.2,2,1.6,2,3.3s-0.9,3.1-2,3.3c0.4,1.5,0.9,2.9,1.7,4.2 c0.9-0.7,2.6-0.3,3.8,0.9c1.2,1.2,1.6,2.8,0.9,3.8c1.3,0.8,2.7,1.4,4.2,1.7c0.2-1.1,1.6-2,3.3-2s3.1,0.9,3.3,2 c1.5-0.4,2.9-0.9,4.2-1.7c-0.7-0.9-0.3-2.6,0.9-3.8c1.3-1.2,2.8-1.6,3.8-0.9c0.8-1.3,1.4-2.7,1.7-4.2C28.9,19.1,28,17.7,28,16z M16,24c-4.4,0-8-3.6-8-8s3.6-8,8-8s8,3.6,8,8S20.4,24,16,24z"/>
</defs>
<use id="gear" xlink:href="#glyphShape-gear"/>
<use id="gear-inverted" xlink:href="#glyphShape-gear"/>
</svg>

После

Ширина:  |  Высота:  |  Размер: 1.3 KiB

Просмотреть файл

@ -181,7 +181,15 @@
border-bottom: 1px solid #ccc;
}
.searchbar-engine-one-off-item.last-of-row {
.search-setting-button-compact {
border-bottom: none !important;
}
.search-panel-one-offs:not([compact=true]) > .searchbar-engine-one-off-item.last-of-row,
.search-panel-one-offs[compact=true] > .searchbar-engine-one-off-item.last-of-row:not(.dummy),
.search-panel-one-offs[compact=true] > .searchbar-engine-one-off-item.dummy:not(.last-of-row),
.search-panel-one-offs[compact=true] > .searchbar-engine-one-off-item.last-engine,
.search-setting-button-compact {
background-image: none;
}
@ -291,3 +299,11 @@
background-color: #d3d3d3;
border-top-color: #bdbebe;
}
.search-setting-button-compact {
list-style-image: url("chrome://browser/skin/gear.svg#gear");
}
.search-setting-button-compact[selected] {
list-style-image: url("chrome://browser/skin/gear.svg#gear-inverted");
}

Просмотреть файл

@ -82,4 +82,10 @@ fi
AC_SUBST(MOZ_NO_WLZDEFS)
AC_SUBST(MOZ_CFLAGS_NSS)
dnl ========================================================
dnl = Test for whether the compiler is compatible with the
dnl = given sanitize options.
dnl ========================================================
AC_TRY_LINK(,,,AC_MSG_ERROR([compiler is incompatible with sanitize options]))
])

Просмотреть файл

@ -803,6 +803,11 @@ AST_MATCHER(CallExpr, isAssertAssignmentTestFunc) {
&& method->getDeclName().isIdentifier()
&& method->getName() == assertName;
}
AST_MATCHER(CXXRecordDecl, isLambdaDecl) {
return Node.isLambda();
}
}
}
@ -1051,12 +1056,21 @@ DiagnosticsMatcher::DiagnosticsMatcher() {
.bind("node"),
&noAddRefReleaseOnReturnChecker);
// Match declrefs with type "pointer to object of ref-counted type" inside a
// lambda, where the declaration they reference is not inside the lambda.
// This excludes arguments and local variables, leaving only captured
// variables.
astMatcher.addMatcher(lambdaExpr().bind("lambda"),
&refCountedInsideLambdaChecker);
// We want to reject any code which captures a pointer to an object of a
// refcounted type, and then lets that value escape. As a primitive analysis,
// we reject any occurances of the lambda as a template parameter to a class
// (which could allow it to escape), as well as any presence of such a lambda
// in a return value (either from lambdas, or in c++14, auto functions).
//
// We check these lambdas' capture lists for raw pointers to refcounted types.
astMatcher.addMatcher(
functionDecl(returns(recordType(hasDeclaration(cxxRecordDecl(isLambdaDecl()).bind("decl"))))),
&refCountedInsideLambdaChecker);
astMatcher.addMatcher(lambdaExpr().bind("lambdaExpr"), &refCountedInsideLambdaChecker);
astMatcher.addMatcher(
classTemplateSpecializationDecl(hasAnyTemplateArgument(refersToType(
recordType(hasDeclaration(cxxRecordDecl(isLambdaDecl()).bind("decl")))))),
&refCountedInsideLambdaChecker);
// Older clang versions such as the ones used on the infra recognize these
// conversions as 'operator _Bool', but newer clang versions recognize these
@ -1358,13 +1372,34 @@ void DiagnosticsMatcher::NoAddRefReleaseOnReturnChecker::run(
void DiagnosticsMatcher::RefCountedInsideLambdaChecker::run(
const MatchFinder::MatchResult &Result) {
static DenseSet<const CXXRecordDecl*> CheckedDecls;
DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
unsigned errorID = Diag.getDiagnosticIDs()->getCustomDiagID(
DiagnosticIDs::Error,
"Refcounted variable %0 of type %1 cannot be captured by a lambda");
unsigned noteID = Diag.getDiagnosticIDs()->getCustomDiagID(
DiagnosticIDs::Note, "Please consider using a smart pointer");
const LambdaExpr *Lambda = Result.Nodes.getNodeAs<LambdaExpr>("lambda");
const CXXRecordDecl *Lambda = Result.Nodes.getNodeAs<CXXRecordDecl>("decl");
if (const LambdaExpr *OuterLambda = Result.Nodes.getNodeAs<LambdaExpr>("lambdaExpr")) {
const CXXMethodDecl *OpCall = OuterLambda->getCallOperator();
QualType ReturnTy = OpCall->getReturnType();
if (const CXXRecordDecl *Record = ReturnTy->getAsCXXRecordDecl()) {
Lambda = Record;
}
}
if (!Lambda || !Lambda->isLambda()) {
return;
}
// Don't report errors on the same declarations more than once.
if (CheckedDecls.count(Lambda)) {
return;
}
CheckedDecls.insert(Lambda);
for (const LambdaCapture Capture : Lambda->captures()) {
if (Capture.capturesVariable() && Capture.getCaptureKind() != LCK_ByRef) {
@ -1374,6 +1409,7 @@ void DiagnosticsMatcher::RefCountedInsideLambdaChecker::run(
Diag.Report(Capture.getLocation(), errorID) << Capture.getCapturedVar()
<< Pointee;
Diag.Report(Capture.getLocation(), noteID);
return;
}
}
}

Просмотреть файл

@ -1,3 +1,5 @@
#include <functional>
#include "mozilla/Function.h"
#define MOZ_STRONG_REF __attribute__((annotate("moz_strong_ref")))
struct RefCountedBase {
@ -45,7 +47,7 @@ void foo() {
});
take([=](R* argptr) {
R* localptr;
ptr->method(); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
ptr->method();
argptr->method();
localptr->method();
});
@ -57,7 +59,7 @@ void foo() {
});
take([=](R* argptr) {
R* localptr;
take(ptr); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
take(ptr);
take(argptr);
take(localptr);
});
@ -67,7 +69,7 @@ void foo() {
take(argsp);
take(localsp);
});
take([ptr](R* argptr) { // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
take([ptr](R* argptr) {
R* localptr;
ptr->method();
argptr->method();
@ -79,7 +81,7 @@ void foo() {
argsp->method();
localsp->method();
});
take([ptr](R* argptr) { // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
take([ptr](R* argptr) {
R* localptr;
take(ptr);
take(argptr);
@ -92,27 +94,558 @@ void foo() {
take(localsp);
});
take([&ptr](R* argptr) {
R* localptr;
ptr->method();
argptr->method();
localptr->method();
});
take([&sp](SmartPtr<R> argsp) {
SmartPtr<R> localsp;
sp->method();
argsp->method();
localsp->method();
});
take([&ptr](R* argptr) {
R* localptr;
take(ptr);
take(argptr);
take(localptr);
});
take([&sp](SmartPtr<R> argsp) {
SmartPtr<R> localsp;
take(sp);
take(argsp);
take(localsp);
});
}
void b() {
R* ptr;
SmartPtr<R> sp;
std::function<void(R*)>([&](R* argptr) {
R* localptr;
ptr->method();
argptr->method();
localptr->method();
});
std::function<void(SmartPtr<R>)>([&](SmartPtr<R> argsp) {
SmartPtr<R> localsp;
sp->method();
argsp->method();
localsp->method();
});
std::function<void(R*)>([&](R* argptr) {
R* localptr;
take(ptr);
take(argptr);
take(localptr);
});
std::function<void(SmartPtr<R>)>([&](SmartPtr<R> argsp) {
SmartPtr<R> localsp;
take(sp);
take(argsp);
take(localsp);
});
std::function<void(R*)>([=](R* argptr) {
R* localptr;
ptr->method(); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
argptr->method();
localptr->method();
});
std::function<void(SmartPtr<R>)>([=](SmartPtr<R> argsp) {
SmartPtr<R> localsp;
sp->method();
argsp->method();
localsp->method();
});
std::function<void(R*)>([=](R* argptr) {
R* localptr;
take(ptr); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
take(argptr);
take(localptr);
});
std::function<void(SmartPtr<R>)>([=](SmartPtr<R> argsp) {
SmartPtr<R> localsp;
take(sp);
take(argsp);
take(localsp);
});
std::function<void(R*)>([ptr](R* argptr) { // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
R* localptr;
ptr->method();
argptr->method();
localptr->method();
});
std::function<void(SmartPtr<R>)>([sp](SmartPtr<R> argsp) {
SmartPtr<R> localsp;
sp->method();
argsp->method();
localsp->method();
});
std::function<void(R*)>([ptr](R* argptr) { // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
R* localptr;
take(ptr);
take(argptr);
take(localptr);
});
std::function<void(SmartPtr<R>)>([sp](SmartPtr<R> argsp) {
SmartPtr<R> localsp;
take(sp);
take(argsp);
take(localsp);
});
std::function<void(R*)>([&ptr](R* argptr) {
R* localptr;
ptr->method();
argptr->method();
localptr->method();
});
std::function<void(SmartPtr<R>)>([&sp](SmartPtr<R> argsp) {
SmartPtr<R> localsp;
sp->method();
argsp->method();
localsp->method();
});
std::function<void(R*)>([&ptr](R* argptr) {
R* localptr;
take(ptr);
take(argptr);
take(localptr);
});
std::function<void(SmartPtr<R>)>([&sp](SmartPtr<R> argsp) {
SmartPtr<R> localsp;
take(sp);
take(argsp);
take(localsp);
});
}
void c() {
R* ptr;
SmartPtr<R> sp;
mozilla::function<void(R*)>([&](R* argptr) {
R* localptr;
ptr->method();
argptr->method();
localptr->method();
});
mozilla::function<void(SmartPtr<R>)>([&](SmartPtr<R> argsp) {
SmartPtr<R> localsp;
sp->method();
argsp->method();
localsp->method();
});
mozilla::function<void(R*)>([&](R* argptr) {
R* localptr;
take(ptr);
take(argptr);
take(localptr);
});
mozilla::function<void(SmartPtr<R>)>([&](SmartPtr<R> argsp) {
SmartPtr<R> localsp;
take(sp);
take(argsp);
take(localsp);
});
mozilla::function<void(R*)>([=](R* argptr) {
R* localptr;
ptr->method(); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
argptr->method();
localptr->method();
});
mozilla::function<void(SmartPtr<R>)>([=](SmartPtr<R> argsp) {
SmartPtr<R> localsp;
sp->method();
argsp->method();
localsp->method();
});
mozilla::function<void(R*)>([=](R* argptr) {
R* localptr;
take(ptr); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
take(argptr);
take(localptr);
});
mozilla::function<void(SmartPtr<R>)>([=](SmartPtr<R> argsp) {
SmartPtr<R> localsp;
take(sp);
take(argsp);
take(localsp);
});
mozilla::function<void(R*)>([ptr](R* argptr) { // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
R* localptr;
ptr->method();
argptr->method();
localptr->method();
});
mozilla::function<void(SmartPtr<R>)>([sp](SmartPtr<R> argsp) {
SmartPtr<R> localsp;
sp->method();
argsp->method();
localsp->method();
});
mozilla::function<void(R*)>([ptr](R* argptr) { // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
R* localptr;
take(ptr);
take(argptr);
take(localptr);
});
mozilla::function<void(SmartPtr<R>)>([sp](SmartPtr<R> argsp) {
SmartPtr<R> localsp;
take(sp);
take(argsp);
take(localsp);
});
mozilla::function<void(R*)>([&ptr](R* argptr) {
R* localptr;
ptr->method();
argptr->method();
localptr->method();
});
mozilla::function<void(SmartPtr<R>)>([&sp](SmartPtr<R> argsp) {
SmartPtr<R> localsp;
sp->method();
argsp->method();
localsp->method();
});
mozilla::function<void(R*)>([&ptr](R* argptr) {
R* localptr;
take(ptr);
take(argptr);
take(localptr);
});
mozilla::function<void(SmartPtr<R>)>([&sp](SmartPtr<R> argsp) {
SmartPtr<R> localsp;
take(sp);
take(argsp);
take(localsp);
});
}
// These tests would check c++14 deduced return types, if they were supported in
// our codebase. They are being kept here for convenience in the future if we do
// add support for c++14 deduced return types
#if 0
auto d1() {
R* ptr;
SmartPtr<R> sp;
return ([&](R* argptr) {
R* localptr;
ptr->method();
argptr->method();
localptr->method();
});
}
auto d2() {
R* ptr;
SmartPtr<R> sp;
return ([&](SmartPtr<R> argsp) {
SmartPtr<R> localsp;
sp->method();
argsp->method();
localsp->method();
});
}
auto d3() {
R* ptr;
SmartPtr<R> sp;
return ([&](R* argptr) {
R* localptr;
take(ptr);
take(argptr);
take(localptr);
});
}
auto d4() {
R* ptr;
SmartPtr<R> sp;
return ([&](SmartPtr<R> argsp) {
SmartPtr<R> localsp;
take(sp);
take(argsp);
take(localsp);
});
}
auto d5() {
R* ptr;
SmartPtr<R> sp;
return ([=](R* argptr) {
R* localptr;
ptr->method(); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
argptr->method();
localptr->method();
});
}
auto d6() {
R* ptr;
SmartPtr<R> sp;
return ([=](SmartPtr<R> argsp) {
SmartPtr<R> localsp;
sp->method();
argsp->method();
localsp->method();
});
}
auto d8() {
R* ptr;
SmartPtr<R> sp;
return ([=](R* argptr) {
R* localptr;
take(ptr); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
take(argptr);
take(localptr);
});
}
auto d9() {
R* ptr;
SmartPtr<R> sp;
return ([=](SmartPtr<R> argsp) {
SmartPtr<R> localsp;
take(sp);
take(argsp);
take(localsp);
});
}
auto d10() {
R* ptr;
SmartPtr<R> sp;
return ([ptr](R* argptr) { // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
R* localptr;
ptr->method();
argptr->method();
localptr->method();
});
}
auto d11() {
R* ptr;
SmartPtr<R> sp;
return ([sp](SmartPtr<R> argsp) {
SmartPtr<R> localsp;
sp->method();
argsp->method();
localsp->method();
});
}
auto d12() {
R* ptr;
SmartPtr<R> sp;
return ([ptr](R* argptr) { // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
R* localptr;
take(ptr);
take(argptr);
take(localptr);
});
}
auto d13() {
R* ptr;
SmartPtr<R> sp;
return ([sp](SmartPtr<R> argsp) {
SmartPtr<R> localsp;
take(sp);
take(argsp);
take(localsp);
});
}
auto d14() {
R* ptr;
SmartPtr<R> sp;
return ([&ptr](R* argptr) {
R* localptr;
ptr->method();
argptr->method();
localptr->method();
});
}
auto d15() {
R* ptr;
SmartPtr<R> sp;
return ([&sp](SmartPtr<R> argsp) {
SmartPtr<R> localsp;
sp->method();
argsp->method();
localsp->method();
});
}
auto d16() {
R* ptr;
SmartPtr<R> sp;
return ([&ptr](R* argptr) {
R* localptr;
take(ptr);
take(argptr);
take(localptr);
});
}
auto d17() {
R* ptr;
SmartPtr<R> sp;
return ([&sp](SmartPtr<R> argsp) {
SmartPtr<R> localsp;
take(sp);
take(argsp);
take(localsp);
});
}
#endif
void e() {
auto e1 = []() {
R* ptr;
SmartPtr<R> sp;
return ([&](R* argptr) {
R* localptr;
ptr->method();
argptr->method();
localptr->method();
});
take([&sp](SmartPtr<R> argsp) {
};
auto e2 = []() {
R* ptr;
SmartPtr<R> sp;
return ([&](SmartPtr<R> argsp) {
SmartPtr<R> localsp;
sp->method();
argsp->method();
localsp->method();
});
take([&ptr](R* argptr) {
};
auto e3 = []() {
R* ptr;
SmartPtr<R> sp;
return ([&](R* argptr) {
R* localptr;
take(ptr);
take(argptr);
take(localptr);
});
take([&sp](SmartPtr<R> argsp) {
};
auto e4 = []() {
R* ptr;
SmartPtr<R> sp;
return ([&](SmartPtr<R> argsp) {
SmartPtr<R> localsp;
take(sp);
take(argsp);
take(localsp);
});
};
auto e5 = []() {
R* ptr;
SmartPtr<R> sp;
return ([=](R* argptr) {
R* localptr;
ptr->method(); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
argptr->method();
localptr->method();
});
};
auto e6 = []() {
R* ptr;
SmartPtr<R> sp;
return ([=](SmartPtr<R> argsp) {
SmartPtr<R> localsp;
sp->method();
argsp->method();
localsp->method();
});
};
auto e8 = []() {
R* ptr;
SmartPtr<R> sp;
return ([=](R* argptr) {
R* localptr;
take(ptr); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
take(argptr);
take(localptr);
});
};
auto e9 = []() {
R* ptr;
SmartPtr<R> sp;
return ([=](SmartPtr<R> argsp) {
SmartPtr<R> localsp;
take(sp);
take(argsp);
take(localsp);
});
};
auto e10 = []() {
R* ptr;
SmartPtr<R> sp;
return ([ptr](R* argptr) { // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
R* localptr;
ptr->method();
argptr->method();
localptr->method();
});
};
auto e11 = []() {
R* ptr;
SmartPtr<R> sp;
return ([sp](SmartPtr<R> argsp) {
SmartPtr<R> localsp;
sp->method();
argsp->method();
localsp->method();
});
};
auto e12 = []() {
R* ptr;
SmartPtr<R> sp;
return ([ptr](R* argptr) { // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
R* localptr;
take(ptr);
take(argptr);
take(localptr);
});
};
auto e13 = []() {
R* ptr;
SmartPtr<R> sp;
return ([sp](SmartPtr<R> argsp) {
SmartPtr<R> localsp;
take(sp);
take(argsp);
take(localsp);
});
};
auto e14 = []() {
R* ptr;
SmartPtr<R> sp;
return ([&ptr](R* argptr) {
R* localptr;
ptr->method();
argptr->method();
localptr->method();
});
};
auto e15 = []() {
R* ptr;
SmartPtr<R> sp;
return ([&sp](SmartPtr<R> argsp) {
SmartPtr<R> localsp;
sp->method();
argsp->method();
localsp->method();
});
};
auto e16 = []() {
R* ptr;
SmartPtr<R> sp;
return ([&ptr](R* argptr) {
R* localptr;
take(ptr);
take(argptr);
take(localptr);
});
};
auto e17 = []() {
R* ptr;
SmartPtr<R> sp;
return ([&sp](SmartPtr<R> argsp) {
SmartPtr<R> localsp;
take(sp);
take(argsp);
take(localsp);
});
};
}

Просмотреть файл

@ -24,6 +24,13 @@ elif [ -d "$topsrcdir/../clang" ]; then
export DSYMUTIL=$topsrcdir/../clang/bin/llvm-dsymutil
fi
# Use an updated linker.
ldflags="-B$topsrcdir/cctools/bin"
# Ensure the updated linker doesn't generate things our older build tools
# don't understand.
ldflags="$ldflags -Wl,-no_data_in_code_info"
export LDFLAGS="$ldflags"
# If not set use the system default clang
if [ -z "$CC" ]; then
export CC=clang

Просмотреть файл

@ -29,8 +29,8 @@ FontInspector.prototype = {
this.inspector.selection.on("new-node", this.onNewNode);
this.inspector.sidebar.on("fontinspector-selected", this.onNewNode);
this.showAll = this.showAll.bind(this);
this.showAllButton = this.chromeDoc.getElementById("font-showall");
this.showAllButton.addEventListener("click", this.showAll);
this.showAllLink = this.chromeDoc.getElementById("font-showall");
this.showAllLink.addEventListener("click", this.showAll);
this.previewTextChanged = this.previewTextChanged.bind(this);
this.previewInput =
this.chromeDoc.getElementById("font-preview-text-input");
@ -57,7 +57,7 @@ FontInspector.prototype = {
this.chromeDoc = null;
this.inspector.sidebar.off("fontinspector-selected", this.onNewNode);
this.inspector.selection.off("new-node", this.onNewNode);
this.showAllButton.removeEventListener("click", this.showAll);
this.showAllLink.removeEventListener("click", this.showAll);
this.previewInput.removeEventListener("input", this.previewTextChanged);
gDevTools.off("theme-switched", this.onThemeChanged);

Просмотреть файл

@ -184,11 +184,11 @@
type="search"
placeholder="&previewHint;"/>
</html:div>
<html:label id="font-showall" class="theme-link" title="&showAllFonts;">&showAllFontsUsed;</html:label>
</html:div>
<html:div id="font-container">
<html:ul id="all-fonts"></html:ul>
<html:button id="font-showall">&showAllFonts;</html:button>
</html:div>
<html:div id="font-template">

Просмотреть файл

@ -87,9 +87,7 @@ define(function (require, exports, module) {
td({className: "netInfoParamName"},
span({title: header.name}, header.name)
),
td({className: "netInfoParamValue"},
code({}, header.value)
)
td({className: "netInfoParamValue"}, header.value)
)
);
});

Просмотреть файл

@ -212,8 +212,18 @@ let Converter = Class({
let themeVarsUrl = clientBaseUrl + "themes/variables.css";
let commonUrl = clientBaseUrl + "themes/common.css";
let os;
let platform = Services.appinfo.OS;
if (platform.startsWith("WINNT")) {
os = "win";
} else if (platform.startsWith("Darwin")) {
os = "mac";
} else {
os = "linux";
}
return "<!DOCTYPE html>\n" +
"<html class=\"" + themeClassName + "\">" +
"<html platform=\"" + os + "\" class=\"" + themeClassName + "\">" +
"<head><title>" + this.htmlEncode(title) + "</title>" +
"<base href=\"" + this.htmlEncode(baseUrl) + "\">" +
"<link rel=\"stylesheet\" type=\"text/css\" href=\"" +

Просмотреть файл

@ -7,10 +7,11 @@
/* General */
body {
background-color: white;
color: var(--theme-body-color);
background-color: var(--theme-body-background);
padding: 0;
margin: 0;
overflow: hidden;
overflow-x: hidden;
}
*:focus {
@ -24,6 +25,7 @@ body {
pre {
background-color: white;
border: none;
font-family: var(--monospace-font-family);
}
#json,

Просмотреть файл

@ -8,41 +8,37 @@
.headersPanelBox {
height: 100%;
font-family: Lucida Grande, Tahoma, sans-serif;
font-size: 11px;
}
.headersPanelBox .netInfoHeadersTable {
overflow: auto;
height: 100%;
line-height: 12px;
}
.headersPanelBox .netHeadersGroup {
padding: 10px;
}
.headersPanelBox td {
vertical-align: bottom;
}
.headersPanelBox .netInfoHeadersGroup {
color: var(--theme-body-color-alt);
margin-bottom: 10px;
border-bottom: 1px solid #D7D7D7;
border-bottom: 1px solid var(--theme-splitter-color);
padding-top: 8px;
padding-bottom: 4px;
font-family: Lucida Grande, Tahoma, sans-serif;
font-weight: bold;
color: #565656;
-moz-user-select: none;
}
.headersPanelBox .netInfoParamValue code {
display: block;
color: #18191A;
font-size: 11px;
.headersPanelBox .netInfoParamValue {
word-wrap: break-word;
}
.headersPanelBox .netInfoParamName {
padding: 2px 10px 0 0;
font-family: Lucida Grande, Tahoma, sans-serif;
font-weight: bold;
vertical-align: top;
text-align: right;
@ -50,17 +46,33 @@
}
/******************************************************************************/
/* Theme colors have been generated/copied from Network Panel's header view */
/* Light Theme */
.theme-light .netInfoParamName {
color: var(--theme-highlight-red);
}
.theme-light .netInfoParamValue {
color: var(--theme-highlight-purple);
}
/* Dark Theme */
.theme-dark .headersPanelBox .netInfoParamName {
color: var(--theme-highlight-blue);
.theme-dark .netInfoParamName {
color: var(--theme-highlight-purple);
}
.theme-dark .headersPanelBox .netInfoParamValue code {
color: var(--theme-highlight-orange);
.theme-dark .netInfoParamValue {
color: var(--theme-highlight-gray);
}
.theme-dark .headersPanelBox .netInfoHeadersGroup {
color: var(--theme-body-color-alt);
/* Firebug Theme */
.theme-firebug .netInfoHeadersTable {
font-family: Lucida Grande, Tahoma, sans-serif;
font-size: 11px;
line-height: 12px;
}
.theme-firebug .netInfoParamValue {
font-family: var(--monospace-font-family);
}

Просмотреть файл

@ -14,20 +14,22 @@
@import "text-panel.css";
@import "headers-panel.css";
/******************************************************************************/
/* Panel Content */
.panelContent {
overflow-y: auto;
font-size: 11px;
font-family: var(--monospace-font-family);
padding-right: 5px;
width: 100%;
}
/* The tree takes the entire horizontal space within the panel content. */
.panelContent .treeTable {
width: 100%;
font-family: var(--monospace-font-family);
}
:root[platform="linux"] .treeTable {
font-size: 80%; /* To handle big monospace font */
}
/* Make sure there is a little space between label and value columns. */

Просмотреть файл

@ -18,7 +18,7 @@
color: var(--theme-content-color1);
width: 200px;
margin-top: 0;
position: fixed;
right: 1px;
margin-right: 1px;
float: right;
padding-left: 20px;
}

Просмотреть файл

@ -11,19 +11,16 @@
}
.textPanelBox .data {
font-size: 11px;
font-family: monospace;
overflow: auto;
height: 100%;
}
.textPanelBox pre {
margin: 0;
font-family: var(--monospace-font-family);
color: var(--theme-content-color1);
}
/******************************************************************************/
/* Dark Theme */
.theme-dark .textPanelBox {
color: var(--theme-content-color1);
}
:root[platform="linux"] .textPanelBox .data {
font-size: 80%; /* To handle big monospace font */
}

Просмотреть файл

@ -24,7 +24,8 @@
vertical-align: middle;
cursor: pointer;
-moz-user-select: none;
padding: 0 2px 1px 2px;
padding: 0 2px;
border-radius: 2px;
}
.toolbar .btn::-moz-focus-inner {
@ -71,13 +72,11 @@
.theme-dark .toolbar .btn,
.theme-light .toolbar .btn {
min-width: 78px;
min-height: 18px;
color: var(--theme-content-color1);
text-shadow: none;
margin: 1px 2px 1px 2px;
border: none;
border-radius: 0;
background-color: rgba(170, 170, 170, .2); /* --toolbar-tab-hover */
transition: background 0.05s ease-in-out;
}

Просмотреть файл

@ -6,6 +6,7 @@
- The Font Inspector is the panel accessible in the Inspector sidebar. -->
<!ENTITY showAllFonts "See all the fonts used in the page">
<!ENTITY showAllFontsUsed "Show all fonts used">
<!ENTITY usedAs "Used as: ">
<!ENTITY system "system">
<!ENTITY remote "remote">

Просмотреть файл

@ -44,12 +44,13 @@
.theme-dark .tabs,
.theme-light .tabs {
background: var(--theme-tab-toolbar-background);
background: var(--theme-body-background);
}
.theme-dark .tabs .tabs-navigation,
.theme-light .tabs .tabs-navigation {
border-bottom: 1px solid var(--theme-splitter-color);
background: var(--theme-tab-toolbar-background);
}
.theme-dark .tabs .tabs-menu-item,
@ -62,15 +63,14 @@
border-color: var(--theme-splitter-color);
}
.theme-dark .tabs .tabs-menu-item:last-child,
.theme-light:not(.theme-firebug) .tabs .tabs-menu-item:last-child {
border-inline-end-width: 1px;
}
.theme-dark .tabs .tabs-menu-item a,
.theme-light .tabs .tabs-menu-item a {
color: var(--theme-content-color1);
}
.theme-dark .tabs .tabs-menu-item a:hover,
.theme-dark .tabs .tabs-menu-item a,
.theme-light .tabs .tabs-menu-item a:hover,
.theme-light .tabs .tabs-menu-item a {
padding: 3px 15px;
}
@ -105,18 +105,18 @@
/* Firebug Theme */
.theme-firebug .tabs {
.theme-firebug .tabs .tabs-navigation {
background-color: rgb(219, 234, 249);
background-image: linear-gradient(rgba(253, 253, 253, 0.2), rgba(253, 253, 253, 0));
}
.theme-firebug .tabs .tabs-navigation {
padding-top: 3px;
padding-left: 3px;
height: 27px;
border-bottom: 1px solid rgb(170, 188, 207);
}
.theme-firebug .tabs .tabs-menu {
margin-bottom: -1px;
}
.theme-firebug .tabs .tabs-menu-item.is-active,
.theme-firebug .tabs .tabs-menu-item.is-active:hover {
background-color: transparent;
@ -155,9 +155,5 @@
.theme-firebug .tabs .tabs-menu-item a {
border: 1px solid transparent;
}
.theme-firebug .tabs .tabs-menu-item a:hover,
.theme-firebug .tabs .tabs-menu-item a {
padding: 4px 8px 4px 8px;
padding: 4px 8px;
}

Просмотреть файл

@ -26,7 +26,7 @@ define(function (require, exports, module) {
* <li class='tabs-menu-item'>Tab #2</li>
* </ul>
* </nav>
* <div class='tab-panel'>
* <div class='panels'>
* The content of active panel here
* </div>
* <div>
@ -184,11 +184,12 @@ define(function (require, exports, module) {
let ref = ("tab-menu-" + index);
let title = tab.props.title;
let tabClassName = tab.props.className;
let isTabSelected = this.state.tabActive === index;
let classes = [
"tabs-menu-item",
tabClassName,
this.state.tabActive === index ? "is-active" : ""
isTabSelected ? "is-active" : ""
].join(" ");
// Set tabindex to -1 (except the selected tab) so, it's focusable,
@ -200,11 +201,18 @@ define(function (require, exports, module) {
DOM.li({
ref: ref,
key: index,
className: classes},
id: "tab-" + index,
className: classes,
role: "presentation",
},
DOM.a({
href: "#",
tabIndex: this.state.tabActive === index ? 0 : -1,
onClick: this.onClickTab.bind(this, index)},
"aria-controls": "panel-" + index,
"aria-selected": isTabSelected,
role: "tab",
onClick: this.onClickTab.bind(this, index),
},
title
)
)
@ -213,7 +221,7 @@ define(function (require, exports, module) {
return (
DOM.nav({className: "tabs-navigation"},
DOM.ul({className: "tabs-menu"},
DOM.ul({className: "tabs-menu", role: "tablist"},
tabs
)
)
@ -251,8 +259,12 @@ define(function (require, exports, module) {
return (
DOM.div({
key: index,
id: "panel-" + index,
style: style,
className: "tab-panel-box"},
className: "tab-panel-box",
role: "tabpanel",
"aria-labelledby": "tab-" + index,
},
(selected || this.state.created[index]) ? tab : null
)
);

Просмотреть файл

@ -27,6 +27,7 @@ support-files =
[test_reps_undefined.html]
[test_reps_window.html]
[test_sidebar_toggle.html]
[test_tabs_accessibility.html]
[test_tree_01.html]
[test_tree_02.html]
[test_tree_03.html]

Просмотреть файл

@ -0,0 +1,72 @@
<!DOCTYPE HTML>
<html>
<!--
Test tabs accessibility.
-->
<head>
<meta charset="utf-8">
<title>Tabs component accessibility test</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<pre id="test">
<script src="head.js" type="application/javascript;version=1.8"></script>
<script type="application/javascript;version=1.8">
window.onload = Task.async(function* () {
try {
const ReactDOM = browserRequire("devtools/client/shared/vendor/react-dom");
const React = browserRequire("devtools/client/shared/vendor/react");
const { Simulate } = React.addons.TestUtils;
const InspectorTabPanel = React.createFactory(browserRequire("devtools/client/inspector/components/inspector-tab-panel"));
const Tabbar = React.createFactory(browserRequire("devtools/client/shared/components/tabs/tabbar"));
const tabbar = Tabbar();
const tabbarReact = ReactDOM.render(tabbar, window.document.body);
const tabbarEl = ReactDOM.findDOMNode(tabbarReact);
// Setup for InspectorTabPanel
const tabpanels = document.createElement("div");
tabpanels.id = "tabpanels";
document.body.appendChild(tabpanels);
yield addTabWithPanel(0);
yield addTabWithPanel(1);
const tabAnchors = tabbarEl.querySelectorAll("li.tabs-menu-item a");
is(tabAnchors[0].parentElement.getAttribute("role"), "presentation", "li role is set correctly");
is(tabAnchors[0].getAttribute("role"), "tab", "Anchor role is set correctly");
is(tabAnchors[0].getAttribute("aria-selected"), "true", "Anchor aria-selected is set correctly by default");
is(tabAnchors[0].getAttribute("aria-controls"), "panel-0", "Anchor aria-controls is set correctly");
is(tabAnchors[1].parentElement.getAttribute("role"), "presentation", "li role is set correctly");
is(tabAnchors[1].getAttribute("role"), "tab", "Anchor role is set correctly");
is(tabAnchors[1].getAttribute("aria-selected"), "false", "Anchor aria-selected is set correctly by default");
is(tabAnchors[1].getAttribute("aria-controls"), "panel-1", "Anchor aria-controls is set correctly");
yield setState(tabbarReact, Object.assign({}, tabbarReact.state, {
activeTab: 1
}));
is(tabAnchors[0].getAttribute("aria-selected"), "false", "Anchor aria-selected is reset correctly");
is(tabAnchors[1].getAttribute("aria-selected"), "true", "Anchor aria-selected is reset correctly");
function addTabWithPanel(tabId) {
// Setup for InspectorTabPanel
let panel = document.createElement("div");
panel.id = `sidebar-panel-${tabId}`;
document.body.appendChild(panel);
return setState(tabbarReact, Object.assign({}, tabbarReact.state, {
tabs: tabbarReact.state.tabs.concat({id: `${tabId}`, title: `tab-${tabId}`, panel: InspectorTabPanel}),
}));
}
} catch(e) {
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
} finally {
SimpleTest.finish();
}
});
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -137,14 +137,16 @@
/******************************************************************************/
/* Themes */
/* Light Theme: toggle icon */
.theme-light .treeTable .treeRow.hasChildren > .treeLabelCell > .treeIcon {
/* Light, Firebug Theme: toggle icon */
.theme-light .treeTable .treeRow.hasChildren > .treeLabelCell > .treeIcon,
.theme-firebug .treeTable .treeRow.hasChildren > .treeLabelCell > .treeIcon {
background-image: url(chrome://devtools/skin/images/controls.png);
background-size: 56px 28px;
background-position: 0 -14px;
}
.theme-light .treeTable .treeRow.hasChildren.opened > .treeLabelCell > .treeIcon {
.theme-light .treeTable .treeRow.hasChildren.opened > .treeLabelCell > .treeIcon,
.theme-firebug .treeTable .treeRow.hasChildren.opened > .treeLabelCell > .treeIcon {
background-image: url(chrome://devtools/skin/images/controls.png);
background-size: 56px 28px;
background-position: -14px -14px;
@ -163,11 +165,10 @@
background-position: -42px -14px;
}
/* Dark and Light Themes: Support for retina displays */
/* Support for retina displays */
@media (min-resolution: 1.1dppx) {
.theme-dark .treeTable .treeRow.hasChildren > .treeLabelCell > .treeIcon,
.theme-light .treeTable .treeRow.hasChildren > .treeLabelCell > .treeIcon {
background-image: url("chrome://devtools/skin/images/controls@2x.png");
.treeTable .treeRow.hasChildren > .treeLabelCell > .treeIcon {
background-image: url("chrome://devtools/skin/images/controls@2x.png") !important;
}
}
@ -185,7 +186,8 @@
color: var(--theme-highlight-pink);
}
.theme-light .treeTable .treeRow.hasChildren > .treeLabelCell > .treeLabel:hover {
.theme-light .treeTable .treeRow.hasChildren > .treeLabelCell > .treeLabel:hover,
.theme-dark .treeTable .treeRow.hasChildren > .treeLabelCell > .treeLabel:hover {
color: var(--theme-highlight-pink);
}

Просмотреть файл

@ -26,13 +26,11 @@
}
#font-showall {
border-radius: 0;
border: 1px solid black;
margin: 3px;
cursor: pointer;
position: absolute;
bottom: 0;
offset-inline-end: 0;
}
#font-showall:hover {
text-decoration: underline;
}
.dim > #font-container,

Просмотреть файл

@ -10,6 +10,13 @@
0 0 0 0 0.79
0 0 0 1 0"/>
</filter>
<filter id="dark-theme-checked-icon-state">
<feColorMatrix in="SourceGraphic" type="matrix"
values="0 0 0 0 0
0 0 0 0 1
0 0 0 0 0.212
0 0 0 1 0"/>
</filter>
<!-- Web Audio Gradients -->
<linearGradient id="bypass-light" x1="6%" y1="8%" x2="12%" y2="12%" spreadMethod="repeat">

До

Ширина:  |  Высота:  |  Размер: 990 B

После

Ширина:  |  Высота:  |  Размер: 1.2 KiB

Просмотреть файл

@ -2,8 +2,6 @@
- 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/. -->
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fill="#0b0b0b">
<path fill-opacity=".3" d="M12 3h2v10h-2z"/>
<path d="M2 3.002v9.996c0-.004.006.002.007.002h11.986c.005 0 .007-.002.007-.002V3.002c0 .004-.006-.002-.007-.002H2.007C2.002 3 2 3.002 2 3.002zm-1 0C1 2.45 1.45 2 2.007 2h11.986A1.01 1.01 0 0 1 15 3.002v9.996C15 13.55 14.55 14 13.993 14H2.007A1.01 1.01 0 0 1 1 12.998V3.002zm10 .453V13h1V3h-1v.455z"/>
<path d="M5 10.25l3-1.875L5 6.5v3.75zm-1 0V6.5a1 1 0 0 1 1.53-.848l3 1.875a1 1 0 0 1 0 1.696l-3 1.875A1 1 0 0 1 4 10.25z"/>
<path fill-opacity=".3" d="M4.5 10.75V6L9 8.375z"/>
<path fill-opacity=".3" d="M12,3h2v10h-2V3z M5,9.9V6.1L8,8L5,9.9z"/>
<path d="M14,2H2C1.4,2,1,2.4,1,3v10c0,0.6,0.4,1,1,1h12c0.6,0,1-0.4,1-1V3C15,2.4,14.6,2,14,2z M2,13L2,13V3h0h9v10 H2L2,13z M14,13C14,13,14,13,14,13h-2V3h2c0,0,0,0,0,0V13z M8.5,7.2l-3-1.9C4.6,4.7,4,5,4,6.1v3.8c0,1.1,0.6,1.4,1.5,0.8l3-1.9 C9.5,8.3,9.5,7.8,8.5,7.2z M5,9.9V6.1L8,8L5,9.9z"/>
</svg>

До

Ширина:  |  Высота:  |  Размер: 858 B

После

Ширина:  |  Высота:  |  Размер: 689 B

Просмотреть файл

@ -2,8 +2,6 @@
- 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/. -->
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fill="#0b0b0b">
<path fill-opacity=".3" d="M12 3h2v10h-2z"/>
<path d="M2 3.002v9.996c0-.004.006.002.007.002h11.986c.005 0 .007-.002.007-.002V3.002c0 .004-.006-.002-.007-.002H2.007C2.002 3 2 3.002 2 3.002zm-1 0C1 2.45 1.45 2 2.007 2h11.986A1.01 1.01 0 0 1 15 3.002v9.996C15 13.55 14.55 14 13.993 14H2.007A1.01 1.01 0 0 1 1 12.998V3.002zm10 .453V13h1V3h-1v.455z"/>
<path d="M8 6.5L5 8.375l3 1.875V6.5zm1 0v3.75a1 1 0 0 1-1.53.848l-3-1.875a1 1 0 0 1 0-1.696l3-1.875A1 1 0 0 1 9 6.5z"/>
<path fill-opacity=".3" d="M8.5 6v4.75L4 8.375z"/>
<path fill-opacity=".3" d="M4,13H2V3h2V13z M11,6.1v3.8L8,8L11,6.1z"/>
<path d="M2,14h12c0.6,0,1-0.4,1-1V3c0-0.6-0.4-1-1-1H2C1.4,2,1,2.4,1,3v10C1,13.6,1.4,14,2,14z M14,3L14,3v10h0H5V3 H14L14,3z M2,3C2,3,2,3,2,3h2v10H2c0,0,0,0,0,0V3z M7.5,8.8l3,1.9c1,0.6,1.5,0.3,1.5-0.8V6.1c0-1.1-0.6-1.4-1.5-0.8l-3,1.9 C6.5,7.7,6.5,8.2,7.5,8.8z M11,6.1v3.8L8,8L11,6.1z"/>
</svg>

До

Ширина:  |  Высота:  |  Размер: 853 B

После

Ширина:  |  Высота:  |  Размер: 688 B

Просмотреть файл

@ -167,6 +167,10 @@
list-style-image: url("chrome://devtools/skin/images/close.svg");
}
.devtools-responsiveui-close > image {
filter: invert(1);
}
.devtools-responsiveui-rotate {
list-style-image: url("chrome://devtools/skin/images/responsivemode/responsiveui-rotate.png");
}

Просмотреть файл

@ -30,7 +30,7 @@
--filter-image: url(images/filter.svg);
--tool-options-image: url(images/tool-options.svg);
--icon-filter: invert(1);
--checked-icon-filter: url(images/filters.svg#checked-icon-state);
--checked-icon-filter: url(images/filters.svg#dark-theme-checked-icon-state);
--toolbar-button-border-color: rgba(0, 0, 0, .4);
}

Просмотреть файл

@ -72,8 +72,14 @@ add_task(function* () {
is(hud.outputNode.textContent.indexOf("Permission denied"), -1,
"no permission denied errors");
// Navigation clears messages. Wait for that clear to happen before
// continuing the test or it might destroy messages we wait later on (Bug
// 1270234).
let cleared = hud.jsterm.once("messages-cleared");
gBrowser.goBack();
info("Waiting for page to navigate");
yield waitForSuccess({
name: "go back",
validator: function () {
@ -81,10 +87,11 @@ add_task(function* () {
},
});
hud.jsterm.clearOutput();
executeSoon(() => {
hud.jsterm.execute("window.location.href");
});
info("Waiting for messages to be cleared due to navigation");
yield cleared;
info("Messages cleared after navigation; checking location");
hud.jsterm.execute("window.location.href");
info("wait for window.location.href after goBack()");
yield waitForMessages(msgForLocation1);

Просмотреть файл

@ -130,7 +130,7 @@ This will generate a request handler whose request and response packets look lik
The client usage should be predictable:
echo.echo("hello").then(str => { assert(str === "hello... hello...") })
hello.echo("hello").then(str => { assert(str === "hello... hello...") })
The library tries hard to make using fronts feel like natural javascript (or as natural as you believe promises are, I guess). When building the response it will put the return value of the function where RetVal() is specified in the response template, and on the client side it will use the value in that position when resolving the promise.

Просмотреть файл

@ -0,0 +1,6 @@
<!DOCTYPE html>
<html>
<body>
Frame A
</body>
</html>

Просмотреть файл

@ -0,0 +1,6 @@
<!DOCTYPE html>
<html>
<body>
Frame A navigated by Frame B
</body>
</html>

Просмотреть файл

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<body>
Frame B navigating Frame A
<script type="text/javascript">
window.open("file_triggeringprincipal_iframe_iframe_window_open_frame_a_nav.html", "framea");
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,6 @@
<!DOCTYPE html>
<html>
<body>
base test frame
</body>
</html>

Просмотреть файл

@ -0,0 +1,6 @@
<!DOCTYPE html>
<html>
<body>
navigated by window.open()
</body>
</html>

Просмотреть файл

@ -0,0 +1,6 @@
<!DOCTYPE html>
<html>
<body>
http
</body>
</html>

Просмотреть файл

@ -26,7 +26,13 @@ support-files =
file_triggeringprincipal_frame_2.html
file_triggeringprincipal_subframe.html
file_triggeringprincipal_subframe_nav.html
file_triggeringprincipal_window_open.html
file_triggeringprincipal_parent_iframe_window_open_base.html
file_triggeringprincipal_parent_iframe_window_open_nav.html
file_triggeringprincipal_iframe_iframe_window_open_frame_a.html
file_triggeringprincipal_iframe_iframe_window_open_frame_b.html
file_triggeringprincipal_iframe_iframe_window_open_frame_a_nav.html
[test_bug13871.html]
skip-if = buildapp == 'b2g' || buildapp == 'mulet' || toolkit == 'android' #RANDOM # Bug 1136180 disabled on B2G Desktop and Mulet for intermittent failures
[test_bug270414.html]
@ -53,3 +59,6 @@ skip-if = (buildapp == 'b2g' && debug) || toolkit == 'android' #RANDOM # b2g-deb
[test_sibling-matching-parent.html]
[test_sibling-off-domain.html]
[test_triggeringprincipal_frame_nav.html]
[test_triggeringprincipal_window_open.html]
[test_triggeringprincipal_parent_iframe_window_open.html]
[test_triggeringprincipal_iframe_iframe_window_open.html]

Просмотреть файл

@ -0,0 +1,87 @@
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script type="text/javascript" src="NavigationUtils.js"></script>
</head>
<body>
<iframe name="framea" id="framea" src="file_triggeringprincipal_iframe_iframe_window_open_frame_a.html"></iframe>
<iframe name="frameb" id="frameb"></iframe>
<script type="text/javascript">
/* We load an iframe (Frame A) which then gets navigated by another iframe (Frame B)
* by calling window.open("http://", "Frame A") later in the test. We then verify the
* TriggeringPrincipal and LoadingPrincipal of the navigated iframe (Frame A).
*
* +---------------------------------------+
* | Parent |
* | |
* | +----------------------------+ |
* | | Frame A | |
* | | | |
* | | | |
* | +----------------------------+ |
* | |
* | +----------------------------+ |
* | | Frame B | |
* | | | |
* | | win.open("http://", "A") | |
* | +----------------------------+ |
* | |
* +---------------------------------------+
*
* Sequence of the test:
* [1] load Frame A
* [2] load Frame B which navigates A
* [3] load navigated Frame A and check triggeringPrincipal and loadingPrincipal
*/
const TRIGGERING_PRINCIPAL_URI =
"http://mochi.test:8888/tests/docshell/test/navigation/file_triggeringprincipal_iframe_iframe_window_open_frame_b.html";
const LOADING_PRINCIPAL_URI =
"http://mochi.test:8888/tests/docshell/test/navigation/test_triggeringprincipal_iframe_iframe_window_open.html";
var frameA = document.getElementById("framea");
function checkResults() {
frameA.removeEventListener('load', checkResults, false);
var channel = SpecialPowers.wrap(frameA.contentDocument).docShell.currentDocumentChannel;
var triggeringPrincipal = channel.loadInfo.triggeringPrincipal.URI.asciiSpec;
var loadingPrincipal = channel.loadInfo.loadingPrincipal.URI.asciiSpec;
is(triggeringPrincipal, TRIGGERING_PRINCIPAL_URI,
"TriggeringPrincipal for targeted window.open() should be the iframe triggering the load");
is(frameA.contentDocument.referrer, TRIGGERING_PRINCIPAL_URI,
"Referrer for targeted window.open() should be the principal of the iframe triggering the load");
is(loadingPrincipal, LOADING_PRINCIPAL_URI,
"LoadingPrincipal for targeted window.open() should be the containing document");
SimpleTest.finish();
}
function performNavigation() {
frameA.removeEventListener('load', performNavigation, false);
frameA.addEventListener('load', checkResults, false);
// load Frame B which then navigates Frame A
var frameB = document.getElementById("frameb");
frameB.src = "file_triggeringprincipal_iframe_iframe_window_open_frame_b.html";
}
// start the test
SimpleTest.waitForExplicitFinish();
frameA.addEventListener('load', performNavigation, false);
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -0,0 +1,70 @@
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script type="text/javascript" src="NavigationUtils.js"></script>
</head>
<body>
<iframe name="testframe" id="testframe" src="file_triggeringprincipal_iframe_iframe_window_open_base.html"></iframe>
<script type="text/javascript">
/* We load an iframe which then gets navigated by the iframe's parent by calling
* window.open("http://", iframe) later in the test. We then verify the
* TriggeringPrincipal and LoadingPrincipal of the navigated iframe.
*
* +------------------------------------------+
* | |
* | +------------------+ |
* | | testframe | |
* | +------------------+ |
* | |
* | window.open("http://", "testframe"); |
* | |
* +------------------------------------------+
*/
const TRIGGERING_PRINCIPAL_URI =
"http://mochi.test:8888/tests/docshell/test/navigation/test_triggeringprincipal_parent_iframe_window_open.html";
const LOADING_PRINCIPAL_URI = TRIGGERING_PRINCIPAL_URI;
var testframe = document.getElementById("testframe");
function checkResults() {
testframe.removeEventListener('load', checkResults, false);
var channel = SpecialPowers.wrap(testframe.contentDocument).docShell.currentDocumentChannel;
var triggeringPrincipal = channel.loadInfo.triggeringPrincipal.URI.asciiSpec;
var loadingPrincipal = channel.loadInfo.loadingPrincipal.URI.asciiSpec;
is(triggeringPrincipal, TRIGGERING_PRINCIPAL_URI,
"TriggeringPrincipal for targeted window.open() should be the principal of the document");
is(testframe.contentDocument.referrer, TRIGGERING_PRINCIPAL_URI,
"Referrer for targeted window.open() should be the principal of the document");
is(loadingPrincipal, LOADING_PRINCIPAL_URI,
"LoadingPrincipal for targeted window.open() should be the <iframe>.ownerDocument");
SimpleTest.finish();
}
function performNavigation() {
testframe.removeEventListener('load', performNavigation, false);
testframe.addEventListener('load', checkResults, false);
win = window.open("file_triggeringprincipal_parent_iframe_window_open_nav.html", "testframe");
}
// start the test
SimpleTest.waitForExplicitFinish();
testframe.addEventListener('load', performNavigation, false);
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -0,0 +1,101 @@
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script type="text/javascript" src="NavigationUtils.js"></script>
</head>
<body>
<script type="text/javascript">
/* We call window.open() using different URIs and make sure the triggeringPrincipal
* loadingPrincipal are correct.
* Test1: window.open(http:)
* Test2: window.open(data:)
* Test3: window.open(javascript:)
*/
const TRIGGERING_PRINCIPAL_URI =
"http://mochi.test:8888/tests/docshell/test/navigation/test_triggeringprincipal_window_open.html";
SimpleTest.waitForExplicitFinish();
const NUM_TESTS = 3;
var test_counter = 0;
function checkFinish() {
test_counter++;
if (test_counter === NUM_TESTS) {
SimpleTest.finish();
}
}
// ----------------------------------------------------------------------------
// Test 1: window.open(http:)
var httpWin = window.open("file_triggeringprincipal_window_open.html", "_blank", "width=10,height=10");
httpWin.onload = function() {
var httpChannel = SpecialPowers.wrap(httpWin.document).docShell.currentDocumentChannel;
var httpTriggeringPrincipal = httpChannel.loadInfo.triggeringPrincipal.URI.asciiSpec;
var httpLoadingPrincipal = httpChannel.loadInfo.loadingPrincipal;
is(httpTriggeringPrincipal, TRIGGERING_PRINCIPAL_URI,
"TriggeringPrincipal for window.open(http:) should be the principal of the document");
is(httpWin.document.referrer, TRIGGERING_PRINCIPAL_URI,
"Referrer for window.open(http:) should be the principal of the document");
is(httpLoadingPrincipal, null,
"LoadingPrincipal for window.open(http:) should be null");
httpWin.close();
checkFinish();
}
// ----------------------------------------------------------------------------
// Test 2: window.open(data:)
var dataWin = window.open("data:text/html,<html><body>data</body></html>", "_blank", "width=10,height=10");
dataWin.onload = function() {
var dataChannel = SpecialPowers.wrap(dataWin.document).docShell.currentDocumentChannel;
var dataTriggeringPrincipal = dataChannel.loadInfo.triggeringPrincipal.URI.asciiSpec;
var dataLoadingPrincipal = dataChannel.loadInfo.loadingPrincipal;
is(dataTriggeringPrincipal, TRIGGERING_PRINCIPAL_URI,
"TriggeringPrincipal for window.open(data:) should be the principal of the document");
is(dataWin.document.referrer, "",
"Referrer for window.open(data:) should be empty");
is(dataLoadingPrincipal, null,
"LoadingPrincipal for window.open(data:) should be null");
dataWin.close();
checkFinish();
}
// ----------------------------------------------------------------------------
// Test 3: window.open(javascript:)
var jsWin = window.open("javascript:'<html><body>js</body></html>';", "_blank", "width=10,height=10");
jsWin.onload = function() {
var jsChannel = SpecialPowers.wrap(jsWin.document).docShell.currentDocumentChannel;
var jsTriggeringPrincipal = jsChannel.loadInfo.triggeringPrincipal.URI.asciiSpec;
var jsLoadingPrincipal = jsChannel.loadInfo.loadingPrincipal;
is(jsTriggeringPrincipal, TRIGGERING_PRINCIPAL_URI,
"TriggeringPrincipal for window.open(javascript:) should be the principal of the document");
is(jsWin.document.referrer, "",
"Referrer for window.open(javascript:) should be empty");
is(jsLoadingPrincipal, null,
"LoadingPrincipal for window.open(javascript:) should be null");
jsWin.close();
checkFinish();
}
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -60,6 +60,9 @@ PostMessageEvent::Run()
MOZ_ASSERT(!mSource || mSource->IsOuterWindow(),
"should have been passed an outer window!");
// Note: We don't init this AutoJSAPI with targetWindow, because we do not
// want exceptions during message deserialization to trigger error events on
// targetWindow.
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
@ -81,7 +84,7 @@ PostMessageEvent::Run()
MOZ_ASSERT(targetWindow->IsInnerWindow(),
"we ordered an inner window!");
JSAutoCompartment ac(cx, targetWindow->GetWrapperPreserveColor());
JSAutoCompartment ac(cx, targetWindow->GetWrapper());
// Ensure that any origin which might have been provided is the origin of this
// window's document. Note that we do this *now* instead of when postMessage

Просмотреть файл

@ -1718,7 +1718,7 @@ nsAttrValue::LoadImage(nsIDocument* aDocument)
bool
nsAttrValue::ParseStyleAttribute(const nsAString& aString,
nsStyledElementNotElementCSSInlineStyle* aElement)
nsStyledElement* aElement)
{
nsIDocument* ownerDoc = aElement->OwnerDoc();
nsHTMLCSSStyleSheet* sheet = ownerDoc->GetInlineStyleSheet();

Просмотреть файл

@ -30,7 +30,7 @@
class nsAString;
class nsIDocument;
class nsStyledElementNotElementCSSInlineStyle;
class nsStyledElement;
struct MiscContainer;
struct ServoDeclarationBlock;
@ -392,7 +392,7 @@ public:
* @param aElement the element the attribute is set on.
*/
bool ParseStyleAttribute(const nsAString& aString,
nsStyledElementNotElementCSSInlineStyle* aElement);
nsStyledElement* aElement);
size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;

Просмотреть файл

@ -19,6 +19,7 @@
#include "nsIDOMRange.h"
#include "nsRange.h"
#include "imgIContainer.h"
#include "imgIRequest.h"
#include "nsIPresShell.h"
#include "nsFocusManager.h"
#include "mozilla/dom/DataTransfer.h"
@ -47,6 +48,16 @@
#include "nsContentUtils.h"
#include "nsContentCID.h"
#ifdef XP_WIN
#include "nsCExternalHandlerService.h"
#include "nsEscape.h"
#include "nsIMimeInfo.h"
#include "nsIMIMEService.h"
#include "nsIURL.h"
#include "nsReadableUtils.h"
#include "nsXULAppAPI.h"
#endif
#include "mozilla/ContentEvents.h"
#include "mozilla/dom/Element.h"
#include "mozilla/EventDispatcher.h"
@ -72,6 +83,13 @@ static nsresult AppendString(nsITransferable *aTransferable,
static nsresult AppendDOMNode(nsITransferable *aTransferable,
nsINode* aDOMNode);
#ifdef XP_WIN
// copy image as file promise onto the transferable
static nsresult AppendImagePromise(nsITransferable* aTransferable,
imgIRequest* aImgRequest,
nsIImageLoadingContent* aImageElement);
#endif
// Helper used for HTMLCopy and GetTransferableForSelection since both routines
// share common code.
static nsresult
@ -439,11 +457,18 @@ nsCopySupport::ImageCopy(nsIImageLoadingContent* aImageElement,
}
if (aCopyFlags & nsIContentViewerEdit::COPY_IMAGE_DATA) {
// get the image data from the element
// get the image data and its request from the element
nsCOMPtr<imgIRequest> imgRequest;
nsCOMPtr<imgIContainer> image =
nsContentUtils::GetImageFromContent(aImageElement);
nsContentUtils::GetImageFromContent(aImageElement,
getter_AddRefs(imgRequest));
NS_ENSURE_TRUE(image, NS_ERROR_FAILURE);
#ifdef XP_WIN
rv = AppendImagePromise(trans, imgRequest, aImageElement);
NS_ENSURE_SUCCESS(rv, rv);
#endif
nsCOMPtr<nsISupportsInterfacePointer>
imgPtr(do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID, &rv));
NS_ENSURE_SUCCESS(rv, rv);
@ -545,6 +570,91 @@ static nsresult AppendDOMNode(nsITransferable *aTransferable,
return AppendString(aTransferable, context, kHTMLContext);
}
#ifdef XP_WIN
static nsresult AppendImagePromise(nsITransferable* aTransferable,
imgIRequest* aImgRequest,
nsIImageLoadingContent* aImageElement)
{
nsresult rv;
NS_ENSURE_TRUE(aImgRequest, NS_OK);
nsCOMPtr<nsINode> node = do_QueryInterface(aImageElement, &rv);
NS_ENSURE_SUCCESS(rv, rv);
// Fix the file extension in the URL if necessary
nsCOMPtr<nsIMIMEService> mimeService =
do_GetService(NS_MIMESERVICE_CONTRACTID);
NS_ENSURE_TRUE(mimeService, NS_OK);
nsCOMPtr<nsIURI> imgUri;
rv = aImgRequest->GetCurrentURI(getter_AddRefs(imgUri));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIURL> imgUrl = do_QueryInterface(imgUri);
NS_ENSURE_TRUE(imgUrl, NS_OK);
nsAutoCString extension;
rv = imgUrl->GetFileExtension(extension);
NS_ENSURE_SUCCESS(rv, rv);
nsXPIDLCString mimeType;
rv = aImgRequest->GetMimeType(getter_Copies(mimeType));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIMIMEInfo> mimeInfo;
mimeService->GetFromTypeAndExtension(mimeType, EmptyCString(),
getter_AddRefs(mimeInfo));
NS_ENSURE_TRUE(mimeInfo, NS_OK);
nsAutoCString spec;
rv = imgUrl->GetSpec(spec);
NS_ENSURE_SUCCESS(rv, rv);
// pass out the image source string
nsString imageSourceString;
CopyUTF8toUTF16(spec, imageSourceString);
bool validExtension;
if (extension.IsEmpty() ||
NS_FAILED(mimeInfo->ExtensionExists(extension,
&validExtension)) ||
!validExtension) {
// Fix the file extension in the URL
rv = imgUrl->Clone(getter_AddRefs(imgUri));
NS_ENSURE_SUCCESS(rv, rv);
imgUrl = do_QueryInterface(imgUri);
nsAutoCString primaryExtension;
mimeInfo->GetPrimaryExtension(primaryExtension);
imgUrl->SetFileExtension(primaryExtension);
}
nsAutoCString fileName;
imgUrl->GetFileName(fileName);
NS_UnescapeURL(fileName);
// make the filename safe for the filesystem
fileName.ReplaceChar(FILE_PATH_SEPARATOR FILE_ILLEGAL_CHARACTERS, '-');
nsString imageDestFileName;
CopyUTF8toUTF16(fileName, imageDestFileName);
rv = AppendString(aTransferable, imageSourceString, kFilePromiseURLMime);
NS_ENSURE_SUCCESS(rv, rv);
rv = AppendString(aTransferable, imageDestFileName, kFilePromiseDestFilename);
NS_ENSURE_SUCCESS(rv, rv);
aTransferable->SetRequestingPrincipal(node->NodePrincipal());
// add the dataless file promise flavor
return aTransferable->AddDataFlavor(kFilePromiseMime);
}
#endif // XP_WIN
nsIContent*
nsCopySupport::GetSelectionForCopy(nsIDocument* aDocument, nsISelection** aSelection)
{

Просмотреть файл

@ -1572,6 +1572,7 @@ GK_ATOM(stroke_width, "stroke-width")
GK_ATOM(strokeWidth, "strokeWidth")
GK_ATOM(surfaceScale, "surfaceScale")
GK_ATOM(svg, "svg")
GK_ATOM(svgContextPaint, "svgContextPaint")
GK_ATOM(svgSwitch, "switch")
GK_ATOM(symbol, "symbol")
GK_ATOM(systemLanguage, "systemLanguage")

Просмотреть файл

@ -1072,7 +1072,7 @@ nsOuterWindowProxy::GetSubframeWindow(JSContext *cx,
if (MOZ_UNLIKELY(!obj)) {
return xpc::Throw(cx, NS_ERROR_FAILURE);
}
JS::ExposeObjectToActiveJS(obj);
vp.setObject(*obj);
return JS_WrapValue(cx, vp);
}

Просмотреть файл

@ -57,7 +57,8 @@ public:
// it stops doing that, please simplify the code in FindAssociatedGlobal in
// BindingUtils.h that does JS::ExposeObjectToActiveJS on the return value of
// GetGlobalJSObject. Also, in that case the JS::ExposeObjectToActiveJS in
// AutoJSAPI::InitInternal can probably be removed.
// AutoJSAPI::InitInternal can probably be removed. And also the similar
// calls in XrayWrapper and nsGlobalWindow.
virtual JSObject* GetGlobalJSObject() = 0;
// This method is not meant to be overridden.

Просмотреть файл

@ -25,14 +25,18 @@
using namespace mozilla;
using namespace mozilla::dom;
NS_IMPL_QUERY_INTERFACE_INHERITED(nsStyledElement,
nsStyledElementBase,
nsStyledElement)
//----------------------------------------------------------------------
// nsIContent methods
bool
nsStyledElementNotElementCSSInlineStyle::ParseAttribute(int32_t aNamespaceID,
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult)
nsStyledElement::ParseAttribute(int32_t aNamespaceID,
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult)
{
if (aAttribute == nsGkAtoms::style && aNamespaceID == kNameSpaceID_None) {
SetMayHaveStyle();
@ -45,9 +49,9 @@ nsStyledElementNotElementCSSInlineStyle::ParseAttribute(int32_t aNamespaceID,
}
nsresult
nsStyledElementNotElementCSSInlineStyle::SetInlineStyleDeclaration(css::Declaration* aDeclaration,
const nsAString* aSerialized,
bool aNotify)
nsStyledElement::SetInlineStyleDeclaration(css::Declaration* aDeclaration,
const nsAString* aSerialized,
bool aNotify)
{
SetMayHaveStyle();
bool modification = false;
@ -90,7 +94,7 @@ nsStyledElementNotElementCSSInlineStyle::SetInlineStyleDeclaration(css::Declarat
}
css::Declaration*
nsStyledElementNotElementCSSInlineStyle::GetInlineStyleDeclaration()
nsStyledElement::GetInlineStyleDeclaration()
{
if (!MayHaveStyle()) {
return nullptr;
@ -108,7 +112,7 @@ nsStyledElementNotElementCSSInlineStyle::GetInlineStyleDeclaration()
// Others and helpers
nsICSSDeclaration*
nsStyledElementNotElementCSSInlineStyle::Style()
nsStyledElement::Style()
{
Element::nsDOMSlots *slots = DOMSlots();
@ -124,7 +128,7 @@ nsStyledElementNotElementCSSInlineStyle::Style()
}
nsresult
nsStyledElementNotElementCSSInlineStyle::ReparseStyleAttribute(bool aForceInDataDoc)
nsStyledElement::ReparseStyleAttribute(bool aForceInDataDoc)
{
if (!MayHaveStyle()) {
return NS_OK;
@ -151,9 +155,9 @@ nsStyledElementNotElementCSSInlineStyle::ReparseStyleAttribute(bool aForceInData
}
void
nsStyledElementNotElementCSSInlineStyle::ParseStyleAttribute(const nsAString& aValue,
nsAttrValue& aResult,
bool aForceInDataDoc)
nsStyledElement::ParseStyleAttribute(const nsAString& aValue,
nsAttrValue& aResult,
bool aForceInDataDoc)
{
nsIDocument* doc = OwnerDoc();
bool isNativeAnon = IsInNativeAnonymousSubtree();

Просмотреть файл

@ -23,18 +23,28 @@ class Declaration;
} // namespace css
} // namespace mozilla
// IID for nsStyledElement interface
#define NS_STYLED_ELEMENT_IID \
{ 0xacbd9ea6, 0x15aa, 0x4f37, \
{ 0x8c, 0xe0, 0x35, 0x1e, 0xd7, 0x21, 0xca, 0xe9 } }
typedef mozilla::dom::Element nsStyledElementBase;
class nsStyledElementNotElementCSSInlineStyle : public nsStyledElementBase
class nsStyledElement : public nsStyledElementBase
{
protected:
inline explicit nsStyledElementNotElementCSSInlineStyle(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
inline explicit nsStyledElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
: nsStyledElementBase(aNodeInfo)
{}
public:
// We don't want to implement AddRef/Release because that would add an extra
// function call for those on pretty much all elements. But we do need QI, so
// we can QI to nsStyledElement.
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
// Element interface methods
virtual mozilla::css::Declaration* GetInlineStyleDeclaration() override;
virtual nsresult SetInlineStyleDeclaration(mozilla::css::Declaration* aDeclaration,
@ -43,6 +53,8 @@ public:
nsICSSDeclaration* Style();
NS_DECLARE_STATIC_IID_ACCESSOR(NS_STYLED_ELEMENT_IID)
protected:
/**
@ -70,11 +82,5 @@ protected:
nsresult ReparseStyleAttribute(bool aForceInDataDoc);
};
class nsStyledElement : public nsStyledElementNotElementCSSInlineStyle {
protected:
inline explicit nsStyledElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
: nsStyledElementNotElementCSSInlineStyle(aNodeInfo)
{}
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsStyledElement, NS_STYLED_ELEMENT_IID)
#endif // __NS_STYLEDELEMENT_H_

Просмотреть файл

@ -9,10 +9,11 @@
#include <algorithm>
#include <stdarg.h>
#include "mozilla/Assertions.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/FloatingPoint.h"
#include "mozilla/Assertions.h"
#include "mozilla/Preferences.h"
#include "mozilla/SizePrintfMacros.h"
#include "mozilla/unused.h"
#include "mozilla/UseCounter.h"
@ -2532,7 +2533,7 @@ ConvertJSValueToByteString(JSContext* cx, JS::Handle<JS::Value> v,
// 20 digits, plus one more for the null terminator.
char index[21];
static_assert(sizeof(size_t) <= 8, "index array too small");
snprintf_literal(index, "%d", badCharIndex);
snprintf_literal(index, "%" PRIuSIZE, badCharIndex);
// A char16_t is 16 bits long. The biggest unsigned 16 bit
// number (65,535) has 5 digits, plus one more for the null
// terminator.

Просмотреть файл

@ -190,6 +190,10 @@ EVENT(dragenter,
eDragEnter,
EventNameType_HTMLXUL,
eDragEventClass)
EVENT(dragexit,
eDragExit,
EventNameType_HTMLXUL,
eDragEventClass)
EVENT(dragleave,
eDragLeave,
EventNameType_HTMLXUL,
@ -778,10 +782,6 @@ NON_IDL_EVENT(commandupdate,
eXULCommandUpdate,
EventNameType_XUL,
eBasicEventClass)
NON_IDL_EVENT(dragexit,
eDragExit,
EventNameType_XUL,
eDragEventClass)
NON_IDL_EVENT(overflow,
eScrollPortOverflow,
EventNameType_XUL,

Просмотреть файл

@ -381,11 +381,7 @@ HTMLButtonElement::PostHandleEvent(EventChainPostVisitor& aVisitor)
// Using presShell to dispatch the event. It makes sure that
// event is not handled if the window is being destroyed.
if (presShell && (event.mMessage != eFormSubmit ||
mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate) ||
// We know the element is a submit control, if this check is moved,
// make sure formnovalidate is used only if it's a submit control.
HasAttr(kNameSpaceID_None, nsGkAtoms::formnovalidate) ||
mForm->CheckValidFormSubmission())) {
mForm->SubmissionCanProceed(this))) {
// TODO: removing this code and have the submit event sent by the form
// see bug 592124.
// Hold a strong ref while dispatching

Просмотреть файл

@ -1932,14 +1932,6 @@ HTMLFormElement::CheckValidFormSubmission()
NS_ASSERTION(!HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate),
"We shouldn't be there if novalidate is set!");
// Don't do validation for a form submit done by a sandboxed document that
// doesn't have 'allow-forms', the submit will have been blocked and the
// HTML5 spec says we shouldn't validate in this case.
nsIDocument* doc = GetComposedDoc();
if (doc && (doc->GetSandboxFlags() & SANDBOXED_FORMS)) {
return true;
}
// When .submit() is called aEvent = nullptr so we can rely on that to know if
// we have to check the validity of the form.
nsCOMPtr<nsIObserverService> service =
@ -2027,6 +2019,41 @@ One should be implemented!");
return true;
}
bool
HTMLFormElement::SubmissionCanProceed(Element* aSubmitter)
{
#ifdef DEBUG
if (aSubmitter) {
nsCOMPtr<nsIFormControl> fc = do_QueryInterface(aSubmitter);
MOZ_ASSERT(fc);
uint32_t type = fc->GetType();
MOZ_ASSERT(type == NS_FORM_INPUT_SUBMIT ||
type == NS_FORM_INPUT_IMAGE ||
type == NS_FORM_BUTTON_SUBMIT,
"aSubmitter is not a submit control?");
}
#endif
// Modified step 2 of
// https://html.spec.whatwg.org/multipage/forms.html#concept-form-submit --
// we're not checking whether the node document is disconnected yet...
if (OwnerDoc()->GetSandboxFlags() & SANDBOXED_FORMS) {
return false;
}
if (HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate)) {
return true;
}
if (aSubmitter &&
aSubmitter->HasAttr(kNameSpaceID_None, nsGkAtoms::formnovalidate)) {
return true;
}
return CheckValidFormSubmission();
}
void
HTMLFormElement::UpdateValidity(bool aElementValidity)
{

Просмотреть файл

@ -277,6 +277,15 @@ public:
*/
bool CheckValidFormSubmission();
/**
* Check whether submission can proceed for this form. This basically
* implements steps 1-4 (more or less) of
* <https://html.spec.whatwg.org/multipage/forms.html#concept-form-submit>.
* aSubmitter, if not null, is the "submitter" from that algorithm. Therefore
* it must be a valid submit control.
*/
bool SubmissionCanProceed(Element* aSubmitter);
/**
* Walk over the form elements and call SubmitNamesValues() on them to get
* their data pumped into the FormSubmitter.

Просмотреть файл

@ -3301,8 +3301,7 @@ HTMLInputElement::MaybeSubmitForm(nsPresContext* aPresContext)
nsEventStatus status = nsEventStatus_eIgnore;
shell->HandleDOMEventWithTarget(submitContent, &event, &status);
} else if (!mForm->ImplicitSubmissionIsDisabled() &&
(mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate) ||
mForm->CheckValidFormSubmission())) {
mForm->SubmissionCanProceed(nullptr)) {
// TODO: removing this code and have the submit event sent by the form,
// bug 592124.
// If there's only one text control, just submit the form
@ -4569,11 +4568,7 @@ HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor)
// TODO: removing this code and have the submit event sent by the
// form, see bug 592124.
if (presShell && (event.mMessage != eFormSubmit ||
mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate) ||
// We know the element is a submit control, if this check is moved,
// make sure formnovalidate is used only if it's a submit control.
HasAttr(kNameSpaceID_None, nsGkAtoms::formnovalidate) ||
mForm->CheckValidFormSubmission())) {
mForm->SubmissionCanProceed(this))) {
// Hold a strong ref while dispatching
RefPtr<mozilla::dom::HTMLFormElement> form(mForm);
presShell->HandleDOMEventWithTarget(mForm, &event, &status);

Просмотреть файл

@ -1885,6 +1885,28 @@ HTMLSelectElement::UpdateSelectedOptions()
}
}
bool
HTMLSelectElement::OpenInParentProcess()
{
nsIFormControlFrame* formControlFrame = GetFormControlFrame(false);
nsIComboboxControlFrame* comboFrame = do_QueryFrame(formControlFrame);
if (comboFrame) {
return comboFrame->IsOpenInParentProcess();
}
return false;
}
void
HTMLSelectElement::SetOpenInParentProcess(bool aVal)
{
nsIFormControlFrame* formControlFrame = GetFormControlFrame(false);
nsIComboboxControlFrame* comboFrame = do_QueryFrame(formControlFrame);
if (comboFrame) {
comboFrame->SetOpenInParentProcess(aVal);
}
}
JSObject*
HTMLSelectElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{

Просмотреть файл

@ -432,6 +432,9 @@ public:
return !Multiple() && Size() <= 1;
}
bool OpenInParentProcess();
void SetOpenInParentProcess(bool aVal);
protected:
virtual ~HTMLSelectElement();

Просмотреть файл

@ -28,7 +28,6 @@
#include "nsIDOMDocumentFragment.h"
#include "nsIDOMHTMLElement.h"
#include "nsIDOMHTMLMenuElement.h"
#include "nsIDOMElementCSSInlineStyle.h"
#include "nsIDOMWindow.h"
#include "nsIDOMDocument.h"
#include "nsMappedAttributes.h"
@ -167,43 +166,6 @@ private:
RefPtr<nsGenericHTMLElement> mElement;
};
class nsGenericHTMLElementTearoff : public nsIDOMElementCSSInlineStyle
{
virtual ~nsGenericHTMLElementTearoff()
{
}
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
explicit nsGenericHTMLElementTearoff(nsGenericHTMLElement* aElement)
: mElement(aElement)
{
}
NS_IMETHOD GetStyle(nsIDOMCSSStyleDeclaration** aStyle) override
{
NS_ADDREF(*aStyle = mElement->Style());
return NS_OK;
}
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsGenericHTMLElementTearoff,
nsIDOMElementCSSInlineStyle)
private:
RefPtr<nsGenericHTMLElement> mElement;
};
NS_IMPL_CYCLE_COLLECTION(nsGenericHTMLElementTearoff, mElement)
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsGenericHTMLElementTearoff)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsGenericHTMLElementTearoff)
NS_INTERFACE_TABLE_HEAD(nsGenericHTMLElementTearoff)
NS_INTERFACE_TABLE_INHERITED(nsGenericHTMLElementTearoff,
nsIDOMElementCSSInlineStyle)
NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsGenericHTMLElementTearoff)
NS_INTERFACE_MAP_END_AGGREGATED(mElement)
NS_IMPL_ADDREF_INHERITED(nsGenericHTMLElement, nsGenericHTMLElementBase)
NS_IMPL_RELEASE_INHERITED(nsGenericHTMLElement, nsGenericHTMLElementBase)
@ -211,8 +173,6 @@ NS_INTERFACE_MAP_BEGIN(nsGenericHTMLElement)
NS_INTERFACE_MAP_ENTRY(nsIDOMHTMLElement)
NS_INTERFACE_MAP_ENTRY(nsIDOMElement)
NS_INTERFACE_MAP_ENTRY(nsIDOMNode)
NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMElementCSSInlineStyle,
new nsGenericHTMLElementTearoff(this))
NS_INTERFACE_MAP_END_INHERITING(nsGenericHTMLElementBase)
nsresult

Просмотреть файл

@ -30,9 +30,7 @@ function getClassName(tag) {
function HTML_TAG(aTagName, aImplClass) {
allTags.push(aTagName);
classInfos[aTagName] = aImplClass;
interfaces[aTagName] =
[ "nsIDOMEventTarget",
"nsIDOMElementCSSInlineStyle" ];
interfaces[aTagName] = [ "nsIDOMEventTarget" ];
// Some interfaces don't appear in classinfo because other interfaces that
// inherit from them do.

Просмотреть файл

@ -27,7 +27,6 @@ XPIDL_SOURCES += [
'nsIDOMCSSUnknownRule.idl',
'nsIDOMCSSValue.idl',
'nsIDOMCSSValueList.idl',
'nsIDOMElementCSSInlineStyle.idl',
'nsIDOMRect.idl',
]

Просмотреть файл

@ -1,20 +0,0 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#include "domstubs.idl"
/**
* The nsIDOMElementCSSInlineStyle interface allows access to the inline
* style information for elements.
*
* For more information on this interface please see
* http://www.w3.org/TR/DOM-Level-2-Style
*/
[scriptable, uuid(99715845-95fc-4a56-aa53-214b65c26e22)]
interface nsIDOMElementCSSInlineStyle : nsISupports
{
readonly attribute nsIDOMCSSStyleDeclaration style;
};

Просмотреть файл

@ -2665,6 +2665,7 @@ ContentParent::RecvReadPermissions(InfallibleTArray<IPC::Permission>* aPermissio
bool
ContentParent::RecvSetClipboard(const IPCDataTransfer& aDataTransfer,
const bool& aIsPrivateData,
const IPC::Principal& aRequestingPrincipal,
const int32_t& aWhichClipboard)
{
nsresult rv;
@ -2730,6 +2731,7 @@ ContentParent::RecvSetClipboard(const IPCDataTransfer& aDataTransfer,
}
trans->SetIsPrivateData(aIsPrivateData);
trans->SetRequestingPrincipal(aRequestingPrincipal);
clipboard->SetData(trans, nullptr, aWhichClipboard);
return true;

Просмотреть файл

@ -958,6 +958,7 @@ private:
virtual bool RecvSetClipboard(const IPCDataTransfer& aDataTransfer,
const bool& aIsPrivateData,
const IPC::Principal& aRequestingPrincipal,
const int32_t& aWhichClipboard) override;
virtual bool RecvGetClipboard(nsTArray<nsCString>&& aTypes,

Просмотреть файл

@ -931,6 +931,7 @@ parent:
// Places the items within dataTransfer on the clipboard.
async SetClipboard(IPCDataTransfer aDataTransfer,
bool aIsPrivateData,
Principal aRequestingPrincipal,
int32_t aWhichClipboard);
// Given a list of supported types, returns the clipboard data for the

Просмотреть файл

@ -122,17 +122,16 @@ public:
{
MutexAutoLock lock(mMutex);
if (aReader->IsSuspended()) {
// Removing suspended readers has no immediate side-effects.
DebugOnly<bool> result = mSuspended.RemoveElement(aReader);
MOZ_ASSERT(result, "Suspended reader must be in mSuspended");
} else {
// Remove the reader from the queue. Note that the reader's IsSuspended
// state is updated on the task queue, so we cannot depend on it here to
// determine the factual suspension state.
DebugOnly<bool> suspended = mSuspended.RemoveElement(aReader);
bool active = mActive.RemoveElement(aReader);
MOZ_ASSERT(suspended || active, "Reader must be in the queue");
if (active && !mSuspended.IsEmpty()) {
// For each removed active reader, we resume a suspended one.
DebugOnly<bool> result = mActive.RemoveElement(aReader);
MOZ_ASSERT(result, "Non-suspended reader must be in mActive");
if (mSuspended.IsEmpty()) {
return;
}
MediaDecoderReader* resumeReader = mSuspended.LastElement();
mActive.AppendElement(resumeReader);
mSuspended.RemoveElementAt(mSuspended.Length() - 1);

Просмотреть файл

@ -460,6 +460,10 @@ MediaFormatReader::EnsureDecoderInitialized(TrackType aTrack)
if (decoder.mDecoderInitialized) {
return true;
}
if (IsSuspended()) {
return false;
}
RefPtr<MediaFormatReader> self = this;
decoder.mInitPromise.Begin(decoder.mDecoder->Init()
->Then(OwnerThread(), __func__,

Просмотреть файл

@ -39,19 +39,13 @@ UNIFIED_SOURCES += [
'ipc/MobileConnectionParent.cpp',
'MobileCallForwardingOptions.cpp',
'MobileCellInfo.cpp',
'MobileConnection.cpp',
'MobileConnectionArray.cpp',
'MobileConnectionCallback.cpp',
'MobileConnectionInfo.cpp',
'MobileNetworkInfo.cpp',
]
SOURCES += [
'MobileConnection.cpp', # Non-unified due to no_pgo
]
if CONFIG['_MSC_VER'] and CONFIG['CPU_ARCH'] == 'x86_64':
SOURCES['MobileConnection.cpp'].no_pgo = True # VS2013 crashes, bug 1084162
IPDL_SOURCES += [
'ipc/PMobileConnection.ipdl',
'ipc/PMobileConnectionRequest.ipdl',

Просмотреть файл

@ -116,7 +116,7 @@ TranslateVersionStr(const WCHAR* szVersion, verBlock *vbVersion)
szJavaBuild[0] = '.';
}
#if (defined(_MSC_VER) && _MSC_VER < 1900) || defined(__MINGW32__)
#if defined(__MINGW32__)
// MSVC 2013 and earlier provided only a non-standard two-argument variant of
// wcstok that is generally not thread-safe. For our purposes here, it works
// fine, though.
@ -125,6 +125,7 @@ TranslateVersionStr(const WCHAR* szVersion, verBlock *vbVersion)
return ::std::wcstok(strToken, strDelimit);
};
#endif
wchar_t* ctx = nullptr;
szNum1 = wcstok(strVer, L".", &ctx);
szNum2 = wcstok(nullptr, L".", &ctx);
@ -445,4 +446,3 @@ nsPluginDirServiceProvider::GetPLIDDirectoriesWithRootKey(uint32_t aKey, nsCOMAr
}
return NS_OK;
}

Просмотреть файл

@ -12,10 +12,10 @@
#include "gfx2DGlue.h"
#include "gfxMatrix.h"
#include "gfxPlatform.h"
#include "gfxSVGGlyphs.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/dom/SVGSVGElement.h"
#include "mozilla/RefPtr.h"
#include "mozilla/SVGContextPaint.h"
#include "nsComputedDOMStyle.h"
#include "nsFontMetrics.h"
#include "nsIFrame.h"
@ -73,7 +73,7 @@ static DashState
GetStrokeDashData(SVGContentUtils::AutoStrokeOptions* aStrokeOptions,
nsSVGElement* aElement,
const nsStyleSVG* aStyleSVG,
gfxTextContextPaint *aContextPaint)
SVGContextPaint* aContextPaint)
{
size_t dashArrayLength;
Float totalLengthOfDashes = 0.0, totalLengthOfGaps = 0.0;
@ -170,7 +170,7 @@ void
SVGContentUtils::GetStrokeOptions(AutoStrokeOptions* aStrokeOptions,
nsSVGElement* aElement,
nsStyleContext* aStyleContext,
gfxTextContextPaint *aContextPaint,
SVGContextPaint* aContextPaint,
StrokeOptionFlags aFlags)
{
RefPtr<nsStyleContext> styleContext;
@ -245,7 +245,7 @@ SVGContentUtils::GetStrokeOptions(AutoStrokeOptions* aStrokeOptions,
Float
SVGContentUtils::GetStrokeWidth(nsSVGElement* aElement,
nsStyleContext* aStyleContext,
gfxTextContextPaint *aContextPaint)
SVGContextPaint* aContextPaint)
{
RefPtr<nsStyleContext> styleContext;
if (aStyleContext) {

Просмотреть файл

@ -17,7 +17,6 @@
#include "nsStringFwd.h"
#include "gfx2DGlue.h"
class gfxTextContextPaint;
class nsIContent;
class nsIDocument;
class nsIFrame;
@ -28,6 +27,7 @@ class nsSVGElement;
namespace mozilla {
class nsSVGAnimatedTransformList;
class SVGAnimatedPreserveAspectRatio;
class SVGContextPaint;
class SVGPreserveAspectRatio;
namespace dom {
class Element;
@ -172,7 +172,7 @@ public:
static void GetStrokeOptions(AutoStrokeOptions* aStrokeOptions,
nsSVGElement* aElement,
nsStyleContext* aStyleContext,
gfxTextContextPaint *aContextPaint,
mozilla::SVGContextPaint* aContextPaint,
StrokeOptionFlags aFlags = eAllStrokeOptions);
/**
@ -186,7 +186,7 @@ public:
*/
static Float GetStrokeWidth(nsSVGElement* aElement,
nsStyleContext* aStyleContext,
gfxTextContextPaint *aContextPaint);
mozilla::SVGContextPaint* aContextPaint);
/*
* Get the number of CSS px (user units) per em (i.e. the em-height in user

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше