Merge mozilla-central to inbound. a=merge CLOSED TREE

This commit is contained in:
Narcis Beleuzu 2018-08-30 20:08:44 +03:00
commit 1e60ae6690
79 changed files with 8756 additions and 2971 deletions

View file

@ -90,7 +90,9 @@ class LinkHandlerChild extends ActorChild {
}
let rel = link.rel && link.rel.toLowerCase();
if (!rel || !link.href)
// We also check .getAttribute, since an empty href attribute will give us
// a link.href that is the same as the document.
if (!rel || !link.href || !link.getAttribute("href"))
return;
// Note: following booleans only work for the current link, not for the

View file

@ -1,5 +1,5 @@
<?xml version='1.0' encoding='UTF-8'?>
<blocklist lastupdate="1535153064735" xmlns="http://www.mozilla.org/2006/addons-blocklist">
<blocklist lastupdate="1535564772911" xmlns="http://www.mozilla.org/2006/addons-blocklist">
<emItems>
<emItem blockID="i334" id="{0F827075-B026-42F3-885D-98981EE7B1AE}">
<prefs/>
@ -2348,6 +2348,18 @@
<prefs/>
<versionRange minVersion="0" maxVersion="*" severity="3"/>
</emItem>
<emItem blockID="a0d44ee3-9492-47d7-ac1c-35f520e819ae" id="/^((Timemetric@tmetric)|(image-fastpicker@eight04.blogspot\.com)|(textMarkertool@underFlyingBirches\.org)|(youpanel@jetpack)|({0ff32ce0-dee9-4e7e-9260-65e58373e21d})|({4ca00873-7e8d-4ada-b460-96cad0eb8fa9})|({6b427f73-2ee1-4256-b69d-7dc253ebe030})|({6f13489d-b274-45b6-80fa-e9daa140e1a4})|({40a9d23b-09ef-4c82-ae1d-7fc5c067e987})|({205c2185-ebe4-4106-92ab-0ffa7c4efcbb})|({256ec7b0-57b4-416d-91c1-2bfdf01b2438})|({568db771-c718-4587-bcd0-e3728ee53550})|({5782a0f1-de26-42e5-a5b3-dae9ec05221b})|({9077390b-89a9-41ad-998f-ab973e37f26f})|({8e7269ac-a171-4d9f-9c0a-c504848fd52f})|({3e6586e2-7410-4f10-bba0-914abfc3a0b4})|({b3f06312-93c7-4a4f-a78b-f5defc185d8f})|({c1aee371-4401-4bab-937a-ceb15c2323c1})|({c579191c-6bb8-4795-adca-d1bf180b512d})|({d0aa0ad2-15ed-4415-8ef5-723f303c2a67})|({d8157e0c-bf39-42eb-a0c3-051ff9724a8c})|({e2a4966f-919d-4afc-a94f-5bd6e0606711})|({ee97f92d-1bfe-4e9d-816c-0dfcd63a6206}))$/">
<prefs/>
<versionRange minVersion="0" maxVersion="*" severity="3"/>
</emItem>
<emItem blockID="016676cc-c381-4c01-adcf-2d46f48142d0" id="/^((\{25211004-63e4-4a94-9c71-bdfeabb72bfe\})|(\{cbf23b92-ea55-4ca9-a5ae-f4197e286bc8\})|(\{7ac0550e-19cb-4d22-be12-b0b352144b33\})|(Mada111@mozilla\.com)|(\{c71709a9-af59-4958-a587-646c8c314c16\})|(\{6ac3f3b4-18db-4f69-a210-7babefd94b1e\})|(addon@fastsearch\.me)|(\{53d152fa-0ae0-47f1-97bf-c97ca3051562\})|(\{f9071611-24ee-472b-b106-f5e2f40bbe54\})|(\{972920f1-3bfd-4e99-b605-8688a94c3c85\})|(\{985afe98-fa74-4932-8026-4bdc880552ac\})|(\{d96a82f5-5d3e-46ed-945f-7c62c20b7644\})|(\{3a036dc5-c13b-499a-a62d-e18aab59d485\})|(\{49574957-56c6-4477-87f1-1ac7fa1b2299\})|(\{097006e8-9a95-4f7c-9c2f-59f20c61771c\})|(\{8619885d-0380-467a-b3fe-92a115299c32\})|(\{aa0587d6-4760-4abe-b3a1-2a5958f46775\})|(\{bdada7ae-cf89-46cf-b1fe-f3681f596278\})|(\{649bead3-df51-4023-8090-02ceb2f7095a\})|(\{097c3142-0b68-416a-9919-9dd576aedc17\})|(\{bc3cced8-51f0-4519-89ee-56706b67ea4b\})|(\{796da6e3-01c0-4c63-96dd-1737710b2ff6\}))$/">
<prefs/>
<versionRange minVersion="0" maxVersion="*" severity="3"/>
</emItem>
<emItem blockID="fcd12629-43df-4751-9654-7cc008f8f7c0" id="/^((fireAnalytics\.download@mozilla\.com)|(fireabsorb@mozilla\.com)|(fireaccent@mozilla\.com)|(fireaccept@mozilla\.com)|(fireads@mozilla\.com)|(firealerts@mozilla\.com)|(fireapi@mozilla\.com)|(fireapp@mozilla\.com)|(fireattribution@mozilla\.com)|(fireauthenticator@mozilla\.com)|(firecalendar@mozilla\.com)|(firemail@mozilla\.com)|(firemarketplace@mozilla\.com)|(firequestions@mozilla\.com)|(firescript@mozilla\.com)|(firesheets@mozilla\.com)|(firespam@mozilla\.com)|(firesuite@mozilla\.com)|(\{3b6dfc8f-e8ed-4b4c-b616-bdc8c526ac1d\})|(\{834f87db-0ff7-4518-89a0-0167a963a869\})|(\{4921fe4d-fbe6-4806-8eed-346d7aff7c75\})|(\{07809949-bd7d-40a6-a17b-19807448f77d\})|(\{68968617-cc8b-4c25-9c38-34646cdbe43e\})|(\{b8b2c0e1-f85d-4acd-aeb1-b6308a473874\})|(\{bc0b3499-f772-468e-9de6-b4aaf65d2bbb\}))$/">
<prefs/>
<versionRange minVersion="0" maxVersion="*" severity="3"/>
</emItem>
</emItems>
<pluginItems>
<pluginItem blockID="p332">

View file

@ -1886,6 +1886,9 @@ var gBrowserInit = {
if (this._boundDelayedStartup) {
this._cancelDelayedStartup();
} else {
if (Win7Features) {
Win7Features.onCloseWindow();
}
Services.prefs.removeObserver(ctrlTab.prefName, ctrlTab);
ctrlTab.uninit();
gBrowserThumbnails.uninit();
@ -2683,9 +2686,15 @@ function URLBarSetURI(aURI) {
valid = true;
}
let isDifferentValidValue = valid && value != gURLBar.value;
gURLBar.value = value;
gURLBar.valueIsTyped = !valid;
gURLBar.removeAttribute("usertyping");
if (isDifferentValidValue) {
// The selection is enforced only for new values, to avoid overriding the
// cursor position when the user switches windows while typing.
gURLBar.selectionStart = gURLBar.selectionEnd = 0;
}
SetPageProxyState(valid ? "valid" : "invalid");
}

View file

@ -26,6 +26,9 @@ support-files =
file_rich_icon.html
file_mask_icon.html
[browser_icon_discovery.js]
[browser_invalid_href_fallback.js]
support-files =
file_invalid_href.html
[browser_preferred_icons.js]
support-files =
icon.svg

View file

@ -0,0 +1,17 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
add_task(async () => {
const testPath = "http://example.com/browser/browser/base/content/test/favicons/";
const expectedIcon = "http://example.com/favicon.ico";
await BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" }, async (browser) => {
let faviconPromise = waitForLinkAvailable(browser);
BrowserTestUtils.loadURI(browser, testPath + "file_invalid_href.html");
await BrowserTestUtils.browserLoaded(browser);
let iconURI = await faviconPromise;
Assert.equal(iconURI, expectedIcon,
"Should have fallen back to the default site favicon for an invalid href attribute");
});
});

View file

@ -0,0 +1,12 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test file for bugs with invalid hrefs for favicons</title>
<!--Empty href; that's the whole point of this file.-->
<link rel="icon" href="">
</head>
<body>
Test file for bugs with invalid hrefs for favicons
</body>
</html>

View file

@ -151,7 +151,6 @@ support-files =
run-if = e10s
[browser_urlHighlight.js]
[browser_urlOverflow.js]
skip-if = true # Bug 1482557
[browser_wyciwyg_urlbarCopying.js]
subsuite = clipboard
support-files =

View file

@ -1,7 +1,7 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
add_task(async function() {
add_task(async function test_arrowRight() {
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:mozilla");
await promiseAutocompleteResultPopup("www.mozilla.org");
await waitForAutocompleteResultAt(0);
@ -19,3 +19,22 @@ add_task(async function() {
BrowserTestUtils.removeTab(tab);
});
add_task(async function test_windowSwitch() {
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:mozilla");
await promiseAutocompleteResultPopup("www.mozilla.org");
await waitForAutocompleteResultAt(0);
gURLBar.focus();
gURLBar.selectTextRange(4, 4);
let newWindow = await BrowserTestUtils.openNewBrowserWindow();
await BrowserTestUtils.closeWindow(newWindow);
Assert.equal(document.activeElement, gURLBar.inputField, "URL Bar should be focused");
is(gURLBar.selectionStart, 4, "Should not have moved the cursor");
is(gURLBar.selectionEnd, 4, "Should not have selected anything");
BrowserTestUtils.removeTab(tab);
});

View file

@ -4,9 +4,13 @@
async function testVal(aExpected, overflowSide = "") {
info(`Testing ${aExpected}`);
gURLBar.value = aExpected;
URLBarSetURI(makeURI(aExpected));
Assert.equal(gURLBar.selectionStart, gURLBar.selectionEnd,
"Selection sanity check");
gURLBar.focus();
Assert.equal(document.activeElement, gURLBar.inputField, "URL Bar should be focused");
Assert.equal(gURLBar.scheme.value, "", "Check the scheme value");
Assert.equal(getComputedStyle(gURLBar.scheme).visibility, "hidden",
"Check the scheme box visibility");
@ -22,8 +26,6 @@ async function testVal(aExpected, overflowSide = "") {
if (scheme == "http://" && Services.prefs.getBoolPref("browser.urlbar.trimURLs", true))
scheme = "";
Assert.equal(gURLBar.selectionStart, gURLBar.selectionEnd,
"Selection sanity check");
Assert.equal(gURLBar.scheme.value, scheme, "Check the scheme value");
let isOverflowed = gURLBar.inputField.scrollWidth > gURLBar.inputField.clientWidth;
Assert.equal(isOverflowed, !!overflowSide, "Check The input field overflow");
@ -39,8 +41,13 @@ async function testVal(aExpected, overflowSide = "") {
}
add_task(async function() {
// We use a new tab for the test to be sure all the tab switching and loading
// is complete before starting, otherwise onLocationChange for this tab could
// override the value we set with an empty value.
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
registerCleanupFunction(function() {
URLBarSetURI();
BrowserTestUtils.removeTab(tab);
});
let lotsOfSpaces = new Array(200).fill("%20").join("");

View file

@ -581,9 +581,9 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
}
// Make sure the host is always visible. Since it is aligned on
// the first strong directional character, we set the overflow
// appropriately.
this.selectionStart = this.selectionEnd = 0;
// the first strong directional character, we set scrollLeft
// appropriately to ensure the domain stays visible in case of an
// overflow.
window.requestAnimationFrame(() => {
// Check for re-entrance. On focus change this formatting code is
// invoked regardless, thus this should be enough.
@ -963,6 +963,11 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
this.handleRevert();
}
}
if (openUILinkWhere == "current") {
// Ensure the start of the URL is visible for usability reasons.
this.selectionStart = this.selectionEnd = 0;
}
]]></body>
</method>

View file

@ -224,7 +224,6 @@ skip-if = os == 'mac' # Save as PDF not supported on Mac OS X
[browser_ext_themes_icons.js]
[browser_ext_themes_validation.js]
[browser_ext_url_overrides_newtab.js]
skip-if = (os == 'linux' && debug) || (os == 'win' && debug) # Bug 1465508
[browser_ext_user_events.js]
[browser_ext_webRequest.js]
[browser_ext_webNavigation_frameId0.js]

View file

@ -309,10 +309,11 @@ add_task(async function test_new_tab_restore_settings() {
// Click the Restore Changes button.
let addonDisabled = waitForAddonDisabled(addon);
let popupHidden = promisePopupHidden(panel);
let locationChanged = BrowserTestUtils.waitForLocationChange(gBrowser, "about:newtab");
clickRestoreSettings(notification);
await popupHidden;
await addonDisabled;
await BrowserTestUtils.waitForLocationChange(gBrowser, "about:newtab");
await locationChanged;
// Ensure panel is closed, settings haven't changed and add-on is disabled.
ok(panel.getAttribute("panelopen") != "true",
@ -435,10 +436,11 @@ add_task(async function test_new_tab_restore_settings_multiple() {
addonDisabled = waitForAddonDisabled(addonOne);
popupHidden = promisePopupHidden(panel);
let locationChanged = BrowserTestUtils.waitForLocationChange(gBrowser, "about:newtab");
clickRestoreSettings(notification);
await popupHidden;
await addonDisabled;
await BrowserTestUtils.waitForLocationChange(gBrowser, "about:newtab");
await locationChanged;
ok(panel.getAttribute("panelopen") != "true",
"The notification panel is closed after restoring the second time");

View file

@ -65,7 +65,6 @@ async function run_drag_test(startBookmarkIndex, newParentGuid) {
let bookmarkWithId = JSON.stringify(Object.assign({
id: bookmarkId,
itemGuid: dragBookmark.guid,
parent: PlacesUtils.unfiledBookmarksFolderId,
uri: dragBookmark.url,
}, dragBookmark));

View file

@ -198,6 +198,7 @@ class ToolboxTabs extends Component {
for (const { id, label, icon } of panelDefinitions) {
if (this.state.overflowedTabIds.includes(id)) {
items.push(MenuItem({
key: id,
id: "tools-chevron-menupopup-" + id,
label,
type: "checkbox",

View file

@ -36,7 +36,7 @@ NetMonitorApp.prototype = {
const parentDoc = toolbox.doc;
const iframe = parentDoc.getElementById("toolbox-panel-iframe-netmonitor");
const top = iframe.ownerDocument.defaultView.top;
top.openUILinkIn(link, "tab");
top.openWebLinkIn(link, "tab");
};
const openSplitConsole = (err) => {

View file

@ -18,7 +18,7 @@
:root.theme-dark {
--tab-line-hover-color: rgba(255,255,255,.2);
--toggle-thumb-color: var(--grey-40);
--toggle-track-color: var(--grey-50);
--toggle-track-color: var(--grey-60);
}
:root[platform="mac"] {

View file

@ -19,7 +19,7 @@ body {
.theme-sidebar {
background: var(--theme-sidebar-background);
color: var(--theme-toolbar-color);
color: var(--theme-body-color);
}
::-moz-selection {
@ -262,8 +262,9 @@ div.CodeMirror span.eval-text {
.devtools-textinput,
.devtools-searchinput,
.devtools-filterinput {
background-color: rgba(24, 29, 32, 1);
color: rgba(184, 200, 217, 1);
/* in between grey-85 and grey-90 */
background-color: #141416;
color: var(--theme-highlight-gray);
}
.CodeMirror-Tern-fname {

View file

@ -14,7 +14,7 @@
:root.theme-dark {
--slider-thumb-color: var(--grey-40);
--slider-track-color: var(--grey-50);
--slider-track-color: var(--grey-60);
--input-background-color: var(--grey-70);
--input-border-color: var(--grey-70);
--input-text-color: var(--grey-40);
@ -209,6 +209,10 @@
align-items: center;
}
.font-control-input .devtools-checkbox-toggle {
margin: 2px 0;
}
.font-control-label {
display: inline-block;
flex: 1;

View file

@ -241,6 +241,7 @@ ul.children + .tag-line::before {
background-repeat: no-repeat;
background-position: center;
border: 1px solid var(--markup-badge-border-color);
color: var(--markup-badge-color);
fill: var(--markup-badge-interactive-color);
vertical-align: middle;
display: inline-block;

View file

@ -40,19 +40,19 @@
--theme-selection-color: #ffffff;
/* Border color that splits the toolbars/panels/headers. */
--theme-splitter-color: #e0e0e1;
--theme-splitter-color: var(--grey-25);
--theme-emphasized-splitter-color: var(--grey-30);
--theme-emphasized-splitter-color-hover: var(--grey-40);
/* Text color */
--theme-comment: var(--grey-50);
--theme-comment-alt: #ccd1d5;
--theme-comment-alt: var(--grey-40);
--theme-body-color: var(--grey-60);
--theme-body-color-alt: var(--grey-40);
--theme-body-color-inactive: #999797;
--theme-content-color1: #292e33;
--theme-content-color2: #8fa1b2;
--theme-content-color3: #667380;
--theme-body-color-alt: var(--grey-50);
--theme-body-color-inactive: var(--grey-40);
--theme-content-color1: var(--grey-80);
--theme-content-color2: var(--grey-60);
--theme-content-color3: var(--grey-45);
--theme-highlight-green: var(--green-70);
--theme-highlight-blue: var(--blue-55);
@ -107,19 +107,19 @@
:root.theme-dark {
--theme-body-background: var(--grey-80);
--theme-sidebar-background: #1B1B1D;
--theme-sidebar-background: var(--grey-85);
--theme-contrast-background: #ffb35b;
/* Toolbar */
--theme-tab-toolbar-background: var(--grey-90);
--theme-toolbar-background: #1B1B1D;
--theme-toolbar-background: var(--grey-85);
--theme-toolbar-color: var(--grey-40);
--theme-toolbar-photon-icon-color: var(--grey-40);
--theme-toolbar-selected-color: white;
--theme-toolbar-checked-color: #75BFFF;
--theme-toolbar-highlighted-color: var(--green-50);
--theme-toolbar-background-hover: #20232B;
--theme-toolbar-background-alt: #1B1B1D;
--theme-toolbar-background-alt: var(--grey-85);
--theme-toolbar-hover: #252526;
--theme-toolbar-hover-active: #252526;
@ -135,15 +135,15 @@
--theme-emphasized-splitter-color: var(--grey-60);
--theme-emphasized-splitter-color-hover: var(--grey-50);
--theme-comment: #939393;
--theme-comment-alt: #939393;
--theme-body-color: #909090;
--theme-body-color-alt: var(--grey-50);
--theme-body-color-inactive: var(--grey-40);
/* Text color */
--theme-comment: var(--grey-45);
--theme-comment-alt: var(--grey-50);
--theme-body-color: var(--grey-40);
--theme-body-color-alt: var(--grey-45);
--theme-body-color-inactive: var(--grey-50);
--theme-content-color1: var(--grey-30);
--theme-content-color2: var(--grey-40);
--theme-content-color3: #58575c;
--theme-content-color3: var(--grey-55);
--theme-highlight-green: #86DE74;
--theme-highlight-blue: #75BFFF;
@ -219,7 +219,9 @@
--theme-console-return-image: url(chrome://devtools/skin/images/webconsole/return.svg);
/* Firefox Colors CSS Variables v1.0.3
* Colors are taken from: https://github.com/FirefoxUX/design-tokens */
* Colors are taken from: https://github.com/FirefoxUX/design-tokens
* Some intermediate colors were added (names ending in '5').
*/
--magenta-50: #ff1ad9;
--magenta-65: #dd00a9;
--magenta-70: #b5007f;
@ -248,15 +250,19 @@
--grey-10: #f9f9fa;
--grey-20: #ededf0;
--grey-25: #e0e0e2;
--grey-30: #d7d7db;
--grey-30-a40: rgba(215, 215, 219, 0.4);
--grey-30-a90: rgba(215, 215, 219, 0.9);
--grey-40: #b1b1b3;
--grey-45: #939395;
--grey-50: #737373;
--grey-55: #5c5c5f;
--grey-60: #4a4a4f;
--grey-60-a50: rgba(74, 74, 79, 0.5);
--grey-70: #38383d;
--grey-80: #2a2a2e;
--grey-85: #1b1b1d;
--grey-90: #0c0c0d;
--grey-90-a10: rgba(12, 12, 13, 0.1);
--grey-90-a80: rgba(12, 12, 13, 0.8);

View file

@ -322,7 +322,7 @@ describe("ConsoleAPICall component:", () => {
const wrapper = render(ConsoleApiCall({ message, serviceContainer, open: true }));
expect(wrapper.find(".message-body").text()).toBe("bar");
expect(wrapper.find(".collapse-button.expanded").length).toBe(1);
expect(wrapper.find(".collapse-button[aria-expanded=true]").length).toBe(1);
});
it("renders group with custom style", () => {
@ -362,7 +362,7 @@ describe("ConsoleAPICall component:", () => {
serviceContainer,
})
));
wrapper.find(".collapse-button.expanded").simulate("click");
wrapper.find(".collapse-button[aria-expanded='true']").simulate("click");
let call = store.dispatch.getCall(0);
expect(call.args[0]).toEqual({
id: message.id,

View file

@ -114,7 +114,7 @@ describe("PageError component:", () => {
const wrapper = render(PageError({ message, serviceContainer, open: true }));
// There should be a collapse button.
expect(wrapper.find(".collapse-button.expanded").length).toBe(1);
expect(wrapper.find(".collapse-button[aria-expanded=true]").length).toBe(1);
// There should be five stacktrace items.
const frameLinks = wrapper.find(`.stack-trace span.frame-link`);
@ -134,7 +134,8 @@ describe("PageError component:", () => {
serviceContainer,
})
));
wrapper.find(".collapse-button.expanded").simulate("click");
wrapper.find(".collapse-button[aria-expanded='true']").simulate("click");
let call = store.dispatch.getCall(0);
expect(call.args[0]).toEqual({
id: message.id,
@ -149,7 +150,7 @@ describe("PageError component:", () => {
serviceContainer,
})
));
wrapper.find(".collapse-button").simulate("click");
wrapper.find(".collapse-button[aria-expanded='false']").simulate("click");
call = store.dispatch.getCall(1);
expect(call.args[0]).toEqual({
id: message.id,

View file

@ -67,19 +67,21 @@ describe("Network message reducer:", () => {
});
it("adds fetched HTTP post data", () => {
const uploadHeaders = Symbol();
const requestPostData = {
postData: {
text: ""
}
},
uploadHeaders,
};
dispatch(actions.networkUpdateRequest("message1", {
requestPostData: requestPostData
requestPostData,
}));
const networkUpdates = getAllNetworkMessagesUpdateById(getState());
expect(networkUpdates.message1.requestPostData).toBe(requestPostData);
expect(networkUpdates.message1.requestHeadersFromUploadStream).toExist();
const {message1} = getAllNetworkMessagesUpdateById(getState());
expect(message1.requestPostData).toBe(requestPostData);
expect(message1.requestHeadersFromUploadStream).toBe(uploadHeaders);
});
});
});

View file

@ -156,8 +156,8 @@ describe("private messages", () => {
const publicMessageId = getFirstMessage(state).id;
const privateMessageId = getLastMessage(state).id;
dispatch(actions.networkUpdateRequest(publicMessageId));
dispatch(actions.networkUpdateRequest(privateMessageId));
dispatch(actions.networkUpdateRequest(publicMessageId, {}));
dispatch(actions.networkUpdateRequest(privateMessageId, {}));
let networkUpdates = getAllNetworkMessagesUpdateById(getState());
expect(Object.keys(networkUpdates)).toEqual([publicMessageId, privateMessageId]);

View file

@ -41,6 +41,7 @@ exports.ConsoleMessage = function(props) {
frame: null,
groupId: null,
exceptionDocURL: null,
executionPoint: undefined,
userProvidedStyles: null,
notes: null,
indent: 0,

View file

@ -10,11 +10,18 @@
#include "mozilla/dom/Selection.h"
#include "mozilla/AsyncEventDispatcher.h"
#include "mozilla/Attributes.h"
#include "mozilla/AutoCopyListener.h"
#include "mozilla/AutoRestore.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/SelectionBinding.h"
#include "mozilla/dom/ShadowRoot.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/EventStates.h"
#include "mozilla/HTMLEditor.h"
#include "mozilla/RangeBoundary.h"
#include "mozilla/Telemetry.h"
#include "nsCOMPtr.h"
#include "nsString.h"
@ -53,7 +60,6 @@
#include "nsINamed.h"
#include "nsISelectionController.h" //for the enums
#include "nsAutoCopyListener.h"
#include "SelectionChangeListener.h"
#include "nsCopySupport.h"
#include "nsIClipboard.h"
@ -62,12 +68,6 @@
#include "nsIBidiKeyboard.h"
#include "nsError.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/ShadowRoot.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/SelectionBinding.h"
#include "mozilla/AsyncEventDispatcher.h"
#include "mozilla/Telemetry.h"
#include "nsViewManager.h"
#include "nsFocusManager.h"
@ -666,9 +666,10 @@ Selection::Selection()
, mDirection(eDirNext)
, mSelectionType(SelectionType::eNormal)
, mCustomColors(nullptr)
, mSelectionChangeBlockerCount(0)
, mUserInitiated(false)
, mCalledByJS(false)
, mSelectionChangeBlockerCount(0)
, mNotifyAutoCopy(false)
{
}
@ -678,9 +679,10 @@ Selection::Selection(nsFrameSelection* aList)
, mDirection(eDirNext)
, mSelectionType(SelectionType::eNormal)
, mCustomColors(nullptr)
, mSelectionChangeBlockerCount(0)
, mUserInitiated(false)
, mCalledByJS(false)
, mSelectionChangeBlockerCount(0)
, mNotifyAutoCopy(false)
{
}
@ -3475,8 +3477,6 @@ Selection::NotifySelectionListeners()
// If there are no selection listeners, we're done!
return NS_OK;
}
AutoTArray<nsCOMPtr<nsISelectionListener>, 8>
selectionListeners(mSelectionListeners);
nsCOMPtr<nsIDocument> doc;
nsIPresShell* ps = GetPresShell();
@ -3484,7 +3484,18 @@ Selection::NotifySelectionListeners()
doc = ps->GetDocument();
}
short reason = frameSelection->PopReason();
// We've notified all selection listeners even when some of them are removed
// (and may be destroyed) during notifying one of them. Therefore, we should
// copy all listeners to the local variable first.
AutoTArray<nsCOMPtr<nsISelectionListener>, 8>
selectionListeners(mSelectionListeners);
int16_t reason = frameSelection->PopReason();
if (mNotifyAutoCopy) {
AutoCopyListener::OnSelectionChange(doc, *this, reason);
}
for (auto& listener : selectionListeners) {
listener->NotifySelectionChanged(doc, this, reason);
}

View file

@ -86,6 +86,14 @@ public:
// match this up with StartBatchChanges
void EndBatchChanges(int16_t aReason = nsISelectionListener::NO_REASON);
/**
* NotifyAutoCopy() starts to notify AutoCopyListener of selection changes.
*/
void NotifyAutoCopy()
{
mNotifyAutoCopy = true;
}
nsIDocument* GetParentObject() const;
DocGroup* GetDocGroup() const;
@ -678,6 +686,10 @@ private:
SelectionType mSelectionType;
UniquePtr<SelectionCustomColors> mCustomColors;
// Non-zero if we don't want any changes we make to the selection to be
// visible to content. If non-zero, content won't be notified about changes.
uint32_t mSelectionChangeBlockerCount;
/**
* True if the current selection operation was initiated by user action.
* It determines whether we exclude -moz-user-select:none nodes or not,
@ -691,9 +703,10 @@ private:
*/
bool mCalledByJS;
// Non-zero if we don't want any changes we make to the selection to be
// visible to content. If non-zero, content won't be notified about changes.
uint32_t mSelectionChangeBlockerCount;
/**
* true if AutoCopyListner::OnSelectionChange() should be called.
*/
bool mNotifyAutoCopy;
};
// Stack-class to turn on/off selection batching.

View file

@ -31,6 +31,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ShadowRoot, DocumentFragment)
for (StyleSheet* sheet : tmp->mStyleSheets) {
// mServoStyles keeps another reference to it if applicable.
if (sheet->IsApplicable()) {
MOZ_ASSERT(tmp->mServoStyles);
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mServoStyles->sheets[i]");
cb.NoteXPCOMChild(sheet);
}
@ -63,7 +64,6 @@ ShadowRoot::ShadowRoot(Element* aElement, ShadowRootMode aMode,
: DocumentFragment(aNodeInfo)
, DocumentOrShadowRoot(*this)
, mMode(aMode)
, mServoStyles(Servo_AuthorStyles_Create())
, mIsUAWidget(false)
{
SetHost(aElement);
@ -313,10 +313,14 @@ ShadowRoot::RemoveSlot(HTMLSlotElement* aSlot)
void
ShadowRoot::RuleAdded(StyleSheet& aSheet, css::Rule& aRule)
{
if (!aSheet.IsApplicable()) {
return;
}
MOZ_ASSERT(mServoStyles);
if (mStyleRuleMap) {
mStyleRuleMap->RuleAdded(aSheet, aRule);
}
Servo_AuthorStyles_ForceDirty(mServoStyles.get());
ApplicableRulesChanged();
}
@ -324,16 +328,25 @@ ShadowRoot::RuleAdded(StyleSheet& aSheet, css::Rule& aRule)
void
ShadowRoot::RuleRemoved(StyleSheet& aSheet, css::Rule& aRule)
{
if (!aSheet.IsApplicable()) {
return;
}
MOZ_ASSERT(mServoStyles);
if (mStyleRuleMap) {
mStyleRuleMap->RuleRemoved(aSheet, aRule);
}
Servo_AuthorStyles_ForceDirty(mServoStyles.get());
ApplicableRulesChanged();
}
void
ShadowRoot::RuleChanged(StyleSheet&, css::Rule*) {
ShadowRoot::RuleChanged(StyleSheet& aSheet, css::Rule*) {
if (!aSheet.IsApplicable()) {
return;
}
MOZ_ASSERT(mServoStyles);
Servo_AuthorStyles_ForceDirty(mServoStyles.get());
ApplicableRulesChanged();
}
@ -366,6 +379,10 @@ ShadowRoot::InsertSheetIntoAuthorData(size_t aIndex, StyleSheet& aSheet)
MOZ_ASSERT(SheetAt(aIndex) == &aSheet);
MOZ_ASSERT(aSheet.IsApplicable());
if (!mServoStyles) {
mServoStyles.reset(Servo_AuthorStyles_Create());
}
if (mStyleRuleMap) {
mStyleRuleMap->SheetAdded(aSheet);
}
@ -405,6 +422,7 @@ ShadowRoot::StyleSheetApplicableStateChanged(StyleSheet& aSheet, bool aApplicabl
if (aApplicable) {
InsertSheetIntoAuthorData(size_t(index), aSheet);
} else {
MOZ_ASSERT(mServoStyles);
if (mStyleRuleMap) {
mStyleRuleMap->SheetRemoved(aSheet);
}
@ -420,6 +438,7 @@ ShadowRoot::RemoveSheet(StyleSheet* aSheet)
RefPtr<StyleSheet> sheet = DocumentOrShadowRoot::RemoveSheet(*aSheet);
MOZ_ASSERT(sheet);
if (sheet->IsApplicable()) {
MOZ_ASSERT(mServoStyles);
if (mStyleRuleMap) {
mStyleRuleMap->SheetRemoved(*sheet);
}

View file

@ -158,12 +158,12 @@ public:
void RemoveSlot(HTMLSlotElement* aSlot);
bool HasSlots() const { return !mSlotMap.IsEmpty(); };
const RawServoAuthorStyles* ServoStyles() const
const RawServoAuthorStyles* GetServoStyles() const
{
return mServoStyles.get();
}
RawServoAuthorStyles* ServoStyles()
RawServoAuthorStyles* GetServoStyles()
{
return mServoStyles.get();
}

View file

@ -493,8 +493,7 @@ XMLHttpRequestMainThread::DetectCharset()
}
nsresult
XMLHttpRequestMainThread::AppendToResponseText(const char * aSrcBuffer,
uint32_t aSrcBufferLen,
XMLHttpRequestMainThread::AppendToResponseText(Span<const uint8_t> aBuffer,
bool aLast)
{
// Call this with an empty buffer to send the decoder the signal
@ -503,36 +502,41 @@ XMLHttpRequestMainThread::AppendToResponseText(const char * aSrcBuffer,
NS_ENSURE_STATE(mDecoder);
CheckedInt<size_t> destBufferLen =
mDecoder->MaxUTF16BufferLength(aSrcBufferLen);
if (!destBufferLen.isValid()) {
return NS_ERROR_OUT_OF_MEMORY;
}
mDecoder->MaxUTF16BufferLength(aBuffer.Length());
CheckedInt32 size = mResponseText.Length();
size += destBufferLen.value();
if (!size.isValid()) {
return NS_ERROR_OUT_OF_MEMORY;
}
{ // scope for holding the mutex that protects mResponseText
XMLHttpRequestStringWriterHelper helper(mResponseText);
XMLHttpRequestStringWriterHelper helper(mResponseText);
uint32_t len = helper.Length();
if (!helper.AddCapacity(destBufferLen.value())) {
return NS_ERROR_OUT_OF_MEMORY;
}
destBufferLen += len;
if (!destBufferLen.isValid() || destBufferLen.value() > UINT32_MAX) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsresult rv;
BulkWriteHandle<char16_t> handle =
helper.BulkWrite(destBufferLen.value(), rv);
if (NS_FAILED(rv)) {
return rv;
}
uint32_t result;
size_t read;
size_t written;
bool hadErrors;
Tie(result, read, written, hadErrors) = mDecoder->DecodeToUTF16(
aBuffer,
handle.AsSpan().From(len),
aLast);
MOZ_ASSERT(result == kInputEmpty);
MOZ_ASSERT(read == aBuffer.Length());
len += written;
MOZ_ASSERT(len <= destBufferLen.value());
Unused << hadErrors;
handle.Finish(len, false);
} // release mutex
uint32_t result;
size_t read;
size_t written;
bool hadErrors;
Tie(result, read, written, hadErrors) = mDecoder->DecodeToUTF16(
AsBytes(MakeSpan(aSrcBuffer, aSrcBufferLen)),
MakeSpan(helper.EndOfExistingData(), destBufferLen.value()),
aLast);
MOZ_ASSERT(result == kInputEmpty);
MOZ_ASSERT(read == aSrcBufferLen);
MOZ_ASSERT(written <= destBufferLen.value());
Unused << hadErrors;
helper.AddLength(written);
if (aLast) {
// Drop the finished decoder to avoid calling into a decoder
// that has finished.
@ -597,8 +601,8 @@ XMLHttpRequestMainThread::GetResponseText(XMLHttpRequestStringSnapshot& aSnapsho
MOZ_ASSERT(mResponseBodyDecodedPos < mResponseBody.Length() ||
mState == XMLHttpRequest_Binding::DONE,
"Unexpected mResponseBodyDecodedPos");
aRv = AppendToResponseText(mResponseBody.get() + mResponseBodyDecodedPos,
mResponseBody.Length() - mResponseBodyDecodedPos,
Span<const uint8_t> span = mResponseBody;
aRv = AppendToResponseText(span.From(mResponseBodyDecodedPos),
mState == XMLHttpRequest_Binding::DONE);
if (aRv.Failed()) {
return;
@ -1608,7 +1612,7 @@ XMLHttpRequestMainThread::StreamReaderFunc(nsIInputStream* in,
xmlHttpRequest->mResponseType == XMLHttpRequestResponseType::Json) {
MOZ_ASSERT(!xmlHttpRequest->mResponseXML,
"We shouldn't be parsing a doc here");
rv = xmlHttpRequest->AppendToResponseText(fromRawSegment, count);
rv = xmlHttpRequest->AppendToResponseText(AsBytes(MakeSpan(fromRawSegment, count)));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -2099,7 +2103,7 @@ XMLHttpRequestMainThread::OnStopRequest(nsIRequest *request, nsISupports *ctxt,
((mResponseType == XMLHttpRequestResponseType::Text) ||
(mResponseType == XMLHttpRequestResponseType::Json) ||
(mResponseType == XMLHttpRequestResponseType::_empty && !mResponseXML))) {
AppendToResponseText(nullptr, 0, true);
AppendToResponseText(Span<const uint8_t>(), true);
}
mWaitingForOnStopRequest = false;

View file

@ -481,7 +481,7 @@ public:
protected:
nsresult DetectCharset();
nsresult AppendToResponseText(const char * aBuffer, uint32_t aBufferLen,
nsresult AppendToResponseText(Span<const uint8_t> aBuffer,
bool aLast = false);
static nsresult StreamReaderFunc(nsIInputStream* in,
void* closure,

View file

@ -38,6 +38,12 @@ public:
return mData.Length();
}
mozilla::BulkWriteHandle<char16_t>
UnsafeBulkWrite(uint32_t aCapacity, nsresult& aRv)
{
return mData.BulkWrite(aCapacity, UnsafeLength(), false, aRv);
}
void
Append(const nsAString& aString)
{
@ -226,22 +232,16 @@ XMLHttpRequestStringWriterHelper::XMLHttpRequestStringWriterHelper(XMLHttpReques
{
}
bool
XMLHttpRequestStringWriterHelper::AddCapacity(int32_t aCapacity)
uint32_t
XMLHttpRequestStringWriterHelper::Length() const
{
return mBuffer->UnsafeData().SetCapacity(mBuffer->UnsafeLength() + aCapacity, fallible);
return mBuffer->UnsafeLength();
}
char16_t*
XMLHttpRequestStringWriterHelper::EndOfExistingData()
mozilla::BulkWriteHandle<char16_t>
XMLHttpRequestStringWriterHelper::BulkWrite(uint32_t aCapacity, nsresult& aRv)
{
return mBuffer->UnsafeData().BeginWriting() + mBuffer->UnsafeLength();
}
void
XMLHttpRequestStringWriterHelper::AddLength(int32_t aLength)
{
mBuffer->UnsafeData().SetLength(mBuffer->UnsafeLength() + aLength);
return mBuffer->UnsafeBulkWrite(aCapacity, aRv);
}
// ---------------------------------------------------------------------------

View file

@ -64,14 +64,14 @@ class MOZ_STACK_CLASS XMLHttpRequestStringWriterHelper final
public:
explicit XMLHttpRequestStringWriterHelper(XMLHttpRequestString& aString);
bool
AddCapacity(int32_t aCapacity);
/**
* The existing length of the string. Do not call during BulkWrite().
*/
uint32_t
Length() const;
char16_t*
EndOfExistingData();
void
AddLength(int32_t aLength);
mozilla::BulkWriteHandle<char16_t>
BulkWrite(uint32_t aCapacity, nsresult& aRv);
private:
XMLHttpRequestStringWriterHelper(const XMLHttpRequestStringWriterHelper&) = delete;

View file

@ -47,22 +47,6 @@ ContainerLayerMLGPU::OnPrepareToRender(FrameBuilder* aBuilder)
return true;
}
if ((!mRenderTarget || mChildrenChanged) &&
gfxPrefs::AdvancedLayersEnableContainerResizing())
{
// Try to compute a more accurate visible region.
AL_LOG("Computing new surface size for container %p:\n", GetLayer());
Maybe<IntRect> bounds = ComputeIntermediateSurfaceBounds();
if (bounds) {
LayerIntRegion region = std::move(GetShadowVisibleRegion());
region.AndWith(LayerIntRect::FromUnknownRect(bounds.value()));
AL_LOG(" computed bounds: %s\n", Stringify(bounds.value()).c_str());
AL_LOG(" new visible: %s\n", Stringify(region).c_str());
SetShadowVisibleRegion(std::move(region));
}
}
mChildrenChanged = false;
mTargetOffset = GetIntermediateSurfaceRect().TopLeft().ToUnknownPoint();
@ -117,41 +101,45 @@ GetTransformedBounds(Layer* aLayer)
return bounds;
}
static Maybe<IntRect>
FindVisibleBounds(Layer* aLayer, const Maybe<RenderTargetIntRect>& aClip)
/* static */ Maybe<IntRect>
ContainerLayerMLGPU::FindVisibleBounds(Layer* aLayer, const Maybe<RenderTargetIntRect>& aClip)
{
AL_LOG(" visiting child %p\n", aLayer);
AL_LOG_IF(aClip, " parent clip: %s\n", Stringify(aClip.value()).c_str());
ContainerLayer* container = aLayer->AsContainerLayer();
if (container && !container->UseIntermediateSurface()) {
Maybe<IntRect> accumulated = Some(IntRect());
if (container) {
if (container->UseIntermediateSurface()) {
container->AsHostLayer()->AsLayerMLGPU()->AsContainerLayerMLGPU()->ComputeIntermediateSurfaceBounds();
} else {
Maybe<IntRect> accumulated = Some(IntRect());
// Traverse children.
for (Layer* child = container->GetFirstChild(); child; child = child->GetNextSibling()) {
Maybe<RenderTargetIntRect> clip = aClip;
if (const Maybe<ParentLayerIntRect>& childClip = child->AsHostLayer()->GetShadowClipRect()) {
RenderTargetIntRect rtChildClip =
TransformBy(ViewAs<ParentLayerToRenderTargetMatrix4x4>(
aLayer->GetEffectiveTransform(),
PixelCastJustification::RenderTargetIsParentLayerForRoot),
childClip.value());
clip = IntersectMaybeRects(clip, Some(rtChildClip));
AL_LOG(" target clip: %s\n", Stringify(rtChildClip).c_str());
AL_LOG_IF(clip, " full clip: %s\n", Stringify(clip.value()).c_str());
}
// Traverse children.
for (Layer* child = container->GetFirstChild(); child; child = child->GetNextSibling()) {
Maybe<RenderTargetIntRect> clip = aClip;
if (const Maybe<ParentLayerIntRect>& childClip = child->AsHostLayer()->GetShadowClipRect()) {
RenderTargetIntRect rtChildClip =
TransformBy(ViewAs<ParentLayerToRenderTargetMatrix4x4>(
aLayer->GetEffectiveTransform(),
PixelCastJustification::RenderTargetIsParentLayerForRoot),
childClip.value());
clip = IntersectMaybeRects(clip, Some(rtChildClip));
AL_LOG(" target clip: %s\n", Stringify(rtChildClip).c_str());
AL_LOG_IF(clip, " full clip: %s\n", Stringify(clip.value()).c_str());
}
Maybe<IntRect> childBounds = FindVisibleBounds(child, clip);
if (!childBounds) {
return Nothing();
}
Maybe<IntRect> childBounds = FindVisibleBounds(child, clip);
if (!childBounds) {
return Nothing();
}
accumulated = accumulated->SafeUnion(childBounds.value());
if (!accumulated) {
return Nothing();
accumulated = accumulated->SafeUnion(childBounds.value());
if (!accumulated) {
return Nothing();
}
}
return accumulated;
}
return accumulated;
}
IntRect bounds = GetTransformedBounds(aLayer);
@ -164,7 +152,7 @@ FindVisibleBounds(Layer* aLayer, const Maybe<RenderTargetIntRect>& aClip)
return Some(bounds);
}
Maybe<IntRect>
void
ContainerLayerMLGPU::ComputeIntermediateSurfaceBounds()
{
Maybe<IntRect> bounds = Some(IntRect());
@ -174,15 +162,16 @@ ContainerLayerMLGPU::ComputeIntermediateSurfaceBounds()
PixelCastJustification::RenderTargetIsParentLayerForRoot);
Maybe<IntRect> childBounds = FindVisibleBounds(child, clip);
if (!childBounds) {
return Nothing();
return;
}
bounds = bounds->SafeUnion(childBounds.value());
if (!bounds) {
return Nothing();
return;
}
}
return bounds;
SetShadowVisibleRegion(LayerIntRect::FromUnknownRect(bounds.value()));
}
void

View file

@ -69,12 +69,15 @@ public:
mView = aView;
}
void ComputeIntermediateSurfaceBounds();
protected:
bool OnPrepareToRender(FrameBuilder* aBuilder) override;
void OnLayerManagerChange(LayerManagerMLGPU* aManager) override;
Maybe<gfx::IntRect> ComputeIntermediateSurfaceBounds();
private:
static Maybe<gfx::IntRect> FindVisibleBounds(Layer* aLayer, const Maybe<RenderTargetIntRect>& aClip);
RefPtr<MLGRenderTarget> mRenderTarget;
// We cache these since occlusion culling can change the visible region.

View file

@ -66,6 +66,11 @@ FrameBuilder::Build()
mWidgetRenderView = new RenderViewMLGPU(this, target, region);
// Traverse the layer tree and compute visible region for intermediate surfaces
if (ContainerLayerMLGPU* root = mRoot->AsLayerMLGPU()->AsContainerLayerMLGPU()) {
root->ComputeIntermediateSurfaceBounds();
}
// Traverse the layer tree and assign each layer to tiles.
{
Maybe<gfx::Polygon> geometry;

View file

@ -11,7 +11,6 @@
#include "DateTimeFormat.h"
#include "nsAttrValue.h"
#include "nsAutoCopyListener.h"
#include "nsColorNames.h"
#include "nsComputedDOMStyle.h"
#include "nsContentDLF.h"
@ -355,7 +354,6 @@ nsLayoutStatics::Shutdown()
WebIDLGlobalNameHash::Shutdown();
nsListControlFrame::Shutdown();
nsXBLService::Shutdown();
nsAutoCopyListener::Shutdown();
FrameLayerBuilder::Shutdown();
CubebUtils::ShutdownLibrary();

View file

@ -0,0 +1,67 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef mozilla_AutoCopyListener_h
#define mozilla_AutoCopyListener_h
#include "mozilla/Attributes.h"
#include "mozilla/dom/Selection.h"
#include "mozilla/StaticPrefs.h"
#include "nsIClipboard.h"
namespace mozilla {
class AutoCopyListener final
{
public:
/**
* OnSelectionChange() is called when a Selection whose NotifyAutoCopy() was
* called is changed.
*
* @param aDocument The document of the Selection. May be nullptr.
* @param aSelection The selection.
* @param aReason The reasons of the change.
* See nsISelectionListener::*_REASON.
*/
static void OnSelectionChange(nsIDocument* aDocument,
dom::Selection& aSelection,
int16_t aReason);
/**
* Init() initializes all static members of this class. Should be called
* only once.
*/
static void Init(int16_t aClipboardID)
{
MOZ_ASSERT(IsValidClipboardID(aClipboardID));
static bool sInitialized = false;
if (!sInitialized && IsValidClipboardID(aClipboardID)) {
sClipboardID = aClipboardID;
sInitialized = true;
}
}
/**
* IsPrefEnabled() returns true if the pref enables auto-copy feature.
*/
static bool IsPrefEnabled()
{
return StaticPrefs::clipboard_autocopy();
}
private:
static bool IsValidClipboardID(int16_t aClipboardID)
{
return aClipboardID >= nsIClipboard::kSelectionClipboard &&
aClipboardID <= nsIClipboard::kSelectionCache;
}
static int16_t sClipboardID;
};
} // namespace mozilla
#endif // #ifndef mozilla_AutoCopyListener_h

View file

@ -109,6 +109,7 @@ EXPORTS += [
]
EXPORTS.mozilla += [
'AutoCopyListener.h',
'CSSAlignUtils.h',
'CSSOrderAwareFrameIterator.h',
'FrameTypeList.h',

View file

@ -1,53 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef nsAutoCopyListener_h_
#define nsAutoCopyListener_h_
#include "nsISelectionListener.h"
#include "mozilla/Attributes.h"
#include "mozilla/dom/Selection.h"
class nsAutoCopyListener final : public nsISelectionListener
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSISELECTIONLISTENER
explicit nsAutoCopyListener(int16_t aClipboardID)
: mCachedClipboard(aClipboardID)
{}
void Listen(mozilla::dom::Selection *aSelection)
{
NS_ASSERTION(aSelection, "Null selection passed to Listen()");
aSelection->AddSelectionListener(this);
}
static nsAutoCopyListener* GetInstance(int16_t aClipboardID)
{
if (!sInstance) {
sInstance = new nsAutoCopyListener(aClipboardID);
NS_ADDREF(sInstance);
}
return sInstance;
}
static void Shutdown()
{
NS_IF_RELEASE(sInstance);
}
private:
~nsAutoCopyListener() {}
static nsAutoCopyListener* sInstance;
int16_t mCachedClipboard;
};
#endif

View file

@ -61,7 +61,6 @@ static NS_DEFINE_CID(kFrameTraversalCID, NS_FRAMETRAVERSAL_CID);
#include "nsIDocument.h"
#include "nsISelectionController.h" //for the enums
#include "nsAutoCopyListener.h"
#include "SelectionChangeListener.h"
#include "nsCopySupport.h"
#include "nsIClipboard.h"
@ -70,6 +69,7 @@ static NS_DEFINE_CID(kFrameTraversalCID, NS_FRAMETRAVERSAL_CID);
#include "nsIBidiKeyboard.h"
#include "nsError.h"
#include "mozilla/AutoCopyListener.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/Selection.h"
#include "mozilla/dom/ShadowRoot.h"
@ -301,22 +301,23 @@ nsFrameSelection::nsFrameSelection()
mDomSelections[i]->SetType(kPresentSelectionTypes[i]);
}
nsAutoCopyListener *autoCopy = nullptr;
// On macOS, cache the current selection to send to osx service menu.
#ifdef XP_MACOSX
autoCopy = nsAutoCopyListener::GetInstance(nsIClipboard::kSelectionCache);
#endif
// Check to see if the autocopy pref is enabled
// and add the autocopy listener if it is
if (Preferences::GetBool("clipboard.autocopy")) {
autoCopy = nsAutoCopyListener::GetInstance(nsIClipboard::kSelectionClipboard);
// On macOS, cache the current selection to send to service menu of macOS.
bool enableAutoCopy = true;
AutoCopyListener::Init(nsIClipboard::kSelectionCache);
#else // #ifdef XP_MACOSX
// Check to see if the auto-copy pref is enabled and make the normal
// Selection notifies auto-copy listener of its changes.
bool enableAutoCopy = AutoCopyListener::IsPrefEnabled();
if (enableAutoCopy) {
AutoCopyListener::Init(nsIClipboard::kSelectionClipboard);
}
#endif // #ifdef XP_MACOSX #else
if (autoCopy) {
if (enableAutoCopy) {
int8_t index = GetIndexFromSelectionType(SelectionType::eNormal);
if (mDomSelections[index]) {
autoCopy->Listen(mDomSelections[index]);
mDomSelections[index]->NotifyAutoCopy();
}
}
}
@ -2898,7 +2899,7 @@ nsFrameSelection::DisconnectFromPresShell()
* if the current selection being repainted is not an empty selection.
*
* If the current selection is empty. The current selection cache
* would be cleared by nsAutoCopyListener::NotifySelectionChanged.
* would be cleared by AutoCopyListener::OnSelectionChange().
*/
nsresult
nsFrameSelection::UpdateSelectionCacheOnRepaintSelection(Selection* aSel)
@ -2917,11 +2918,9 @@ nsFrameSelection::UpdateSelectionCacheOnRepaintSelection(Selection* aSel)
return NS_OK;
}
// nsAutoCopyListener
// mozilla::AutoCopyListener
nsAutoCopyListener* nsAutoCopyListener::sInstance = nullptr;
NS_IMPL_ISUPPORTS(nsAutoCopyListener, nsISelectionListener)
int16_t AutoCopyListener::sClipboardID = -1;
/*
* What we do now:
@ -2955,40 +2954,51 @@ NS_IMPL_ISUPPORTS(nsAutoCopyListener, nsISelectionListener)
* widget cocoa nsClipboard whenever selection changes.
*/
NS_IMETHODIMP
nsAutoCopyListener::NotifySelectionChanged(nsIDocument *aDoc,
Selection *aSel, int16_t aReason)
// static
void
AutoCopyListener::OnSelectionChange(nsIDocument* aDocument,
Selection& aSelection,
int16_t aReason)
{
if (mCachedClipboard == nsIClipboard::kSelectionCache) {
MOZ_ASSERT(IsValidClipboardID(sClipboardID));
if (sClipboardID == nsIClipboard::kSelectionCache) {
nsFocusManager* fm = nsFocusManager::GetFocusManager();
// If no active window, do nothing because a current selection changed
// cannot occur unless it is in the active window.
if (!fm->GetActiveWindow()) {
return NS_OK;
return;
}
}
if (!(aReason & nsISelectionListener::MOUSEUP_REASON ||
aReason & nsISelectionListener::SELECTALL_REASON ||
aReason & nsISelectionListener::KEYPRESS_REASON))
return NS_OK; //dont care if we are still dragging
static const int16_t kResasonsToHandle =
nsISelectionListener::MOUSEUP_REASON |
nsISelectionListener::SELECTALL_REASON |
nsISelectionListener::KEYPRESS_REASON;
if (!(aReason & kResasonsToHandle)) {
return; // Don't care if we are still dragging.
}
if (!aDoc || !aSel || aSel->IsCollapsed()) {
if (!aDocument || aSelection.IsCollapsed()) {
#ifdef DEBUG_CLIPBOARD
fprintf(stderr, "CLIPBOARD: no selection/collapsed selection\n");
#endif
if (sClipboardID != nsIClipboard::kSelectionCache) {
// XXX Should we clear X clipboard?
return;
}
// If on macOS, clear the current selection transferable cached
// on the parent process (nsClipboard) when the selection is empty.
if (mCachedClipboard == nsIClipboard::kSelectionCache) {
return nsCopySupport::ClearSelectionCache();
}
/* clear X clipboard? */
return NS_OK;
DebugOnly<nsresult> rv = nsCopySupport::ClearSelectionCache();
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"nsCopySupport::ClearSelectionCache() failed");
return;
}
NS_ENSURE_TRUE(aDoc, NS_ERROR_FAILURE);
// call the copy code
return nsCopySupport::HTMLCopy(aSel, aDoc,
mCachedClipboard, false);
// Call the copy code.
DebugOnly<nsresult> rv =
nsCopySupport::HTMLCopy(&aSelection, aDocument, sClipboardID, false);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"nsCopySupport::HTMLCopy() failed");
}

View file

@ -228,7 +228,9 @@ ServoStyleSet::InvalidateStyleForDocumentStateChanges(EventStates aStatesChanged
AutoTArray<RawServoAuthorStylesBorrowed, 20> nonDocumentStyles;
EnumerateShadowRoots(*mDocument, [&](ShadowRoot& aShadowRoot) {
nonDocumentStyles.AppendElement(aShadowRoot.ServoStyles());
if (auto* authorStyles = aShadowRoot.GetServoStyles()) {
nonDocumentStyles.AppendElement(authorStyles);
}
});
mDocument->BindingManager()->EnumerateBoundContentProtoBindings(
@ -261,7 +263,9 @@ ServoStyleSet::MediumFeaturesChanged(MediaFeatureChangeReason aReason)
AutoTArray<RawServoAuthorStylesBorrowedMut, 20> nonDocumentStyles;
EnumerateShadowRoots(*mDocument, [&](ShadowRoot& aShadowRoot) {
nonDocumentStyles.AppendElement(aShadowRoot.ServoStyles());
if (auto* authorStyles = aShadowRoot.GetServoStyles()) {
nonDocumentStyles.AppendElement(authorStyles);
}
});
// FIXME(emilio): This is broken for XBL. See bug 1406875.
@ -1281,16 +1285,17 @@ ServoStyleSet::EnsureUniqueInnerOnCSSSheets()
queue.RemoveElementAt(idx);
if (!sheet->HasUniqueInner()) {
RawServoAuthorStyles* authorStyles = nullptr;
if (owner.is<ShadowRoot*>()) {
Servo_AuthorStyles_ForceDirty(owner.as<ShadowRoot*>()->ServoStyles());
authorStyles = owner.as<ShadowRoot*>()->GetServoStyles();
} else if (owner.is<nsXBLPrototypeBinding*>()) {
authorStyles = owner.as<nsXBLPrototypeBinding*>()->GetServoStyles();
}
if (authorStyles) {
Servo_AuthorStyles_ForceDirty(authorStyles);
mNeedsRestyleAfterEnsureUniqueInner = true;
anyNonDocStyleChanged = true;
} else if (owner.is<nsXBLPrototypeBinding*>()) {
if (auto* styles = owner.as<nsXBLPrototypeBinding*>()->GetServoStyles()) {
Servo_AuthorStyles_ForceDirty(styles);
mNeedsRestyleAfterEnsureUniqueInner = true;
anyNonDocStyleChanged = true;
}
}
}
@ -1465,7 +1470,9 @@ ServoStyleSet::UpdateStylist()
MOZ_ASSERT(GetPresContext(), "How did they get dirty?");
EnumerateShadowRoots(*mDocument, [&](ShadowRoot& aShadowRoot) {
Servo_AuthorStyles_Flush(aShadowRoot.ServoStyles(), mRawSet.get());
if (auto* authorStyles = aShadowRoot.GetServoStyles()) {
Servo_AuthorStyles_Flush(authorStyles, mRawSet.get());
}
});
mDocument->BindingManager()->EnumerateBoundContentProtoBindings(

View file

@ -838,7 +838,7 @@ nsTextBoxFrame::UpdateAccessTitle()
/*
* Note that if you change appending access key label spec,
* you need to maintain same logic in following methods. See bug 324159.
* toolkit/content/commonDialog.js (setLabelForNode)
* toolkit/components/prompts/src/CommonDialog.jsm (setLabelForNode)
* toolkit/content/widgets/text.xml (formatAccessKey)
*/
int32_t menuAccessKey;
@ -861,6 +861,11 @@ nsTextBoxFrame::UpdateAccessTitle()
return;
}
if (StringEndsWith(mTitle, accessKeyLabel)) {
// Never append another "(X)" if the title already ends with "(X)".
return;
}
const nsDependentString& kEllipsis = nsContentUtils::GetLocalizedEllipsis();
uint32_t offset = mTitle.Length();
if (StringEndsWith(mTitle, kEllipsis)) {

View file

@ -12,7 +12,6 @@
#include "AudioSegment.h"
#include "AudioConverter.h"
#include "CSFLog.h"
#include "DOMMediaStream.h"
#include "ImageContainer.h"
#include "ImageTypes.h"
@ -30,6 +29,7 @@
#include "VideoStreamTrack.h"
#include "VideoUtils.h"
#include "libyuv/convert.h"
#include "mozilla/Logging.h"
#include "mozilla/PeerIdentity.h"
#include "mozilla/Preferences.h"
#include "mozilla/SharedThreadPool.h"
@ -78,11 +78,7 @@ using namespace mozilla::dom;
using namespace mozilla::gfx;
using namespace mozilla::layers;
static const char* mpLogTag = "MediaPipeline";
#ifdef LOGTAG
#undef LOGTAG
#endif
#define LOGTAG mpLogTag
mozilla::LazyLogModule gMediaPipelineLog("MediaPipeline");
namespace mozilla {
extern mozilla::LogModule*
@ -175,10 +171,10 @@ public:
// giving us a margin to not cause some machines to drop every other frame.
const int32_t queueThrottlingLimit = 1;
if (mLength > queueThrottlingLimit) {
CSFLogDebug(LOGTAG,
"VideoFrameConverter %p queue is full. Throttling by "
"throwing away a frame.",
this);
MOZ_LOG(gMediaPipelineLog, LogLevel::Debug,
("VideoFrameConverter %p queue is full. Throttling by "
"throwing away a frame.",
this));
#ifdef DEBUG
++mThrottleCount;
mThrottleRecord = std::max(mThrottleCount, mThrottleRecord);
@ -190,19 +186,19 @@ public:
if (mThrottleCount > 0) {
if (mThrottleCount > 5) {
// Log at a higher level when we have large drops.
CSFLogInfo(LOGTAG,
"VideoFrameConverter %p stopped throttling after throwing "
"away %d frames. Longest throttle so far was %d frames.",
this,
mThrottleCount,
mThrottleRecord);
MOZ_LOG(gMediaPipelineLog, LogLevel::Info,
("VideoFrameConverter %p stopped throttling after throwing "
"away %d frames. Longest throttle so far was %d frames.",
this,
mThrottleCount,
mThrottleRecord));
} else {
CSFLogDebug(LOGTAG,
"VideoFrameConverter %p stopped throttling after throwing "
"away %d frames. Longest throttle so far was %d frames.",
this,
mThrottleCount,
mThrottleRecord);
MOZ_LOG(gMediaPipelineLog, LogLevel::Debug,
("VideoFrameConverter %p stopped throttling after throwing "
"away %d frames. Longest throttle so far was %d frames.",
this,
mThrottleCount,
mThrottleRecord));
}
mThrottleCount = 0;
}
@ -260,7 +256,8 @@ protected:
{
// check for parameter sanity
if (!aBuffer || aVideoFrameLength == 0 || aWidth == 0 || aHeight == 0) {
CSFLogError(LOGTAG, "%s Invalid Parameters", __FUNCTION__);
MOZ_LOG(gMediaPipelineLog, LogLevel::Error, ("%s Invalid Parameters",
__FUNCTION__));
MOZ_ASSERT(false);
return;
}
@ -312,11 +309,13 @@ protected:
if (!buffer) {
MOZ_DIAGNOSTIC_ASSERT(false, "Buffers not leaving scope except for "
"reconfig, should never leak");
CSFLogWarn(LOGTAG, "Creating a buffer for a black video frame failed");
MOZ_LOG(gMediaPipelineLog, LogLevel::Warning,
("Creating a buffer for a black video frame failed"));
return;
}
CSFLogDebug(LOGTAG, "Sending a black video frame");
MOZ_LOG(gMediaPipelineLog, LogLevel::Debug,
("Sending a black video frame"));
webrtc::I420Buffer::SetBlack(buffer);
webrtc::VideoFrame frame(buffer,
0, 0, // not setting timestamps
@ -360,7 +359,8 @@ protected:
0,
0, // not setting timestamps
webrtc::kVideoRotation_0);
CSFLogDebug(LOGTAG, "Sending an I420 video frame");
MOZ_LOG(gMediaPipelineLog, LogLevel::Debug,
("Sending an I420 video frame"));
VideoFrameConverted(i420_frame);
return;
}
@ -368,20 +368,19 @@ protected:
RefPtr<SourceSurface> surf = aImage->GetAsSourceSurface();
if (!surf) {
CSFLogError(LOGTAG,
"Getting surface from %s image failed",
Stringify(format).c_str());
MOZ_LOG(gMediaPipelineLog, LogLevel::Error,
("Getting surface from %s image failed",
Stringify(format).c_str()));
return;
}
RefPtr<DataSourceSurface> data = surf->GetDataSurface();
if (!data) {
CSFLogError(
LOGTAG,
"Getting data surface from %s image with %s (%s) surface failed",
Stringify(format).c_str(),
Stringify(surf->GetType()).c_str(),
Stringify(surf->GetFormat()).c_str());
MOZ_LOG(gMediaPipelineLog, LogLevel::Error,
("Getting data surface from %s image with %s (%s) surface failed",
Stringify(format).c_str(),
Stringify(surf->GetType()).c_str(),
Stringify(surf->GetFormat()).c_str()));
return;
}
@ -393,18 +392,18 @@ protected:
rtc::scoped_refptr<webrtc::I420Buffer> buffer =
mBufferPool.CreateBuffer(aSize.width, aSize.height);
if (!buffer) {
CSFLogWarn(LOGTAG, "Creating a buffer for a black video frame failed");
MOZ_LOG(gMediaPipelineLog, LogLevel::Warning,
("Creating a buffer for a black video frame failed"));
return;
}
DataSourceSurface::ScopedMap map(data, DataSourceSurface::READ);
if (!map.IsMapped()) {
CSFLogError(
LOGTAG,
"Reading DataSourceSurface from %s image with %s (%s) surface failed",
Stringify(format).c_str(),
Stringify(surf->GetType()).c_str(),
Stringify(surf->GetFormat()).c_str());
MOZ_LOG(gMediaPipelineLog, LogLevel::Error,
("Reading DataSourceSurface from %s image with %s (%s) surface failed",
Stringify(format).c_str(),
Stringify(surf->GetType()).c_str(),
Stringify(surf->GetFormat()).c_str()));
return;
}
@ -436,21 +435,21 @@ protected:
aSize.height);
break;
default:
CSFLogError(LOGTAG,
"Unsupported RGB video format %s",
Stringify(surf->GetFormat()).c_str());
MOZ_LOG(gMediaPipelineLog, LogLevel::Error,
("Unsupported RGB video format %s",
Stringify(surf->GetFormat()).c_str()));
MOZ_ASSERT(PR_FALSE);
return;
}
if (rv != 0) {
CSFLogError(LOGTAG,
"%s to I420 conversion failed",
Stringify(surf->GetFormat()).c_str());
MOZ_LOG(gMediaPipelineLog, LogLevel::Error,
("%s to I420 conversion failed",
Stringify(surf->GetFormat()).c_str()));
return;
}
CSFLogDebug(LOGTAG,
"Sending an I420 video frame converted from %s",
Stringify(surf->GetFormat()).c_str());
MOZ_LOG(gMediaPipelineLog, LogLevel::Debug,
("Sending an I420 video frame converted from %s",
Stringify(surf->GetFormat()).c_str()));
webrtc::VideoFrame frame(buffer,
0, 0, // not setting timestamps
webrtc::kVideoRotation_0);
@ -706,7 +705,8 @@ MediaPipeline::MediaPipeline(const std::string& aPc,
MediaPipeline::~MediaPipeline()
{
CSFLogInfo(LOGTAG, "Destroying MediaPipeline: %s", mDescription.c_str());
MOZ_LOG(gMediaPipelineLog, LogLevel::Info,
("Destroying MediaPipeline: %s", mDescription.c_str()));
NS_ReleaseOnMainThreadSystemGroup("MediaPipeline::mConduit",
mConduit.forget());
}
@ -728,7 +728,8 @@ MediaPipeline::DetachTransport_s()
{
ASSERT_ON_THREAD(mStsThread);
CSFLogInfo(LOGTAG, "%s in %s", mDescription.c_str(), __FUNCTION__);
MOZ_LOG(gMediaPipelineLog, LogLevel::Info,
("%s in %s", mDescription.c_str(), __FUNCTION__));
disconnect_all();
mTransport->Detach();
@ -867,7 +868,7 @@ MediaPipeline::StateChange(TransportLayer* aLayer, TransportLayer::State aState)
MOZ_ASSERT(info);
if (aState == TransportLayer::TS_OPEN) {
CSFLogInfo(LOGTAG, "Flow is ready");
MOZ_LOG(gMediaPipelineLog, LogLevel::Info, ("Flow is ready"));
TransportReady_s(*info);
} else if (aState == TransportLayer::TS_CLOSED ||
aState == TransportLayer::TS_ERROR) {
@ -903,24 +904,24 @@ MediaPipeline::TransportReady_s(TransportInfo& aInfo)
// TODO(ekr@rtfm.com): implement some kind of notification on
// failure. bug 852665.
if (aInfo.mState != StateType::MP_CONNECTING) {
CSFLogError(LOGTAG,
"Transport ready for flow in wrong state:%s :%s",
mDescription.c_str(),
ToString(aInfo.mType));
MOZ_LOG(gMediaPipelineLog, LogLevel::Error,
("Transport ready for flow in wrong state:%s :%s",
mDescription.c_str(),
ToString(aInfo.mType)));
return NS_ERROR_FAILURE;
}
CSFLogInfo(LOGTAG,
"Transport ready for pipeline %p flow %s: %s",
this,
mDescription.c_str(),
ToString(aInfo.mType));
MOZ_LOG(gMediaPipelineLog, LogLevel::Info,
("Transport ready for pipeline %p flow %s: %s",
this,
mDescription.c_str(),
ToString(aInfo.mType)));
if (mDirection == DirectionType::RECEIVE) {
CSFLogInfo(LOGTAG,
"Listening for %s packets received on %p",
ToString(aInfo.mType),
aInfo.mSrtp);
MOZ_LOG(gMediaPipelineLog, LogLevel::Info,
("Listening for %s packets received on %p",
ToString(aInfo.mType),
aInfo.mSrtp));
aInfo.mSrtp->SignalPacketReceived.connect(
this, &MediaPipeline::PacketReceived);
@ -939,7 +940,8 @@ MediaPipeline::TransportFailed_s(TransportInfo& aInfo)
aInfo.mState = StateType::MP_CLOSED;
UpdateRtcpMuxState(aInfo);
CSFLogInfo(LOGTAG, "Transport closed for flow %s", ToString(aInfo.mType));
MOZ_LOG(gMediaPipelineLog, LogLevel::Info,
("Transport closed for flow %s", ToString(aInfo.mType)));
NS_WARNING(
"MediaPipeline Transport failed. This is not properly cleaned up yet");
@ -975,7 +977,8 @@ MediaPipeline::SendPacket(TransportLayer* aLayer, MediaPacket& packet)
if (res == TE_WOULDBLOCK)
return NS_OK;
CSFLogError(LOGTAG, "Failed write on stream %s", mDescription.c_str());
MOZ_LOG(gMediaPipelineLog, LogLevel::Error,
("Failed write on stream %s", mDescription.c_str()));
return NS_BASE_STREAM_CLOSED;
}
@ -989,14 +992,14 @@ MediaPipeline::IncrementRtpPacketsSent(int32_t aBytes)
mRtpBytesSent += aBytes;
if (!(mRtpPacketsSent % 100)) {
CSFLogInfo(LOGTAG,
"RTP sent packet count for %s Pipeline %p Flow: %p: %u (%" PRId64
" bytes)",
mDescription.c_str(),
this,
static_cast<void*>(mRtp.mTransport),
mRtpPacketsSent,
mRtpBytesSent);
MOZ_LOG(gMediaPipelineLog, LogLevel::Info,
("RTP sent packet count for %s Pipeline %p Flow: %p: %u (%" PRId64
" bytes)",
mDescription.c_str(),
this,
static_cast<void*>(mRtp.mTransport),
mRtpPacketsSent,
mRtpBytesSent));
}
}
@ -1005,12 +1008,12 @@ MediaPipeline::IncrementRtcpPacketsSent()
{
++mRtcpPacketsSent;
if (!(mRtcpPacketsSent % 100)) {
CSFLogInfo(LOGTAG,
"RTCP sent packet count for %s Pipeline %p Flow: %p: %u",
mDescription.c_str(),
this,
static_cast<void*>(mRtp.mTransport),
mRtcpPacketsSent);
MOZ_LOG(gMediaPipelineLog, LogLevel::Info,
("RTCP sent packet count for %s Pipeline %p Flow: %p: %u",
mDescription.c_str(),
this,
static_cast<void*>(mRtp.mTransport),
mRtcpPacketsSent));
}
}
@ -1020,15 +1023,14 @@ MediaPipeline::IncrementRtpPacketsReceived(int32_t aBytes)
++mRtpPacketsReceived;
mRtpBytesReceived += aBytes;
if (!(mRtpPacketsReceived % 100)) {
CSFLogInfo(
LOGTAG,
"RTP received packet count for %s Pipeline %p Flow: %p: %u (%" PRId64
" bytes)",
mDescription.c_str(),
this,
static_cast<void*>(mRtp.mTransport),
mRtpPacketsReceived,
mRtpBytesReceived);
MOZ_LOG(gMediaPipelineLog, LogLevel::Info,
("RTP received packet count for %s Pipeline %p Flow: %p: %u (%"
PRId64 " bytes)",
mDescription.c_str(),
this,
static_cast<void*>(mRtp.mTransport),
mRtpPacketsReceived,
mRtpBytesReceived));
}
}
@ -1037,12 +1039,12 @@ MediaPipeline::IncrementRtcpPacketsReceived()
{
++mRtcpPacketsReceived;
if (!(mRtcpPacketsReceived % 100)) {
CSFLogInfo(LOGTAG,
"RTCP received packet count for %s Pipeline %p Flow: %p: %u",
mDescription.c_str(),
this,
static_cast<void*>(mRtp.mTransport),
mRtcpPacketsReceived);
MOZ_LOG(gMediaPipelineLog, LogLevel::Info,
("RTCP received packet count for %s Pipeline %p Flow: %p: %u",
mDescription.c_str(),
this,
static_cast<void*>(mRtp.mTransport),
mRtcpPacketsReceived));
}
}
@ -1054,22 +1056,26 @@ MediaPipeline::RtpPacketReceived(TransportLayer* aLayer, MediaPacket& packet)
}
if (!mTransport->Pipeline()) {
CSFLogError(LOGTAG, "Discarding incoming packet; transport disconnected");
MOZ_LOG(gMediaPipelineLog, LogLevel::Error,
("Discarding incoming packet; transport disconnected"));
return;
}
if (!mConduit) {
CSFLogDebug(LOGTAG, "Discarding incoming packet; media disconnected");
MOZ_LOG(gMediaPipelineLog, LogLevel::Debug,
("Discarding incoming packet; media disconnected"));
return;
}
if (mRtp.mState != StateType::MP_OPEN) {
CSFLogError(LOGTAG, "Discarding incoming packet; pipeline not open");
MOZ_LOG(gMediaPipelineLog, LogLevel::Error,
("Discarding incoming packet; pipeline not open"));
return;
}
if (mRtp.mSrtp->state() != TransportLayer::TS_OPEN) {
CSFLogError(LOGTAG, "Discarding incoming packet; transport not open");
MOZ_LOG(gMediaPipelineLog, LogLevel::Error,
("Discarding incoming packet; transport not open"));
return;
}
@ -1124,7 +1130,8 @@ MediaPipeline::RtpPacketReceived(TransportLayer* aLayer, MediaPacket& packet)
}
}
CSFLogDebug(LOGTAG, "%s received RTP packet.", mDescription.c_str());
MOZ_LOG(gMediaPipelineLog, LogLevel::Debug,
("%s received RTP packet.", mDescription.c_str()));
IncrementRtpPacketsReceived(packet.len());
OnRtpPacketReceived();
@ -1146,22 +1153,26 @@ void
MediaPipeline::RtcpPacketReceived(TransportLayer* aLayer, MediaPacket& packet)
{
if (!mTransport->Pipeline()) {
CSFLogDebug(LOGTAG, "Discarding incoming packet; transport disconnected");
MOZ_LOG(gMediaPipelineLog, LogLevel::Debug,
("Discarding incoming packet; transport disconnected"));
return;
}
if (!mConduit) {
CSFLogDebug(LOGTAG, "Discarding incoming packet; media disconnected");
MOZ_LOG(gMediaPipelineLog, LogLevel::Debug,
("Discarding incoming packet; media disconnected"));
return;
}
if (mRtcp.mState != StateType::MP_OPEN) {
CSFLogDebug(LOGTAG, "Discarding incoming packet; pipeline not open");
MOZ_LOG(gMediaPipelineLog, LogLevel::Debug,
("Discarding incoming packet; pipeline not open"));
return;
}
if (mRtcp.mSrtp->state() != TransportLayer::TS_OPEN) {
CSFLogError(LOGTAG, "Discarding incoming packet; transport not open");
MOZ_LOG(gMediaPipelineLog, LogLevel::Error,
("Discarding incoming packet; transport not open"));
return;
}
@ -1175,7 +1186,8 @@ MediaPipeline::RtcpPacketReceived(TransportLayer* aLayer, MediaPacket& packet)
// have a TransportLayer that breaks up compound RTCP so we can filter them
// individually, but I doubt that will matter much.
CSFLogDebug(LOGTAG, "%s received RTCP packet.", mDescription.c_str());
MOZ_LOG(gMediaPipelineLog, LogLevel::Debug,
("%s received RTCP packet.", mDescription.c_str()));
IncrementRtcpPacketsReceived();
RtpLogger::LogPacket(packet, true, mDescription);
@ -1194,7 +1206,8 @@ void
MediaPipeline::PacketReceived(TransportLayer* aLayer, MediaPacket& packet)
{
if (!mTransport->Pipeline()) {
CSFLogDebug(LOGTAG, "Discarding incoming packet; transport disconnected");
MOZ_LOG(gMediaPipelineLog, LogLevel::Debug,
("Discarding incoming packet; transport disconnected"));
return;
}
@ -1441,11 +1454,10 @@ MediaPipelineTransmit::Start()
mConduit->StartTransmitting();
// TODO(ekr@rtfm.com): Check for errors
CSFLogDebug(
LOGTAG,
"Attaching pipeline to track %p conduit type=%s",
this,
(mConduit->type() == MediaSessionConduit::AUDIO ? "audio" : "video"));
MOZ_LOG(gMediaPipelineLog, LogLevel::Debug,
("Attaching pipeline to track %p conduit type=%s",
this,
(mConduit->type() == MediaSessionConduit::AUDIO ? "audio" : "video")));
#if !defined(MOZILLA_EXTERNAL_LINKAGE)
// With full duplex we don't risk having audio come in late to the MSG
@ -1543,12 +1555,11 @@ MediaPipelineTransmit::SetTrack(MediaStreamTrack* aDomTrack)
nsString nsTrackId;
aDomTrack->GetId(nsTrackId);
std::string track_id(NS_ConvertUTF16toUTF8(nsTrackId).get());
CSFLogDebug(
LOGTAG,
"Reattaching pipeline to track %p track %s conduit type: %s",
&aDomTrack,
track_id.c_str(),
(mConduit->type() == MediaSessionConduit::AUDIO ? "audio" : "video"));
MOZ_LOG(gMediaPipelineLog, LogLevel::Debug,
("Reattaching pipeline to track %p track %s conduit type: %s",
&aDomTrack,
track_id.c_str(),
(mConduit->type() == MediaSessionConduit::AUDIO ? "audio" : "video")));
}
RefPtr<dom::MediaStreamTrack> oldTrack = mDomTrack;
@ -1574,15 +1585,16 @@ MediaPipeline::ConnectTransport_s(TransportInfo& aInfo)
if (aInfo.mSrtp->state() == TransportLayer::TS_OPEN) {
nsresult res = TransportReady_s(aInfo);
if (NS_FAILED(res)) {
CSFLogError(LOGTAG,
"Error calling TransportReady(); res=%u in %s",
static_cast<uint32_t>(res),
__FUNCTION__);
MOZ_LOG(gMediaPipelineLog, LogLevel::Error,
("Error calling TransportReady(); res=%u in %s",
static_cast<uint32_t>(res),
__FUNCTION__));
return res;
}
} else if (aInfo.mSrtp->state() == TransportLayer::TS_ERROR) {
CSFLogError(
LOGTAG, "%s transport is already in error state", ToString(aInfo.mType));
MOZ_LOG(gMediaPipelineLog, LogLevel::Error,
("%s transport is already in error state",
ToString(aInfo.mType)));
TransportFailed_s(aInfo);
return NS_ERROR_FAILURE;
}
@ -1668,10 +1680,10 @@ MediaPipeline::PipelineTransport::SendRtpRtcpPacket_s(
mPipeline->IncrementRtcpPacketsSent();
}
CSFLogDebug(LOGTAG,
"%s sending %s packet",
mPipeline->mDescription.c_str(),
(isRtp ? "RTP" : "RTCP"));
MOZ_LOG(gMediaPipelineLog, LogLevel::Debug,
("%s sending %s packet",
mPipeline->mDescription.c_str(),
(isRtp ? "RTP" : "RTCP")));
return mPipeline->SendPacket(transport.mSrtp, packet);
}
@ -1701,13 +1713,12 @@ MediaPipelineTransmit::PipelineListener::NotifyRealtimeTrackData(
StreamTime aOffset,
const MediaSegment& aMedia)
{
CSFLogDebug(
LOGTAG,
"MediaPipeline::NotifyRealtimeTrackData() listener=%p, offset=%" PRId64
", duration=%" PRId64,
this,
aOffset,
aMedia.GetDuration());
MOZ_LOG(gMediaPipelineLog, LogLevel::Debug,
("MediaPipeline::NotifyRealtimeTrackData() listener=%p, offset=%" PRId64
", duration=%" PRId64,
this,
aOffset,
aMedia.GetDuration()));
if (aMedia.GetType() == MediaSegment::VIDEO) {
TRACE_COMMENT("Video");
@ -1726,7 +1737,8 @@ MediaPipelineTransmit::PipelineListener::NotifyQueuedChanges(
StreamTime aOffset,
const MediaSegment& aQueuedMedia)
{
CSFLogDebug(LOGTAG, "MediaPipeline::NotifyQueuedChanges()");
MOZ_LOG(gMediaPipelineLog, LogLevel::Debug,
("MediaPipeline::NotifyQueuedChanges()"));
if (aQueuedMedia.GetType() == MediaSegment::VIDEO) {
// We always get video from SetCurrentFrames().
@ -1754,11 +1766,11 @@ void
MediaPipelineTransmit::PipelineListener::NotifyDirectListenerInstalled(
InstallationResult aResult)
{
CSFLogInfo(
LOGTAG,
"MediaPipeline::NotifyDirectListenerInstalled() listener=%p, result=%d",
this,
static_cast<int32_t>(aResult));
MOZ_LOG(gMediaPipelineLog, LogLevel::Info,
("MediaPipeline::NotifyDirectListenerInstalled() listener=%p,"
" result=%d",
this,
static_cast<int32_t>(aResult)));
mDirectConnect = InstallationResult::SUCCESS == aResult;
}
@ -1766,9 +1778,9 @@ MediaPipelineTransmit::PipelineListener::NotifyDirectListenerInstalled(
void
MediaPipelineTransmit::PipelineListener::NotifyDirectListenerUninstalled()
{
CSFLogInfo(LOGTAG,
"MediaPipeline::NotifyDirectListenerUninstalled() listener=%p",
this);
MOZ_LOG(gMediaPipelineLog, LogLevel::Info,
("MediaPipeline::NotifyDirectListenerUninstalled() listener=%p",
this));
mDirectConnect = false;
}
@ -1778,7 +1790,8 @@ MediaPipelineTransmit::PipelineListener::NewData(const MediaSegment& aMedia,
TrackRate aRate /* = 0 */)
{
if (!mActive) {
CSFLogDebug(LOGTAG, "Discarding packets because transport not ready");
MOZ_LOG(gMediaPipelineLog, LogLevel::Debug,
("Discarding packets because transport not ready"));
return;
}
@ -1851,13 +1864,12 @@ public:
} else if (mTrack->AsVideoStreamTrack()) {
mSource->AddTrack(mTrackId, 0, new VideoSegment());
}
CSFLogDebug(
LOGTAG,
"GenericReceiveListener added %s track %d (%p) to stream %p",
mTrack->AsAudioStreamTrack() ? "audio" : "video",
mTrackId,
mTrack.get(),
mSource.get());
MOZ_LOG(gMediaPipelineLog, LogLevel::Debug,
("GenericReceiveListener added %s track %d (%p) to stream %p",
mTrack->AsAudioStreamTrack() ? "audio" : "video",
mTrackId,
mTrack.get(),
mSource.get()));
mSource->AdvanceKnownTracksTime(STREAM_TIME_MAX);
mSource->AddListener(this);
@ -1900,8 +1912,7 @@ public:
void EndTrack()
{
CSFLogDebug(LOGTAG, "GenericReceiveListener ending track");
MOZ_LOG(gMediaPipelineLog, LogLevel::Debug, ("GenericReceiveListener ending track"));
// This breaks the cycle with the SourceMediaStream
mSource->RemoveListener(this);
@ -2033,13 +2044,13 @@ private:
if (err != kMediaConduitNoError) {
// Insert silence on conduit/GIPS failure (extremely unlikely)
CSFLogError(LOGTAG,
"Audio conduit failed (%d) to return data @ %" PRId64
" (desired %" PRId64 " -> %f)",
err,
mPlayedTicks,
aDesiredTime,
mSource->StreamTimeToSeconds(aDesiredTime));
MOZ_LOG(gMediaPipelineLog, LogLevel::Error,
("Audio conduit failed (%d) to return data @ %" PRId64
" (desired %" PRId64 " -> %f)",
err,
mPlayedTicks,
aDesiredTime,
mSource->StreamTimeToSeconds(aDesiredTime)));
// if this is not enough we'll loop and provide more
samplesLength = samplesPer10ms;
PodArrayZero(scratchBuffer);
@ -2047,8 +2058,8 @@ private:
MOZ_RELEASE_ASSERT(samplesLength <= scratchBufferLength);
CSFLogDebug(
LOGTAG, "Audio conduit returned buffer of length %u", samplesLength);
MOZ_LOG(gMediaPipelineLog, LogLevel::Debug,
("Audio conduit returned buffer of length %u", samplesLength));
RefPtr<SharedBuffer> samples =
SharedBuffer::Create(samplesLength * sizeof(uint16_t));
@ -2095,7 +2106,7 @@ private:
}
}
} else {
CSFLogError(LOGTAG, "AppendToTrack failed");
MOZ_LOG(gMediaPipelineLog, LogLevel::Error, ("AppendToTrack failed"));
// we can't un-read the data, but that's ok since we don't want to
// buffer - but don't i-loop!
break;
@ -2199,7 +2210,7 @@ public:
segment.AppendFrame(image.forget(), delta, size, mPrincipalHandle);
// Handle track not actually added yet or removed/finished
if (!mSource->AppendToTrack(mTrackId, &segment)) {
CSFLogError(LOGTAG, "AppendToTrack failed");
MOZ_LOG(gMediaPipelineLog, LogLevel::Error, ("AppendToTrack failed"));
return;
}
mPlayedTicks = aDesiredTime;

View file

@ -11,13 +11,10 @@
#include "webrtc/common_types.h"
#include "CSFLog.h"
#include "mozilla/Logging.h"
static const char* mpfLogTag = "MediaPipelineFilter";
#ifdef LOGTAG
#undef LOGTAG
#endif
#define LOGTAG mpfLogTag
// defined in MediaPipeline.cpp
extern mozilla::LazyLogModule gMediaPipelineLog;
namespace mozilla {
@ -45,10 +42,10 @@ bool MediaPipelineFilter::Filter(const webrtc::RTPHeader& header,
return true;
}
if (!header.extension.rtpStreamId.empty()) {
CSFLogDebug(LOGTAG,
"MediaPipelineFilter ignoring seq# %u ssrc: %u RID: %s",
header.sequenceNumber, header.ssrc,
header.extension.rtpStreamId.data());
MOZ_LOG(gMediaPipelineLog, LogLevel::Debug,
("MediaPipelineFilter ignoring seq# %u ssrc: %u RID: %s",
header.sequenceNumber, header.ssrc,
header.extension.rtpStreamId.data()));
}
if (remote_ssrc_set_.count(header.ssrc)) {

View file

@ -6,8 +6,6 @@
#include "RtpLogger.h"
#include "CSFLog.h"
#include <ctime>
#include <iomanip>
#include <sstream>
@ -21,25 +19,21 @@
// Logging context
using namespace mozilla;
static const char* rlLogTag = "RtpLogger";
#ifdef LOGTAG
#undef LOGTAG
#endif
#define LOGTAG rlLogTag
mozilla::LazyLogModule gRtpLoggerLog("RtpLogger");
namespace mozilla {
bool RtpLogger::IsPacketLoggingOn() {
return CSFLogTestLevel(CSF_LOG_DEBUG);
return MOZ_LOG_TEST(gRtpLoggerLog, LogLevel::Debug);
}
void RtpLogger::LogPacket(const MediaPacket& packet, bool input,
std::string desc) {
if (CSFLogTestLevel(CSF_LOG_DEBUG)) {
if (MOZ_LOG_TEST(gRtpLoggerLog, LogLevel::Debug)) {
bool isRtp = (packet.type() == MediaPacket::RTP);
std::stringstream ss;
/* This creates text2pcap compatible format, e.g.:
* RTCP_PACKET O 10:36:26.864934 000000 80 c8 00 06 6d ...
* RTCP_PACKET O 10:36:26.864934 000000 80 c8 00 06 6d ...
*/
ss << (input ? "I " : "O ");
std::time_t t = std::time(nullptr);
@ -63,10 +57,10 @@ void RtpLogger::LogPacket(const MediaPacket& packet, bool input,
for (size_t i=0; i < packet.len(); ++i) {
ss << " " << std::setw(2) << (int)packet.data()[i];
}
CSFLogDebug(LOGTAG, "%s%s%s", desc.c_str(),
(isRtp ? " RTP_PACKET " : " RTCP_PACKET "), ss.str().c_str());
MOZ_LOG(gRtpLoggerLog, LogLevel::Debug,
("%s%s%s", desc.c_str(),
(isRtp ? " RTP_PACKET " : " RTCP_PACKET "), ss.str().c_str()));
}
}
} // end of namespace

View file

@ -12,7 +12,6 @@ LOCAL_INCLUDES += [
'/media/libyuv/libyuv/include',
'/media/mtransport',
'/media/webrtc',
'/media/webrtc/signaling/src/common/browser_logging',
'/media/webrtc/signaling/src/media-conduit',
'/media/webrtc/trunk',
'/netwerk/srtp/src/crypto/include',

View file

@ -87,6 +87,22 @@ VARCACHE_PREF(
RelaxedAtomicBool, false
)
//---------------------------------------------------------------------------
// Clipboard prefs
//---------------------------------------------------------------------------
#if !defined(ANDROID) && !defined(XP_MACOSX) && defined(XP_UNIX)
# define PREF_VALUE true
#else
# define PREF_VALUE false
#endif
VARCACHE_PREF(
"clipboard.autocopy",
clipboard_autocopy,
bool, PREF_VALUE
)
#undef PREF_VALUE
//---------------------------------------------------------------------------
// DOM prefs
//---------------------------------------------------------------------------

View file

@ -1174,4 +1174,4 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
static const int32_t kUnknownId = -1;
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1543836493627000);
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1544097545444000);

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -342,7 +342,7 @@ pub trait TShadowRoot: Sized + Copy + Clone + PartialEq {
fn host(&self) -> <Self::ConcreteNode as TNode>::ConcreteElement;
/// Get the style data for this ShadowRoot.
fn style_data<'a>(&self) -> &'a CascadeData
fn style_data<'a>(&self) -> Option<&'a CascadeData>
where
Self: 'a;
@ -824,30 +824,36 @@ pub trait TElement:
if let Some(shadow) = self.containing_shadow() {
doc_rules_apply = false;
f(
shadow.style_data(),
self.as_node().owner_doc().quirks_mode(),
Some(shadow.host()),
);
if let Some(data) = shadow.style_data() {
f(
data,
self.as_node().owner_doc().quirks_mode(),
Some(shadow.host()),
);
}
}
if let Some(shadow) = self.shadow_root() {
f(
shadow.style_data(),
self.as_node().owner_doc().quirks_mode(),
Some(shadow.host()),
);
if let Some(data) = shadow.style_data() {
f(
data,
self.as_node().owner_doc().quirks_mode(),
Some(shadow.host()),
);
}
}
let mut current = self.assigned_slot();
while let Some(slot) = current {
// Slots can only have assigned nodes when in a shadow tree.
let shadow = slot.containing_shadow().unwrap();
f(
shadow.style_data(),
self.as_node().owner_doc().quirks_mode(),
Some(shadow.host()),
);
if let Some(data) = shadow.style_data() {
f(
data,
self.as_node().owner_doc().quirks_mode(),
Some(shadow.host()),
);
}
current = slot.assigned_slot();
}

View file

@ -167,15 +167,14 @@ impl<'lr> TShadowRoot for GeckoShadowRoot<'lr> {
}
#[inline]
fn style_data<'a>(&self) -> &'a CascadeData
fn style_data<'a>(&self) -> Option<&'a CascadeData>
where
Self: 'a,
{
debug_assert!(!self.0.mServoStyles.mPtr.is_null());
let author_styles = unsafe {
&*(self.0.mServoStyles.mPtr as *const structs::RawServoAuthorStyles
as *const bindings::RawServoAuthorStyles)
(self.0.mServoStyles.mPtr
as *const structs::RawServoAuthorStyles
as *const bindings::RawServoAuthorStyles).as_ref()?
};
@ -187,7 +186,7 @@ impl<'lr> TShadowRoot for GeckoShadowRoot<'lr> {
author_styles.stylesheets.dirty()
);
&author_styles.data
Some(&author_styles.data)
}
#[inline]

View file

@ -1209,7 +1209,7 @@ impl Stylist {
// to add some sort of AuthorScoped cascade level or something.
if matches_author_rules {
if let Some(shadow) = rule_hash_target.shadow_root() {
if let Some(map) = shadow.style_data().host_rules(pseudo_element) {
if let Some(map) = shadow.style_data().and_then(|data| data.host_rules(pseudo_element)) {
context.with_shadow_host(Some(rule_hash_target), |context| {
map.get_all_matching_rules(
element,
@ -1236,8 +1236,7 @@ impl Stylist {
for slot in slots.iter().rev() {
let shadow = slot.containing_shadow().unwrap();
let styles = shadow.style_data();
if let Some(map) = styles.slotted_rules(pseudo_element) {
if let Some(map) = shadow.style_data().and_then(|data| data.slotted_rules(pseudo_element)) {
context.with_shadow_host(Some(shadow.host()), |context| {
map.get_all_matching_rules(
element,
@ -1256,7 +1255,7 @@ impl Stylist {
if let Some(containing_shadow) = rule_hash_target.containing_shadow() {
let cascade_data = containing_shadow.style_data();
let host = containing_shadow.host();
if let Some(map) = cascade_data.normal_rules(pseudo_element) {
if let Some(map) = cascade_data.and_then(|data| data.normal_rules(pseudo_element)) {
context.with_shadow_host(Some(host), |context| {
map.get_all_matching_rules(
element,
@ -1286,6 +1285,11 @@ impl Stylist {
//
// See: https://github.com/w3c/svgwg/issues/505
//
// FIXME(emilio, bug 1487259): We now do after bug 1483882, we
// should jump out of the <svg:use> shadow tree chain now.
//
// Unless the used node is cross-doc, I guess, in which case doc
// rules are probably ok...
let host_is_svg_use =
host.is_svg_element() &&
host.local_name() == &*local_name!("use");
@ -1434,11 +1438,15 @@ impl Stylist {
// [2]: https://github.com/w3c/csswg-drafts/issues/1995
// [3]: https://bugzil.la/1458189
if let Some(shadow) = element.shadow_root() {
try_find_in!(shadow.style_data());
if let Some(data) = shadow.style_data() {
try_find_in!(data);
}
}
if let Some(shadow) = element.containing_shadow() {
try_find_in!(shadow.style_data());
if let Some(data) = shadow.style_data() {
try_find_in!(data);
}
} else {
try_find_in!(self.cascade_data.author);
}

View file

@ -1061,7 +1061,7 @@ LoginManagerPrompter.prototype = {
// Ugh. We can't use the strings from the popup window, because they
// have the access key marked in the string (eg "Mo&zilla"), along
// with some weird rules for handling access keys that do not occur
// in the string, for L10N. See commonDialog.js's setLabelForNode().
// in the string, for L10N. See CommonDialog.jsm's setLabelForNode().
var neverButtonText =
this._getLocalizedString("notifyBarNeverRememberButtonText2");
var neverButtonAccessKey =

View file

@ -1515,11 +1515,11 @@ var update = async function(db, pageInfo) {
baseParams.url = pageInfo.url.href;
}
if (pageInfo.description || pageInfo.description === null) {
if ("description" in pageInfo) {
updateFragments.push("description");
params.description = pageInfo.description;
}
if (pageInfo.previewImageURL || pageInfo.previewImageURL === null) {
if ("previewImageURL" in pageInfo) {
updateFragments.push("preview_image_url");
params.preview_image_url = pageInfo.previewImageURL ? pageInfo.previewImageURL.href : null;
}

View file

@ -455,7 +455,7 @@ var PlacesDBUtils = {
// D.4 move orphan items to unsorted folder
{ query:
`UPDATE moz_bookmarks SET
parent = :unsorted_folder
parent = (SELECT id FROM moz_bookmarks WHERE guid = :unfiledGuid)
WHERE guid NOT IN (
:rootGuid, :menuGuid, :toolbarGuid, :unfiledGuid, :tagsGuid /* skip roots */
) AND id IN (
@ -464,7 +464,6 @@ var PlacesDBUtils = {
(SELECT id FROM moz_bookmarks WHERE id = b.parent LIMIT 1)
)`,
params: {
unsorted_folder: PlacesUtils.unfiledBookmarksFolderId,
rootGuid: PlacesUtils.bookmarks.rootGuid,
menuGuid: PlacesUtils.bookmarks.menuGuid,
toolbarGuid: PlacesUtils.bookmarks.toolbarGuid,
@ -530,7 +529,7 @@ var PlacesDBUtils = {
// as parent, if they have bad parent move them to unsorted bookmarks.
{ query:
`UPDATE moz_bookmarks SET
parent = :unsorted_folder
parent = (SELECT id FROM moz_bookmarks WHERE guid = :unfiledGuid)
WHERE guid NOT IN (
:rootGuid, :menuGuid, :toolbarGuid, :unfiledGuid, :tagsGuid /* skip roots */
) AND id IN (
@ -541,7 +540,6 @@ var PlacesDBUtils = {
LIMIT 1)
)`,
params: {
unsorted_folder: PlacesUtils.unfiledBookmarksFolderId,
bookmark_type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
separator_type: PlacesUtils.bookmarks.TYPE_SEPARATOR,
rootGuid: PlacesUtils.bookmarks.rootGuid,

View file

@ -1062,16 +1062,16 @@ var PlacesUtils = {
throw new TypeError(`title property of PageInfo object: ${pageInfo.title} must be a string if provided`);
}
if (typeof pageInfo.description === "string" || pageInfo.description === null) {
if ("description" in pageInfo && (typeof pageInfo.description === "string" || pageInfo.description === null)) {
info.description = pageInfo.description ? pageInfo.description.slice(0, DB_DESCRIPTION_LENGTH_MAX) : null;
} else if (pageInfo.description !== undefined) {
throw new TypeError(`description property of pageInfo object: ${pageInfo.description} must be either a string or null if provided`);
}
if (pageInfo.previewImageURL || pageInfo.previewImageURL === null) {
if ("previewImageURL" in pageInfo) {
let previewImageURL = pageInfo.previewImageURL;
if (previewImageURL === null) {
if (!previewImageURL) {
info.previewImageURL = null;
} else if (typeof(previewImageURL) === "string" && previewImageURL.length <= DB_URL_LENGTH_MAX) {
info.previewImageURL = new URL(previewImageURL);
@ -1278,11 +1278,6 @@ var PlacesUtils = {
return this.tagsFolderId = this.bookmarks.tagsFolder;
},
get unfiledBookmarksFolderId() {
delete this.unfiledBookmarksFolderId;
return this.unfiledBookmarksFolderId = this.bookmarks.unfiledBookmarksFolder;
},
/**
* Checks if item is a root.
*

View file

@ -286,11 +286,6 @@ interface nsINavBookmarksService : nsISupports
*/
readonly attribute long long tagsFolder;
/**
* The item ID of the unfiled-bookmarks folder.
*/
readonly attribute long long unfiledBookmarksFolder;
/**
* The item ID of the personal toolbar folder.
*/

View file

@ -340,16 +340,6 @@ nsNavBookmarks::GetTagsFolder(int64_t* aRoot)
}
NS_IMETHODIMP
nsNavBookmarks::GetUnfiledBookmarksFolder(int64_t* aRoot)
{
int64_t id = mDB->GetUnfiledFolderId();
NS_ENSURE_TRUE(id > 0, NS_ERROR_UNEXPECTED);
*aRoot = id;
return NS_OK;
}
NS_IMETHODIMP
nsNavBookmarks::GetTotalSyncChanges(int64_t* aTotalSyncChanges)
{

View file

@ -219,7 +219,7 @@ add_task(async function update_move_different_folder() {
let folder = await PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_FOLDER,
parentGuid: PlacesUtils.bookmarks.unfiledGuid });
let bmItemId = await PlacesUtils.promiseItemId(bm.guid);
let bmOldParentId = PlacesUtils.unfiledBookmarksFolderId;
let bmOldParentId = await PlacesUtils.promiseItemId(PlacesUtils.bookmarks.unfiledGuid);
let bmOldIndex = bm.index;
let observer = expectNotifications();
@ -512,14 +512,16 @@ add_task(async function reorder_notification() {
sorted.map(bm => bm.guid));
let expectedNotifications = [];
let unfiledBookmarksFolderId =
await PlacesUtils.promiseItemId(PlacesUtils.bookmarks.unfiledGuid);
for (let i = 0; i < sorted.length; ++i) {
let child = sorted[i];
let childId = await PlacesUtils.promiseItemId(child.guid);
expectedNotifications.push({ name: "onItemMoved",
arguments: [ childId,
PlacesUtils.unfiledBookmarksFolderId,
unfiledBookmarksFolderId,
child.index,
PlacesUtils.unfiledBookmarksFolderId,
unfiledBookmarksFolderId,
i,
child.type,
child.guid,

View file

@ -6,10 +6,12 @@ add_task(async function boookmarks_tree_cache() {
// bookmarks methods - using, eg, PlacesUtils.bookmarks.insert() doesn't
// demonstrate the problem as it indirectly arranges for the observers to
// be added.
let id = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
uri("http://example.com"),
PlacesUtils.bookmarks.DEFAULT_INDEX,
"A title");
let id = PlacesUtils.bookmarks.insertBookmark(
await PlacesUtils.promiseItemId(PlacesUtils.bookmarks.unfiledGuid),
uri("http://example.com"),
PlacesUtils.bookmarks.DEFAULT_INDEX,
"A title");
await PlacesUtils.promiseBookmarksTree();
PlacesUtils.bookmarks.removeItem(id);

View file

@ -3,6 +3,8 @@
// Tests that each nsINavBookmarksObserver method gets the correct input.
var gUnfiledFolderId;
var gBookmarksObserver = {
expected: [],
setup(expected) {
@ -96,9 +98,11 @@ var gBookmarkSkipObserver = {
};
add_task(function setup() {
add_task(async function setup() {
PlacesUtils.bookmarks.addObserver(gBookmarksObserver);
PlacesUtils.bookmarks.addObserver(gBookmarkSkipObserver);
gUnfiledFolderId = await PlacesUtils.promiseItemId(PlacesUtils.bookmarks.unfiledGuid);
});
add_task(async function onItemAdded_bookmark() {
@ -112,7 +116,7 @@ add_task(async function onItemAdded_bookmark() {
{ name: "onItemAdded",
args: [
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
{ name: "parentId", check: v => v === PlacesUtils.unfiledBookmarksFolderId },
{ name: "parentId", check: v => v === gUnfiledFolderId },
{ name: "index", check: v => v === 0 },
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK },
{ name: "uri", check: v => v instanceof Ci.nsIURI && v.equals(uri) },
@ -140,7 +144,7 @@ add_task(async function onItemAdded_separator() {
{ name: "onItemAdded",
args: [
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
{ name: "parentId", check: v => v === PlacesUtils.unfiledBookmarksFolderId },
{ name: "parentId", check: v => v === gUnfiledFolderId },
{ name: "index", check: v => v === 1 },
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_SEPARATOR },
{ name: "uri", check: v => v === null },
@ -168,7 +172,7 @@ add_task(async function onItemAdded_folder() {
{ name: "onItemAdded",
args: [
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
{ name: "parentId", check: v => v === PlacesUtils.unfiledBookmarksFolderId },
{ name: "parentId", check: v => v === gUnfiledFolderId },
{ name: "index", check: v => v === 2 },
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_FOLDER },
{ name: "uri", check: v => v === null },
@ -206,7 +210,7 @@ add_task(async function onItemChanged_title_bookmark() {
{ name: "newValue", check: v => v === title },
{ name: "lastModified", check: v => typeof(v) == "number" && v > 0 },
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK },
{ name: "parentId", check: v => v === PlacesUtils.unfiledBookmarksFolderId },
{ name: "parentId", check: v => v === gUnfiledFolderId },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "oldValue", check: v => typeof(v) == "string" },
@ -263,7 +267,7 @@ add_task(async function onItemChanged_tags_bookmark() {
{ name: "newValue", check: v => v === "" },
{ name: "lastModified", check: v => typeof(v) == "number" && v > 0 },
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK },
{ name: "parentId", check: v => v === PlacesUtils.unfiledBookmarksFolderId },
{ name: "parentId", check: v => v === gUnfiledFolderId },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "oldValue", check: v => typeof(v) == "string" },
@ -299,7 +303,7 @@ add_task(async function onItemChanged_tags_bookmark() {
{ name: "newValue", check: v => v === "" },
{ name: "lastModified", check: v => typeof(v) == "number" && v > 0 },
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK },
{ name: "parentId", check: v => v === PlacesUtils.unfiledBookmarksFolderId },
{ name: "parentId", check: v => v === gUnfiledFolderId },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "oldValue", check: v => typeof(v) == "string" },
@ -324,7 +328,7 @@ add_task(async function onItemMoved_bookmark() {
{ name: "onItemMoved",
args: [
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
{ name: "oldParentId", check: v => v === PlacesUtils.unfiledBookmarksFolderId },
{ name: "oldParentId", check: v => v === gUnfiledFolderId },
{ name: "oldIndex", check: v => v === 0 },
{ name: "newParentId", check: v => v === PlacesUtils.toolbarFolderId },
{ name: "newIndex", check: v => v === 0 },
@ -340,7 +344,7 @@ add_task(async function onItemMoved_bookmark() {
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
{ name: "oldParentId", check: v => v === PlacesUtils.toolbarFolderId },
{ name: "oldIndex", check: v => v === 0 },
{ name: "newParentId", check: v => v === PlacesUtils.unfiledBookmarksFolderId },
{ name: "newParentId", check: v => v === gUnfiledFolderId },
{ name: "newIndex", check: v => v === 0 },
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
@ -381,7 +385,7 @@ add_task(async function onItemMoved_bookmark() {
{ name: "time", check: v => typeof(v) == "number" && v > 0 },
{ name: "transitionType", check: v => v === PlacesUtils.history.TRANSITION_TYPED },
{ name: "uri", check: v => v instanceof Ci.nsIURI && v.equals(uri) },
{ name: "parentId", check: v => v === PlacesUtils.unfiledBookmarksFolderId },
{ name: "parentId", check: v => v === gUnfiledFolderId },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
] },
@ -404,7 +408,7 @@ add_task(async function onItemRemoved_bookmark() {
{ name: "onItemRemoved",
args: [
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
{ name: "parentId", check: v => v === PlacesUtils.unfiledBookmarksFolderId },
{ name: "parentId", check: v => v === gUnfiledFolderId },
{ name: "index", check: v => v === 0 },
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK },
{ name: "uri", check: v => v instanceof Ci.nsIURI && v.equals(uri) },
@ -482,7 +486,7 @@ add_task(async function onItemRemoved_folder_recursive() {
{ name: "onItemAdded",
args: [
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
{ name: "parentId", check: v => v === PlacesUtils.unfiledBookmarksFolderId },
{ name: "parentId", check: v => v === gUnfiledFolderId },
{ name: "index", check: v => v === 0 },
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_FOLDER },
{ name: "uri", check: v => v === null },

View file

@ -326,26 +326,6 @@ function visits_in_database(aURI) {
}
}
/**
* Checks that we don't have any bookmark
*/
function check_no_bookmarks() {
let query = PlacesUtils.history.getNewQuery();
let folders = [
PlacesUtils.bookmarks.toolbarFolder,
PlacesUtils.bookmarks.bookmarksMenuFolder,
PlacesUtils.bookmarks.unfiledBookmarksFolder,
];
query.setFolders(folders, 3);
let options = PlacesUtils.history.getNewQueryOptions();
options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS;
let root = PlacesUtils.history.executeQuery(query, options).root;
root.containerOpen = true;
if (root.childCount != 0)
do_throw("Unable to remove all bookmarks");
root.containerOpen = false;
}
/**
* Allows waiting for an observer notification once.
*

View file

@ -158,6 +158,11 @@ add_task(async function test_previewImageURL_change_saved() {
await PlacesUtils.history.update({ url: TEST_URL, guid, previewImageURL });
previewImageURLInDB = await PlacesTestUtils.fieldInDB(TEST_URL, "preview_image_url");
Assert.equal(previewImageURL, previewImageURLInDB, "previewImageURL should be updated via GUID as expected");
previewImageURL = "";
await PlacesUtils.history.update({ url: TEST_URL, previewImageURL});
previewImageURLInDB = await PlacesTestUtils.fieldInDB(TEST_URL, "preview_image_url");
Assert.strictEqual(null, previewImageURLInDB, "an empty previewImageURL should set it to null in the database");
});
add_task(async function test_change_description_and_preview_saved() {

View file

@ -83,7 +83,6 @@ add_task(async function test_bookmarks() {
Assert.ok(bs.bookmarksMenuFolder > 0);
Assert.ok(bs.tagsFolder > 0);
Assert.ok(bs.toolbarFolder > 0);
Assert.ok(bs.unfiledBookmarksFolder > 0);
// test getFolderIdForItem() with bogus item id will throw
try {
@ -101,7 +100,6 @@ add_task(async function test_bookmarks() {
Assert.equal(bs.getFolderIdForItem(bs.bookmarksMenuFolder), bs.placesRoot);
Assert.equal(bs.getFolderIdForItem(bs.tagsFolder), bs.placesRoot);
Assert.equal(bs.getFolderIdForItem(bs.toolbarFolder), bs.placesRoot);
Assert.equal(bs.getFolderIdForItem(bs.unfiledBookmarksFolder), bs.placesRoot);
// create a folder to hold all the tests
// this makes the tests more tolerant of changes to default_places.html

View file

@ -18,7 +18,7 @@ var as = PlacesUtils.annotations;
var fs = PlacesUtils.favicons;
var mDBConn = hs.DBConnection;
var gUnfiledFolderId;
// ------------------------------------------------------------------------------
// Helpers
@ -87,7 +87,7 @@ function addBookmark(aPlaceId, aType, aParent, aKeywordId, aFolderType, aTitle,
:guid, :sync_status, :change_counter)`);
stmt.params.place_id = aPlaceId || null;
stmt.params.type = aType || bs.TYPE_BOOKMARK;
stmt.params.parent = aParent || bs.unfiledBookmarksFolder;
stmt.params.parent = aParent || gUnfiledFolderId;
stmt.params.keyword_id = aKeywordId || null;
stmt.params.folder_type = aFolderType || null;
stmt.params.title = typeof(aTitle) == "string" ? aTitle : null;
@ -558,22 +558,22 @@ tests.push({
// Check that bookmarks are now children of a real folder (unfiled)
let expectedInfos = [{
id: this._orphanBookmarkId,
parent: bs.unfiledBookmarksFolder,
parent: gUnfiledFolderId,
syncChangeCounter: 1,
}, {
id: this._orphanSeparatorId,
parent: bs.unfiledBookmarksFolder,
parent: gUnfiledFolderId,
syncChangeCounter: 1,
}, {
id: this._orphanFolderId,
parent: bs.unfiledBookmarksFolder,
parent: gUnfiledFolderId,
syncChangeCounter: 1,
}, {
id: this._bookmarkId,
parent: this._orphanFolderId,
syncChangeCounter: 0,
}, {
id: bs.unfiledBookmarksFolder,
id: gUnfiledFolderId,
parent: bs.placesRoot,
syncChangeCounter: 3,
}];
@ -692,14 +692,14 @@ tests.push({
// Check that bookmarks are now children of a real folder (unfiled)
let expectedInfos = [{
id: this._bookmarkId1,
parent: bs.unfiledBookmarksFolder,
parent: gUnfiledFolderId,
syncChangeCounter: 1,
}, {
id: this._bookmarkId2,
parent: bs.unfiledBookmarksFolder,
parent: gUnfiledFolderId,
syncChangeCounter: 1,
}, {
id: bs.unfiledBookmarksFolder,
id: gUnfiledFolderId,
parent: bs.placesRoot,
syncChangeCounter: 2,
}];
@ -749,7 +749,8 @@ tests.push({
source: PlacesUtils.bookmarks.SOURCES.SYNC,
});
function randomize_positions(aParent, aResultArray) {
async function randomize_positions(aParent, aResultArray) {
let parentId = await PlacesUtils.promiseItemId(aParent);
let stmt = mDBConn.createStatement(
`UPDATE moz_bookmarks SET position = :rand
WHERE id IN (
@ -758,7 +759,7 @@ tests.push({
)`
);
for (let i = 0; i < (NUM_BOOKMARKS / 2); i++) {
stmt.params.parent = aParent;
stmt.params.parent = parentId;
stmt.params.rand = Math.round(Math.random() * (NUM_BOOKMARKS - 1));
stmt.execute();
stmt.reset();
@ -771,7 +772,7 @@ tests.push({
FROM moz_bookmarks WHERE parent = :parent
ORDER BY position ASC, ROWID ASC`
);
stmt.params.parent = aParent;
stmt.params.parent = parentId;
while (stmt.executeStep()) {
aResultArray.push(stmt.row.id);
print(stmt.row.id + "\t" + stmt.row.position + "\t" +
@ -781,9 +782,10 @@ tests.push({
}
// Set random positions for the added bookmarks.
randomize_positions(PlacesUtils.unfiledBookmarksFolderId,
this._unfiledBookmarks);
randomize_positions(PlacesUtils.toolbarFolderId, this._toolbarBookmarks);
await randomize_positions(PlacesUtils.bookmarks.unfiledGuid,
this._unfiledBookmarks);
await randomize_positions(PlacesUtils.bookmarks.toolbarGuid,
this._toolbarBookmarks);
let syncInfos = await PlacesTestUtils.fetchBookmarkSyncFields(
PlacesUtils.bookmarks.unfiledGuid, PlacesUtils.bookmarks.toolbarGuid);
@ -794,12 +796,13 @@ tests.push({
let db = await PlacesUtils.promiseDBConnection();
async function check_order(aParent, aResultArray) {
let parentId = await PlacesUtils.promiseItemId(aParent);
// Build the expected ordered list of bookmarks.
let childRows = await db.executeCached(
`SELECT id, position, syncChangeCounter FROM moz_bookmarks
WHERE parent = :parent
ORDER BY position ASC`,
{ parent: aParent }
{ parent: parentId }
);
for (let row of childRows) {
let id = row.getResultByName("id");
@ -813,15 +816,15 @@ tests.push({
let parentRows = await db.executeCached(
`SELECT syncChangeCounter FROM moz_bookmarks
WHERE id = :parent`,
{ parent: aParent });
{ parent: parentId });
for (let row of parentRows) {
let actualChangeCounter = row.getResultByName("syncChangeCounter");
Assert.ok(actualChangeCounter > 0);
}
}
await check_order(PlacesUtils.unfiledBookmarksFolderId, this._unfiledBookmarks);
await check_order(PlacesUtils.toolbarFolderId, this._toolbarBookmarks);
await check_order(PlacesUtils.bookmarks.unfiledGuid, this._unfiledBookmarks);
await check_order(PlacesUtils.bookmarks.toolbarGuid, this._toolbarBookmarks);
},
});
@ -1861,7 +1864,7 @@ tests.push({
}, {
guid: "bookmarkCCCC",
placeId: null,
parentId: bs.unfiledBookmarksFolder,
parentId: gUnfiledFolderId,
dateAdded: null,
lastModified: null,
}, {
@ -1873,13 +1876,13 @@ tests.push({
}, {
guid: "bookmarkEEEE",
placeId: placeIdWithVisits,
parentId: bs.unfiledBookmarksFolder,
parentId: gUnfiledFolderId,
dateAdded: PlacesUtils.toPRTime(new Date(2017, 9, 3)),
lastModified: PlacesUtils.toPRTime(new Date(2017, 9, 6)),
}, {
guid: "bookmarkFFFF",
placeId: placeIdWithZeroVisit,
parentId: bs.unfiledBookmarksFolder,
parentId: gUnfiledFolderId,
dateAdded: 0,
lastModified: 0,
});
@ -1994,7 +1997,7 @@ tests.push({
async setup() {
this._bookmarksWithDates.push({
guid: "bookmarkGGGG",
parentId: bs.unfiledBookmarksFolder,
parentId: gUnfiledFolderId,
dateAdded: PlacesUtils.toPRTime(new Date(2017, 9, 6)),
lastModified: PlacesUtils.toPRTime(new Date(2017, 9, 3)),
});
@ -2191,6 +2194,9 @@ tests.push({
// ------------------------------------------------------------------------------
add_task(async function test_preventive_maintenance() {
gUnfiledFolderId =
await PlacesUtils.promiseItemId(PlacesUtils.bookmarks.unfiledGuid);
// Get current bookmarks max ID for cleanup
let stmt = mDBConn.createStatement("SELECT MAX(id) FROM moz_bookmarks");
stmt.executeStep();
@ -2219,6 +2225,6 @@ add_task(async function test_preventive_maintenance() {
Assert.equal(bs.getFolderIdForItem(bs.placesRoot), 0);
Assert.equal(bs.getFolderIdForItem(bs.bookmarksMenuFolder), bs.placesRoot);
Assert.equal(bs.getFolderIdForItem(bs.tagsFolder), bs.placesRoot);
Assert.equal(bs.getFolderIdForItem(bs.unfiledBookmarksFolder), bs.placesRoot);
Assert.equal(bs.getFolderIdForItem(gUnfiledFolderId), bs.placesRoot);
Assert.equal(bs.getFolderIdForItem(bs.toolbarFolder), bs.placesRoot);
});

View file

@ -7,6 +7,9 @@ add_task(async function test_livemarks() {
try {
let buf = await openMirror("livemarks");
let unfiledFolderId =
await PlacesUtils.promiseItemId(PlacesUtils.bookmarks.unfiledGuid);
info("Set up mirror");
await PlacesUtils.bookmarks.insertTree({
guid: PlacesUtils.bookmarks.menuGuid,
@ -264,7 +267,7 @@ add_task(async function test_livemarks() {
}, {
name: "onItemAdded",
params: { itemId: livemarkE.id,
parentId: PlacesUtils.unfiledBookmarksFolderId,
parentId: unfiledFolderId,
index: 0, type: PlacesUtils.bookmarks.TYPE_FOLDER,
urlHref: null, title: "E", guid: "livemarkEEEE",
parentGuid: "unfiled_____",
@ -344,7 +347,7 @@ add_task(async function test_livemarks() {
params: { itemId: livemarkE.id, property: PlacesUtils.LMANNO_FEEDURI,
isAnnoProperty: true, newValue: "",
type: PlacesUtils.bookmarks.TYPE_FOLDER,
parentId: PlacesUtils.unfiledBookmarksFolderId,
parentId: unfiledFolderId,
guid: "livemarkEEEE",
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
oldValue: "",
@ -354,7 +357,7 @@ add_task(async function test_livemarks() {
params: { itemId: livemarkE.id, property: PlacesUtils.LMANNO_SITEURI,
isAnnoProperty: true, newValue: "",
type: PlacesUtils.bookmarks.TYPE_FOLDER,
parentId: PlacesUtils.unfiledBookmarksFolderId,
parentId: unfiledFolderId,
guid: "livemarkEEEE",
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
oldValue: "",

View file

@ -297,7 +297,8 @@ add_task(async function test_move() {
name: "onItemMoved",
params: { itemId: localItemIds.get("mozFolder___"),
oldParentId: localItemIds.get("devFolder___"),
oldIndex: 1, newParentId: PlacesUtils.unfiledBookmarksFolderId,
oldIndex: 1,
newParentId: await PlacesUtils.promiseItemId(PlacesUtils.bookmarks.unfiledGuid),
newIndex: 0, type: PlacesUtils.bookmarks.TYPE_FOLDER,
guid: "mozFolder___",
oldParentGuid: "devFolder___",

View file

@ -1,6 +1,13 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
let unfiledFolderId;
add_task(async function setup() {
unfiledFolderId =
await PlacesUtils.promiseItemId(PlacesUtils.bookmarks.unfiledGuid);
});
add_task(async function test_value_combo() {
let buf = await openMirror("value_combo");
@ -689,7 +696,7 @@ add_task(async function test_keywords_complex() {
}, {
name: "onItemAdded",
params: { itemId: localItemIds.get("bookmarkBBB1"),
parentId: PlacesUtils.unfiledBookmarksFolderId, index: 0,
parentId: unfiledFolderId, index: 0,
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
urlHref: "http://example.com/b", title: "B",
guid: "bookmarkBBB1",
@ -1261,7 +1268,7 @@ add_task(async function test_duplicate_url_rows() {
params: { itemId: localItemIds.get("bookmarkCCCC"), property: "title",
isAnnoProperty: false, newValue: "C (remote)",
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
parentId: PlacesUtils.unfiledBookmarksFolderId,
parentId: unfiledFolderId,
guid: "bookmarkCCCC",
parentGuid: PlacesUtils.bookmarks.unfiledGuid, oldValue: "C",
source: PlacesUtils.bookmarks.SOURCES.SYNC },

View file

@ -6,8 +6,13 @@
const FEED_URI = NetUtil.newURI("http://feed.rss/");
const SITE_URI = NetUtil.newURI("http://site.org/");
let unfiledFolderId;
// This test must be the first one, since it's testing the cache.
add_task(async function test_livemark_cache() {
unfiledFolderId =
await PlacesUtils.promiseItemId(PlacesUtils.bookmarks.unfiledGuid);
// Add a livemark through other APIs.
let folder = await PlacesUtils.bookmarks.insert({
type: PlacesUtils.bookmarks.TYPE_FOLDER,
@ -31,7 +36,7 @@ add_task(async function test_livemark_cache() {
Assert.equal(folder.index, livemark.index);
Assert.equal(folder.title, livemark.title);
Assert.equal(id, livemark.id);
Assert.equal(PlacesUtils.unfiledBookmarksFolderId, livemark.parentId);
Assert.equal(unfiledFolderId, livemark.parentId);
Assert.equal("http://example.com/feed", livemark.feedURI.spec);
Assert.equal("http://example.com/site", livemark.siteURI.spec);
@ -77,7 +82,7 @@ add_task(async function test_addLivemark_invalidParentId_throws() {
add_task(async function test_addLivemark_noIndex_throws() {
try {
await PlacesUtils.livemarks.addLivemark({
parentId: PlacesUtils.unfiledBookmarksFolderId });
parentId: unfiledFolderId });
do_throw("Invoking addLivemark with no index should throw");
} catch (ex) {
Assert.equal(ex.result, Cr.NS_ERROR_INVALID_ARG);
@ -87,7 +92,7 @@ add_task(async function test_addLivemark_noIndex_throws() {
add_task(async function test_addLivemark_badIndex_throws() {
try {
await PlacesUtils.livemarks.addLivemark(
{ parentId: PlacesUtils.unfiledBookmarksFolderId,
{ parentId: unfiledFolderId,
index: "test" });
do_throw("Invoking addLivemark with a bad index should throw");
} catch (ex) {
@ -98,7 +103,7 @@ add_task(async function test_addLivemark_badIndex_throws() {
add_task(async function test_addLivemark_invalidIndex_throws() {
try {
await PlacesUtils.livemarks.addLivemark(
{ parentId: PlacesUtils.unfiledBookmarksFolderId,
{ parentId: unfiledFolderId,
index: -2,
});
do_throw("Invoking addLivemark with an invalid index should throw");
@ -160,7 +165,7 @@ add_task(async function test_addLivemark_parentId_succeeds() {
aURI, aTitle) {
onItemAddedCalled = true;
PlacesUtils.bookmarks.removeObserver(this);
Assert.equal(aParentId, PlacesUtils.unfiledBookmarksFolderId);
Assert.equal(aParentId, unfiledFolderId);
Assert.equal(aIndex, 0);
Assert.equal(aItemType, Ci.nsINavBookmarksService.TYPE_FOLDER);
Assert.equal(aTitle, "test");
@ -169,7 +174,7 @@ add_task(async function test_addLivemark_parentId_succeeds() {
await PlacesUtils.livemarks.addLivemark(
{ title: "test",
parentId: PlacesUtils.unfiledBookmarksFolderId,
parentId: unfiledFolderId,
feedURI: FEED_URI });
Assert.ok(onItemAddedCalled);
});
@ -184,7 +189,7 @@ add_task(async function test_addLivemark_noSiteURI_succeeds() {
Assert.ok(livemark.id > 0);
do_check_valid_places_guid(livemark.guid);
Assert.equal(livemark.title, "test");
Assert.equal(livemark.parentId, PlacesUtils.unfiledBookmarksFolderId);
Assert.equal(livemark.parentId, unfiledFolderId);
Assert.equal(livemark.parentGuid, PlacesUtils.bookmarks.unfiledGuid);
Assert.ok(livemark.feedURI.equals(FEED_URI));
Assert.equal(livemark.siteURI, null);
@ -207,7 +212,7 @@ add_task(async function test_addLivemark_succeeds() {
Assert.ok(livemark.id > 0);
do_check_valid_places_guid(livemark.guid);
Assert.equal(livemark.title, "test");
Assert.equal(livemark.parentId, PlacesUtils.unfiledBookmarksFolderId);
Assert.equal(livemark.parentId, unfiledFolderId);
Assert.equal(livemark.parentGuid, PlacesUtils.bookmarks.unfiledGuid);
Assert.ok(livemark.feedURI.equals(FEED_URI));
Assert.ok(livemark.siteURI.equals(SITE_URI));
@ -405,7 +410,7 @@ add_task(async function test_getLivemark_guid_succeeds() {
await PlacesUtils.livemarks.getLivemark({ id: 789, guid: "34567890ABCD" });
Assert.equal(livemark.title, "test");
Assert.equal(livemark.parentId, PlacesUtils.unfiledBookmarksFolderId);
Assert.equal(livemark.parentId, unfiledFolderId);
Assert.equal(livemark.parentGuid, PlacesUtils.bookmarks.unfiledGuid);
Assert.ok(livemark.feedURI.equals(FEED_URI));
Assert.equal(livemark.siteURI, null);
@ -425,7 +430,7 @@ add_task(async function test_getLivemark_id_succeeds() {
livemark = await PlacesUtils.livemarks.getLivemark({ id: livemark.id });
Assert.equal(livemark.title, "test");
Assert.equal(livemark.parentId, PlacesUtils.unfiledBookmarksFolderId);
Assert.equal(livemark.parentId, unfiledFolderId);
Assert.equal(livemark.parentGuid, PlacesUtils.bookmarks.unfiledGuid);
Assert.ok(livemark.feedURI.equals(FEED_URI));
Assert.equal(livemark.siteURI, null);
@ -451,7 +456,7 @@ add_task(async function test_getLivemark_removeItem_contention() {
livemark = await PlacesUtils.livemarks.getLivemark({ guid: livemark.guid });
Assert.equal(livemark.title, "test");
Assert.equal(livemark.parentId, PlacesUtils.unfiledBookmarksFolderId);
Assert.equal(livemark.parentId, unfiledFolderId);
Assert.ok(livemark.feedURI.equals(FEED_URI));
Assert.equal(livemark.siteURI, null);
do_check_guid_for_bookmark(livemark.id, livemark.guid);

View file

@ -137,6 +137,8 @@
accessKeyIndex =
labelText.toUpperCase().indexOf(accessKey.toUpperCase());
}
} else if (labelText.endsWith(`(${accessKey.toUpperCase()})`)) {
accessKeyIndex = labelText.length - (1 + accessKey.length); // = index of accessKey.
}
const HTML_NS = "http://www.w3.org/1999/xhtml";

View file

@ -65,12 +65,6 @@ toolbarbutton[disabled="true"][open="true"] {
-moz-stack-sizing: ignore;
}
.toolbarbutton-badge:-moz-window-inactive {
background-color: rgb(230,230,230);
box-shadow: none;
color: rgb(192,192,192);
}
toolbar[mode="icons"] > *|* > .toolbarbutton-badge {
margin-inline-end: -10px !important;
}

View file

@ -6726,6 +6726,13 @@ nsWindow::ClearCachedResources()
void
nsWindow::UpdateClientOffsetForCSDWindow()
{
// We update window offset on X11 as the window position is calculated
// relatively to mShell. We don't do that on Wayland as our wl_subsurface
// is attached to mContainer and mShell is ignored.
if (!mIsX11Display) {
return;
}
// _NET_FRAME_EXTENTS is not set on client decorated windows,
// so we need to read offset between mContainer and toplevel mShell
// window.
@ -7148,6 +7155,8 @@ nsWindow::GetSystemCSDSupportLevel() {
sCSDSupportLevel = CSD_SUPPORT_SYSTEM;
} else if (strstr(currentDesktop, "LXQt") != nullptr) {
sCSDSupportLevel = CSD_SUPPORT_SYSTEM;
} else if (strstr(currentDesktop, "Deepin") != nullptr) {
sCSDSupportLevel = CSD_SUPPORT_SYSTEM;
} else {
// Release or beta builds are not supposed to be broken
// so disable titlebar rendering on untested/unknown systems.

View file

@ -101,7 +101,7 @@ TaskbarPreview::SetVisible(bool visible) {
// to use it then just pretend that everything succeeded. The caller doesn't
// actually have a way to detect this since it's the same case as when we
// CanMakeTaskbarCalls returns false.
if (!mWnd)
if (!IsWindowAvailable())
return NS_OK;
return visible ? Enable() : Disable();
@ -168,7 +168,7 @@ TaskbarPreview::Enable() {
nsresult rv = NS_OK;
if (CanMakeTaskbarCalls()) {
rv = UpdateTaskbarProperties();
} else {
} else if (IsWindowAvailable()) {
WindowHook &hook = GetWindowHook();
hook.AddMonitor(nsAppShell::GetTaskbarButtonCreatedMessage(), MainWindowHook, this);
}

View file

@ -391,16 +391,14 @@ Base64EncodeHelper(const T& aBinary, T& aBase64)
uint32_t base64Len = ((aBinary.Length() + 2) / 3) * 4;
// Add one byte for null termination.
if (!aBase64.SetCapacity(base64Len + 1, fallible)) {
return NS_ERROR_OUT_OF_MEMORY;
nsresult rv;
auto handle = aBase64.BulkWrite(base64Len, 0, false, rv);
if (NS_FAILED(rv)) {
return rv;
}
typename T::char_type* base64 = aBase64.BeginWriting();
Encode(aBinary.BeginReading(), aBinary.Length(), base64);
base64[base64Len] = '\0';
aBase64.SetLength(base64Len);
Encode(aBinary.BeginReading(), aBinary.Length(), handle.Elements());
handle.Finish(base64Len, false);
return NS_OK;
}
@ -562,6 +560,8 @@ template<typename T>
static nsresult
Base64DecodeString(const T& aBase64, T& aBinary)
{
aBinary.Truncate();
// Check for overflow.
if (aBase64.Length() > UINT32_MAX / 3) {
return NS_ERROR_FAILURE;
@ -569,26 +569,29 @@ Base64DecodeString(const T& aBase64, T& aBinary)
// Don't decode the empty string
if (aBase64.IsEmpty()) {
aBinary.Truncate();
return NS_OK;
}
uint32_t binaryLen = ((aBase64.Length() * 3) / 4);
// Add one byte for null termination.
if (!aBinary.SetCapacity(binaryLen + 1, fallible)) {
return NS_ERROR_OUT_OF_MEMORY;
}
typename T::char_type* binary = aBinary.BeginWriting();
nsresult rv = Base64DecodeHelper(aBase64.BeginReading(), aBase64.Length(),
binary, &binaryLen);
if (NS_FAILED(rv)) {
aBinary.Truncate();
nsresult rv;
auto handle = aBinary.BulkWrite(binaryLen, 0, false, rv);
if(NS_FAILED(rv)) {
// Must not touch the handle if failing here, but we
// already truncated the string at the top, so it's
// unchanged.
return rv;
}
aBinary.SetLength(binaryLen);
rv = Base64DecodeHelper(aBase64.BeginReading(), aBase64.Length(),
handle.Elements(), &binaryLen);
if (NS_FAILED(rv)) {
// Retruncate to match old semantics of this method.
handle.Finish(0, true);
return rv;
}
handle.Finish(binaryLen, true);
return NS_OK;
}

View file

@ -578,20 +578,23 @@ nsStorageInputStream::Serialize(InputStreamParams& aParams, FileDescriptorArray&
{
nsCString combined;
int64_t offset;
mozilla::DebugOnly<nsresult> rv = Tell(&offset);
nsresult rv = Tell(&offset);
MOZ_ASSERT(NS_SUCCEEDED(rv));
uint64_t remaining;
rv = Available(&remaining);
MOZ_ASSERT(NS_SUCCEEDED(rv));
combined.SetCapacity(remaining);
auto handle = combined.BulkWrite(remaining, 0, false, rv);
MOZ_ASSERT(NS_SUCCEEDED(rv));
uint32_t numRead = 0;
rv = Read(combined.BeginWriting(), remaining, &numRead);
rv = Read(handle.Elements(), remaining, &numRead);
MOZ_ASSERT(NS_SUCCEEDED(rv));
MOZ_ASSERT(numRead == remaining);
combined.SetLength(numRead);
handle.Finish(numRead, false);
rv = Seek(NS_SEEK_SET, offset);
MOZ_ASSERT(NS_SUCCEEDED(rv));

View file

@ -511,17 +511,35 @@ public:
}
// AssignLiteral must ONLY be applied to an actual literal string, or
// a char array *constant* declared without an explicit size.
// Do not attempt to use it with a regular char* pointer, or with a
// non-constant char array variable. Use AssignASCII for those.
// There are not fallible version of these methods because they only really
// apply to small allocations that we wouldn't want to check anyway.
// a character array *constant* declared without an explicit size.
// Do not attempt to use it with a regular character pointer, or with a
// non-constant chararacter array variable. Use AssignASCII for those.
//
// This method does not need a fallible version, because it uses the
// POD buffer of the literal as the string's buffer without allocating.
// The literal does not need to be ASCII. If this a 16-bit string, this
// method takes a u"" literal. (The overload on 16-bit strings that takes
// a "" literal takes only ASCII.)
template<int N>
void AssignLiteral(const char_type (&aStr)[N])
{
AssignLiteral(aStr, N - 1);
}
// AssignLiteral must ONLY be applied to an actual literal string, or
// a character array *constant* declared without an explicit size.
// Do not attempt to use it with a regular character pointer, or with a
// non-constant chararacter array variable. Use AssignASCII for those.
//
// This method takes an 8-bit (ASCII-only!) string that is expanded
// into a 16-bit string at run time causing a run-time allocation.
// To avoid the run-time allocation (at the cost of the literal
// taking twice the size in the binary), use the above overload that
// takes a u"" string instead. Using the overload that takes a u""
// literal is generally preferred when working with 16-bit strings.
//
// There is not a fallible version of this method because it only really
// applies to small allocations that we wouldn't want to check anyway.
template<int N, typename Q = T, typename EnableIfChar16 = typename mozilla::Char16OnlyT<Q>>
void AssignLiteral(const incompatible_char_type (&aStr)[N])
{
@ -735,9 +753,12 @@ public:
void NS_FASTCALL AppendFloat(double aFloat);
public:
// Appends a literal string ("" literal in the 8-bit case and u"" literal
// in the 16-bit case) to the string.
//
// AppendLiteral must ONLY be applied to an actual literal string.
// Do not attempt to use it with a regular char* pointer, or with a char
// array variable. Use Append or AppendASCII for those.
// Do not attempt to use it with a regular character pointer, or with a
// character array variable. Use Append or AppendASCII for those.
template<int N>
void AppendLiteral(const char_type (&aStr)[N])
{
@ -745,6 +766,11 @@ public:
}
// Only enable for T = char16_t
//
// Appends an 8-bit literal string ("" literal) to a 16-bit string by
// expanding it. The literal must only contain ASCII.
//
// Using u"" literals with 16-bit strings is generally preferred.
template <int N, typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
void AppendLiteral(const incompatible_char_type (&aStr)[N])
{