зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to inbound. a=merge CLOSED TREE
This commit is contained in:
Коммит
fdb6353ff2
|
@ -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()
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче