Merge mozilla-central to mozilla-inbound

This commit is contained in:
Carsten "Tomcat" Book 2016-11-24 16:46:19 +01:00
Родитель 8865218aa3 61849e269d
Коммит dd36826044
313 изменённых файлов: 19587 добавлений и 17512 удалений

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

@ -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,

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