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": { "env": {
"mozilla/browser-window": true "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 // XXX Bug 1436303. These directories are still being fixed, so turn off
// mozilla/no-cc-etc for now. // mozilla/no-cc-etc for now.

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

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

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

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

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

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

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

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

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

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

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

@ -50,6 +50,8 @@ export default class PaymentDialog extends PaymentStateSubscriberMixin(HTMLEleme
this._payerRelatedEls = contents.querySelectorAll(".payer-related"); this._payerRelatedEls = contents.querySelectorAll(".payer-related");
this._payerAddressPicker = contents.querySelector("address-picker.payer-related"); this._payerAddressPicker = contents.querySelector("address-picker.payer-related");
this._header = contents.querySelector("header");
this._errorText = contents.querySelector("#error-text"); this._errorText = contents.querySelector("#error-text");
this._disabledOverlay = contents.getElementById("disabled-overlay"); this._disabledOverlay = contents.getElementById("disabled-overlay");
@ -260,6 +262,10 @@ export default class PaymentDialog extends PaymentStateSubscriberMixin(HTMLEleme
totalAmountEl.value = totalItem.amount.value; totalAmountEl.value = totalItem.amount.value;
totalAmountEl.currency = totalItem.amount.currency; 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._orderDetailsOverlay.hidden = !state.orderDetailsShowing;
this._errorText.textContent = paymentDetails.error; this._errorText.textContent = paymentDetails.error;

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

@ -24,10 +24,12 @@ export default class PaymentMethodPicker extends PaymentStateSubscriberMixin(HTM
this.securityCodeInput.size = 3; this.securityCodeInput.size = 3;
this.securityCodeInput.addEventListener("change", this); this.securityCodeInput.addEventListener("change", this);
this.addLink = document.createElement("a"); this.addLink = document.createElement("a");
this.addLink.className = "add-link";
this.addLink.href = "javascript:void(0)"; this.addLink.href = "javascript:void(0)";
this.addLink.textContent = this.dataset.addLinkLabel; this.addLink.textContent = this.dataset.addLinkLabel;
this.addLink.addEventListener("click", this); this.addLink.addEventListener("click", this);
this.editLink = document.createElement("a"); this.editLink = document.createElement("a");
this.editLink.className = "edit-link";
this.editLink.href = "javascript:void(0)"; this.editLink.href = "javascript:void(0)";
this.editLink.textContent = this.dataset.editLinkLabel; this.editLink.textContent = this.dataset.editLinkLabel;
this.editLink.addEventListener("click", this); 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"); }, "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"); info("Closing the payment dialog");
spawnPaymentDialogTask(frame, async function() { spawnPaymentDialogTask(frame, async function() {
content.document.getElementById("address-page-cancel-button").click(); 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, { await setupPaymentDialog(browser, {
methodData: [PTU.MethodData.basicCard], methodData: [PTU.MethodData.basicCard],
details: PTU.Details.total60USD, details: PTU.Details.total60USD,
options: PTU.Options.requestShippingOption,
merchantTaskFn: PTU.ContentTasks.createAndShowRequest, 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"); }, "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"); info("Closing the payment dialog");
spawnPaymentDialogTask(frame, async function() { 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"); await BrowserTestUtils.waitForCondition(() => win.closed, "dialog should be closed");

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

@ -1339,3 +1339,9 @@ if CONFIG['MOZ_SYSTEM_ICU']:
'unicode/ustring.h', 'unicode/ustring.h',
'unicode/utypes.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. # executable permissions.
os.chmod('config.status', 0o755) os.chmod('config.status', 0o755)
if config.get('MOZ_BUILD_APP') != 'js' or config.get('JS_STANDALONE'): 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 from mozbuild.config_status import config_status
# Some values in sanitized_config also have more complex types, such as # 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). // to automatically trigger multiline editing (equivalent to shift + enter).
pref("devtools.webconsole.autoMultiline", true); pref("devtools.webconsole.autoMultiline", true);
// Enable the webconsole sidebar toggle in Nightly builds. // Enable the webconsole sidebar toggle
#if defined(NIGHTLY_BUILD)
pref("devtools.webconsole.sidebarToggle", true);
#else
pref("devtools.webconsole.sidebarToggle", false); pref("devtools.webconsole.sidebarToggle", false);
#endif
// Disable the new performance recording panel by default // Disable the new performance recording panel by default
pref("devtools.performance.new-panel-enabled", false); pref("devtools.performance.new-panel-enabled", false);

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

@ -33,12 +33,22 @@ const PriorityLevels = {
* *
* See also MDN for more info about <xul:notificationbox>: * See also MDN for more info about <xul:notificationbox>:
* https://developer.mozilla.org/en-US/docs/Mozilla/Tech/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 { class NotificationBox extends Component {
static get propTypes() { static get propTypes() {
return { return {
// Optional box ID (used for mounted node ID attribute)
id: PropTypes.string,
// List of notifications appended into the box. // 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 to appear on the notification.
label: PropTypes.string.isRequired, label: PropTypes.string.isRequired,
@ -74,7 +84,7 @@ class NotificationBox extends Component {
// A function to call to notify you of interesting things that happen // A function to call to notify you of interesting things that happen
// with the notification box. // with the notification box.
eventCallback: PropTypes.func, eventCallback: PropTypes.func,
})), })),*/
// Message that should be shown when hovering over the close button // Message that should be shown when hovering over the close button
closeButtonTooltip: PropTypes.string closeButtonTooltip: PropTypes.string
@ -109,43 +119,16 @@ class NotificationBox extends Component {
* added behind it. See `propTypes` for arguments description. * added behind it. See `propTypes` for arguments description.
*/ */
appendNotification(label, value, image, priority, buttons = [], eventCallback) { appendNotification(label, value, image, priority, buttons = [], eventCallback) {
// Priority level must be within expected interval const newState = appendNotification(this.state, {
// (see priority levels at the top of this file). label,
if (priority < PriorityLevels.PRIORITY_INFO_LOW || value,
priority > PriorityLevels.PRIORITY_CRITICAL_BLOCK) { image,
throw new Error("Invalid notification priority " + priority); priority,
} buttons,
eventCallback,
// 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,
}); });
// High priorities must be on top. this.setState(newState);
notifications = notifications.sortBy((val, key) => {
return -val.priority;
});
this.setState({
notifications: notifications
});
} }
/** /**
@ -192,6 +175,10 @@ class NotificationBox extends Component {
notification.eventCallback("removed"); notification.eventCallback("removed");
} }
if (!this.state.notifications.get(notification.value)) {
return;
}
this.setState({ this.setState({
notifications: this.state.notifications.remove(notification.value) notifications: this.state.notifications.remove(notification.value)
}); });
@ -260,16 +247,92 @@ class NotificationBox extends Component {
* notification is rendered at a time. * notification is rendered at a time.
*/ */
render() { render() {
let notification = this.state.notifications.first(); const notifications = this.props.notifications || this.state.notifications;
let content = notification ? const notification = notifications ? notifications.first() : null;
const content = notification ?
this.renderNotification(notification) : this.renderNotification(notification) :
null; null;
return div({className: "notificationbox"}, return div({
className: "notificationbox",
id: this.props.id},
content 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.NotificationBox = NotificationBox;
module.exports.PriorityLevels = PriorityLevels; 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("./filters"),
require("./messages"), require("./messages"),
require("./ui"), require("./ui"),
require("./notifications"),
]; ];
const actions = Object.assign({}, ...actionModules); const actions = Object.assign({}, ...actionModules);

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

@ -7,5 +7,6 @@ DevToolsModules(
'filters.js', 'filters.js',
'index.js', 'index.js',
'messages.js', 'messages.js',
'notifications.js',
'ui.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, "AutocompletePopup", "devtools/client/shared/autocomplete-popup");
loader.lazyRequireGetter(this, "asyncStorage", "devtools/shared/async-storage"); loader.lazyRequireGetter(this, "asyncStorage", "devtools/shared/async-storage");
loader.lazyRequireGetter(this, "gDevTools", "devtools/client/framework/devtools", true); 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"); const l10n = require("devtools/client/webconsole/webconsole-l10n");
@ -53,6 +51,8 @@ class JSTerm extends Component {
static get propTypes() { static get propTypes() {
return { return {
hud: PropTypes.object.isRequired, 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 { const {
hud, hud,
} = props; } = props;
this.hud = hud; this.hud = hud;
this.hudId = this.hud.hudId; this.hudId = this.hud.hudId;
this.inputHistoryCount = Services.prefs.getIntPref(PREF_INPUT_HISTORY_COUNT); 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("input", this._inputEventHandler);
this.inputNode.addEventListener("keyup", this._inputEventHandler); this.inputNode.addEventListener("keyup", this._inputEventHandler);
this.inputNode.addEventListener("focus", this._focusEventHandler); 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.hud.window.addEventListener("blur", this._blurEventHandler);
this.lastInputValue && this.setInputValue(this.lastInputValue); this.lastInputValue && this.setInputValue(this.lastInputValue);
@ -1279,29 +1270,11 @@ class JSTerm extends Component {
this._inputCharWidth = tempLabel.offsetWidth; this._inputCharWidth = tempLabel.offsetWidth;
tempLabel.remove(); tempLabel.remove();
// Calculate the width of the chevron placed at the beginning of the input // 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) this._chevronWidth = +doc.defaultView.getComputedStyle(this.inputNode)
.paddingLeft.replace(/[^0-9.]/g, "") - 4; .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() { destroy() {
this.clearCompletion(); this.clearCompletion();
@ -1318,12 +1291,6 @@ class JSTerm extends Component {
} }
if (this.inputNode) { 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("keypress", this._keyPress);
this.inputNode.removeEventListener("input", this._inputEventHandler); this.inputNode.removeEventListener("input", this._inputEventHandler);
this.inputNode.removeEventListener("keyup", this._inputEventHandler); this.inputNode.removeEventListener("keyup", this._inputEventHandler);
@ -1340,8 +1307,11 @@ class JSTerm extends Component {
return null; return null;
} }
return [ let {
dom.div({id: "webconsole-notificationbox", key: "notification"}), onPaste
} = this.props;
return (
dom.div({ dom.div({
className: "jsterm-input-container", className: "jsterm-input-container",
key: "jsterm-container", key: "jsterm-container",
@ -1365,9 +1335,11 @@ class JSTerm extends Component {
ref: node => { ref: node => {
this.inputNode = node; this.inputNode = node;
}, },
onPaste: onPaste,
onDrop: onPaste,
}) })
), )
]; );
} }
} }

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

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

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

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

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

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

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

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

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

@ -7,6 +7,7 @@ DevToolsModules(
'filters.js', 'filters.js',
'index.js', 'index.js',
'messages.js', 'messages.js',
'notifications.js',
'prefs.js', 'prefs.js',
'ui.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( DevToolsModules(
'filters.js', 'filters.js',
'messages.js', 'messages.js',
'notifications.js',
'prefs.js', 'prefs.js',
'ui.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); let menuPopup = await openContextMenu(hud, networkMessage.node);
ok(menuPopup, "The context menu is displayed on a network message"); ok(menuPopup, "The context menu is displayed on a network message");
let expectedContextMenu = addPrefBasedEntries([ let expectedContextMenu = [
"#console-menu-copy-url (a)", "#console-menu-copy-url (a)",
"#console-menu-open-url (T)", "#console-menu-open-url (T)",
"#console-menu-store (S) [disabled]", "#console-menu-store (S) [disabled]",
"#console-menu-copy (C)", "#console-menu-copy (C)",
"#console-menu-copy-object (o) [disabled]", "#console-menu-copy-object (o) [disabled]",
"#console-menu-select (A)", "#console-menu-select (A)"
]); ];
is(getSimplifiedContextMenu(menuPopup).join("\n"), expectedContextMenu.join("\n"), is(getSimplifiedContextMenu(menuPopup).join("\n"), expectedContextMenu.join("\n"),
"The context menu has the expected entries for a network message"); "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); menuPopup = await openContextMenu(hud, logMessage.node);
ok(menuPopup, "The context menu is displayed on a log message"); ok(menuPopup, "The context menu is displayed on a log message");
expectedContextMenu = addPrefBasedEntries([ expectedContextMenu = [
"#console-menu-store (S) [disabled]", "#console-menu-store (S) [disabled]",
"#console-menu-copy (C)", "#console-menu-copy (C)",
"#console-menu-copy-object (o) [disabled]", "#console-menu-copy-object (o) [disabled]",
"#console-menu-select (A)", "#console-menu-select (A)"
]); ];
is(getSimplifiedContextMenu(menuPopup).join("\n"), expectedContextMenu.join("\n"), is(getSimplifiedContextMenu(menuPopup).join("\n"), expectedContextMenu.join("\n"),
"The context menu has the expected entries for a simple log message"); "The context menu has the expected entries for a simple log message");
await hideContextMenu(hud); 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) { function getSimplifiedContextMenu(popupElement) {
return [...popupElement.querySelectorAll("menuitem")] return [...popupElement.querySelectorAll("menuitem")]
.map(entry => { .map(entry => {

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

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

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

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

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

@ -250,25 +250,29 @@ const NodeActor = protocol.ActorClassWithSpec(nodeSpec, {
return null; 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() { get isDisplayed() {
// Consider all non-element nodes as displayed. let type = this.displayType;
if (InspectorActorUtils.isNodeDead(this) ||
this.rawNode.nodeType !== Ci.nsIDOMNode.ELEMENT_NODE) { // Consider all non-elements or elements with no display-types to be displayed.
if (!type) {
return true; return true;
} }
let style = this.computedStyle; // Otherwise consider elements to be displayed only if their display-types is other
if (!style) { // than "none"".
return true; return type !== "none";
}
return style.display !== "none";
}, },
/** /**

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

@ -45,6 +45,7 @@ DevToolsModules(
'highlighters.js', 'highlighters.js',
'layout.js', 'layout.js',
'memory.js', 'memory.js',
'network-event.js',
'object.js', 'object.js',
'pause-scoped.js', 'pause-scoped.js',
'perf.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, "NetworkMonitor", "devtools/shared/webconsole/network-monitor", true);
loader.lazyRequireGetter(this, "NetworkMonitorChild", "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, "ConsoleProgressListener", "devtools/shared/webconsole/network-monitor", true);
loader.lazyRequireGetter(this, "StackTraceCollector", "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); loader.lazyRequireGetter(this, "JSPropertyProvider", "devtools/shared/webconsole/js-property-provider", true);
@ -1904,529 +1905,3 @@ WebConsoleActor.prototype.requestTypes =
}; };
exports.WebConsoleActor = WebConsoleActor; 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() { get isDisplayed() {
// The NodeActor's form contains the isDisplayed information as a boolean return this._form.isDisplayed;
// starting from FF32. Before that, the property is missing
return "isDisplayed" in this._form ? this._form.isDisplayed : true;
}, },
get isTreeDisplayed() { get isTreeDisplayed() {

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

@ -1012,10 +1012,11 @@ Actor.prototype = extend(Pool.prototype, {
return { actor: this.actorID }; return { actor: this.actorID };
}, },
writeError: function(error) { writeError: function(error, typeName, method) {
console.error(error); console.error(`Error while calling actor '${typeName}'s method '${method}'`,
error.message);
if (error.stack) { if (error.stack) {
dump(error.stack); console.error(error.stack);
} }
this.conn.send({ this.conn.send({
from: this.actorID, from: this.actorID,
@ -1151,6 +1152,10 @@ var generateRequestHandlers = function(actorSpec, actorProto) {
throw ex; 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 ret = this[spec.name].apply(this, args);
let sendReturn = (retToSend) => { let sendReturn = (retToSend) => {
@ -1172,7 +1177,7 @@ var generateRequestHandlers = function(actorSpec, actorProto) {
try { try {
this.destroy(); this.destroy();
} catch (e) { } catch (e) {
this.writeError(e); this.writeError(e, actorProto.typeName, spec.name);
return; return;
} }
} }
@ -1184,11 +1189,11 @@ var generateRequestHandlers = function(actorSpec, actorProto) {
return p return p
.then(() => ret) .then(() => ret)
.then(sendReturn) .then(sendReturn)
.catch(e => this.writeError(e)); .catch(e => this.writeError(e, actorProto.typeName, spec.name));
}); });
} catch (e) { } catch (e) {
this._queueResponse(p => { 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/css/ImageLoader.h"
#include "mozilla/layers/IAPZCTreeManager.h" // for layers::ZoomToRectBehavior #include "mozilla/layers/IAPZCTreeManager.h" // for layers::ZoomToRectBehavior
#include "mozilla/dom/Promise.h" #include "mozilla/dom/Promise.h"
#include "mozilla/ServoBindings.h"
#include "mozilla/StyleSheetInlines.h" #include "mozilla/StyleSheetInlines.h"
#include "mozilla/gfx/GPUProcessManager.h" #include "mozilla/gfx/GPUProcessManager.h"
#include "mozilla/dom/TimeoutManager.h" #include "mozilla/dom/TimeoutManager.h"

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

@ -206,6 +206,32 @@ SourceBuffer::AppendBuffer(const ArrayBufferView& aData, ErrorResult& aRv)
AppendData(aData.Data(), aData.Length(), 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 void
SourceBuffer::Abort(ErrorResult& aRv) 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); MSE_API("Remove(aStart=%f, aEnd=%f)", aStart, aEnd);
DDLOG(DDLogCategory::API, "Remove-from", aStart); DDLOG(DDLogCategory::API, "Remove-from", aStart);
DDLOG(DDLogCategory::API, "Remove-until", aEnd); 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()) { if (!IsAttached()) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return; return;
@ -276,8 +351,6 @@ SourceBuffer::Remove(double aStart, double aEnd, ErrorResult& aRv)
if (mMediaSource->ReadyState() == MediaSourceReadyState::Ended) { if (mMediaSource->ReadyState() == MediaSourceReadyState::Ended) {
mMediaSource->SetReadyState(MediaSourceReadyState::Open); mMediaSource->SetReadyState(MediaSourceReadyState::Open);
} }
RangeRemoval(aStart, aEnd);
} }
void void
@ -459,6 +532,10 @@ SourceBuffer::StopUpdating()
mUpdating = false; mUpdating = false;
QueueAsyncSimpleEvent("update"); QueueAsyncSimpleEvent("update");
QueueAsyncSimpleEvent("updateend"); QueueAsyncSimpleEvent("updateend");
if (mDOMPromise) {
mDOMPromise->MaybeResolveWithUndefined();
mDOMPromise = nullptr;
}
} }
void void
@ -468,6 +545,10 @@ SourceBuffer::AbortUpdating()
mUpdating = false; mUpdating = false;
QueueAsyncSimpleEvent("abort"); QueueAsyncSimpleEvent("abort");
QueueAsyncSimpleEvent("updateend"); QueueAsyncSimpleEvent("updateend");
if (mDOMPromise) {
mDOMPromise->MaybeReject(NS_ERROR_DOM_MEDIA_ABORT_ERR);
mDOMPromise = nullptr;
}
} }
void void
@ -485,6 +566,7 @@ SourceBuffer::CheckEndTime()
void void
SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv) SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv)
{ {
MOZ_ASSERT(NS_IsMainThread());
MSE_DEBUG("AppendData(aLength=%u)", aLength); MSE_DEBUG("AppendData(aLength=%u)", aLength);
RefPtr<MediaByteBuffer> data = PrepareAppend(aData, aLength, aRv); RefPtr<MediaByteBuffer> data = PrepareAppend(aData, aLength, aRv);
@ -500,8 +582,43 @@ SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aR
->Track(mPendingAppend); ->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 void
SourceBuffer::AppendDataCompletedWithSuccess(const SourceBufferTask::AppendBufferResult& aResult) SourceBuffer::AppendDataCompletedWithSuccess(
const SourceBufferTask::AppendBufferResult& aResult)
{ {
MOZ_ASSERT(mUpdating); MOZ_ASSERT(mUpdating);
mPendingAppend.Complete(); mPendingAppend.Complete();
@ -570,10 +687,17 @@ SourceBuffer::AppendError(const MediaResult& aDecodeError)
MOZ_ASSERT(NS_FAILED(aDecodeError)); MOZ_ASSERT(NS_FAILED(aDecodeError));
mMediaSource->EndOfStream(aDecodeError); mMediaSource->EndOfStream(aDecodeError);
if (mDOMPromise) {
mDOMPromise->MaybeReject(aDecodeError);
mDOMPromise = nullptr;
}
} }
already_AddRefed<MediaByteBuffer> 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; typedef TrackBuffersManager::EvictDataResult Result;
@ -660,12 +784,14 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(SourceBuffer)
tmp->Detach(); tmp->Detach();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mMediaSource) NS_IMPL_CYCLE_COLLECTION_UNLINK(mMediaSource)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mBuffered) NS_IMPL_CYCLE_COLLECTION_UNLINK(mBuffered)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDOMPromise)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(DOMEventTargetHelper) NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(SourceBuffer, NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(SourceBuffer,
DOMEventTargetHelper) DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaSource) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaSource)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBuffered) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBuffered)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDOMPromise)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_ADDREF_INHERITED(SourceBuffer, DOMEventTargetHelper) NS_IMPL_ADDREF_INHERITED(SourceBuffer, DOMEventTargetHelper)

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

@ -88,11 +88,20 @@ public:
void AppendBuffer(const ArrayBuffer& aData, ErrorResult& aRv); void AppendBuffer(const ArrayBuffer& aData, ErrorResult& aRv);
void AppendBuffer(const ArrayBufferView& 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 Abort(ErrorResult& aRv);
void AbortBufferAppend(); void AbortBufferAppend();
void Remove(double aStart, double aEnd, ErrorResult& aRv); 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); void ChangeType(const nsAString& aType, ErrorResult& aRv);
IMPL_EVENT_HANDLER(updatestart); IMPL_EVENT_HANDLER(updatestart);
@ -157,6 +166,10 @@ private:
// Shared implementation of AppendBuffer overloads. // Shared implementation of AppendBuffer overloads.
void AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv); 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". // Implement the "Append Error Algorithm".
// Will call endOfStream() with "decode" error if aDecodeError is true. // Will call endOfStream() with "decode" error if aDecodeError is true.
@ -190,6 +203,11 @@ private:
RefPtr<TimeRanges> mBuffered; RefPtr<TimeRanges> mBuffered;
MozPromiseRequestHolder<MediaSource::ActiveCompletionPromise> mCompletionPromise; 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 } // 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. //Register timeout function to dump debugging logs.
SimpleTest.registerTimeoutFunction(function() { SimpleTest.registerTimeoutFunction(function() {
for (var v of document.getElementsByTagName("video")) { 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 skip-if = toolkit == 'android' # Not supported on android
[test_Eviction_mp4.html] [test_Eviction_mp4.html]
skip-if = android_version == '15' # Not supported on Android(Bug 1358271) 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] [test_FrameSelection.html]
skip-if = android_version == '22' || toolkit == 'android' # bug 1341519, bug 1401090 skip-if = android_version == '22' || toolkit == 'android' # bug 1341519, bug 1401090
[test_FrameSelection_mp4.html] [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); void appendBuffer(ArrayBuffer data);
[Throws] [Throws]
void appendBuffer(ArrayBufferView data); 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] //[Throws]
//void appendStream(Stream stream, [EnforceRange] optional unsigned long long maxSize); //void appendStream(Stream stream, [EnforceRange] optional unsigned long long maxSize);
[Throws] [Throws]
@ -47,6 +53,10 @@ interface SourceBuffer : EventTarget {
[Throws] [Throws]
void remove(double start, unrestricted double end); void remove(double start, unrestricted double end);
// Experimental function as proposed in: // 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 // https://github.com/w3c/media-source/issues/155
[Throws, Func="mozilla::dom::MediaSource::ExperimentalEnabled"] [Throws, Func="mozilla::dom::MediaSource::ExperimentalEnabled"]
void changeType(DOMString type); void changeType(DOMString type);

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

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

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

@ -11,6 +11,9 @@ const LDAPSyncQueryContractID = "@mozilla.org/ldapsyncquery;1";
const nsIPrefService = Ci.nsIPrefService; const nsIPrefService = Ci.nsIPrefService;
const PrefServiceContractID = "@mozilla.org/preferences-service;1"; 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 gVersion;
var gIsUTF8; var gIsUTF8;

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

@ -4,17 +4,12 @@
/* eslint no-unsafe-finally: "off"*/ /* eslint no-unsafe-finally: "off"*/
/* Turning off this rule to allow control flow operations in finally block /* Turning off this rule to allow control flow operations in finally block
* http://eslint.org/docs/rules/no-unsafe-finally */ * 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); ChromeUtils.import("resource://gre/modules/Services.jsm");
let defaultPrefD = dirSvc.get("PrfDef", Ci.nsIFile);
function run_test() {
let greD = Services.dirsvc.get("GreD", Ci.nsIFile);
let defaultPrefD = Services.dirsvc.get("PrfDef", Ci.nsIFile);
let testDir = do_get_cwd(); let testDir = do_get_cwd();
try { try {
@ -24,7 +19,7 @@ function run_test() {
// Make sure nsReadConfig is initialized. // Make sure nsReadConfig is initialized.
Cc["@mozilla.org/readconfig;1"].getService(Ci.nsISupports); Cc["@mozilla.org/readconfig;1"].getService(Ci.nsISupports);
ps.resetPrefs(); Services.prefs.resetPrefs();
var tests = [{ var tests = [{
filename: "autoconfig-utf8.cfg", filename: "autoconfig-utf8.cfg",
@ -47,24 +42,24 @@ function run_test() {
function testAutoConfig(test) { function testAutoConfig(test) {
// Make sure pref values are unset. // Make sure pref values are unset.
for (let prefName in test.prefs) { 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(); let autoConfigCfg = testDir.clone();
autoConfigCfg.append(test.filename); autoConfigCfg.append(test.filename);
autoConfigCfg.copyTo(greD, "autoconfig.cfg"); 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) { for (let prefName in test.prefs) {
Assert.equal(test.prefs[prefName], Assert.equal(test.prefs[prefName],
prefs.getStringPref(prefName)); Services.prefs.getStringPref(prefName));
} }
ps.resetPrefs(); Services.prefs.resetPrefs();
// Make sure pref values are reset. // Make sure pref values are reset.
for (let prefName in test.prefs) { 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#if defined(MOZ_WIDGET_GTK) #if defined(MOZ_WIDGET_GTK)
#include <gdk/gdkx.h> #define GET_NATIVE_WINDOW_FROM_REAL_WIDGET(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_EGL_WINDOW))
// we're using default display for now #define GET_NATIVE_WINDOW_FROM_COMPOSITOR_WIDGET(aWidget) ((EGLNativeWindowType)aWidget->RealWidget()->GetNativeData(NS_NATIVE_EGL_WINDOW))
#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)))
#elif defined(MOZ_WIDGET_ANDROID) #elif defined(MOZ_WIDGET_ANDROID)
#define GET_NATIVE_WINDOW_FROM_REAL_WIDGET(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_JAVA_SURFACE)) #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()) #define GET_NATIVE_WINDOW_FROM_COMPOSITOR_WIDGET(aWidget) (aWidget->AsAndroid()->GetEGLNativeWindow())

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

@ -31,6 +31,13 @@
#include "GLContextProvider.h" #include "GLContextProvider.h"
#include "gfxPrefs.h" #include "gfxPrefs.h"
#include "ScopedGLHelpers.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 mozilla {
namespace gl { namespace gl {
@ -719,7 +726,22 @@ GLLibraryEGL::CreateDisplay(bool forceAccel, const nsCOMPtr<nsIGfxInfo>& gfxInfo
mIsWARP = true; mIsWARP = true;
} }
} else { } 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) { if (!chosenDisplay) {
@ -888,4 +910,3 @@ AfterEGLCall(const char* glFunction)
} /* namespace gl */ } /* namespace gl */
} /* namespace mozilla */ } /* namespace mozilla */

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

@ -177,6 +177,7 @@
#include "nsLayoutStylesheetCache.h" #include "nsLayoutStylesheetCache.h"
#include "mozilla/layers/InputAPZContext.h" #include "mozilla/layers/InputAPZContext.h"
#include "mozilla/layers/FocusTarget.h" #include "mozilla/layers/FocusTarget.h"
#include "mozilla/ServoBindings.h"
#include "mozilla/ServoStyleSet.h" #include "mozilla/ServoStyleSet.h"
#include "mozilla/StyleSheet.h" #include "mozilla/StyleSheet.h"
#include "mozilla/StyleSheetInlines.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 1453342.html
load 1453196.html load 1453196.html
pref(dom.webcomponents.shadowdom.enabled,true) load 1414303.html pref(dom.webcomponents.shadowdom.enabled,true) load 1414303.html
load 1461812.html

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -12,6 +12,7 @@
#include "mozilla/AtomArray.h" #include "mozilla/AtomArray.h"
#include "mozilla/ServoTypes.h" #include "mozilla/ServoTypes.h"
#include "mozilla/ServoBindingTypes.h" #include "mozilla/ServoBindingTypes.h"
#include "mozilla/ServoComputedDataInlines.h"
#include "mozilla/ServoElementSnapshot.h" #include "mozilla/ServoElementSnapshot.h"
#include "mozilla/css/SheetLoadData.h" #include "mozilla/css/SheetLoadData.h"
#include "mozilla/css/SheetParsingMode.h" #include "mozilla/css/SheetParsingMode.h"
@ -20,7 +21,6 @@
#include "mozilla/ComputedTimingFunction.h" #include "mozilla/ComputedTimingFunction.h"
#include "nsChangeHint.h" #include "nsChangeHint.h"
#include "nsIDocument.h" #include "nsIDocument.h"
#include "nsStyleStruct.h"
/* /*
* API for Servo to access Gecko data structures. * API for Servo to access Gecko data structures.
@ -78,17 +78,6 @@ const bool GECKO_IS_NIGHTLY = true;
const bool GECKO_IS_NIGHTLY = false; const bool GECKO_IS_NIGHTLY = false;
#endif #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_) \ #define NS_DECL_THREADSAFE_FFI_REFCOUNTING(class_, name_) \
void Gecko_AddRef##name_##ArbitraryThread(class_* aPtr); \ void Gecko_AddRef##name_##ArbitraryThread(class_* aPtr); \
void Gecko_Release##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, bool moz_legacy_syntax,
uint32_t stops); 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); nsAtom* Gecko_GetImageElement(const nsStyleImage* image);
const nsStyleGradient* Gecko_GetGradientImageValue(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" #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, * Type definitions used to interact with Servo. This gets included by nsINode,
* so don't add significant include dependencies to this file. * so don't add significant include dependencies to this file.
@ -129,44 +125,6 @@ enum class InheritTarget {
PlaceholderFrame, 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 // These measurements are obtained for both the UA cache and the Stylist, but
// not all the fields are used in both cases. // not all the fields are used in both cases.
class ServoStyleSetSizes 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 } // 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 #endif // mozilla_ServoTypes_h

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

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

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

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

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

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

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

@ -22,6 +22,7 @@ from mozbuild.base import MachCommandConditions
from mozbuild.frontend.emitter import TreeMetadataEmitter from mozbuild.frontend.emitter import TreeMetadataEmitter
from mozbuild.frontend.reader import BuildReader from mozbuild.frontend.reader import BuildReader
from mozbuild.mozinfo import write_mozinfo from mozbuild.mozinfo import write_mozinfo
from mozbuild.util import FileAvoidWrite
from itertools import chain from itertools import chain
from mozbuild.backend import ( from mozbuild.backend import (
@ -114,10 +115,8 @@ def config_status(topobjdir='.', topsrcdir='.', defines=None,
non_global_defines=non_global_defines, substs=substs, non_global_defines=non_global_defines, substs=substs,
source=source, mozconfig=mozconfig) source=source, mozconfig=mozconfig)
# mozinfo.json only needs written if configure changes and configure always with FileAvoidWrite(os.path.join(topobjdir, 'mozinfo.json')) as f:
# passes this environment variable. write_mozinfo(f, env, os.environ)
if 'WRITE_MOZINFO' in os.environ:
write_mozinfo(os.path.join(topobjdir, 'mozinfo.json'), env, os.environ)
cpu_start = time.clock() cpu_start = time.clock()
time_start = time.time() 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', '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'): '_CRT_RAND_S', 'CHROMIUM_SANDBOX_BUILD'):
DEFINES[var] = True DEFINES[var] = True
if CONFIG['CC_TYPE'] != 'gcc':
DEFINES['SANDBOX_EXPORTS'] = True
LOCAL_INCLUDES += ['/security/sandbox/chromium-shim'] LOCAL_INCLUDES += ['/security/sandbox/chromium-shim']
LOCAL_INCLUDES += ['/security/sandbox/chromium'] LOCAL_INCLUDES += ['/security/sandbox/chromium']

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

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

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

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

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

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

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

@ -40,18 +40,14 @@ pub struct CssUrl {
impl CssUrl { impl CssUrl {
/// Try to parse a URL from a string value that is a valid CSS token for a /// 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 /// URL.
/// gecko version. pub fn parse_from_string(url: String, context: &ParserContext) -> Self {
pub fn parse_from_string<'a>(
url: String,
context: &ParserContext,
) -> Result<Self, ParseError<'a>> {
let serialization = Arc::new(url); let serialization = Arc::new(url);
let resolved = context.url_data.join(&serialization).ok(); let resolved = context.url_data.join(&serialization).ok();
Ok(CssUrl { CssUrl {
original: Some(serialization), original: Some(serialization),
resolved: resolved, resolved: resolved,
}) }
} }
/// Returns true if the URL is definitely invalid. For Servo URLs, we can /// 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>, input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> { ) -> Result<Self, ParseError<'i>> {
let url = input.expect_url()?; 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_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, let media = parse_media_query_list(&self.context, input,
self.error_context.error_reporter); self.error_context.error_reporter);

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

@ -990,7 +990,7 @@ impl Parse for MozImageRect {
input.try(|i| i.expect_function_matching("-moz-image-rect"))?; input.try(|i| i.expect_function_matching("-moz-image-rect"))?;
input.parse_nested_block(|i| { input.parse_nested_block(|i| {
let string = i.expect_url_or_string()?; 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()?; i.expect_comma()?;
let top = NumberOrPercentage::parse_non_negative(context, i)?; let top = NumberOrPercentage::parse_non_negative(context, i)?;
i.expect_comma()?; i.expect_comma()?;

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

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

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

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

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

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

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

@ -1,42 +1,3 @@
[RTCPeerConnection-setRemoteDescription.html] [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] [Switching role from offerer to answerer after going back to stable state should succeed]
expected: FAIL 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" "support"
], ],
"binast/large.https.html": [ "binast/large.https.html": [
"3b27ede3f0666df43f752d8022c1e72d87f5b64f", "35b870a066dc31ecab2f0de8fb38a6d54345f332",
"testharness" "testharness"
], ],
"binast/large.js": [ "binast/large.js": [
@ -1070,7 +1070,7 @@
"support" "support"
], ],
"binast/small.https.html": [ "binast/small.https.html": [
"01ecd5cf1b3e7e5fa7bc53960d9defb80eb3eef7", "aedfb37a31775d878fc64237656cdb956331fb86",
"testharness" "testharness"
], ],
"binast/small.js": [ "binast/small.js": [

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

@ -16,7 +16,7 @@
// countAudioLine() // countAudioLine()
// countVideoLine() // countVideoLine()
// test_state_change_event() // test_state_change_event()
// assert_session_desc_equals() // assert_session_desc_similar()
/* /*
* 4.3.2. createOffer() * 4.3.2. createOffer()
@ -50,8 +50,8 @@
pc.setLocalDescription(offer) pc.setLocalDescription(offer)
.then(() => { .then(() => {
assert_equals(pc.signalingState, 'have-local-offer'); assert_equals(pc.signalingState, 'have-local-offer');
assert_session_desc_equals(pc.localDescription, offer); assert_session_desc_similar(pc.localDescription, offer);
assert_session_desc_equals(pc.pendingLocalDescription, offer); assert_session_desc_similar(pc.pendingLocalDescription, offer);
assert_equals(pc.currentLocalDescription, null); assert_equals(pc.currentLocalDescription, null);
})); }));
}, 'createOffer() and then setLocalDescription() should succeed'); }, '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), assert_true(isSimilarSessionDescription(sessionDesc1, sessionDesc2),
'Expect both session descriptions to have the same count of media lines'); '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), assert_false(isSimilarSessionDescription(sessionDesc1, sessionDesc2),
'Expect both session descriptions to have different count of media lines'); '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: // The following helper functions are called from RTCPeerConnection-helper.js:
// generateOffer // generateOffer
// generateAnswer // generateAnswer
// assert_session_desc_equals // assert_session_desc_similar
// test_state_change_event // test_state_change_event
/* /*
@ -71,11 +71,11 @@
pc.setLocalDescription(answer) pc.setLocalDescription(answer)
.then(() => { .then(() => {
assert_equals(pc.signalingState, 'stable'); assert_equals(pc.signalingState, 'stable');
assert_session_desc_equals(pc.localDescription, answer); assert_session_desc_similar(pc.localDescription, answer);
assert_session_desc_equals(pc.remoteDescription, offer); assert_session_desc_similar(pc.remoteDescription, offer);
assert_session_desc_equals(pc.currentLocalDescription, answer); assert_session_desc_similar(pc.currentLocalDescription, answer);
assert_session_desc_equals(pc.currentRemoteDescription, offer); assert_session_desc_similar(pc.currentRemoteDescription, offer);
assert_equals(pc.pendingLocalDescription, null); assert_equals(pc.pendingLocalDescription, null);
assert_equals(pc.pendingRemoteDescription, null); assert_equals(pc.pendingRemoteDescription, null);
@ -99,11 +99,11 @@
pc.setLocalDescription({ type: 'answer' }) pc.setLocalDescription({ type: 'answer' })
.then(() => { .then(() => {
assert_equals(pc.signalingState, 'stable'); assert_equals(pc.signalingState, 'stable');
assert_session_desc_equals(pc.localDescription, answer); assert_session_desc_similar(pc.localDescription, answer);
assert_session_desc_equals(pc.remoteDescription, offer); assert_session_desc_similar(pc.remoteDescription, offer);
assert_session_desc_equals(pc.currentLocalDescription, answer); assert_session_desc_similar(pc.currentLocalDescription, answer);
assert_session_desc_equals(pc.currentRemoteDescription, offer); assert_session_desc_similar(pc.currentRemoteDescription, offer);
assert_equals(pc.pendingLocalDescription, null); assert_equals(pc.pendingLocalDescription, null);
assert_equals(pc.pendingRemoteDescription, null); assert_equals(pc.pendingRemoteDescription, null);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -11,11 +11,8 @@
// https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html // https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html
// The following helper functions are called from RTCPeerConnection-helper.js: // The following helper functions are called from RTCPeerConnection-helper.js:
// generateOffer() // assert_session_desc_not_similar()
// generateAnswer() // assert_session_desc_similar()
// assert_session_desc_not_equals()
// assert_session_desc_equals()
// test_state_change_event()
/* /*
4.3.2. Interface Definition 4.3.2. Interface Definition
@ -48,76 +45,101 @@
/* /*
4.6.1. enum RTCSdpType 4.6.1. enum RTCSdpType
*/ */
promise_test(t => { promise_test(async t => {
const pc = new RTCPeerConnection(); const pc = new RTCPeerConnection();
t.add_cleanup(() => pc.close());
// SDP is validated after WebIDL validation // SDP is validated after WebIDL validation
return promise_rejects(t, new TypeError(), try {
pc.setRemoteDescription({ await pc.setRemoteDescription({ type: 'bogus', sdp: 'bogus' });
type: 'bogus', t.unreached_func("Should have rejected.");
sdp: 'bogus' } catch (e) {
})); assert_throws(new TypeError(), () => { throw e });
}
}, 'setRemoteDescription with invalid type and invalid SDP should reject with TypeError'); }, 'setRemoteDescription with invalid type and invalid SDP should reject with TypeError');
promise_test(t => { promise_test(async t => {
const pc = new RTCPeerConnection(); const pc = new RTCPeerConnection();
t.add_cleanup(() => pc.close());
// SDP is validated after validating type // SDP is validated after validating type
return promise_rejects(t, 'InvalidStateError', try {
pc.setRemoteDescription({ await pc.setRemoteDescription({ type: 'answer', sdp: 'invalid' });
type: 'answer', t.unreached_func("Should have rejected.");
sdp: 'invalid' } catch (e) {
})); assert_throws('InvalidStateError', () => { throw e });
}
}, 'setRemoteDescription() with invalid SDP and stable state should reject with InvalidStateError'); }, '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 */ /* Operations after returning to stable state */
promise_test(t => { promise_test(async t => {
const pc = new RTCPeerConnection(); const pc = new RTCPeerConnection();
const pc2 = new RTCPeerConnection(); const pc2 = new RTCPeerConnection();
t.add_cleanup(() => pc.close());
t.add_cleanup(() => pc2.close());
test_state_change_event(t, pc, const offer1 = await pc2.createOffer({ offerToReceiveAudio: true });
['have-remote-offer', 'stable', 'have-remote-offer']); await pc.setRemoteDescription(offer1);
await pc.setLocalDescription(await pc.createAnswer());
return pc2.createOffer({ offerToReceiveAudio: true }) const offer2 = await pc2.createOffer({ offerToReceiveVideo: true });
.then(offer1 => await pc.setRemoteDescription(offer2);
pc.setRemoteDescription(offer1) assert_session_desc_not_similar(offer1, offer2);
.then(() => pc.createAnswer()) assert_session_desc_similar(pc.remoteDescription, offer2);
.then(answer => pc.setLocalDescription(answer)) assert_session_desc_similar(pc.currentRemoteDescription, offer1);
.then(() => pc2.createOffer({ offerToReceiveVideo: true })) assert_session_desc_similar(pc.pendingRemoteDescription, offer2);
.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);
});
}));
}, 'Calling setRemoteDescription() again after one round of remote-offer/local-answer should succeed'); }, '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 pc = new RTCPeerConnection();
const pc2 = new RTCPeerConnection();
t.add_cleanup(() => pc.close());
t.add_cleanup(() => pc2.close());
test_state_change_event(t, pc, const offer = await pc.createOffer({ offerToReceiveAudio: true });
['have-local-offer', 'stable', 'have-remote-offer']); await pc.setLocalDescription(offer);
await pc2.setRemoteDescription(offer);
return pc.createOffer({ offerToReceiveAudio: true }) const answer = await pc2.createAnswer();
.then(offer => await pc2.setLocalDescription(answer);
pc.setLocalDescription(offer) await pc.setRemoteDescription(answer);
.then(() => generateAnswer(offer))) await pc.setRemoteDescription(await pc2.createOffer());
.then(answer => assert_equals(pc.remoteDescription.sdp, pc.pendingRemoteDescription.sdp);
pc.setRemoteDescription(answer) assert_session_desc_similar(pc.remoteDescription, offer);
.then(() => generateOffer({ pc, data: true })) assert_session_desc_similar(pc.currentRemoteDescription, answer);
.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);
})));
}, 'Switching role from offerer to answerer after going back to stable state should succeed'); }, '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.index, updatedItem.type,
updatedItem.guid, item.parentGuid, updatedItem.guid, item.parentGuid,
updatedItem.parentGuid, updatedItem.parentGuid,
updatedItem.source ]); updatedItem.source,
updatedItem.url && updatedItem.url.href ]);
} }
// Remove non-enumerable properties. // Remove non-enumerable properties.
@ -1200,7 +1201,7 @@ var Bookmarks = Object.freeze({
i, child.type, i, child.type,
child.guid, child.parentGuid, child.guid, child.parentGuid,
child.parentGuid, child.parentGuid,
source ]); source, child.url && child.url.href ]);
} }
})(); })();
}, },

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

@ -1447,10 +1447,11 @@ class SyncedBookmarksMirror {
let movedItemRows = await this.db.execute(` let movedItemRows = await this.db.execute(`
SELECT b.id, b.guid, b.type, p.id AS newParentId, c.oldParentId, SELECT b.id, b.guid, b.type, p.id AS newParentId, c.oldParentId,
p.guid AS newParentGuid, c.oldParentGuid, p.guid AS newParentGuid, c.oldParentGuid,
b.position AS newPosition, c.oldPosition b.position AS newPosition, c.oldPosition, h.url
FROM itemsMoved c FROM itemsMoved c
JOIN moz_bookmarks b ON b.id = c.itemId JOIN moz_bookmarks b ON b.id = c.itemId
JOIN moz_bookmarks p ON p.id = b.parent 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`); ORDER BY c.level, newParentId, newPosition`);
for await (let row of yieldingIterator(movedItemRows)) { for await (let row of yieldingIterator(movedItemRows)) {
let info = { let info = {
@ -1463,6 +1464,7 @@ class SyncedBookmarksMirror {
oldParentGuid: row.getResultByName("oldParentGuid"), oldParentGuid: row.getResultByName("oldParentGuid"),
newPosition: row.getResultByName("newPosition"), newPosition: row.getResultByName("newPosition"),
oldPosition: row.getResultByName("oldPosition"), oldPosition: row.getResultByName("oldPosition"),
urlHref: row.getResultByName("url"),
}; };
observersToNotify.noteItemMoved(info); observersToNotify.noteItemMoved(info);
} }
@ -4603,7 +4605,7 @@ class BookmarkObserverRecorder {
isTagging: false, isTagging: false,
args: [info.id, info.oldParentId, info.oldPosition, info.newParentId, args: [info.id, info.oldParentId, info.oldPosition, info.newParentId,
info.newPosition, info.type, info.guid, info.oldParentGuid, 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 * @param aSource
* A change source constant from nsINavBookmarksService::SOURCE_*, * A change source constant from nsINavBookmarksService::SOURCE_*,
* passed to the method that notifies the observer. * passed to the method that notifies the observer.
* @param aURI
* The URI for this bookmark.
*/ */
void onItemMoved(in long long aItemId, void onItemMoved(in long long aItemId,
in long long aOldParentId, in long long aOldParentId,
@ -256,7 +258,8 @@ interface nsINavBookmarkObserver : nsISupports
in ACString aGuid, in ACString aGuid,
in ACString aOldParentGuid, in ACString aOldParentGuid,
in ACString aNewParentGuid, 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& aGUID,
const nsACString& aOldParentGUID, const nsACString& aOldParentGUID,
const nsACString& aNewParentGUID, const nsACString& aNewParentGUID,
uint16_t aSource) uint16_t aSource,
const nsACString& aURI)
{ {
// 1. The query cannot be affected by the item's position // 1. The query cannot be affected by the item's position
// 2. For the time being, we cannot optimize this not to update // 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& aGUID,
const nsACString& aOldParentGUID, const nsACString& aOldParentGUID,
const nsACString& aNewParentGUID, const nsACString& aNewParentGUID,
uint16_t aSource) uint16_t aSource,
const nsACString& aURI)
{ {
NS_ASSERTION(aOldParent == mTargetFolderItemId || aNewParent == mTargetFolderItemId, NS_ASSERTION(aOldParent == mTargetFolderItemId || aNewParent == mTargetFolderItemId,
"Got a bookmark message that doesn't belong to us"); "Got a bookmark message that doesn't belong to us");
RESTART_AND_RETURN_IF_ASYNC_PENDING(); 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; uint32_t index;
nsNavHistoryResultNode* node = FindChildById(aItemId, &index); nsNavHistoryResultNode* node = FindChildById(aItemId, &index);
// Bug 1097528. // Bug 1097528.
@ -4010,12 +4022,6 @@ nsNavHistoryFolderResultNode::OnItemMoved(int64_t aItemId,
if (!node && aOldParent == mTargetFolderItemId) if (!node && aOldParent == mTargetFolderItemId)
return NS_OK; 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()) if (!StartIncrementalUpdate())
return NS_OK; // entire container was refreshed for us return NS_OK; // entire container was refreshed for us
@ -4670,25 +4676,26 @@ nsNavHistoryResult::OnItemMoved(int64_t aItemId,
const nsACString& aGUID, const nsACString& aGUID,
const nsACString& aOldParentGUID, const nsACString& aOldParentGUID,
const nsACString& aNewParentGUID, const nsACString& aNewParentGUID,
uint16_t aSource) uint16_t aSource,
const nsACString& aURI)
{ {
ENUMERATE_BOOKMARK_FOLDER_OBSERVERS(aOldParent, ENUMERATE_BOOKMARK_FOLDER_OBSERVERS(aOldParent,
OnItemMoved(aItemId, aOldParent, aOldIndex, aNewParent, aNewIndex, OnItemMoved(aItemId, aOldParent, aOldIndex, aNewParent, aNewIndex,
aItemType, aGUID, aOldParentGUID, aNewParentGUID, aSource)); aItemType, aGUID, aOldParentGUID, aNewParentGUID, aSource, aURI));
if (aNewParent != aOldParent) { if (aNewParent != aOldParent) {
ENUMERATE_BOOKMARK_FOLDER_OBSERVERS(aNewParent, ENUMERATE_BOOKMARK_FOLDER_OBSERVERS(aNewParent,
OnItemMoved(aItemId, aOldParent, aOldIndex, aNewParent, aNewIndex, 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, ENUMERATE_ALL_BOOKMARKS_OBSERVERS(OnItemMoved(aItemId, aOldParent, aOldIndex,
aNewParent, aNewIndex, aNewParent, aNewIndex,
aItemType, aGUID, aItemType, aGUID,
aOldParentGUID, aOldParentGUID,
aNewParentGUID, aSource)); aNewParentGUID, aSource, aURI));
ENUMERATE_HISTORY_OBSERVERS(OnItemMoved(aItemId, aOldParent, aOldIndex, ENUMERATE_HISTORY_OBSERVERS(OnItemMoved(aItemId, aOldParent, aOldIndex,
aNewParent, aNewIndex, aItemType, aNewParent, aNewIndex, aItemType,
aGUID, aOldParentGUID, aGUID, aOldParentGUID,
aNewParentGUID, aSource)); aNewParentGUID, aSource, aURI));
return NS_OK; return NS_OK;
} }

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

@ -193,7 +193,8 @@ add_task(async function update_move_same_folder() {
observer.check([ { name: "onItemMoved", observer.check([ { name: "onItemMoved",
arguments: [ bmItemId, bmParentId, bmOldIndex, bmParentId, bm.index, arguments: [ bmItemId, bmParentId, bmOldIndex, bmParentId, bm.index,
bm.type, bm.guid, bm.parentGuid, bm.parentGuid, 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. // 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", observer.check([ { name: "onItemMoved",
arguments: [ bmItemId, bmParentId, bmOldIndex, bmParentId, bm.index, arguments: [ bmItemId, bmParentId, bmOldIndex, bmParentId, bm.index,
bm.type, bm.guid, bm.parentGuid, bm.parentGuid, 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, bm.index, bm.type, bm.guid,
PlacesUtils.bookmarks.unfiledGuid, PlacesUtils.bookmarks.unfiledGuid,
bm.parentGuid, 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.guid,
child.parentGuid, child.parentGuid,
child.parentGuid, child.parentGuid,
Ci.nsINavBookmarksService.SOURCE_DEFAULT Ci.nsINavBookmarksService.SOURCE_DEFAULT,
child.url
] }); ] });
} }
observer.check(expectedNotifications); observer.check(expectedNotifications);

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

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

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

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

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

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

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

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

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