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

This commit is contained in:
shindli 2018-05-16 21:53:27 +03:00
Родитель 57542ca64e 55f2b0d77a
Коммит fdb6353ff2
107 изменённых файлов: 2047 добавлений и 1191 удалений

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

@ -39,15 +39,6 @@ module.exports = {
"env": {
"mozilla/browser-window": true
}
},{
// XXX Bug 1421969. These files/directories are still being fixed,
// so turn off mozilla/use-services for them for now.
"files": [
"extensions/pref/**",
],
"rules": {
"mozilla/use-services": "off",
}
}, {
// XXX Bug 1436303. These directories are still being fixed, so turn off
// mozilla/no-cc-etc for now.

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

@ -2093,6 +2093,12 @@ window._gBrowser = {
return;
}
// Reset webrtc sharing state.
if (tab._sharingState) {
this.setBrowserSharing(aBrowser, {});
}
webrtcUI.forgetStreamsFromBrowser(aBrowser);
// Set browser parameters for when browser is restored. Also remove
// listeners and set up lazy restore data in SessionStore. This must
// be done before aBrowser is destroyed and removed from the document.

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

@ -110,15 +110,13 @@ this.windows = class extends ExtensionAPI {
getAll: function(getInfo) {
let doNotCheckTypes = getInfo === null || getInfo.windowTypes === null;
function typeFilter(win) {
return doNotCheckTypes || getInfo.windowTypes.includes(win.type);
let windows = [];
for (let win of windowManager.getAll()) {
if (doNotCheckTypes || getInfo.windowTypes.includes(win.type)) {
windows.push(win.convert(getInfo));
}
}
let windows = Array.from(windowManager.getAll(), win => win.convert(getInfo))
.filter(typeFilter);
return Promise.resolve(windows);
return windows;
},
create: function(createData) {

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

@ -26,6 +26,7 @@ export default class AddressForm extends PaymentStateSubscriberMixin(HTMLElement
this.cancelButton.addEventListener("click", this);
this.backButton = document.createElement("button");
this.backButton.className = "back-button";
this.backButton.addEventListener("click", this);
this.saveButton = document.createElement("button");

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

@ -22,10 +22,12 @@ export default class AddressPicker extends PaymentStateSubscriberMixin(HTMLEleme
this.dropdown = new RichSelect();
this.dropdown.addEventListener("change", this);
this.addLink = document.createElement("a");
this.addLink.className = "add-link";
this.addLink.href = "javascript:void(0)";
this.addLink.textContent = this.dataset.addLinkLabel;
this.addLink.addEventListener("click", this);
this.editLink = document.createElement("a");
this.editLink.className = "edit-link";
this.editLink.href = "javascript:void(0)";
this.editLink.textContent = this.dataset.editLinkLabel;
this.editLink.addEventListener("click", this);

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

@ -24,6 +24,7 @@ export default class BasicCardForm extends PaymentStateSubscriberMixin(HTMLEleme
this.genericErrorText = document.createElement("div");
this.backButton = document.createElement("button");
this.backButton.className = "back-button";
this.backButton.addEventListener("click", this);
this.saveButton = document.createElement("button");

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

@ -50,6 +50,8 @@ export default class PaymentDialog extends PaymentStateSubscriberMixin(HTMLEleme
this._payerRelatedEls = contents.querySelectorAll(".payer-related");
this._payerAddressPicker = contents.querySelector("address-picker.payer-related");
this._header = contents.querySelector("header");
this._errorText = contents.querySelector("#error-text");
this._disabledOverlay = contents.getElementById("disabled-overlay");
@ -260,6 +262,10 @@ export default class PaymentDialog extends PaymentStateSubscriberMixin(HTMLEleme
totalAmountEl.value = totalItem.amount.value;
totalAmountEl.currency = totalItem.amount.currency;
// Show the total header on the address and basic card pages only during
// on-boarding(FTU) and on the payment summary page.
this._header.hidden = !state.page.onboardingWizard && state.page.id != "payment-summary";
this._orderDetailsOverlay.hidden = !state.orderDetailsShowing;
this._errorText.textContent = paymentDetails.error;

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

@ -24,10 +24,12 @@ export default class PaymentMethodPicker extends PaymentStateSubscriberMixin(HTM
this.securityCodeInput.size = 3;
this.securityCodeInput.addEventListener("change", this);
this.addLink = document.createElement("a");
this.addLink.className = "add-link";
this.addLink.href = "javascript:void(0)";
this.addLink.textContent = this.dataset.addLinkLabel;
this.addLink.addEventListener("click", this);
this.editLink = document.createElement("a");
this.editLink.className = "edit-link";
this.editLink.href = "javascript:void(0)";
this.editLink.textContent = this.dataset.editLinkLabel;
this.editLink.addEventListener("click", this);

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

@ -30,6 +30,11 @@ add_task(async function test_onboarding_wizard_without_saved_addresses() {
}, "Address page is shown first if there are no saved addresses");
});
info("Check if the total header is visible on the address page during on-boarding");
let isHeaderVisible =
spawnPaymentDialogTask(frame, PTU.DialogContentTasks.isElementVisible, "header");
ok(isHeaderVisible, "Total Header is visible on the address page during on-boarding");
info("Closing the payment dialog");
spawnPaymentDialogTask(frame, async function() {
content.document.getElementById("address-page-cancel-button").click();
@ -50,6 +55,7 @@ add_task(async function test_onboarding_wizard_with_saved_addresses() {
await setupPaymentDialog(browser, {
methodData: [PTU.MethodData.basicCard],
details: PTU.Details.total60USD,
options: PTU.Options.requestShippingOption,
merchantTaskFn: PTU.ContentTasks.createAndShowRequest,
});
@ -67,9 +73,61 @@ add_task(async function test_onboarding_wizard_with_saved_addresses() {
}, "Payment summary page is shown when there are saved addresses");
});
info("Check if the total header is visible on payments summary page");
let isHeaderVisible =
spawnPaymentDialogTask(frame, PTU.DialogContentTasks.isElementVisible, "header");
ok(isHeaderVisible, "Total Header is visible on the payment summary page");
// Click on the Add/Edit buttons in the payment summary page to check if
// the total header is visible on the address page and the basic card page.
let buttons = ["address-picker[selected-state-key='selectedShippingAddress'] .add-link",
"address-picker[selected-state-key='selectedShippingAddress'] .edit-link",
"payment-method-picker .add-link",
"payment-method-picker .edit-link"];
for (let button of buttons) {
// eslint-disable-next-line no-shadow
await spawnPaymentDialogTask(frame, async function(button) {
let {
PaymentTestUtils: PTU,
} = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
content.document.querySelector(button).click();
if (button.startsWith("address")) {
await ContentTaskUtils.waitForCondition(() =>
content.document.querySelector("address-form .back-button"),
"Address page is rendered");
await PTU.DialogContentUtils.waitForState(content, (state) => {
return state.page.id == "address-page";
}, "Address page is shown");
} else {
await ContentTaskUtils.waitForCondition(() =>
content.document.querySelector("basic-card-form .back-button"),
"Basic card page is rendered");
await PTU.DialogContentUtils.waitForState(content, (state) => {
return state.page.id == "basic-card-page";
}, "Basic card page is shown");
}
}, button);
isHeaderVisible =
await spawnPaymentDialogTask(frame, PTU.DialogContentTasks.isElementVisible, "header");
ok(!isHeaderVisible, "Total Header is hidden on the address page");
if (button.startsWith("address")) {
spawnPaymentDialogTask(frame, async function() {
content.document.querySelector("address-form .back-button").click();
});
} else {
spawnPaymentDialogTask(frame, async function() {
content.document.querySelector("basic-card-form .back-button").click();
});
}
}
info("Closing the payment dialog");
spawnPaymentDialogTask(frame, async function() {
content.document.getElementById("address-page-cancel-button").click();
content.document.getElementById("cancel").click();
});
await BrowserTestUtils.waitForCondition(() => win.closed, "dialog should be closed");

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

@ -1339,3 +1339,9 @@ if CONFIG['MOZ_SYSTEM_ICU']:
'unicode/ustring.h',
'unicode/utypes.h',
]
if CONFIG['MOZ_WAYLAND']:
system_headers += [
'wayland-client.h',
'wayland-egl.h',
]

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

@ -108,7 +108,6 @@ def config_status(config):
# executable permissions.
os.chmod('config.status', 0o755)
if config.get('MOZ_BUILD_APP') != 'js' or config.get('JS_STANDALONE'):
os.environ[b'WRITE_MOZINFO'] = b'1'
from mozbuild.config_status import config_status
# Some values in sanitized_config also have more complex types, such as

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

@ -292,12 +292,8 @@ pref("devtools.webconsole.timestampMessages", false);
// to automatically trigger multiline editing (equivalent to shift + enter).
pref("devtools.webconsole.autoMultiline", true);
// Enable the webconsole sidebar toggle in Nightly builds.
#if defined(NIGHTLY_BUILD)
pref("devtools.webconsole.sidebarToggle", true);
#else
// Enable the webconsole sidebar toggle
pref("devtools.webconsole.sidebarToggle", false);
#endif
// Disable the new performance recording panel by default
pref("devtools.performance.new-panel-enabled", false);

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

@ -33,12 +33,22 @@ const PriorityLevels = {
*
* See also MDN for more info about <xul:notificationbox>:
* https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/notificationbox
*
* This component can maintain its own state (list of notifications)
* as well as consume list of notifications provided as a prop
* (coming e.g. from Redux store).
*/
class NotificationBox extends Component {
static get propTypes() {
return {
// Optional box ID (used for mounted node ID attribute)
id: PropTypes.string,
// List of notifications appended into the box.
notifications: PropTypes.arrayOf(PropTypes.shape({
// Use `PropTypes.arrayOf` validation (see below) as soon as
// ImmutableJS is removed. See bug 1461678 for more details.
notifications: PropTypes.object,
/* notifications: PropTypes.arrayOf(PropTypes.shape({
// label to appear on the notification.
label: PropTypes.string.isRequired,
@ -74,7 +84,7 @@ class NotificationBox extends Component {
// A function to call to notify you of interesting things that happen
// with the notification box.
eventCallback: PropTypes.func,
})),
})),*/
// Message that should be shown when hovering over the close button
closeButtonTooltip: PropTypes.string
@ -109,43 +119,16 @@ class NotificationBox extends Component {
* added behind it. See `propTypes` for arguments description.
*/
appendNotification(label, value, image, priority, buttons = [], eventCallback) {
// Priority level must be within expected interval
// (see priority levels at the top of this file).
if (priority < PriorityLevels.PRIORITY_INFO_LOW ||
priority > PriorityLevels.PRIORITY_CRITICAL_BLOCK) {
throw new Error("Invalid notification priority " + priority);
}
// Custom image URL is not supported yet.
if (image) {
throw new Error("Custom image URL is not supported yet");
}
let type = "warning";
if (priority >= PriorityLevels.PRIORITY_CRITICAL_LOW) {
type = "critical";
} else if (priority <= PriorityLevels.PRIORITY_INFO_HIGH) {
type = "info";
}
let notifications = this.state.notifications.set(value, {
label: label,
value: value,
image: image,
priority: priority,
type: type,
buttons: Array.isArray(buttons) ? buttons : [],
eventCallback: eventCallback,
const newState = appendNotification(this.state, {
label,
value,
image,
priority,
buttons,
eventCallback,
});
// High priorities must be on top.
notifications = notifications.sortBy((val, key) => {
return -val.priority;
});
this.setState({
notifications: notifications
});
this.setState(newState);
}
/**
@ -192,6 +175,10 @@ class NotificationBox extends Component {
notification.eventCallback("removed");
}
if (!this.state.notifications.get(notification.value)) {
return;
}
this.setState({
notifications: this.state.notifications.remove(notification.value)
});
@ -260,16 +247,92 @@ class NotificationBox extends Component {
* notification is rendered at a time.
*/
render() {
let notification = this.state.notifications.first();
let content = notification ?
const notifications = this.props.notifications || this.state.notifications;
const notification = notifications ? notifications.first() : null;
const content = notification ?
this.renderNotification(notification) :
null;
return div({className: "notificationbox"},
return div({
className: "notificationbox",
id: this.props.id},
content
);
}
}
// Helpers
/**
* Create a new notification. If another notification is already present with
* a higher priority, the new notification will be added behind it.
* See `propTypes` for arguments description.
*/
function appendNotification(state, props) {
const {
label,
value,
image,
priority,
buttons,
eventCallback
} = props;
// Priority level must be within expected interval
// (see priority levels at the top of this file).
if (priority < PriorityLevels.PRIORITY_INFO_LOW ||
priority > PriorityLevels.PRIORITY_CRITICAL_BLOCK) {
throw new Error("Invalid notification priority " + priority);
}
// Custom image URL is not supported yet.
if (image) {
throw new Error("Custom image URL is not supported yet");
}
let type = "warning";
if (priority >= PriorityLevels.PRIORITY_CRITICAL_LOW) {
type = "critical";
} else if (priority <= PriorityLevels.PRIORITY_INFO_HIGH) {
type = "info";
}
if (!state.notifications) {
state.notifications = new Immutable.OrderedMap();
}
let notifications = state.notifications.set(value, {
label: label,
value: value,
image: image,
priority: priority,
type: type,
buttons: Array.isArray(buttons) ? buttons : [],
eventCallback: eventCallback,
});
// High priorities must be on top.
notifications = notifications.sortBy((val, key) => {
return -val.priority;
});
return {
notifications: notifications
};
}
function getNotificationWithValue(notifications, value) {
return notifications ? notifications.get(value) : null;
}
function removeNotificationWithValue(notifications, value) {
return {
notifications: notifications.remove(value)
};
}
module.exports.NotificationBox = NotificationBox;
module.exports.PriorityLevels = PriorityLevels;
module.exports.appendNotification = appendNotification;
module.exports.getNotificationWithValue = getNotificationWithValue;
module.exports.removeNotificationWithValue = removeNotificationWithValue;

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

@ -10,6 +10,7 @@ const actionModules = [
require("./filters"),
require("./messages"),
require("./ui"),
require("./notifications"),
];
const actions = Object.assign({}, ...actionModules);

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

@ -7,5 +7,6 @@ DevToolsModules(
'filters.js',
'index.js',
'messages.js',
'notifications.js',
'ui.js',
)

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

@ -0,0 +1,43 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=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/. */
"use strict";
const {
APPEND_NOTIFICATION,
REMOVE_NOTIFICATION,
} = require("devtools/client/webconsole/constants");
/**
* Append a notification into JSTerm notification list.
*/
function appendNotification(label, value, image, priority, buttons = [], eventCallback) {
return {
type: APPEND_NOTIFICATION,
label,
value,
image,
priority,
buttons,
eventCallback,
};
}
/**
* Remove notification with specified value from JSTerm
* notification list.
*/
function removeNotification(value) {
return {
type: REMOVE_NOTIFICATION,
value,
};
}
module.exports = {
appendNotification,
removeNotification,
};

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

@ -0,0 +1,172 @@
/* 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/. */
"use strict";
const { Component, createFactory } = require("devtools/client/shared/vendor/react");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const { connect } = require("devtools/client/shared/redux/visibility-handler-connect");
const actions = require("devtools/client/webconsole/actions/index");
const ConsoleOutput = createFactory(require("devtools/client/webconsole/components/ConsoleOutput"));
const FilterBar = createFactory(require("devtools/client/webconsole/components/FilterBar"));
const SideBar = createFactory(require("devtools/client/webconsole/components/SideBar"));
const JSTerm = createFactory(require("devtools/client/webconsole/components/JSTerm"));
const NotificationBox = createFactory(require("devtools/client/shared/components/NotificationBox").NotificationBox);
const l10n = require("devtools/client/webconsole/webconsole-l10n");
const { Utils: WebConsoleUtils } = require("devtools/client/webconsole/utils");
const SELF_XSS_OK = l10n.getStr("selfxss.okstring");
const SELF_XSS_MSG = l10n.getFormatStr("selfxss.msg", [SELF_XSS_OK]);
const {
getNotificationWithValue,
PriorityLevels,
} = require("devtools/client/shared/components/NotificationBox");
const { getAllNotifications } = require("devtools/client/webconsole/selectors/notifications");
const { div } = dom;
/**
* Console root Application component.
*/
class App extends Component {
static get propTypes() {
return {
attachRefToHud: PropTypes.func.isRequired,
dispatch: PropTypes.func.isRequired,
hud: PropTypes.object.isRequired,
notifications: PropTypes.object,
onFirstMeaningfulPaint: PropTypes.func.isRequired,
serviceContainer: PropTypes.object.isRequired,
};
}
constructor(props) {
super(props);
this.onPaste = this.onPaste.bind(this);
}
onPaste(event) {
const {
dispatch,
hud,
notifications,
} = this.props;
const {
usageCount,
CONSOLE_ENTRY_THRESHOLD
} = WebConsoleUtils;
// Bail out if self-xss notification is suppressed.
if (hud.isBrowserConsole || usageCount >= CONSOLE_ENTRY_THRESHOLD) {
return;
}
// Stop event propagation, so the clipboard content is *not* inserted.
event.preventDefault();
event.stopPropagation();
// Bail out if self-xss notification is already there.
if (getNotificationWithValue(notifications, "selfxss-notification")) {
return;
}
const inputField = this.node.querySelector(".jsterm-input-node");
// Cleanup function if notification is closed by the user.
const removeCallback = (eventType) => {
if (eventType == "removed") {
inputField.removeEventListener("keyup", pasteKeyUpHandler);
dispatch(actions.removeNotification("selfxss-notification"));
}
};
// Create self-xss notification
dispatch(actions.appendNotification(
SELF_XSS_MSG,
"selfxss-notification",
null,
PriorityLevels.PRIORITY_WARNING_HIGH,
null,
removeCallback
));
// Remove notification automatically when the user
// types "allow pasting".
function pasteKeyUpHandler() {
let value = inputField.value || inputField.textContent;
if (value.includes(SELF_XSS_OK)) {
dispatch(actions.removeNotification("selfxss-notification"));
inputField.removeEventListener("keyup", pasteKeyUpHandler);
WebConsoleUtils.usageCount = WebConsoleUtils.CONSOLE_ENTRY_THRESHOLD;
}
}
inputField.addEventListener("keyup", pasteKeyUpHandler);
}
// Rendering
render() {
const {
attachRefToHud,
hud,
notifications,
onFirstMeaningfulPaint,
serviceContainer,
} = this.props;
// Render the entire Console panel. The panel consists
// from the following parts:
// * FilterBar - Buttons & free text for content filtering
// * Content - List of logs & messages
// * SideBar - Object inspector
// * NotificationBox - Notifications for JSTerm (self-xss warning at the moment)
// * JSTerm - Input command line.
return (
div({
className: "webconsole-output-wrapper",
ref: node => {
this.node = node;
}},
FilterBar({
hidePersistLogsCheckbox: hud.isBrowserConsole,
serviceContainer: {
attachRefToHud
}
}),
ConsoleOutput({
serviceContainer,
onFirstMeaningfulPaint,
}),
SideBar({
serviceContainer,
}),
NotificationBox({
id: "webconsole-notificationbox",
notifications,
}),
JSTerm({
hud,
onPaste: this.onPaste,
}),
)
);
}
}
const mapStateToProps = state => ({
notifications: getAllNotifications(state),
});
const mapDispatchToProps = dispatch => ({
dispatch,
});
module.exports = connect(mapStateToProps, mapDispatchToProps)(App);

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

@ -18,8 +18,6 @@ loader.lazyRequireGetter(this, "EventEmitter", "devtools/shared/event-emitter");
loader.lazyRequireGetter(this, "AutocompletePopup", "devtools/client/shared/autocomplete-popup");
loader.lazyRequireGetter(this, "asyncStorage", "devtools/shared/async-storage");
loader.lazyRequireGetter(this, "gDevTools", "devtools/client/framework/devtools", true);
loader.lazyRequireGetter(this, "NotificationBox", "devtools/client/shared/components/NotificationBox", true);
loader.lazyRequireGetter(this, "PriorityLevels", "devtools/client/shared/components/NotificationBox", true);
const l10n = require("devtools/client/webconsole/webconsole-l10n");
@ -53,6 +51,8 @@ class JSTerm extends Component {
static get propTypes() {
return {
hud: PropTypes.object.isRequired,
// Handler for clipboard 'paste' event (also used for 'drop' event).
onPaste: PropTypes.func,
};
}
@ -62,6 +62,7 @@ class JSTerm extends Component {
const {
hud,
} = props;
this.hud = hud;
this.hudId = this.hud.hudId;
this.inputHistoryCount = Services.prefs.getIntPref(PREF_INPUT_HISTORY_COUNT);
@ -176,16 +177,6 @@ class JSTerm extends Component {
this.inputNode.addEventListener("input", this._inputEventHandler);
this.inputNode.addEventListener("keyup", this._inputEventHandler);
this.inputNode.addEventListener("focus", this._focusEventHandler);
if (!this.hud.isBrowserConsole) {
let okstring = l10n.getStr("selfxss.okstring");
let msg = l10n.getFormatStr("selfxss.msg", [okstring]);
this._onPaste = WebConsoleUtils.pasteHandlerGen(this.inputNode,
this.getNotificationBox(), msg, okstring);
this.inputNode.addEventListener("paste", this._onPaste);
this.inputNode.addEventListener("drop", this._onPaste);
}
this.hud.window.addEventListener("blur", this._blurEventHandler);
this.lastInputValue && this.setInputValue(this.lastInputValue);
@ -1279,29 +1270,11 @@ class JSTerm extends Component {
this._inputCharWidth = tempLabel.offsetWidth;
tempLabel.remove();
// Calculate the width of the chevron placed at the beginning of the input
// box. Remove 4 more pixels to accomodate the padding of the popup.
// box. Remove 4 more pixels to accommodate the padding of the popup.
this._chevronWidth = +doc.defaultView.getComputedStyle(this.inputNode)
.paddingLeft.replace(/[^0-9.]/g, "") - 4;
}
/**
* Build the notification box as soon as needed.
*/
getNotificationBox() {
if (this._notificationBox) {
return this._notificationBox;
}
let box = this.hud.document.getElementById("webconsole-notificationbox");
let toolbox = gDevTools.getToolbox(this.hud.owner.target);
// Render NotificationBox and assign priority levels to it.
this._notificationBox = Object.assign(
toolbox.ReactDOM.render(toolbox.React.createElement(NotificationBox), box),
PriorityLevels);
return this._notificationBox;
}
destroy() {
this.clearCompletion();
@ -1318,12 +1291,6 @@ class JSTerm extends Component {
}
if (this.inputNode) {
if (this._onPaste) {
this.inputNode.removeEventListener("paste", this._onPaste);
this.inputNode.removeEventListener("drop", this._onPaste);
this._onPaste = null;
}
this.inputNode.removeEventListener("keypress", this._keyPress);
this.inputNode.removeEventListener("input", this._inputEventHandler);
this.inputNode.removeEventListener("keyup", this._inputEventHandler);
@ -1340,8 +1307,11 @@ class JSTerm extends Component {
return null;
}
return [
dom.div({id: "webconsole-notificationbox", key: "notification"}),
let {
onPaste
} = this.props;
return (
dom.div({
className: "jsterm-input-container",
key: "jsterm-container",
@ -1365,9 +1335,11 @@ class JSTerm extends Component {
ref: node => {
this.inputNode = node;
},
onPaste: onPaste,
onDrop: onPaste,
})
),
];
)
);
}
}

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

@ -8,6 +8,7 @@ DIRS += [
]
DevToolsModules(
'App.js',
'CollapseButton.js',
'ConsoleOutput.js',
'ConsoleTable.js',

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

@ -27,6 +27,8 @@ const actionTypes = {
SIDEBAR_CLOSE: "SIDEBAR_CLOSE",
SHOW_OBJECT_IN_SIDEBAR: "SHOW_OBJECT_IN_SIDEBAR",
TIMESTAMPS_TOGGLE: "TIMESTAMPS_TOGGLE",
APPEND_NOTIFICATION: "APPEND_NOTIFICATION",
REMOVE_NOTIFICATION: "REMOVE_NOTIFICATION",
};
const prefs = {

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

@ -4,7 +4,6 @@
"use strict";
const { createElement, createFactory } = require("devtools/client/shared/vendor/react");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const ReactDOM = require("devtools/client/shared/vendor/react-dom");
const { Provider } = require("devtools/client/shared/vendor/react-redux");
@ -16,10 +15,7 @@ const { getAllMessagesById, getMessage } = require("devtools/client/webconsole/s
const Telemetry = require("devtools/client/shared/telemetry");
const EventEmitter = require("devtools/shared/event-emitter");
const ConsoleOutput = createFactory(require("devtools/client/webconsole/components/ConsoleOutput"));
const FilterBar = createFactory(require("devtools/client/webconsole/components/FilterBar"));
const SideBar = createFactory(require("devtools/client/webconsole/components/SideBar"));
const JSTerm = createFactory(require("devtools/client/webconsole/components/JSTerm"));
const App = createFactory(require("devtools/client/webconsole/components/App"));
let store = null;
@ -43,6 +39,7 @@ function NewConsoleOutputWrapper(parentNode, hud, toolbox, owner, document) {
store = configureStore(this.hud);
}
NewConsoleOutputWrapper.prototype = {
init: function() {
return new Promise((resolve) => {
@ -211,28 +208,15 @@ NewConsoleOutputWrapper.prototype = {
});
}
let provider = createElement(
Provider,
{ store },
dom.div(
{className: "webconsole-output-wrapper"},
FilterBar({
hidePersistLogsCheckbox: this.hud.isBrowserConsole,
serviceContainer: {
attachRefToHud
}
}),
ConsoleOutput({
serviceContainer,
onFirstMeaningfulPaint: resolve
}),
SideBar({
serviceContainer,
}),
JSTerm({
hud: this.hud,
}),
));
const app = App({
attachRefToHud,
serviceContainer,
hud,
onFirstMeaningfulPaint: resolve,
});
// Render the root Application component.
let provider = createElement(Provider, { store }, app);
this.body = ReactDOM.render(provider, this.parentNode);
});
},

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

@ -9,10 +9,12 @@ const { filters } = require("./filters");
const { messages } = require("./messages");
const { prefs } = require("./prefs");
const { ui } = require("./ui");
const { notifications } = require("./notifications");
exports.reducers = {
filters,
messages,
prefs,
ui,
notifications,
};

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

@ -7,6 +7,7 @@ DevToolsModules(
'filters.js',
'index.js',
'messages.js',
'notifications.js',
'prefs.js',
'ui.js',
)

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

@ -0,0 +1,58 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=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/. */
"use strict";
const {
APPEND_NOTIFICATION,
REMOVE_NOTIFICATION,
} = require("devtools/client/webconsole/constants");
const {
appendNotification,
removeNotificationWithValue
} = require("devtools/client/shared/components/NotificationBox");
/**
* Create default initial state for this reducer. The state is composed
* from list of notifications.
*/
function getInitialState() {
return {
notifications: undefined,
};
}
/**
* Reducer function implementation. This reducers is responsible
* for maintaining list of notifications. It's consumed by
* `NotificationBox` component.
*/
function notifications(state = getInitialState(), action) {
switch (action.type) {
case APPEND_NOTIFICATION:
return append(state, action);
case REMOVE_NOTIFICATION:
return remove(state, action);
}
return state;
}
// Helpers
function append(state, action) {
return appendNotification(state, action);
}
function remove(state, action) {
return removeNotificationWithValue(state.notifications, action.value);
}
// Exports
module.exports = {
notifications,
};

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

@ -6,6 +6,7 @@
DevToolsModules(
'filters.js',
'messages.js',
'notifications.js',
'prefs.js',
'ui.js',
)

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

@ -0,0 +1,14 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=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/. */
"use strict";
function getAllNotifications(state) {
return state.notifications.notifications;
}
module.exports = {
getAllNotifications,
};

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

@ -26,14 +26,14 @@ add_task(async function() {
let menuPopup = await openContextMenu(hud, networkMessage.node);
ok(menuPopup, "The context menu is displayed on a network message");
let expectedContextMenu = addPrefBasedEntries([
let expectedContextMenu = [
"#console-menu-copy-url (a)",
"#console-menu-open-url (T)",
"#console-menu-store (S) [disabled]",
"#console-menu-copy (C)",
"#console-menu-copy-object (o) [disabled]",
"#console-menu-select (A)",
]);
"#console-menu-select (A)"
];
is(getSimplifiedContextMenu(menuPopup).join("\n"), expectedContextMenu.join("\n"),
"The context menu has the expected entries for a network message");
@ -47,26 +47,18 @@ add_task(async function() {
menuPopup = await openContextMenu(hud, logMessage.node);
ok(menuPopup, "The context menu is displayed on a log message");
expectedContextMenu = addPrefBasedEntries([
expectedContextMenu = [
"#console-menu-store (S) [disabled]",
"#console-menu-copy (C)",
"#console-menu-copy-object (o) [disabled]",
"#console-menu-select (A)",
]);
"#console-menu-select (A)"
];
is(getSimplifiedContextMenu(menuPopup).join("\n"), expectedContextMenu.join("\n"),
"The context menu has the expected entries for a simple log message");
await hideContextMenu(hud);
});
function addPrefBasedEntries(expectedEntries) {
if (Services.prefs.getBoolPref("devtools.webconsole.sidebarToggle", false)) {
expectedEntries.push("#console-menu-open-sidebar (V) [disabled]");
}
return expectedEntries;
}
function getSimplifiedContextMenu(popupElement) {
return [...popupElement.querySelectorAll("menuitem")]
.map(entry => {

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

@ -17,6 +17,8 @@ const WebConsoleUtils = require("devtools/client/webconsole/utils").Utils;
const stringToCopy = "foobazbarBug642615";
add_task(async function() {
await pushPref("devtools.selfxss.count", 0);
let {jsterm} = await openNewTabAndConsole(TEST_URI);
jsterm.clearOutput();
ok(!jsterm.completeNode.value, "no completeNode.value");

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

@ -28,6 +28,8 @@ exports.CONSOLE_WORKER_IDS = [
var WebConsoleUtils = {
CONSOLE_ENTRY_THRESHOLD,
/**
* Wrap a string in an nsISupportsString object.
*
@ -125,7 +127,7 @@ var WebConsoleUtils = {
/**
* Helper function to deduce the name of the provided function.
*
* @param funtion function
* @param function function
* The function whose name will be returned.
* @return string
* Function name.

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

@ -250,25 +250,29 @@ const NodeActor = protocol.ActorClassWithSpec(nodeSpec, {
return null;
}
return style.display;
let display = null;
try {
display = style.display;
} catch (e) {
// Fails for <scrollbar> elements.
}
return display;
},
/**
* Is the node's display computed style value other than "none"
* Is the node currently displayed?
*/
get isDisplayed() {
// Consider all non-element nodes as displayed.
if (InspectorActorUtils.isNodeDead(this) ||
this.rawNode.nodeType !== Ci.nsIDOMNode.ELEMENT_NODE) {
let type = this.displayType;
// Consider all non-elements or elements with no display-types to be displayed.
if (!type) {
return true;
}
let style = this.computedStyle;
if (!style) {
return true;
}
return style.display !== "none";
// Otherwise consider elements to be displayed only if their display-types is other
// than "none"".
return type !== "none";
},
/**

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

@ -45,6 +45,7 @@ DevToolsModules(
'highlighters.js',
'layout.js',
'memory.js',
'network-event.js',
'object.js',
'pause-scoped.js',
'perf.js',

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

@ -0,0 +1,533 @@
/* 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/. */
"use strict";
/**
* Creates an actor for a network event.
*
* @constructor
* @param object webConsoleActor
* The parent WebConsoleActor instance for this object.
*/
function NetworkEventActor(webConsoleActor) {
this.parent = webConsoleActor;
this.conn = this.parent.conn;
this._request = {
method: null,
url: null,
httpVersion: null,
headers: [],
cookies: [],
headersSize: null,
postData: {},
};
this._response = {
headers: [],
cookies: [],
content: {},
};
this._timings = {};
this._stackTrace = {};
// Keep track of LongStringActors owned by this NetworkEventActor.
this._longStringActors = new Set();
}
NetworkEventActor.prototype =
{
_request: null,
_response: null,
_timings: null,
_longStringActors: null,
actorPrefix: "netEvent",
/**
* Returns a grip for this actor for returning in a protocol message.
*/
grip: function() {
return {
actor: this.actorID,
startedDateTime: this._startedDateTime,
timeStamp: Date.parse(this._startedDateTime),
url: this._request.url,
method: this._request.method,
isXHR: this._isXHR,
cause: this._cause,
fromCache: this._fromCache,
fromServiceWorker: this._fromServiceWorker,
private: this._private,
};
},
/**
* Releases this actor from the pool.
*/
release: function() {
for (let grip of this._longStringActors) {
let actor = this.parent.getActorByID(grip.actor);
if (actor) {
this.parent.releaseActor(actor);
}
}
this._longStringActors = new Set();
if (this._request.url) {
this.parent._networkEventActorsByURL.delete(this._request.url);
}
if (this.channel) {
this.parent._netEvents.delete(this.channel);
}
this.parent.releaseActor(this);
},
/**
* Handle a protocol request to release a grip.
*/
onRelease: function() {
this.release();
return {};
},
/**
* Set the properties of this actor based on it's corresponding
* network event.
*
* @param object networkEvent
* The network event associated with this actor.
*/
init: function(networkEvent) {
this._startedDateTime = networkEvent.startedDateTime;
this._isXHR = networkEvent.isXHR;
this._cause = networkEvent.cause;
this._fromCache = networkEvent.fromCache;
this._fromServiceWorker = networkEvent.fromServiceWorker;
// Stack trace info isn't sent automatically. The client
// needs to request it explicitly using getStackTrace
// packet.
this._stackTrace = networkEvent.cause.stacktrace;
delete networkEvent.cause.stacktrace;
networkEvent.cause.stacktraceAvailable =
!!(this._stackTrace && this._stackTrace.length);
for (let prop of ["method", "url", "httpVersion", "headersSize"]) {
this._request[prop] = networkEvent[prop];
}
this._discardRequestBody = networkEvent.discardRequestBody;
this._discardResponseBody = networkEvent.discardResponseBody;
this._truncated = false;
this._private = networkEvent.private;
},
/**
* The "getRequestHeaders" packet type handler.
*
* @return object
* The response packet - network request headers.
*/
onGetRequestHeaders: function() {
return {
from: this.actorID,
headers: this._request.headers,
headersSize: this._request.headersSize,
rawHeaders: this._request.rawHeaders,
};
},
/**
* The "getRequestCookies" packet type handler.
*
* @return object
* The response packet - network request cookies.
*/
onGetRequestCookies: function() {
return {
from: this.actorID,
cookies: this._request.cookies,
};
},
/**
* The "getRequestPostData" packet type handler.
*
* @return object
* The response packet - network POST data.
*/
onGetRequestPostData: function() {
return {
from: this.actorID,
postData: this._request.postData,
postDataDiscarded: this._discardRequestBody,
};
},
/**
* The "getSecurityInfo" packet type handler.
*
* @return object
* The response packet - connection security information.
*/
onGetSecurityInfo: function() {
return {
from: this.actorID,
securityInfo: this._securityInfo,
};
},
/**
* The "getResponseHeaders" packet type handler.
*
* @return object
* The response packet - network response headers.
*/
onGetResponseHeaders: function() {
return {
from: this.actorID,
headers: this._response.headers,
headersSize: this._response.headersSize,
rawHeaders: this._response.rawHeaders,
};
},
/**
* The "getResponseCache" packet type handler.
*
* @return object
* The cache packet - network cache information.
*/
onGetResponseCache: function() {
return {
from: this.actorID,
cache: this._response.responseCache,
};
},
/**
* The "getResponseCookies" packet type handler.
*
* @return object
* The response packet - network response cookies.
*/
onGetResponseCookies: function() {
return {
from: this.actorID,
cookies: this._response.cookies,
};
},
/**
* The "getResponseContent" packet type handler.
*
* @return object
* The response packet - network response content.
*/
onGetResponseContent: function() {
return {
from: this.actorID,
content: this._response.content,
contentDiscarded: this._discardResponseBody,
};
},
/**
* The "getEventTimings" packet type handler.
*
* @return object
* The response packet - network event timings.
*/
onGetEventTimings: function() {
return {
from: this.actorID,
timings: this._timings,
totalTime: this._totalTime,
offsets: this._offsets
};
},
/**
* The "getStackTrace" packet type handler.
*
* @return object
* The response packet - stack trace.
*/
onGetStackTrace: function() {
return {
from: this.actorID,
stacktrace: this._stackTrace,
};
},
/** ****************************************************************
* Listeners for new network event data coming from NetworkMonitor.
******************************************************************/
/**
* Add network request headers.
*
* @param array headers
* The request headers array.
* @param string rawHeaders
* The raw headers source.
*/
addRequestHeaders: function(headers, rawHeaders) {
this._request.headers = headers;
this._prepareHeaders(headers);
rawHeaders = this.parent._createStringGrip(rawHeaders);
if (typeof rawHeaders == "object") {
this._longStringActors.add(rawHeaders);
}
this._request.rawHeaders = rawHeaders;
let packet = {
from: this.actorID,
type: "networkEventUpdate",
updateType: "requestHeaders",
headers: headers.length,
headersSize: this._request.headersSize,
};
this.conn.send(packet);
},
/**
* Add network request cookies.
*
* @param array cookies
* The request cookies array.
*/
addRequestCookies: function(cookies) {
this._request.cookies = cookies;
this._prepareHeaders(cookies);
let packet = {
from: this.actorID,
type: "networkEventUpdate",
updateType: "requestCookies",
cookies: cookies.length,
};
this.conn.send(packet);
},
/**
* Add network request POST data.
*
* @param object postData
* The request POST data.
*/
addRequestPostData: function(postData) {
this._request.postData = postData;
postData.text = this.parent._createStringGrip(postData.text);
if (typeof postData.text == "object") {
this._longStringActors.add(postData.text);
}
let packet = {
from: this.actorID,
type: "networkEventUpdate",
updateType: "requestPostData",
dataSize: postData.text.length,
discardRequestBody: this._discardRequestBody,
};
this.conn.send(packet);
},
/**
* Add the initial network response information.
*
* @param object info
* The response information.
* @param string rawHeaders
* The raw headers source.
*/
addResponseStart: function(info, rawHeaders) {
rawHeaders = this.parent._createStringGrip(rawHeaders);
if (typeof rawHeaders == "object") {
this._longStringActors.add(rawHeaders);
}
this._response.rawHeaders = rawHeaders;
this._response.httpVersion = info.httpVersion;
this._response.status = info.status;
this._response.statusText = info.statusText;
this._response.headersSize = info.headersSize;
this._discardResponseBody = info.discardResponseBody;
let packet = {
from: this.actorID,
type: "networkEventUpdate",
updateType: "responseStart",
response: info
};
this.conn.send(packet);
},
/**
* Add connection security information.
*
* @param object info
* The object containing security information.
*/
addSecurityInfo: function(info) {
this._securityInfo = info;
let packet = {
from: this.actorID,
type: "networkEventUpdate",
updateType: "securityInfo",
state: info.state,
};
this.conn.send(packet);
},
/**
* Add network response headers.
*
* @param array headers
* The response headers array.
*/
addResponseHeaders: function(headers) {
this._response.headers = headers;
this._prepareHeaders(headers);
let packet = {
from: this.actorID,
type: "networkEventUpdate",
updateType: "responseHeaders",
headers: headers.length,
headersSize: this._response.headersSize,
};
this.conn.send(packet);
},
/**
* Add network response cookies.
*
* @param array cookies
* The response cookies array.
*/
addResponseCookies: function(cookies) {
this._response.cookies = cookies;
this._prepareHeaders(cookies);
let packet = {
from: this.actorID,
type: "networkEventUpdate",
updateType: "responseCookies",
cookies: cookies.length,
};
this.conn.send(packet);
},
/**
* Add network response content.
*
* @param object content
* The response content.
* @param object
* - boolean discardedResponseBody
* Tells if the response content was recorded or not.
* - boolean truncated
* Tells if the some of the response content is missing.
*/
addResponseContent: function(content, {discardResponseBody, truncated}) {
this._truncated = truncated;
this._response.content = content;
content.text = this.parent._createStringGrip(content.text);
if (typeof content.text == "object") {
this._longStringActors.add(content.text);
}
let packet = {
from: this.actorID,
type: "networkEventUpdate",
updateType: "responseContent",
mimeType: content.mimeType,
contentSize: content.size,
encoding: content.encoding,
transferredSize: content.transferredSize,
discardResponseBody,
};
this.conn.send(packet);
},
addResponseCache: function(content) {
this._response.responseCache = content.responseCache;
let packet = {
from: this.actorID,
type: "networkEventUpdate",
updateType: "responseCache",
};
this.conn.send(packet);
},
/**
* Add network event timing information.
*
* @param number total
* The total time of the network event.
* @param object timings
* Timing details about the network event.
*/
addEventTimings: function(total, timings, offsets) {
this._totalTime = total;
this._timings = timings;
this._offsets = offsets;
let packet = {
from: this.actorID,
type: "networkEventUpdate",
updateType: "eventTimings",
totalTime: total
};
this.conn.send(packet);
},
/**
* Prepare the headers array to be sent to the client by using the
* LongStringActor for the header values, when needed.
*
* @private
* @param array aHeaders
*/
_prepareHeaders: function(headers) {
for (let header of headers) {
header.value = this.parent._createStringGrip(header.value);
if (typeof header.value == "object") {
this._longStringActors.add(header.value);
}
}
},
};
NetworkEventActor.prototype.requestTypes =
{
"release": NetworkEventActor.prototype.onRelease,
"getRequestHeaders": NetworkEventActor.prototype.onGetRequestHeaders,
"getRequestCookies": NetworkEventActor.prototype.onGetRequestCookies,
"getRequestPostData": NetworkEventActor.prototype.onGetRequestPostData,
"getResponseHeaders": NetworkEventActor.prototype.onGetResponseHeaders,
"getResponseCookies": NetworkEventActor.prototype.onGetResponseCookies,
"getResponseCache": NetworkEventActor.prototype.onGetResponseCache,
"getResponseContent": NetworkEventActor.prototype.onGetResponseContent,
"getEventTimings": NetworkEventActor.prototype.onGetEventTimings,
"getSecurityInfo": NetworkEventActor.prototype.onGetSecurityInfo,
"getStackTrace": NetworkEventActor.prototype.onGetStackTrace,
};
exports.NetworkEventActor = NetworkEventActor;

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

@ -20,6 +20,7 @@ const ErrorDocs = require("devtools/server/actors/errordocs");
loader.lazyRequireGetter(this, "NetworkMonitor", "devtools/shared/webconsole/network-monitor", true);
loader.lazyRequireGetter(this, "NetworkMonitorChild", "devtools/shared/webconsole/network-monitor", true);
loader.lazyRequireGetter(this, "NetworkEventActor", "devtools/server/actors/network-event", true);
loader.lazyRequireGetter(this, "ConsoleProgressListener", "devtools/shared/webconsole/network-monitor", true);
loader.lazyRequireGetter(this, "StackTraceCollector", "devtools/shared/webconsole/network-monitor", true);
loader.lazyRequireGetter(this, "JSPropertyProvider", "devtools/shared/webconsole/js-property-provider", true);
@ -1904,529 +1905,3 @@ WebConsoleActor.prototype.requestTypes =
};
exports.WebConsoleActor = WebConsoleActor;
/**
* Creates an actor for a network event.
*
* @constructor
* @param object webConsoleActor
* The parent WebConsoleActor instance for this object.
*/
function NetworkEventActor(webConsoleActor) {
this.parent = webConsoleActor;
this.conn = this.parent.conn;
this._request = {
method: null,
url: null,
httpVersion: null,
headers: [],
cookies: [],
headersSize: null,
postData: {},
};
this._response = {
headers: [],
cookies: [],
content: {},
};
this._timings = {};
this._stackTrace = {};
// Keep track of LongStringActors owned by this NetworkEventActor.
this._longStringActors = new Set();
}
NetworkEventActor.prototype =
{
_request: null,
_response: null,
_timings: null,
_longStringActors: null,
actorPrefix: "netEvent",
/**
* Returns a grip for this actor for returning in a protocol message.
*/
grip: function() {
return {
actor: this.actorID,
startedDateTime: this._startedDateTime,
timeStamp: Date.parse(this._startedDateTime),
url: this._request.url,
method: this._request.method,
isXHR: this._isXHR,
cause: this._cause,
fromCache: this._fromCache,
fromServiceWorker: this._fromServiceWorker,
private: this._private,
};
},
/**
* Releases this actor from the pool.
*/
release: function() {
for (let grip of this._longStringActors) {
let actor = this.parent.getActorByID(grip.actor);
if (actor) {
this.parent.releaseActor(actor);
}
}
this._longStringActors = new Set();
if (this._request.url) {
this.parent._networkEventActorsByURL.delete(this._request.url);
}
if (this.channel) {
this.parent._netEvents.delete(this.channel);
}
this.parent.releaseActor(this);
},
/**
* Handle a protocol request to release a grip.
*/
onRelease: function() {
this.release();
return {};
},
/**
* Set the properties of this actor based on it's corresponding
* network event.
*
* @param object networkEvent
* The network event associated with this actor.
*/
init: function(networkEvent) {
this._startedDateTime = networkEvent.startedDateTime;
this._isXHR = networkEvent.isXHR;
this._cause = networkEvent.cause;
this._fromCache = networkEvent.fromCache;
this._fromServiceWorker = networkEvent.fromServiceWorker;
// Stack trace info isn't sent automatically. The client
// needs to request it explicitly using getStackTrace
// packet.
this._stackTrace = networkEvent.cause.stacktrace;
delete networkEvent.cause.stacktrace;
networkEvent.cause.stacktraceAvailable =
!!(this._stackTrace && this._stackTrace.length);
for (let prop of ["method", "url", "httpVersion", "headersSize"]) {
this._request[prop] = networkEvent[prop];
}
this._discardRequestBody = networkEvent.discardRequestBody;
this._discardResponseBody = networkEvent.discardResponseBody;
this._truncated = false;
this._private = networkEvent.private;
},
/**
* The "getRequestHeaders" packet type handler.
*
* @return object
* The response packet - network request headers.
*/
onGetRequestHeaders: function() {
return {
from: this.actorID,
headers: this._request.headers,
headersSize: this._request.headersSize,
rawHeaders: this._request.rawHeaders,
};
},
/**
* The "getRequestCookies" packet type handler.
*
* @return object
* The response packet - network request cookies.
*/
onGetRequestCookies: function() {
return {
from: this.actorID,
cookies: this._request.cookies,
};
},
/**
* The "getRequestPostData" packet type handler.
*
* @return object
* The response packet - network POST data.
*/
onGetRequestPostData: function() {
return {
from: this.actorID,
postData: this._request.postData,
postDataDiscarded: this._discardRequestBody,
};
},
/**
* The "getSecurityInfo" packet type handler.
*
* @return object
* The response packet - connection security information.
*/
onGetSecurityInfo: function() {
return {
from: this.actorID,
securityInfo: this._securityInfo,
};
},
/**
* The "getResponseHeaders" packet type handler.
*
* @return object
* The response packet - network response headers.
*/
onGetResponseHeaders: function() {
return {
from: this.actorID,
headers: this._response.headers,
headersSize: this._response.headersSize,
rawHeaders: this._response.rawHeaders,
};
},
/**
* The "getResponseCache" packet type handler.
*
* @return object
* The cache packet - network cache information.
*/
onGetResponseCache: function() {
return {
from: this.actorID,
cache: this._response.responseCache,
};
},
/**
* The "getResponseCookies" packet type handler.
*
* @return object
* The response packet - network response cookies.
*/
onGetResponseCookies: function() {
return {
from: this.actorID,
cookies: this._response.cookies,
};
},
/**
* The "getResponseContent" packet type handler.
*
* @return object
* The response packet - network response content.
*/
onGetResponseContent: function() {
return {
from: this.actorID,
content: this._response.content,
contentDiscarded: this._discardResponseBody,
};
},
/**
* The "getEventTimings" packet type handler.
*
* @return object
* The response packet - network event timings.
*/
onGetEventTimings: function() {
return {
from: this.actorID,
timings: this._timings,
totalTime: this._totalTime,
offsets: this._offsets
};
},
/**
* The "getStackTrace" packet type handler.
*
* @return object
* The response packet - stack trace.
*/
onGetStackTrace: function() {
return {
from: this.actorID,
stacktrace: this._stackTrace,
};
},
/** ****************************************************************
* Listeners for new network event data coming from NetworkMonitor.
******************************************************************/
/**
* Add network request headers.
*
* @param array headers
* The request headers array.
* @param string rawHeaders
* The raw headers source.
*/
addRequestHeaders: function(headers, rawHeaders) {
this._request.headers = headers;
this._prepareHeaders(headers);
rawHeaders = this.parent._createStringGrip(rawHeaders);
if (typeof rawHeaders == "object") {
this._longStringActors.add(rawHeaders);
}
this._request.rawHeaders = rawHeaders;
let packet = {
from: this.actorID,
type: "networkEventUpdate",
updateType: "requestHeaders",
headers: headers.length,
headersSize: this._request.headersSize,
};
this.conn.send(packet);
},
/**
* Add network request cookies.
*
* @param array cookies
* The request cookies array.
*/
addRequestCookies: function(cookies) {
this._request.cookies = cookies;
this._prepareHeaders(cookies);
let packet = {
from: this.actorID,
type: "networkEventUpdate",
updateType: "requestCookies",
cookies: cookies.length,
};
this.conn.send(packet);
},
/**
* Add network request POST data.
*
* @param object postData
* The request POST data.
*/
addRequestPostData: function(postData) {
this._request.postData = postData;
postData.text = this.parent._createStringGrip(postData.text);
if (typeof postData.text == "object") {
this._longStringActors.add(postData.text);
}
let packet = {
from: this.actorID,
type: "networkEventUpdate",
updateType: "requestPostData",
dataSize: postData.text.length,
discardRequestBody: this._discardRequestBody,
};
this.conn.send(packet);
},
/**
* Add the initial network response information.
*
* @param object info
* The response information.
* @param string rawHeaders
* The raw headers source.
*/
addResponseStart: function(info, rawHeaders) {
rawHeaders = this.parent._createStringGrip(rawHeaders);
if (typeof rawHeaders == "object") {
this._longStringActors.add(rawHeaders);
}
this._response.rawHeaders = rawHeaders;
this._response.httpVersion = info.httpVersion;
this._response.status = info.status;
this._response.statusText = info.statusText;
this._response.headersSize = info.headersSize;
this._discardResponseBody = info.discardResponseBody;
let packet = {
from: this.actorID,
type: "networkEventUpdate",
updateType: "responseStart",
response: info
};
this.conn.send(packet);
},
/**
* Add connection security information.
*
* @param object info
* The object containing security information.
*/
addSecurityInfo: function(info) {
this._securityInfo = info;
let packet = {
from: this.actorID,
type: "networkEventUpdate",
updateType: "securityInfo",
state: info.state,
};
this.conn.send(packet);
},
/**
* Add network response headers.
*
* @param array headers
* The response headers array.
*/
addResponseHeaders: function(headers) {
this._response.headers = headers;
this._prepareHeaders(headers);
let packet = {
from: this.actorID,
type: "networkEventUpdate",
updateType: "responseHeaders",
headers: headers.length,
headersSize: this._response.headersSize,
};
this.conn.send(packet);
},
/**
* Add network response cookies.
*
* @param array cookies
* The response cookies array.
*/
addResponseCookies: function(cookies) {
this._response.cookies = cookies;
this._prepareHeaders(cookies);
let packet = {
from: this.actorID,
type: "networkEventUpdate",
updateType: "responseCookies",
cookies: cookies.length,
};
this.conn.send(packet);
},
/**
* Add network response content.
*
* @param object content
* The response content.
* @param object
* - boolean discardedResponseBody
* Tells if the response content was recorded or not.
* - boolean truncated
* Tells if the some of the response content is missing.
*/
addResponseContent: function(content, {discardResponseBody, truncated}) {
this._truncated = truncated;
this._response.content = content;
content.text = this.parent._createStringGrip(content.text);
if (typeof content.text == "object") {
this._longStringActors.add(content.text);
}
let packet = {
from: this.actorID,
type: "networkEventUpdate",
updateType: "responseContent",
mimeType: content.mimeType,
contentSize: content.size,
encoding: content.encoding,
transferredSize: content.transferredSize,
discardResponseBody,
};
this.conn.send(packet);
},
addResponseCache: function(content) {
this._response.responseCache = content.responseCache;
let packet = {
from: this.actorID,
type: "networkEventUpdate",
updateType: "responseCache",
};
this.conn.send(packet);
},
/**
* Add network event timing information.
*
* @param number total
* The total time of the network event.
* @param object timings
* Timing details about the network event.
*/
addEventTimings: function(total, timings, offsets) {
this._totalTime = total;
this._timings = timings;
this._offsets = offsets;
let packet = {
from: this.actorID,
type: "networkEventUpdate",
updateType: "eventTimings",
totalTime: total
};
this.conn.send(packet);
},
/**
* Prepare the headers array to be sent to the client by using the
* LongStringActor for the header values, when needed.
*
* @private
* @param array aHeaders
*/
_prepareHeaders: function(headers) {
for (let header of headers) {
header.value = this.parent._createStringGrip(header.value);
if (typeof header.value == "object") {
this._longStringActors.add(header.value);
}
}
},
};
NetworkEventActor.prototype.requestTypes =
{
"release": NetworkEventActor.prototype.onRelease,
"getRequestHeaders": NetworkEventActor.prototype.onGetRequestHeaders,
"getRequestCookies": NetworkEventActor.prototype.onGetRequestCookies,
"getRequestPostData": NetworkEventActor.prototype.onGetRequestPostData,
"getResponseHeaders": NetworkEventActor.prototype.onGetResponseHeaders,
"getResponseCookies": NetworkEventActor.prototype.onGetResponseCookies,
"getResponseCache": NetworkEventActor.prototype.onGetResponseCache,
"getResponseContent": NetworkEventActor.prototype.onGetResponseContent,
"getEventTimings": NetworkEventActor.prototype.onGetEventTimings,
"getSecurityInfo": NetworkEventActor.prototype.onGetSecurityInfo,
"getStackTrace": NetworkEventActor.prototype.onGetStackTrace,
};

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

@ -348,9 +348,7 @@ const NodeFront = FrontClassWithSpec(nodeSpec, {
},
get isDisplayed() {
// The NodeActor's form contains the isDisplayed information as a boolean
// starting from FF32. Before that, the property is missing
return "isDisplayed" in this._form ? this._form.isDisplayed : true;
return this._form.isDisplayed;
},
get isTreeDisplayed() {

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

@ -1012,10 +1012,11 @@ Actor.prototype = extend(Pool.prototype, {
return { actor: this.actorID };
},
writeError: function(error) {
console.error(error);
writeError: function(error, typeName, method) {
console.error(`Error while calling actor '${typeName}'s method '${method}'`,
error.message);
if (error.stack) {
dump(error.stack);
console.error(error.stack);
}
this.conn.send({
from: this.actorID,
@ -1151,6 +1152,10 @@ var generateRequestHandlers = function(actorSpec, actorProto) {
throw ex;
}
if (!this[spec.name]) {
throw new Error(`Spec for '${actorProto.typeName}' specifies a '${spec.name}'` +
` method that isn't implemented by the actor`);
}
let ret = this[spec.name].apply(this, args);
let sendReturn = (retToSend) => {
@ -1172,7 +1177,7 @@ var generateRequestHandlers = function(actorSpec, actorProto) {
try {
this.destroy();
} catch (e) {
this.writeError(e);
this.writeError(e, actorProto.typeName, spec.name);
return;
}
}
@ -1184,11 +1189,11 @@ var generateRequestHandlers = function(actorSpec, actorProto) {
return p
.then(() => ret)
.then(sendReturn)
.catch(e => this.writeError(e));
.catch(e => this.writeError(e, actorProto.typeName, spec.name));
});
} catch (e) {
this._queueResponse(p => {
return p.then(() => this.writeError(e));
return p.then(() => this.writeError(e, actorProto.typeName, spec.name));
});
}
};

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

@ -108,6 +108,7 @@
#include "mozilla/css/ImageLoader.h"
#include "mozilla/layers/IAPZCTreeManager.h" // for layers::ZoomToRectBehavior
#include "mozilla/dom/Promise.h"
#include "mozilla/ServoBindings.h"
#include "mozilla/StyleSheetInlines.h"
#include "mozilla/gfx/GPUProcessManager.h"
#include "mozilla/dom/TimeoutManager.h"

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

@ -206,6 +206,32 @@ SourceBuffer::AppendBuffer(const ArrayBufferView& aData, ErrorResult& aRv)
AppendData(aData.Data(), aData.Length(), aRv);
}
already_AddRefed<Promise>
SourceBuffer::AppendBufferAsync(const ArrayBuffer& aData,
ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread());
MSE_API("AppendBufferAsync(ArrayBuffer)");
aData.ComputeLengthAndData();
DDLOG(DDLogCategory::API, "AppendBufferAsync", aData.Length());
return AppendDataAsync(aData.Data(), aData.Length(), aRv);
}
already_AddRefed<Promise>
SourceBuffer::AppendBufferAsync(const ArrayBufferView& aData,
ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread());
MSE_API("AppendBufferAsync(ArrayBufferView)");
aData.ComputeLengthAndData();
DDLOG(DDLogCategory::API, "AppendBufferAsync", aData.Length());
return AppendDataAsync(aData.Data(), aData.Length(), aRv);
}
void
SourceBuffer::Abort(ErrorResult& aRv)
{
@ -259,6 +285,55 @@ SourceBuffer::Remove(double aStart, double aEnd, ErrorResult& aRv)
MSE_API("Remove(aStart=%f, aEnd=%f)", aStart, aEnd);
DDLOG(DDLogCategory::API, "Remove-from", aStart);
DDLOG(DDLogCategory::API, "Remove-until", aEnd);
PrepareRemove(aStart, aEnd, aRv);
if (aRv.Failed()) {
return;
}
RangeRemoval(aStart, aEnd);
}
already_AddRefed<Promise>
SourceBuffer::RemoveAsync(double aStart, double aEnd, ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread());
MSE_API("RemoveAsync(aStart=%f, aEnd=%f)", aStart, aEnd);
DDLOG(DDLogCategory::API, "Remove-from", aStart);
DDLOG(DDLogCategory::API, "Remove-until", aEnd);
if (!IsAttached()) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return nullptr;
}
nsCOMPtr<nsIGlobalObject> parentObject =
do_QueryInterface(mMediaSource->GetParentObject());
if (!parentObject) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
RefPtr<Promise> promise = Promise::Create(parentObject, aRv);
if (aRv.Failed()) {
return nullptr;
}
PrepareRemove(aStart, aEnd, aRv);
if (aRv.Failed()) {
// The bindings will automatically return a rejected promise.
return nullptr;
}
MOZ_ASSERT(!mDOMPromise, "Can't have a pending operation going");
mDOMPromise = promise;
RangeRemoval(aStart, aEnd);
return promise.forget();
}
void
SourceBuffer::PrepareRemove(double aStart, double aEnd, ErrorResult& aRv)
{
if (!IsAttached()) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
@ -276,8 +351,6 @@ SourceBuffer::Remove(double aStart, double aEnd, ErrorResult& aRv)
if (mMediaSource->ReadyState() == MediaSourceReadyState::Ended) {
mMediaSource->SetReadyState(MediaSourceReadyState::Open);
}
RangeRemoval(aStart, aEnd);
}
void
@ -459,6 +532,10 @@ SourceBuffer::StopUpdating()
mUpdating = false;
QueueAsyncSimpleEvent("update");
QueueAsyncSimpleEvent("updateend");
if (mDOMPromise) {
mDOMPromise->MaybeResolveWithUndefined();
mDOMPromise = nullptr;
}
}
void
@ -468,6 +545,10 @@ SourceBuffer::AbortUpdating()
mUpdating = false;
QueueAsyncSimpleEvent("abort");
QueueAsyncSimpleEvent("updateend");
if (mDOMPromise) {
mDOMPromise->MaybeReject(NS_ERROR_DOM_MEDIA_ABORT_ERR);
mDOMPromise = nullptr;
}
}
void
@ -485,6 +566,7 @@ SourceBuffer::CheckEndTime()
void
SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread());
MSE_DEBUG("AppendData(aLength=%u)", aLength);
RefPtr<MediaByteBuffer> data = PrepareAppend(aData, aLength, aRv);
@ -500,8 +582,43 @@ SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aR
->Track(mPendingAppend);
}
already_AddRefed<Promise>
SourceBuffer::AppendDataAsync(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread());
if (!IsAttached()) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return nullptr;
}
nsCOMPtr<nsIGlobalObject> parentObject =
do_QueryInterface(mMediaSource->GetParentObject());
if (!parentObject) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
RefPtr<Promise> promise = Promise::Create(parentObject, aRv);
if (aRv.Failed()) {
return nullptr;
}
AppendData(aData, aLength, aRv);
if (aRv.Failed()) {
return nullptr;
}
MOZ_ASSERT(!mDOMPromise, "Can't have a pending operation going");
mDOMPromise = promise;
return promise.forget();
}
void
SourceBuffer::AppendDataCompletedWithSuccess(const SourceBufferTask::AppendBufferResult& aResult)
SourceBuffer::AppendDataCompletedWithSuccess(
const SourceBufferTask::AppendBufferResult& aResult)
{
MOZ_ASSERT(mUpdating);
mPendingAppend.Complete();
@ -570,10 +687,17 @@ SourceBuffer::AppendError(const MediaResult& aDecodeError)
MOZ_ASSERT(NS_FAILED(aDecodeError));
mMediaSource->EndOfStream(aDecodeError);
if (mDOMPromise) {
mDOMPromise->MaybeReject(aDecodeError);
mDOMPromise = nullptr;
}
}
already_AddRefed<MediaByteBuffer>
SourceBuffer::PrepareAppend(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv)
SourceBuffer::PrepareAppend(const uint8_t* aData,
uint32_t aLength,
ErrorResult& aRv)
{
typedef TrackBuffersManager::EvictDataResult Result;
@ -660,12 +784,14 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(SourceBuffer)
tmp->Detach();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mMediaSource)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mBuffered)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDOMPromise)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(SourceBuffer,
DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaSource)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBuffered)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDOMPromise)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_ADDREF_INHERITED(SourceBuffer, DOMEventTargetHelper)

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

@ -88,11 +88,20 @@ public:
void AppendBuffer(const ArrayBuffer& aData, ErrorResult& aRv);
void AppendBuffer(const ArrayBufferView& aData, ErrorResult& aRv);
already_AddRefed<Promise> AppendBufferAsync(const ArrayBuffer& aData,
ErrorResult& aRv);
already_AddRefed<Promise> AppendBufferAsync(const ArrayBufferView& aData,
ErrorResult& aRv);
void Abort(ErrorResult& aRv);
void AbortBufferAppend();
void Remove(double aStart, double aEnd, ErrorResult& aRv);
already_AddRefed<Promise> RemoveAsync(double aStart,
double aEnd,
ErrorResult& aRv);
void ChangeType(const nsAString& aType, ErrorResult& aRv);
IMPL_EVENT_HANDLER(updatestart);
@ -157,6 +166,10 @@ private:
// Shared implementation of AppendBuffer overloads.
void AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv);
// Shared implementation of AppendBufferAsync overloads.
already_AddRefed<Promise> AppendDataAsync(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv);
void PrepareRemove(double aStart, double aEnd, ErrorResult& aRv);
// Implement the "Append Error Algorithm".
// Will call endOfStream() with "decode" error if aDecodeError is true.
@ -190,6 +203,11 @@ private:
RefPtr<TimeRanges> mBuffered;
MozPromiseRequestHolder<MediaSource::ActiveCompletionPromise> mCompletionPromise;
// Only used if MSE v2 experimental mode is active.
// Contains the current Promise to be resolved following use of
// appendBufferAsync and removeAsync. Not set of no operation is pending.
RefPtr<Promise> mDOMPromise;
};
} // namespace dom

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

@ -115,6 +115,36 @@ function fetchAndLoad(sb, prefix, chunks, suffix) {
});
}
function loadSegmentAsync(sb, typedArrayOrArrayBuffer) {
var typedArray = (typedArrayOrArrayBuffer instanceof ArrayBuffer) ? new Uint8Array(typedArrayOrArrayBuffer)
: typedArrayOrArrayBuffer;
info(`Loading buffer2: [${typedArray.byteOffset}, ${typedArray.byteOffset + typedArray.byteLength})`);
var beforeBuffered = timeRangeToString(sb.buffered);
return sb.appendBufferAsync(typedArray).then(() => {
var afterBuffered = timeRangeToString(sb.buffered);
info(`SourceBuffer buffered ranges grew from ${beforeBuffered} to ${afterBuffered}`);
});
}
function fetchAndLoadAsync(sb, prefix, chunks, suffix) {
// Fetch the buffers in parallel.
var buffers = {};
var fetches = [];
for (var chunk of chunks) {
fetches.push(fetchWithXHR(prefix + chunk + suffix).then(((c, x) => buffers[c] = x).bind(null, chunk)));
}
// Load them in series, as required per spec.
return Promise.all(fetches).then(function() {
var rv = Promise.resolve();
for (var chunk of chunks) {
rv = rv.then(loadSegmentAsync.bind(null, sb, buffers[chunk]));
}
return rv;
});
}
//Register timeout function to dump debugging logs.
SimpleTest.registerTimeoutFunction(function() {
for (var v of document.getElementsByTagName("video")) {

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

@ -81,6 +81,8 @@ skip-if = android_version == '22' || toolkit == 'android' # bug 1358640, bug 140
skip-if = toolkit == 'android' # Not supported on android
[test_Eviction_mp4.html]
skip-if = android_version == '15' # Not supported on Android(Bug 1358271)
[test_ExperimentalAsync.html]
skip-if = android_version == '22' || toolkit == 'android' # bug 1341519, bug 1401090
[test_FrameSelection.html]
skip-if = android_version == '22' || toolkit == 'android' # bug 1341519, bug 1401090
[test_FrameSelection_mp4.html]

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

@ -0,0 +1,102 @@
<!DOCTYPE html>
<html><head>
<meta http-equiv="content-type" content="text/html; charset=windows-1252">
<title>MSE: testing removeAsync and appendBufferAsync</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="mediasource.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<pre id="test"><script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
addMSEPrefs(
["media.mediasource.eviction_threshold.audio", 524288],
["media.dormant-on-pause-timeout-ms", -1], // FIXME: bug 1319292
["media.mediasource.experimental.enabled", true]
);
// We fill up the source buffer with audio data until the buffer is full.
// We ensure that QuotaExceededError is thrown once the buffer is full.
// We then seek to half the content. By that time, another appendBuffer must succeed
// as the auto-eviction would succeed (removing all data prior currentTime)
// The test then fills the audio buffer and plays until the end.
// Fill up the SourceBuffer by appending data repeatedly via doAppendDataFunc until
// an exception is thrown.
async function fillUpSourceBuffer(sourceBuffer, doAppendDataFunc, onCaughtExceptionCallback) {
try {
// We are appending data repeatedly in sequence mode, there should be no gaps.
while(true) {
ok(sourceBuffer.buffered.length <= 1, "there should be no gap in buffered ranges.");
await doAppendDataFunc();
}
} catch (ex) {
ok(true, "appendBuffer promise got rejected");
onCaughtExceptionCallback(ex);
}
}
runWithMSE(async function(ms, el) {
el.controls = true;
await once(ms, "sourceopen");
ok(true, "Receive a sourceopen event");
let audiosb = ms.addSourceBuffer("audio/mp4");
// Test removeAsync
audiosb.mode = "sequence";
var audioInitBuffer = await fetchWithXHR("bipbop/bipbop_audioinit.mp4");
await audiosb.appendBufferAsync(audioInitBuffer);
var audioBuffer = await fetchWithXHR("bipbop/bipbop_audio1.m4s");
fillUpSourceBuffer(audiosb,
function() { // doAppendDataFunc
return audiosb.appendBufferAsync(audioBuffer);
},
async function(ex) { // onCaughtExceptionCallback
is(ex.name, "QuotaExceededError", "QuotaExceededError thrown");
is(audiosb.buffered.end(0), el.duration, "Duration is end of buffered range");
let seekTime = audiosb.buffered.end(0) / 2;
el.currentTime = seekTime;
await once(el, "seeked");
dump("dump: seeked to " + seekTime);
is(el.currentTime, seekTime, "correctly seeked to " + seekTime);
await audiosb.appendBufferAsync(audioBuffer).catch(function(ex) {
ok(false, "Shouldn't throw another time when data can be evicted");
el.mozDumpDebugInfo();
SimpleTest.finish();
});
// Test that an error in remove return a rejected promise
await audiosb.removeAsync(5, 0).catch(async function(ex) {
ok(true, "remove promise got rejected with end <= start");
is(ex.name, "TypeError");
await audiosb.removeAsync(ms.duration + 1, Infinity).catch(async function(ex) {
ok(true, "remove promise got rejected with start > duration");
is(ex.name, "TypeError");
await audiosb.removeAsync(0, Infinity).catch(function(ex) {
ok(false, "shouldn't throw");
});
ok(true, "remove succeeded");
is(audiosb.buffered.length, 0, "buffered should be empty");
audiosb.mode = "segment";
audiosb.timestampOffset = 0;
el.currentTime = 0;
await fetchAndLoadAsync(audiosb, "bipbop/bipbop_audio", range(1, 4), ".m4s");
ms.endOfStream();
el.play();
await once(el, "ended");
is(el.currentTime, el.duration, "played to the end");
SimpleTest.finish();
throw ex; // ensure we don't fallback on lines below.
});
ok(false, "should have returned an error");
});
ok(false, "should have returned an error");
}
);
});
</script>
</pre>
</body>
</html>

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

@ -40,6 +40,12 @@ interface SourceBuffer : EventTarget {
void appendBuffer(ArrayBuffer data);
[Throws]
void appendBuffer(ArrayBufferView data);
// Experimental function as proposed in:
// https://github.com/w3c/media-source/issues/100 for promise proposal.
[Throws, Func="mozilla::dom::MediaSource::ExperimentalEnabled"]
Promise<void> appendBufferAsync(ArrayBuffer data);
[Throws, Func="mozilla::dom::MediaSource::ExperimentalEnabled"]
Promise<void> appendBufferAsync(ArrayBufferView data);
//[Throws]
//void appendStream(Stream stream, [EnforceRange] optional unsigned long long maxSize);
[Throws]
@ -47,6 +53,10 @@ interface SourceBuffer : EventTarget {
[Throws]
void remove(double start, unrestricted double end);
// Experimental function as proposed in:
// https://github.com/w3c/media-source/issues/100 for promise proposal.
[Throws, Func="mozilla::dom::MediaSource::ExperimentalEnabled"]
Promise<void> removeAsync(double start, unrestricted double end);
// Experimental function as proposed in:
// https://github.com/w3c/media-source/issues/155
[Throws, Func="mozilla::dom::MediaSource::ExperimentalEnabled"]
void changeType(DOMString type);

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

@ -16,6 +16,7 @@
#include "nsLayoutCID.h"
#include "mozilla/dom/URL.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/ServoBindings.h"
#include "mozilla/ServoStyleRuleMap.h"
#include "mozilla/StyleSheet.h"
#include "mozilla/StyleSheetInlines.h"

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

@ -11,6 +11,9 @@ const LDAPSyncQueryContractID = "@mozilla.org/ldapsyncquery;1";
const nsIPrefService = Ci.nsIPrefService;
const PrefServiceContractID = "@mozilla.org/preferences-service;1";
// ChromeUtils isn't available here, so we can't use Services.*
/* eslint-disable mozilla/use-services */
var gVersion;
var gIsUTF8;

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

@ -4,17 +4,12 @@
/* eslint no-unsafe-finally: "off"*/
/* Turning off this rule to allow control flow operations in finally block
* http://eslint.org/docs/rules/no-unsafe-finally */
function run_test() {
let dirSvc = Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties);
let obsvc = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
let ps = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefService);
let prefs = ps.getBranch(null);
let greD = dirSvc.get("GreD", Ci.nsIFile);
let defaultPrefD = dirSvc.get("PrfDef", Ci.nsIFile);
ChromeUtils.import("resource://gre/modules/Services.jsm");
function run_test() {
let greD = Services.dirsvc.get("GreD", Ci.nsIFile);
let defaultPrefD = Services.dirsvc.get("PrfDef", Ci.nsIFile);
let testDir = do_get_cwd();
try {
@ -24,7 +19,7 @@ function run_test() {
// Make sure nsReadConfig is initialized.
Cc["@mozilla.org/readconfig;1"].getService(Ci.nsISupports);
ps.resetPrefs();
Services.prefs.resetPrefs();
var tests = [{
filename: "autoconfig-utf8.cfg",
@ -47,24 +42,24 @@ function run_test() {
function testAutoConfig(test) {
// Make sure pref values are unset.
for (let prefName in test.prefs) {
Assert.equal(Ci.nsIPrefBranch.PREF_INVALID, prefs.getPrefType(prefName));
Assert.equal(Ci.nsIPrefBranch.PREF_INVALID, Services.prefs.getPrefType(prefName));
}
let autoConfigCfg = testDir.clone();
autoConfigCfg.append(test.filename);
autoConfigCfg.copyTo(greD, "autoconfig.cfg");
obsvc.notifyObservers(ps, "prefservice:before-read-userprefs");
Services.obs.notifyObservers(Services.prefs, "prefservice:before-read-userprefs");
for (let prefName in test.prefs) {
Assert.equal(test.prefs[prefName],
prefs.getStringPref(prefName));
Services.prefs.getStringPref(prefName));
}
ps.resetPrefs();
Services.prefs.resetPrefs();
// Make sure pref values are reset.
for (let prefName in test.prefs) {
Assert.equal(Ci.nsIPrefBranch.PREF_INVALID, prefs.getPrefType(prefName));
Assert.equal(Ci.nsIPrefBranch.PREF_INVALID, Services.prefs.getPrefType(prefName));
}
}
@ -91,6 +86,6 @@ function run_test() {
}
}
ps.resetPrefs();
Services.prefs.resetPrefs();
}
}

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

@ -4,10 +4,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#if defined(MOZ_WIDGET_GTK)
#include <gdk/gdkx.h>
// we're using default display for now
#define GET_NATIVE_WINDOW_FROM_REAL_WIDGET(aWidget) ((EGLNativeWindowType)GDK_WINDOW_XID((GdkWindow*)aWidget->GetNativeData(NS_NATIVE_WINDOW)))
#define GET_NATIVE_WINDOW_FROM_COMPOSITOR_WIDGET(aWidget) ((EGLNativeWindowType)GDK_WINDOW_XID((GdkWindow*)aWidget->RealWidget()->GetNativeData(NS_NATIVE_WINDOW)))
#define GET_NATIVE_WINDOW_FROM_REAL_WIDGET(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_EGL_WINDOW))
#define GET_NATIVE_WINDOW_FROM_COMPOSITOR_WIDGET(aWidget) ((EGLNativeWindowType)aWidget->RealWidget()->GetNativeData(NS_NATIVE_EGL_WINDOW))
#elif defined(MOZ_WIDGET_ANDROID)
#define GET_NATIVE_WINDOW_FROM_REAL_WIDGET(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_JAVA_SURFACE))
#define GET_NATIVE_WINDOW_FROM_COMPOSITOR_WIDGET(aWidget) (aWidget->AsAndroid()->GetEGLNativeWindow())

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

@ -31,6 +31,13 @@
#include "GLContextProvider.h"
#include "gfxPrefs.h"
#include "ScopedGLHelpers.h"
#ifdef MOZ_WIDGET_GTK
#include <gdk/gdk.h>
#ifdef MOZ_WAYLAND
#include <gdk/gdkwayland.h>
#include <dlfcn.h>
#endif // MOZ_WIDGET_GTK
#endif // MOZ_WAYLAND
namespace mozilla {
namespace gl {
@ -719,7 +726,22 @@ GLLibraryEGL::CreateDisplay(bool forceAccel, const nsCOMPtr<nsIGfxInfo>& gfxInfo
mIsWARP = true;
}
} else {
chosenDisplay = GetAndInitDisplay(*this, EGL_DEFAULT_DISPLAY);
void *nativeDisplay = EGL_DEFAULT_DISPLAY;
#ifdef MOZ_WAYLAND
// Some drivers doesn't support EGL_DEFAULT_DISPLAY
GdkDisplay *gdkDisplay = gdk_display_get_default();
if (GDK_IS_WAYLAND_DISPLAY(gdkDisplay)) {
static auto sGdkWaylandDisplayGetWlDisplay =
(wl_display *(*)(GdkDisplay *))
dlsym(RTLD_DEFAULT, "gdk_wayland_display_get_wl_display");
nativeDisplay = sGdkWaylandDisplayGetWlDisplay(gdkDisplay);
if (!nativeDisplay) {
NS_WARNING("Failed to get wl_display.");
return nullptr;
}
}
#endif
chosenDisplay = GetAndInitDisplay(*this, nativeDisplay);
}
if (!chosenDisplay) {
@ -888,4 +910,3 @@ AfterEGLCall(const char* glFunction)
} /* namespace gl */
} /* namespace mozilla */

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

@ -177,6 +177,7 @@
#include "nsLayoutStylesheetCache.h"
#include "mozilla/layers/InputAPZContext.h"
#include "mozilla/layers/FocusTarget.h"
#include "mozilla/ServoBindings.h"
#include "mozilla/ServoStyleSet.h"
#include "mozilla/StyleSheet.h"
#include "mozilla/StyleSheetInlines.h"

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

@ -0,0 +1,19 @@
<style>
:not(feConvolveMatrix) {
width: -moz-max-content;
column-width: 0em;
text-indent: 1pt;
}
.cl {
padding-bottom: 93vw;
}
</style>
<script>
function go() {
b.appendChild(a);
}
</script>
<marquee id="b">4H</marquee>
<details class="cl">
<summary id="a" style="mix-blend-mode:color-dodge">A</summary>
<style onload="go()">

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

@ -531,3 +531,4 @@ load 1453702.html
load 1453342.html
load 1453196.html
pref(dom.webcomponents.shadowdom.enabled,true) load 1414303.html
load 1461812.html

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

@ -13,6 +13,7 @@
#include "brotli/decode.h"
#include "zlib.h"
#include "mozilla/dom/FontFaceSet.h"
#include "mozilla/ServoBindings.h"
#include "mozilla/ServoFontFaceRule.h"
#include "mozilla/Unused.h"

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

@ -149,8 +149,7 @@ RetainedDisplayListBuilder::PreProcessDisplayList(RetainedDisplayList* aList,
if (item->GetChildren()) {
if (!PreProcessDisplayList(item->GetChildren(), SelectAGRForFrame(f, aAGR))) {
mBuilder.MarkFrameForDisplayIfVisible(f, mBuilder.RootReferenceFrame());
mBuilder.MarkFrameModifiedDuringBuilding(f);
return false;
}
}
@ -463,11 +462,6 @@ public:
bool mResultIsModified;
};
void RetainedDisplayList::ClearDAG()
{
mDAG.Clear();
}
/**
* Takes two display lists and merges them into an output list.
*
@ -1119,7 +1113,7 @@ RetainedDisplayListBuilder::AttemptPartialUpdate(
&modifiedAGR, framesWithProps.Frames()) ||
!PreProcessDisplayList(&mList, modifiedAGR)) {
mBuilder.LeavePresShell(mBuilder.RootReferenceFrame(), List());
mList.ClearDAG();
mList.DeleteAll(&mBuilder);
return PartialUpdateResult::Failed;
}
@ -1157,7 +1151,8 @@ RetainedDisplayListBuilder::AttemptPartialUpdate(
if (mBuilder.PartialBuildFailed()) {
mBuilder.SetPartialBuildFailed(false);
mBuilder.LeavePresShell(mBuilder.RootReferenceFrame(), List());
mList.ClearDAG();
mList.DeleteAll(&mBuilder);
modifiedDL.DeleteAll(&mBuilder);
return PartialUpdateResult::Failed;
}

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

@ -35,6 +35,7 @@
#include "LayerState.h"
#include "FrameMetrics.h"
#include "ImgDrawResult.h"
#include "mozilla/EffectCompositor.h"
#include "mozilla/EnumeratedArray.h"
#include "mozilla/Maybe.h"
#include "mozilla/UniquePtr.h"
@ -3474,11 +3475,10 @@ public:
}
}
mOldItems.Clear();
mDAG.Clear();
nsDisplayList::DeleteAll(aBuilder);
}
void ClearDAG();
DirectedAcyclicGraph<MergedListUnits> mDAG;
// Temporary state initialized during the preprocess pass

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

@ -11,6 +11,7 @@
#include "nsCRT.h"
#include "mozilla/AsyncEventDispatcher.h"
#include "mozilla/ComputedStyleInlines.h"
#include "mozilla/dom/Selection.h"
#include "mozilla/dom/CustomEvent.h"
#include "mozilla/dom/ScriptSettings.h"

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

@ -13,6 +13,7 @@
#include <algorithm>
#include "mozilla/ArenaObjectID.h"
#include "mozilla/Assertions.h"
#include "mozilla/ServoComputedData.h"
#include "mozilla/ServoTypes.h"
#include "mozilla/ServoUtils.h"
#include "mozilla/StyleComplexColor.h"

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

@ -15,9 +15,8 @@
#define ComputedStyleInlines_h
#include "mozilla/ComputedStyle.h"
#include "mozilla/ComputedStyle.h"
#include "mozilla/ServoComputedDataInlines.h"
#include "mozilla/ServoUtils.h"
#include "mozilla/ServoBindings.h"
namespace mozilla {
@ -28,7 +27,7 @@ ComputedStyle::Style##name_() { \
} \
const nsStyle##name_ * \
ComputedStyle::ThreadsafeStyle##name_() { \
if (mozilla::ServoStyleSet::IsInServoTraversal()) { \
if (mozilla::IsInServoTraversal()) { \
return ComputedData()->GetStyle##name_(); \
} \
return Style##name_(); \
@ -53,7 +52,7 @@ const nsStyle##name_ * ComputedStyle::DoGetStyle##name_() { \
/* perform any remaining main thread work on the struct */ \
if (needToCompute) { \
MOZ_ASSERT(NS_IsMainThread()); \
MOZ_ASSERT(!mozilla::ServoStyleSet::IsInServoTraversal()); \
MOZ_ASSERT(!mozilla::IsInServoTraversal()); \
const_cast<nsStyle##name_*>(data)->FinishStyle(mPresContext, nullptr); \
/* the ComputedStyle owns the struct */ \
AddStyleBit(NS_STYLE_INHERIT_BIT(name_)); \

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

@ -8,6 +8,7 @@
#define mozilla_ServoBindingTypes_h
#include "mozilla/RefPtr.h"
#include "mozilla/ServoComputedData.h"
#include "mozilla/ServoTypes.h"
#include "mozilla/SheetType.h"
#include "mozilla/UniquePtr.h"

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

@ -1668,11 +1668,11 @@ Gecko_CreateGradient(uint8_t aShape,
return result;
}
const mozilla::css::URLValueData*
Gecko_GetURLValue(const nsStyleImage* aImage)
const nsStyleImageRequest*
Gecko_GetImageRequest(const nsStyleImage* aImage)
{
MOZ_ASSERT(aImage && aImage->GetType() == eStyleImageType_Image);
return aImage->GetURLValue();
MOZ_ASSERT(aImage);
return aImage->ImageRequest();
}
nsAtom*

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

@ -12,6 +12,7 @@
#include "mozilla/AtomArray.h"
#include "mozilla/ServoTypes.h"
#include "mozilla/ServoBindingTypes.h"
#include "mozilla/ServoComputedDataInlines.h"
#include "mozilla/ServoElementSnapshot.h"
#include "mozilla/css/SheetLoadData.h"
#include "mozilla/css/SheetParsingMode.h"
@ -20,7 +21,6 @@
#include "mozilla/ComputedTimingFunction.h"
#include "nsChangeHint.h"
#include "nsIDocument.h"
#include "nsStyleStruct.h"
/*
* API for Servo to access Gecko data structures.
@ -78,17 +78,6 @@ const bool GECKO_IS_NIGHTLY = true;
const bool GECKO_IS_NIGHTLY = false;
#endif
namespace mozilla {
#define STYLE_STRUCT(name_) struct Gecko##name_ {nsStyle##name_ gecko;};
#include "nsStyleStructList.h"
#undef STYLE_STRUCT
}
#define STYLE_STRUCT(name_) \
const nsStyle##name_* ServoComputedData::GetStyle##name_() const { return &name_.mPtr->gecko; }
#include "nsStyleStructList.h"
#undef STYLE_STRUCT
#define NS_DECL_THREADSAFE_FFI_REFCOUNTING(class_, name_) \
void Gecko_AddRef##name_##ArbitraryThread(class_* aPtr); \
void Gecko_Release##name_##ArbitraryThread(class_* aPtr);
@ -371,7 +360,7 @@ nsStyleGradient* Gecko_CreateGradient(uint8_t shape,
bool moz_legacy_syntax,
uint32_t stops);
const mozilla::css::URLValueData* Gecko_GetURLValue(const nsStyleImage* image);
const nsStyleImageRequest* Gecko_GetImageRequest(const nsStyleImage* image);
nsAtom* Gecko_GetImageElement(const nsStyleImage* image);
const nsStyleGradient* Gecko_GetGradientImageValue(const nsStyleImage* image);

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

@ -0,0 +1,111 @@
/* -*- 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_ServoComputedData_h
#define mozilla_ServoComputedData_h
#include "mozilla/ServoTypes.h"
/*
* ServoComputedData and its related types.
*/
#define STYLE_STRUCT(name_) struct nsStyle##name_;
#include "nsStyleStructList.h"
#undef STYLE_STRUCT
namespace mozilla {
struct ServoWritingMode {
uint8_t mBits;
};
struct ServoCustomPropertiesMap {
uintptr_t mPtr;
};
struct ServoRuleNode {
uintptr_t mPtr;
};
class ComputedStyle;
struct ServoVisitedStyle {
// This is actually a strong reference
// but ServoComputedData's destructor is
// managed by the Rust code so we just use a
// regular pointer
ComputedStyle* mPtr;
};
struct ServoComputedValueFlags {
uint16_t mFlags;
};
#define STYLE_STRUCT(name_) struct Gecko##name_;
#include "nsStyleStructList.h"
#undef STYLE_STRUCT
} // namespace mozilla
class ServoComputedData;
struct ServoComputedDataForgotten
{
// Make sure you manually mem::forget the backing ServoComputedData
// after calling this
explicit ServoComputedDataForgotten(const ServoComputedData* aValue) : mPtr(aValue) {}
const ServoComputedData* mPtr;
};
/**
* We want C++ to be able to read the style struct fields of ComputedValues
* so we define this type on the C++ side and use the bindgenned version
* on the Rust side.
*/
class ServoComputedData
{
friend class mozilla::ComputedStyle;
public:
// Constructs via memcpy. Will not move out of aValue.
explicit ServoComputedData(const ServoComputedDataForgotten aValue);
#define STYLE_STRUCT(name_) \
mozilla::ServoRawOffsetArc<mozilla::Gecko##name_> name_; \
inline const nsStyle##name_* GetStyle##name_() const;
#include "nsStyleStructList.h"
#undef STYLE_STRUCT
void AddSizeOfExcludingThis(nsWindowSizes& aSizes) const;
private:
mozilla::ServoCustomPropertiesMap custom_properties;
mozilla::ServoWritingMode writing_mode;
mozilla::ServoComputedValueFlags flags;
/// The rule node representing the ordered list of rules matched for this
/// node. Can be None for default values and text nodes. This is
/// essentially an optimization to avoid referencing the root rule node.
mozilla::ServoRuleNode rules;
/// The element's computed values if visited, only computed if there's a
/// relevant link for this element. A element's "relevant link" is the
/// element being matched if it is a link or the nearest ancestor link.
mozilla::ServoVisitedStyle visited_style;
// C++ just sees this struct as a bucket of bits, and will
// do the wrong thing if we let it use the default copy ctor/assignment
// operator. Remove them so that there is no footgun.
//
// We remove the move ctor/assignment operator as well, because
// moves in C++ don't prevent destructors from being called,
// which will lead to double frees.
ServoComputedData& operator=(const ServoComputedData&) = delete;
ServoComputedData(const ServoComputedData&) = delete;
ServoComputedData&& operator=(const ServoComputedData&&) = delete;
ServoComputedData(const ServoComputedData&&) = delete;
};
#endif // mozilla_ServoComputedData_h

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

@ -0,0 +1,24 @@
/* -*- 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_ServoComputedDataInlines_h
#define mozilla_ServoComputedDataInlines_h
#include "mozilla/ServoComputedData.h"
#include "nsStyleStruct.h"
namespace mozilla {
#define STYLE_STRUCT(name_) struct Gecko##name_ {nsStyle##name_ gecko;};
#include "nsStyleStructList.h"
#undef STYLE_STRUCT
}
#define STYLE_STRUCT(name_) \
const nsStyle##name_* ServoComputedData::GetStyle##name_() const { return &name_.mPtr->gecko; }
#include "nsStyleStructList.h"
#undef STYLE_STRUCT
#endif // mozilla_ServoComputedDataInlines_h

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

@ -9,10 +9,6 @@
#include "mozilla/TypedEnumBits.h"
#define STYLE_STRUCT(name_) struct nsStyle##name_;
#include "nsStyleStructList.h"
#undef STYLE_STRUCT
/*
* Type definitions used to interact with Servo. This gets included by nsINode,
* so don't add significant include dependencies to this file.
@ -129,44 +125,6 @@ enum class InheritTarget {
PlaceholderFrame,
};
struct ServoWritingMode {
uint8_t mBits;
};
struct ServoCustomPropertiesMap {
uintptr_t mPtr;
};
struct ServoRuleNode {
uintptr_t mPtr;
};
class ComputedStyle;
struct ServoVisitedStyle {
// This is actually a strong reference
// but ServoComputedData's destructor is
// managed by the Rust code so we just use a
// regular pointer
ComputedStyle* mPtr;
};
template <typename T>
struct ServoRawOffsetArc {
// Again, a strong reference, but
// managed by the Rust code
T* mPtr;
};
struct ServoComputedValueFlags {
uint16_t mFlags;
};
#define STYLE_STRUCT(name_) struct Gecko##name_;
#include "nsStyleStructList.h"
#undef STYLE_STRUCT
// These measurements are obtained for both the UA cache and the Stylist, but
// not all the fields are used in both cases.
class ServoStyleSetSizes
@ -189,63 +147,13 @@ public:
{}
};
template <typename T>
struct ServoRawOffsetArc {
// Again, a strong reference, but
// managed by the Rust code
T* mPtr;
};
} // namespace mozilla
class ServoComputedData;
struct ServoComputedDataForgotten
{
// Make sure you manually mem::forget the backing ServoComputedData
// after calling this
explicit ServoComputedDataForgotten(const ServoComputedData* aValue) : mPtr(aValue) {}
const ServoComputedData* mPtr;
};
/**
* We want C++ to be able to read the style struct fields of ComputedValues
* so we define this type on the C++ side and use the bindgenned version
* on the Rust side.
*/
class ServoComputedData
{
friend class mozilla::ComputedStyle;
public:
// Constructs via memcpy. Will not move out of aValue.
explicit ServoComputedData(const ServoComputedDataForgotten aValue);
#define STYLE_STRUCT(name_) \
mozilla::ServoRawOffsetArc<mozilla::Gecko##name_> name_; \
inline const nsStyle##name_* GetStyle##name_() const;
#include "nsStyleStructList.h"
#undef STYLE_STRUCT
void AddSizeOfExcludingThis(nsWindowSizes& aSizes) const;
private:
mozilla::ServoCustomPropertiesMap custom_properties;
mozilla::ServoWritingMode writing_mode;
mozilla::ServoComputedValueFlags flags;
/// The rule node representing the ordered list of rules matched for this
/// node. Can be None for default values and text nodes. This is
/// essentially an optimization to avoid referencing the root rule node.
mozilla::ServoRuleNode rules;
/// The element's computed values if visited, only computed if there's a
/// relevant link for this element. A element's "relevant link" is the
/// element being matched if it is a link or the nearest ancestor link.
mozilla::ServoVisitedStyle visited_style;
// C++ just sees this struct as a bucket of bits, and will
// do the wrong thing if we let it use the default copy ctor/assignment
// operator. Remove them so that there is no footgun.
//
// We remove the move ctor/assignment operator as well, because
// moves in C++ don't prevent destructors from being called,
// which will lead to double frees.
ServoComputedData& operator=(const ServoComputedData&) = delete;
ServoComputedData(const ServoComputedData&) = delete;
ServoComputedData&& operator=(const ServoComputedData&&) = delete;
ServoComputedData(const ServoComputedData&&) = delete;
};
#endif // mozilla_ServoTypes_h

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

@ -81,6 +81,8 @@ EXPORTS.mozilla += [
'ServoBindingList.h',
'ServoBindings.h',
'ServoBindingTypes.h',
'ServoComputedData.h',
'ServoComputedDataInlines.h',
'ServoCounterStyleRule.h',
'ServoCSSParser.h',
'ServoCSSRuleList.h',

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

@ -3716,7 +3716,7 @@ nsStyleDisplay::FinishStyle(
// ImageValue is created, in both Gecko and Stylo. That will
// avoid doing a mutation here.
if (shapeImage->GetType() == eStyleImageType_Image) {
shapeImage->GetImageRequest()->GetImageValue()->SetCORSMode(
shapeImage->ImageRequest()->GetImageValue()->SetCORSMode(
CORSMode::CORS_ANONYMOUS);
}
const nsStyleImage* oldShapeImage =

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

@ -43,6 +43,7 @@ class nsIURI;
class nsTextFrame;
class imgIContainer;
class nsPresContext;
struct nsStyleDisplay;
struct nsStyleVisibility;
namespace mozilla {
class ComputedStyle;
@ -382,7 +383,7 @@ struct nsStyleImage
if (mType == eStyleImageType_Image && !mImage->IsResolved()) {
const nsStyleImageRequest* oldRequest =
(aOldImage && aOldImage->GetType() == eStyleImageType_Image)
? aOldImage->GetImageRequest() : nullptr;
? aOldImage->ImageRequest() : nullptr;
mImage->Resolve(aContext, oldRequest);
}
}
@ -390,20 +391,20 @@ struct nsStyleImage
nsStyleImageType GetType() const {
return mType;
}
nsStyleImageRequest* GetImageRequest() const {
nsStyleImageRequest* ImageRequest() const {
MOZ_ASSERT(mType == eStyleImageType_Image, "Data is not an image!");
MOZ_ASSERT(mImage);
return mImage;
}
imgRequestProxy* GetImageData() const {
return GetImageRequest()->get();
return ImageRequest()->get();
}
nsStyleGradient* GetGradientData() const {
NS_ASSERTION(mType == eStyleImageType_Gradient, "Data is not a gradient!");
return mGradient;
}
bool IsResolved() const {
return mType != eStyleImageType_Image || GetImageRequest()->IsResolved();
return mType != eStyleImageType_Image || ImageRequest()->IsResolved();
}
const nsAtom* GetElementId() const {
NS_ASSERTION(mType == eStyleImageType_Element, "Data is not an element!");
@ -2685,15 +2686,16 @@ public:
return mContent.mCounters;
}
nsStyleImageRequest* GetImageRequest() const
nsStyleImageRequest* ImageRequest() const
{
MOZ_ASSERT(mType == eStyleContentType_Image);
MOZ_ASSERT(mContent.mImage);
return mContent.mImage;
}
imgRequestProxy* GetImage() const
{
return GetImageRequest()->get();
return ImageRequest()->get();
}
void SetKeyword(nsStyleContentType aType)

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

@ -22,6 +22,7 @@ from mozbuild.base import MachCommandConditions
from mozbuild.frontend.emitter import TreeMetadataEmitter
from mozbuild.frontend.reader import BuildReader
from mozbuild.mozinfo import write_mozinfo
from mozbuild.util import FileAvoidWrite
from itertools import chain
from mozbuild.backend import (
@ -114,10 +115,8 @@ def config_status(topobjdir='.', topsrcdir='.', defines=None,
non_global_defines=non_global_defines, substs=substs,
source=source, mozconfig=mozconfig)
# mozinfo.json only needs written if configure changes and configure always
# passes this environment variable.
if 'WRITE_MOZINFO' in os.environ:
write_mozinfo(os.path.join(topobjdir, 'mozinfo.json'), env, os.environ)
with FileAvoidWrite(os.path.join(topobjdir, 'mozinfo.json')) as f:
write_mozinfo(f, env, os.environ)
cpu_start = time.clock()
time_start = time.time()

4
security/sandbox/moz.build Normal file → Executable file
Просмотреть файл

@ -156,9 +156,11 @@ elif CONFIG['OS_ARCH'] == 'WINNT':
'chromium/sandbox/win/src/service_resolver_32.cc',
]
for var in ('UNICODE', '_UNICODE', 'NS_NO_XPCOM', 'SANDBOX_EXPORTS',
for var in ('UNICODE', '_UNICODE', 'NS_NO_XPCOM',
'_CRT_RAND_S', 'CHROMIUM_SANDBOX_BUILD'):
DEFINES[var] = True
if CONFIG['CC_TYPE'] != 'gcc':
DEFINES['SANDBOX_EXPORTS'] = True
LOCAL_INCLUDES += ['/security/sandbox/chromium-shim']
LOCAL_INCLUDES += ['/security/sandbox/chromium']

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

@ -426,10 +426,10 @@ impl nsStyleImage {
}
}
unsafe fn get_image_url(self: &nsStyleImage) -> ComputedImageUrl {
let url_value = bindings::Gecko_GetURLValue(self);
ComputedImageUrl::from_url_value_data(url_value.as_ref().unwrap())
.expect("Could not convert to ComputedUrl")
unsafe fn get_image_url(&self) -> ComputedImageUrl {
let image_request = bindings::Gecko_GetImageRequest(self)
.as_ref().expect("Null image request?");
ComputedImageUrl::from_image_request(image_request)
}
unsafe fn get_gradient(self: &nsStyleImage) -> Box<Gradient> {
@ -634,6 +634,7 @@ pub mod basic_shape {
use gecko_bindings::structs::{StyleGeometryBox, StyleShapeSource, StyleShapeSourceType};
use gecko_bindings::structs::{nsStyleCoord, nsStyleCorners};
use gecko_bindings::sugar::ns_style_coord::{CoordDataMut, CoordDataValue};
use gecko_bindings::sugar::refptr::RefPtr;
use std::borrow::Borrow;
use values::computed::basic_shape::{BasicShape, ClippingShape, FloatAreaShape, ShapeRadius};
use values::computed::border::{BorderCornerRadius, BorderRadius};
@ -678,8 +679,8 @@ pub mod basic_shape {
match other.mType {
StyleShapeSourceType::URL => unsafe {
let shape_image = &*other.mShapeImage.mPtr;
let other_url = &(**shape_image.__bindgen_anon_1.mURLValue.as_ref());
let url = ComputedUrl::from_url_value_data(&other_url._base).unwrap();
let other_url = RefPtr::new(*shape_image.__bindgen_anon_1.mURLValue.as_ref());
let url = ComputedUrl::from_url_value(other_url);
ShapeSource::ImageOrUrl(url)
},
StyleShapeSourceType::Image => {

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

@ -38,16 +38,11 @@ pub struct CssUrl {
impl CssUrl {
/// Try to parse a URL from a string value that is a valid CSS token for a
/// URL.
///
/// Returns `Err` in the case that extra_data is incomplete.
pub fn parse_from_string<'a>(
url: String,
context: &ParserContext,
) -> Result<Self, ParseError<'a>> {
Ok(CssUrl {
pub fn parse_from_string(url: String, context: &ParserContext) -> Self {
CssUrl {
serialization: Arc::new(url),
extra_data: context.url_data.clone(),
})
}
}
/// Returns true if the URL is definitely invalid. We don't eagerly resolve
@ -58,13 +53,13 @@ impl CssUrl {
}
/// Convert from URLValueData to SpecifiedUrl.
unsafe fn from_url_value_data(url: &URLValueData) -> Result<Self, ()> {
unsafe fn from_url_value_data(url: &URLValueData) -> Self {
let arc_type =
&url.mString as *const _ as *const RawOffsetArc<String>;
Ok(CssUrl {
CssUrl {
serialization: Arc::from_raw_offset((*arc_type).clone()),
extra_data: url.mExtraData.to_safe(),
})
}
}
/// Returns true if this URL looks like a fragment.
@ -104,7 +99,7 @@ impl Parse for CssUrl {
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
let url = input.expect_url()?;
Self::parse_from_string(url.as_ref().to_owned(), context)
Ok(Self::parse_from_string(url.as_ref().to_owned(), context))
}
}
@ -188,11 +183,8 @@ pub struct SpecifiedImageUrl {
impl SpecifiedImageUrl {
/// Parse a URL from a string value. See SpecifiedUrl::parse_from_string.
pub fn parse_from_string<'a>(
url: String,
context: &ParserContext,
) -> Result<Self, ParseError<'a>> {
CssUrl::parse_from_string(url, context).map(Self::from_css_url)
pub fn parse_from_string(url: String, context: &ParserContext) -> Self {
Self::from_css_url(CssUrl::parse_from_string(url, context))
}
fn from_css_url(url: CssUrl) -> Self {
@ -295,11 +287,10 @@ impl ToCss for ComputedUrl {
}
impl ComputedUrl {
/// Convert from URLValueData to ComputedUrl.
pub unsafe fn from_url_value_data(url: &URLValueData) -> Result<Self, ()> {
Ok(ComputedUrl(
SpecifiedUrl::from_css_url(CssUrl::from_url_value_data(url)?)
))
/// Convert from RefPtr<URLValue> to ComputedUrl.
pub unsafe fn from_url_value(url_value: RefPtr<URLValue>) -> Self {
let url = CssUrl::from_url_value_data(&url_value._base);
ComputedUrl(SpecifiedUrl { url, url_value })
}
}
@ -317,21 +308,10 @@ impl ToCss for ComputedImageUrl {
}
impl ComputedImageUrl {
/// Convert from URLValueData to SpecifiedUrl.
pub unsafe fn from_url_value_data(url: &URLValueData) -> Result<Self, ()> {
Ok(ComputedImageUrl(
SpecifiedImageUrl::from_css_url(CssUrl::from_url_value_data(url)?)
))
}
/// Convert from nsStyleImageReques to ComputedImageUrl.
pub unsafe fn from_image_request(image_request: &nsStyleImageRequest) -> Result<Self, ()> {
if image_request.mImageValue.mRawPtr.is_null() {
return Err(());
}
let image_value = image_request.mImageValue.mRawPtr.as_ref().unwrap();
let url_value_data = &image_value._base;
Self::from_url_value_data(url_value_data)
pub unsafe fn from_image_request(image_request: &nsStyleImageRequest) -> Self {
let image_value = image_request.mImageValue.to_safe();
let url = CssUrl::from_url_value_data(&image_value._base);
ComputedImageUrl(SpecifiedImageUrl { url, image_value })
}
}

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

@ -43,6 +43,7 @@ use gecko_bindings::structs::mozilla::CSSPseudoElementType;
use gecko_bindings::structs::mozilla::CSSPseudoElementType_InheritingAnonBox;
use gecko_bindings::structs::root::NS_STYLE_CONTEXT_TYPE_SHIFT;
use gecko_bindings::sugar::ns_style_coord::{CoordDataValue, CoordData, CoordDataMut};
use gecko_bindings::sugar::refptr::RefPtr;
use gecko::values::convert_nscolor_to_rgba;
use gecko::values::convert_rgba_to_nscolor;
use gecko::values::GeckoStyleCoordConvertible;
@ -758,13 +759,10 @@ def set_gecko_property(ffi_name, expr):
nsStyleSVGPaintType::eStyleSVGPaintType_ContextFill => SVGPaintKind::ContextFill,
nsStyleSVGPaintType::eStyleSVGPaintType_ContextStroke => SVGPaintKind::ContextStroke,
nsStyleSVGPaintType::eStyleSVGPaintType_Server => {
unsafe {
SVGPaintKind::PaintServer(
ComputedUrl::from_url_value_data(
&(**paint.mPaint.mPaintServer.as_ref())._base
).unwrap()
)
}
SVGPaintKind::PaintServer(unsafe {
let url = RefPtr::new(*paint.mPaint.mPaintServer.as_ref());
ComputedUrl::from_url_value(url)
})
}
nsStyleSVGPaintType::eStyleSVGPaintType_Color => {
unsafe { SVGPaintKind::Color(convert_nscolor_to_rgba(*paint.mPaint.mColor.as_ref())) }
@ -967,13 +965,9 @@ def set_gecko_property(ffi_name, expr):
return UrlOrNone::none()
}
unsafe {
let gecko_url_value = &*self.gecko.${gecko_ffi_name}.mRawPtr;
UrlOrNone::Url(
ComputedUrl::from_url_value_data(&gecko_url_value._base)
.expect("${gecko_ffi_name} could not convert to ComputedUrl")
)
}
UrlOrNone::Url(unsafe {
ComputedUrl::from_url_value(self.gecko.${gecko_ffi_name}.to_safe())
})
}
</%def>
@ -4146,9 +4140,7 @@ fn static_assert() {
unsafe {
let ref gecko_image_request = *self.gecko.mListStyleImage.mRawPtr;
UrlOrNone::Url(ComputedImageUrl::from_image_request(
gecko_image_request
).expect("mListStyleImage could not convert to ComputedImageUrl"))
UrlOrNone::Url(ComputedImageUrl::from_image_request(gecko_image_request))
}
}
@ -4553,11 +4545,10 @@ fn static_assert() {
});
},
NS_STYLE_FILTER_URL => {
filters.push(unsafe {
Filter::Url(
ComputedUrl::from_url_value_data(&(**filter.__bindgen_anon_1.mURL.as_ref())._base).unwrap()
)
});
filters.push(Filter::Url(unsafe {
let url = RefPtr::new(*filter.__bindgen_anon_1.mURL.as_ref());
ComputedUrl::from_url_value(url)
}));
}
_ => {},
}
@ -5438,7 +5429,6 @@ clip-path
let url = unsafe {
let gecko_image_request = gecko_cursor_image.mImage.mRawPtr.as_ref().unwrap();
ComputedImageUrl::from_image_request(&gecko_image_request)
.expect("mCursorImages.mImage could not convert to ComputedImageUrl")
};
let hotspot =
@ -5714,7 +5704,6 @@ clip-path
&**gecko_content.mContent.mImage.as_ref();
ContentItem::Url(
ComputedImageUrl::from_image_request(gecko_image_request)
.expect("mContent could not convert to ComputedImageUrl")
)
}
},

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

@ -40,18 +40,14 @@ pub struct CssUrl {
impl CssUrl {
/// Try to parse a URL from a string value that is a valid CSS token for a
/// URL. Never fails - the API is only fallible to be compatible with the
/// gecko version.
pub fn parse_from_string<'a>(
url: String,
context: &ParserContext,
) -> Result<Self, ParseError<'a>> {
/// URL.
pub fn parse_from_string(url: String, context: &ParserContext) -> Self {
let serialization = Arc::new(url);
let resolved = context.url_data.join(&serialization).ok();
Ok(CssUrl {
CssUrl {
original: Some(serialization),
resolved: resolved,
})
}
}
/// Returns true if the URL is definitely invalid. For Servo URLs, we can
@ -110,7 +106,7 @@ impl Parse for CssUrl {
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
let url = input.expect_url()?;
Self::parse_from_string(url.as_ref().to_owned(), context)
Ok(Self::parse_from_string(url.as_ref().to_owned(), context))
}
}

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

@ -158,7 +158,7 @@ impl<'a, 'i, R: ParseErrorReporter> AtRuleParser<'i> for TopLevelRuleParser<'a,
}
let url_string = input.expect_url_or_string()?.as_ref().to_owned();
let url = CssUrl::parse_from_string(url_string, &self.context)?;
let url = CssUrl::parse_from_string(url_string, &self.context);
let media = parse_media_query_list(&self.context, input,
self.error_context.error_reporter);

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

@ -990,7 +990,7 @@ impl Parse for MozImageRect {
input.try(|i| i.expect_function_matching("-moz-image-rect"))?;
input.parse_nested_block(|i| {
let string = i.expect_url_or_string()?;
let url = SpecifiedImageUrl::parse_from_string(string.as_ref().to_owned(), context)?;
let url = SpecifiedImageUrl::parse_from_string(string.as_ref().to_owned(), context);
i.expect_comma()?;
let top = NumberOrPercentage::parse_non_negative(context, i)?;
i.expect_comma()?;

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

@ -4171,14 +4171,13 @@ pub extern "C" fn Servo_DeclarationBlock_SetBackgroundImage(
ParsingMode::DEFAULT,
QuirksMode::NoQuirks,
);
if let Ok(url) = SpecifiedImageUrl::parse_from_string(string.into(), &context) {
let decl = PropertyDeclaration::BackgroundImage(BackgroundImage(
vec![Either::Second(Image::Url(url))]
));
write_locked_arc(declarations, |decls: &mut PropertyDeclarationBlock| {
decls.push(decl, Importance::Normal, DeclarationSource::CssOm);
})
}
let url = SpecifiedImageUrl::parse_from_string(string.into(), &context);
let decl = PropertyDeclaration::BackgroundImage(BackgroundImage(
vec![Either::Second(Image::Url(url))]
));
write_locked_arc(declarations, |decls: &mut PropertyDeclarationBlock| {
decls.push(decl, Importance::Normal, DeclarationSource::CssOm);
});
}
#[no_mangle]

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

@ -613954,7 +613954,7 @@
"testharness"
],
"webrtc/RTCPeerConnection-createOffer.html": [
"5b3d38072afd9bbb3e95925c3959ff3f4268a347",
"eb493db4cc91a26bda40cef0583deae9b56390e2",
"testharness"
],
"webrtc/RTCPeerConnection-generateCertificate.html": [
@ -613978,7 +613978,7 @@
"testharness"
],
"webrtc/RTCPeerConnection-helper.js": [
"d579dd68118d72c06455d8ccdbeb666f8f39c58a",
"5bde36117c593d989be1d2d0556580c876e6fc73",
"support"
],
"webrtc/RTCPeerConnection-iceConnectionState.html": [
@ -614014,35 +614014,35 @@
"testharness"
],
"webrtc/RTCPeerConnection-setLocalDescription-answer.html": [
"e215aa042c67a23ae776b83d662a035a22e03810",
"0e1ccd318b00a062e0715fff1f23aee41f9e2f93",
"testharness"
],
"webrtc/RTCPeerConnection-setLocalDescription-offer.html": [
"117fc91599d11b63f2d232a63bace8e367dbb72a",
"0ac2372763bbe290e91232a4bdcbe1390eb70a61",
"testharness"
],
"webrtc/RTCPeerConnection-setLocalDescription-pranswer.html": [
"9653d2176c51b638b0c03dec363d2a2fb8386281",
"2640311073b9eac8713e48bbdbad81cb2955d8b7",
"testharness"
],
"webrtc/RTCPeerConnection-setLocalDescription-rollback.html": [
"293081a9ebd031cc4919a01ec323630394d401a8",
"c09a060a0323af3e59fc54b40ff7afc29d95fb40",
"testharness"
],
"webrtc/RTCPeerConnection-setLocalDescription.html": [
"b4cac26716f01ff80c902d3536dc0d2de6d85388",
"74011901cbedc4398d9594f6ff5c7b911a898c04",
"testharness"
],
"webrtc/RTCPeerConnection-setRemoteDescription-answer.html": [
"3f85858a7afe6a5346b2d47f5505d25caef2668b",
"a38de5d34ec38b3326550de76e43fd948df53d4d",
"testharness"
],
"webrtc/RTCPeerConnection-setRemoteDescription-offer.html": [
"34337ef2126bfe276675db8884cd2a9aaa2d4432",
"41fda938d9013b8f3bb552c646134694965002b6",
"testharness"
],
"webrtc/RTCPeerConnection-setRemoteDescription-pranswer.html": [
"6ddea8760cbacc775ee99aa700fd71883cfb9bd7",
"685dfa2463c63b40c779ce6a22105337a1eb51b4",
"testharness"
],
"webrtc/RTCPeerConnection-setRemoteDescription-replaceTrack.https.html": [
@ -614050,7 +614050,7 @@
"testharness"
],
"webrtc/RTCPeerConnection-setRemoteDescription-rollback.html": [
"6142a9b3b95bb26634af5300bc24981f2b4cb2a4",
"6614b5b0febd718a94bbec110568b9aaf80dc9eb",
"testharness"
],
"webrtc/RTCPeerConnection-setRemoteDescription-tracks.https.html": [
@ -614058,7 +614058,7 @@
"testharness"
],
"webrtc/RTCPeerConnection-setRemoteDescription.html": [
"2a2e3f9ff0a5912fa260d7124f7f5a9c3862c533",
"59f826d4d23cd52f15f3940cc3abe66933e91037",
"testharness"
],
"webrtc/RTCPeerConnection-track-stats.https.html": [

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

@ -1,4 +1,4 @@
[collections.py]
[test_arguments]
bug: 1453057
expected: FAIL

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

@ -1,42 +1,3 @@
[RTCPeerConnection-setRemoteDescription.html]
expected: TIMEOUT
[Malformed SDP description should be rejected with RTCError]
expected: FAIL
[SDP type that is invalid for current signaling state should be rejected with InvalidStateError]
expected: FAIL
[setRemoteDescription with valid offer should succeed]
expected: FAIL
[Setting remote description multiple times with different offer should succeed]
expected: FAIL
[setRemoteDescription(offer) should never resolve if connection is closed in parallel]
disabled: unstable
expected: FAIL
[setRemoteDescription(offer) with invalid SDP should reject with RTCError]
expected: FAIL
[setRemoteDescription() with valid state and answer should succeed]
expected: FAIL
[Switching role from offerer to answerer after going back to stable state should succeed]
expected: FAIL
[Calling setRemoteDescription(answer) from stable state should reject with InvalidStateError]
expected: FAIL
[Calling setRemoteDescription(offer) from have-local-offer state should reject with InvalidStateError]
expected: FAIL
[Calling setRemoteDescription(answer) from have-remote-offer state should reject with InvalidStateError]
expected: FAIL
[setRemoteDescription should trigger ontrack event when the MSID of the stream is is parsed.]
expected: FAIL
[Test onsignalingstatechange event for Switching role from offerer to answerer after going back to stable state should succeed]
expected: TIMEOUT

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

@ -1054,7 +1054,7 @@
"support"
],
"binast/large.https.html": [
"3b27ede3f0666df43f752d8022c1e72d87f5b64f",
"35b870a066dc31ecab2f0de8fb38a6d54345f332",
"testharness"
],
"binast/large.js": [
@ -1070,7 +1070,7 @@
"support"
],
"binast/small.https.html": [
"01ecd5cf1b3e7e5fa7bc53960d9defb80eb3eef7",
"aedfb37a31775d878fc64237656cdb956331fb86",
"testharness"
],
"binast/small.js": [

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

@ -16,7 +16,7 @@
// countAudioLine()
// countVideoLine()
// test_state_change_event()
// assert_session_desc_equals()
// assert_session_desc_similar()
/*
* 4.3.2. createOffer()
@ -50,8 +50,8 @@
pc.setLocalDescription(offer)
.then(() => {
assert_equals(pc.signalingState, 'have-local-offer');
assert_session_desc_equals(pc.localDescription, offer);
assert_session_desc_equals(pc.pendingLocalDescription, offer);
assert_session_desc_similar(pc.localDescription, offer);
assert_session_desc_similar(pc.pendingLocalDescription, offer);
assert_equals(pc.currentLocalDescription, null);
}));
}, 'createOffer() and then setLocalDescription() should succeed');

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

@ -93,12 +93,12 @@ function isSimilarSessionDescription(sessionDesc1, sessionDesc2) {
}
}
function assert_session_desc_equals(sessionDesc1, sessionDesc2) {
function assert_session_desc_similar(sessionDesc1, sessionDesc2) {
assert_true(isSimilarSessionDescription(sessionDesc1, sessionDesc2),
'Expect both session descriptions to have the same count of media lines');
}
function assert_session_desc_not_equals(sessionDesc1, sessionDesc2) {
function assert_session_desc_not_similar(sessionDesc1, sessionDesc2) {
assert_false(isSimilarSessionDescription(sessionDesc1, sessionDesc2),
'Expect both session descriptions to have different count of media lines');
}

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

@ -13,7 +13,7 @@
// The following helper functions are called from RTCPeerConnection-helper.js:
// generateOffer
// generateAnswer
// assert_session_desc_equals
// assert_session_desc_similar
// test_state_change_event
/*
@ -71,11 +71,11 @@
pc.setLocalDescription(answer)
.then(() => {
assert_equals(pc.signalingState, 'stable');
assert_session_desc_equals(pc.localDescription, answer);
assert_session_desc_equals(pc.remoteDescription, offer);
assert_session_desc_similar(pc.localDescription, answer);
assert_session_desc_similar(pc.remoteDescription, offer);
assert_session_desc_equals(pc.currentLocalDescription, answer);
assert_session_desc_equals(pc.currentRemoteDescription, offer);
assert_session_desc_similar(pc.currentLocalDescription, answer);
assert_session_desc_similar(pc.currentRemoteDescription, offer);
assert_equals(pc.pendingLocalDescription, null);
assert_equals(pc.pendingRemoteDescription, null);
@ -99,11 +99,11 @@
pc.setLocalDescription({ type: 'answer' })
.then(() => {
assert_equals(pc.signalingState, 'stable');
assert_session_desc_equals(pc.localDescription, answer);
assert_session_desc_equals(pc.remoteDescription, offer);
assert_session_desc_similar(pc.localDescription, answer);
assert_session_desc_similar(pc.remoteDescription, offer);
assert_session_desc_equals(pc.currentLocalDescription, answer);
assert_session_desc_equals(pc.currentRemoteDescription, offer);
assert_session_desc_similar(pc.currentLocalDescription, answer);
assert_session_desc_similar(pc.currentRemoteDescription, offer);
assert_equals(pc.pendingLocalDescription, null);
assert_equals(pc.pendingRemoteDescription, null);

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

@ -12,8 +12,8 @@
// The following helper functions are called from RTCPeerConnection-helper.js:
// generateOffer
// assert_session_desc_not_equals
// assert_session_desc_equals
// assert_session_desc_not_similar
// assert_session_desc_similar
// test_state_change_event
/*
@ -65,8 +65,8 @@
pc.setLocalDescription(offer)
.then(() => {
assert_equals(pc.signalingState, 'have-local-offer');
assert_session_desc_equals(pc.localDescription, offer);
assert_session_desc_equals(pc.pendingLocalDescription, offer);
assert_session_desc_similar(pc.localDescription, offer);
assert_session_desc_similar(pc.pendingLocalDescription, offer);
assert_equals(pc.currentLocalDescription, null);
}));
}, 'setLocalDescription with valid offer should succeed');
@ -84,8 +84,8 @@
pc.setLocalDescription({ type: 'offer' })
.then(() => {
assert_equals(pc.signalingState, 'have-local-offer');
assert_session_desc_equals(pc.localDescription, offer);
assert_session_desc_equals(pc.pendingLocalDescription, offer);
assert_session_desc_similar(pc.localDescription, offer);
assert_session_desc_similar(pc.pendingLocalDescription, offer);
assert_equals(pc.currentLocalDescription, null);
}));
}, 'setLocalDescription with type offer and null sdp should use lastOffer generated from createOffer');
@ -117,7 +117,7 @@
.then(offer1 =>
pc.createOffer({ offerToReceiveVideo: true })
.then(offer2 => {
assert_session_desc_not_equals(offer1, offer2);
assert_session_desc_not_similar(offer1, offer2);
return promise_rejects(t, 'InvalidModificationError',
pc.setLocalDescription(offer1));
}));
@ -137,10 +137,10 @@
.then(offer2 =>
pc.setLocalDescription(offer2)
.then(offer2 => {
assert_session_desc_not_equals(offer1, offer2);
assert_session_desc_not_similar(offer1, offer2);
assert_equals(pc.signalingState, 'have-local-offer');
assert_session_desc_equals(pc.localDescription, offer2);
assert_session_desc_equals(pc.pendingLocalDescription, offer2);
assert_session_desc_similar(pc.localDescription, offer2);
assert_session_desc_similar(pc.pendingLocalDescription, offer2);
assert_equals(pc.currentLocalDescription, null);
}))));
}, 'Creating and setting offer multiple times should succeed');

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

@ -13,7 +13,7 @@
// The following helper functions are called from RTCPeerConnection-helper.js:
// generateOffer
// generateAnswer
// assert_session_desc_equals
// assert_session_desc_similar
// test_state_change_event
/*
@ -94,12 +94,12 @@
.then(() => {
assert_equals(pc.signalingState, 'have-local-pranswer');
assert_session_desc_equals(pc.remoteDescription, offer);
assert_session_desc_equals(pc.pendingRemoteDescription, offer);
assert_session_desc_similar(pc.remoteDescription, offer);
assert_session_desc_similar(pc.pendingRemoteDescription, offer);
assert_equals(pc.currentRemoteDescription, null);
assert_session_desc_equals(pc.localDescription, pranswer);
assert_session_desc_equals(pc.pendingLocalDescription, pranswer);
assert_session_desc_similar(pc.localDescription, pranswer);
assert_session_desc_similar(pc.pendingLocalDescription, pranswer);
assert_equals(pc.currentLocalDescription, null);
assert_equals(pc.pendingRemoteDescription, null);
@ -138,11 +138,11 @@
.then(() => pc.setLocalDescription(answer))
.then(() => {
assert_equals(pc.signalingState, 'stable');
assert_session_desc_equals(pc.localDescription, answer);
assert_session_desc_equals(pc.remoteDescription, offer);
assert_session_desc_similar(pc.localDescription, answer);
assert_session_desc_similar(pc.remoteDescription, offer);
assert_session_desc_equals(pc.currentLocalDescription, answer);
assert_session_desc_equals(pc.currentRemoteDescription, offer);
assert_session_desc_similar(pc.currentLocalDescription, answer);
assert_session_desc_similar(pc.currentRemoteDescription, offer);
assert_equals(pc.pendingLocalDescription, null);
assert_equals(pc.pendingRemoteDescription, null);

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

@ -11,7 +11,7 @@
// https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html
// The following helper functions are called from RTCPeerConnection-helper.js:
// assert_session_desc_equals
// assert_session_desc_similar
// test_state_change_event
/*

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

@ -12,8 +12,8 @@
// The following helper functions are called from RTCPeerConnection-helper.js:
// generateOffer
// assert_session_desc_not_equals
// assert_session_desc_equals
// assert_session_desc_not_similar
// assert_session_desc_similar
// test_state_change_event
/*
@ -61,10 +61,10 @@
pc.setLocalDescription(offer2)
.then(() => {
assert_equals(pc.signalingState, 'have-local-offer');
assert_session_desc_not_equals(offer1, offer2);
assert_session_desc_equals(pc.localDescription, offer2);
assert_session_desc_equals(pc.currentLocalDescription, offer1);
assert_session_desc_equals(pc.pendingLocalDescription, offer2);
assert_session_desc_not_similar(offer1, offer2);
assert_session_desc_similar(pc.localDescription, offer2);
assert_session_desc_similar(pc.currentLocalDescription, offer1);
assert_session_desc_similar(pc.pendingLocalDescription, offer2);
})));
}, 'Calling createOffer() and setLocalDescription() again after one round of local-offer/remote-answer should succeed');
@ -83,9 +83,9 @@
pc.setLocalDescription(offer)
.then(() => {
assert_equals(pc.signalingState, 'have-local-offer');
assert_session_desc_equals(pc.localDescription, offer);
assert_session_desc_equals(pc.currentLocalDescription, answer);
assert_session_desc_equals(pc.pendingLocalDescription, offer);
assert_session_desc_similar(pc.localDescription, offer);
assert_session_desc_similar(pc.currentLocalDescription, answer);
assert_session_desc_similar(pc.pendingLocalDescription, offer);
})));
}, 'Switching role from answerer to offerer after going back to stable state should succeed');

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

@ -13,7 +13,7 @@
// The following helper functions are called from RTCPeerConnection-helper.js:
// generateOffer()
// generateAnswer()
// assert_session_desc_equals()
// assert_session_desc_similar()
// test_state_change_event()
/*
@ -71,11 +71,11 @@
.then(() => {
assert_equals(pc.signalingState, 'stable');
assert_session_desc_equals(pc.localDescription, offer);
assert_session_desc_equals(pc.remoteDescription, answer);
assert_session_desc_similar(pc.localDescription, offer);
assert_session_desc_similar(pc.remoteDescription, answer);
assert_session_desc_equals(pc.currentLocalDescription, offer);
assert_session_desc_equals(pc.currentRemoteDescription, answer);
assert_session_desc_similar(pc.currentLocalDescription, offer);
assert_session_desc_similar(pc.currentRemoteDescription, answer);
assert_equals(pc.pendingLocalDescription, null);
assert_equals(pc.pendingRemoteDescription, null);

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

@ -11,7 +11,7 @@
// https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html
// The following helper functions are called from RTCPeerConnection-helper.js:
// assert_session_desc_equals()
// assert_session_desc_similar()
// test_state_change_event()
/*
@ -63,8 +63,8 @@
return pc2.setRemoteDescription(offer)
.then(() => {
assert_equals(pc2.signalingState, 'have-remote-offer');
assert_session_desc_equals(pc2.remoteDescription, offer);
assert_session_desc_equals(pc2.pendingRemoteDescription, offer);
assert_session_desc_similar(pc2.remoteDescription, offer);
assert_session_desc_similar(pc2.pendingRemoteDescription, offer);
assert_equals(pc2.currentRemoteDescription, null);
});
});
@ -85,8 +85,8 @@
.then(() => pc2.setRemoteDescription(offer))
.then(() => {
assert_equals(pc2.signalingState, 'have-remote-offer');
assert_session_desc_equals(pc2.remoteDescription, offer);
assert_session_desc_equals(pc2.pendingRemoteDescription, offer);
assert_session_desc_similar(pc2.remoteDescription, offer);
assert_session_desc_similar(pc2.pendingRemoteDescription, offer);
assert_equals(pc2.currentRemoteDescription, null);
});
});
@ -107,14 +107,14 @@
.then(()=> {
return pc1.createOffer({ offerToReceiveAudio: true })
.then(offer2 => {
assert_session_desc_not_equals(offer1, offer2);
assert_session_desc_not_similar(offer1, offer2);
return pc2.setRemoteDescription(offer1)
.then(() => pc2.setRemoteDescription(offer2))
.then(() => {
assert_equals(pc2.signalingState, 'have-remote-offer');
assert_session_desc_equals(pc2.remoteDescription, offer2);
assert_session_desc_equals(pc2.pendingRemoteDescription, offer2);
assert_session_desc_similar(pc2.remoteDescription, offer2);
assert_session_desc_similar(pc2.pendingRemoteDescription, offer2);
assert_equals(pc2.currentRemoteDescription, null);
});
});

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

@ -13,7 +13,7 @@
// The following helper functions are called from RTCPeerConnection-helper.js:
// generateOffer
// generateAnswer
// assert_session_desc_equals
// assert_session_desc_similar
// test_state_change_event
/*
@ -93,12 +93,12 @@
.then(() => {
assert_equals(pc.signalingState, 'have-remote-pranswer');
assert_session_desc_equals(pc.localDescription, offer);
assert_session_desc_equals(pc.pendingLocalDescription, offer);
assert_session_desc_similar(pc.localDescription, offer);
assert_session_desc_similar(pc.pendingLocalDescription, offer);
assert_equals(pc.currentLocalDescription, null);
assert_session_desc_equals(pc.remoteDescription, pranswer);
assert_session_desc_equals(pc.pendingRemoteDescription, pranswer);
assert_session_desc_similar(pc.remoteDescription, pranswer);
assert_session_desc_similar(pc.pendingRemoteDescription, pranswer);
assert_equals(pc.currentRemoteDescription, null);
});
}));
@ -136,12 +136,12 @@
.then(() => {
assert_equals(pc.signalingState, 'stable');
assert_session_desc_equals(pc.localDescription, offer);
assert_session_desc_equals(pc.currentLocalDescription, offer);
assert_session_desc_similar(pc.localDescription, offer);
assert_session_desc_similar(pc.currentLocalDescription, offer);
assert_equals(pc.pendingLocalDescription, null);
assert_session_desc_equals(pc.remoteDescription, answer);
assert_session_desc_equals(pc.currentRemoteDescription, answer);
assert_session_desc_similar(pc.remoteDescription, answer);
assert_session_desc_similar(pc.currentRemoteDescription, answer);
assert_equals(pc.pendingRemoteDescription, null);
});
}));

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

@ -12,7 +12,7 @@
// The following helper functions are called from RTCPeerConnection-helper.js:
// generateOffer
// assert_session_desc_equals
// assert_session_desc_similar
// test_state_change_event
/*

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

@ -11,11 +11,8 @@
// https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html
// The following helper functions are called from RTCPeerConnection-helper.js:
// generateOffer()
// generateAnswer()
// assert_session_desc_not_equals()
// assert_session_desc_equals()
// test_state_change_event()
// assert_session_desc_not_similar()
// assert_session_desc_similar()
/*
4.3.2. Interface Definition
@ -48,76 +45,101 @@
/*
4.6.1. enum RTCSdpType
*/
promise_test(t => {
promise_test(async t => {
const pc = new RTCPeerConnection();
t.add_cleanup(() => pc.close());
// SDP is validated after WebIDL validation
return promise_rejects(t, new TypeError(),
pc.setRemoteDescription({
type: 'bogus',
sdp: 'bogus'
}));
try {
await pc.setRemoteDescription({ type: 'bogus', sdp: 'bogus' });
t.unreached_func("Should have rejected.");
} catch (e) {
assert_throws(new TypeError(), () => { throw e });
}
}, 'setRemoteDescription with invalid type and invalid SDP should reject with TypeError');
promise_test(t => {
promise_test(async t => {
const pc = new RTCPeerConnection();
t.add_cleanup(() => pc.close());
// SDP is validated after validating type
return promise_rejects(t, 'InvalidStateError',
pc.setRemoteDescription({
type: 'answer',
sdp: 'invalid'
}));
try {
await pc.setRemoteDescription({ type: 'answer', sdp: 'invalid' });
t.unreached_func("Should have rejected.");
} catch (e) {
assert_throws('InvalidStateError', () => { throw e });
}
}, 'setRemoteDescription() with invalid SDP and stable state should reject with InvalidStateError');
/* Dedicated signalingstate events test. */
promise_test(async t => {
const pc = new RTCPeerConnection();
const pc2 = new RTCPeerConnection();
t.add_cleanup(() => pc.close());
t.add_cleanup(() => pc2.close());
let eventCount = 0;
const states = [
'stable', 'have-local-offer', 'stable', 'have-remote-offer', 'closed'
];
pc.onsignalingstatechange = () =>
assert_equals(pc.signalingState, states[++eventCount]);
const assert_state = state => {
assert_equals(state, pc.signalingState);
assert_equals(state, states[eventCount]);
};
const offer = await pc.createOffer({ offerToReceiveAudio: true });
assert_state('stable');
await pc.setLocalDescription(offer);
assert_state('have-local-offer');
await pc2.setRemoteDescription(offer);
await pc2.setLocalDescription(await pc2.createAnswer());
await pc.setRemoteDescription(pc2.localDescription);
assert_state('stable');
await pc.setRemoteDescription(await pc2.createOffer());
assert_state('have-remote-offer');
pc.close();
assert_state('closed');
}, 'Negotiation should fire signalingsstate events');
/* Operations after returning to stable state */
promise_test(t => {
promise_test(async t => {
const pc = new RTCPeerConnection();
const pc2 = new RTCPeerConnection();
t.add_cleanup(() => pc.close());
t.add_cleanup(() => pc2.close());
test_state_change_event(t, pc,
['have-remote-offer', 'stable', 'have-remote-offer']);
return pc2.createOffer({ offerToReceiveAudio: true })
.then(offer1 =>
pc.setRemoteDescription(offer1)
.then(() => pc.createAnswer())
.then(answer => pc.setLocalDescription(answer))
.then(() => pc2.createOffer({ offerToReceiveVideo: true }))
.then(offer2 => {
return pc.setRemoteDescription(offer2)
.then(() => {
assert_equals(pc.signalingState, 'have-remote-offer');
assert_session_desc_not_equals(offer1, offer2);
assert_session_desc_equals(pc.remoteDescription, offer2);
assert_session_desc_equals(pc.currentRemoteDescription, offer1);
assert_session_desc_equals(pc.pendingRemoteDescription, offer2);
});
}));
const offer1 = await pc2.createOffer({ offerToReceiveAudio: true });
await pc.setRemoteDescription(offer1);
await pc.setLocalDescription(await pc.createAnswer());
const offer2 = await pc2.createOffer({ offerToReceiveVideo: true });
await pc.setRemoteDescription(offer2);
assert_session_desc_not_similar(offer1, offer2);
assert_session_desc_similar(pc.remoteDescription, offer2);
assert_session_desc_similar(pc.currentRemoteDescription, offer1);
assert_session_desc_similar(pc.pendingRemoteDescription, offer2);
}, 'Calling setRemoteDescription() again after one round of remote-offer/local-answer should succeed');
promise_test(t => {
promise_test(async t => {
const pc = new RTCPeerConnection();
const pc2 = new RTCPeerConnection();
t.add_cleanup(() => pc.close());
t.add_cleanup(() => pc2.close());
test_state_change_event(t, pc,
['have-local-offer', 'stable', 'have-remote-offer']);
return pc.createOffer({ offerToReceiveAudio: true })
.then(offer =>
pc.setLocalDescription(offer)
.then(() => generateAnswer(offer)))
.then(answer =>
pc.setRemoteDescription(answer)
.then(() => generateOffer({ pc, data: true }))
.then(offer =>
pc.setRemoteDescription(offer)
.then(() => {
assert_equals(pc.signalingState, 'have-remote-offer');
assert_session_desc_equals(pc.remoteDescription, offer);
assert_session_desc_equals(pc.currentRemoteDescription, answer);
assert_session_desc_equals(pc.pendingRemoteDescription, offer);
})));
const offer = await pc.createOffer({ offerToReceiveAudio: true });
await pc.setLocalDescription(offer);
await pc2.setRemoteDescription(offer);
const answer = await pc2.createAnswer();
await pc2.setLocalDescription(answer);
await pc.setRemoteDescription(answer);
await pc.setRemoteDescription(await pc2.createOffer());
assert_equals(pc.remoteDescription.sdp, pc.pendingRemoteDescription.sdp);
assert_session_desc_similar(pc.remoteDescription, offer);
assert_session_desc_similar(pc.currentRemoteDescription, answer);
}, 'Switching role from offerer to answerer after going back to stable state should succeed');
/*

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

@ -786,7 +786,8 @@ var Bookmarks = Object.freeze({
updatedItem.index, updatedItem.type,
updatedItem.guid, item.parentGuid,
updatedItem.parentGuid,
updatedItem.source ]);
updatedItem.source,
updatedItem.url && updatedItem.url.href ]);
}
// Remove non-enumerable properties.
@ -1200,7 +1201,7 @@ var Bookmarks = Object.freeze({
i, child.type,
child.guid, child.parentGuid,
child.parentGuid,
source ]);
source, child.url && child.url.href ]);
}
})();
},

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

@ -1447,10 +1447,11 @@ class SyncedBookmarksMirror {
let movedItemRows = await this.db.execute(`
SELECT b.id, b.guid, b.type, p.id AS newParentId, c.oldParentId,
p.guid AS newParentGuid, c.oldParentGuid,
b.position AS newPosition, c.oldPosition
b.position AS newPosition, c.oldPosition, h.url
FROM itemsMoved c
JOIN moz_bookmarks b ON b.id = c.itemId
JOIN moz_bookmarks p ON p.id = b.parent
LEFT JOIN moz_places h ON h.id = b.fk
ORDER BY c.level, newParentId, newPosition`);
for await (let row of yieldingIterator(movedItemRows)) {
let info = {
@ -1463,6 +1464,7 @@ class SyncedBookmarksMirror {
oldParentGuid: row.getResultByName("oldParentGuid"),
newPosition: row.getResultByName("newPosition"),
oldPosition: row.getResultByName("oldPosition"),
urlHref: row.getResultByName("url"),
};
observersToNotify.noteItemMoved(info);
}
@ -4603,7 +4605,7 @@ class BookmarkObserverRecorder {
isTagging: false,
args: [info.id, info.oldParentId, info.oldPosition, info.newParentId,
info.newPosition, info.type, info.guid, info.oldParentGuid,
info.newParentGuid, PlacesUtils.bookmarks.SOURCES.SYNC],
info.newParentGuid, PlacesUtils.bookmarks.SOURCES.SYNC, info.urlHref],
});
}

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

@ -246,6 +246,8 @@ interface nsINavBookmarkObserver : nsISupports
* @param aSource
* A change source constant from nsINavBookmarksService::SOURCE_*,
* passed to the method that notifies the observer.
* @param aURI
* The URI for this bookmark.
*/
void onItemMoved(in long long aItemId,
in long long aOldParentId,
@ -256,7 +258,8 @@ interface nsINavBookmarkObserver : nsISupports
in ACString aGuid,
in ACString aOldParentGuid,
in ACString aNewParentGuid,
in unsigned short aSource);
in unsigned short aSource,
in AUTF8String aURI);
};
/**

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

@ -3032,7 +3032,8 @@ nsNavHistoryQueryResultNode::OnItemMoved(int64_t aFolder,
const nsACString& aGUID,
const nsACString& aOldParentGUID,
const nsACString& aNewParentGUID,
uint16_t aSource)
uint16_t aSource,
const nsACString& aURI)
{
// 1. The query cannot be affected by the item's position
// 2. For the time being, we cannot optimize this not to update
@ -3991,13 +3992,24 @@ nsNavHistoryFolderResultNode::OnItemMoved(int64_t aItemId,
const nsACString& aGUID,
const nsACString& aOldParentGUID,
const nsACString& aNewParentGUID,
uint16_t aSource)
uint16_t aSource,
const nsACString& aURI)
{
NS_ASSERTION(aOldParent == mTargetFolderItemId || aNewParent == mTargetFolderItemId,
"Got a bookmark message that doesn't belong to us");
RESTART_AND_RETURN_IF_ASYNC_PENDING();
bool excludeItems = mOptions->ExcludeItems();
if (excludeItems &&
(aItemType == nsINavBookmarksService::TYPE_SEPARATOR ||
(aItemType == nsINavBookmarksService::TYPE_BOOKMARK &&
!StringBeginsWith(aURI, NS_LITERAL_CSTRING("place:"))))) {
// This is a bookmark or a separator, so we don't need to handle this if
// we're excluding items.
return NS_OK;
}
uint32_t index;
nsNavHistoryResultNode* node = FindChildById(aItemId, &index);
// Bug 1097528.
@ -4010,12 +4022,6 @@ nsNavHistoryFolderResultNode::OnItemMoved(int64_t aItemId,
if (!node && aOldParent == mTargetFolderItemId)
return NS_OK;
bool excludeItems = mOptions->ExcludeItems();
if (node && excludeItems && (node->IsURI() || node->IsSeparator())) {
// Don't update items when we aren't displaying them.
return NS_OK;
}
if (!StartIncrementalUpdate())
return NS_OK; // entire container was refreshed for us
@ -4670,25 +4676,26 @@ nsNavHistoryResult::OnItemMoved(int64_t aItemId,
const nsACString& aGUID,
const nsACString& aOldParentGUID,
const nsACString& aNewParentGUID,
uint16_t aSource)
uint16_t aSource,
const nsACString& aURI)
{
ENUMERATE_BOOKMARK_FOLDER_OBSERVERS(aOldParent,
OnItemMoved(aItemId, aOldParent, aOldIndex, aNewParent, aNewIndex,
aItemType, aGUID, aOldParentGUID, aNewParentGUID, aSource));
aItemType, aGUID, aOldParentGUID, aNewParentGUID, aSource, aURI));
if (aNewParent != aOldParent) {
ENUMERATE_BOOKMARK_FOLDER_OBSERVERS(aNewParent,
OnItemMoved(aItemId, aOldParent, aOldIndex, aNewParent, aNewIndex,
aItemType, aGUID, aOldParentGUID, aNewParentGUID, aSource));
aItemType, aGUID, aOldParentGUID, aNewParentGUID, aSource, aURI));
}
ENUMERATE_ALL_BOOKMARKS_OBSERVERS(OnItemMoved(aItemId, aOldParent, aOldIndex,
aNewParent, aNewIndex,
aItemType, aGUID,
aOldParentGUID,
aNewParentGUID, aSource));
aNewParentGUID, aSource, aURI));
ENUMERATE_HISTORY_OBSERVERS(OnItemMoved(aItemId, aOldParent, aOldIndex,
aNewParent, aNewIndex, aItemType,
aGUID, aOldParentGUID,
aNewParentGUID, aSource));
aNewParentGUID, aSource, aURI));
return NS_OK;
}

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

@ -193,7 +193,8 @@ add_task(async function update_move_same_folder() {
observer.check([ { name: "onItemMoved",
arguments: [ bmItemId, bmParentId, bmOldIndex, bmParentId, bm.index,
bm.type, bm.guid, bm.parentGuid, bm.parentGuid,
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
Ci.nsINavBookmarksService.SOURCE_DEFAULT,
"http://move.example.com/" ] }
]);
// Test that we get the right index for DEFAULT_INDEX input.
@ -206,7 +207,8 @@ add_task(async function update_move_same_folder() {
observer.check([ { name: "onItemMoved",
arguments: [ bmItemId, bmParentId, bmOldIndex, bmParentId, bm.index,
bm.type, bm.guid, bm.parentGuid, bm.parentGuid,
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
Ci.nsINavBookmarksService.SOURCE_DEFAULT,
bm.url ] }
]);
});
@ -231,7 +233,8 @@ add_task(async function update_move_different_folder() {
bm.index, bm.type, bm.guid,
PlacesUtils.bookmarks.unfiledGuid,
bm.parentGuid,
Ci.nsINavBookmarksService.SOURCE_DEFAULT ] }
Ci.nsINavBookmarksService.SOURCE_DEFAULT,
"http://move.example.com/" ] }
]);
});
@ -522,7 +525,8 @@ add_task(async function reorder_notification() {
child.guid,
child.parentGuid,
child.parentGuid,
Ci.nsINavBookmarksService.SOURCE_DEFAULT
Ci.nsINavBookmarksService.SOURCE_DEFAULT,
child.url
] });
}
observer.check(expectedNotifications);

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

@ -333,6 +333,7 @@ add_task(async function onItemMoved_bookmark() {
{ name: "oldParentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "newParentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
{ name: "url", check: v => typeof(v) == "string" },
] },
{ name: "onItemMoved",
args: [
@ -346,6 +347,7 @@ add_task(async function onItemMoved_bookmark() {
{ name: "oldParentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "newParentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
{ name: "url", check: v => typeof(v) == "string" },
] },
])]);
await PlacesUtils.bookmarks.update({

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

@ -253,11 +253,11 @@ BookmarkObserver.prototype = {
},
onItemVisited() {},
onItemMoved(itemId, oldParentId, oldIndex, newParentId, newIndex, type, guid,
oldParentGuid, newParentGuid, source) {
oldParentGuid, newParentGuid, source, uri) {
this.notifications.push({
name: "onItemMoved",
params: { itemId, oldParentId, oldIndex, newParentId, newIndex, type,
guid, oldParentGuid, newParentGuid, source },
guid, oldParentGuid, newParentGuid, source, uri },
});
},

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

@ -115,7 +115,8 @@ add_task(async function test_value_structure_conflict() {
guid: "bookmarkEEEE",
oldParentGuid: "folderDDDDDD",
newParentGuid: "folderDDDDDD",
source: PlacesUtils.bookmarks.SOURCES.SYNC },
source: PlacesUtils.bookmarks.SOURCES.SYNC,
uri: "http://example.com/e" },
}, {
name: "onItemMoved",
params: { itemId: localItemIds.get("bookmarkBBBB"),
@ -125,7 +126,8 @@ add_task(async function test_value_structure_conflict() {
guid: "bookmarkBBBB",
oldParentGuid: "folderDDDDDD",
newParentGuid: "folderDDDDDD",
source: PlacesUtils.bookmarks.SOURCES.SYNC },
source: PlacesUtils.bookmarks.SOURCES.SYNC,
uri: "http://example.com/b" },
}, {
name: "onItemChanged",
params: { itemId: localItemIds.get("folderDDDDDD"), property: "title",
@ -289,7 +291,8 @@ add_task(async function test_move() {
guid: "devFolder___",
oldParentGuid: PlacesUtils.bookmarks.menuGuid,
newParentGuid: PlacesUtils.bookmarks.toolbarGuid,
source: PlacesUtils.bookmarks.SOURCES.SYNC },
source: PlacesUtils.bookmarks.SOURCES.SYNC,
uri: null },
}, {
name: "onItemMoved",
params: { itemId: localItemIds.get("mozFolder___"),
@ -299,7 +302,8 @@ add_task(async function test_move() {
guid: "mozFolder___",
oldParentGuid: "devFolder___",
newParentGuid: PlacesUtils.bookmarks.unfiledGuid,
source: PlacesUtils.bookmarks.SOURCES.SYNC },
source: PlacesUtils.bookmarks.SOURCES.SYNC,
uri: null },
}, {
name: "onItemMoved",
params: { itemId: localItemIds.get("bzBmk_______"),
@ -309,7 +313,8 @@ add_task(async function test_move() {
guid: "bzBmk_______",
oldParentGuid: PlacesUtils.bookmarks.menuGuid,
newParentGuid: "devFolder___",
source: PlacesUtils.bookmarks.SOURCES.SYNC },
source: PlacesUtils.bookmarks.SOURCES.SYNC,
uri: "https://bugzilla.mozilla.org/" },
}, {
name: "onItemMoved",
params: { itemId: localItemIds.get("wmBmk_______"),
@ -319,7 +324,8 @@ add_task(async function test_move() {
guid: "wmBmk_______",
oldParentGuid: "devFolder___",
newParentGuid: "devFolder___",
source: PlacesUtils.bookmarks.SOURCES.SYNC },
source: PlacesUtils.bookmarks.SOURCES.SYNC,
uri: "https://webmaker.org/" },
}, {
name: "onItemMoved",
params: { itemId: localItemIds.get("nightlyBmk__"),
@ -329,7 +335,8 @@ add_task(async function test_move() {
guid: "nightlyBmk__",
oldParentGuid: "mozFolder___",
newParentGuid: "mozFolder___",
source: PlacesUtils.bookmarks.SOURCES.SYNC },
source: PlacesUtils.bookmarks.SOURCES.SYNC,
uri: "https://nightly.mozilla.org/" },
}, {
name: "onItemMoved",
params: { itemId: localItemIds.get("mdnBmk______"),
@ -339,7 +346,8 @@ add_task(async function test_move() {
guid: "mdnBmk______",
oldParentGuid: "devFolder___",
newParentGuid: "mozFolder___",
source: PlacesUtils.bookmarks.SOURCES.SYNC },
source: PlacesUtils.bookmarks.SOURCES.SYNC,
uri: "https://developer.mozilla.org/" },
}, {
name: "onItemMoved",
params: { itemId: localItemIds.get("fxBmk_______"),
@ -349,7 +357,8 @@ add_task(async function test_move() {
guid: "fxBmk_______",
oldParentGuid: "mozFolder___",
newParentGuid: "mozFolder___",
source: PlacesUtils.bookmarks.SOURCES.SYNC },
source: PlacesUtils.bookmarks.SOURCES.SYNC,
uri: "http://getfirefox.com/" },
}]);
await assertLocalTree(PlacesUtils.bookmarks.rootGuid, {
@ -513,7 +522,8 @@ add_task(async function test_move_into_parent_sibling() {
guid: "bookmarkBBBB",
oldParentGuid: "folderAAAAAA",
newParentGuid: "folderCCCCCC",
source: PlacesUtils.bookmarks.SOURCES.SYNC },
source: PlacesUtils.bookmarks.SOURCES.SYNC,
uri: "http://example.com/b" },
}]);
await assertLocalTree(PlacesUtils.bookmarks.menuGuid, {
@ -666,7 +676,8 @@ add_task(async function test_complex_move_with_additions() {
guid: "bookmarkCCCC",
oldParentGuid: "folderAAAAAA",
newParentGuid: PlacesUtils.bookmarks.menuGuid,
source: PlacesUtils.bookmarks.SOURCES.SYNC },
source: PlacesUtils.bookmarks.SOURCES.SYNC,
uri: "http://example.com/c" },
}, {
name: "onItemMoved",
params: { itemId: localItemIds.get("folderAAAAAA"),
@ -676,7 +687,8 @@ add_task(async function test_complex_move_with_additions() {
guid: "folderAAAAAA",
oldParentGuid: PlacesUtils.bookmarks.menuGuid,
newParentGuid: PlacesUtils.bookmarks.toolbarGuid,
source: PlacesUtils.bookmarks.SOURCES.SYNC },
source: PlacesUtils.bookmarks.SOURCES.SYNC,
uri: null },
}]);
await assertLocalTree(PlacesUtils.bookmarks.rootGuid, {

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

@ -145,7 +145,8 @@ add_task(async function test_value_combo() {
guid: "bzBmk_______",
oldParentGuid: PlacesUtils.bookmarks.toolbarGuid,
newParentGuid: PlacesUtils.bookmarks.toolbarGuid,
source: PlacesUtils.bookmarks.SOURCES.SYNC },
source: PlacesUtils.bookmarks.SOURCES.SYNC,
uri: "https://bugzilla.mozilla.org/" },
}, {
name: "onItemChanged",
params: { itemId: localItemIds.get("mozBmk______"), property: "title",
@ -708,7 +709,8 @@ add_task(async function test_keywords_complex() {
guid: "bookmarkBBBB",
oldParentGuid: PlacesUtils.bookmarks.menuGuid,
newParentGuid: PlacesUtils.bookmarks.menuGuid,
source: PlacesUtils.bookmarks.SOURCES.SYNC },
source: PlacesUtils.bookmarks.SOURCES.SYNC,
uri: "http://example.com/b" },
}, {
name: "onItemMoved",
params: { itemId: localItemIds.get("bookmarkCCCC"),
@ -718,7 +720,8 @@ add_task(async function test_keywords_complex() {
guid: "bookmarkCCCC",
oldParentGuid: PlacesUtils.bookmarks.menuGuid,
newParentGuid: PlacesUtils.bookmarks.menuGuid,
source: PlacesUtils.bookmarks.SOURCES.SYNC },
source: PlacesUtils.bookmarks.SOURCES.SYNC,
uri: "http://example.com/c-remote" },
}, {
name: "onItemMoved",
params: { itemId: localItemIds.get("bookmarkDDDD"),
@ -728,7 +731,8 @@ add_task(async function test_keywords_complex() {
guid: "bookmarkDDDD",
oldParentGuid: PlacesUtils.bookmarks.menuGuid,
newParentGuid: PlacesUtils.bookmarks.menuGuid,
source: PlacesUtils.bookmarks.SOURCES.SYNC },
source: PlacesUtils.bookmarks.SOURCES.SYNC,
uri: "http://example.com/d" },
}, {
name: "onItemMoved",
params: { itemId: localItemIds.get("bookmarkEEEE"),
@ -738,7 +742,8 @@ add_task(async function test_keywords_complex() {
guid: "bookmarkEEEE",
oldParentGuid: PlacesUtils.bookmarks.menuGuid,
newParentGuid: PlacesUtils.bookmarks.menuGuid,
source: PlacesUtils.bookmarks.SOURCES.SYNC },
source: PlacesUtils.bookmarks.SOURCES.SYNC,
uri: "http://example.com/e" },
}, {
name: "onItemChanged",
params: { itemId: localItemIds.get("bookmarkCCCC"), property: "title",

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

@ -10,6 +10,7 @@
#include <time.h>
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/dom/Element.h"
#include "mozilla/Logging.h"
#include "mozilla/Mutex.h"
#include "mozilla/Preferences.h"
@ -982,7 +983,7 @@ nsRFPService::GetSpoofedKeyCodeInfo(const nsIDocument* aDoc,
// If the content-langauge is not given, we try to get langauge from the HTML
// lang attribute.
if (language.IsEmpty()) {
Element* elm = aDoc->GetHtmlElement();
dom::Element* elm = aDoc->GetHtmlElement();
if (elm) {
elm->GetLang(language);

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