зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to mozilla-inbound
This commit is contained in:
Коммит
dd36826044
|
@ -1,13 +1,6 @@
|
|||
# Checks run by clang-tidy over Mozilla code.
|
||||
# NOTE: please request review from ehsan when changing this file.
|
||||
|
||||
# The following checks are currently enabled:
|
||||
# * misc-use-override
|
||||
# Adds missing override keywords, and removes override keywords if the final
|
||||
# keyword is present as well.
|
||||
Checks: '-*,misc-use-override'
|
||||
CheckOptions:
|
||||
# Don't touch the virtual keyword!
|
||||
- key: misc-use-override.KeepVirtual
|
||||
value: '1'
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@ StyleInfo::TextIndent(nsAString& aValue)
|
|||
}
|
||||
|
||||
void
|
||||
StyleInfo::Margin(css::Side aSide, nsAString& aValue)
|
||||
StyleInfo::Margin(Side aSide, nsAString& aValue)
|
||||
{
|
||||
MOZ_ASSERT(mElement->GetPrimaryFrame(), " mElement->GetPrimaryFrame() needs to be valid pointer");
|
||||
aValue.Truncate();
|
||||
|
|
|
@ -1,48 +1,48 @@
|
|||
[
|
||||
{
|
||||
"size" : 102421980,
|
||||
"digest" : "f25292aa93dc449e0472eee511c0ac15b5f1a4272ab76cf53ce5d20dc57f29e83da49ae1a9d9e994192647f75e13ae60f75ba2ac3cb9d26d5f5d6cabf88de921",
|
||||
"version" : "gcc 4.9.3",
|
||||
"unpack" : true,
|
||||
"filename" : "gcc.tar.xz",
|
||||
"algorithm" : "sha512"
|
||||
"size": 102421980,
|
||||
"digest": "f25292aa93dc449e0472eee511c0ac15b5f1a4272ab76cf53ce5d20dc57f29e83da49ae1a9d9e994192647f75e13ae60f75ba2ac3cb9d26d5f5d6cabf88de921",
|
||||
"version": "gcc 4.9.3",
|
||||
"unpack": true,
|
||||
"filename": "gcc.tar.xz",
|
||||
"algorithm": "sha512"
|
||||
},
|
||||
{
|
||||
"unpack" : true,
|
||||
"algorithm" : "sha512",
|
||||
"filename" : "sixgill.tar.xz",
|
||||
"hg_id" : "8cb9c3fb039a+ tip",
|
||||
"digest" : "36dc644e24c0aa824975ad8f5c15714445d5cb064d823000c3cb637e885199414d7df551e6b99233f0656dcf5760918192ef04113c486af37f3c489bb93ad029",
|
||||
"size" : 2631908
|
||||
"unpack": true,
|
||||
"algorithm": "sha512",
|
||||
"filename": "sixgill.tar.xz",
|
||||
"hg_id": "8cb9c3fb039a+ tip",
|
||||
"digest": "36dc644e24c0aa824975ad8f5c15714445d5cb064d823000c3cb637e885199414d7df551e6b99233f0656dcf5760918192ef04113c486af37f3c489bb93ad029",
|
||||
"size": 2631908
|
||||
},
|
||||
{
|
||||
"algorithm" : "sha512",
|
||||
"filename" : "gtk3.tar.xz",
|
||||
"setup" : "setup.sh",
|
||||
"unpack" : true,
|
||||
"digest" : "3915f8ec396c56a8a92e6f9695b70f09ce9d1582359d1258e37e3fd43a143bc974410e4cfc27f500e095f34a8956206e0ebf799b7287f0f38def0d5e34ed71c9",
|
||||
"size" : 12072532
|
||||
"algorithm": "sha512",
|
||||
"filename": "gtk3.tar.xz",
|
||||
"setup": "setup.sh",
|
||||
"unpack": true,
|
||||
"digest": "3915f8ec396c56a8a92e6f9695b70f09ce9d1582359d1258e37e3fd43a143bc974410e4cfc27f500e095f34a8956206e0ebf799b7287f0f38def0d5e34ed71c9",
|
||||
"size": 12072532
|
||||
},
|
||||
{
|
||||
"version": "rustc 1.13.0 (2c6933acc 2016-11-07) repack",
|
||||
"size": 68921028,
|
||||
"digest": "9a9ceccc02d4be445ffa64617683419a4f47990b1f2689980ac8db13d6369435ef4af1a3714d77377fb7b3b0ec213856ab7144ff22cbe0881d49aed44d82c0fc",
|
||||
"version": "rustc 1.14.0-beta.2 (e627a2e6e 2016-11-16) repack",
|
||||
"size": 96275316,
|
||||
"digest": "26c11e34df81f5d7ffafc3492df9c6821f644a2e2eda5cfbbcdb1ac23e4ee196007b417c862c60a97bbf66e4be9c801400990938cd3aefec19b1cf9eaf1a9b54",
|
||||
"algorithm": "sha512",
|
||||
"filename": "rustc.tar.xz",
|
||||
"unpack": true
|
||||
},
|
||||
{
|
||||
"algorithm" : "sha512",
|
||||
"filename" : "sccache.tar.bz2",
|
||||
"unpack" : true,
|
||||
"digest" : "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831",
|
||||
"size" : 167175
|
||||
"algorithm": "sha512",
|
||||
"filename": "sccache.tar.bz2",
|
||||
"unpack": true,
|
||||
"digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831",
|
||||
"size": 167175
|
||||
},
|
||||
{
|
||||
"filename" : "moz-tt.tar.bz2",
|
||||
"algorithm" : "sha512",
|
||||
"unpack" : true,
|
||||
"digest" : "2dffe4e5419a0c0c9908dc52b01cc07379a42e2aa8481be7a26bb8750b586b95bbac3fe57e64f5d37b43e206516ea70ad938a2e45858fdcf1e28258e70ae8d8c",
|
||||
"size" : 31078810
|
||||
"filename": "moz-tt.tar.bz2",
|
||||
"algorithm": "sha512",
|
||||
"unpack": true,
|
||||
"digest": "2dffe4e5419a0c0c9908dc52b01cc07379a42e2aa8481be7a26bb8750b586b95bbac3fe57e64f5d37b43e206516ea70ad938a2e45858fdcf1e28258e70ae8d8c",
|
||||
"size": 31078810
|
||||
}
|
||||
]
|
||||
|
|
|
@ -16,9 +16,9 @@
|
|||
"unpack": true
|
||||
},
|
||||
{
|
||||
"version": "rustc 1.13.0 (2c6933acc 2016-11-07) repack",
|
||||
"size": 68921028,
|
||||
"digest": "9a9ceccc02d4be445ffa64617683419a4f47990b1f2689980ac8db13d6369435ef4af1a3714d77377fb7b3b0ec213856ab7144ff22cbe0881d49aed44d82c0fc",
|
||||
"version": "rustc 1.14.0-beta.2 (e627a2e6e 2016-11-16) repack",
|
||||
"size": 96275316,
|
||||
"digest": "26c11e34df81f5d7ffafc3492df9c6821f644a2e2eda5cfbbcdb1ac23e4ee196007b417c862c60a97bbf66e4be9c801400990938cd3aefec19b1cf9eaf1a9b54",
|
||||
"algorithm": "sha512",
|
||||
"filename": "rustc.tar.xz",
|
||||
"unpack": true
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<blocklist lastupdate="1479908016230" xmlns="http://www.mozilla.org/2006/addons-blocklist">
|
||||
<blocklist lastupdate="1479994717581" xmlns="http://www.mozilla.org/2006/addons-blocklist">
|
||||
<emItems>
|
||||
<emItem blockID="i545" id="superlrcs@svenyor.net">
|
||||
<prefs/>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
cursor: default;
|
||||
}
|
||||
|
||||
.contentSearchSuggestionTable:-moz-dir(rtl) {
|
||||
.contentSearchSuggestionTable:dir(rtl) {
|
||||
left: auto;
|
||||
right: 0;
|
||||
}
|
||||
|
@ -115,7 +115,7 @@
|
|||
background-position: right center;
|
||||
}
|
||||
|
||||
.contentSearchOneOffItem:-moz-dir(rtl) {
|
||||
.contentSearchOneOffItem:dir(rtl) {
|
||||
background-position: left center;
|
||||
}
|
||||
|
||||
|
|
|
@ -75,14 +75,6 @@ function runOverflowTests(aEvent) {
|
|||
ok(left(scrollbox) <= firstScrollableLeft, "Scrolled to the start with a triple click " +
|
||||
"(" + left(scrollbox) + " <= " + firstScrollableLeft + ")");
|
||||
|
||||
for (var i = 2; i; i--)
|
||||
EventUtils.synthesizeWheel(scrollbox, 1, 1, { deltaX: -1.0, deltaMode: WheelEvent.DOM_DELTA_LINE });
|
||||
is(left(firstScrollable()), firstScrollableLeft, "Remained at the start with the mouse wheel");
|
||||
|
||||
element = nextRightElement();
|
||||
EventUtils.synthesizeWheel(scrollbox, 1, 1, { deltaX: 1.0, deltaMode: WheelEvent.DOM_DELTA_LINE});
|
||||
isRight(element, "Scrolled one tab to the right with the mouse wheel");
|
||||
|
||||
while (tabs.length > 1)
|
||||
gBrowser.removeTab(tabs[0]);
|
||||
|
||||
|
|
|
@ -91,6 +91,7 @@ BrowserAction.prototype = {
|
|||
view.setAttribute("flex", "1");
|
||||
|
||||
document.getElementById("PanelUI-multiView").appendChild(view);
|
||||
document.addEventListener("popupshowing", this);
|
||||
},
|
||||
|
||||
onDestroyed: document => {
|
||||
|
@ -100,6 +101,7 @@ BrowserAction.prototype = {
|
|||
CustomizableUI.hidePanelForNode(view);
|
||||
view.remove();
|
||||
}
|
||||
document.removeEventListener("popupshowing", this);
|
||||
},
|
||||
|
||||
onCreated: node => {
|
||||
|
@ -227,6 +229,20 @@ BrowserAction.prototype = {
|
|||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case "popupshowing":
|
||||
const menu = event.target;
|
||||
const trigger = menu.triggerNode;
|
||||
const node = window.document.getElementById(this.id);
|
||||
|
||||
if (menu.localName === "menupopup" && node && isAncestorOrSelf(node, trigger)) {
|
||||
global.actionContextMenu({
|
||||
extension: this.extension,
|
||||
onBrowserAction: true,
|
||||
menu: menu,
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@ var {
|
|||
IconDetails,
|
||||
} = ExtensionUtils;
|
||||
|
||||
const ACTION_MENU_TOP_LEVEL_LIMIT = 6;
|
||||
|
||||
// Map[Extension -> Map[ID -> MenuItem]]
|
||||
// Note: we want to enumerate all the menu items so
|
||||
// this cannot be a weak map.
|
||||
|
@ -30,12 +32,12 @@ var gNextRadioGroupID = 0;
|
|||
// The max length of a menu item's label.
|
||||
var gMaxLabelLength = 64;
|
||||
|
||||
// When a new contextMenu is opened, this function is called and
|
||||
// we populate the |xulMenu| with all the items from extensions
|
||||
// to be displayed. We always clear all the items again when
|
||||
// popuphidden fires.
|
||||
var gMenuBuilder = {
|
||||
build: function(contextData) {
|
||||
// When a new contextMenu is opened, this function is called and
|
||||
// we populate the |xulMenu| with all the items from extensions
|
||||
// to be displayed. We always clear all the items again when
|
||||
// popuphidden fires.
|
||||
build(contextData) {
|
||||
let xulMenu = contextData.menu;
|
||||
xulMenu.addEventListener("popuphidden", this);
|
||||
this.xulMenu = xulMenu;
|
||||
|
@ -75,9 +77,44 @@ var gMenuBuilder = {
|
|||
}
|
||||
},
|
||||
|
||||
// Builds a context menu for browserAction and pageAction buttons.
|
||||
buildActionContextMenu(contextData) {
|
||||
const {menu} = contextData;
|
||||
|
||||
contextData.tab = TabManager.activeTab;
|
||||
contextData.pageUrl = contextData.tab.linkedBrowser.currentURI.spec;
|
||||
|
||||
const root = gRootItems.get(contextData.extension);
|
||||
const children = this.buildChildren(root, contextData);
|
||||
const visible = children.slice(0, ACTION_MENU_TOP_LEVEL_LIMIT);
|
||||
|
||||
if (visible.length) {
|
||||
this.xulMenu = menu;
|
||||
menu.addEventListener("popuphidden", this);
|
||||
|
||||
const separator = menu.ownerDocument.createElement("menuseparator");
|
||||
menu.insertBefore(separator, menu.firstChild);
|
||||
this.itemsToCleanUp.add(separator);
|
||||
|
||||
for (const child of visible) {
|
||||
this.itemsToCleanUp.add(child);
|
||||
menu.insertBefore(child, separator);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
buildElementWithChildren(item, contextData) {
|
||||
let element = this.buildSingleElement(item, contextData);
|
||||
const element = this.buildSingleElement(item, contextData);
|
||||
const children = this.buildChildren(item, contextData);
|
||||
if (children.length) {
|
||||
element.firstChild.append(...children);
|
||||
}
|
||||
return element;
|
||||
},
|
||||
|
||||
buildChildren(item, contextData) {
|
||||
let groupName;
|
||||
let children = [];
|
||||
for (let child of item.children) {
|
||||
if (child.type == "radio" && !child.groupName) {
|
||||
if (!groupName) {
|
||||
|
@ -89,15 +126,10 @@ var gMenuBuilder = {
|
|||
}
|
||||
|
||||
if (child.enabledForContext(contextData)) {
|
||||
let childElement = this.buildElementWithChildren(child, contextData);
|
||||
// Here element must be a menu element and its first child
|
||||
// is a menupopup, we have to append its children to this
|
||||
// menupopup.
|
||||
element.firstChild.appendChild(childElement);
|
||||
children.push(this.buildElementWithChildren(child, contextData));
|
||||
}
|
||||
}
|
||||
|
||||
return element;
|
||||
return children;
|
||||
},
|
||||
|
||||
removeTopLevelMenuIfNeeded(element) {
|
||||
|
@ -198,7 +230,7 @@ var gMenuBuilder = {
|
|||
return element;
|
||||
},
|
||||
|
||||
handleEvent: function(event) {
|
||||
handleEvent(event) {
|
||||
if (this.xulMenu != event.target || event.type != "popuphidden") {
|
||||
return;
|
||||
}
|
||||
|
@ -215,6 +247,11 @@ var gMenuBuilder = {
|
|||
itemsToCleanUp: new Set(),
|
||||
};
|
||||
|
||||
// Called from pageAction or browserAction popup.
|
||||
global.actionContextMenu = function(contextData) {
|
||||
gMenuBuilder.buildActionContextMenu(contextData);
|
||||
};
|
||||
|
||||
function contextMenuObserver(subject, topic, data) {
|
||||
subject = subject.wrappedJSObject;
|
||||
gMenuBuilder.build(subject);
|
||||
|
@ -255,6 +292,14 @@ function getContexts(contextData) {
|
|||
contexts.add("audio");
|
||||
}
|
||||
|
||||
if (contextData.onPageAction) {
|
||||
contexts.add("page_action");
|
||||
}
|
||||
|
||||
if (contextData.onBrowserAction) {
|
||||
contexts.add("browser_action");
|
||||
}
|
||||
|
||||
if (contexts.size == 1) {
|
||||
contexts.add("page");
|
||||
}
|
||||
|
|
|
@ -119,11 +119,8 @@ PageAction.prototype = {
|
|||
button.id = this.id;
|
||||
button.setAttribute("class", "urlbar-icon");
|
||||
|
||||
button.addEventListener("click", event => { // eslint-disable-line mozilla/balanced-listeners
|
||||
if (event.button == 0) {
|
||||
this.handleClick(window);
|
||||
}
|
||||
});
|
||||
button.addEventListener("click", this); // eslint-disable-line mozilla/balanced-listeners
|
||||
document.addEventListener("popupshowing", this);
|
||||
|
||||
document.getElementById("urlbar-icons").appendChild(button);
|
||||
|
||||
|
@ -156,6 +153,31 @@ PageAction.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
handleEvent(event) {
|
||||
const window = event.target.ownerDocument.defaultView;
|
||||
|
||||
switch (event.type) {
|
||||
case "click":
|
||||
if (event.button === 0) {
|
||||
this.handleClick(window);
|
||||
}
|
||||
break;
|
||||
|
||||
case "popupshowing":
|
||||
const menu = event.target;
|
||||
const trigger = menu.triggerNode;
|
||||
|
||||
if (menu.localName === "menupopup" && trigger && trigger.id === this.id) {
|
||||
global.actionContextMenu({
|
||||
extension: this.extension,
|
||||
onPageAction: true,
|
||||
menu: menu,
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
// Handles a click event on the page action button for the given
|
||||
// window.
|
||||
// If the page action has a |popup| property, a panel is opened to
|
||||
|
@ -192,6 +214,7 @@ PageAction.prototype = {
|
|||
for (let window of WindowListManager.browserWindows()) {
|
||||
if (this.buttons.has(window)) {
|
||||
this.buttons.get(window).remove();
|
||||
window.removeEventListener("popupshowing", this);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -33,6 +33,7 @@ support-files =
|
|||
[browser_ext_commands_onCommand.js]
|
||||
[browser_ext_contentscript_connect.js]
|
||||
[browser_ext_contextMenus.js]
|
||||
[browser_ext_contextMenus_actionMenus.js]
|
||||
[browser_ext_contextMenus_checkboxes.js]
|
||||
[browser_ext_contextMenus_icons.js]
|
||||
[browser_ext_contextMenus_onclick.js]
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
/* vim: set sts=2 sw=2 et tw=80: */
|
||||
"use strict";
|
||||
|
||||
var {AppConstants} = Cu.import("resource://gre/modules/AppConstants.jsm");
|
||||
|
||||
add_task(function* () {
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
/* 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";
|
||||
|
||||
add_task(function* () {
|
||||
const manifest = {
|
||||
page_action: {},
|
||||
browser_action: {},
|
||||
permissions: ["contextMenus"],
|
||||
};
|
||||
|
||||
async function background() {
|
||||
const contexts = ["page_action", "browser_action"];
|
||||
|
||||
const parentId = browser.contextMenus.create({contexts, title: "parent"});
|
||||
await browser.contextMenus.create({contexts, parentId, title: "click A"});
|
||||
await browser.contextMenus.create({contexts, parentId, title: "click B"});
|
||||
|
||||
for (let i = 1; i < 9; i++) {
|
||||
await browser.contextMenus.create({contexts, title: `click ${i}`});
|
||||
}
|
||||
|
||||
browser.contextMenus.onClicked.addListener((info, tab) => {
|
||||
browser.test.sendMessage("click", {info, tab});
|
||||
});
|
||||
|
||||
const [tab] = await browser.tabs.query({active: true});
|
||||
await browser.pageAction.show(tab.id);
|
||||
browser.test.sendMessage("ready", tab.id);
|
||||
}
|
||||
|
||||
const extension = ExtensionTestUtils.loadExtension({manifest, background});
|
||||
const tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "http://example.com/");
|
||||
|
||||
yield extension.startup();
|
||||
const tabId = yield extension.awaitMessage("ready");
|
||||
|
||||
for (const kind of ["page", "browser"]) {
|
||||
const menu = yield openActionContextMenu(extension, kind);
|
||||
const [submenu, second, , , , last, separator] = menu.children;
|
||||
|
||||
is(submenu.tagName, "menu", "Correct submenu type");
|
||||
is(submenu.label, "parent", "Correct submenu title");
|
||||
is(submenu.firstChild.children.length, 2, "Correct number of submenu items");
|
||||
|
||||
is(second.tagName, "menuitem", "Second menu item type is correct");
|
||||
is(second.label, "click 1", "Second menu item title is correct");
|
||||
|
||||
is(last.label, "click 5", "Last menu item title is correct");
|
||||
is(separator.tagName, "menuseparator", "Separator after last menu item");
|
||||
|
||||
yield closeActionContextMenu(last);
|
||||
const {info, tab} = yield extension.awaitMessage("click");
|
||||
is(info.pageUrl, "http://example.com/", "Click info pageUrl is correct");
|
||||
is(tab.id, tabId, "Click event tab ID is correct");
|
||||
}
|
||||
|
||||
yield BrowserTestUtils.removeTab(tab);
|
||||
yield extension.unload();
|
||||
});
|
|
@ -10,13 +10,14 @@
|
|||
* promisePopupShown promisePopupHidden
|
||||
* openContextMenu closeContextMenu
|
||||
* openExtensionContextMenu closeExtensionContextMenu
|
||||
* openActionContextMenu closeActionContextMenu
|
||||
* imageBuffer getListStyleImage getPanelForNode
|
||||
* awaitExtensionPanel awaitPopupResize
|
||||
* promiseContentDimensions alterContent
|
||||
*/
|
||||
|
||||
var {AppConstants} = Cu.import("resource://gre/modules/AppConstants.jsm");
|
||||
var {CustomizableUI} = Cu.import("resource:///modules/CustomizableUI.jsm");
|
||||
const {AppConstants} = Cu.import("resource://gre/modules/AppConstants.jsm");
|
||||
const {CustomizableUI} = Cu.import("resource:///modules/CustomizableUI.jsm");
|
||||
|
||||
// We run tests under two different configurations, from browser.ini and
|
||||
// browser-remote.ini. When running from browser-remote.ini, the tests are
|
||||
|
@ -240,6 +241,30 @@ function* closeExtensionContextMenu(itemToSelect) {
|
|||
yield popupHiddenPromise;
|
||||
}
|
||||
|
||||
function* openActionContextMenu(extension, kind, win = window) {
|
||||
const menu = win.document.getElementById("toolbar-context-menu");
|
||||
const id = `${makeWidgetId(extension.id)}-${kind}-action`;
|
||||
const button = win.document.getElementById(id);
|
||||
SetPageProxyState("valid");
|
||||
|
||||
const shown = BrowserTestUtils.waitForEvent(menu, "popupshown");
|
||||
EventUtils.synthesizeMouseAtCenter(button, {type: "contextmenu"}, win);
|
||||
yield shown;
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
function closeActionContextMenu(itemToSelect, win = window) {
|
||||
const menu = win.document.getElementById("toolbar-context-menu");
|
||||
const hidden = BrowserTestUtils.waitForEvent(menu, "popuphidden");
|
||||
if (itemToSelect) {
|
||||
EventUtils.synthesizeMouseAtCenter(itemToSelect, {}, win);
|
||||
} else {
|
||||
menu.hidePopup();
|
||||
}
|
||||
return hidden;
|
||||
}
|
||||
|
||||
function getPageActionPopup(extension, win = window) {
|
||||
let panelId = makeWidgetId(extension.id) + "-panel";
|
||||
return win.document.getElementById(panelId);
|
||||
|
|
|
@ -172,7 +172,7 @@ const AutoMigrate = {
|
|||
|
||||
let migrator = MigrationUtils.getMigrator(migratorKey);
|
||||
if (!migrator) {
|
||||
throw new Error("Migrator specified or a default was found, but the migrator object is not available.");
|
||||
throw new Error("Migrator specified or a default was found, but the migrator object is not available (or has no data).");
|
||||
}
|
||||
return {migrator, pickedKey: migratorKey};
|
||||
},
|
||||
|
|
|
@ -36,6 +36,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "WindowsRegistry",
|
|||
var gMigrators = null;
|
||||
var gProfileStartup = null;
|
||||
var gMigrationBundle = null;
|
||||
var gPreviousDefaultBrowserKey = "";
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gAvailableMigratorKeys", function() {
|
||||
if (AppConstants.platform == "win") {
|
||||
|
@ -719,19 +720,29 @@ this.MigrationUtils = Object.freeze({
|
|||
// ourselves as the default (on Windows 7 and below). In that case, check if we
|
||||
// have a registry key that tells us where to go:
|
||||
if (key == "firefox" && AppConstants.isPlatformAndVersionAtMost("win", "6.2")) {
|
||||
const kRegPath = "Software\\Mozilla\\Firefox";
|
||||
let oldDefault = WindowsRegistry.readRegKey(
|
||||
Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, kRegPath, "OldDefaultBrowserCommand");
|
||||
if (oldDefault) {
|
||||
// Remove the key:
|
||||
WindowsRegistry.removeRegKey(
|
||||
Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, kRegPath, "OldDefaultBrowserCommand");
|
||||
try {
|
||||
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFileWin);
|
||||
file.initWithCommandLine(oldDefault);
|
||||
key = APP_DESC_TO_KEY[file.getVersionInfoField("FileDescription")] || key;
|
||||
} catch (ex) {
|
||||
Cu.reportError("Could not convert old default browser value to description.");
|
||||
// Because we remove the registry key, reading the registry key only works once.
|
||||
// We save the value for subsequent calls to avoid hard-to-trace bugs when multiple
|
||||
// consumers ask for this key.
|
||||
if (gPreviousDefaultBrowserKey) {
|
||||
key = gPreviousDefaultBrowserKey;
|
||||
} else {
|
||||
// We didn't have a saved value, so check the registry.
|
||||
const kRegPath = "Software\\Mozilla\\Firefox";
|
||||
let oldDefault = WindowsRegistry.readRegKey(
|
||||
Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, kRegPath, "OldDefaultBrowserCommand");
|
||||
if (oldDefault) {
|
||||
// Remove the key:
|
||||
WindowsRegistry.removeRegKey(
|
||||
Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, kRegPath, "OldDefaultBrowserCommand");
|
||||
try {
|
||||
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFileWin);
|
||||
file.initWithCommandLine(oldDefault);
|
||||
key = APP_DESC_TO_KEY[file.getVersionInfoField("FileDescription")] || key;
|
||||
// Save the value for future callers.
|
||||
gPreviousDefaultBrowserKey = key;
|
||||
} catch (ex) {
|
||||
Cu.reportError("Could not convert old default browser value to description.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -905,7 +916,7 @@ this.MigrationUtils = Object.freeze({
|
|||
|
||||
if (!isRefresh && AutoMigrate.enabled) {
|
||||
try {
|
||||
AutoMigrate.migrate(aProfileStartup, aMigratorKey, aProfileToMigrate);
|
||||
AutoMigrate.migrate(aProfileStartup, migratorKey, aProfileToMigrate);
|
||||
return;
|
||||
} catch (ex) {
|
||||
// If automigration failed, continue and show the dialog.
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"version": "clang 3.8.0, libgcc 4.8.5",
|
||||
"size": 140319580,
|
||||
"digest": "34e219d7e8eaffa81710631c34d21355563d06335b3c00851e94c1f42f9098788fded8463dd0f67dd699f77b47a0245dd7aff754943a7a03fb5fd145a808254f",
|
||||
"algorithm": "sha512",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.xz",
|
||||
"unpack": true
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"version": "gcc 4.8.5 + PR64905",
|
||||
"size": 80160264,
|
||||
"digest": "c1a9dc9da289b8528874d16300b9d13a997cec99195bb0bc46ff665216d8535d6d6cb5af6b4b1f2749af6815dab12e703fdb3849014e5c23a70eff351a0baf4e",
|
||||
"algorithm": "sha512",
|
||||
"algorithm": "sha512",
|
||||
"filename": "gcc.tar.xz",
|
||||
"unpack": true
|
||||
},
|
||||
|
@ -16,9 +16,9 @@
|
|||
"unpack": true
|
||||
},
|
||||
{
|
||||
"version": "rustc 1.13.0 (2c6933acc 2016-11-07) repack x86_64+i586",
|
||||
"size": 68921028,
|
||||
"digest": "9a9ceccc02d4be445ffa64617683419a4f47990b1f2689980ac8db13d6369435ef4af1a3714d77377fb7b3b0ec213856ab7144ff22cbe0881d49aed44d82c0fc",
|
||||
"version": "rustc 1.14.0-beta.2 (e627a2e6e 2016-11-16) repack",
|
||||
"size": 96275316,
|
||||
"digest": "26c11e34df81f5d7ffafc3492df9c6821f644a2e2eda5cfbbcdb1ac23e4ee196007b417c862c60a97bbf66e4be9c801400990938cd3aefec19b1cf9eaf1a9b54",
|
||||
"algorithm": "sha512",
|
||||
"filename": "rustc.tar.xz",
|
||||
"unpack": true
|
||||
|
|
|
@ -1,32 +1,32 @@
|
|||
[
|
||||
{
|
||||
"size" : 102421980,
|
||||
"version" : "gcc 4.9.3",
|
||||
"filename" : "gcc.tar.xz",
|
||||
"algorithm" : "sha512",
|
||||
"digest" : "f25292aa93dc449e0472eee511c0ac15b5f1a4272ab76cf53ce5d20dc57f29e83da49ae1a9d9e994192647f75e13ae60f75ba2ac3cb9d26d5f5d6cabf88de921",
|
||||
"unpack" : true
|
||||
"size": 102421980,
|
||||
"version": "gcc 4.9.3",
|
||||
"filename": "gcc.tar.xz",
|
||||
"algorithm": "sha512",
|
||||
"digest": "f25292aa93dc449e0472eee511c0ac15b5f1a4272ab76cf53ce5d20dc57f29e83da49ae1a9d9e994192647f75e13ae60f75ba2ac3cb9d26d5f5d6cabf88de921",
|
||||
"unpack": true
|
||||
},
|
||||
{
|
||||
"digest" : "36dc644e24c0aa824975ad8f5c15714445d5cb064d823000c3cb637e885199414d7df551e6b99233f0656dcf5760918192ef04113c486af37f3c489bb93ad029",
|
||||
"unpack" : true,
|
||||
"algorithm" : "sha512",
|
||||
"filename" : "sixgill.tar.xz",
|
||||
"size" : 2631908,
|
||||
"hg_id" : "8cb9c3fb039a+ tip"
|
||||
"digest": "36dc644e24c0aa824975ad8f5c15714445d5cb064d823000c3cb637e885199414d7df551e6b99233f0656dcf5760918192ef04113c486af37f3c489bb93ad029",
|
||||
"unpack": true,
|
||||
"algorithm": "sha512",
|
||||
"filename": "sixgill.tar.xz",
|
||||
"size": 2631908,
|
||||
"hg_id": "8cb9c3fb039a+ tip"
|
||||
},
|
||||
{
|
||||
"digest" : "3915f8ec396c56a8a92e6f9695b70f09ce9d1582359d1258e37e3fd43a143bc974410e4cfc27f500e095f34a8956206e0ebf799b7287f0f38def0d5e34ed71c9",
|
||||
"unpack" : true,
|
||||
"setup" : "setup.sh",
|
||||
"algorithm" : "sha512",
|
||||
"filename" : "gtk3.tar.xz",
|
||||
"size" : 12072532
|
||||
"digest": "3915f8ec396c56a8a92e6f9695b70f09ce9d1582359d1258e37e3fd43a143bc974410e4cfc27f500e095f34a8956206e0ebf799b7287f0f38def0d5e34ed71c9",
|
||||
"unpack": true,
|
||||
"setup": "setup.sh",
|
||||
"algorithm": "sha512",
|
||||
"filename": "gtk3.tar.xz",
|
||||
"size": 12072532
|
||||
},
|
||||
{
|
||||
"version": "rustc 1.13.0 (2c6933acc 2016-11-07) repack",
|
||||
"size": 68921028,
|
||||
"digest": "9a9ceccc02d4be445ffa64617683419a4f47990b1f2689980ac8db13d6369435ef4af1a3714d77377fb7b3b0ec213856ab7144ff22cbe0881d49aed44d82c0fc",
|
||||
"version": "rustc 1.14.0-beta.2 (e627a2e6e 2016-11-16) repack",
|
||||
"size": 96275316,
|
||||
"digest": "26c11e34df81f5d7ffafc3492df9c6821f644a2e2eda5cfbbcdb1ac23e4ee196007b417c862c60a97bbf66e4be9c801400990938cd3aefec19b1cf9eaf1a9b54",
|
||||
"algorithm": "sha512",
|
||||
"filename": "rustc.tar.xz",
|
||||
"unpack": true
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"version": "gcc 4.8.5 + PR64905",
|
||||
"size": 80160264,
|
||||
"digest": "c1a9dc9da289b8528874d16300b9d13a997cec99195bb0bc46ff665216d8535d6d6cb5af6b4b1f2749af6815dab12e703fdb3849014e5c23a70eff351a0baf4e",
|
||||
"algorithm": "sha512",
|
||||
"algorithm": "sha512",
|
||||
"filename": "gcc.tar.xz",
|
||||
"unpack": true
|
||||
},
|
||||
|
@ -16,9 +16,9 @@
|
|||
"unpack": true
|
||||
},
|
||||
{
|
||||
"version": "rustc 1.13.0 (2c6933acc 2016-11-07) repack",
|
||||
"size": 68921028,
|
||||
"digest": "9a9ceccc02d4be445ffa64617683419a4f47990b1f2689980ac8db13d6369435ef4af1a3714d77377fb7b3b0ec213856ab7144ff22cbe0881d49aed44d82c0fc",
|
||||
"version": "rustc 1.14.0-beta.2 (e627a2e6e 2016-11-16) repack",
|
||||
"size": 96275316,
|
||||
"digest": "26c11e34df81f5d7ffafc3492df9c6821f644a2e2eda5cfbbcdb1ac23e4ee196007b417c862c60a97bbf66e4be9c801400990938cd3aefec19b1cf9eaf1a9b54",
|
||||
"algorithm": "sha512",
|
||||
"filename": "rustc.tar.xz",
|
||||
"unpack": true
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"version": "clang 3.8.0",
|
||||
"size": 133060926,
|
||||
"digest": "aff5ad3ac2d41db19d1ba0df5f97b189a7d7e1b6af8c56e22c2b0cced84d75fa98394ded6a4ba5713652e6684a0a46f47aeccf87991f9e849bf8d7d82e564f6f",
|
||||
"algorithm": "sha512",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.bz2",
|
||||
"unpack": true
|
||||
}
|
||||
|
|
|
@ -8,18 +8,18 @@
|
|||
"unpack": true
|
||||
},
|
||||
{
|
||||
"size": 3008804,
|
||||
"visibility": "public",
|
||||
"digest": "ba6937f14f3d8b26dcb2d39490dee6b0a8afb60f672f5debb71d7b62c1ec52103201b4b1a3d258f945567de531384b36ddb2ce4aa73dc63d72305b11c146847c",
|
||||
"algorithm": "sha512",
|
||||
"size": 3008804,
|
||||
"visibility": "public",
|
||||
"digest": "ba6937f14f3d8b26dcb2d39490dee6b0a8afb60f672f5debb71d7b62c1ec52103201b4b1a3d258f945567de531384b36ddb2ce4aa73dc63d72305b11c146847c",
|
||||
"algorithm": "sha512",
|
||||
"unpack": true,
|
||||
"filename": "cctools.tar.gz"
|
||||
},
|
||||
{
|
||||
"size": 35215976,
|
||||
"visibility": "internal",
|
||||
"digest": "8be736545ddab25ebded188458ce974d5c9a7e29f3c50d2ebfbcb878f6aff853dd2ff5a3528bdefc64396a10101a1b50fd2fe52000140df33643cebe1ea759da",
|
||||
"algorithm": "sha512",
|
||||
"size": 35215976,
|
||||
"visibility": "internal",
|
||||
"digest": "8be736545ddab25ebded188458ce974d5c9a7e29f3c50d2ebfbcb878f6aff853dd2ff5a3528bdefc64396a10101a1b50fd2fe52000140df33643cebe1ea759da",
|
||||
"algorithm": "sha512",
|
||||
"unpack": true,
|
||||
"filename": "MacOSX10.7.sdk.tar.bz2"
|
||||
},
|
||||
|
@ -33,25 +33,25 @@
|
|||
"size": 1020700
|
||||
},
|
||||
{
|
||||
"size": 57060,
|
||||
"visibility": "public",
|
||||
"digest": "9649ca595f4cf088d118da26201f92cc94cda7af49c7c48112ee31cd13c83b2935b3e145de9dd78060cff2480b4c2e7ff5fb24235876956fed13c87852071998",
|
||||
"algorithm": "sha512",
|
||||
"size": 57060,
|
||||
"visibility": "public",
|
||||
"digest": "9649ca595f4cf088d118da26201f92cc94cda7af49c7c48112ee31cd13c83b2935b3e145de9dd78060cff2480b4c2e7ff5fb24235876956fed13c87852071998",
|
||||
"algorithm": "sha512",
|
||||
"unpack": true,
|
||||
"filename": "dmg.tar.xz"
|
||||
},
|
||||
{
|
||||
"size": 188880,
|
||||
"visibility": "public",
|
||||
"digest": "1ffddd43efb03aed897ee42035d9d8d758a8d66ab6c867599ef755e1a586768fc22011ce03698af61454920b00fe8bed08c9a681e7bd324d7f8f78c026c83943",
|
||||
"algorithm": "sha512",
|
||||
"size": 188880,
|
||||
"visibility": "public",
|
||||
"digest": "1ffddd43efb03aed897ee42035d9d8d758a8d66ab6c867599ef755e1a586768fc22011ce03698af61454920b00fe8bed08c9a681e7bd324d7f8f78c026c83943",
|
||||
"algorithm": "sha512",
|
||||
"unpack": true,
|
||||
"filename": "genisoimage.tar.xz"
|
||||
},
|
||||
{
|
||||
"version": "rustc 1.13.0 (2c6933acc 2016-11-07) repack",
|
||||
"size": 119642844,
|
||||
"digest": "b219c07d78819b9ea930024205ac905f89b958948fbfb3146864724bf4994401911fdb1636d6f32e46de1f587f4ee9ae7975a886bfacc5f0bde8ea5955b4e42a",
|
||||
"version": "rustc 1.14.0-beta.2 (e627a2e6e 2016-11-16) repack",
|
||||
"size": 152410204,
|
||||
"digest": "951653b08e68f89c1f9ebc236f1f91dee18d30bdc53e374bd55beacd5a67cc545e95bd1655d3c8d9a473513aaaec2281952f16585e8ed34a734ee6517ac17e49",
|
||||
"algorithm": "sha512",
|
||||
"filename": "rustc.tar.xz",
|
||||
"unpack": true
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
"filename": "mozmake.exe"
|
||||
},
|
||||
{
|
||||
"version": "rustc 1.13.0 (2c6933acc 2016-11-07) repack",
|
||||
"size": 58997576,
|
||||
"digest": "be97bb7f60fea39b9b0411b7ce247036a9373b01ed8cc60f30ed3c6254473ab7ef1881f222f10845253e0608c6f3d21add0871d0485d9de413297906d5c5409c",
|
||||
"version": "rustc 1.14.0-beta.2 (e627a2e6e 2016-11-16) repack",
|
||||
"size": 64146480,
|
||||
"digest": "d3a43d755a9819029421ef7f0f2997f79d4e327b38715878e097b633f858e7fb36882eef19ca59751487cef89692f8d082babf1b8196342e75bfe6b1ad9d8e7f",
|
||||
"algorithm": "sha512",
|
||||
"filename": "rustc.tar.bz2",
|
||||
"unpack": true
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
"filename": "mozmake.exe"
|
||||
},
|
||||
{
|
||||
"version": "rustc 1.13.0 (2c6933acc 2016-11-07) repack",
|
||||
"size": 58997576,
|
||||
"digest": "be97bb7f60fea39b9b0411b7ce247036a9373b01ed8cc60f30ed3c6254473ab7ef1881f222f10845253e0608c6f3d21add0871d0485d9de413297906d5c5409c",
|
||||
"version": "rustc 1.14.0-beta.2 (e627a2e6e 2016-11-16) repack",
|
||||
"size": 64146480,
|
||||
"digest": "d3a43d755a9819029421ef7f0f2997f79d4e327b38715878e097b633f858e7fb36882eef19ca59751487cef89692f8d082babf1b8196342e75bfe6b1ad9d8e7f",
|
||||
"algorithm": "sha512",
|
||||
"filename": "rustc.tar.bz2",
|
||||
"unpack": true
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
"filename": "mozmake.exe"
|
||||
},
|
||||
{
|
||||
"version": "rustc 1.13.0 (2c6933acc 2016-11-07) repack",
|
||||
"size": 58997576,
|
||||
"digest": "be97bb7f60fea39b9b0411b7ce247036a9373b01ed8cc60f30ed3c6254473ab7ef1881f222f10845253e0608c6f3d21add0871d0485d9de413297906d5c5409c",
|
||||
"version": "rustc 1.14.0-beta.2 (e627a2e6e 2016-11-16) repack",
|
||||
"size": 64146480,
|
||||
"digest": "d3a43d755a9819029421ef7f0f2997f79d4e327b38715878e097b633f858e7fb36882eef19ca59751487cef89692f8d082babf1b8196342e75bfe6b1ad9d8e7f",
|
||||
"algorithm": "sha512",
|
||||
"filename": "rustc.tar.bz2",
|
||||
"unpack": true
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
"filename": "mozmake.exe"
|
||||
},
|
||||
{
|
||||
"version": "rustc 1.13.0 (2c6933acc 2016-11-07) repack",
|
||||
"size": 63966131,
|
||||
"digest": "a431492ca5ae3454e7d5de3962ff0b40d96f69a9046428a1fe310397a5dda9ba2f6b697958e8386b119d56b700563ffe1b58c63f84b527b2df320893306854cf",
|
||||
"version": "rustc 1.14.0-beta.2 (e627a2e6e 2016-11-16) repack",
|
||||
"size": 69780370,
|
||||
"digest": "9eb86b4345f974470efbaddadf9f462af019be3ea4318471eea3c6dbe6e4c2108af7c6d6130b396ecb6550aa105ab8102dfa85b8964ebc1611061e485581cbf3",
|
||||
"algorithm": "sha512",
|
||||
"visibility": "public",
|
||||
"filename": "rustc.tar.bz2",
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
"filename": "mozmake.exe"
|
||||
},
|
||||
{
|
||||
"version": "rustc 1.13.0 (2c6933acc 2016-11-07) repack",
|
||||
"size": 63966131,
|
||||
"digest": "a431492ca5ae3454e7d5de3962ff0b40d96f69a9046428a1fe310397a5dda9ba2f6b697958e8386b119d56b700563ffe1b58c63f84b527b2df320893306854cf",
|
||||
"version": "rustc 1.14.0-beta.2 (e627a2e6e 2016-11-16) repack",
|
||||
"size": 69780370,
|
||||
"digest": "9eb86b4345f974470efbaddadf9f462af019be3ea4318471eea3c6dbe6e4c2108af7c6d6130b396ecb6550aa105ab8102dfa85b8964ebc1611061e485581cbf3",
|
||||
"algorithm": "sha512",
|
||||
"visibility": "public",
|
||||
"filename": "rustc.tar.bz2",
|
||||
|
|
|
@ -17,6 +17,6 @@ body {
|
|||
background-size: 16px, 16px;
|
||||
}
|
||||
|
||||
#defaultEngine:-moz-dir(rtl) {
|
||||
#defaultEngine:dir(rtl) {
|
||||
background-position: calc(100% - 5px) center;
|
||||
}
|
||||
|
|
|
@ -71,6 +71,14 @@ set_config('MOZ_BUILD_ROOT', delayed_getattr(check_build_environment,
|
|||
'topobjdir'))
|
||||
set_config('DIST', delayed_getattr(check_build_environment, 'dist'))
|
||||
|
||||
add_old_configure_assignment(
|
||||
'_topsrcdir', delayed_getattr(check_build_environment, 'topsrcdir'))
|
||||
add_old_configure_assignment(
|
||||
'_objdir', delayed_getattr(check_build_environment, 'topobjdir'))
|
||||
add_old_configure_assignment(
|
||||
'MOZ_BUILD_ROOT', delayed_getattr(check_build_environment, 'topobjdir'))
|
||||
add_old_configure_assignment(
|
||||
'DIST', delayed_getattr(check_build_environment, 'dist'))
|
||||
|
||||
option(env='MOZ_AUTOMATION', help='Enable options for automated builds')
|
||||
set_config('MOZ_AUTOMATION', depends_if('MOZ_AUTOMATION')(lambda x: True))
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.notificationbox .details:-moz-dir(rtl)
|
||||
.notificationbox .notificationInner:-moz-dir(rtl) {
|
||||
.notificationbox .details:dir(rtl)
|
||||
.notificationbox .notificationInner:dir(rtl) {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
|
|
|
@ -915,26 +915,27 @@ KeyframeEffectReadOnly::GetKeyframes(JSContext*& aCx,
|
|||
|
||||
JS::Rooted<JSObject*> keyframeObject(aCx, &keyframeJSValue.toObject());
|
||||
for (const PropertyValuePair& propertyValue : keyframe.mPropertyValues) {
|
||||
|
||||
const char* name = nsCSSProps::PropertyIDLName(propertyValue.mProperty);
|
||||
|
||||
// nsCSSValue::AppendToString does not accept shorthands properties but
|
||||
// works with token stream values if we pass eCSSProperty_UNKNOWN as
|
||||
// the property.
|
||||
nsCSSPropertyID propertyForSerializing =
|
||||
nsCSSProps::IsShorthand(propertyValue.mProperty)
|
||||
? eCSSProperty_UNKNOWN
|
||||
: propertyValue.mProperty;
|
||||
|
||||
nsAutoString stringValue;
|
||||
if (propertyValue.mServoDeclarationBlock) {
|
||||
// FIXME: When we support animations for custom properties on servo, we
|
||||
// should pass the flag to Servo_DeclarationBlock_SerializeOneValue.
|
||||
// Now, we pass false to simplify it.
|
||||
nsIAtom* atom = nsCSSProps::AtomForProperty(propertyValue.mProperty);
|
||||
Servo_DeclarationBlock_SerializeOneValue(
|
||||
propertyValue.mServoDeclarationBlock, &stringValue);
|
||||
propertyValue.mServoDeclarationBlock, atom, false, &stringValue);
|
||||
} else {
|
||||
// nsCSSValue::AppendToString does not accept shorthands properties but
|
||||
// works with token stream values if we pass eCSSProperty_UNKNOWN as
|
||||
// the property.
|
||||
nsCSSPropertyID propertyForSerializing =
|
||||
nsCSSProps::IsShorthand(propertyValue.mProperty)
|
||||
? eCSSProperty_UNKNOWN
|
||||
: propertyValue.mProperty;
|
||||
propertyValue.mValue.AppendToString(
|
||||
propertyForSerializing, stringValue, nsCSSValue::eNormalized);
|
||||
}
|
||||
|
||||
const char* name = nsCSSProps::PropertyIDLName(propertyValue.mProperty);
|
||||
JS::Rooted<JS::Value> value(aCx);
|
||||
if (!ToJSValue(aCx, stringValue, &value) ||
|
||||
!JS_DefineProperty(aCx, keyframeObject, name, value,
|
||||
|
|
|
@ -295,7 +295,7 @@ DOMIntersectionObserver::Update(nsIDocument* aDocument, DOMHighResTimeStamp time
|
|||
|
||||
nsMargin rootMargin;
|
||||
NS_FOR_CSS_SIDES(side) {
|
||||
nscoord basis = side == NS_SIDE_TOP || side == NS_SIDE_BOTTOM ?
|
||||
nscoord basis = side == eSideTop || side == eSideBottom ?
|
||||
rootRect.height : rootRect.width;
|
||||
nsCSSValue value = mRootMargin.*nsCSSRect::sides[side];
|
||||
nsStyleCoord coord;
|
||||
|
|
|
@ -36,6 +36,7 @@ GK_ATOM(moz, "_moz")
|
|||
GK_ATOM(mozframetype, "mozframetype")
|
||||
GK_ATOM(_moz_abspos, "_moz_abspos")
|
||||
GK_ATOM(_moz_activated, "_moz_activated")
|
||||
GK_ATOM(_moz_anonclass, "_moz_anonclass")
|
||||
GK_ATOM(_moz_resizing, "_moz_resizing")
|
||||
GK_ATOM(mozallowfullscreen, "mozallowfullscreen")
|
||||
GK_ATOM(moztype, "_moz-type")
|
||||
|
|
|
@ -691,6 +691,114 @@ private:
|
|||
bool mCancelled = false;
|
||||
};
|
||||
|
||||
class HTMLMediaElement::ErrorSink
|
||||
{
|
||||
public:
|
||||
explicit ErrorSink(HTMLMediaElement* aOwner)
|
||||
: mOwner(aOwner)
|
||||
{
|
||||
MOZ_ASSERT(mOwner);
|
||||
}
|
||||
|
||||
void SetError(uint16_t aErrorCode, const nsACString& aErrorDetails)
|
||||
{
|
||||
// Since we have multiple paths calling into DecodeError, e.g.
|
||||
// MediaKeys::Terminated and EMEH264Decoder::Error. We should take the 1st
|
||||
// one only in order not to fire multiple 'error' events.
|
||||
if (mError) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsValidErrorCode(aErrorCode)) {
|
||||
NS_ASSERTION(false, "Undefined MediaError codes!");
|
||||
return;
|
||||
}
|
||||
|
||||
mError = new MediaError(mOwner, aErrorCode, aErrorDetails);
|
||||
if (CanOwnerPlayUnsupportedTypeMedia()) {
|
||||
mOwner->ChangeNetworkState(nsIDOMHTMLMediaElement::NETWORK_NO_SOURCE);
|
||||
OpenUnsupportedMediaForOwner();
|
||||
} else {
|
||||
mOwner->DispatchAsyncEvent(NS_LITERAL_STRING("error"));
|
||||
if (mOwner->ReadyState() == HAVE_NOTHING &&
|
||||
aErrorCode == MEDIA_ERR_ABORTED) {
|
||||
// https://html.spec.whatwg.org/multipage/embedded-content.html#media-data-processing-steps-list
|
||||
// "If the media data fetching process is aborted by the user"
|
||||
mOwner->DispatchAsyncEvent(NS_LITERAL_STRING("abort"));
|
||||
mOwner->ChangeNetworkState(nsIDOMHTMLMediaElement::NETWORK_EMPTY);
|
||||
mOwner->DispatchAsyncEvent(NS_LITERAL_STRING("emptied"));
|
||||
} else if (aErrorCode == MEDIA_ERR_SRC_NOT_SUPPORTED) {
|
||||
mOwner->ChangeNetworkState(nsIDOMHTMLMediaElement::NETWORK_NO_SOURCE);
|
||||
} else {
|
||||
mOwner->ChangeNetworkState(nsIDOMHTMLMediaElement::NETWORK_IDLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ResetError()
|
||||
{
|
||||
mError = nullptr;
|
||||
}
|
||||
|
||||
void NotifyPlayStarted()
|
||||
{
|
||||
if (CanOwnerPlayUnsupportedTypeMedia()) {
|
||||
OpenUnsupportedMediaForOwner();
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<MediaError> mError;
|
||||
|
||||
private:
|
||||
bool IsValidErrorCode(const uint16_t& aErrorCode) const
|
||||
{
|
||||
return (aErrorCode == MEDIA_ERR_DECODE ||
|
||||
aErrorCode == MEDIA_ERR_NETWORK ||
|
||||
aErrorCode == MEDIA_ERR_ABORTED ||
|
||||
aErrorCode == MEDIA_ERR_SRC_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
bool CanOwnerPlayUnsupportedTypeMedia() const
|
||||
{
|
||||
#if defined(MOZ_WIDGET_ANDROID)
|
||||
// On Fennec, we will user an external app to open unsupported media types.
|
||||
if (!Preferences::GetBool("media.openUnsupportedTypeWithExternalApp")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mError) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t errorCode = mError->Code();
|
||||
if (errorCode != MEDIA_ERR_SRC_NOT_SUPPORTED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If media doesn't start playing, we don't need to open it.
|
||||
if (mOwner->Paused()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
void OpenUnsupportedMediaForOwner() const
|
||||
{
|
||||
nsContentUtils::DispatchTrustedEvent(mOwner->OwnerDoc(),
|
||||
static_cast<nsIContent*>(mOwner),
|
||||
NS_LITERAL_STRING("OpenMediaWithExternalApp"),
|
||||
true,
|
||||
true);
|
||||
}
|
||||
|
||||
// Media elememt's life cycle would be longer than error sink, so we use the
|
||||
// raw pointer and this class would only be referenced by media element.
|
||||
HTMLMediaElement* mOwner;
|
||||
};
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(HTMLMediaElement, nsGenericHTMLElement)
|
||||
NS_IMPL_RELEASE_INHERITED(HTMLMediaElement, nsGenericHTMLElement)
|
||||
|
||||
|
@ -705,7 +813,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLMediaElement, nsGenericHTM
|
|||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLoadBlockedDoc)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSourceLoadCandidate)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAudioChannelAgent)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mError)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mErrorSink->mError)
|
||||
for (uint32_t i = 0; i < tmp->mOutputStreams.Length(); ++i) {
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOutputStreams[i].mStream);
|
||||
}
|
||||
|
@ -730,7 +838,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLMediaElement, nsGenericHTMLE
|
|||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mLoadBlockedDoc)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSourceLoadCandidate)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mAudioChannelAgent)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mError)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mErrorSink->mError)
|
||||
for (uint32_t i = 0; i < tmp->mOutputStreams.Length(); ++i) {
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOutputStreams[i].mStream)
|
||||
}
|
||||
|
@ -965,7 +1073,7 @@ void HTMLMediaElement::AbortExistingLoads()
|
|||
DispatchAsyncEvent(NS_LITERAL_STRING("abort"));
|
||||
}
|
||||
|
||||
mError = nullptr;
|
||||
mErrorSink->ResetError();
|
||||
mCurrentPlayRangeStart = -1.0;
|
||||
mLoadedDataFired = false;
|
||||
mAutoplaying = true;
|
||||
|
@ -1026,12 +1134,9 @@ void HTMLMediaElement::NoSupportedMediaSourceError(const nsACString& aErrorDetai
|
|||
if (mDecoder) {
|
||||
ShutdownDecoder();
|
||||
}
|
||||
mError = new MediaError(this, MEDIA_ERR_SRC_NOT_SUPPORTED, aErrorDetails);
|
||||
ChangeNetworkState(nsIDOMHTMLMediaElement::NETWORK_NO_SOURCE);
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("error"));
|
||||
mErrorSink->SetError(MEDIA_ERR_SRC_NOT_SUPPORTED, aErrorDetails);
|
||||
ChangeDelayLoadStatus(false);
|
||||
UpdateAudioChannelPlayingState();
|
||||
OpenUnsupportedMediaWithExtenalAppIfNeeded();
|
||||
}
|
||||
|
||||
typedef void (HTMLMediaElement::*SyncSectionFn)();
|
||||
|
@ -2930,7 +3035,8 @@ HTMLMediaElement::HTMLMediaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNo
|
|||
mDefaultPlaybackStartPosition(0.0),
|
||||
mIsAudioTrackAudible(false),
|
||||
mAudible(IsAudible()),
|
||||
mVisibilityState(Visibility::APPROXIMATELY_NONVISIBLE)
|
||||
mVisibilityState(Visibility::APPROXIMATELY_NONVISIBLE),
|
||||
mErrorSink(new ErrorSink(this))
|
||||
{
|
||||
ErrorResult rv;
|
||||
|
||||
|
@ -3042,6 +3148,8 @@ HTMLMediaElement::Play(ErrorResult& aRv)
|
|||
if (NS_FAILED(rv)) {
|
||||
aRv.Throw(rv);
|
||||
}
|
||||
|
||||
OpenUnsupportedMediaWithExternalAppIfNeeded();
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -3088,10 +3196,6 @@ HTMLMediaElement::PlayInternal()
|
|||
UpdateSrcMediaStreamPlaying();
|
||||
UpdateAudioChannelPlayingState();
|
||||
|
||||
// The check here is to handle the case that the media element starts playing
|
||||
// after it loaded fail. eg. preload the data before playing.
|
||||
OpenUnsupportedMediaWithExtenalAppIfNeeded();
|
||||
|
||||
// We should check audio channel playing state before dispatching any events,
|
||||
// because we don't want to dispatch events for blocked media. For blocked
|
||||
// media, the event would be pending until media is resumed.
|
||||
|
@ -3134,7 +3238,13 @@ NS_IMETHODIMP HTMLMediaElement::Play()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
return PlayInternal();
|
||||
nsresult rv = PlayInternal();
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
OpenUnsupportedMediaWithExternalAppIfNeeded();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
HTMLMediaElement::WakeLockBoolWrapper&
|
||||
|
@ -4429,7 +4539,7 @@ void HTMLMediaElement::DecodeError(const MediaResult& aError)
|
|||
AudioTracks()->EmptyTracks();
|
||||
VideoTracks()->EmptyTracks();
|
||||
if (mIsLoadingFromSourceChildren) {
|
||||
mError = nullptr;
|
||||
mErrorSink->ResetError();
|
||||
if (mSourceLoadCandidate) {
|
||||
DispatchAsyncSourceError(mSourceLoadCandidate);
|
||||
QueueLoadFromSourceTask();
|
||||
|
@ -4456,29 +4566,7 @@ void HTMLMediaElement::LoadAborted()
|
|||
void HTMLMediaElement::Error(uint16_t aErrorCode,
|
||||
const nsACString& aErrorDetails)
|
||||
{
|
||||
NS_ASSERTION(aErrorCode == MEDIA_ERR_DECODE ||
|
||||
aErrorCode == MEDIA_ERR_NETWORK ||
|
||||
aErrorCode == MEDIA_ERR_ABORTED,
|
||||
"Only use MediaError codes!");
|
||||
|
||||
// Since we have multiple paths calling into DecodeError, e.g.
|
||||
// MediaKeys::Terminated and EMEH264Decoder::Error. We should take the 1st
|
||||
// one only in order not to fire multiple 'error' events.
|
||||
if (mError) {
|
||||
return;
|
||||
}
|
||||
mError = new MediaError(this, aErrorCode, aErrorDetails);
|
||||
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("error"));
|
||||
if (mReadyState == HAVE_NOTHING && aErrorCode == MEDIA_ERR_ABORTED) {
|
||||
// https://html.spec.whatwg.org/multipage/embedded-content.html#media-data-processing-steps-list
|
||||
// "If the media data fetching process is aborted by the user"
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("abort"));
|
||||
ChangeNetworkState(nsIDOMHTMLMediaElement::NETWORK_EMPTY);
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("emptied"));
|
||||
} else {
|
||||
ChangeNetworkState(nsIDOMHTMLMediaElement::NETWORK_IDLE);
|
||||
}
|
||||
mErrorSink->SetError(aErrorCode, aErrorDetails);
|
||||
ChangeDelayLoadStatus(false);
|
||||
UpdateAudioChannelPlayingState();
|
||||
}
|
||||
|
@ -4885,7 +4973,7 @@ void HTMLMediaElement::ChangeReadyState(nsMediaReadyState aState)
|
|||
DispatchAsyncEvent(NS_LITERAL_STRING("waiting"));
|
||||
} else if (oldState >= nsIDOMHTMLMediaElement::HAVE_FUTURE_DATA &&
|
||||
mReadyState < nsIDOMHTMLMediaElement::HAVE_FUTURE_DATA &&
|
||||
!Paused() && !Ended() && !mError) {
|
||||
!Paused() && !Ended() && !mErrorSink->mError) {
|
||||
FireTimeUpdate(false);
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("waiting"));
|
||||
}
|
||||
|
@ -4946,7 +5034,8 @@ void HTMLMediaElement::ChangeNetworkState(nsMediaNetworkState aState)
|
|||
mBegun = true;
|
||||
// Start progress notification when entering NETWORK_LOADING.
|
||||
StartProgress();
|
||||
} else if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_IDLE && !mError) {
|
||||
} else if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_IDLE &&
|
||||
!mErrorSink->mError) {
|
||||
// Fire 'suspend' event when entering NETWORK_IDLE and no error presented.
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("suspend"));
|
||||
}
|
||||
|
@ -5646,6 +5735,20 @@ MediaStream* HTMLMediaElement::GetSrcMediaStream() const
|
|||
return mSrcStream->GetPlaybackStream();
|
||||
}
|
||||
|
||||
MediaError*
|
||||
HTMLMediaElement::GetError() const
|
||||
{
|
||||
return mErrorSink->mError;
|
||||
}
|
||||
|
||||
void
|
||||
HTMLMediaElement::OpenUnsupportedMediaWithExternalAppIfNeeded() const
|
||||
{
|
||||
// Error sink would check the error state and other conditions to decide
|
||||
// whether we can open unsupported type media with an external app.
|
||||
mErrorSink->NotifyPlayStarted();
|
||||
}
|
||||
|
||||
void HTMLMediaElement::GetCurrentSpec(nsCString& aString)
|
||||
{
|
||||
if (mLoadingSrc) {
|
||||
|
@ -5796,7 +5899,7 @@ bool
|
|||
HTMLMediaElement::IsPlayingThroughTheAudioChannel() const
|
||||
{
|
||||
// If we have an error, we are not playing.
|
||||
if (mError) {
|
||||
if (mErrorSink->mError) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -5857,11 +5960,6 @@ HTMLMediaElement::UpdateAudioChannelPlayingState(bool aForcePlaying)
|
|||
void
|
||||
HTMLMediaElement::NotifyAudioChannelAgent(bool aPlaying)
|
||||
{
|
||||
// This is needed to pass nsContentUtils::IsCallerChrome().
|
||||
// AudioChannel API should not called from content but it can happen that
|
||||
// this method has some content JS in its stack.
|
||||
AutoNoJSAPI nojsapi;
|
||||
|
||||
if (aPlaying) {
|
||||
// The reason we don't call NotifyStartedPlaying after the media element
|
||||
// really becomes audible is because there is another case needs to block
|
||||
|
@ -6555,40 +6653,6 @@ HTMLMediaElement::MaybeNotifyMediaResumed(SuspendTypes aSuspend)
|
|||
}));
|
||||
}
|
||||
|
||||
bool
|
||||
HTMLMediaElement::HaveFailedWithSourceNotSupportedError() const
|
||||
{
|
||||
if (!mError) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t errorCode = mError->Code();
|
||||
return (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_NO_SOURCE &&
|
||||
errorCode == MEDIA_ERR_SRC_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
void
|
||||
HTMLMediaElement::OpenUnsupportedMediaWithExtenalAppIfNeeded()
|
||||
{
|
||||
if (!Preferences::GetBool("media.openUnsupportedTypeWithExternalApp")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!HaveFailedWithSourceNotSupportedError()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If media doesn't start playing, we don't need to open it.
|
||||
if (mPaused) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsContentUtils::DispatchTrustedEvent(OwnerDoc(), static_cast<nsIContent*>(this),
|
||||
NS_LITERAL_STRING("OpenMediaWithExternalApp"),
|
||||
true,
|
||||
true);
|
||||
}
|
||||
|
||||
bool
|
||||
HTMLMediaElement::ShouldElementBePaused()
|
||||
{
|
||||
|
|
|
@ -421,10 +421,7 @@ public:
|
|||
|
||||
// WebIDL
|
||||
|
||||
MediaError* GetError() const
|
||||
{
|
||||
return mError;
|
||||
}
|
||||
MediaError* GetError() const;
|
||||
|
||||
// XPCOM GetSrc() is OK
|
||||
void SetSrc(const nsAString& aSrc, ErrorResult& aRv)
|
||||
|
@ -761,6 +758,7 @@ protected:
|
|||
virtual ~HTMLMediaElement();
|
||||
|
||||
class ChannelLoader;
|
||||
class ErrorSink;
|
||||
class MediaLoadListener;
|
||||
class MediaStreamTracksAvailableCallback;
|
||||
class MediaStreamTrackListener;
|
||||
|
@ -1283,9 +1281,6 @@ protected:
|
|||
bool IsTabActivated() const;
|
||||
|
||||
bool IsAudible() const;
|
||||
bool HaveFailedWithSourceNotSupportedError() const;
|
||||
|
||||
void OpenUnsupportedMediaWithExtenalAppIfNeeded();
|
||||
|
||||
// It's used for fennec only, send the notification when the user resumes the
|
||||
// media which was paused by media control.
|
||||
|
@ -1296,6 +1291,10 @@ protected:
|
|||
// For nsAsyncEventRunner.
|
||||
nsresult DispatchEvent(const nsAString& aName);
|
||||
|
||||
// Open unsupported types media with the external app when the media element
|
||||
// triggers play() after loaded fail. eg. preload the data before start play.
|
||||
void OpenUnsupportedMediaWithExternalAppIfNeeded() const;
|
||||
|
||||
// The current decoder. Load() has been called on this decoder.
|
||||
// At most one of mDecoder and mSrcStream can be non-null.
|
||||
RefPtr<MediaDecoder> mDecoder;
|
||||
|
@ -1357,9 +1356,6 @@ protected:
|
|||
|
||||
RefPtr<ChannelLoader> mChannelLoader;
|
||||
|
||||
// Error attribute
|
||||
RefPtr<MediaError> mError;
|
||||
|
||||
// The current media load ID. This is incremented every time we start a
|
||||
// new load. Async events note the ID when they're first sent, and only fire
|
||||
// if the ID is unchanged when they come to fire.
|
||||
|
@ -1745,6 +1741,8 @@ private:
|
|||
bool mAudible;
|
||||
|
||||
Visibility mVisibilityState;
|
||||
|
||||
UniquePtr<ErrorSink> mErrorSink;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -342,8 +342,8 @@ nsGenericHTMLElement::GetOffsetRect(CSSIntRect& aRect)
|
|||
if (parent &&
|
||||
parent->StylePosition()->mBoxSizing != StyleBoxSizing::Border) {
|
||||
const nsStyleBorder* border = parent->StyleBorder();
|
||||
origin.x -= border->GetComputedBorderWidth(NS_SIDE_LEFT);
|
||||
origin.y -= border->GetComputedBorderWidth(NS_SIDE_TOP);
|
||||
origin.x -= border->GetComputedBorderWidth(eSideLeft);
|
||||
origin.y -= border->GetComputedBorderWidth(eSideTop);
|
||||
}
|
||||
|
||||
// XXX We should really consider subtracting out padding for
|
||||
|
|
|
@ -973,7 +973,9 @@ ContentChild::InitXPCOM()
|
|||
&isLangRTL, &haveBidiKeyboards,
|
||||
&mAvailableDictionaries,
|
||||
&clipboardCaps, &domainPolicy, &initialData,
|
||||
&mFontFamilies, &userContentSheetURL);
|
||||
&mFontFamilies, &userContentSheetURL,
|
||||
&mLookAndFeelCache);
|
||||
|
||||
RecvSetOffline(isOffline);
|
||||
RecvSetConnectivity(isConnected);
|
||||
RecvSetCaptivePortalState(captivePortalState);
|
||||
|
|
|
@ -31,6 +31,7 @@ struct SubstitutionMapping;
|
|||
struct OverrideMapping;
|
||||
class nsIDomainPolicy;
|
||||
class nsIURIClassifierCallback;
|
||||
struct LookAndFeelInt;
|
||||
|
||||
namespace mozilla {
|
||||
class RemoteSpellcheckEngineChild;
|
||||
|
@ -625,6 +626,11 @@ public:
|
|||
virtual bool
|
||||
DeallocPURLClassifierChild(PURLClassifierChild* aActor) override;
|
||||
|
||||
nsTArray<LookAndFeelInt>&
|
||||
LookAndFeelCache() {
|
||||
return mLookAndFeelCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for protocols that use the GPU process when available.
|
||||
* Overrides FatalError to just be a warning when communicating with the
|
||||
|
@ -654,6 +660,8 @@ private:
|
|||
// parent process and used to initialize gfx in the child. Currently used
|
||||
// only on MacOSX.
|
||||
InfallibleTArray<mozilla::dom::FontFamilyListEntry> mFontFamilies;
|
||||
// Temporary storage for nsXPLookAndFeel flags.
|
||||
nsTArray<LookAndFeelInt> mLookAndFeelCache;
|
||||
|
||||
/**
|
||||
* An ID unique to the process containing our corresponding
|
||||
|
|
|
@ -2506,7 +2506,8 @@ ContentParent::RecvGetXPCOMProcessAttributes(bool* aIsOffline,
|
|||
DomainPolicyClone* domainPolicy,
|
||||
StructuredCloneData* aInitialData,
|
||||
InfallibleTArray<FontFamilyListEntry>* fontFamilies,
|
||||
OptionalURIParams* aUserContentCSSURL)
|
||||
OptionalURIParams* aUserContentCSSURL,
|
||||
nsTArray<LookAndFeelInt>* aLookAndFeelIntCache)
|
||||
{
|
||||
nsCOMPtr<nsIIOService> io(do_GetIOService());
|
||||
MOZ_ASSERT(io, "No IO service?");
|
||||
|
@ -2571,6 +2572,7 @@ ContentParent::RecvGetXPCOMProcessAttributes(bool* aIsOffline,
|
|||
|
||||
// This is only implemented (returns a non-empty list) by MacOSX at present.
|
||||
gfxPlatform::GetPlatform()->GetSystemFontFamilyList(fontFamilies);
|
||||
*aLookAndFeelIntCache = LookAndFeel::GetIntCache();
|
||||
|
||||
// Content processes have no permission to access profile directory, so we
|
||||
// send the file URL instead.
|
||||
|
@ -3262,13 +3264,6 @@ ContentParent::RecvNSSU2FTokenSign(nsTArray<uint8_t>&& aApplication,
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ContentParent::RecvGetLookAndFeelCache(nsTArray<LookAndFeelInt>* aLookAndFeelIntCache)
|
||||
{
|
||||
*aLookAndFeelIntCache = LookAndFeel::GetIntCache();
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ContentParent::RecvIsSecureURI(const uint32_t& type,
|
||||
const URIParams& uri,
|
||||
|
|
|
@ -726,7 +726,8 @@ private:
|
|||
DomainPolicyClone* domainPolicy,
|
||||
StructuredCloneData* initialData,
|
||||
InfallibleTArray<FontFamilyListEntry>* fontFamilies,
|
||||
OptionalURIParams* aUserContentSheetURL) override;
|
||||
OptionalURIParams* aUserContentSheetURL,
|
||||
nsTArray<LookAndFeelInt>* aLookAndFeelIntCache) override;
|
||||
|
||||
virtual bool
|
||||
DeallocPJavaScriptParent(mozilla::jsipc::PJavaScriptParent*) override;
|
||||
|
@ -972,8 +973,6 @@ private:
|
|||
const bool& aContentOrNormalChannel,
|
||||
const bool& aAnyChannel) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvGetLookAndFeelCache(nsTArray<LookAndFeelInt>* aLookAndFeelIntCache) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvKeywordToURI(const nsCString& aKeyword,
|
||||
nsString* aProviderName,
|
||||
OptionalInputStreamParams* aPostData,
|
||||
|
|
|
@ -672,7 +672,8 @@ parent:
|
|||
DomainPolicyClone domainPolicy,
|
||||
StructuredCloneData initialData,
|
||||
FontFamilyListEntry[] fontFamilies /* used on MacOSX only */,
|
||||
OptionalURIParams userContentSheetURL);
|
||||
OptionalURIParams userContentSheetURL,
|
||||
LookAndFeelInt[] lookAndFeelIntCache);
|
||||
|
||||
sync CreateChildProcess(IPCTabContext context,
|
||||
ProcessPriority priority,
|
||||
|
@ -773,9 +774,6 @@ parent:
|
|||
|
||||
async AccumulateMixedContentHSTS(URIParams uri, bool active, bool hasHSTSPriming);
|
||||
|
||||
sync GetLookAndFeelCache()
|
||||
returns (LookAndFeelInt[] lookAndFeelIntCache);
|
||||
|
||||
nested(inside_cpow) async PHal();
|
||||
|
||||
async PHeapSnapshotTempFileHelper();
|
||||
|
|
|
@ -152,9 +152,11 @@ void
|
|||
MediaDecoder::ResourceCallback::Disconnect()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mDecoder = nullptr;
|
||||
mTimer->Cancel();
|
||||
mTimer = nullptr;
|
||||
if (mDecoder) {
|
||||
mDecoder = nullptr;
|
||||
mTimer->Cancel();
|
||||
mTimer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
MediaDecoderOwner*
|
||||
|
@ -287,7 +289,7 @@ void
|
|||
MediaDecoder::NotifyOwnerActivityChanged(bool aIsVisible)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
|
||||
SetElementVisibility(aIsVisible);
|
||||
|
||||
MediaDecoderOwner* owner = GetOwner();
|
||||
|
@ -308,7 +310,7 @@ void
|
|||
MediaDecoder::Pause()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
|
||||
if (mPlayState == PLAY_STATE_LOADING || IsEnded()) {
|
||||
mNextState = PLAY_STATE_PAUSED;
|
||||
return;
|
||||
|
@ -358,7 +360,7 @@ void
|
|||
MediaDecoder::SetInfinite(bool aInfinite)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
|
||||
mInfiniteStream = aInfinite;
|
||||
DurationChanged();
|
||||
}
|
||||
|
@ -459,7 +461,7 @@ void
|
|||
MediaDecoder::Shutdown()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
|
||||
|
||||
// Unwatch all watch targets to prevent further notifications.
|
||||
mWatchManager.Shutdown();
|
||||
|
@ -510,6 +512,8 @@ MediaDecoder::Shutdown()
|
|||
MediaDecoder::~MediaDecoder()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_DIAGNOSTIC_ASSERT(IsShutdown());
|
||||
mResourceCallback->Disconnect();
|
||||
MediaMemoryTracker::RemoveMediaDecoder(this);
|
||||
UnpinForSeek();
|
||||
MOZ_COUNT_DTOR(MediaDecoder);
|
||||
|
@ -555,7 +559,7 @@ MediaDecoder::OnDecoderDoctorEvent(DecoderDoctorEvent aEvent)
|
|||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
// OnDecoderDoctorEvent is disconnected at shutdown time.
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
|
||||
HTMLMediaElement* element = mOwner->GetMediaElement();
|
||||
if (!element) {
|
||||
return;
|
||||
|
@ -689,7 +693,7 @@ nsresult
|
|||
MediaDecoder::Seek(double aTime, SeekTarget::Type aSeekType, dom::Promise* aPromise /*=nullptr*/)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
|
||||
|
||||
MOZ_ASSERT(aTime >= 0.0, "Cannot seek to a negative value.");
|
||||
|
||||
|
@ -789,7 +793,7 @@ MediaDecoder::MetadataLoaded(nsAutoPtr<MediaInfo> aInfo,
|
|||
MediaDecoderEventVisibility aEventVisibility)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
|
||||
|
||||
DECODER_LOG("MetadataLoaded, channels=%u rate=%u hasAudio=%d hasVideo=%d",
|
||||
aInfo->mAudio.mChannels, aInfo->mAudio.mRate,
|
||||
|
@ -862,7 +866,7 @@ MediaDecoder::FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo,
|
|||
MediaDecoderEventVisibility aEventVisibility)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
|
||||
|
||||
DECODER_LOG("FirstFrameLoaded, channels=%u rate=%u hasAudio=%d hasVideo=%d mPlayState=%s",
|
||||
aInfo->mAudio.mChannels, aInfo->mAudio.mRate,
|
||||
|
@ -898,7 +902,7 @@ void
|
|||
MediaDecoder::NetworkError()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
|
||||
mOwner->NetworkError();
|
||||
}
|
||||
|
||||
|
@ -906,7 +910,7 @@ void
|
|||
MediaDecoder::DecodeError(const MediaResult& aError)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
|
||||
mOwner->DecodeError(aError);
|
||||
}
|
||||
|
||||
|
@ -928,7 +932,7 @@ bool
|
|||
MediaDecoder::OwnerHasError() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
|
||||
return mOwner->HasError();
|
||||
}
|
||||
|
||||
|
@ -978,7 +982,7 @@ void
|
|||
MediaDecoder::PlaybackEnded()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
|
||||
|
||||
if (mLogicallySeeking || mPlayState == PLAY_STATE_LOADING) {
|
||||
return;
|
||||
|
@ -1055,7 +1059,7 @@ void
|
|||
MediaDecoder::NotifySuspendedStatusChanged()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
|
||||
if (mResource) {
|
||||
bool suspended = mResource->IsSuspendedByCache();
|
||||
mOwner->NotifySuspendedByCache(suspended);
|
||||
|
@ -1066,7 +1070,7 @@ void
|
|||
MediaDecoder::NotifyBytesDownloaded()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
|
||||
UpdatePlaybackRate();
|
||||
mOwner->DownloadProgressed();
|
||||
}
|
||||
|
@ -1075,7 +1079,7 @@ void
|
|||
MediaDecoder::NotifyDownloadEnded(nsresult aStatus)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
|
||||
|
||||
DECODER_LOG("NotifyDownloadEnded, status=%x", aStatus);
|
||||
|
||||
|
@ -1101,7 +1105,7 @@ void
|
|||
MediaDecoder::NotifyPrincipalChanged()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
|
||||
nsCOMPtr<nsIPrincipal> newPrincipal = GetCurrentPrincipal();
|
||||
mMediaPrincipalHandle = MakePrincipalHandle(newPrincipal);
|
||||
mOwner->NotifyDecoderPrincipalChanged();
|
||||
|
@ -1111,7 +1115,7 @@ void
|
|||
MediaDecoder::NotifyBytesConsumed(int64_t aBytes, int64_t aOffset)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
|
||||
|
||||
if (mIgnoreProgressData) {
|
||||
return;
|
||||
|
@ -1128,7 +1132,7 @@ void
|
|||
MediaDecoder::OnSeekResolved()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
|
||||
mSeekRequest.Complete();
|
||||
|
||||
{
|
||||
|
@ -1158,7 +1162,7 @@ void
|
|||
MediaDecoder::SeekingStarted()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
|
||||
mOwner->SeekStarted();
|
||||
}
|
||||
|
||||
|
@ -1186,7 +1190,7 @@ void
|
|||
MediaDecoder::UpdateLogicalPositionInternal()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
|
||||
|
||||
double currentPosition = static_cast<double>(CurrentPosition()) / static_cast<double>(USECS_PER_S);
|
||||
if (mPlayState == PLAY_STATE_ENDED) {
|
||||
|
@ -1210,7 +1214,7 @@ void
|
|||
MediaDecoder::DurationChanged()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
|
||||
|
||||
double oldDuration = mDuration;
|
||||
if (IsInfinite()) {
|
||||
|
@ -1487,7 +1491,7 @@ void MediaDecoder::AddSizeOfResources(ResourceSizes* aSizes) {
|
|||
void
|
||||
MediaDecoder::NotifyDataArrived() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
|
||||
mDataArrivedEvent.Notify();
|
||||
}
|
||||
|
||||
|
@ -1502,7 +1506,7 @@ void
|
|||
MediaDecoder::FireTimeUpdate()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
|
||||
mOwner->FireTimeUpdate(true);
|
||||
}
|
||||
|
||||
|
@ -1651,7 +1655,7 @@ void
|
|||
MediaDecoder::ConstructMediaTracks()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
|
||||
|
||||
if (mMediaTracksConstructed || !mInfo) {
|
||||
return;
|
||||
|
@ -1688,7 +1692,7 @@ void
|
|||
MediaDecoder::RemoveMediaTracks()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
|
||||
|
||||
HTMLMediaElement* element = mOwner->GetMediaElement();
|
||||
if (!element) {
|
||||
|
@ -1726,7 +1730,7 @@ MediaDecoder::NextFrameBufferedStatus()
|
|||
void
|
||||
MediaDecoder::DumpDebugInfo()
|
||||
{
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
|
||||
DUMP_LOG("metadata: channels=%u rate=%u hasAudio=%d hasVideo=%d, "
|
||||
"state: mPlayState=%s mdsm=%p",
|
||||
mInfo ? mInfo->mAudio.mChannels : 0, mInfo ? mInfo->mAudio.mRate : 0,
|
||||
|
@ -1747,7 +1751,7 @@ MediaDecoder::DumpDebugInfo()
|
|||
void
|
||||
MediaDecoder::NotifyAudibleStateChanged()
|
||||
{
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
|
||||
mOwner->SetAudibleState(mIsAudioDataAudible);
|
||||
}
|
||||
|
||||
|
|
|
@ -166,18 +166,6 @@ public:
|
|||
// probably be removed somehow.
|
||||
virtual RefPtr<SeekPromise> Seek(SeekTarget aTarget, int64_t aEndTime) = 0;
|
||||
|
||||
// Called to move the reader into idle state. When the reader is
|
||||
// created it is assumed to be active (i.e. not idle). When the media
|
||||
// element is paused and we don't need to decode any more data, the state
|
||||
// machine calls SetIdle() to inform the reader that its decoder won't be
|
||||
// needed for a while. The reader can use these notifications to enter
|
||||
// a low power state when the decoder isn't needed, if desired.
|
||||
// This is most useful on mobile.
|
||||
// Note: DecodeVideoFrame, DecodeAudioData, ReadMetadata and Seek should
|
||||
// activate the decoder if necessary. The state machine only needs to know
|
||||
// when to call SetIdle().
|
||||
virtual void SetIdle() {}
|
||||
|
||||
virtual void SetCDMProxy(CDMProxy* aProxy) {}
|
||||
|
||||
// Tell the reader that the data decoded are not for direct playback, so it
|
||||
|
|
|
@ -11,8 +11,7 @@ namespace mozilla {
|
|||
|
||||
MediaDecoderReaderWrapper::MediaDecoderReaderWrapper(AbstractThread* aOwnerThread,
|
||||
MediaDecoderReader* aReader)
|
||||
: mForceZeroStartTime(aReader->ForceZeroStartTime())
|
||||
, mOwnerThread(aOwnerThread)
|
||||
: mOwnerThread(aOwnerThread)
|
||||
, mReader(aReader)
|
||||
{}
|
||||
|
||||
|
@ -183,15 +182,6 @@ MediaDecoderReaderWrapper::ReleaseResources()
|
|||
mReader->OwnerThread()->Dispatch(r.forget());
|
||||
}
|
||||
|
||||
void
|
||||
MediaDecoderReaderWrapper::SetIdle()
|
||||
{
|
||||
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
|
||||
nsCOMPtr<nsIRunnable> r =
|
||||
NewRunnableMethod(mReader, &MediaDecoderReader::SetIdle);
|
||||
mReader->OwnerThread()->Dispatch(r.forget());
|
||||
}
|
||||
|
||||
void
|
||||
MediaDecoderReaderWrapper::ResetDecode(TrackSet aTracks)
|
||||
{
|
||||
|
|
|
@ -73,7 +73,6 @@ public:
|
|||
RefPtr<ShutdownPromise> Shutdown();
|
||||
|
||||
void ReleaseResources();
|
||||
void SetIdle();
|
||||
void ResetDecode(TrackSet aTracks);
|
||||
|
||||
nsresult Init() { return mReader->Init(); }
|
||||
|
@ -122,7 +121,6 @@ private:
|
|||
MediaCallbackExc<WaitCallbackData>& WaitCallbackRef(MediaData::Type aType);
|
||||
MozPromiseRequestHolder<WaitForDataPromise>& WaitRequestRef(MediaData::Type aType);
|
||||
|
||||
const bool mForceZeroStartTime;
|
||||
const RefPtr<AbstractThread> mOwnerThread;
|
||||
const RefPtr<MediaDecoderReader> mReader;
|
||||
|
||||
|
|
|
@ -2447,16 +2447,9 @@ MediaDecoderStateMachine::DispatchDecodeTasksIfNeeded()
|
|||
MOZ_ASSERT(mState != DECODER_STATE_COMPLETED ||
|
||||
(!needToDecodeAudio && !needToDecodeVideo));
|
||||
|
||||
bool needIdle = !IsLogicallyPlaying() &&
|
||||
mState != DECODER_STATE_SEEKING &&
|
||||
!needToDecodeAudio &&
|
||||
!needToDecodeVideo &&
|
||||
!IsPlaying();
|
||||
|
||||
SAMPLE_LOG("DispatchDecodeTasksIfNeeded needAudio=%d audioStatus=%s needVideo=%d videoStatus=%s needIdle=%d",
|
||||
SAMPLE_LOG("DispatchDecodeTasksIfNeeded needAudio=%d audioStatus=%s needVideo=%d videoStatus=%s",
|
||||
needToDecodeAudio, AudioRequestStatus(),
|
||||
needToDecodeVideo, VideoRequestStatus(),
|
||||
needIdle);
|
||||
needToDecodeVideo, VideoRequestStatus());
|
||||
|
||||
if (needToDecodeAudio) {
|
||||
EnsureAudioDecodeTaskQueued();
|
||||
|
@ -2464,13 +2457,6 @@ MediaDecoderStateMachine::DispatchDecodeTasksIfNeeded()
|
|||
if (needToDecodeVideo) {
|
||||
EnsureVideoDecodeTaskQueued();
|
||||
}
|
||||
|
||||
if (needIdle) {
|
||||
DECODER_LOG("Dispatching SetIdle() audioQueue=%lld videoQueue=%lld",
|
||||
GetDecodedAudioDuration(),
|
||||
VideoQueue().Duration());
|
||||
mReader->SetIdle();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -117,13 +117,29 @@ GMPContentParent::DecryptorDestroyed(GMPDecryptorParent* aSession)
|
|||
CloseIfUnused();
|
||||
}
|
||||
|
||||
void
|
||||
GMPContentParent::AddCloseBlocker()
|
||||
{
|
||||
MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
|
||||
++mCloseBlockerCount;
|
||||
}
|
||||
|
||||
void
|
||||
GMPContentParent::RemoveCloseBlocker()
|
||||
{
|
||||
MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
|
||||
--mCloseBlockerCount;
|
||||
CloseIfUnused();
|
||||
}
|
||||
|
||||
void
|
||||
GMPContentParent::CloseIfUnused()
|
||||
{
|
||||
if (mAudioDecoders.IsEmpty() &&
|
||||
mDecryptors.IsEmpty() &&
|
||||
mVideoDecoders.IsEmpty() &&
|
||||
mVideoEncoders.IsEmpty()) {
|
||||
mVideoEncoders.IsEmpty() &&
|
||||
mCloseBlockerCount == 0) {
|
||||
RefPtr<GMPContentParent> toClose;
|
||||
if (mParent) {
|
||||
toClose = mParent->ForgetGMPContentParent();
|
||||
|
|
|
@ -62,7 +62,27 @@ public:
|
|||
return mPluginId;
|
||||
}
|
||||
|
||||
class CloseBlocker {
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CloseBlocker)
|
||||
|
||||
explicit CloseBlocker(GMPContentParent* aParent)
|
||||
: mParent(aParent)
|
||||
{
|
||||
mParent->AddCloseBlocker();
|
||||
}
|
||||
RefPtr<GMPContentParent> mParent;
|
||||
private:
|
||||
~CloseBlocker() {
|
||||
mParent->RemoveCloseBlocker();
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
void AddCloseBlocker();
|
||||
void RemoveCloseBlocker();
|
||||
|
||||
~GMPContentParent();
|
||||
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
@ -95,6 +115,7 @@ private:
|
|||
RefPtr<GMPParent> mParent;
|
||||
nsCString mDisplayName;
|
||||
uint32_t mPluginId;
|
||||
uint32_t mCloseBlockerCount = 0;
|
||||
};
|
||||
|
||||
} // namespace gmp
|
||||
|
|
|
@ -1049,32 +1049,17 @@ GMPParent::RecvAsyncShutdownComplete()
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
class RunCreateContentParentCallbacks : public Runnable
|
||||
void
|
||||
GMPParent::ResolveGetContentParentPromises()
|
||||
{
|
||||
public:
|
||||
explicit RunCreateContentParentCallbacks(GMPContentParent* aGMPContentParent)
|
||||
: mGMPContentParent(aGMPContentParent)
|
||||
{
|
||||
nsTArray<UniquePtr<MozPromiseHolder<GetGMPContentParentPromise>>> promises;
|
||||
promises.SwapElements(mGetContentParentPromises);
|
||||
MOZ_ASSERT(mGetContentParentPromises.IsEmpty());
|
||||
RefPtr<GMPContentParent::CloseBlocker> blocker(new GMPContentParent::CloseBlocker(mGMPContentParent));
|
||||
for (auto& holder : promises) {
|
||||
holder->Resolve(blocker, __func__);
|
||||
}
|
||||
|
||||
void TakeCallbacks(nsTArray<UniquePtr<GetGMPContentParentCallback>>& aCallbacks)
|
||||
{
|
||||
mCallbacks.SwapElements(aCallbacks);
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
Run() override
|
||||
{
|
||||
for (uint32_t i = 0, length = mCallbacks.Length(); i < length; ++i) {
|
||||
mCallbacks[i]->Done(mGMPContentParent);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
RefPtr<GMPContentParent> mGMPContentParent;
|
||||
nsTArray<UniquePtr<GetGMPContentParentCallback>> mCallbacks;
|
||||
};
|
||||
}
|
||||
|
||||
PGMPContentParent*
|
||||
GMPParent::AllocPGMPContentParent(Transport* aTransport, ProcessId aOtherPid)
|
||||
|
@ -1086,33 +1071,42 @@ GMPParent::AllocPGMPContentParent(Transport* aTransport, ProcessId aOtherPid)
|
|||
mGMPContentParent->Open(aTransport, aOtherPid, XRE_GetIOMessageLoop(),
|
||||
ipc::ParentSide);
|
||||
|
||||
RefPtr<RunCreateContentParentCallbacks> runCallbacks =
|
||||
new RunCreateContentParentCallbacks(mGMPContentParent);
|
||||
runCallbacks->TakeCallbacks(mCallbacks);
|
||||
NS_DispatchToCurrentThread(runCallbacks);
|
||||
MOZ_ASSERT(mCallbacks.IsEmpty());
|
||||
ResolveGetContentParentPromises();
|
||||
|
||||
return mGMPContentParent;
|
||||
}
|
||||
|
||||
bool
|
||||
GMPParent::GetGMPContentParent(UniquePtr<GetGMPContentParentCallback>&& aCallback)
|
||||
void
|
||||
GMPParent::RejectGetContentParentPromises()
|
||||
{
|
||||
nsTArray<UniquePtr<MozPromiseHolder<GetGMPContentParentPromise>>> promises;
|
||||
promises.SwapElements(mGetContentParentPromises);
|
||||
MOZ_ASSERT(mGetContentParentPromises.IsEmpty());
|
||||
for (auto& holder : promises) {
|
||||
holder->Reject(NS_ERROR_FAILURE, __func__);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GMPParent::GetGMPContentParent(UniquePtr<MozPromiseHolder<GetGMPContentParentPromise>>&& aPromiseHolder)
|
||||
{
|
||||
LOGD("%s %p", __FUNCTION__, this);
|
||||
MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
|
||||
|
||||
if (mGMPContentParent) {
|
||||
aCallback->Done(mGMPContentParent);
|
||||
RefPtr<GMPContentParent::CloseBlocker> blocker(new GMPContentParent::CloseBlocker(mGMPContentParent));
|
||||
aPromiseHolder->Resolve(blocker, __func__);
|
||||
} else {
|
||||
mCallbacks.AppendElement(Move(aCallback));
|
||||
mGetContentParentPromises.AppendElement(Move(aPromiseHolder));
|
||||
// If we don't have a GMPContentParent and we try to get one for the first
|
||||
// time (mCallbacks.Length() == 1) then call PGMPContent::Open. If more
|
||||
// time (mGetContentParentPromises.Length() == 1) then call PGMPContent::Open. If more
|
||||
// calls to GetGMPContentParent happen before mGMPContentParent has been
|
||||
// set then we should just store them, so that they get called when we set
|
||||
// mGMPContentParent as a result of the PGMPContent::Open call.
|
||||
if (mCallbacks.Length() == 1) {
|
||||
if (mGetContentParentPromises.Length() == 1) {
|
||||
if (!EnsureProcessLoaded() || !PGMPContent::Open(this)) {
|
||||
return false;
|
||||
RejectGetContentParentPromises();
|
||||
return;
|
||||
}
|
||||
// We want to increment this as soon as possible, to avoid that we'd try
|
||||
// to shut down the GMP process while we're still trying to get a
|
||||
|
@ -1120,13 +1114,12 @@ GMPParent::GetGMPContentParent(UniquePtr<GetGMPContentParentCallback>&& aCallbac
|
|||
++mGMPContentChildCount;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
already_AddRefed<GMPContentParent>
|
||||
GMPParent::ForgetGMPContentParent()
|
||||
{
|
||||
MOZ_ASSERT(mCallbacks.IsEmpty());
|
||||
MOZ_ASSERT(mGetContentParentPromises.IsEmpty());
|
||||
return Move(mGMPContentParent.forget());
|
||||
}
|
||||
|
||||
|
|
|
@ -73,20 +73,6 @@ enum GMPState {
|
|||
|
||||
class GMPContentParent;
|
||||
|
||||
class GetGMPContentParentCallback
|
||||
{
|
||||
public:
|
||||
GetGMPContentParentCallback()
|
||||
{
|
||||
MOZ_COUNT_CTOR(GetGMPContentParentCallback);
|
||||
};
|
||||
virtual ~GetGMPContentParentCallback()
|
||||
{
|
||||
MOZ_COUNT_DTOR(GetGMPContentParentCallback);
|
||||
};
|
||||
virtual void Done(GMPContentParent* aGMPContentParent) = 0;
|
||||
};
|
||||
|
||||
class GMPParent final : public PGMPParent
|
||||
{
|
||||
public:
|
||||
|
@ -159,7 +145,7 @@ public:
|
|||
// Called when the child process has died.
|
||||
void ChildTerminated();
|
||||
|
||||
bool GetGMPContentParent(UniquePtr<GetGMPContentParentCallback>&& aCallback);
|
||||
void GetGMPContentParent(UniquePtr<MozPromiseHolder<GetGMPContentParentPromise>>&& aPromiseHolder);
|
||||
already_AddRefed<GMPContentParent> ForgetGMPContentParent();
|
||||
|
||||
bool EnsureProcessLoaded(base::ProcessId* aID);
|
||||
|
@ -203,9 +189,12 @@ private:
|
|||
mozilla::ipc::IPCResult RecvPGMPContentChildDestroyed() override;
|
||||
bool IsUsed()
|
||||
{
|
||||
return mGMPContentChildCount > 0;
|
||||
return mGMPContentChildCount > 0 ||
|
||||
!mGetContentParentPromises.IsEmpty();
|
||||
}
|
||||
|
||||
void ResolveGetContentParentPromises();
|
||||
void RejectGetContentParentPromises();
|
||||
|
||||
static void AbortWaitingForGMPAsyncShutdown(nsITimer* aTimer, void* aClosure);
|
||||
nsresult EnsureAsyncShutdownTimeoutSet();
|
||||
|
@ -239,7 +228,7 @@ private:
|
|||
// This is used for GMP content in the parent, there may be more of these in
|
||||
// the content processes.
|
||||
RefPtr<GMPContentParent> mGMPContentParent;
|
||||
nsTArray<UniquePtr<GetGMPContentParentCallback>> mCallbacks;
|
||||
nsTArray<UniquePtr<MozPromiseHolder<GetGMPContentParentPromise>>> mGetContentParentPromises;
|
||||
uint32_t mGMPContentChildCount;
|
||||
|
||||
bool mAsyncShutdownRequired;
|
||||
|
|
|
@ -295,30 +295,6 @@ GeckoMediaPluginService::GetAbstractGMPThread()
|
|||
return mAbstractGMPThread;
|
||||
}
|
||||
|
||||
class GetGMPContentParentForAudioDecoderDone : public GetGMPContentParentCallback
|
||||
{
|
||||
public:
|
||||
explicit GetGMPContentParentForAudioDecoderDone(UniquePtr<GetGMPAudioDecoderCallback>&& aCallback,
|
||||
GMPCrashHelper* aHelper)
|
||||
: mCallback(Move(aCallback))
|
||||
, mHelper(aHelper)
|
||||
{
|
||||
}
|
||||
|
||||
void Done(GMPContentParent* aGMPParent) override
|
||||
{
|
||||
GMPAudioDecoderParent* gmpADP = nullptr;
|
||||
if (aGMPParent && NS_SUCCEEDED(aGMPParent->GetGMPAudioDecoder(&gmpADP))) {
|
||||
gmpADP->SetCrashHelper(mHelper);
|
||||
}
|
||||
mCallback->Done(gmpADP);
|
||||
}
|
||||
|
||||
private:
|
||||
UniquePtr<GetGMPAudioDecoderCallback> mCallback;
|
||||
RefPtr<GMPCrashHelper> mHelper;
|
||||
};
|
||||
|
||||
NS_IMETHODIMP
|
||||
GeckoMediaPluginService::GetGMPAudioDecoder(GMPCrashHelper* aHelper,
|
||||
nsTArray<nsCString>* aTags,
|
||||
|
@ -333,48 +309,28 @@ GeckoMediaPluginService::GetGMPAudioDecoder(GMPCrashHelper* aHelper,
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
UniquePtr<GetGMPContentParentCallback> callback(
|
||||
new GetGMPContentParentForAudioDecoderDone(Move(aCallback), aHelper));
|
||||
if (!GetContentParentFrom(aHelper,
|
||||
aNodeId,
|
||||
NS_LITERAL_CSTRING(GMP_API_AUDIO_DECODER),
|
||||
*aTags,
|
||||
Move(callback))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
GetGMPAudioDecoderCallback* rawCallback = aCallback.release();
|
||||
RefPtr<AbstractThread> thread(GetAbstractGMPThread());
|
||||
RefPtr<GMPCrashHelper> helper(aHelper);
|
||||
GetContentParent(aHelper, aNodeId, NS_LITERAL_CSTRING(GMP_API_AUDIO_DECODER), *aTags)
|
||||
->Then(thread, __func__,
|
||||
[rawCallback, helper](RefPtr<GMPContentParent::CloseBlocker> wrapper) {
|
||||
RefPtr<GMPContentParent> parent = wrapper->mParent;
|
||||
UniquePtr<GetGMPAudioDecoderCallback> callback(rawCallback);
|
||||
GMPAudioDecoderParent* actor = nullptr;
|
||||
if (parent && NS_SUCCEEDED(parent->GetGMPAudioDecoder(&actor))) {
|
||||
actor->SetCrashHelper(helper);
|
||||
}
|
||||
callback->Done(actor);
|
||||
},
|
||||
[rawCallback] {
|
||||
UniquePtr<GetGMPAudioDecoderCallback> callback(rawCallback);
|
||||
callback->Done(nullptr);
|
||||
});
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class GetGMPContentParentForVideoDecoderDone : public GetGMPContentParentCallback
|
||||
{
|
||||
public:
|
||||
explicit GetGMPContentParentForVideoDecoderDone(UniquePtr<GetGMPVideoDecoderCallback>&& aCallback,
|
||||
GMPCrashHelper* aHelper,
|
||||
uint32_t aDecryptorId)
|
||||
: mCallback(Move(aCallback))
|
||||
, mHelper(aHelper)
|
||||
, mDecryptorId(aDecryptorId)
|
||||
{
|
||||
}
|
||||
|
||||
void Done(GMPContentParent* aGMPParent) override
|
||||
{
|
||||
GMPVideoDecoderParent* gmpVDP = nullptr;
|
||||
GMPVideoHostImpl* videoHost = nullptr;
|
||||
if (aGMPParent && NS_SUCCEEDED(aGMPParent->GetGMPVideoDecoder(&gmpVDP, mDecryptorId))) {
|
||||
videoHost = &gmpVDP->Host();
|
||||
gmpVDP->SetCrashHelper(mHelper);
|
||||
}
|
||||
mCallback->Done(gmpVDP, videoHost);
|
||||
}
|
||||
|
||||
private:
|
||||
UniquePtr<GetGMPVideoDecoderCallback> mCallback;
|
||||
RefPtr<GMPCrashHelper> mHelper;
|
||||
const uint32_t mDecryptorId;
|
||||
};
|
||||
|
||||
NS_IMETHODIMP
|
||||
GeckoMediaPluginService::GetDecryptingGMPVideoDecoder(GMPCrashHelper* aHelper,
|
||||
nsTArray<nsCString>* aTags,
|
||||
|
@ -390,45 +346,30 @@ GeckoMediaPluginService::GetDecryptingGMPVideoDecoder(GMPCrashHelper* aHelper,
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
UniquePtr<GetGMPContentParentCallback> callback(
|
||||
new GetGMPContentParentForVideoDecoderDone(Move(aCallback), aHelper, aDecryptorId));
|
||||
if (!GetContentParentFrom(aHelper,
|
||||
aNodeId,
|
||||
NS_LITERAL_CSTRING(GMP_API_VIDEO_DECODER),
|
||||
*aTags,
|
||||
Move(callback))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
GetGMPVideoDecoderCallback* rawCallback = aCallback.release();
|
||||
RefPtr<AbstractThread> thread(GetAbstractGMPThread());
|
||||
RefPtr<GMPCrashHelper> helper(aHelper);
|
||||
GetContentParent(aHelper, aNodeId, NS_LITERAL_CSTRING(GMP_API_VIDEO_DECODER), *aTags)
|
||||
->Then(thread, __func__,
|
||||
[rawCallback, helper, aDecryptorId](RefPtr<GMPContentParent::CloseBlocker> wrapper) {
|
||||
RefPtr<GMPContentParent> parent = wrapper->mParent;
|
||||
UniquePtr<GetGMPVideoDecoderCallback> callback(rawCallback);
|
||||
GMPVideoDecoderParent* actor = nullptr;
|
||||
GMPVideoHostImpl* host = nullptr;
|
||||
if (parent && NS_SUCCEEDED(parent->GetGMPVideoDecoder(&actor, aDecryptorId))) {
|
||||
host = &(actor->Host());
|
||||
actor->SetCrashHelper(helper);
|
||||
}
|
||||
callback->Done(actor, host);
|
||||
},
|
||||
[rawCallback] {
|
||||
UniquePtr<GetGMPVideoDecoderCallback> callback(rawCallback);
|
||||
callback->Done(nullptr, nullptr);
|
||||
});
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class GetGMPContentParentForVideoEncoderDone : public GetGMPContentParentCallback
|
||||
{
|
||||
public:
|
||||
explicit GetGMPContentParentForVideoEncoderDone(UniquePtr<GetGMPVideoEncoderCallback>&& aCallback,
|
||||
GMPCrashHelper* aHelper)
|
||||
: mCallback(Move(aCallback))
|
||||
, mHelper(aHelper)
|
||||
{
|
||||
}
|
||||
|
||||
void Done(GMPContentParent* aGMPParent) override
|
||||
{
|
||||
GMPVideoEncoderParent* gmpVEP = nullptr;
|
||||
GMPVideoHostImpl* videoHost = nullptr;
|
||||
if (aGMPParent && NS_SUCCEEDED(aGMPParent->GetGMPVideoEncoder(&gmpVEP))) {
|
||||
videoHost = &gmpVEP->Host();
|
||||
gmpVEP->SetCrashHelper(mHelper);
|
||||
}
|
||||
mCallback->Done(gmpVEP, videoHost);
|
||||
}
|
||||
|
||||
private:
|
||||
UniquePtr<GetGMPVideoEncoderCallback> mCallback;
|
||||
RefPtr<GMPCrashHelper> mHelper;
|
||||
};
|
||||
|
||||
NS_IMETHODIMP
|
||||
GeckoMediaPluginService::GetGMPVideoEncoder(GMPCrashHelper* aHelper,
|
||||
nsTArray<nsCString>* aTags,
|
||||
|
@ -443,43 +384,30 @@ GeckoMediaPluginService::GetGMPVideoEncoder(GMPCrashHelper* aHelper,
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
UniquePtr<GetGMPContentParentCallback> callback(
|
||||
new GetGMPContentParentForVideoEncoderDone(Move(aCallback), aHelper));
|
||||
if (!GetContentParentFrom(aHelper,
|
||||
aNodeId,
|
||||
NS_LITERAL_CSTRING(GMP_API_VIDEO_ENCODER),
|
||||
*aTags,
|
||||
Move(callback))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
GetGMPVideoEncoderCallback* rawCallback = aCallback.release();
|
||||
RefPtr<AbstractThread> thread(GetAbstractGMPThread());
|
||||
RefPtr<GMPCrashHelper> helper(aHelper);
|
||||
GetContentParent(aHelper, aNodeId, NS_LITERAL_CSTRING(GMP_API_VIDEO_ENCODER), *aTags)
|
||||
->Then(thread, __func__,
|
||||
[rawCallback, helper](RefPtr<GMPContentParent::CloseBlocker> wrapper) {
|
||||
RefPtr<GMPContentParent> parent = wrapper->mParent;
|
||||
UniquePtr<GetGMPVideoEncoderCallback> callback(rawCallback);
|
||||
GMPVideoEncoderParent* actor = nullptr;
|
||||
GMPVideoHostImpl* host = nullptr;
|
||||
if (parent && NS_SUCCEEDED(parent->GetGMPVideoEncoder(&actor))) {
|
||||
host = &(actor->Host());
|
||||
actor->SetCrashHelper(helper);
|
||||
}
|
||||
callback->Done(actor, host);
|
||||
},
|
||||
[rawCallback] {
|
||||
UniquePtr<GetGMPVideoEncoderCallback> callback(rawCallback);
|
||||
callback->Done(nullptr, nullptr);
|
||||
});
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class GetGMPContentParentForDecryptorDone : public GetGMPContentParentCallback
|
||||
{
|
||||
public:
|
||||
explicit GetGMPContentParentForDecryptorDone(UniquePtr<GetGMPDecryptorCallback>&& aCallback,
|
||||
GMPCrashHelper* aHelper)
|
||||
: mCallback(Move(aCallback))
|
||||
, mHelper(aHelper)
|
||||
{
|
||||
}
|
||||
|
||||
void Done(GMPContentParent* aGMPParent) override
|
||||
{
|
||||
GMPDecryptorParent* ksp = nullptr;
|
||||
if (aGMPParent && NS_SUCCEEDED(aGMPParent->GetGMPDecryptor(&ksp))) {
|
||||
ksp->SetCrashHelper(mHelper);
|
||||
}
|
||||
mCallback->Done(ksp);
|
||||
}
|
||||
|
||||
private:
|
||||
UniquePtr<GetGMPDecryptorCallback> mCallback;
|
||||
RefPtr<GMPCrashHelper> mHelper;
|
||||
};
|
||||
|
||||
NS_IMETHODIMP
|
||||
GeckoMediaPluginService::GetGMPDecryptor(GMPCrashHelper* aHelper,
|
||||
nsTArray<nsCString>* aTags,
|
||||
|
@ -502,15 +430,24 @@ GeckoMediaPluginService::GetGMPDecryptor(GMPCrashHelper* aHelper,
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
UniquePtr<GetGMPContentParentCallback> callback(
|
||||
new GetGMPContentParentForDecryptorDone(Move(aCallback), aHelper));
|
||||
if (!GetContentParentFrom(aHelper,
|
||||
aNodeId,
|
||||
NS_LITERAL_CSTRING(GMP_API_DECRYPTOR),
|
||||
*aTags,
|
||||
Move(callback))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
GetGMPDecryptorCallback* rawCallback = aCallback.release();
|
||||
RefPtr<AbstractThread> thread(GetAbstractGMPThread());
|
||||
RefPtr<GMPCrashHelper> helper(aHelper);
|
||||
GetContentParent(aHelper, aNodeId, NS_LITERAL_CSTRING(GMP_API_DECRYPTOR), *aTags)
|
||||
->Then(thread, __func__,
|
||||
[rawCallback, helper](RefPtr<GMPContentParent::CloseBlocker> wrapper) {
|
||||
RefPtr<GMPContentParent> parent = wrapper->mParent;
|
||||
UniquePtr<GetGMPDecryptorCallback> callback(rawCallback);
|
||||
GMPDecryptorParent* actor = nullptr;
|
||||
if (parent && NS_SUCCEEDED(parent->GetGMPDecryptor(&actor))) {
|
||||
actor->SetCrashHelper(helper);
|
||||
}
|
||||
callback->Done(actor);
|
||||
},
|
||||
[rawCallback] {
|
||||
UniquePtr<GetGMPDecryptorCallback> callback(rawCallback);
|
||||
callback->Done(nullptr);
|
||||
});
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include "mozilla/AbstractThread.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "mozilla/MozPromise.h"
|
||||
#include "GMPContentParent.h"
|
||||
|
||||
template <class> struct already_AddRefed;
|
||||
|
||||
|
@ -32,7 +34,7 @@ extern LogModule* GetGMPLog();
|
|||
|
||||
namespace gmp {
|
||||
|
||||
class GetGMPContentParentCallback;
|
||||
typedef MozPromise<RefPtr<GMPContentParent::CloseBlocker>, nsresult, /* IsExclusive = */ true> GetGMPContentParentPromise;
|
||||
|
||||
class GeckoMediaPluginService : public mozIGeckoMediaPluginService
|
||||
, public nsIObserver
|
||||
|
@ -93,11 +95,12 @@ protected:
|
|||
virtual ~GeckoMediaPluginService();
|
||||
|
||||
virtual void InitializePlugins(AbstractThread* aAbstractGMPThread) = 0;
|
||||
virtual bool GetContentParentFrom(GMPCrashHelper* aHelper,
|
||||
const nsACString& aNodeId,
|
||||
const nsCString& aAPI,
|
||||
const nsTArray<nsCString>& aTags,
|
||||
UniquePtr<GetGMPContentParentCallback>&& aCallback) = 0;
|
||||
|
||||
virtual RefPtr<GetGMPContentParentPromise>
|
||||
GetContentParent(GMPCrashHelper* aHelper,
|
||||
const nsACString& aNodeId,
|
||||
const nsCString& aAPI,
|
||||
const nsTArray<nsCString>& aTags) = 0;
|
||||
|
||||
nsresult GMPDispatch(nsIRunnable* event, uint32_t flags = NS_DISPATCH_NORMAL);
|
||||
nsresult GMPDispatch(already_AddRefed<nsIRunnable> event, uint32_t flags = NS_DISPATCH_NORMAL);
|
||||
|
|
|
@ -52,85 +52,72 @@ GeckoMediaPluginServiceChild::GetSingleton()
|
|||
return service.forget().downcast<GeckoMediaPluginServiceChild>();
|
||||
}
|
||||
|
||||
class GetContentParentFromDone : public GetServiceChildCallback
|
||||
{
|
||||
public:
|
||||
GetContentParentFromDone(GMPCrashHelper* aHelper, const nsACString& aNodeId, const nsCString& aAPI,
|
||||
const nsTArray<nsCString>& aTags,
|
||||
UniquePtr<GetGMPContentParentCallback>&& aCallback)
|
||||
: mHelper(aHelper),
|
||||
mNodeId(aNodeId),
|
||||
mAPI(aAPI),
|
||||
mTags(aTags),
|
||||
mCallback(Move(aCallback))
|
||||
{
|
||||
}
|
||||
|
||||
void Done(GMPServiceChild* aGMPServiceChild) override
|
||||
{
|
||||
if (!aGMPServiceChild) {
|
||||
mCallback->Done(nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t pluginId;
|
||||
nsresult rv;
|
||||
bool ok = aGMPServiceChild->SendSelectGMP(mNodeId, mAPI, mTags, &pluginId, &rv);
|
||||
if (!ok || rv == NS_ERROR_ILLEGAL_DURING_SHUTDOWN) {
|
||||
mCallback->Done(nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mHelper) {
|
||||
RefPtr<GeckoMediaPluginService> gmps(GeckoMediaPluginService::GetGeckoMediaPluginService());
|
||||
gmps->ConnectCrashHelper(pluginId, mHelper);
|
||||
}
|
||||
|
||||
nsTArray<base::ProcessId> alreadyBridgedTo;
|
||||
aGMPServiceChild->GetAlreadyBridgedTo(alreadyBridgedTo);
|
||||
|
||||
base::ProcessId otherProcess;
|
||||
nsCString displayName;
|
||||
ok = aGMPServiceChild->SendLaunchGMP(pluginId, alreadyBridgedTo, &otherProcess,
|
||||
&displayName, &rv);
|
||||
if (!ok || rv == NS_ERROR_ILLEGAL_DURING_SHUTDOWN) {
|
||||
mCallback->Done(nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<GMPContentParent> parent;
|
||||
aGMPServiceChild->GetBridgedGMPContentParent(otherProcess,
|
||||
getter_AddRefs(parent));
|
||||
if (!alreadyBridgedTo.Contains(otherProcess)) {
|
||||
parent->SetDisplayName(displayName);
|
||||
parent->SetPluginId(pluginId);
|
||||
}
|
||||
|
||||
mCallback->Done(parent);
|
||||
}
|
||||
|
||||
private:
|
||||
RefPtr<GMPCrashHelper> mHelper;
|
||||
nsCString mNodeId;
|
||||
nsCString mAPI;
|
||||
const nsTArray<nsCString> mTags;
|
||||
UniquePtr<GetGMPContentParentCallback> mCallback;
|
||||
};
|
||||
|
||||
bool
|
||||
GeckoMediaPluginServiceChild::GetContentParentFrom(GMPCrashHelper* aHelper,
|
||||
const nsACString& aNodeId,
|
||||
const nsCString& aAPI,
|
||||
const nsTArray<nsCString>& aTags,
|
||||
UniquePtr<GetGMPContentParentCallback>&& aCallback)
|
||||
RefPtr<GetGMPContentParentPromise>
|
||||
GeckoMediaPluginServiceChild::GetContentParent(GMPCrashHelper* aHelper,
|
||||
const nsACString& aNodeId,
|
||||
const nsCString& aAPI,
|
||||
const nsTArray<nsCString>& aTags)
|
||||
{
|
||||
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
|
||||
|
||||
UniquePtr<GetServiceChildCallback> callback(
|
||||
new GetContentParentFromDone(aHelper, aNodeId, aAPI, aTags, Move(aCallback)));
|
||||
GetServiceChild(Move(callback));
|
||||
MozPromiseHolder<GetGMPContentParentPromise>* rawHolder = new MozPromiseHolder<GetGMPContentParentPromise>();
|
||||
RefPtr<GetGMPContentParentPromise> promise = rawHolder->Ensure(__func__);
|
||||
RefPtr<AbstractThread> thread(GetAbstractGMPThread());
|
||||
|
||||
return true;
|
||||
nsCString nodeId(aNodeId);
|
||||
nsCString api(aAPI);
|
||||
nsTArray<nsCString> tags(aTags);
|
||||
RefPtr<GMPCrashHelper> helper(aHelper);
|
||||
RefPtr<GeckoMediaPluginServiceChild> self(this);
|
||||
GetServiceChild()->Then(thread, __func__,
|
||||
[self, nodeId, api, tags, helper, rawHolder](GMPServiceChild* child) {
|
||||
UniquePtr<MozPromiseHolder<GetGMPContentParentPromise>> holder(rawHolder);
|
||||
nsresult rv;
|
||||
|
||||
nsTArray<base::ProcessId> alreadyBridgedTo;
|
||||
child->GetAlreadyBridgedTo(alreadyBridgedTo);
|
||||
|
||||
base::ProcessId otherProcess;
|
||||
nsCString displayName;
|
||||
uint32_t pluginId = 0;
|
||||
bool ok = child->SendLaunchGMP(nodeId,
|
||||
api,
|
||||
tags,
|
||||
alreadyBridgedTo,
|
||||
&pluginId,
|
||||
&otherProcess,
|
||||
&displayName,
|
||||
&rv);
|
||||
if (helper && pluginId) {
|
||||
// Note: Even if the launch failed, we need to connect the crash
|
||||
// helper so that if the launch failed due to the plugin crashing,
|
||||
// we can report the crash via the crash reporter. The crash
|
||||
// handling notification will arrive shortly if the launch failed
|
||||
// due to the plugin crashing.
|
||||
self->ConnectCrashHelper(pluginId, helper);
|
||||
}
|
||||
|
||||
if (!ok || NS_FAILED(rv)) {
|
||||
LOGD(("GeckoMediaPluginServiceChild::GetContentParent SendLaunchGMP failed rv=%d", rv));
|
||||
holder->Reject(rv, __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<GMPContentParent> parent;
|
||||
child->GetBridgedGMPContentParent(otherProcess, getter_AddRefs(parent));
|
||||
if (!alreadyBridgedTo.Contains(otherProcess)) {
|
||||
parent->SetDisplayName(displayName);
|
||||
parent->SetPluginId(pluginId);
|
||||
}
|
||||
RefPtr<GMPContentParent::CloseBlocker> blocker(new GMPContentParent::CloseBlocker(parent));
|
||||
holder->Resolve(blocker, __func__);
|
||||
},
|
||||
[rawHolder](nsresult rv) {
|
||||
UniquePtr<MozPromiseHolder<GetGMPContentParentPromise>> holder(rawHolder);
|
||||
holder->Reject(rv, __func__);
|
||||
});
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
typedef mozilla::dom::GMPCapabilityData GMPCapabilityData;
|
||||
|
@ -244,46 +231,6 @@ GeckoMediaPluginServiceChild::HasPluginForAPI(const nsACString& aAPI,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
class GetNodeIdDone : public GetServiceChildCallback
|
||||
{
|
||||
public:
|
||||
GetNodeIdDone(const nsAString& aOrigin, const nsAString& aTopLevelOrigin,
|
||||
const nsAString& aGMPName,
|
||||
bool aInPrivateBrowsing, UniquePtr<GetNodeIdCallback>&& aCallback)
|
||||
: mOrigin(aOrigin),
|
||||
mTopLevelOrigin(aTopLevelOrigin),
|
||||
mGMPName(aGMPName),
|
||||
mInPrivateBrowsing(aInPrivateBrowsing),
|
||||
mCallback(Move(aCallback))
|
||||
{
|
||||
}
|
||||
|
||||
void Done(GMPServiceChild* aGMPServiceChild) override
|
||||
{
|
||||
if (!aGMPServiceChild) {
|
||||
mCallback->Done(NS_ERROR_FAILURE, EmptyCString());
|
||||
return;
|
||||
}
|
||||
|
||||
nsCString outId;
|
||||
if (!aGMPServiceChild->SendGetGMPNodeId(mOrigin, mTopLevelOrigin,
|
||||
mGMPName,
|
||||
mInPrivateBrowsing, &outId)) {
|
||||
mCallback->Done(NS_ERROR_FAILURE, EmptyCString());
|
||||
return;
|
||||
}
|
||||
|
||||
mCallback->Done(NS_OK, outId);
|
||||
}
|
||||
|
||||
private:
|
||||
nsString mOrigin;
|
||||
nsString mTopLevelOrigin;
|
||||
nsString mGMPName;
|
||||
bool mInPrivateBrowsing;
|
||||
UniquePtr<GetNodeIdCallback> mCallback;
|
||||
};
|
||||
|
||||
NS_IMETHODIMP
|
||||
GeckoMediaPluginServiceChild::GetNodeId(const nsAString& aOrigin,
|
||||
const nsAString& aTopLevelOrigin,
|
||||
|
@ -291,9 +238,32 @@ GeckoMediaPluginServiceChild::GetNodeId(const nsAString& aOrigin,
|
|||
bool aInPrivateBrowsing,
|
||||
UniquePtr<GetNodeIdCallback>&& aCallback)
|
||||
{
|
||||
UniquePtr<GetServiceChildCallback> callback(
|
||||
new GetNodeIdDone(aOrigin, aTopLevelOrigin, aGMPName, aInPrivateBrowsing, Move(aCallback)));
|
||||
GetServiceChild(Move(callback));
|
||||
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
|
||||
|
||||
GetNodeIdCallback* rawCallback = aCallback.release();
|
||||
RefPtr<AbstractThread> thread(GetAbstractGMPThread());
|
||||
nsString origin(aOrigin);
|
||||
nsString topLevelOrigin(aTopLevelOrigin);
|
||||
nsString gmpName(aGMPName);
|
||||
bool pb = aInPrivateBrowsing;
|
||||
GetServiceChild()->Then(thread, __func__,
|
||||
[rawCallback, origin, topLevelOrigin, gmpName, pb](GMPServiceChild* child) {
|
||||
UniquePtr<GetNodeIdCallback> callback(rawCallback);
|
||||
nsCString outId;
|
||||
if (!child->SendGetGMPNodeId(origin, topLevelOrigin,
|
||||
gmpName,
|
||||
pb, &outId)) {
|
||||
callback->Done(NS_ERROR_FAILURE, EmptyCString());
|
||||
return;
|
||||
}
|
||||
|
||||
callback->Done(NS_OK, outId);
|
||||
},
|
||||
[rawCallback](nsresult rv) {
|
||||
UniquePtr<GetNodeIdCallback> callback(rawCallback);
|
||||
callback->Done(NS_ERROR_FAILURE, EmptyCString());
|
||||
});
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -316,41 +286,46 @@ GeckoMediaPluginServiceChild::Observe(nsISupports* aSubject,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
GeckoMediaPluginServiceChild::GetServiceChild(UniquePtr<GetServiceChildCallback>&& aCallback)
|
||||
RefPtr<GeckoMediaPluginServiceChild::GetServiceChildPromise>
|
||||
GeckoMediaPluginServiceChild::GetServiceChild()
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
|
||||
|
||||
if (!mServiceChild) {
|
||||
dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
|
||||
if (!contentChild) {
|
||||
return;
|
||||
return GetServiceChildPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
|
||||
}
|
||||
mGetServiceChildCallbacks.AppendElement(Move(aCallback));
|
||||
if (mGetServiceChildCallbacks.Length() == 1) {
|
||||
MozPromiseHolder<GetServiceChildPromise>* holder = mGetServiceChildPromises.AppendElement();
|
||||
RefPtr<GetServiceChildPromise> promise = holder->Ensure(__func__);
|
||||
if (mGetServiceChildPromises.Length() == 1) {
|
||||
NS_DispatchToMainThread(WrapRunnable(contentChild,
|
||||
&dom::ContentChild::SendCreateGMPService));
|
||||
}
|
||||
return;
|
||||
return promise;
|
||||
}
|
||||
|
||||
aCallback->Done(mServiceChild.get());
|
||||
return GetServiceChildPromise::CreateAndResolve(mServiceChild.get(), __func__);
|
||||
}
|
||||
|
||||
void
|
||||
GeckoMediaPluginServiceChild::SetServiceChild(UniquePtr<GMPServiceChild>&& aServiceChild)
|
||||
{
|
||||
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
|
||||
|
||||
mServiceChild = Move(aServiceChild);
|
||||
nsTArray<UniquePtr<GetServiceChildCallback>> getServiceChildCallbacks;
|
||||
getServiceChildCallbacks.SwapElements(mGetServiceChildCallbacks);
|
||||
for (uint32_t i = 0, length = getServiceChildCallbacks.Length(); i < length; ++i) {
|
||||
getServiceChildCallbacks[i]->Done(mServiceChild.get());
|
||||
|
||||
nsTArray<MozPromiseHolder<GetServiceChildPromise>> holders;
|
||||
holders.SwapElements(mGetServiceChildPromises);
|
||||
for (MozPromiseHolder<GetServiceChildPromise>& holder : holders) {
|
||||
holder.Resolve(mServiceChild.get(), __func__);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GeckoMediaPluginServiceChild::RemoveGMPContentParent(GMPContentParent* aGMPContentParent)
|
||||
{
|
||||
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
|
||||
|
||||
if (mServiceChild) {
|
||||
mServiceChild->RemoveGMPContentParent(aGMPContentParent);
|
||||
}
|
||||
|
|
|
@ -19,20 +19,6 @@ namespace gmp {
|
|||
class GMPContentParent;
|
||||
class GMPServiceChild;
|
||||
|
||||
class GetServiceChildCallback
|
||||
{
|
||||
public:
|
||||
GetServiceChildCallback()
|
||||
{
|
||||
MOZ_COUNT_CTOR(GetServiceChildCallback);
|
||||
}
|
||||
virtual ~GetServiceChildCallback()
|
||||
{
|
||||
MOZ_COUNT_DTOR(GetServiceChildCallback);
|
||||
}
|
||||
virtual void Done(GMPServiceChild* aGMPServiceChild) = 0;
|
||||
};
|
||||
|
||||
class GeckoMediaPluginServiceChild : public GeckoMediaPluginService
|
||||
{
|
||||
friend class GMPServiceChild;
|
||||
|
@ -62,20 +48,21 @@ protected:
|
|||
{
|
||||
// Nothing to do here.
|
||||
}
|
||||
bool GetContentParentFrom(GMPCrashHelper* aHelper,
|
||||
const nsACString& aNodeId,
|
||||
const nsCString& aAPI,
|
||||
const nsTArray<nsCString>& aTags,
|
||||
UniquePtr<GetGMPContentParentCallback>&& aCallback)
|
||||
override;
|
||||
|
||||
virtual RefPtr<GetGMPContentParentPromise>
|
||||
GetContentParent(GMPCrashHelper* aHelper,
|
||||
const nsACString& aNodeId,
|
||||
const nsCString& aAPI,
|
||||
const nsTArray<nsCString>& aTags) override;
|
||||
|
||||
private:
|
||||
friend class OpenPGMPServiceChild;
|
||||
|
||||
void GetServiceChild(UniquePtr<GetServiceChildCallback>&& aCallback);
|
||||
typedef MozPromise<GMPServiceChild*, nsresult, /* IsExclusive = */ true> GetServiceChildPromise;
|
||||
RefPtr<GetServiceChildPromise> GetServiceChild();
|
||||
|
||||
nsTArray<MozPromiseHolder<GetServiceChildPromise>> mGetServiceChildPromises;
|
||||
UniquePtr<GMPServiceChild> mServiceChild;
|
||||
nsTArray<UniquePtr<GetServiceChildCallback>> mGetServiceChildCallbacks;
|
||||
};
|
||||
|
||||
class GMPServiceChild : public PGMPServiceChild
|
||||
|
|
|
@ -529,43 +529,45 @@ GeckoMediaPluginServiceParent::EnsureInitialized() {
|
|||
return mInitPromise.Ensure(__func__);
|
||||
}
|
||||
|
||||
bool
|
||||
GeckoMediaPluginServiceParent::GetContentParentFrom(GMPCrashHelper* aHelper,
|
||||
const nsACString& aNodeId,
|
||||
const nsCString& aAPI,
|
||||
const nsTArray<nsCString>& aTags,
|
||||
UniquePtr<GetGMPContentParentCallback>&& aCallback)
|
||||
RefPtr<GetGMPContentParentPromise>
|
||||
GeckoMediaPluginServiceParent::GetContentParent(GMPCrashHelper* aHelper,
|
||||
const nsACString& aNodeId,
|
||||
const nsCString& aAPI,
|
||||
const nsTArray<nsCString>& aTags)
|
||||
{
|
||||
RefPtr<AbstractThread> thread(GetAbstractGMPThread());
|
||||
if (!thread) {
|
||||
return false;
|
||||
return GetGMPContentParentPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
|
||||
}
|
||||
|
||||
typedef MozPromiseHolder<GetGMPContentParentPromise> PromiseHolder;
|
||||
PromiseHolder* rawHolder = new PromiseHolder();
|
||||
RefPtr<GeckoMediaPluginServiceParent> self(this);
|
||||
RefPtr<GetGMPContentParentPromise> promise = rawHolder->Ensure(__func__);
|
||||
nsCString nodeId(aNodeId);
|
||||
nsTArray<nsCString> tags(aTags);
|
||||
nsCString api(aAPI);
|
||||
GetGMPContentParentCallback* rawCallback = aCallback.release();
|
||||
RefPtr<GMPCrashHelper> helper(aHelper);
|
||||
EnsureInitialized()->Then(thread, __func__,
|
||||
[self, tags, api, nodeId, rawCallback, helper]() -> void {
|
||||
UniquePtr<GetGMPContentParentCallback> callback(rawCallback);
|
||||
[self, tags, api, nodeId, helper, rawHolder]() -> void {
|
||||
UniquePtr<PromiseHolder> holder(rawHolder);
|
||||
RefPtr<GMPParent> gmp = self->SelectPluginForAPI(nodeId, api, tags);
|
||||
LOGD(("%s: %p returning %p for api %s", __FUNCTION__, (void *)self, (void *)gmp, api.get()));
|
||||
if (!gmp) {
|
||||
NS_WARNING("GeckoMediaPluginServiceParent::GetContentParentFrom failed");
|
||||
callback->Done(nullptr);
|
||||
holder->Reject(NS_ERROR_FAILURE, __func__);
|
||||
return;
|
||||
}
|
||||
self->ConnectCrashHelper(gmp->GetPluginId(), helper);
|
||||
gmp->GetGMPContentParent(Move(callback));
|
||||
gmp->GetGMPContentParent(Move(holder));
|
||||
},
|
||||
[rawCallback]() -> void {
|
||||
UniquePtr<GetGMPContentParentCallback> callback(rawCallback);
|
||||
[rawHolder]() -> void {
|
||||
UniquePtr<PromiseHolder> holder(rawHolder);
|
||||
NS_WARNING("GMPService::EnsureInitialized failed.");
|
||||
callback->Done(nullptr);
|
||||
holder->Reject(NS_ERROR_FAILURE, __func__);
|
||||
});
|
||||
return true;
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1965,10 +1967,13 @@ GMPServiceParent::~GMPServiceParent()
|
|||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
GMPServiceParent::RecvSelectGMP(const nsCString& aNodeId,
|
||||
GMPServiceParent::RecvLaunchGMP(const nsCString& aNodeId,
|
||||
const nsCString& aAPI,
|
||||
nsTArray<nsCString>&& aTags,
|
||||
nsTArray<ProcessId>&& aAlreadyBridgedTo,
|
||||
uint32_t* aOutPluginId,
|
||||
ProcessId* aOutProcessId,
|
||||
nsCString* aOutDisplayName,
|
||||
nsresult* aOutRv)
|
||||
{
|
||||
if (mService->IsShuttingDown()) {
|
||||
|
@ -1979,45 +1984,25 @@ GMPServiceParent::RecvSelectGMP(const nsCString& aNodeId,
|
|||
RefPtr<GMPParent> gmp = mService->SelectPluginForAPI(aNodeId, aAPI, aTags);
|
||||
if (gmp) {
|
||||
*aOutPluginId = gmp->GetPluginId();
|
||||
*aOutRv = NS_OK;
|
||||
} else {
|
||||
*aOutRv = NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCString api = aTags[0];
|
||||
LOGD(("%s: %p returning %p for api %s", __FUNCTION__, (void *)this, (void *)gmp, api.get()));
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
GMPServiceParent::RecvLaunchGMP(const uint32_t& aPluginId,
|
||||
nsTArray<ProcessId>&& aAlreadyBridgedTo,
|
||||
ProcessId* aOutProcessId,
|
||||
nsCString* aOutDisplayName,
|
||||
nsresult* aOutRv)
|
||||
{
|
||||
*aOutRv = NS_OK;
|
||||
if (mService->IsShuttingDown()) {
|
||||
*aOutRv = NS_ERROR_ILLEGAL_DURING_SHUTDOWN;
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
RefPtr<GMPParent> gmp(mService->GetById(aPluginId));
|
||||
if (!gmp) {
|
||||
*aOutRv = NS_ERROR_FAILURE;
|
||||
*aOutPluginId = 0;
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
if (!gmp->EnsureProcessLoaded(aOutProcessId)) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
*aOutRv = NS_ERROR_FAILURE;
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
*aOutDisplayName = gmp->GetDisplayName();
|
||||
|
||||
if (!(aAlreadyBridgedTo.Contains(*aOutProcessId) || gmp->Bridge(this))) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
*aOutRv = NS_ERROR_FAILURE;
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
*aOutRv = NS_OK;
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
|
|
@ -126,12 +126,13 @@ protected:
|
|||
void InitializePlugins(AbstractThread* aAbstractGMPThread) override;
|
||||
RefPtr<GenericPromise::AllPromiseType> LoadFromEnvironment();
|
||||
RefPtr<GenericPromise> AddOnGMPThread(nsString aDirectory);
|
||||
bool GetContentParentFrom(GMPCrashHelper* aHelper,
|
||||
const nsACString& aNodeId,
|
||||
const nsCString& aAPI,
|
||||
const nsTArray<nsCString>& aTags,
|
||||
UniquePtr<GetGMPContentParentCallback>&& aCallback)
|
||||
override;
|
||||
|
||||
virtual RefPtr<GetGMPContentParentPromise>
|
||||
GetContentParent(GMPCrashHelper* aHelper,
|
||||
const nsACString& aNodeId,
|
||||
const nsCString& aAPI,
|
||||
const nsTArray<nsCString>& aTags) override;
|
||||
|
||||
private:
|
||||
// Creates a copy of aOriginal. Note that the caller is responsible for
|
||||
// adding this to GeckoMediaPluginServiceParent::mPlugins.
|
||||
|
@ -255,14 +256,11 @@ public:
|
|||
|
||||
static PGMPServiceParent* Create(Transport* aTransport, ProcessId aOtherPid);
|
||||
|
||||
mozilla::ipc::IPCResult RecvSelectGMP(const nsCString& aNodeId,
|
||||
mozilla::ipc::IPCResult RecvLaunchGMP(const nsCString& aNodeId,
|
||||
const nsCString& aAPI,
|
||||
nsTArray<nsCString>&& aTags,
|
||||
uint32_t* aOutPluginId,
|
||||
nsresult* aOutRv) override;
|
||||
|
||||
mozilla::ipc::IPCResult RecvLaunchGMP(const uint32_t& aPluginId,
|
||||
nsTArray<ProcessId>&& aAlreadyBridgedTo,
|
||||
uint32_t* aOutPluginId,
|
||||
ProcessId* aOutID,
|
||||
nsCString* aOutDisplayName,
|
||||
nsresult* aOutRv) override;
|
||||
|
|
|
@ -16,11 +16,11 @@ sync protocol PGMPService
|
|||
|
||||
parent:
|
||||
|
||||
sync SelectGMP(nsCString nodeId, nsCString api, nsCString[] tags)
|
||||
returns (uint32_t pluginId, nsresult aResult);
|
||||
|
||||
sync LaunchGMP(uint32_t pluginId, ProcessId[] alreadyBridgedTo)
|
||||
returns (ProcessId id, nsCString displayName, nsresult aResult);
|
||||
sync LaunchGMP(nsCString nodeId,
|
||||
nsCString api,
|
||||
nsCString[] tags,
|
||||
ProcessId[] alreadyBridgedTo)
|
||||
returns (uint32_t pluginId, ProcessId id, nsCString displayName, nsresult aResult);
|
||||
|
||||
sync GetGMPNodeId(nsString origin, nsString topLevelOrigin,
|
||||
nsString gmpName,
|
||||
|
|
|
@ -19,7 +19,10 @@ function runWithMSE(testFunction) {
|
|||
|
||||
document.body.appendChild(el);
|
||||
SimpleTest.registerCleanupFunction(function () {
|
||||
el.parentNode.removeChild(el);
|
||||
el.remove();
|
||||
// Don't trigger load algorithm to prevent 'error' events.
|
||||
el.preload = "none";
|
||||
el.src = null;
|
||||
});
|
||||
|
||||
testFunction(ms, el);
|
||||
|
|
|
@ -264,19 +264,24 @@ function LoadTest(test, elem, token, loadParams)
|
|||
});
|
||||
}
|
||||
|
||||
// Same as LoadTest, but manage a token+"_load" start&finished.
|
||||
// Also finish main token if loading fails.
|
||||
function LoadTestWithManagedLoadToken(test, elem, manager, token, loadParams)
|
||||
{
|
||||
manager.started(token + "_load");
|
||||
return LoadTest(test, elem, token, loadParams)
|
||||
.catch(function (reason) {
|
||||
ok(false, TimeStamp(token) + " - Error during load: " + reason);
|
||||
manager.finished(token + "_load");
|
||||
function EMEPromise() {
|
||||
var self = this;
|
||||
self.promise = new Promise(function(resolve, reject) {
|
||||
self.resolve = resolve;
|
||||
self.reject = reject;
|
||||
});
|
||||
}
|
||||
|
||||
// Finish |token| when all promises are resolved or any one promise is
|
||||
// rejected. It also clean up the media element to release resources.
|
||||
function EMEPromiseAll(v, token, promises) {
|
||||
Promise.all(promises).then(values => {
|
||||
removeNodeAndSource(v);
|
||||
manager.finished(token);
|
||||
}, reason => {
|
||||
ok(false, TimeStamp(token) + " - Error during load: " + reason);
|
||||
removeNodeAndSource(v);
|
||||
manager.finished(token);
|
||||
})
|
||||
.then(function () {
|
||||
manager.finished(token + "_load");
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -120,8 +120,11 @@ function nextTest() {
|
|||
}
|
||||
}
|
||||
|
||||
if (gVideo && gVideo.parentNode)
|
||||
gVideo.parentNode.removeChild(gVideo);
|
||||
if (gVideo) {
|
||||
gVideo.remove();
|
||||
gVideo.preload = "none"; // Don't trigger load algorithm.
|
||||
gVideo.src = null;
|
||||
}
|
||||
|
||||
gVideo = null;
|
||||
SpecialPowers.forceGC();
|
||||
|
|
|
@ -21,6 +21,7 @@ function startTest(test, token)
|
|||
var v = SetupEME(test, token);
|
||||
v.preload = "auto"; // Required due to "canplay" not firing for MSE unless we do this.
|
||||
|
||||
var p1 = new EMEPromise;
|
||||
v.addEventListener("loadeddata", function(ev) {
|
||||
var video = ev.target;
|
||||
var canvas = document.createElement("canvas");
|
||||
|
@ -35,11 +36,11 @@ function startTest(test, token)
|
|||
threwError = true;
|
||||
}
|
||||
ok(threwError, TimeStamp(token) + " - Should throw an error when trying to draw EME video to canvas.");
|
||||
manager.finished(token);
|
||||
p1.resolve();
|
||||
});
|
||||
|
||||
LoadTestWithManagedLoadToken(test, v, manager, token,
|
||||
{ onlyLoadFirstFragments:2, noEndOfStream:false });
|
||||
var p2 = LoadTest(test, v, token, { onlyLoadFirstFragments:2, noEndOfStream:false });
|
||||
EMEPromiseAll(v, token, [p1.promise, p2]);
|
||||
}
|
||||
|
||||
function beginTest() {
|
||||
|
|
|
@ -20,10 +20,11 @@ function startTest(test, token)
|
|||
// 3. capturing a media element with mozCaptureStream that has a MediaKeys should fail.
|
||||
|
||||
// Case 1. setting MediaKeys on an element captured by MediaElementSource should fail.
|
||||
var p1 = new EMEPromise;
|
||||
var case1token = token + "_case1";
|
||||
var setKeysFailed = function() {
|
||||
ok(true, TimeStamp(case1token) + " setMediaKeys failed as expected.");
|
||||
manager.finished(case1token);
|
||||
p1.resolve();
|
||||
};
|
||||
var v1 = SetupEME(test, case1token, { onSetKeysFail: setKeysFailed });
|
||||
var context = new AudioContext();
|
||||
|
@ -32,8 +33,8 @@ function startTest(test, token)
|
|||
ok(false, TimeStamp(case1token) + " should never reach loadeddata, as setMediaKeys should fail");
|
||||
});
|
||||
manager.started(case1token);
|
||||
LoadTestWithManagedLoadToken(test, v1, manager, case1token,
|
||||
{ onlyLoadFirstFragments:2, noEndOfStream:false });
|
||||
var p2 = LoadTest(test, v1, case1token, { onlyLoadFirstFragments:2, noEndOfStream:false });
|
||||
EMEPromiseAll(v1, case1token, [p1.promise, p2]);
|
||||
}
|
||||
|
||||
function beginTest() {
|
||||
|
|
|
@ -20,6 +20,7 @@ function startTest(test, token)
|
|||
// 3. capturing a media element with mozCaptureStream that has a MediaKeys should fail.
|
||||
|
||||
// Case 2. creating a MediaElementSource on a media element with a MediaKeys should fail.
|
||||
var p1 = new EMEPromise;
|
||||
var case2token = token + "_case2";
|
||||
var v2 = SetupEME(test, case2token);
|
||||
v2.addEventListener("loadeddata", function(ev) {
|
||||
|
@ -32,11 +33,11 @@ function startTest(test, token)
|
|||
threw = true;
|
||||
}
|
||||
ok(threw, "Should throw an error creating a MediaElementSource on an EME video.");
|
||||
manager.finished(case2token);
|
||||
p1.resolve();
|
||||
});
|
||||
manager.started(case2token);
|
||||
LoadTestWithManagedLoadToken(test, v2, manager, case2token,
|
||||
{ onlyLoadFirstFragments:2, noEndOfStream:false });
|
||||
var p2 = LoadTest(test, v2, case2token, { onlyLoadFirstFragments:2, noEndOfStream:false });
|
||||
EMEPromiseAll(v2, case2token, [p1.promise, p2]);
|
||||
}
|
||||
|
||||
function beginTest() {
|
||||
|
|
|
@ -20,6 +20,7 @@ function startTest(test, token)
|
|||
// 3. capturing a media element with mozCaptureStream that has a MediaKeys should fail.
|
||||
|
||||
// Case 3. capturing a media element with mozCaptureStream that has a MediaKeys should fail.
|
||||
var p1 = new EMEPromise;
|
||||
var case3token = token + "_case3";
|
||||
var v3 = SetupEME(test, case3token);
|
||||
v3.addEventListener("loadeddata", function(ev) {
|
||||
|
@ -31,11 +32,11 @@ function startTest(test, token)
|
|||
threw = true;
|
||||
}
|
||||
ok(threw, TimeStamp(case3token) + " Should throw an error calling mozCaptureStreamUntilEnded an EME video.");
|
||||
manager.finished(case3token);
|
||||
p1.resolve();
|
||||
});
|
||||
manager.started(case3token);
|
||||
LoadTestWithManagedLoadToken(test, v3, manager, case3token,
|
||||
{ onlyLoadFirstFragments:2, noEndOfStream:false });
|
||||
var p2 = LoadTest(test, v3, case3token, { onlyLoadFirstFragments:2, noEndOfStream:false });
|
||||
EMEPromiseAll(v3, case3token, [p1.promise, p2]);
|
||||
}
|
||||
|
||||
function beginTest() {
|
||||
|
|
|
@ -119,9 +119,7 @@ function startTest(test, token) {
|
|||
ok(a, name + ": " + msg);
|
||||
}}(name);
|
||||
var localFinish = function(v, manager) { return function() {
|
||||
if (v.parentNode) {
|
||||
v.parentNode.removeChild(v);
|
||||
}
|
||||
removeNodeAndSource(v);
|
||||
manager.finished(v.token);
|
||||
}}(v, manager);
|
||||
window['test_fragment_noplay'](v, test.start, test.end, localIs, localOk, localFinish);
|
||||
|
|
|
@ -235,19 +235,18 @@ already_AddRefed<Element>
|
|||
HTMLEditor::CreateGrabber(nsINode* aParentNode)
|
||||
{
|
||||
// let's create a grabber through the element factory
|
||||
nsCOMPtr<nsIDOMElement> retDOM;
|
||||
CreateAnonymousElement(NS_LITERAL_STRING("span"), GetAsDOMNode(aParentNode),
|
||||
NS_LITERAL_STRING("mozGrabber"), false,
|
||||
getter_AddRefs(retDOM));
|
||||
|
||||
NS_ENSURE_TRUE(retDOM, nullptr);
|
||||
RefPtr<Element> ret =
|
||||
CreateAnonymousElement(nsGkAtoms::span, GetAsDOMNode(aParentNode),
|
||||
NS_LITERAL_STRING("mozGrabber"), false);
|
||||
if (NS_WARN_IF(!ret)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// add the mouse listener so we can detect a click on a resizer
|
||||
nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(retDOM));
|
||||
nsCOMPtr<nsIDOMEventTarget> evtTarget = do_QueryInterface(ret);
|
||||
evtTarget->AddEventListener(NS_LITERAL_STRING("mousedown"),
|
||||
mEventListener, false);
|
||||
|
||||
nsCOMPtr<Element> ret = do_QueryInterface(retDOM);
|
||||
return ret.forget();
|
||||
}
|
||||
|
||||
|
@ -271,7 +270,7 @@ HTMLEditor::RefreshGrabber()
|
|||
|
||||
SetAnonymousElementPosition(mPositionedObjectX+12,
|
||||
mPositionedObjectY-14,
|
||||
static_cast<nsIDOMElement*>(GetAsDOMNode(mGrabber)));
|
||||
mGrabber);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -295,9 +294,9 @@ HTMLEditor::HideGrabber()
|
|||
nsCOMPtr<nsIContent> parentContent = mGrabber->GetParent();
|
||||
NS_ENSURE_TRUE(parentContent, NS_ERROR_NULL_POINTER);
|
||||
|
||||
DeleteRefToAnonymousNode(static_cast<nsIDOMElement*>(GetAsDOMNode(mGrabber)), parentContent, ps);
|
||||
DeleteRefToAnonymousNode(mGrabber, parentContent, ps);
|
||||
mGrabber = nullptr;
|
||||
DeleteRefToAnonymousNode(static_cast<nsIDOMElement*>(GetAsDOMNode(mPositioningShadow)), parentContent, ps);
|
||||
DeleteRefToAnonymousNode(mPositioningShadow, parentContent, ps);
|
||||
mPositioningShadow = nullptr;
|
||||
|
||||
return NS_OK;
|
||||
|
@ -400,8 +399,7 @@ HTMLEditor::EndMoving()
|
|||
nsCOMPtr<nsIContent> parentContent = mGrabber->GetParent();
|
||||
NS_ENSURE_TRUE(parentContent, NS_ERROR_FAILURE);
|
||||
|
||||
DeleteRefToAnonymousNode(static_cast<nsIDOMElement*>(GetAsDOMNode(mPositioningShadow)),
|
||||
parentContent, ps);
|
||||
DeleteRefToAnonymousNode(mPositioningShadow, parentContent, ps);
|
||||
|
||||
mPositioningShadow = nullptr;
|
||||
}
|
||||
|
|
|
@ -161,51 +161,56 @@ ElementDeletionObserver::NodeWillBeDestroyed(const nsINode* aNode)
|
|||
NS_RELEASE_THIS();
|
||||
}
|
||||
|
||||
// Returns in *aReturn an anonymous nsDOMElement of type aTag,
|
||||
// child of aParentNode. If aIsCreatedHidden is true, the class
|
||||
// "hidden" is added to the created element. If aAnonClass is not
|
||||
// the empty string, it becomes the value of the attribute "_moz_anonclass"
|
||||
nsresult
|
||||
HTMLEditor::CreateAnonymousElement(const nsAString& aTag,
|
||||
already_AddRefed<Element>
|
||||
HTMLEditor::CreateAnonymousElement(nsIAtom* aTag,
|
||||
nsIDOMNode* aParentNode,
|
||||
const nsAString& aAnonClass,
|
||||
bool aIsCreatedHidden,
|
||||
nsIDOMElement** aReturn)
|
||||
bool aIsCreatedHidden)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aParentNode);
|
||||
NS_ENSURE_ARG_POINTER(aReturn);
|
||||
*aReturn = nullptr;
|
||||
if (NS_WARN_IF(!aParentNode)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> parentContent( do_QueryInterface(aParentNode) );
|
||||
NS_ENSURE_TRUE(parentContent, NS_OK);
|
||||
nsCOMPtr<nsIContent> parentContent = do_QueryInterface(aParentNode);
|
||||
if (NS_WARN_IF(!parentContent)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = GetDocument();
|
||||
NS_ENSURE_TRUE(doc, NS_ERROR_NULL_POINTER);
|
||||
if (NS_WARN_IF(!doc)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Get the pres shell
|
||||
nsCOMPtr<nsIPresShell> ps = GetPresShell();
|
||||
NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
|
||||
if (NS_WARN_IF(!ps)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Create a new node through the element factory
|
||||
nsCOMPtr<nsIAtom> tagAtom = NS_Atomize(aTag);
|
||||
nsCOMPtr<Element> newContent = CreateHTMLContent(tagAtom);
|
||||
NS_ENSURE_STATE(newContent);
|
||||
|
||||
nsCOMPtr<nsIDOMElement> newElement = do_QueryInterface(newContent);
|
||||
NS_ENSURE_TRUE(newElement, NS_ERROR_FAILURE);
|
||||
RefPtr<Element> newContent = CreateHTMLContent(aTag);
|
||||
if (NS_WARN_IF(!newContent)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// add the "hidden" class if needed
|
||||
if (aIsCreatedHidden) {
|
||||
nsresult rv = newElement->SetAttribute(NS_LITERAL_STRING("class"),
|
||||
NS_LITERAL_STRING("hidden"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsresult rv =
|
||||
newContent->SetAttr(kNameSpaceID_None, nsGkAtoms::_class,
|
||||
NS_LITERAL_STRING("hidden"), true);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// add an _moz_anonclass attribute if needed
|
||||
if (!aAnonClass.IsEmpty()) {
|
||||
nsresult rv = newElement->SetAttribute(NS_LITERAL_STRING("_moz_anonclass"),
|
||||
aAnonClass);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsresult rv =
|
||||
newContent->SetAttr(kNameSpaceID_None, nsGkAtoms::_moz_anonclass,
|
||||
aAnonClass, true);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -217,7 +222,7 @@ HTMLEditor::CreateAnonymousElement(const nsAString& aTag,
|
|||
newContent->BindToTree(doc, parentContent, parentContent, true);
|
||||
if (NS_FAILED(rv)) {
|
||||
newContent->UnbindFromTree();
|
||||
return rv;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -239,8 +244,7 @@ HTMLEditor::CreateAnonymousElement(const nsAString& aTag,
|
|||
// display the element
|
||||
ps->RecreateFramesFor(newContent);
|
||||
|
||||
newElement.forget(aReturn);
|
||||
return NS_OK;
|
||||
return newContent.forget();
|
||||
}
|
||||
|
||||
// Removes event listener and calls DeleteRefToAnonymousNode.
|
||||
|
@ -256,12 +260,12 @@ HTMLEditor::RemoveListenerAndDeleteRef(const nsAString& aEvent,
|
|||
if (evtTarget) {
|
||||
evtTarget->RemoveEventListener(aEvent, aListener, aUseCapture);
|
||||
}
|
||||
DeleteRefToAnonymousNode(static_cast<nsIDOMElement*>(GetAsDOMNode(aElement)), aParentContent, aShell);
|
||||
DeleteRefToAnonymousNode(aElement, aParentContent, aShell);
|
||||
}
|
||||
|
||||
// Deletes all references to an anonymous element
|
||||
void
|
||||
HTMLEditor::DeleteRefToAnonymousNode(nsIDOMElement* aElement,
|
||||
HTMLEditor::DeleteRefToAnonymousNode(nsIContent* aContent,
|
||||
nsIContent* aParentContent,
|
||||
nsIPresShell* aShell)
|
||||
{
|
||||
|
@ -269,38 +273,37 @@ HTMLEditor::DeleteRefToAnonymousNode(nsIDOMElement* aElement,
|
|||
// node so its references get removed from the frame manager's
|
||||
// undisplay map, and its layout frames get destroyed!
|
||||
|
||||
if (aElement) {
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
|
||||
if (content) {
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
// Need to check whether aShell has been destroyed (but not yet deleted).
|
||||
// In that case presContext->GetPresShell() returns nullptr.
|
||||
// See bug 338129.
|
||||
if (content->IsInComposedDoc() && aShell && aShell->GetPresContext() &&
|
||||
aShell->GetPresContext()->GetPresShell() == aShell) {
|
||||
nsCOMPtr<nsIDocumentObserver> docObserver = do_QueryInterface(aShell);
|
||||
if (docObserver) {
|
||||
// Call BeginUpdate() so that the nsCSSFrameConstructor/PresShell
|
||||
// knows we're messing with the frame tree.
|
||||
nsCOMPtr<nsIDocument> document = GetDocument();
|
||||
if (document) {
|
||||
docObserver->BeginUpdate(document, UPDATE_CONTENT_MODEL);
|
||||
}
|
||||
if (NS_WARN_IF(!aContent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// XXX This is wrong (bug 439258). Once it's fixed, the NS_WARNING
|
||||
// in RestyleManager::RestyleForRemove should be changed back
|
||||
// to an assertion.
|
||||
docObserver->ContentRemoved(content->GetComposedDoc(),
|
||||
aParentContent, content, -1,
|
||||
content->GetPreviousSibling());
|
||||
if (document) {
|
||||
docObserver->EndUpdate(document, UPDATE_CONTENT_MODEL);
|
||||
}
|
||||
}
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
// Need to check whether aShell has been destroyed (but not yet deleted).
|
||||
// In that case presContext->GetPresShell() returns nullptr.
|
||||
// See bug 338129.
|
||||
if (aContent->IsInComposedDoc() && aShell && aShell->GetPresContext() &&
|
||||
aShell->GetPresContext()->GetPresShell() == aShell) {
|
||||
nsCOMPtr<nsIDocumentObserver> docObserver = do_QueryInterface(aShell);
|
||||
if (docObserver) {
|
||||
// Call BeginUpdate() so that the nsCSSFrameConstructor/PresShell
|
||||
// knows we're messing with the frame tree.
|
||||
nsCOMPtr<nsIDocument> document = GetDocument();
|
||||
if (document) {
|
||||
docObserver->BeginUpdate(document, UPDATE_CONTENT_MODEL);
|
||||
}
|
||||
|
||||
// XXX This is wrong (bug 439258). Once it's fixed, the NS_WARNING
|
||||
// in RestyleManager::RestyleForRemove should be changed back
|
||||
// to an assertion.
|
||||
docObserver->ContentRemoved(aContent->GetComposedDoc(),
|
||||
aParentContent, aContent, -1,
|
||||
aContent->GetPreviousSibling());
|
||||
if (document) {
|
||||
docObserver->EndUpdate(document, UPDATE_CONTENT_MODEL);
|
||||
}
|
||||
content->UnbindFromTree();
|
||||
}
|
||||
}
|
||||
aContent->UnbindFromTree();
|
||||
}
|
||||
|
||||
// The following method is mostly called by a selection listener. When a
|
||||
|
@ -539,10 +542,10 @@ HTMLEditor::GetPositionAndDimensions(nsIDOMElement* aElement,
|
|||
void
|
||||
HTMLEditor::SetAnonymousElementPosition(int32_t aX,
|
||||
int32_t aY,
|
||||
nsIDOMElement* aElement)
|
||||
Element* aElement)
|
||||
{
|
||||
mCSSEditUtils->SetCSSPropertyPixels(aElement, NS_LITERAL_STRING("left"), aX);
|
||||
mCSSEditUtils->SetCSSPropertyPixels(aElement, NS_LITERAL_STRING("top"), aY);
|
||||
mCSSEditUtils->SetCSSPropertyPixels(*aElement, *nsGkAtoms::left, aX);
|
||||
mCSSEditUtils->SetCSSPropertyPixels(*aElement, *nsGkAtoms::top, aY);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -921,7 +921,7 @@ protected:
|
|||
Element* aElement,
|
||||
nsIContent* aParentContent,
|
||||
nsIPresShell* aShell);
|
||||
void DeleteRefToAnonymousNode(nsIDOMElement* aElement,
|
||||
void DeleteRefToAnonymousNode(nsIContent* aContent,
|
||||
nsIContent* aParentContent,
|
||||
nsIPresShell* aShell);
|
||||
|
||||
|
@ -1007,7 +1007,7 @@ protected:
|
|||
already_AddRefed<Element> CreateResizer(int16_t aLocation,
|
||||
nsIDOMNode* aParentNode);
|
||||
void SetAnonymousElementPosition(int32_t aX, int32_t aY,
|
||||
nsIDOMElement* aResizer);
|
||||
Element* aResizer);
|
||||
|
||||
already_AddRefed<Element> CreateShadow(nsIDOMNode* aParentNode,
|
||||
nsIDOMElement* aOriginalObject);
|
||||
|
@ -1062,16 +1062,16 @@ protected:
|
|||
// inline table editing
|
||||
nsCOMPtr<nsIDOMElement> mInlineEditedCell;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> mAddColumnBeforeButton;
|
||||
nsCOMPtr<nsIDOMElement> mRemoveColumnButton;
|
||||
nsCOMPtr<nsIDOMElement> mAddColumnAfterButton;
|
||||
RefPtr<Element> mAddColumnBeforeButton;
|
||||
RefPtr<Element> mRemoveColumnButton;
|
||||
RefPtr<Element> mAddColumnAfterButton;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> mAddRowBeforeButton;
|
||||
nsCOMPtr<nsIDOMElement> mRemoveRowButton;
|
||||
nsCOMPtr<nsIDOMElement> mAddRowAfterButton;
|
||||
RefPtr<Element> mAddRowBeforeButton;
|
||||
RefPtr<Element> mRemoveRowButton;
|
||||
RefPtr<Element> mAddRowAfterButton;
|
||||
|
||||
void AddMouseClickListener(nsIDOMElement* aElement);
|
||||
void RemoveMouseClickListener(nsIDOMElement* aElement);
|
||||
void AddMouseClickListener(Element* aElement);
|
||||
void RemoveMouseClickListener(Element* aElement);
|
||||
|
||||
nsCOMPtr<nsILinkHandler> mLinkHandler;
|
||||
|
||||
|
@ -1098,6 +1098,25 @@ private:
|
|||
const nsAString& aTagName, nsINode* aNode);
|
||||
already_AddRefed<Element> CreateElementWithDefaults(
|
||||
const nsAString& aTagName);
|
||||
/**
|
||||
* Returns an anonymous Element of type aTag,
|
||||
* child of aParentNode. If aIsCreatedHidden is true, the class
|
||||
* "hidden" is added to the created element. If aAnonClass is not
|
||||
* the empty string, it becomes the value of the attribute "_moz_anonclass"
|
||||
* @return a Element
|
||||
* @param aTag [IN] desired type of the element to create
|
||||
* @param aParentNode [IN] the parent node of the created anonymous
|
||||
* element
|
||||
* @param aAnonClass [IN] contents of the _moz_anonclass attribute
|
||||
* @param aIsCreatedHidden [IN] a boolean specifying if the class "hidden"
|
||||
* is to be added to the created anonymous
|
||||
* element
|
||||
*/
|
||||
already_AddRefed<Element> CreateAnonymousElement(
|
||||
nsIAtom* aTag,
|
||||
nsIDOMNode* aParentNode,
|
||||
const nsAString& aAnonClass,
|
||||
bool aIsCreatedHidden);
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -138,18 +138,17 @@ already_AddRefed<Element>
|
|||
HTMLEditor::CreateResizer(int16_t aLocation,
|
||||
nsIDOMNode* aParentNode)
|
||||
{
|
||||
nsCOMPtr<nsIDOMElement> retDOM;
|
||||
nsresult rv = CreateAnonymousElement(NS_LITERAL_STRING("span"),
|
||||
aParentNode,
|
||||
NS_LITERAL_STRING("mozResizer"),
|
||||
false,
|
||||
getter_AddRefs(retDOM));
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
NS_ENSURE_TRUE(retDOM, nullptr);
|
||||
RefPtr<Element> ret =
|
||||
CreateAnonymousElement(nsGkAtoms::span,
|
||||
aParentNode,
|
||||
NS_LITERAL_STRING("mozResizer"),
|
||||
false);
|
||||
if (NS_WARN_IF(!ret)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// add the mouse listener so we can detect a click on a resizer
|
||||
nsCOMPtr<nsIDOMEventTarget> evtTarget = do_QueryInterface(retDOM);
|
||||
nsCOMPtr<nsIDOMEventTarget> evtTarget = do_QueryInterface(ret);
|
||||
evtTarget->AddEventListener(NS_LITERAL_STRING("mousedown"), mEventListener,
|
||||
true);
|
||||
|
||||
|
@ -183,9 +182,8 @@ HTMLEditor::CreateResizer(int16_t aLocation,
|
|||
break;
|
||||
}
|
||||
|
||||
nsCOMPtr<Element> ret = do_QueryInterface(retDOM);
|
||||
rv = ret->SetAttr(kNameSpaceID_None, nsGkAtoms::anonlocation, locationStr,
|
||||
true);
|
||||
nsresult rv =
|
||||
ret->SetAttr(kNameSpaceID_None, nsGkAtoms::anonlocation, locationStr, true);
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
return ret.forget();
|
||||
}
|
||||
|
@ -195,20 +193,15 @@ HTMLEditor::CreateShadow(nsIDOMNode* aParentNode,
|
|||
nsIDOMElement* aOriginalObject)
|
||||
{
|
||||
// let's create an image through the element factory
|
||||
nsAutoString name;
|
||||
nsCOMPtr<nsIAtom> name;
|
||||
if (HTMLEditUtils::IsImage(aOriginalObject)) {
|
||||
name.AssignLiteral("img");
|
||||
name = nsGkAtoms::img;
|
||||
} else {
|
||||
name.AssignLiteral("span");
|
||||
name = nsGkAtoms::span;
|
||||
}
|
||||
nsCOMPtr<nsIDOMElement> retDOM;
|
||||
CreateAnonymousElement(name, aParentNode,
|
||||
NS_LITERAL_STRING("mozResizingShadow"), true,
|
||||
getter_AddRefs(retDOM));
|
||||
|
||||
NS_ENSURE_TRUE(retDOM, nullptr);
|
||||
|
||||
nsCOMPtr<Element> ret = do_QueryInterface(retDOM);
|
||||
RefPtr<Element> ret =
|
||||
CreateAnonymousElement(name, aParentNode,
|
||||
NS_LITERAL_STRING("mozResizingShadow"), true);
|
||||
return ret.forget();
|
||||
}
|
||||
|
||||
|
@ -216,12 +209,9 @@ already_AddRefed<Element>
|
|||
HTMLEditor::CreateResizingInfo(nsIDOMNode* aParentNode)
|
||||
{
|
||||
// let's create an info box through the element factory
|
||||
nsCOMPtr<nsIDOMElement> retDOM;
|
||||
CreateAnonymousElement(NS_LITERAL_STRING("span"), aParentNode,
|
||||
NS_LITERAL_STRING("mozResizingInfo"), true,
|
||||
getter_AddRefs(retDOM));
|
||||
|
||||
nsCOMPtr<Element> ret = do_QueryInterface(retDOM);
|
||||
RefPtr<Element> ret =
|
||||
CreateAnonymousElement(nsGkAtoms::span, aParentNode,
|
||||
NS_LITERAL_STRING("mozResizingInfo"), true);
|
||||
return ret.forget();
|
||||
}
|
||||
|
||||
|
@ -251,16 +241,16 @@ HTMLEditor::SetAllResizersPosition()
|
|||
int32_t rw = (int32_t)((resizerWidth + 1) / 2);
|
||||
int32_t rh = (int32_t)((resizerHeight+ 1) / 2);
|
||||
|
||||
SetAnonymousElementPosition(x-rw, y-rh, static_cast<nsIDOMElement*>(GetAsDOMNode(mTopLeftHandle)));
|
||||
SetAnonymousElementPosition(x+w/2-rw, y-rh, static_cast<nsIDOMElement*>(GetAsDOMNode(mTopHandle)));
|
||||
SetAnonymousElementPosition(x+w-rw-1, y-rh, static_cast<nsIDOMElement*>(GetAsDOMNode(mTopRightHandle)));
|
||||
SetAnonymousElementPosition(x-rw, y-rh, mTopLeftHandle);
|
||||
SetAnonymousElementPosition(x+w/2-rw, y-rh, mTopHandle);
|
||||
SetAnonymousElementPosition(x+w-rw-1, y-rh, mTopRightHandle);
|
||||
|
||||
SetAnonymousElementPosition(x-rw, y+h/2-rh, static_cast<nsIDOMElement*>(GetAsDOMNode(mLeftHandle)));
|
||||
SetAnonymousElementPosition(x+w-rw-1, y+h/2-rh, static_cast<nsIDOMElement*>(GetAsDOMNode(mRightHandle)));
|
||||
SetAnonymousElementPosition(x-rw, y+h/2-rh, mLeftHandle);
|
||||
SetAnonymousElementPosition(x+w-rw-1, y+h/2-rh, mRightHandle);
|
||||
|
||||
SetAnonymousElementPosition(x-rw, y+h-rh-1, static_cast<nsIDOMElement*>(GetAsDOMNode(mBottomLeftHandle)));
|
||||
SetAnonymousElementPosition(x+w/2-rw, y+h-rh-1, static_cast<nsIDOMElement*>(GetAsDOMNode(mBottomHandle)));
|
||||
SetAnonymousElementPosition(x+w-rw-1, y+h-rh-1, static_cast<nsIDOMElement*>(GetAsDOMNode(mBottomRightHandle)));
|
||||
SetAnonymousElementPosition(x-rw, y+h-rh-1, mBottomLeftHandle);
|
||||
SetAnonymousElementPosition(x+w/2-rw, y+h-rh-1, mBottomHandle);
|
||||
SetAnonymousElementPosition(x+w-rw-1, y+h-rh-1, mBottomRightHandle);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -728,7 +718,7 @@ HTMLEditor::SetShadowPosition(Element* aShadow,
|
|||
int32_t aOriginalObjectX,
|
||||
int32_t aOriginalObjectY)
|
||||
{
|
||||
SetAnonymousElementPosition(aOriginalObjectX, aOriginalObjectY, static_cast<nsIDOMElement*>(GetAsDOMNode(aShadow)));
|
||||
SetAnonymousElementPosition(aOriginalObjectX, aOriginalObjectY, aShadow);
|
||||
|
||||
if (HTMLEditUtils::IsImage(aOriginalObject)) {
|
||||
nsAutoString imageSource;
|
||||
|
|
|
@ -61,25 +61,25 @@ HTMLEditor::ShowInlineTableEditingUI(nsIDOMElement* aCell)
|
|||
nsCOMPtr<nsIDOMElement> bodyElement = do_QueryInterface(GetRoot());
|
||||
NS_ENSURE_TRUE(bodyElement, NS_ERROR_NULL_POINTER);
|
||||
|
||||
CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement,
|
||||
NS_LITERAL_STRING("mozTableAddColumnBefore"),
|
||||
false, getter_AddRefs(mAddColumnBeforeButton));
|
||||
CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement,
|
||||
NS_LITERAL_STRING("mozTableRemoveColumn"),
|
||||
false, getter_AddRefs(mRemoveColumnButton));
|
||||
CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement,
|
||||
NS_LITERAL_STRING("mozTableAddColumnAfter"),
|
||||
false, getter_AddRefs(mAddColumnAfterButton));
|
||||
mAddColumnBeforeButton =
|
||||
CreateAnonymousElement(nsGkAtoms::a, bodyElement,
|
||||
NS_LITERAL_STRING("mozTableAddColumnBefore"), false);
|
||||
mRemoveColumnButton =
|
||||
CreateAnonymousElement(nsGkAtoms::a, bodyElement,
|
||||
NS_LITERAL_STRING("mozTableRemoveColumn"), false);
|
||||
mAddColumnAfterButton =
|
||||
CreateAnonymousElement(nsGkAtoms::a, bodyElement,
|
||||
NS_LITERAL_STRING("mozTableAddColumnAfter"), false);
|
||||
|
||||
CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement,
|
||||
NS_LITERAL_STRING("mozTableAddRowBefore"),
|
||||
false, getter_AddRefs(mAddRowBeforeButton));
|
||||
CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement,
|
||||
NS_LITERAL_STRING("mozTableRemoveRow"),
|
||||
false, getter_AddRefs(mRemoveRowButton));
|
||||
CreateAnonymousElement(NS_LITERAL_STRING("a"), bodyElement,
|
||||
NS_LITERAL_STRING("mozTableAddRowAfter"),
|
||||
false, getter_AddRefs(mAddRowAfterButton));
|
||||
mAddRowBeforeButton =
|
||||
CreateAnonymousElement(nsGkAtoms::a, bodyElement,
|
||||
NS_LITERAL_STRING("mozTableAddRowBefore"), false);
|
||||
mRemoveRowButton =
|
||||
CreateAnonymousElement(nsGkAtoms::a, bodyElement,
|
||||
NS_LITERAL_STRING("mozTableRemoveRow"), false);
|
||||
mAddRowAfterButton =
|
||||
CreateAnonymousElement(nsGkAtoms::a, bodyElement,
|
||||
NS_LITERAL_STRING("mozTableAddRowAfter"), false);
|
||||
|
||||
AddMouseClickListener(mAddColumnBeforeButton);
|
||||
AddMouseClickListener(mRemoveColumnButton);
|
||||
|
@ -188,7 +188,7 @@ HTMLEditor::DoInlineTableEditingAction(nsIDOMElement* aElement)
|
|||
}
|
||||
|
||||
void
|
||||
HTMLEditor::AddMouseClickListener(nsIDOMElement* aElement)
|
||||
HTMLEditor::AddMouseClickListener(Element* aElement)
|
||||
{
|
||||
nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(aElement));
|
||||
if (evtTarget) {
|
||||
|
@ -198,7 +198,7 @@ HTMLEditor::AddMouseClickListener(nsIDOMElement* aElement)
|
|||
}
|
||||
|
||||
void
|
||||
HTMLEditor::RemoveMouseClickListener(nsIDOMElement* aElement)
|
||||
HTMLEditor::RemoveMouseClickListener(Element* aElement)
|
||||
{
|
||||
nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(aElement));
|
||||
if (evtTarget) {
|
||||
|
@ -234,17 +234,12 @@ HTMLEditor::RefreshInlineTableEditingUI()
|
|||
|
||||
SetAnonymousElementPosition(xHoriz-10, yCell-7, mAddColumnBeforeButton);
|
||||
#ifdef DISABLE_TABLE_DELETION
|
||||
NS_NAMED_LITERAL_STRING(classStr, "class");
|
||||
|
||||
if (colCount== 1) {
|
||||
mRemoveColumnButton->SetAttribute(classStr,
|
||||
NS_LITERAL_STRING("hidden"));
|
||||
}
|
||||
else {
|
||||
bool hasClass = false;
|
||||
rv = mRemoveColumnButton->HasAttribute(classStr, &hasClass);
|
||||
if (NS_SUCCEEDED(rv) && hasClass) {
|
||||
mRemoveColumnButton->RemoveAttribute(classStr);
|
||||
mRemoveColumnButton->SetAttr(kNameSpaceID_None, nsGkAtoms::_class,
|
||||
NS_LITERAL_STRING("hidden"), true);
|
||||
} else {
|
||||
if (mRemoveColumnButton->HasAttr(kNameSpaceID_None, nsGkAtoms::_class)) {
|
||||
mRemoveColumnButton->UnsetAttr(kNameSpaceID_None, nsGkAtoms::_class);
|
||||
}
|
||||
#endif
|
||||
SetAnonymousElementPosition(xHoriz-4, yCell-7, mRemoveColumnButton);
|
||||
|
@ -256,14 +251,11 @@ HTMLEditor::RefreshInlineTableEditingUI()
|
|||
SetAnonymousElementPosition(xCell-7, yVert-10, mAddRowBeforeButton);
|
||||
#ifdef DISABLE_TABLE_DELETION
|
||||
if (rowCount== 1) {
|
||||
mRemoveRowButton->SetAttribute(classStr,
|
||||
NS_LITERAL_STRING("hidden"));
|
||||
}
|
||||
else {
|
||||
bool hasClass = false;
|
||||
rv = mRemoveRowButton->HasAttribute(classStr, &hasClass);
|
||||
if (NS_SUCCEEDED(rv) && hasClass) {
|
||||
mRemoveRowButton->RemoveAttribute(classStr);
|
||||
mRemoveRowButton->SetAttr(kNameSpaceID_None, nsGkAtoms::_class,
|
||||
NS_LITERAL_STRING("hidden"), true);
|
||||
} else {
|
||||
if (mRemoveRowButton->HasAttr(kNameSpaceID_None, nsGkAtoms::_class)) {
|
||||
mRemoveRowButton->UnsetAttr(kNameSpaceID_None, nsGkAtoms::_class, true);
|
||||
}
|
||||
#endif
|
||||
SetAnonymousElementPosition(xCell-7, yVert-4, mRemoveRowButton);
|
||||
|
|
|
@ -226,7 +226,9 @@ skip-if = toolkit == 'android' # bug 1054087
|
|||
[test_dom_input_event_on_texteditor.html]
|
||||
[test_dragdrop.html]
|
||||
skip-if = os == 'android'
|
||||
[test_inlineTableEditing.html]
|
||||
[test_keypress_untrusted_event.html]
|
||||
[test_objectResizing.html]
|
||||
[test_root_element_replacement.html]
|
||||
[test_select_all_without_body.html]
|
||||
[test_spellcheck_pref.html]
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none;">
|
||||
|
||||
</div>
|
||||
|
||||
<div id="editable1" contenteditable="true">
|
||||
<table id="table1">
|
||||
<tr id="tr1"><td>ABCDEFG</td><td>HIJKLMN</td></tr>
|
||||
<tr id="tr2"><td>ABCDEFG</td><td>HIJKLMN</td></tr>
|
||||
<tr id="tr3"><td>ABCDEFG</td><td>HIJKLMN</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
<pre id="test">
|
||||
|
||||
<script class="testbody" type="application/javascript">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(function() {
|
||||
document.execCommand("enableObjectResizing", false, "false");
|
||||
document.execCommand("enableInlineTableEditing", false, "true");
|
||||
|
||||
let tableNode = document.getElementById("table1");
|
||||
synthesizeMouseAtCenter(tableNode, {});
|
||||
isnot(tableNode.getAttribute("_moz_resizing"), "true",
|
||||
"_moz_resizing attribute shouldn't be true without object resizing");
|
||||
|
||||
ok(document.getElementById("tr2"), "id=tr2 should exist");
|
||||
synthesizeMouse(tr2, 0, tr2.clientHeight / 2, {});
|
||||
ok(!document.getElementById("tr2"),
|
||||
"id=tr2 should be removed by a click in the row");
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,51 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none;">
|
||||
|
||||
</div>
|
||||
|
||||
<div id="editable1" contenteditable="true">
|
||||
<table id="table1">
|
||||
<tr><td>ABCDEFG</td><td>HIJKLMN</td></tr>
|
||||
<tr><td>ABCDEFG</td><td>HIJKLMN</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
<pre id="test">
|
||||
|
||||
<script class="testbody" type="application/javascript">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(function() {
|
||||
document.execCommand("enableObjectResizing", false, "true");
|
||||
|
||||
let tableNode = document.getElementById("table1");
|
||||
synthesizeMouseAtCenter(tableNode, {});
|
||||
is(tableNode.getAttribute("_moz_resizing"), "true",
|
||||
"_moz_resizing attribute should be true with object resizing");
|
||||
|
||||
let originalHeight = tableNode.clientHeight;
|
||||
synthesizeMouse(tableNode, 0, originalHeight, { type: "mousedown" });
|
||||
synthesizeMouse(tableNode, 0, originalHeight + 100, { type: "mousemove" });
|
||||
synthesizeMouse(tableNode, 0, originalHeight + 100, { type: "mouseup" });
|
||||
isnot(originalHeight, tableNode.clientHeight,
|
||||
"table height should be changed by dragging a resizer grip");
|
||||
|
||||
let originalWidth = tableNode.clientWidth;
|
||||
synthesizeMouse(tableNode, originalWidth, 0, { type: "mousedown" });
|
||||
synthesizeMouse(tableNode, originalWidth + 100, 0, { type: "mousemove" });
|
||||
synthesizeMouse(tableNode, originalWidth + 100, 0, { type: "mouseup" });
|
||||
isnot(originalWidth, tableNode.clientWidth,
|
||||
"table width should be changed by dragging a resizer grip");
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -509,24 +509,6 @@ interface nsIHTMLEditor : nsISupports
|
|||
*/
|
||||
void removeInsertionListener(in nsIContentFilter inFilter);
|
||||
|
||||
/**
|
||||
* Returns an anonymous nsDOMElement of type aTag,
|
||||
* child of aParentNode. If aIsCreatedHidden is true, the class
|
||||
* "hidden" is added to the created element. If aAnonClass is not
|
||||
* the empty string, it becomes the value of the attribute "_moz_anonclass"
|
||||
* @return a DOM Element
|
||||
* @param aTag [IN] a string representing the desired type of
|
||||
* the element to create
|
||||
* @param aParentNode [IN] the parent node of the created anonymous
|
||||
* element
|
||||
* @param aAnonClass [IN] contents of the _moz_anonclass attribute
|
||||
* @param aIsCreatedHidden [IN] a boolean specifying if the class "hidden"
|
||||
* is to be added to the created anonymous
|
||||
* element
|
||||
*/
|
||||
nsIDOMElement createAnonymousElement(in AString aTag, in nsIDOMNode aParentNode,
|
||||
in AString aAnonClass, in boolean aIsCreatedHidden);
|
||||
|
||||
/**
|
||||
* returns the deepest container of the selection
|
||||
* @return a DOM Element
|
||||
|
|
|
@ -330,19 +330,19 @@ struct BaseRect {
|
|||
}
|
||||
Point CCWCorner(mozilla::Side side) const {
|
||||
switch (side) {
|
||||
case NS_SIDE_TOP: return TopLeft();
|
||||
case NS_SIDE_RIGHT: return TopRight();
|
||||
case NS_SIDE_BOTTOM: return BottomRight();
|
||||
case NS_SIDE_LEFT: return BottomLeft();
|
||||
case eSideTop: return TopLeft();
|
||||
case eSideRight: return TopRight();
|
||||
case eSideBottom: return BottomRight();
|
||||
case eSideLeft: return BottomLeft();
|
||||
}
|
||||
MOZ_CRASH("GFX: Incomplete switch");
|
||||
}
|
||||
Point CWCorner(mozilla::Side side) const {
|
||||
switch (side) {
|
||||
case NS_SIDE_TOP: return TopRight();
|
||||
case NS_SIDE_RIGHT: return BottomRight();
|
||||
case NS_SIDE_BOTTOM: return BottomLeft();
|
||||
case NS_SIDE_LEFT: return TopLeft();
|
||||
case eSideTop: return TopRight();
|
||||
case eSideRight: return BottomRight();
|
||||
case eSideBottom: return BottomLeft();
|
||||
case eSideLeft: return TopLeft();
|
||||
}
|
||||
MOZ_CRASH("GFX: Incomplete switch");
|
||||
}
|
||||
|
@ -363,10 +363,10 @@ struct BaseRect {
|
|||
T Edge(mozilla::Side aSide) const
|
||||
{
|
||||
switch (aSide) {
|
||||
case NS_SIDE_TOP: return Y();
|
||||
case NS_SIDE_RIGHT: return XMost();
|
||||
case NS_SIDE_BOTTOM: return YMost();
|
||||
case NS_SIDE_LEFT: return X();
|
||||
case eSideTop: return Y();
|
||||
case eSideRight: return XMost();
|
||||
case eSideBottom: return YMost();
|
||||
case eSideLeft: return X();
|
||||
}
|
||||
MOZ_CRASH("GFX: Incomplete switch");
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#define MOZILLA_GFX_TYPES_H_
|
||||
|
||||
#include "mozilla/EndianUtils.h"
|
||||
#include "mozilla/MacroArgs.h" // for MOZ_CONCAT
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
@ -397,11 +398,24 @@ enum SideBits {
|
|||
eSideBitsAll = eSideBitsTopBottom | eSideBitsLeftRight
|
||||
};
|
||||
|
||||
// Creates a for loop that walks over the four mozilla::Side values.
|
||||
// We use an int32_t helper variable (instead of a Side) for our loop counter,
|
||||
// to avoid triggering undefined behavior just before we exit the loop (at
|
||||
// which point the counter is incremented beyond the largest valid Side value).
|
||||
#define NS_FOR_CSS_SIDES(var_) \
|
||||
int32_t MOZ_CONCAT(var_,__LINE__) = mozilla::eSideTop; \
|
||||
for (mozilla::Side var_; \
|
||||
MOZ_CONCAT(var_,__LINE__) <= mozilla::eSideLeft && \
|
||||
((var_ = mozilla::Side(MOZ_CONCAT(var_,__LINE__))), true); \
|
||||
++MOZ_CONCAT(var_,__LINE__))
|
||||
|
||||
static inline Side& operator++(Side& side) {
|
||||
MOZ_ASSERT(side >= eSideTop && side <= eSideLeft,
|
||||
"Out of range side");
|
||||
side = Side(side + 1);
|
||||
return side;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#define NS_SIDE_TOP mozilla::eSideTop
|
||||
#define NS_SIDE_RIGHT mozilla::eSideRight
|
||||
#define NS_SIDE_BOTTOM mozilla::eSideBottom
|
||||
#define NS_SIDE_LEFT mozilla::eSideLeft
|
||||
|
||||
#endif /* MOZILLA_GFX_TYPES_H_ */
|
||||
|
|
|
@ -25,6 +25,7 @@ union GfxPrefValue {
|
|||
int32_t;
|
||||
uint32_t;
|
||||
float;
|
||||
nsCString;
|
||||
};
|
||||
|
||||
struct GfxPrefSetting {
|
||||
|
|
|
@ -4,17 +4,17 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsRect.h"
|
||||
#include "mozilla/gfx/Types.h" // for NS_SIDE_BOTTOM, etc
|
||||
#include "mozilla/gfx/Types.h" // for eSideBottom, etc
|
||||
#include "mozilla/CheckedInt.h" // for CheckedInt
|
||||
#include "nsDeviceContext.h" // for nsDeviceContext
|
||||
#include "nsString.h" // for nsAutoString, etc
|
||||
#include "nsMargin.h" // for nsMargin
|
||||
|
||||
static_assert((int(NS_SIDE_TOP) == 0) &&
|
||||
(int(NS_SIDE_RIGHT) == 1) &&
|
||||
(int(NS_SIDE_BOTTOM) == 2) &&
|
||||
(int(NS_SIDE_LEFT) == 3),
|
||||
"The mozilla::css::Side sequence must match the nsMargin nscoord sequence");
|
||||
static_assert((int(eSideTop) == 0) &&
|
||||
(int(eSideRight) == 1) &&
|
||||
(int(eSideBottom) == 2) &&
|
||||
(int(eSideLeft) == 3),
|
||||
"The mozilla::Side sequence must match the nsMargin nscoord sequence");
|
||||
|
||||
const mozilla::gfx::IntRect& GetMaxSizedIntRect() {
|
||||
static const mozilla::gfx::IntRect r(0, 0, INT32_MAX, INT32_MAX);
|
||||
|
|
|
@ -268,13 +268,24 @@ TEST(Layers, TextureYCbCrSerialization) {
|
|||
clientData.mPicX = 0;
|
||||
|
||||
ImageBridgeChild::InitSameProcess();
|
||||
// wait until IPDL connection
|
||||
#ifdef XP_WIN
|
||||
Sleep(1);
|
||||
#else
|
||||
sleep(1);
|
||||
#endif
|
||||
|
||||
RefPtr<ImageBridgeChild> imageBridge = ImageBridgeChild::GetSingleton();
|
||||
static int retry = 5;
|
||||
while(!imageBridge->IPCOpen() && retry) {
|
||||
// IPDL connection takes time especially in slow testing environment, like
|
||||
// VM machines. Here we added retry mechanism to wait for IPDL connnection.
|
||||
#ifdef XP_WIN
|
||||
Sleep(1);
|
||||
#else
|
||||
sleep(1);
|
||||
#endif
|
||||
retry--;
|
||||
}
|
||||
|
||||
// Skip this testing if IPDL connection is not ready
|
||||
if (!retry && !imageBridge->IPCOpen()) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<TextureClient> client = TextureClient::CreateForYCbCr(imageBridge, clientData.mYSize, clientData.mCbCrSize,
|
||||
StereoMode::MONO, YUVColorSpace::BT601,
|
||||
|
|
|
@ -158,6 +158,14 @@ void gfxPrefs::PrefAddVarCache(float* aVariable,
|
|||
Preferences::AddFloatVarCache(aVariable, aPref, aDefault);
|
||||
}
|
||||
|
||||
void gfxPrefs::PrefAddVarCache(std::string* aVariable,
|
||||
const char* aPref,
|
||||
std::string aDefault)
|
||||
{
|
||||
MOZ_ASSERT(IsPrefsServiceAvailable());
|
||||
Preferences::SetCString(aPref, aVariable->c_str());
|
||||
}
|
||||
|
||||
bool gfxPrefs::PrefGet(const char* aPref, bool aDefault)
|
||||
{
|
||||
MOZ_ASSERT(IsPrefsServiceAvailable());
|
||||
|
@ -182,6 +190,16 @@ float gfxPrefs::PrefGet(const char* aPref, float aDefault)
|
|||
return Preferences::GetFloat(aPref, aDefault);
|
||||
}
|
||||
|
||||
|
||||
std::string gfxPrefs::PrefGet(const char* aPref, std::string aDefault)
|
||||
{
|
||||
MOZ_ASSERT(IsPrefsServiceAvailable());
|
||||
|
||||
nsAdoptingCString result;
|
||||
Preferences::GetCString(aPref, &result);
|
||||
return result.get();
|
||||
}
|
||||
|
||||
void gfxPrefs::PrefSet(const char* aPref, bool aValue)
|
||||
{
|
||||
MOZ_ASSERT(IsPrefsServiceAvailable());
|
||||
|
@ -206,6 +224,12 @@ void gfxPrefs::PrefSet(const char* aPref, float aValue)
|
|||
Preferences::SetFloat(aPref, aValue);
|
||||
}
|
||||
|
||||
void gfxPrefs::PrefSet(const char* aPref, std::string aValue)
|
||||
{
|
||||
MOZ_ASSERT(IsPrefsServiceAvailable());
|
||||
Preferences::SetCString(aPref, aValue.c_str());
|
||||
}
|
||||
|
||||
static void
|
||||
OnGfxPrefChanged(const char* aPrefname, void* aClosure)
|
||||
{
|
||||
|
@ -246,6 +270,11 @@ void gfxPrefs::CopyPrefValue(const float* aValue, GfxPrefValue* aOutValue)
|
|||
*aOutValue = *aValue;
|
||||
}
|
||||
|
||||
void gfxPrefs::CopyPrefValue(const std::string* aValue, GfxPrefValue* aOutValue)
|
||||
{
|
||||
*aOutValue = nsCString(aValue->c_str());
|
||||
}
|
||||
|
||||
void gfxPrefs::CopyPrefValue(const GfxPrefValue* aValue, bool* aOutValue)
|
||||
{
|
||||
*aOutValue = aValue->get_bool();
|
||||
|
@ -265,3 +294,8 @@ void gfxPrefs::CopyPrefValue(const GfxPrefValue* aValue, float* aOutValue)
|
|||
{
|
||||
*aOutValue = aValue->get_float();
|
||||
}
|
||||
|
||||
void gfxPrefs::CopyPrefValue(const GfxPrefValue* aValue, std::string* aOutValue)
|
||||
{
|
||||
*aOutValue = aValue->get_nsCString().get();
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <cmath> // for M_PI
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Function.h"
|
||||
#include "mozilla/gfx/LoggingConstants.h"
|
||||
|
@ -645,14 +646,17 @@ private:
|
|||
static void PrefAddVarCache(int32_t*, const char*, int32_t);
|
||||
static void PrefAddVarCache(uint32_t*, const char*, uint32_t);
|
||||
static void PrefAddVarCache(float*, const char*, float);
|
||||
static void PrefAddVarCache(std::string*, const char*, std::string);
|
||||
static bool PrefGet(const char*, bool);
|
||||
static int32_t PrefGet(const char*, int32_t);
|
||||
static uint32_t PrefGet(const char*, uint32_t);
|
||||
static float PrefGet(const char*, float);
|
||||
static std::string PrefGet(const char*, std::string);
|
||||
static void PrefSet(const char* aPref, bool aValue);
|
||||
static void PrefSet(const char* aPref, int32_t aValue);
|
||||
static void PrefSet(const char* aPref, uint32_t aValue);
|
||||
static void PrefSet(const char* aPref, float aValue);
|
||||
static void PrefSet(const char* aPref, std::string aValue);
|
||||
static void WatchChanges(const char* aPrefname, Pref* aPref);
|
||||
static void UnwatchChanges(const char* aPrefname, Pref* aPref);
|
||||
// Creating these to avoid having to include PGPU.h in the .h
|
||||
|
@ -660,10 +664,12 @@ private:
|
|||
static void CopyPrefValue(const int32_t* aValue, GfxPrefValue* aOutValue);
|
||||
static void CopyPrefValue(const uint32_t* aValue, GfxPrefValue* aOutValue);
|
||||
static void CopyPrefValue(const float* aValue, GfxPrefValue* aOutValue);
|
||||
static void CopyPrefValue(const std::string* aValue, GfxPrefValue* aOutValue);
|
||||
static void CopyPrefValue(const GfxPrefValue* aValue, bool* aOutValue);
|
||||
static void CopyPrefValue(const GfxPrefValue* aValue, int32_t* aOutValue);
|
||||
static void CopyPrefValue(const GfxPrefValue* aValue, uint32_t* aOutValue);
|
||||
static void CopyPrefValue(const GfxPrefValue* aValue, float* aOutValue);
|
||||
static void CopyPrefValue(const GfxPrefValue* aValue, std::string* aOutValue);
|
||||
|
||||
static void AssertMainThread();
|
||||
|
||||
|
|
|
@ -90,20 +90,20 @@ struct gfxRect :
|
|||
|
||||
gfxPoint CCWCorner(mozilla::Side side) const {
|
||||
switch (side) {
|
||||
case NS_SIDE_TOP: return TopLeft();
|
||||
case NS_SIDE_RIGHT: return TopRight();
|
||||
case NS_SIDE_BOTTOM: return BottomRight();
|
||||
case NS_SIDE_LEFT: return BottomLeft();
|
||||
case mozilla::eSideTop: return TopLeft();
|
||||
case mozilla::eSideRight: return TopRight();
|
||||
case mozilla::eSideBottom: return BottomRight();
|
||||
case mozilla::eSideLeft: return BottomLeft();
|
||||
}
|
||||
MOZ_CRASH("Incomplete switch");
|
||||
}
|
||||
|
||||
gfxPoint CWCorner(mozilla::Side side) const {
|
||||
switch (side) {
|
||||
case NS_SIDE_TOP: return TopRight();
|
||||
case NS_SIDE_RIGHT: return BottomRight();
|
||||
case NS_SIDE_BOTTOM: return BottomLeft();
|
||||
case NS_SIDE_LEFT: return TopLeft();
|
||||
case mozilla::eSideTop: return TopRight();
|
||||
case mozilla::eSideRight: return BottomRight();
|
||||
case mozilla::eSideBottom: return BottomLeft();
|
||||
case mozilla::eSideLeft: return TopLeft();
|
||||
}
|
||||
MOZ_CRASH("Incomplete switch");
|
||||
}
|
||||
|
|
|
@ -60,17 +60,18 @@ static pfn_VR_GetGenericInterface vr_GetGenericInterface = nullptr;
|
|||
|
||||
// EButton_System, EButton_DPad_xx, and EButton_A
|
||||
// can not be triggered in Steam Vive in OpenVR SDK 1.0.3.
|
||||
// Reminder: changing the order of these buttons may break web content.
|
||||
const uint64_t gOpenVRButtonMask[] = {
|
||||
// vr::ButtonMaskFromId(vr::EVRButtonId::k_EButton_System),
|
||||
vr::ButtonMaskFromId(vr::EVRButtonId::k_EButton_ApplicationMenu),
|
||||
vr::ButtonMaskFromId(vr::EVRButtonId::k_EButton_SteamVR_Touchpad),
|
||||
vr::ButtonMaskFromId(vr::EVRButtonId::k_EButton_SteamVR_Trigger),
|
||||
// vr::ButtonMaskFromId(vr::EVRButtonId::k_EButton_A),
|
||||
vr::ButtonMaskFromId(vr::EVRButtonId::k_EButton_Grip),
|
||||
vr::ButtonMaskFromId(vr::EVRButtonId::k_EButton_ApplicationMenu)
|
||||
// vr::ButtonMaskFromId(vr::EVRButtonId::k_EButton_DPad_Left),
|
||||
// vr::ButtonMaskFromId(vr::EVRButtonId::k_EButton_DPad_Up),
|
||||
// vr::ButtonMaskFromId(vr::EVRButtonId::k_EButton_DPad_Right),
|
||||
// vr::ButtonMaskFromId(vr::EVRButtonId::k_EButton_DPad_Down),
|
||||
// vr::ButtonMaskFromId(vr::EVRButtonId::k_EButton_A),
|
||||
vr::ButtonMaskFromId(vr::EVRButtonId::k_EButton_SteamVR_Touchpad),
|
||||
vr::ButtonMaskFromId(vr::EVRButtonId::k_EButton_SteamVR_Trigger)
|
||||
// vr::ButtonMaskFromId(vr::EVRButtonId::k_EButton_DPad_Down)
|
||||
};
|
||||
|
||||
const uint32_t gNumOpenVRButtonMask = sizeof(gOpenVRButtonMask) /
|
||||
|
|
|
@ -63,20 +63,10 @@ dnl ========================================================
|
|||
USE_PTHREADS=
|
||||
_PTHREAD_LDFLAGS=""
|
||||
|
||||
dnl Do not allow objdir == srcdir builds
|
||||
dnl ==============================================================
|
||||
_topsrcdir=`cd $srcdir; pwd -W 2>/dev/null || pwd -P`
|
||||
_objdir=`pwd -P`
|
||||
|
||||
MOZ_BUILD_ROOT=`pwd -W 2>/dev/null || pwd -P`
|
||||
|
||||
MOZ_DEFAULT_COMPILER
|
||||
|
||||
if test -z "$JS_STANDALONE"; then
|
||||
autoconfmk=autoconf-js.mk
|
||||
#DIST is exported from top-level configure
|
||||
else
|
||||
DIST="$MOZ_BUILD_ROOT/dist"
|
||||
fi
|
||||
AC_SUBST(autoconfmk)
|
||||
|
||||
|
|
|
@ -4625,9 +4625,9 @@ GetBSizeTakenByBoxSizing(StyleBoxSizing aBoxSizing,
|
|||
const nsStyleSides& stylePadding =
|
||||
aFrame->StylePadding()->mPadding;
|
||||
const nsStyleCoord& paddingStart =
|
||||
stylePadding.Get(aHorizontalAxis ? NS_SIDE_TOP : NS_SIDE_LEFT);
|
||||
stylePadding.Get(aHorizontalAxis ? eSideTop : eSideLeft);
|
||||
const nsStyleCoord& paddingEnd =
|
||||
stylePadding.Get(aHorizontalAxis ? NS_SIDE_BOTTOM : NS_SIDE_RIGHT);
|
||||
stylePadding.Get(aHorizontalAxis ? eSideBottom : eSideRight);
|
||||
nscoord pad;
|
||||
// XXXbz Calling GetPercentBSize on padding values looks bogus, since
|
||||
// percent padding is always a percentage of the inline-size of the
|
||||
|
@ -6711,23 +6711,23 @@ nsLayoutUtils::HasNonZeroCorner(const nsStyleCorners& aCorners)
|
|||
}
|
||||
|
||||
// aCorner is a "full corner" value, i.e. NS_CORNER_TOP_LEFT etc
|
||||
static bool IsCornerAdjacentToSide(uint8_t aCorner, css::Side aSide)
|
||||
static bool IsCornerAdjacentToSide(uint8_t aCorner, Side aSide)
|
||||
{
|
||||
static_assert((int)NS_SIDE_TOP == NS_CORNER_TOP_LEFT, "Check for Full Corner");
|
||||
static_assert((int)NS_SIDE_RIGHT == NS_CORNER_TOP_RIGHT, "Check for Full Corner");
|
||||
static_assert((int)NS_SIDE_BOTTOM == NS_CORNER_BOTTOM_RIGHT, "Check for Full Corner");
|
||||
static_assert((int)NS_SIDE_LEFT == NS_CORNER_BOTTOM_LEFT, "Check for Full Corner");
|
||||
static_assert((int)NS_SIDE_TOP == ((NS_CORNER_TOP_RIGHT - 1)&3), "Check for Full Corner");
|
||||
static_assert((int)NS_SIDE_RIGHT == ((NS_CORNER_BOTTOM_RIGHT - 1)&3), "Check for Full Corner");
|
||||
static_assert((int)NS_SIDE_BOTTOM == ((NS_CORNER_BOTTOM_LEFT - 1)&3), "Check for Full Corner");
|
||||
static_assert((int)NS_SIDE_LEFT == ((NS_CORNER_TOP_LEFT - 1)&3), "Check for Full Corner");
|
||||
static_assert((int)eSideTop == NS_CORNER_TOP_LEFT, "Check for Full Corner");
|
||||
static_assert((int)eSideRight == NS_CORNER_TOP_RIGHT, "Check for Full Corner");
|
||||
static_assert((int)eSideBottom == NS_CORNER_BOTTOM_RIGHT, "Check for Full Corner");
|
||||
static_assert((int)eSideLeft == NS_CORNER_BOTTOM_LEFT, "Check for Full Corner");
|
||||
static_assert((int)eSideTop == ((NS_CORNER_TOP_RIGHT - 1)&3), "Check for Full Corner");
|
||||
static_assert((int)eSideRight == ((NS_CORNER_BOTTOM_RIGHT - 1)&3), "Check for Full Corner");
|
||||
static_assert((int)eSideBottom == ((NS_CORNER_BOTTOM_LEFT - 1)&3), "Check for Full Corner");
|
||||
static_assert((int)eSideLeft == ((NS_CORNER_TOP_LEFT - 1)&3), "Check for Full Corner");
|
||||
|
||||
return aSide == aCorner || aSide == ((aCorner - 1)&3);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
nsLayoutUtils::HasNonZeroCornerOnSide(const nsStyleCorners& aCorners,
|
||||
css::Side aSide)
|
||||
Side aSide)
|
||||
{
|
||||
static_assert(NS_CORNER_TOP_LEFT_X/2 == NS_CORNER_TOP_LEFT, "Check for Non Zero on side");
|
||||
static_assert(NS_CORNER_TOP_LEFT_Y/2 == NS_CORNER_TOP_LEFT, "Check for Non Zero on side");
|
||||
|
|
|
@ -1938,7 +1938,7 @@ public:
|
|||
* given side.
|
||||
*/
|
||||
static bool HasNonZeroCornerOnSide(const nsStyleCorners& aCorners,
|
||||
mozilla::css::Side aSide);
|
||||
mozilla::Side aSide);
|
||||
|
||||
/**
|
||||
* Determine if a widget is likely to require transparency or translucency.
|
||||
|
|
|
@ -52,7 +52,7 @@ nsRect
|
|||
nsFieldSetFrame::VisualBorderRectRelativeToSelf() const
|
||||
{
|
||||
WritingMode wm = GetWritingMode();
|
||||
css::Side legendSide = wm.PhysicalSide(eLogicalSideBStart);
|
||||
Side legendSide = wm.PhysicalSide(eLogicalSideBStart);
|
||||
nscoord legendBorder = StyleBorder()->GetComputedBorderWidth(legendSide);
|
||||
LogicalRect r(wm, LogicalPoint(wm, 0, 0), GetLogicalSize(wm));
|
||||
nsSize containerSize = r.Size(wm).GetPhysicalSize(wm);
|
||||
|
@ -237,7 +237,7 @@ nsFieldSetFrame::PaintBorder(
|
|||
this, rect);
|
||||
|
||||
if (nsIFrame* legend = GetLegend()) {
|
||||
css::Side legendSide = wm.PhysicalSide(eLogicalSideBStart);
|
||||
Side legendSide = wm.PhysicalSide(eLogicalSideBStart);
|
||||
nscoord legendBorderWidth =
|
||||
StyleBorder()->GetComputedBorderWidth(legendSide);
|
||||
|
||||
|
|
|
@ -906,10 +906,10 @@ ReflowInput::ComputeRelativeOffsets(WritingMode aWM,
|
|||
nsMargin& aComputedOffsets)
|
||||
{
|
||||
LogicalMargin offsets(aWM);
|
||||
mozilla::css::Side inlineStart = aWM.PhysicalSide(eLogicalSideIStart);
|
||||
mozilla::css::Side inlineEnd = aWM.PhysicalSide(eLogicalSideIEnd);
|
||||
mozilla::css::Side blockStart = aWM.PhysicalSide(eLogicalSideBStart);
|
||||
mozilla::css::Side blockEnd = aWM.PhysicalSide(eLogicalSideBEnd);
|
||||
mozilla::Side inlineStart = aWM.PhysicalSide(eLogicalSideIStart);
|
||||
mozilla::Side inlineEnd = aWM.PhysicalSide(eLogicalSideIEnd);
|
||||
mozilla::Side blockStart = aWM.PhysicalSide(eLogicalSideBStart);
|
||||
mozilla::Side blockEnd = aWM.PhysicalSide(eLogicalSideBEnd);
|
||||
|
||||
const nsStylePosition* position = aFrame->StylePosition();
|
||||
|
||||
|
@ -1144,9 +1144,9 @@ ReflowInput::CalculateBorderPaddingMargin(
|
|||
nscoord* aOutsideBoxSizing) const
|
||||
{
|
||||
WritingMode wm = GetWritingMode();
|
||||
mozilla::css::Side startSide =
|
||||
mozilla::Side startSide =
|
||||
wm.PhysicalSide(MakeLogicalSide(aAxis, eLogicalEdgeStart));
|
||||
mozilla::css::Side endSide =
|
||||
mozilla::Side endSide =
|
||||
wm.PhysicalSide(MakeLogicalSide(aAxis, eLogicalEdgeEnd));
|
||||
|
||||
nsMargin styleBorder = mStyleBorder->GetComputedBorder();
|
||||
|
|
|
@ -324,11 +324,11 @@ public:
|
|||
// two-bit values:
|
||||
// bit 0 = the eOrientationMask value
|
||||
// bit 1 = the eBlockFlowMask value
|
||||
static const mozilla::css::Side kLogicalBlockSides[][2] = {
|
||||
{ NS_SIDE_TOP, NS_SIDE_BOTTOM }, // horizontal-tb
|
||||
{ NS_SIDE_RIGHT, NS_SIDE_LEFT }, // vertical-rl
|
||||
{ NS_SIDE_BOTTOM, NS_SIDE_TOP }, // (horizontal-bt)
|
||||
{ NS_SIDE_LEFT, NS_SIDE_RIGHT }, // vertical-lr
|
||||
static const mozilla::Side kLogicalBlockSides[][2] = {
|
||||
{ eSideTop, eSideBottom }, // horizontal-tb
|
||||
{ eSideRight, eSideLeft }, // vertical-rl
|
||||
{ eSideBottom, eSideTop }, // (horizontal-bt)
|
||||
{ eSideLeft, eSideRight }, // vertical-lr
|
||||
};
|
||||
|
||||
// Ignore the SIDEWAYS_MASK bit of the writing-mode value, as this has no
|
||||
|
@ -352,23 +352,23 @@ public:
|
|||
// is no horizontal-bt writing-mode, and no text-orientation value that
|
||||
// produces "inverted" text. (The former 'sideways-left' value, no longer
|
||||
// in the spec, would have produced this in vertical-rl mode.)
|
||||
static const mozilla::css::Side kLogicalInlineSides[][2] = {
|
||||
{ NS_SIDE_LEFT, NS_SIDE_RIGHT }, // horizontal-tb ltr
|
||||
{ NS_SIDE_TOP, NS_SIDE_BOTTOM }, // vertical-rl ltr
|
||||
{ NS_SIDE_RIGHT, NS_SIDE_LEFT }, // horizontal-tb rtl
|
||||
{ NS_SIDE_BOTTOM, NS_SIDE_TOP }, // vertical-rl rtl
|
||||
{ NS_SIDE_RIGHT, NS_SIDE_LEFT }, // (horizontal-bt) (inverted) ltr
|
||||
{ NS_SIDE_TOP, NS_SIDE_BOTTOM }, // sideways-lr rtl
|
||||
{ NS_SIDE_LEFT, NS_SIDE_RIGHT }, // (horizontal-bt) (inverted) rtl
|
||||
{ NS_SIDE_BOTTOM, NS_SIDE_TOP }, // sideways-lr ltr
|
||||
{ NS_SIDE_LEFT, NS_SIDE_RIGHT }, // horizontal-tb (inverted) rtl
|
||||
{ NS_SIDE_TOP, NS_SIDE_BOTTOM }, // vertical-rl (inverted) rtl
|
||||
{ NS_SIDE_RIGHT, NS_SIDE_LEFT }, // horizontal-tb (inverted) ltr
|
||||
{ NS_SIDE_BOTTOM, NS_SIDE_TOP }, // vertical-rl (inverted) ltr
|
||||
{ NS_SIDE_LEFT, NS_SIDE_RIGHT }, // (horizontal-bt) ltr
|
||||
{ NS_SIDE_TOP, NS_SIDE_BOTTOM }, // vertical-lr ltr
|
||||
{ NS_SIDE_RIGHT, NS_SIDE_LEFT }, // (horizontal-bt) rtl
|
||||
{ NS_SIDE_BOTTOM, NS_SIDE_TOP }, // vertical-lr rtl
|
||||
static const mozilla::Side kLogicalInlineSides[][2] = {
|
||||
{ eSideLeft, eSideRight }, // horizontal-tb ltr
|
||||
{ eSideTop, eSideBottom }, // vertical-rl ltr
|
||||
{ eSideRight, eSideLeft }, // horizontal-tb rtl
|
||||
{ eSideBottom, eSideTop }, // vertical-rl rtl
|
||||
{ eSideRight, eSideLeft }, // (horizontal-bt) (inverted) ltr
|
||||
{ eSideTop, eSideBottom }, // sideways-lr rtl
|
||||
{ eSideLeft, eSideRight }, // (horizontal-bt) (inverted) rtl
|
||||
{ eSideBottom, eSideTop }, // sideways-lr ltr
|
||||
{ eSideLeft, eSideRight }, // horizontal-tb (inverted) rtl
|
||||
{ eSideTop, eSideBottom }, // vertical-rl (inverted) rtl
|
||||
{ eSideRight, eSideLeft }, // horizontal-tb (inverted) ltr
|
||||
{ eSideBottom, eSideTop }, // vertical-rl (inverted) ltr
|
||||
{ eSideLeft, eSideRight }, // (horizontal-bt) ltr
|
||||
{ eSideTop, eSideBottom }, // vertical-lr ltr
|
||||
{ eSideRight, eSideLeft }, // (horizontal-bt) rtl
|
||||
{ eSideBottom, eSideTop }, // vertical-lr rtl
|
||||
};
|
||||
|
||||
// Inline axis sides depend on all three of writing-mode, text-orientation
|
||||
|
@ -404,7 +404,7 @@ public:
|
|||
* given the current writing mode.
|
||||
* (This is the inverse of the PhysicalSide() method above.)
|
||||
*/
|
||||
LogicalSide LogicalSideForPhysicalSide(mozilla::css::Side aSide) const
|
||||
LogicalSide LogicalSideForPhysicalSide(mozilla::Side aSide) const
|
||||
{
|
||||
// indexes are four-bit values:
|
||||
// bit 0 = the eOrientationMask value
|
||||
|
@ -463,7 +463,7 @@ public:
|
|||
{
|
||||
auto side = static_cast<LogicalSide>(aDir);
|
||||
if (IsInline(side)) {
|
||||
return !IsInlineReversed() ? side : GetOppositeSide(side);
|
||||
return IsBidiLTR() ? side : GetOppositeSide(side);
|
||||
}
|
||||
return !IsLineInverted() ? side : GetOppositeSide(side);
|
||||
}
|
||||
|
|
|
@ -93,14 +93,14 @@ nsColumnSetFrame::PaintColumnRule(nsRenderingContext* aCtx,
|
|||
nsStyleBorder border(presContext);
|
||||
Sides skipSides;
|
||||
if (isVertical) {
|
||||
border.SetBorderWidth(NS_SIDE_TOP, ruleWidth);
|
||||
border.SetBorderStyle(NS_SIDE_TOP, ruleStyle);
|
||||
border.SetBorderWidth(eSideTop, ruleWidth);
|
||||
border.SetBorderStyle(eSideTop, ruleStyle);
|
||||
border.mBorderTopColor = StyleComplexColor::FromColor(ruleColor);
|
||||
skipSides |= mozilla::eSideBitsLeftRight;
|
||||
skipSides |= mozilla::eSideBitsBottom;
|
||||
} else {
|
||||
border.SetBorderWidth(NS_SIDE_LEFT, ruleWidth);
|
||||
border.SetBorderStyle(NS_SIDE_LEFT, ruleStyle);
|
||||
border.SetBorderWidth(eSideLeft, ruleWidth);
|
||||
border.SetBorderStyle(eSideLeft, ruleStyle);
|
||||
border.mBorderLeftColor = StyleComplexColor::FromColor(ruleColor);
|
||||
skipSides |= mozilla::eSideBitsTopBottom;
|
||||
skipSides |= mozilla::eSideBitsRight;
|
||||
|
|
|
@ -834,9 +834,9 @@ nsContainerFrame::DoInlineIntrinsicISize(nsRenderingContext *aRenderingContext,
|
|||
aType == nsLayoutUtils::PREF_ISIZE, "bad type");
|
||||
|
||||
WritingMode wm = GetWritingMode();
|
||||
mozilla::css::Side startSide =
|
||||
mozilla::Side startSide =
|
||||
wm.PhysicalSideForInlineAxis(eLogicalEdgeStart);
|
||||
mozilla::css::Side endSide =
|
||||
mozilla::Side endSide =
|
||||
wm.PhysicalSideForInlineAxis(eLogicalEdgeEnd);
|
||||
|
||||
const nsStylePadding *stylePadding = StylePadding();
|
||||
|
|
|
@ -221,7 +221,7 @@ nsFloatManager::GetFlowArea(WritingMode aWM, nscoord aBCoord, nscoord aBSize,
|
|||
if (floatStyle == StyleFloat::Left) {
|
||||
// A left float
|
||||
nscoord lineRightEdge =
|
||||
fi.LineRight(aShapeType, blockStart, bandBlockEnd);
|
||||
fi.LineRight(aWM, aShapeType, blockStart, bandBlockEnd);
|
||||
if (lineRightEdge > lineLeft) {
|
||||
lineLeft = lineRightEdge;
|
||||
// Only set haveFloats to true if the float is inside our
|
||||
|
@ -233,7 +233,7 @@ nsFloatManager::GetFlowArea(WritingMode aWM, nscoord aBCoord, nscoord aBSize,
|
|||
} else {
|
||||
// A right float
|
||||
nscoord lineLeftEdge =
|
||||
fi.LineLeft(aShapeType, blockStart, bandBlockEnd);
|
||||
fi.LineLeft(aWM, aShapeType, blockStart, bandBlockEnd);
|
||||
if (lineLeftEdge < lineRight) {
|
||||
lineRight = lineLeftEdge;
|
||||
// See above.
|
||||
|
@ -593,7 +593,8 @@ nsFloatManager::FloatInfo::~FloatInfo()
|
|||
#endif
|
||||
|
||||
nscoord
|
||||
nsFloatManager::FloatInfo::LineLeft(ShapeType aShapeType,
|
||||
nsFloatManager::FloatInfo::LineLeft(WritingMode aWM,
|
||||
ShapeType aShapeType,
|
||||
const nscoord aBStart,
|
||||
const nscoord aBEnd) const
|
||||
{
|
||||
|
@ -614,12 +615,32 @@ nsFloatManager::FloatInfo::LineLeft(ShapeType aShapeType,
|
|||
if (!hasRadii) {
|
||||
return ShapeBoxRect().x;
|
||||
}
|
||||
// Bug 1316549: Fix non-ltr direction and writing-mode.
|
||||
|
||||
// Get the physical side for line-left since border-radii are in
|
||||
// the physical axis.
|
||||
mozilla::Side lineLeftSide =
|
||||
aWM.PhysicalSide(aWM.LogicalSideForLineRelativeDir(eLineRelativeDirLeft));
|
||||
nscoord blockStartCornerRadiusL =
|
||||
radii[NS_SIDE_TO_HALF_CORNER(lineLeftSide, true, false)];
|
||||
nscoord blockStartCornerRadiusB =
|
||||
radii[NS_SIDE_TO_HALF_CORNER(lineLeftSide, true, true)];
|
||||
nscoord blockEndCornerRadiusL =
|
||||
radii[NS_SIDE_TO_HALF_CORNER(lineLeftSide, false, false)];
|
||||
nscoord blockEndCornerRadiusB =
|
||||
radii[NS_SIDE_TO_HALF_CORNER(lineLeftSide, false, true)];
|
||||
|
||||
if (aWM.IsLineInverted()) {
|
||||
// This happens only when aWM is vertical-lr. Need to swap blockStart
|
||||
// and blockEnd corners.
|
||||
std::swap(blockStartCornerRadiusL, blockEndCornerRadiusL);
|
||||
std::swap(blockStartCornerRadiusB, blockEndCornerRadiusB);
|
||||
}
|
||||
|
||||
nscoord lineLeftDiff =
|
||||
ComputeEllipseXInterceptDiff(
|
||||
ComputeEllipseLineInterceptDiff(
|
||||
ShapeBoxRect().y, ShapeBoxRect().YMost(),
|
||||
radii[NS_CORNER_TOP_LEFT_X], radii[NS_CORNER_TOP_LEFT_Y],
|
||||
radii[NS_CORNER_BOTTOM_LEFT_X], radii[NS_CORNER_BOTTOM_LEFT_Y],
|
||||
blockStartCornerRadiusL, blockStartCornerRadiusB,
|
||||
blockEndCornerRadiusL, blockEndCornerRadiusB,
|
||||
aBStart, aBEnd);
|
||||
return ShapeBoxRect().x + lineLeftDiff;
|
||||
}
|
||||
|
@ -630,7 +651,8 @@ nsFloatManager::FloatInfo::LineLeft(ShapeType aShapeType,
|
|||
}
|
||||
|
||||
nscoord
|
||||
nsFloatManager::FloatInfo::LineRight(ShapeType aShapeType,
|
||||
nsFloatManager::FloatInfo::LineRight(WritingMode aWM,
|
||||
ShapeType aShapeType,
|
||||
const nscoord aBStart,
|
||||
const nscoord aBEnd) const
|
||||
{
|
||||
|
@ -651,12 +673,32 @@ nsFloatManager::FloatInfo::LineRight(ShapeType aShapeType,
|
|||
if (!hasRadii) {
|
||||
return ShapeBoxRect().XMost();
|
||||
}
|
||||
// Bug 1316549: Fix non-ltr direction and writing-mode.
|
||||
|
||||
// Get the physical side for line-right since border-radii are in
|
||||
// the physical axis.
|
||||
mozilla::Side lineRightSide =
|
||||
aWM.PhysicalSide(aWM.LogicalSideForLineRelativeDir(eLineRelativeDirRight));
|
||||
nscoord blockStartCornerRadiusL =
|
||||
radii[NS_SIDE_TO_HALF_CORNER(lineRightSide, false, false)];
|
||||
nscoord blockStartCornerRadiusB =
|
||||
radii[NS_SIDE_TO_HALF_CORNER(lineRightSide, false, true)];
|
||||
nscoord blockEndCornerRadiusL =
|
||||
radii[NS_SIDE_TO_HALF_CORNER(lineRightSide, true, false)];
|
||||
nscoord blockEndCornerRadiusB =
|
||||
radii[NS_SIDE_TO_HALF_CORNER(lineRightSide, true, true)];
|
||||
|
||||
if (aWM.IsLineInverted()) {
|
||||
// This happens only when aWM is vertical-lr. Need to swap blockStart
|
||||
// and blockEnd corners.
|
||||
std::swap(blockStartCornerRadiusL, blockEndCornerRadiusL);
|
||||
std::swap(blockStartCornerRadiusB, blockEndCornerRadiusB);
|
||||
}
|
||||
|
||||
nscoord lineRightDiff =
|
||||
ComputeEllipseXInterceptDiff(
|
||||
ComputeEllipseLineInterceptDiff(
|
||||
ShapeBoxRect().y, ShapeBoxRect().YMost(),
|
||||
radii[NS_CORNER_TOP_RIGHT_X], radii[NS_CORNER_TOP_RIGHT_Y],
|
||||
radii[NS_CORNER_BOTTOM_RIGHT_X], radii[NS_CORNER_BOTTOM_RIGHT_Y],
|
||||
blockStartCornerRadiusL, blockStartCornerRadiusB,
|
||||
blockEndCornerRadiusL, blockEndCornerRadiusB,
|
||||
aBStart, aBEnd);
|
||||
return ShapeBoxRect().XMost() - lineRightDiff;
|
||||
}
|
||||
|
@ -667,29 +709,30 @@ nsFloatManager::FloatInfo::LineRight(ShapeType aShapeType,
|
|||
}
|
||||
|
||||
/* static */ nscoord
|
||||
nsFloatManager::FloatInfo::ComputeEllipseXInterceptDiff(
|
||||
const nscoord aShapeBoxY, const nscoord aShapeBoxYMost,
|
||||
const nscoord aTopCornerRadiusX, const nscoord aTopCornerRadiusY,
|
||||
const nscoord aBottomCornerRadiusX, const nscoord aBottomCornerRadiusY,
|
||||
const nscoord aBandY, const nscoord aBandYMost)
|
||||
nsFloatManager::FloatInfo::ComputeEllipseLineInterceptDiff(
|
||||
const nscoord aShapeBoxBStart, const nscoord aShapeBoxBEnd,
|
||||
const nscoord aBStartCornerRadiusL, const nscoord aBStartCornerRadiusB,
|
||||
const nscoord aBEndCornerRadiusL, const nscoord aBEndCornerRadiusB,
|
||||
const nscoord aBandBStart, const nscoord aBandBEnd)
|
||||
{
|
||||
// An Example for the band intersects with the top right corner of an ellipse.
|
||||
// An example for the band intersecting with the top right corner of an
|
||||
// ellipse with writing-mode horizontal-tb.
|
||||
//
|
||||
// xIntercept xDiff
|
||||
// lineIntercept lineDiff
|
||||
// | |
|
||||
// +---------------------------------|-------|-+---- aShapeBoxY
|
||||
// +---------------------------------|-------|-+---- aShapeBoxBStart
|
||||
// | ##########^ | | |
|
||||
// | ##############|#### | | |
|
||||
// +---------#################|######|-------|-+---- aBandY
|
||||
// +---------#################|######|-------|-+---- aBandBStart
|
||||
// | ###################|######|## | |
|
||||
// | # aTopCornerRadiusY |######|### | |
|
||||
// | aBStartCornerRadiusB |######|### | |
|
||||
// | ######################|######|##### | |
|
||||
// +---#######################|<-----------><->^---- aBandYMost
|
||||
// +---#######################|<-----------><->^---- aBandBEnd
|
||||
// | ########################|############## |
|
||||
// | ########################|############## |---- y
|
||||
// | ########################|############## |---- b
|
||||
// | #########################|############### |
|
||||
// | ######################## v<-------------->v
|
||||
// |######################### aTopCornerRadiusX|
|
||||
// |###################### aBStartCornerRadiusL|
|
||||
// |###########################################|
|
||||
// |###########################################|
|
||||
// |###########################################|
|
||||
|
@ -705,32 +748,34 @@ nsFloatManager::FloatInfo::ComputeEllipseXInterceptDiff(
|
|||
// | ######################### |
|
||||
// | ################### |
|
||||
// | ########### |
|
||||
// +-------------------------------------------+----- aShapeBoxYMost
|
||||
// +-------------------------------------------+----- aShapeBoxBEnd
|
||||
|
||||
NS_ASSERTION(aShapeBoxY <= aShapeBoxYMost, "Bad shape box coordinates!");
|
||||
NS_ASSERTION(aBandY <= aBandYMost, "Bad band coordinates!");
|
||||
NS_ASSERTION(aShapeBoxBStart <= aShapeBoxBEnd, "Bad shape box coordinates!");
|
||||
NS_ASSERTION(aBandBStart <= aBandBEnd, "Bad band coordinates!");
|
||||
|
||||
nscoord xDiff = 0;
|
||||
nscoord lineDiff = 0;
|
||||
|
||||
// If the band intersects both the top and bottom corners, we don't need
|
||||
// to enter either branch because the correct xDiff is 0.
|
||||
if (aBandYMost >= aShapeBoxY &&
|
||||
aBandYMost <= aShapeBoxY + aTopCornerRadiusY) {
|
||||
// The band intersects only the top corner.
|
||||
nscoord y = aTopCornerRadiusY - (aBandYMost - aShapeBoxY);
|
||||
nscoord xIntercept =
|
||||
XInterceptAtY(y, aTopCornerRadiusX, aTopCornerRadiusY);
|
||||
xDiff = aTopCornerRadiusX - xIntercept;
|
||||
} else if (aBandY >= aShapeBoxYMost - aBottomCornerRadiusY &&
|
||||
aBandY <= aShapeBoxYMost) {
|
||||
// The band intersects only the bottom corner.
|
||||
nscoord y = aBottomCornerRadiusY - (aShapeBoxYMost - aBandY);
|
||||
nscoord xIntercept =
|
||||
XInterceptAtY(y, aBottomCornerRadiusX, aBottomCornerRadiusY);
|
||||
xDiff = aBottomCornerRadiusX - xIntercept;
|
||||
// If the band intersects both the block-start and block-end corners, we
|
||||
// don't need to enter either branch because the correct lineDiff is 0.
|
||||
if (aBStartCornerRadiusB > 0 &&
|
||||
aBandBEnd >= aShapeBoxBStart &&
|
||||
aBandBEnd <= aShapeBoxBStart + aBStartCornerRadiusB) {
|
||||
// The band intersects only the block-start corner.
|
||||
nscoord b = aBStartCornerRadiusB - (aBandBEnd - aShapeBoxBStart);
|
||||
nscoord lineIntercept =
|
||||
XInterceptAtY(b, aBStartCornerRadiusL, aBStartCornerRadiusB);
|
||||
lineDiff = aBStartCornerRadiusL - lineIntercept;
|
||||
} else if (aBEndCornerRadiusB > 0 &&
|
||||
aBandBStart >= aShapeBoxBEnd - aBEndCornerRadiusB &&
|
||||
aBandBStart <= aShapeBoxBEnd) {
|
||||
// The band intersects only the block-end corner.
|
||||
nscoord b = aBEndCornerRadiusB - (aShapeBoxBEnd - aBandBStart);
|
||||
nscoord lineIntercept =
|
||||
XInterceptAtY(b, aBEndCornerRadiusL, aBEndCornerRadiusB);
|
||||
lineDiff = aBEndCornerRadiusL - lineIntercept;
|
||||
}
|
||||
|
||||
return xDiff;
|
||||
return lineDiff;
|
||||
}
|
||||
|
||||
/* static */ nscoord
|
||||
|
|
|
@ -335,10 +335,10 @@ private:
|
|||
// aBStart and aBEnd are the starting and ending coordinate of a band.
|
||||
// LineLeft() and LineRight() return the innermost line-left extent and
|
||||
// line-right extent within the given band, respectively.
|
||||
nscoord LineLeft(ShapeType aShapeType, const nscoord aBStart,
|
||||
const nscoord aBEnd) const;
|
||||
nscoord LineRight(ShapeType aShapeType, const nscoord aBStart,
|
||||
const nscoord aBEnd) const;
|
||||
nscoord LineLeft(mozilla::WritingMode aWM, ShapeType aShapeType,
|
||||
const nscoord aBStart, const nscoord aBEnd) const;
|
||||
nscoord LineRight(mozilla::WritingMode aWM, ShapeType aShapeType,
|
||||
const nscoord aBStart, const nscoord aBEnd) const;
|
||||
|
||||
nscoord BStart(ShapeType aShapeType) const
|
||||
{
|
||||
|
@ -349,18 +349,19 @@ private:
|
|||
return aShapeType == ShapeType::Margin ? BEnd() : ShapeBoxRect().YMost();
|
||||
}
|
||||
|
||||
// Compute the minimum x-axis difference between the bounding shape box
|
||||
// and its rounded corner within the given band (y-axis region). This is
|
||||
// used as a helper function to compute the LineRight() and LineLeft().
|
||||
// See the picture in the implementation for an example.
|
||||
// Compute the minimum line-axis difference between the bounding shape
|
||||
// box and its rounded corner within the given band (block-axis region).
|
||||
// This is used as a helper function to compute the LineRight() and
|
||||
// LineLeft(). See the picture in the implementation for an example.
|
||||
// RadiusL and RadiusB stand for radius on the line-axis and block-axis.
|
||||
//
|
||||
// Returns the x-axis diff, or 0 if there's no rounded corner within
|
||||
// the given band.
|
||||
static nscoord ComputeEllipseXInterceptDiff(
|
||||
const nscoord aShapeBoxY, const nscoord aShapeBoxYMost,
|
||||
const nscoord aTopCornerRadiusX, const nscoord aTopCornerRadiusY,
|
||||
const nscoord aBottomCornerRadiusX, const nscoord aBottomCornerRadiusY,
|
||||
const nscoord aBandY, const nscoord aBandYMost);
|
||||
// Returns radius-x diff on the line-axis, or 0 if there's no rounded
|
||||
// corner within the given band.
|
||||
static nscoord ComputeEllipseLineInterceptDiff(
|
||||
const nscoord aShapeBoxBStart, const nscoord aShapeBoxBEnd,
|
||||
const nscoord aBStartCornerRadiusL, const nscoord aBStartCornerRadiusB,
|
||||
const nscoord aBEndCornerRadiusL, const nscoord aBEndCornerRadiusB,
|
||||
const nscoord aBandBStart, const nscoord aBandBEnd);
|
||||
|
||||
static nscoord XInterceptAtY(const nscoord aY, const nscoord aRadiusX,
|
||||
const nscoord aRadiusY);
|
||||
|
|
|
@ -4632,11 +4632,11 @@ IntrinsicSizeOffsets(nsIFrame* aFrame, bool aForISize)
|
|||
|
||||
const nsStyleBorder* styleBorder = aFrame->StyleBorder();
|
||||
if (verticalAxis) {
|
||||
result.hBorder += styleBorder->GetComputedBorderWidth(NS_SIDE_TOP);
|
||||
result.hBorder += styleBorder->GetComputedBorderWidth(NS_SIDE_BOTTOM);
|
||||
result.hBorder += styleBorder->GetComputedBorderWidth(eSideTop);
|
||||
result.hBorder += styleBorder->GetComputedBorderWidth(eSideBottom);
|
||||
} else {
|
||||
result.hBorder += styleBorder->GetComputedBorderWidth(NS_SIDE_LEFT);
|
||||
result.hBorder += styleBorder->GetComputedBorderWidth(NS_SIDE_RIGHT);
|
||||
result.hBorder += styleBorder->GetComputedBorderWidth(eSideLeft);
|
||||
result.hBorder += styleBorder->GetComputedBorderWidth(eSideRight);
|
||||
}
|
||||
|
||||
const nsStyleDisplay* disp = aFrame->StyleDisplay();
|
||||
|
|
|
@ -116,20 +116,20 @@ nsInlineFrame::IsSelfEmpty()
|
|||
// get logical start and end flags.
|
||||
if (wm.IsVertical()) {
|
||||
haveStart =
|
||||
border->GetComputedBorderWidth(NS_SIDE_TOP) != 0 ||
|
||||
border->GetComputedBorderWidth(eSideTop) != 0 ||
|
||||
!nsLayoutUtils::IsPaddingZero(padding->mPadding.GetTop()) ||
|
||||
!IsMarginZero(margin->mMargin.GetTop());
|
||||
haveEnd =
|
||||
border->GetComputedBorderWidth(NS_SIDE_BOTTOM) != 0 ||
|
||||
border->GetComputedBorderWidth(eSideBottom) != 0 ||
|
||||
!nsLayoutUtils::IsPaddingZero(padding->mPadding.GetBottom()) ||
|
||||
!IsMarginZero(margin->mMargin.GetBottom());
|
||||
} else {
|
||||
haveStart =
|
||||
border->GetComputedBorderWidth(NS_SIDE_LEFT) != 0 ||
|
||||
border->GetComputedBorderWidth(eSideLeft) != 0 ||
|
||||
!nsLayoutUtils::IsPaddingZero(padding->mPadding.GetLeft()) ||
|
||||
!IsMarginZero(margin->mMargin.GetLeft());
|
||||
haveEnd =
|
||||
border->GetComputedBorderWidth(NS_SIDE_RIGHT) != 0 ||
|
||||
border->GetComputedBorderWidth(eSideRight) != 0 ||
|
||||
!nsLayoutUtils::IsPaddingZero(padding->mPadding.GetRight()) ||
|
||||
!IsMarginZero(margin->mMargin.GetRight());
|
||||
}
|
||||
|
|
|
@ -758,8 +758,8 @@ IsPercentageAware(const nsIFrame* aFrame)
|
|||
pos->mWidth.GetUnit() != eStyleUnit_Auto) ||
|
||||
pos->MaxWidthDependsOnContainer() ||
|
||||
pos->MinWidthDependsOnContainer() ||
|
||||
pos->OffsetHasPercent(NS_SIDE_RIGHT) ||
|
||||
pos->OffsetHasPercent(NS_SIDE_LEFT)) {
|
||||
pos->OffsetHasPercent(eSideRight) ||
|
||||
pos->OffsetHasPercent(eSideLeft)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -79,7 +79,7 @@ nsPageContentFrame::Reflow(nsPresContext* aPresContext,
|
|||
nscoord xmost = aDesiredSize.ScrollableOverflow().XMost();
|
||||
if (xmost > aDesiredSize.Width()) {
|
||||
nscoord widthToFit = xmost + padding.right +
|
||||
kidReflowInput.mStyleBorder->GetComputedBorderWidth(NS_SIDE_RIGHT);
|
||||
kidReflowInput.mStyleBorder->GetComputedBorderWidth(eSideRight);
|
||||
float ratio = float(maxSize.width) / widthToFit;
|
||||
NS_ASSERTION(ratio >= 0.0 && ratio < 1.0, "invalid shrink-to-fit ratio");
|
||||
mPD->mShrinkToFitRatio = std::min(mPD->mShrinkToFitRatio, ratio);
|
||||
|
|
|
@ -204,13 +204,13 @@ ApplyBorderToStyle(const nsMathMLmtdFrame* aFrame,
|
|||
// values, we simply repeat the last value.
|
||||
int32_t listLength = rowLinesList->Length();
|
||||
if (rowIndex < listLength) {
|
||||
aStyleBorder.SetBorderStyle(NS_SIDE_TOP,
|
||||
aStyleBorder.SetBorderStyle(eSideTop,
|
||||
rowLinesList->ElementAt(rowIndex - 1));
|
||||
} else {
|
||||
aStyleBorder.SetBorderStyle(NS_SIDE_TOP,
|
||||
aStyleBorder.SetBorderStyle(eSideTop,
|
||||
rowLinesList->ElementAt(listLength - 1));
|
||||
}
|
||||
aStyleBorder.SetBorderWidth(NS_SIDE_TOP, borderWidth);
|
||||
aStyleBorder.SetBorderWidth(eSideTop, borderWidth);
|
||||
}
|
||||
|
||||
// We don't place a column line on the left of the first column.
|
||||
|
@ -219,13 +219,13 @@ ApplyBorderToStyle(const nsMathMLmtdFrame* aFrame,
|
|||
// values, we simply repeat the last value.
|
||||
int32_t listLength = columnLinesList->Length();
|
||||
if (columnIndex < listLength) {
|
||||
aStyleBorder.SetBorderStyle(NS_SIDE_LEFT,
|
||||
aStyleBorder.SetBorderStyle(eSideLeft,
|
||||
columnLinesList->ElementAt(columnIndex - 1));
|
||||
} else {
|
||||
aStyleBorder.SetBorderStyle(NS_SIDE_LEFT,
|
||||
aStyleBorder.SetBorderStyle(eSideLeft,
|
||||
columnLinesList->ElementAt(listLength - 1));
|
||||
}
|
||||
aStyleBorder.SetBorderWidth(NS_SIDE_LEFT, borderWidth);
|
||||
aStyleBorder.SetBorderWidth(eSideLeft, borderWidth);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,13 +10,6 @@
|
|||
#define DOT_LENGTH 1 // square
|
||||
#define DASH_LENGTH 3 // 3 times longer than dot
|
||||
|
||||
// some shorthand for side bits
|
||||
#define SIDE_BIT_TOP (1 << NS_SIDE_TOP)
|
||||
#define SIDE_BIT_RIGHT (1 << NS_SIDE_RIGHT)
|
||||
#define SIDE_BIT_BOTTOM (1 << NS_SIDE_BOTTOM)
|
||||
#define SIDE_BIT_LEFT (1 << NS_SIDE_LEFT)
|
||||
#define SIDE_BITS_ALL (SIDE_BIT_TOP|SIDE_BIT_RIGHT|SIDE_BIT_BOTTOM|SIDE_BIT_LEFT)
|
||||
|
||||
#define C_TL NS_CORNER_TOP_LEFT
|
||||
#define C_TR NS_CORNER_TOP_RIGHT
|
||||
#define C_BR NS_CORNER_BOTTOM_RIGHT
|
||||
|
|
|
@ -437,7 +437,7 @@ static DrawResult DrawBorderImage(nsPresContext* aPresContext,
|
|||
Sides aSkipSides,
|
||||
PaintBorderFlags aFlags);
|
||||
|
||||
static nscolor MakeBevelColor(mozilla::css::Side whichSide, uint8_t style,
|
||||
static nscolor MakeBevelColor(mozilla::Side whichSide, uint8_t style,
|
||||
nscolor aBackgroundColor,
|
||||
nscolor aBorderColor);
|
||||
|
||||
|
@ -461,7 +461,7 @@ void nsCSSRendering::Shutdown()
|
|||
* Make a bevel color
|
||||
*/
|
||||
static nscolor
|
||||
MakeBevelColor(mozilla::css::Side whichSide, uint8_t style,
|
||||
MakeBevelColor(mozilla::Side whichSide, uint8_t style,
|
||||
nscolor aBackgroundColor, nscolor aBorderColor)
|
||||
{
|
||||
|
||||
|
@ -476,24 +476,24 @@ MakeBevelColor(mozilla::css::Side whichSide, uint8_t style,
|
|||
(style == NS_STYLE_BORDER_STYLE_RIDGE)) {
|
||||
// Flip colors for these two border styles
|
||||
switch (whichSide) {
|
||||
case NS_SIDE_BOTTOM: whichSide = NS_SIDE_TOP; break;
|
||||
case NS_SIDE_RIGHT: whichSide = NS_SIDE_LEFT; break;
|
||||
case NS_SIDE_TOP: whichSide = NS_SIDE_BOTTOM; break;
|
||||
case NS_SIDE_LEFT: whichSide = NS_SIDE_RIGHT; break;
|
||||
case eSideBottom: whichSide = eSideTop; break;
|
||||
case eSideRight: whichSide = eSideLeft; break;
|
||||
case eSideTop: whichSide = eSideBottom; break;
|
||||
case eSideLeft: whichSide = eSideRight; break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (whichSide) {
|
||||
case NS_SIDE_BOTTOM:
|
||||
case eSideBottom:
|
||||
theColor = colors[1];
|
||||
break;
|
||||
case NS_SIDE_RIGHT:
|
||||
case eSideRight:
|
||||
theColor = colors[1];
|
||||
break;
|
||||
case NS_SIDE_TOP:
|
||||
case eSideTop:
|
||||
theColor = colors[0];
|
||||
break;
|
||||
case NS_SIDE_LEFT:
|
||||
case eSideLeft:
|
||||
default:
|
||||
theColor = colors[0];
|
||||
break;
|
||||
|
@ -1582,10 +1582,10 @@ nsCSSRendering::PaintBoxShadowOuter(nsPresContext* aPresContext,
|
|||
|
||||
Float borderSizes[4];
|
||||
|
||||
borderSizes[NS_SIDE_LEFT] = spreadDistance;
|
||||
borderSizes[NS_SIDE_TOP] = spreadDistance;
|
||||
borderSizes[NS_SIDE_RIGHT] = spreadDistance;
|
||||
borderSizes[NS_SIDE_BOTTOM] = spreadDistance;
|
||||
borderSizes[eSideLeft] = spreadDistance;
|
||||
borderSizes[eSideTop] = spreadDistance;
|
||||
borderSizes[eSideRight] = spreadDistance;
|
||||
borderSizes[eSideBottom] = spreadDistance;
|
||||
|
||||
nsCSSBorderRenderer::ComputeOuterRadii(borderRadii, borderSizes,
|
||||
&clipRectRadii);
|
||||
|
@ -1694,19 +1694,19 @@ nsCSSRendering::PaintBoxShadowInner(nsPresContext* aPresContext,
|
|||
|
||||
// See PaintBoxShadowOuter and bug 514670
|
||||
if (innerRadii[C_TL].width > 0 || innerRadii[C_BL].width > 0) {
|
||||
borderSizes[NS_SIDE_LEFT] = spreadDistance;
|
||||
borderSizes[eSideLeft] = spreadDistance;
|
||||
}
|
||||
|
||||
if (innerRadii[C_TL].height > 0 || innerRadii[C_TR].height > 0) {
|
||||
borderSizes[NS_SIDE_TOP] = spreadDistance;
|
||||
borderSizes[eSideTop] = spreadDistance;
|
||||
}
|
||||
|
||||
if (innerRadii[C_TR].width > 0 || innerRadii[C_BR].width > 0) {
|
||||
borderSizes[NS_SIDE_RIGHT] = spreadDistance;
|
||||
borderSizes[eSideRight] = spreadDistance;
|
||||
}
|
||||
|
||||
if (innerRadii[C_BL].height > 0 || innerRadii[C_BR].height > 0) {
|
||||
borderSizes[NS_SIDE_BOTTOM] = spreadDistance;
|
||||
borderSizes[eSideBottom] = spreadDistance;
|
||||
}
|
||||
|
||||
nsCSSBorderRenderer::ComputeInnerRadii(innerRadii, borderSizes,
|
||||
|
@ -1837,7 +1837,7 @@ nsCSSRendering::PaintBackground(const PaintBGParams& aParams)
|
|||
}
|
||||
|
||||
static bool
|
||||
IsOpaqueBorderEdge(const nsStyleBorder& aBorder, mozilla::css::Side aSide)
|
||||
IsOpaqueBorderEdge(const nsStyleBorder& aBorder, mozilla::Side aSide)
|
||||
{
|
||||
if (aBorder.GetComputedBorder().Side(aSide) == 0)
|
||||
return true;
|
||||
|
@ -4273,32 +4273,32 @@ DrawSolidBorderSegment(DrawTarget& aDrawTarget,
|
|||
Float startBevelOffset =
|
||||
NSAppUnitsToFloatPixels(aStartBevelOffset, aAppUnitsPerDevPixel);
|
||||
switch(aStartBevelSide) {
|
||||
case NS_SIDE_TOP:
|
||||
case eSideTop:
|
||||
poly[0].x += startBevelOffset;
|
||||
break;
|
||||
case NS_SIDE_BOTTOM:
|
||||
case eSideBottom:
|
||||
poly[3].x += startBevelOffset;
|
||||
break;
|
||||
case NS_SIDE_RIGHT:
|
||||
case eSideRight:
|
||||
poly[1].y += startBevelOffset;
|
||||
break;
|
||||
case NS_SIDE_LEFT:
|
||||
case eSideLeft:
|
||||
poly[0].y += startBevelOffset;
|
||||
}
|
||||
|
||||
Float endBevelOffset =
|
||||
NSAppUnitsToFloatPixels(aEndBevelOffset, aAppUnitsPerDevPixel);
|
||||
switch(aEndBevelSide) {
|
||||
case NS_SIDE_TOP:
|
||||
case eSideTop:
|
||||
poly[1].x -= endBevelOffset;
|
||||
break;
|
||||
case NS_SIDE_BOTTOM:
|
||||
case eSideBottom:
|
||||
poly[2].x -= endBevelOffset;
|
||||
break;
|
||||
case NS_SIDE_RIGHT:
|
||||
case eSideRight:
|
||||
poly[2].y -= endBevelOffset;
|
||||
break;
|
||||
case NS_SIDE_LEFT:
|
||||
case eSideLeft:
|
||||
poly[3].y -= endBevelOffset;
|
||||
}
|
||||
|
||||
|
@ -4350,7 +4350,7 @@ nsCSSRendering::DrawTableBorderSegment(DrawTarget& aDrawTarget,
|
|||
uint8_t aEndBevelSide,
|
||||
nscoord aEndBevelOffset)
|
||||
{
|
||||
bool horizontal = ((NS_SIDE_TOP == aStartBevelSide) || (NS_SIDE_BOTTOM == aStartBevelSide));
|
||||
bool horizontal = ((eSideTop == aStartBevelSide) || (eSideBottom == aStartBevelSide));
|
||||
nscoord twipsPerPixel = NSIntPixelsToAppUnits(1, aAppUnitsPerCSSPixel);
|
||||
uint8_t ridgeGroove = NS_STYLE_BORDER_STYLE_RIDGE;
|
||||
|
||||
|
@ -4434,7 +4434,7 @@ nsCSSRendering::DrawTableBorderSegment(DrawTarget& aDrawTarget,
|
|||
? RoundFloatToPixel(0.5f * (float)aStartBevelOffset, twipsPerPixel, true) : 0;
|
||||
nscoord endBevel = (aEndBevelOffset > 0)
|
||||
? RoundFloatToPixel(0.5f * (float)aEndBevelOffset, twipsPerPixel, true) : 0;
|
||||
mozilla::css::Side ridgeGrooveSide = (horizontal) ? NS_SIDE_TOP : NS_SIDE_LEFT;
|
||||
mozilla::Side ridgeGrooveSide = (horizontal) ? eSideTop : eSideLeft;
|
||||
// FIXME: In theory, this should use the visited-dependent
|
||||
// background color, but I don't care.
|
||||
nscolor bevelColor = MakeBevelColor(ridgeGrooveSide, ridgeGroove,
|
||||
|
@ -4445,11 +4445,11 @@ nsCSSRendering::DrawTableBorderSegment(DrawTarget& aDrawTarget,
|
|||
if (horizontal) { // top, bottom
|
||||
half = RoundFloatToPixel(0.5f * (float)aBorder.height, twipsPerPixel);
|
||||
rect.height = half;
|
||||
if (NS_SIDE_TOP == aStartBevelSide) {
|
||||
if (eSideTop == aStartBevelSide) {
|
||||
rect.x += startBevel;
|
||||
rect.width -= startBevel;
|
||||
}
|
||||
if (NS_SIDE_TOP == aEndBevelSide) {
|
||||
if (eSideTop == aEndBevelSide) {
|
||||
rect.width -= endBevel;
|
||||
}
|
||||
DrawSolidBorderSegment(aDrawTarget, rect, bevelColor,
|
||||
|
@ -4460,11 +4460,11 @@ nsCSSRendering::DrawTableBorderSegment(DrawTarget& aDrawTarget,
|
|||
else { // left, right
|
||||
half = RoundFloatToPixel(0.5f * (float)aBorder.width, twipsPerPixel);
|
||||
rect.width = half;
|
||||
if (NS_SIDE_LEFT == aStartBevelSide) {
|
||||
if (eSideLeft == aStartBevelSide) {
|
||||
rect.y += startBevel;
|
||||
rect.height -= startBevel;
|
||||
}
|
||||
if (NS_SIDE_LEFT == aEndBevelSide) {
|
||||
if (eSideLeft == aEndBevelSide) {
|
||||
rect.height -= endBevel;
|
||||
}
|
||||
DrawSolidBorderSegment(aDrawTarget, rect, bevelColor,
|
||||
|
@ -4474,7 +4474,7 @@ nsCSSRendering::DrawTableBorderSegment(DrawTarget& aDrawTarget,
|
|||
}
|
||||
|
||||
rect = aBorder;
|
||||
ridgeGrooveSide = (NS_SIDE_TOP == ridgeGrooveSide) ? NS_SIDE_BOTTOM : NS_SIDE_RIGHT;
|
||||
ridgeGrooveSide = (eSideTop == ridgeGrooveSide) ? eSideBottom : eSideRight;
|
||||
// FIXME: In theory, this should use the visited-dependent
|
||||
// background color, but I don't care.
|
||||
bevelColor = MakeBevelColor(ridgeGrooveSide, ridgeGroove,
|
||||
|
@ -4482,11 +4482,11 @@ nsCSSRendering::DrawTableBorderSegment(DrawTarget& aDrawTarget,
|
|||
if (horizontal) {
|
||||
rect.y = rect.y + half;
|
||||
rect.height = aBorder.height - half;
|
||||
if (NS_SIDE_BOTTOM == aStartBevelSide) {
|
||||
if (eSideBottom == aStartBevelSide) {
|
||||
rect.x += startBevel;
|
||||
rect.width -= startBevel;
|
||||
}
|
||||
if (NS_SIDE_BOTTOM == aEndBevelSide) {
|
||||
if (eSideBottom == aEndBevelSide) {
|
||||
rect.width -= endBevel;
|
||||
}
|
||||
DrawSolidBorderSegment(aDrawTarget, rect, bevelColor,
|
||||
|
@ -4497,11 +4497,11 @@ nsCSSRendering::DrawTableBorderSegment(DrawTarget& aDrawTarget,
|
|||
else {
|
||||
rect.x = rect.x + half;
|
||||
rect.width = aBorder.width - half;
|
||||
if (NS_SIDE_RIGHT == aStartBevelSide) {
|
||||
if (eSideRight == aStartBevelSide) {
|
||||
rect.y += aStartBevelOffset - startBevel;
|
||||
rect.height -= startBevel;
|
||||
}
|
||||
if (NS_SIDE_RIGHT == aEndBevelSide) {
|
||||
if (eSideRight == aEndBevelSide) {
|
||||
rect.height -= endBevel;
|
||||
}
|
||||
DrawSolidBorderSegment(aDrawTarget, rect, bevelColor,
|
||||
|
@ -4526,11 +4526,11 @@ nsCSSRendering::DrawTableBorderSegment(DrawTarget& aDrawTarget,
|
|||
|
||||
// draw the top line or rect
|
||||
nsRect topRect(aBorder.x, aBorder.y, aBorder.width, thirdHeight);
|
||||
if (NS_SIDE_TOP == aStartBevelSide) {
|
||||
if (eSideTop == aStartBevelSide) {
|
||||
topRect.x += aStartBevelOffset - startBevel;
|
||||
topRect.width -= aStartBevelOffset - startBevel;
|
||||
}
|
||||
if (NS_SIDE_TOP == aEndBevelSide) {
|
||||
if (eSideTop == aEndBevelSide) {
|
||||
topRect.width -= aEndBevelOffset - endBevel;
|
||||
}
|
||||
DrawSolidBorderSegment(aDrawTarget, topRect, aBorderColor,
|
||||
|
@ -4541,11 +4541,11 @@ nsCSSRendering::DrawTableBorderSegment(DrawTarget& aDrawTarget,
|
|||
// draw the botom line or rect
|
||||
nscoord heightOffset = aBorder.height - thirdHeight;
|
||||
nsRect bottomRect(aBorder.x, aBorder.y + heightOffset, aBorder.width, aBorder.height - heightOffset);
|
||||
if (NS_SIDE_BOTTOM == aStartBevelSide) {
|
||||
if (eSideBottom == aStartBevelSide) {
|
||||
bottomRect.x += aStartBevelOffset - startBevel;
|
||||
bottomRect.width -= aStartBevelOffset - startBevel;
|
||||
}
|
||||
if (NS_SIDE_BOTTOM == aEndBevelSide) {
|
||||
if (eSideBottom == aEndBevelSide) {
|
||||
bottomRect.width -= aEndBevelOffset - endBevel;
|
||||
}
|
||||
DrawSolidBorderSegment(aDrawTarget, bottomRect, aBorderColor,
|
||||
|
@ -4557,11 +4557,11 @@ nsCSSRendering::DrawTableBorderSegment(DrawTarget& aDrawTarget,
|
|||
nscoord thirdWidth = RoundFloatToPixel(0.333333f * (float)aBorder.width, twipsPerPixel);
|
||||
|
||||
nsRect leftRect(aBorder.x, aBorder.y, thirdWidth, aBorder.height);
|
||||
if (NS_SIDE_LEFT == aStartBevelSide) {
|
||||
if (eSideLeft == aStartBevelSide) {
|
||||
leftRect.y += aStartBevelOffset - startBevel;
|
||||
leftRect.height -= aStartBevelOffset - startBevel;
|
||||
}
|
||||
if (NS_SIDE_LEFT == aEndBevelSide) {
|
||||
if (eSideLeft == aEndBevelSide) {
|
||||
leftRect.height -= aEndBevelOffset - endBevel;
|
||||
}
|
||||
DrawSolidBorderSegment(aDrawTarget, leftRect, aBorderColor,
|
||||
|
@ -4571,11 +4571,11 @@ nsCSSRendering::DrawTableBorderSegment(DrawTarget& aDrawTarget,
|
|||
|
||||
nscoord widthOffset = aBorder.width - thirdWidth;
|
||||
nsRect rightRect(aBorder.x + widthOffset, aBorder.y, aBorder.width - widthOffset, aBorder.height);
|
||||
if (NS_SIDE_RIGHT == aStartBevelSide) {
|
||||
if (eSideRight == aStartBevelSide) {
|
||||
rightRect.y += aStartBevelOffset - startBevel;
|
||||
rightRect.height -= aStartBevelOffset - startBevel;
|
||||
}
|
||||
if (NS_SIDE_RIGHT == aEndBevelSide) {
|
||||
if (eSideRight == aEndBevelSide) {
|
||||
rightRect.height -= aEndBevelOffset - endBevel;
|
||||
}
|
||||
DrawSolidBorderSegment(aDrawTarget, rightRect, aBorderColor,
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче