Merge m-c to b2ginbound, a=merge

This commit is contained in:
Wes Kocher 2015-09-03 14:11:39 -07:00
commit 1478c7cff8
171 changed files with 3870 additions and 2007 deletions

View File

@ -1,5 +1,5 @@
<?xml version="1.0"?>
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1437165748000">
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1441146756000">
<emItems>
<emItem blockID="i58" id="webmaster@buzzzzvideos.info">
<versionRange minVersion="0" maxVersion="*">
@ -30,6 +30,12 @@
</versionRange>
<prefs>
</prefs>
</emItem>
<emItem blockID="i994" id="addonhack@mozilla.kewis.ch">
<versionRange minVersion="0" maxVersion="*" severity="3">
</versionRange>
<prefs>
</prefs>
</emItem>
<emItem blockID="i400" id="{dd6b651f-dfb9-4142-b0bd-09912ad22674}">
<versionRange minVersion="0" maxVersion="*" severity="1">
@ -267,6 +273,12 @@
</versionRange>
<prefs>
</prefs>
</emItem>
<emItem blockID="i972" id="831778-poidjao88DASfsAnindsd@jetpack">
<versionRange minVersion="0" maxVersion="*" severity="3">
</versionRange>
<prefs>
</prefs>
</emItem>
<emItem blockID="i352" id="vpyekkifgv@vpyekkifgv.org">
<versionRange minVersion="0" maxVersion="*" severity="3">
@ -312,6 +324,12 @@
</versionRange>
<prefs>
</prefs>
</emItem>
<emItem blockID="i988" id="{b12785f5-d8d0-4530-a3ea-5c4263b85bef}">
<versionRange minVersion="0" maxVersion="*" severity="1">
</versionRange>
<prefs>
</prefs>
</emItem>
<emItem blockID="i856" id="/^({94d62e35-4b43-494c-bf52-ba5935df36ef}|firefox@advanceelite\.com|{bb7b7a60-f574-47c2-8a0b-4c56f2da9802})$/">
<versionRange minVersion="0" maxVersion="*" severity="3">
@ -460,8 +478,10 @@
<prefs>
</prefs>
</emItem>
<emItem blockID="i644" id="youtubeunblocker@unblocker.yt">
<emItem blockID="i990" id="youtubeunblocker@unblocker.yt">
<versionRange minVersion="43.4.1" maxVersion="77.5.1" severity="3">
</versionRange>
<versionRange minVersion="0" maxVersion="0.6.16" severity="1">
</versionRange>
<prefs>
</prefs>
@ -817,6 +837,12 @@
</versionRange>
<prefs>
</prefs>
</emItem>
<emItem blockID="i980" id="wHO@W9.net">
<versionRange minVersion="0" maxVersion="*" severity="3">
</versionRange>
<prefs>
</prefs>
</emItem>
<emItem blockID="i99" id="pfzPXmnzQRXX6@2iABkVe.com">
<versionRange minVersion="0" maxVersion="*">
@ -1149,8 +1175,8 @@
<prefs>
</prefs>
</emItem>
<emItem blockID="i306" id="{ADFA33FD-16F5-4355-8504-DF4D664CFE10}">
<versionRange minVersion="0" maxVersion="*" severity="1">
<emItem blockID="i437" id="{4933189D-C7F7-4C6E-834B-A29F087BFD23}">
<versionRange minVersion="0" maxVersion="*" severity="3">
</versionRange>
<prefs>
</prefs>
@ -1328,6 +1354,12 @@
</versionRange>
<prefs>
</prefs>
</emItem>
<emItem blockID="i968" id="{184AA5E6-741D-464a-820E-94B3ABC2F3B4}">
<versionRange minVersion="0" maxVersion="*" severity="3">
</versionRange>
<prefs>
</prefs>
</emItem>
<emItem blockID="i754" id="{bb7b7a60-f574-47c2-8a0b-4c56f2da9802}">
<versionRange minVersion="0" maxVersion="*" severity="1">
@ -1760,6 +1792,12 @@
</versionRange>
<prefs>
</prefs>
</emItem>
<emItem blockID="i982" id="odtffplugin@ibm.com">
<versionRange minVersion="9.0.1.1" maxVersion="9.0.1.100" severity="1">
</versionRange>
<prefs>
</prefs>
</emItem>
<emItem blockID="i564" id="/^(firefox@vebergreat\.net|EFGLQA@78ETGYN-0W7FN789T87\.COM)$/">
<versionRange minVersion="0" maxVersion="*" severity="1">
@ -2056,8 +2094,8 @@
<prefs>
</prefs>
</emItem>
<emItem blockID="i437" id="{4933189D-C7F7-4C6E-834B-A29F087BFD23}">
<versionRange minVersion="0" maxVersion="*" severity="3">
<emItem blockID="i306" id="{ADFA33FD-16F5-4355-8504-DF4D664CFE10}">
<versionRange minVersion="0" maxVersion="*" severity="1">
</versionRange>
<prefs>
</prefs>
@ -2343,6 +2381,12 @@
</versionRange>
<prefs>
</prefs>
</emItem>
<emItem blockID="i970" id="hha8771ui3-Fo9j9h7aH98jsdfa8sda@jetpack">
<versionRange minVersion="0" maxVersion="*" severity="3">
</versionRange>
<prefs>
</prefs>
</emItem>
<emItem blockID="i342" id="lbmsrvfvxcblvpane@lpaezhjez.org">
<versionRange minVersion="0" maxVersion="*" severity="1">
@ -3163,6 +3207,43 @@
</devices>
<feature>DIRECT3D_9_LAYERS</feature> <featureStatus>BLOCKED_DEVICE</featureStatus> </gfxBlacklistEntry>
<gfxBlacklistEntry blockID="g511"> <os>WINNT 5.1</os> <vendor>0x8086</vendor> <feature>DIRECT3D_9_LAYERS, WEBGL_ANGLE</feature> <featureStatus>BLOCKED_DRIVER_VERSION</featureStatus> <driverVersion>6.14.10.5218</driverVersion> <driverVersionComparator>LESS_THAN</driverVersionComparator> </gfxBlacklistEntry>
<gfxBlacklistEntry blockID="g974"> <os>WINNT 10.0</os> <vendor>0x1002</vendor> <devices>
<device>0x6920</device>
<device>0x6921</device>
<device>0x6928</device>
<device>0x6929</device>
<device>0x692b</device>
<device>0x692f</device>
<device>0x6930</device>
<device>0x6938</device>
<device>0x6939</device>
<device>0x6900</device>
<device>0x6901</device>
<device>0x6902</device>
<device>0x6903</device>
<device>0x6907</device>
<device>0x7300</device>
</devices>
<feature>DIRECT2D</feature> <featureStatus>BLOCKED_DRIVER_VERSION</featureStatus> <driverVersion>15.201.1151.0</driverVersion> <driverVersionComparator>LESS_THAN</driverVersionComparator> </gfxBlacklistEntry>
<gfxBlacklistEntry blockID="g984"> <os>All</os> <vendor>0x8086</vendor> <feature>DIRECT2D</feature> <featureStatus>BLOCKED_DRIVER_VERSION</featureStatus> <driverVersion>8.15.10.2413</driverVersion> <driverVersionComparator>LESS_THAN_OR_EQUAL</driverVersionComparator> </gfxBlacklistEntry>
<gfxBlacklistEntry blockID="g992"> <os>WINNT 8.1</os> <vendor>0x1002</vendor> <devices>
<device>0x6920</device>
<device>0x6921</device>
<device>0x6928</device>
<device>0x6929</device>
<device>0x692b</device>
<device>0x692f</device>
<device>0x6930</device>
<device>0x6938</device>
<device>0x6939</device>
<device>0x6900</device>
<device>0x6901</device>
<device>0x6902</device>
<device>0x6903</device>
<device>0x6907</device>
<device>0x7300</device>
</devices>
<feature>DIRECT2D</feature> <featureStatus>BLOCKED_DRIVER_VERSION</featureStatus> <driverVersion>15.201.1151.0</driverVersion> <driverVersionComparator>LESS_THAN</driverVersionComparator> </gfxBlacklistEntry>
</gfxItems>
<certItems>

View File

@ -263,6 +263,7 @@ let gFxAccounts = {
let defaultLabel = this.panelUIStatus.getAttribute("defaultlabel");
let errorLabel = this.panelUIStatus.getAttribute("errorlabel");
let unverifiedLabel = this.panelUIStatus.getAttribute("unverifiedlabel");
let signedInTooltiptext = this.panelUIStatus.getAttribute("signedinTooltiptext");
let updateWithUserData = (userData) => {
@ -287,6 +288,13 @@ let gFxAccounts = {
this.panelUILabel.setAttribute("label", errorLabel);
this.panelUIStatus.setAttribute("tooltiptext", tooltipDescription);
showErrorBadge = true;
} else if (!userData.verified) {
let tooltipDescription = this.strings.formatStringFromName("verifyDescription", [userData.email], 1);
this.panelUIFooter.setAttribute("fxastatus", "error");
this.panelUIFooter.setAttribute("unverified", "true");
this.panelUILabel.setAttribute("label", unverifiedLabel);
this.panelUIStatus.setAttribute("tooltiptext", tooltipDescription);
showErrorBadge = true;
} else {
this.panelUIFooter.setAttribute("fxastatus", "signedin");
this.panelUILabel.setAttribute("label", userData.email);
@ -438,7 +446,11 @@ let gFxAccounts = {
this.openPreferences();
break;
case "error":
this.openSignInAgainPage("menupanel");
if (this.panelUIFooter.getAttribute("unverified")) {
this.openPreferences();
} else {
this.openSignInAgainPage("menupanel");
}
break;
case "migrate-signup":
case "migrate-verify":

View File

@ -602,6 +602,7 @@ ContentSearchUIController.prototype = {
this._updateSearchWithHeader();
document.getElementById("contentSearchSettingsButton").textContent =
this._strings.searchSettings;
this.input.setAttribute("placeholder", this._strings.searchPlaceholder);
},
_updateDefaultEngineHeader: function () {

View File

@ -21,6 +21,12 @@
case "can_link_account":
test_can_link_account();
break;
case "logout":
test_logout();
break;
case "delete":
test_delete();
break;
}
};
@ -93,6 +99,40 @@
window.dispatchEvent(event);
}
function test_logout() {
var event = new window.CustomEvent("WebChannelMessageToChrome", {
detail: {
id: webChannelId,
message: {
command: "fxaccounts:logout",
data: {
uid: 'uid'
},
messageId: 3,
},
},
});
window.dispatchEvent(event);
}
function test_delete() {
var event = new window.CustomEvent("WebChannelMessageToChrome", {
detail: {
id: webChannelId,
message: {
command: "fxaccounts:delete",
data: {
uid: 'uid'
},
messageId: 4,
},
},
});
window.dispatchEvent(event);
}
</script>
</body>
</html>

View File

@ -120,6 +120,62 @@ let gTests = [
yield promiseEcho;
});
}
},
{
desc: "fxa web channel - logout messages should notify the fxAccounts object",
run: function* () {
let promiseLogout = new Promise((resolve, reject) => {
let logout = (uid) => {
Assert.equal(uid, 'uid');
client.tearDown();
resolve();
};
let client = new FxAccountsWebChannel({
content_uri: TEST_HTTP_PATH,
channel_id: TEST_CHANNEL_ID,
helpers: {
logout: logout
}
});
});
yield BrowserTestUtils.withNewTab({
gBrowser: gBrowser,
url: TEST_BASE_URL + "?logout"
}, function* () {
yield promiseLogout;
});
}
},
{
desc: "fxa web channel - delete messages should notify the fxAccounts object",
run: function* () {
let promiseDelete = new Promise((resolve, reject) => {
let logout = (uid) => {
Assert.equal(uid, 'uid');
client.tearDown();
resolve();
};
let client = new FxAccountsWebChannel({
content_uri: TEST_HTTP_PATH,
channel_id: TEST_CHANNEL_ID,
helpers: {
logout: logout
}
});
});
yield BrowserTestUtils.withNewTab({
gBrowser: gBrowser,
url: TEST_BASE_URL + "?delete"
}, function* () {
yield promiseDelete;
});
}
}
]; // gTests

View File

@ -68,7 +68,6 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
this._mayTrimURLs = this._prefs.getBoolPref("trimURLs");
this._userMadeSearchSuggestionsChoice =
this._prefs.getBoolPref("userMadeSearchSuggestionsChoice");
this._ignoreNextSelect = false;
this.inputField.controllers.insertControllerAt(0, this._copyCutController);
this.inputField.addEventListener("paste", this, false);
@ -854,15 +853,6 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
]]></body>
</method>
<method name="selectTextRange">
<parameter name="aStartIndex"/>
<parameter name="aEndIndex"/>
<body><![CDATA[
this._ignoreNextSelect = true;
this.inputField.setSelectionRange(aStartIndex, aEndIndex);
]]></body>
</method>
<method name="onInput">
<parameter name="aEvent"/>
<body><![CDATA[
@ -1015,20 +1005,16 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
<handler event="dragover" phase="capturing" action="this.onDragOver(event, this);"/>
<handler event="drop" phase="capturing" action="this.onDrop(event, this);"/>
<handler event="select"><![CDATA[
if (this._ignoreNextSelect) {
// If this select event is coming from autocomplete's selectTextRange,
// then we don't need to adjust what's on the selection keyboard here,
// but make sure to reset the flag since this should be a one-time
// suppression.
this._ignoreNextSelect = false;
return;
}
if (!Cc["@mozilla.org/widget/clipboard;1"]
.getService(Ci.nsIClipboard)
.supportsSelectionClipboard())
return;
if (!window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils)
.isHandlingUserInput)
return;
var val = this._getSelectedValueForClipboard();
if (!val)
return;

View File

@ -25,6 +25,7 @@
defaultlabel="&fxaSignIn.label;"
signedinTooltiptext="&fxaSignedIn.tooltip;"
errorlabel="&fxaSignInError.label;"
unverifiedlabel="&fxaUnverified.label;"
onclick="if (event.which == 1) gFxAccounts.onMenuPanelCommand();">
<image id="PanelUI-fxa-avatar"/>
<toolbarbutton id="PanelUI-fxa-label"

View File

@ -6,6 +6,7 @@
Components.utils.import("resource://gre/modules/DownloadUtils.jsm");
Components.utils.import("resource://gre/modules/LoadContextInfo.jsm");
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/BrowserUtils.jsm");
var gAdvancedPane = {
_inited: false,
@ -590,7 +591,7 @@ var gAdvancedPane = {
// get the permission
var pm = Components.classes["@mozilla.org/permissionmanager;1"]
.getService(Components.interfaces.nsIPermissionManager);
var perm = pm.getPermissionObject(principal, "offline-app");
var perm = pm.getPermissionObject(principal, "offline-app", true);
// clear offline cache entries
try {

View File

@ -252,8 +252,8 @@
<label id="fxaEmailAddress1"/>
<label id="fxaDisplayName" hidden="true"/>
<hbox class="fxaAccountBoxButtons" align="center">
<vbox flex="1"><button id="fxaUnlinkButton">&disconnect.label;</button></vbox>
<vbox flex="1"><label id="verifiedManage" class="text-link">&verifiedManage.label;</label></vbox>
<button id="fxaUnlinkButton">&disconnect.label;</button>
<label id="verifiedManage" class="text-link">&verifiedManage.label;</label>
</hbox>
</vbox>
</hbox>

View File

@ -24,18 +24,33 @@ add_task(function*() {
yield checkKeyBindings(toolbox);
}
Services.prefs.clearUserPref("devtools.toolbox.zoomValue", BOTTOM);
Services.prefs.clearUserPref("devtools.toolbox.zoomValue");
Services.prefs.setCharPref("devtools.toolbox.host", BOTTOM);
yield toolbox.destroy();
gBrowser.removeCurrentTab();
});
function* checkKeyBindings(toolbox) {
function zoomWithKey(toolbox, key) {
if (!key) {
info("Key was empty, skipping zoomWithKey");
return;
}
info("Zooming with key: " + key);
let currentZoom = toolbox.zoomValue;
let key = toolbox.doc.getElementById("toolbox-zoom-in-key").getAttribute("key");
EventUtils.synthesizeKey(key, {accelKey: true}, toolbox.doc.defaultView);
let newZoom = toolbox.zoomValue;
isnot(newZoom, currentZoom, "The zoom level was changed in the toolbox");
isnot(toolbox.zoomValue, currentZoom, "The zoom level was changed in the toolbox");
}
function* checkKeyBindings(toolbox) {
zoomWithKey(toolbox, toolbox.doc.getElementById("toolbox-zoom-in-key").getAttribute("key"));
zoomWithKey(toolbox, toolbox.doc.getElementById("toolbox-zoom-in-key2").getAttribute("key"));
zoomWithKey(toolbox, toolbox.doc.getElementById("toolbox-zoom-in-key3").getAttribute("key"));
zoomWithKey(toolbox, toolbox.doc.getElementById("toolbox-zoom-reset-key").getAttribute("key"));
zoomWithKey(toolbox, toolbox.doc.getElementById("toolbox-zoom-out-key").getAttribute("key"));
zoomWithKey(toolbox, toolbox.doc.getElementById("toolbox-zoom-out-key2").getAttribute("key"));
zoomWithKey(toolbox, toolbox.doc.getElementById("toolbox-zoom-reset-key2").getAttribute("key"));
}

View File

@ -572,11 +572,20 @@ Toolbox.prototype = {
let inKey2 = this.doc.getElementById("toolbox-zoom-in-key2");
inKey2.addEventListener("command", this.zoomIn.bind(this), true);
let inKey3 = this.doc.getElementById("toolbox-zoom-in-key3");
inKey3.addEventListener("command", this.zoomIn.bind(this), true);
let outKey = this.doc.getElementById("toolbox-zoom-out-key");
outKey.addEventListener("command", this.zoomOut.bind(this), true);
let outKey2 = this.doc.getElementById("toolbox-zoom-out-key2");
outKey2.addEventListener("command", this.zoomOut.bind(this), true);
let resetKey = this.doc.getElementById("toolbox-zoom-reset-key");
resetKey.addEventListener("command", this.zoomReset.bind(this), true);
let resetKey2 = this.doc.getElementById("toolbox-zoom-reset-key2");
resetKey2.addEventListener("command", this.zoomReset.bind(this), true);
},
_disableZoomKeys: function() {
@ -586,11 +595,20 @@ Toolbox.prototype = {
let inKey2 = this.doc.getElementById("toolbox-zoom-in-key2");
inKey2.setAttribute("disabled", "true");
let inKey3 = this.doc.getElementById("toolbox-zoom-in-key3");
inKey3.setAttribute("disabled", "true");
let outKey = this.doc.getElementById("toolbox-zoom-out-key");
outKey.setAttribute("disabled", "true");
let outKey2 = this.doc.getElementById("toolbox-zoom-out-key2");
outKey2.setAttribute("disabled", "true");
let resetKey = this.doc.getElementById("toolbox-zoom-reset-key");
resetKey.setAttribute("disabled", "true");
let resetKey2 = this.doc.getElementById("toolbox-zoom-reset-key2");
resetKey2.setAttribute("disabled", "true");
},
/**

View File

@ -44,19 +44,31 @@
oncommand="void(0);"
modifiers="accel"/>
<key id="toolbox-zoom-in-key"
key="&toolboxZoomIn.key;"
key="&fullZoomEnlargeCmd.commandkey;"
oncommand="void(0);"
modifiers="accel"/>
<key id="toolbox-zoom-in-key2"
key="&toolboxZoomIn.key2;"
key="&fullZoomEnlargeCmd.commandkey2;"
oncommand="void(0);"
modifiers="accel"/>
<key id="toolbox-zoom-in-key3"
key="&fullZoomEnlargeCmd.commandkey3;"
oncommand="void(0);"
modifiers="accel"/>
<key id="toolbox-zoom-out-key"
key="&toolboxZoomOut.key;"
key="&fullZoomReduceCmd.commandkey;"
oncommand="void(0);"
modifiers="accel"/>
<key id="toolbox-zoom-out-key2"
key="&fullZoomReduceCmd.commandkey2;"
oncommand="void(0);"
modifiers="accel"/>
<key id="toolbox-zoom-reset-key"
key="&toolboxZoomReset.key;"
key="&fullZoomResetCmd.commandkey;"
oncommand="void(0);"
modifiers="accel"/>
<key id="toolbox-zoom-reset-key2"
key="&fullZoomResetCmd.commandkey2;"
oncommand="void(0);"
modifiers="accel"/>
<key id="toolbox-reload-key"

View File

@ -92,7 +92,7 @@
save="${elt}"
class="editor comment theme-comment"><!--
--><span>&lt;!--</span><!--
--><pre save="${value}" style="display:inline-block;" tabindex="0"></pre><!--
--><pre save="${value}" style="display:inline-block; white-space: normal;" tabindex="0"></pre><!--
--><span>--&gt;</span><!--
--></span>

View File

@ -8,14 +8,17 @@
const { Cu, Cc, Ci, components } = require("chrome");
const TAB_SIZE = "devtools.editor.tabsize";
const {
EXPAND_TAB,
TAB_SIZE,
DETECT_INDENT,
getIndentationFromIteration
} = require("devtools/toolkit/shared/indentation");
const ENABLE_CODE_FOLDING = "devtools.editor.enableCodeFolding";
const EXPAND_TAB = "devtools.editor.expandtab";
const KEYMAP = "devtools.editor.keymap";
const AUTO_CLOSE = "devtools.editor.autoclosebrackets";
const AUTOCOMPLETE = "devtools.editor.autocomplete";
const DETECT_INDENT = "devtools.editor.detectindentation";
const DETECT_INDENT_MAX_LINES = 500;
const L10N_BUNDLE = "chrome://browser/locale/devtools/sourceeditor.properties";
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
const VALID_KEYMAPS = new Set(["emacs", "vim", "sublime"]);
@ -514,20 +517,15 @@ Editor.prototype = {
resetIndentUnit: function() {
let cm = editors.get(this);
let indentWithTabs = !Services.prefs.getBoolPref(EXPAND_TAB);
let indentUnit = Services.prefs.getIntPref(TAB_SIZE);
let shouldDetect = Services.prefs.getBoolPref(DETECT_INDENT);
let iterFn = function(start, end, callback) {
cm.eachLine(start, end, (line) => {
return callback(line.text);
});
};
let {indentUnit, indentWithTabs} = getIndentationFromIteration(iterFn);
cm.setOption("tabSize", indentUnit);
if (shouldDetect) {
let indent = detectIndentation(this);
if (indent != null) {
indentWithTabs = indent.tabs;
indentUnit = indent.spaces ? indent.spaces : indentUnit;
}
}
cm.setOption("indentUnit", indentUnit);
cm.setOption("indentWithTabs", indentWithTabs);
},
@ -1300,73 +1298,4 @@ function controller(ed) {
};
}
/**
* Detect the indentation used in an editor. Returns an object
* with 'tabs' - whether this is tab-indented and 'spaces' - the
* width of one indent in spaces. Or `null` if it's inconclusive.
*/
function detectIndentation(ed) {
let cm = editors.get(ed);
let spaces = {}; // # spaces indent -> # lines with that indent
let last = 0; // indentation width of the last line we saw
let tabs = 0; // # of lines that start with a tab
let total = 0; // # of indented lines (non-zero indent)
cm.eachLine(0, DETECT_INDENT_MAX_LINES, (line) => {
let text = line.text;
if (text.startsWith("\t")) {
tabs++;
total++;
return;
}
let width = 0;
while (text[width] === " ") {
width++;
}
// don't count lines that are all spaces
if (width == text.length) {
last = 0;
return;
}
if (width > 1) {
total++;
}
// see how much this line is offset from the line above it
let indent = Math.abs(width - last);
if (indent > 1 && indent <= 8) {
spaces[indent] = (spaces[indent] || 0) + 1;
}
last = width;
});
// this file is not indented at all
if (total == 0) {
return null;
}
// mark as tabs if they start more than half the lines
if (tabs >= total / 2) {
return { tabs: true };
}
// find most frequent non-zero width difference between adjacent lines
let freqIndent = null, max = 1;
for (let width in spaces) {
width = parseInt(width, 10);
let tally = spaces[width];
if (tally > max) {
max = tally;
freqIndent = width;
}
}
if (!freqIndent) {
return null;
}
return { tabs: false, spaces: freqIndent };
}
module.exports = Editor;

View File

@ -7,18 +7,12 @@
"use strict";
const {Cu} = require("chrome");
const EventEmitter = require("devtools/toolkit/event-emitter");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/Promise.jsm");
let EventEmitter = require("devtools/toolkit/event-emitter");
loader.lazyGetter(this, "StorageFront",
() => require("devtools/server/actors/storage").StorageFront);
loader.lazyGetter(this, "StorageUI",
() => require("devtools/storage/ui").StorageUI);
loader.lazyRequireGetter(this, "StorageFront",
"devtools/server/actors/storage", true);
loader.lazyRequireGetter(this, "StorageUI",
"devtools/storage/ui", true);
let StoragePanel = this.StoragePanel =
function StoragePanel(panelWin, toolbox) {
@ -88,9 +82,3 @@ StoragePanel.prototype = {
return Promise.resolve(null);
},
};
XPCOMUtils.defineLazyGetter(StoragePanel.prototype, "strings",
function() {
return Services.strings.createBundle(
"chrome://browser/locale/devtools/storage.properties");
});

View File

@ -6,27 +6,24 @@
"use strict";
const {Cu} = require("chrome");
const STORAGE_STRINGS = "chrome://browser/locale/devtools/storage.properties";
const EventEmitter = require("devtools/toolkit/event-emitter");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyGetter(this, "TreeWidget",
() => require("devtools/shared/widgets/TreeWidget").TreeWidget);
XPCOMUtils.defineLazyGetter(this, "TableWidget",
() => require("devtools/shared/widgets/TableWidget").TableWidget);
XPCOMUtils.defineLazyModuleGetter(this, "EventEmitter",
"resource://gre/modules/devtools/event-emitter.js");
XPCOMUtils.defineLazyModuleGetter(this, "ViewHelpers",
loader.lazyRequireGetter(this, "TreeWidget",
"devtools/shared/widgets/TreeWidget", true);
loader.lazyRequireGetter(this, "TableWidget",
"devtools/shared/widgets/TableWidget", true);
loader.lazyImporter(this, "ViewHelpers",
"resource:///modules/devtools/ViewHelpers.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "VariablesView",
loader.lazyImporter(this, "VariablesView",
"resource:///modules/devtools/VariablesView.jsm");
let Telemetry = require("devtools/shared/telemetry");
const Telemetry = require("devtools/shared/telemetry");
/**
* Localization convenience methods.
*/
let L10N = new ViewHelpers.L10N(STORAGE_STRINGS);
const STORAGE_STRINGS = "chrome://browser/locale/devtools/storage.properties";
const L10N = new ViewHelpers.L10N(STORAGE_STRINGS);
const GENERIC_VARIABLES_VIEW_SETTINGS = {
lazyEmpty: true,
@ -177,88 +174,15 @@ StorageUI.prototype = {
*/
onUpdate: function({ changed, added, deleted }) {
if (deleted) {
for (let type in deleted) {
for (let host in deleted[type]) {
if (!deleted[type][host].length) {
// This means that the whole host is deleted, thus the item should
// be removed from the storage tree
if (this.tree.isSelected([type, host])) {
this.table.clear();
this.hideSidebar();
this.tree.selectPreviousItem();
}
this.tree.remove([type, host]);
} else if (this.tree.isSelected([type, host])) {
for (let name of deleted[type][host]) {
try {
// trying to parse names in case its for indexedDB
let names = JSON.parse(name);
if (!names[2]) {
if (this.tree.isSelected([type, host, names[0], names[1]])) {
this.tree.selectPreviousItem();
this.tree.remove([type, host, names[0], names[1]]);
this.table.clear();
this.hideSidebar();
}
} else if (this.tree.isSelected([ type, host,
names[0], names[1]])) {
this.removeItemFromTable(names[2]);
}
} catch (ex) {
this.removeItemFromTable(name);
}
}
}
}
}
this.handleDeletedItems(deleted);
}
if (added) {
for (let type in added) {
for (let host in added[type]) {
this.tree.add([type, {id: host, type: "url"}]);
for (let name of added[type][host]) {
try {
name = JSON.parse(name);
if (name.length == 3) {
name.splice(2, 1);
}
this.tree.add([type, host, ...name]);
if (!this.tree.selectedItem) {
this.tree.selectedItem = [type, host, name[0], name[1]];
this.fetchStorageObjects(type, host, [JSON.stringify(name)], 1);
}
} catch(ex) {
// Do nothing
}
}
if (this.tree.isSelected([type, host])) {
this.fetchStorageObjects(type, host, added[type][host], 1);
}
}
}
this.handleAddedItems(added);
}
if (changed) {
let [type, host, db, objectStore] = this.tree.selectedItem;
if (changed[type] && changed[type][host]) {
if (changed[type][host].length) {
try {
let toUpdate = [];
for (let name of changed[type][host]) {
let names = JSON.parse(name);
if (names[0] == db && names[1] == objectStore && names[2]) {
toUpdate.push(name);
}
}
this.fetchStorageObjects(type, host, toUpdate, 2);
} catch (ex) {
this.fetchStorageObjects(type, host, changed[type][host], 2);
}
}
}
this.handleChangedItems(changed);
}
if (added || deleted || changed) {
@ -266,6 +190,106 @@ StorageUI.prototype = {
}
},
/**
* Handle added items received by onUpdate
*
* @param {object} See onUpdate docs
*/
handleAddedItems: function(added) {
for (let type in added) {
for (let host in added[type]) {
this.tree.add([type, {id: host, type: "url"}]);
for (let name of added[type][host]) {
try {
name = JSON.parse(name);
if (name.length == 3) {
name.splice(2, 1);
}
this.tree.add([type, host, ...name]);
if (!this.tree.selectedItem) {
this.tree.selectedItem = [type, host, name[0], name[1]];
this.fetchStorageObjects(type, host, [JSON.stringify(name)], 1);
}
} catch(ex) {
// Do nothing
}
}
if (this.tree.isSelected([type, host])) {
this.fetchStorageObjects(type, host, added[type][host], 1);
}
}
}
},
/**
* Handle deleted items received by onUpdate
*
* @param {object} See onUpdate docs
*/
handleDeletedItems: function(deleted) {
for (let type in deleted) {
for (let host in deleted[type]) {
if (!deleted[type][host].length) {
// This means that the whole host is deleted, thus the item should
// be removed from the storage tree
if (this.tree.isSelected([type, host])) {
this.table.clear();
this.hideSidebar();
this.tree.selectPreviousItem();
}
this.tree.remove([type, host]);
} else if (this.tree.isSelected([type, host])) {
for (let name of deleted[type][host]) {
try {
// trying to parse names in case its for indexedDB
let names = JSON.parse(name);
if (!this.tree.isSelected([type, host, names[0], names[1]])) {
return;
}
if (!names[2]) {
this.tree.selectPreviousItem();
this.tree.remove([type, host, names[0], names[1]]);
this.table.clear();
this.hideSidebar();
} else {
this.removeItemFromTable(names[2]);
}
} catch (ex) {
this.removeItemFromTable(name);
}
}
}
}
}
},
/**
* Handle changed items received by onUpdate
*
* @param {object} See onUpdate docs
*/
handleChangedItems: function(changed) {
let [type, host, db, objectStore] = this.tree.selectedItem;
if (!changed[type] || !changed[type][host] ||
changed[type][host].length == 0) {
return;
}
try {
let toUpdate = [];
for (let name of changed[type][host]) {
let names = JSON.parse(name);
if (names[0] == db && names[1] == objectStore && names[2]) {
toUpdate.push(name);
}
}
this.fetchStorageObjects(type, host, toUpdate, 2);
} catch (ex) {
this.fetchStorageObjects(type, host, changed[type][host], 2);
}
},
/**
* Fetches the storage objects from the storage actor and populates the
* storage table with the returned data.
@ -311,26 +335,27 @@ StorageUI.prototype = {
let typeLabel = L10N.getStr("tree.labels." + type);
this.tree.add([{id: type, label: typeLabel, type: "store"}]);
if (storageTypes[type].hosts) {
this.storageTypes[type] = storageTypes[type];
for (let host in storageTypes[type].hosts) {
this.tree.add([type, {id: host, type: "url"}]);
for (let name of storageTypes[type].hosts[host]) {
try {
let names = JSON.parse(name);
this.tree.add([type, host, ...names]);
if (!this.tree.selectedItem) {
this.tree.selectedItem = [type, host, names[0], names[1]];
this.fetchStorageObjects(type, host, [name], 0);
}
} catch(ex) {
// Do nothing
if (!storageTypes[type].hosts) {
continue;
}
this.storageTypes[type] = storageTypes[type];
for (let host in storageTypes[type].hosts) {
this.tree.add([type, {id: host, type: "url"}]);
for (let name of storageTypes[type].hosts[host]) {
try {
let names = JSON.parse(name);
this.tree.add([type, host, ...names]);
if (!this.tree.selectedItem) {
this.tree.selectedItem = [type, host, names[0], names[1]];
this.fetchStorageObjects(type, host, [name], 0);
}
} catch(ex) {
// Do Nothing
}
if (!this.tree.selectedItem) {
this.tree.selectedItem = [type, host];
this.fetchStorageObjects(type, host, null, 0);
}
}
if (!this.tree.selectedItem) {
this.tree.selectedItem = [type, host];
this.fetchStorageObjects(type, host, null, 0);
}
}
}
@ -478,8 +503,7 @@ StorageUI.prototype = {
}
}
// Testing for array
for (let i = 0; i < separators.length; i++) {
let p = separators[i];
for (let p of separators) {
let regex = new RegExp("^[^" + p + "]+(" + p + "+[^" + p + "]*)+$", "g");
if (value.match(regex)) {
return value.split(p.replace(/\\*/g, ""));

View File

@ -2874,7 +2874,7 @@ RuleEditor.prototype = {
ruleView.highlightedSelector);
}
this._moveSelectorFocus(newRule, direction);
editor._moveSelectorFocus(direction);
}).then(null, err => {
this.isEditing = false;
promiseWarn(err);
@ -2882,22 +2882,19 @@ RuleEditor.prototype = {
},
/**
* Handle moving the focus change after pressing tab and return from the
* selector inplace editor. The focused element after a tab or return keypress
* is lost because the rule editor is replaced.
* Handle moving the focus change after a tab or return keypress in the
* selector inplace editor.
*
* @param {Rule} rule
* The Rule object.
* @param {Number} direction
* The move focus direction number.
*/
_moveSelectorFocus: function(rule, direction) {
_moveSelectorFocus: function(direction) {
if (!direction || direction === Ci.nsIFocusManager.MOVEFOCUS_BACKWARD) {
return;
}
if (rule.textProps.length > 0) {
rule.textProps[0].editor.nameSpan.click();
if (this.rule.textProps.length > 0) {
this.rule.textProps[0].editor.nameSpan.click();
} else {
this.propertyList.click();
}

View File

@ -110,6 +110,7 @@ skip-if = e10s # Bug 1039528: "inspect element" contextual-menu doesn't work wit
[browser_ruleview_edit-selector_03.js]
[browser_ruleview_edit-selector_04.js]
[browser_ruleview_edit-selector_05.js]
[browser_ruleview_edit-selector_06.js]
[browser_ruleview_editable-field-focus_01.js]
[browser_ruleview_editable-field-focus_02.js]
[browser_ruleview_eyedropper.js]

View File

@ -0,0 +1,76 @@
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Testing selector inplace-editor behaviors in the rule-view with unmatched
// selectors
const TEST_URI = `
<style type="text/css">
.testclass {
text-align: center;
}
div {
}
</style>
<div class="testclass">Styled Node</div>
`;
add_task(function*() {
yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
let {inspector, view} = yield openRuleView();
yield selectNode(".testclass", inspector);
yield testEditClassSelector(view);
yield testEditDivSelector(view);
});
function* testEditClassSelector(view) {
let ruleEditor = getRuleViewRuleEditor(view, 1);
let editor = yield focusEditableField(view, ruleEditor.selectorText);
editor.input.value = "body";
let onRuleViewChanged = once(view, "ruleview-changed");
EventUtils.synthesizeKey("VK_RETURN", {});
yield onRuleViewChanged;
// Get the new rule editor that replaced the original
ruleEditor = getRuleViewRuleEditor(view, 1);
let propEditor = ruleEditor.rule.textProps[0].editor;
info("Check that the correct rules are visible");
is(view._elementStyle.rules.length, 3, "Should have 3 rules.");
ok(ruleEditor.element.getAttribute("unmatched"), "Rule editor is unmatched.");
is(getRuleViewRule(view, ".testclass"), undefined,
"Rule with .testclass selector should not exist.");
ok(getRuleViewRule(view, "body"),
"Rule with body selector exists.");
is(inplaceEditor(propEditor.nameSpan),
inplaceEditor(view.styleDocument.activeElement),
"Focus should have moved to the property name.");
}
function* testEditDivSelector(view) {
let ruleEditor = getRuleViewRuleEditor(view, 2);
let editor = yield focusEditableField(view, ruleEditor.selectorText);
editor.input.value = "asdf";
let onRuleViewChanged = once(view, "ruleview-changed");
EventUtils.synthesizeKey("VK_RETURN", {});
yield onRuleViewChanged;
// Get the new rule editor that replaced the original
ruleEditor = getRuleViewRuleEditor(view, 2);
info("Check that the correct rules are visible");
is(view._elementStyle.rules.length, 3, "Should have 3 rules.");
ok(ruleEditor.element.getAttribute("unmatched"), "Rule editor is unmatched.");
is(getRuleViewRule(view, "div"), undefined,
"Rule with div selector should not exist.");
ok(getRuleViewRule(view, "asdf"),
"Rule with asdf selector exists.");
is(inplaceEditor(ruleEditor.newPropSpan),
inplaceEditor(view.styleDocument.activeElement),
"Focus should have moved to the property name.");
}

View File

@ -27,6 +27,9 @@ resendVerificationEmail.accessKey = R
# LOCALIZATION NOTE (reconnectDescription) - %S = Email address of user's Firefox Account
reconnectDescription = Reconnect %S
# LOCALIZATION NOTE (verifyDescription) - %S = Email address of user's Firefox Account
verifyDescription = Verify %S
forgetMigration.label = Forget
forgetMigration.accessKey = F

View File

@ -112,6 +112,7 @@ These should match what Safari and other Apple applications use on OS X Lion. --
<!ENTITY fxaSignIn.label "Sign in to &syncBrand.shortName.label;">
<!ENTITY fxaSignedIn.tooltip "Open &syncBrand.shortName.label; preferences">
<!ENTITY fxaSignInError.label "Reconnect to &syncBrand.shortName.label;">
<!ENTITY fxaUnverified.label "Verify Your Account">
<!ENTITY syncStartPanel2.heading "&syncBrand.shortName.label; enabled">
<!ENTITY syncStartPanel2.subTitle "&brandShortName; will begin syncing momentarily.">
<!ENTITY syncErrorPanel.heading "Cannot connect to &syncBrand.shortName.label;">

View File

@ -15,10 +15,21 @@
<!ENTITY toolboxNextTool.key "]">
<!ENTITY toolboxPreviousTool.key "[">
<!ENTITY toolboxZoomIn.key "+">
<!ENTITY toolboxZoomIn.key2 "="> <!-- + is above this key on many keyboards -->
<!ENTITY toolboxZoomOut.key "-">
<!ENTITY toolboxZoomReset.key "0">
<!-- LOCALIZATION NOTE :
fullZoomEnlargeCmd.commandkey, fullZoomEnlargeCmd.commandkey2,
fullZoomEnlargeCmd.commandkey3, fullZoomReduceCmd.commandkey,
fullZoomReduceCmd.commandkey2, fullZoomResetCmd.commandkey,
and fullZoomResetCmd.commandkey2 should all match the corresponding
values from browser.dtd. -->
<!ENTITY fullZoomEnlargeCmd.commandkey "+">
<!ENTITY fullZoomEnlargeCmd.commandkey2 "=">
<!ENTITY fullZoomEnlargeCmd.commandkey3 "">
<!ENTITY fullZoomReduceCmd.commandkey "-">
<!ENTITY fullZoomReduceCmd.commandkey2 "">
<!ENTITY fullZoomResetCmd.commandkey "0">
<!ENTITY fullZoomResetCmd.commandkey2 "">
<!ENTITY toolboxReload.key "r">
<!-- This key is used with the accel+shift modifiers to minimize the toolbox -->

View File

@ -110,13 +110,13 @@
}
#PanelUI-menu-button[badge-status="update-succeeded"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
background-image: url(chrome://browser/skin/update-badge.svg);
background-color: #74BF43;
background: #74BF43 url(chrome://browser/skin/update-badge.svg) no-repeat center;
height: 13px;
}
#PanelUI-menu-button[badge-status="update-failed"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
background-image: url(chrome://browser/skin/update-badge-failed.svg);
background-color: #D90000;
background: #D90000 url(chrome://browser/skin/update-badge-failed.svg) no-repeat center;
height: 13px;
}
#PanelUI-menu-button[badge-status="fxa-needs-authentication"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {

View File

@ -468,13 +468,18 @@ description > html|a {
margin-top: 11px;
}
.fxaAccountBoxButtons button {
.fxaAccountBoxButtons > * {
-moz-box-flex: 1;
}
.fxaAccountBoxButtons > button {
padding-left: 11px;
padding-right: 11px;
margin: 0;
min-width: 0;
}
.fxaAccountBoxButtons button:first-child {
.fxaAccountBoxButtons > button:first-child {
margin-right: 14px !important;
}

View File

@ -38,33 +38,14 @@ leak:nr_reg_local_init
leak:r_log_register
leak:nr_reg_set
# Additional WebRTC leak suppressions added for Mochitest 3.
leak:mozilla::TransportLayerDtls::Setup
# Bug 1187424 - DesktopApplication does not free any of its string members.
leak:webrtc::DesktopApplication::
# Bug 1187518 - SCTP leaks in child process while running WebRTC tests.
leak:recv_function_udp
# Bug 1074310 - Very large e10s vp8 leaks, maybe in WebRTC tests.
leak:set_noise_sensitivity
leak:vp8_alloc_compressor_data
leak:vp8_change_config
leak:vp8_lookahead_init
leak:vpx_codec_enc_init_ver
###
### Many leaks only affect some test suites. The suite annotations are not checked.
###
# Bug 981195 - Small leak in the parser. m4
leak:ObjectGroup::fixPlainObjectGroup
# Bug 982111 - WebM is leaking. m1
leak:nestegg_read_packet
# Bug 987385 - Various plugin leaks. m3
leak:mozilla::plugins::PPluginInstanceParent::CallNPP_HandleEvent
leak:mozilla::plugins::PPluginModuleParent::OnCallReceived
@ -89,7 +70,7 @@ leak:_render_glyph_outline
# Bug 1023548 - Small leak under SECITEM_AllocItem_Util. bc1, bc3
leak:SECITEM_AllocItem_Util
# This is a one-time leak, so it is probably okay to ignore. bc1, oth
# This is a one-time leak, so it is probably okay to ignore. bc3, oth
leak:GlobalPrinters::InitializeGlobalPrinters
leak:nsPSPrinterList::GetPrinterList

View File

@ -36,33 +36,37 @@ static RedirEntry kRedirMap[] = {
},
{ "about", "chrome://global/content/aboutAbout.xhtml", 0 },
{
"credits", "http://www.mozilla.org/credits/",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT
"addons", "chrome://mozapps/content/extensions/extensions.xul",
nsIAboutModule::ALLOW_SCRIPT
},
{
"mozilla", "chrome://global/content/mozilla.xhtml",
"buildconfig", "chrome://global/content/buildconfig.html",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT
},
{
"plugins", "chrome://global/content/plugins.html",
nsIAboutModule::URI_MUST_LOAD_IN_CHILD
},
{ "config", "chrome://global/content/config.xul", 0 },
#ifdef MOZ_CRASHREPORTER
{ "crashes", "chrome://global/content/crashes.xhtml", 0 },
#endif
{
"logo", "chrome://branding/content/about.png",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT
},
{
"buildconfig", "chrome://global/content/buildconfig.html",
"credits", "http://www.mozilla.org/credits/",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT
},
{
"license", "chrome://global/content/license.html",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT
},
{
"logo", "chrome://branding/content/about.png",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT
},
{
"memory", "chrome://global/content/aboutMemory.xhtml",
nsIAboutModule::ALLOW_SCRIPT
},
{
"mozilla", "chrome://global/content/mozilla.xhtml",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT
},
{
"neterror", "chrome://global/content/netError.xhtml",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
@ -71,9 +75,14 @@ static RedirEntry kRedirMap[] = {
nsIAboutModule::HIDE_FROM_ABOUTABOUT
},
{
"memory", "chrome://global/content/aboutMemory.xhtml",
"networking", "chrome://global/content/aboutNetworking.xhtml",
nsIAboutModule::ALLOW_SCRIPT
},
{
"newaddon", "chrome://mozapps/content/extensions/newaddon.xul",
nsIAboutModule::ALLOW_SCRIPT |
nsIAboutModule::HIDE_FROM_ABOUTABOUT
},
#ifdef NIGHTLY_BUILD
{
"performance", "chrome://global/content/aboutPerformance.xhtml",
@ -81,29 +90,8 @@ static RedirEntry kRedirMap[] = {
},
#endif
{
"addons", "chrome://mozapps/content/extensions/extensions.xul",
nsIAboutModule::ALLOW_SCRIPT
},
{
"newaddon", "chrome://mozapps/content/extensions/newaddon.xul",
nsIAboutModule::ALLOW_SCRIPT |
nsIAboutModule::HIDE_FROM_ABOUTABOUT
},
{
"support", "chrome://global/content/aboutSupport.xhtml",
nsIAboutModule::ALLOW_SCRIPT
},
{
"telemetry", "chrome://global/content/aboutTelemetry.xhtml",
nsIAboutModule::ALLOW_SCRIPT
},
{
"networking", "chrome://global/content/aboutNetworking.xhtml",
nsIAboutModule::ALLOW_SCRIPT
},
{
"webrtc", "chrome://global/content/aboutwebrtc/aboutWebrtc.xhtml",
nsIAboutModule::ALLOW_SCRIPT
"plugins", "chrome://global/content/plugins.html",
nsIAboutModule::URI_MUST_LOAD_IN_CHILD
},
{
"serviceworkers", "chrome://global/content/aboutServiceWorkers.xhtml",
@ -117,6 +105,18 @@ static RedirEntry kRedirMap[] = {
"srcdoc", "about:blank",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
nsIAboutModule::HIDE_FROM_ABOUTABOUT
},
{
"support", "chrome://global/content/aboutSupport.xhtml",
nsIAboutModule::ALLOW_SCRIPT
},
{
"telemetry", "chrome://global/content/aboutTelemetry.xhtml",
nsIAboutModule::ALLOW_SCRIPT
},
{
"webrtc", "chrome://global/content/aboutwebrtc/aboutWebrtc.xhtml",
nsIAboutModule::ALLOW_SCRIPT
}
};
static const int kRedirTotal = mozilla::ArrayLength(kRedirMap);

View File

@ -154,27 +154,27 @@ const mozilla::Module::ContractIDEntry kDocShellContracts[] = {
{ NS_WEBNAVIGATION_INFO_CONTRACTID, &kNS_WEBNAVIGATION_INFO_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "about", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "addons", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "buildconfig", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "config", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
#ifdef MOZ_CRASHREPORTER
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "crashes", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
#endif
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "credits", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "plugins", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "mozilla", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "logo", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "buildconfig", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "license", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "neterror", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "logo", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "memory", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "performance", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "addons", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "mozilla", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "neterror", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "networking", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "newaddon", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "performance", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "plugins", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "serviceworkers", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "srcdoc", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "support", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "telemetry", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "networking", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "webrtc", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "srcdoc", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "serviceworkers", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_URI_LOADER_CONTRACTID, &kNS_URI_LOADER_CID },
{ NS_DOCUMENTLOADER_SERVICE_CONTRACTID, &kNS_DOCUMENTLOADER_SERVICE_CID },
{ NS_EXTERNALHELPERAPPSERVICE_CONTRACTID, &kNS_EXTERNALHELPERAPPSERVICE_CID },

View File

@ -23,10 +23,22 @@ using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::dom::workers;
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(PerformanceObserver,
mOwner,
mPerformance,
mCallback)
NS_IMPL_CYCLE_COLLECTION_CLASS(PerformanceObserver)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(PerformanceObserver)
tmp->Disconnect();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCallback)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPerformance)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(PerformanceObserver)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallback)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPerformance)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(PerformanceObserver)
NS_IMPL_CYCLE_COLLECTING_ADDREF(PerformanceObserver)
NS_IMPL_CYCLE_COLLECTING_RELEASE(PerformanceObserver)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PerformanceObserver)
@ -95,7 +107,22 @@ PerformanceObserver::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProt
}
void
PerformanceObserver::Notify(PerformanceEntry* aEntry)
PerformanceObserver::Notify()
{
if (mQueuedEntries.IsEmpty()) {
return;
}
nsRefPtr<PerformanceObserverEntryList> list =
new PerformanceObserverEntryList(this, mQueuedEntries);
ErrorResult rv;
mCallback->Call(this, *list, *this, rv);
NS_WARN_IF(rv.Failed());
mQueuedEntries.Clear();
}
void
PerformanceObserver::QueueEntry(PerformanceEntry* aEntry)
{
MOZ_ASSERT(aEntry);
@ -105,12 +132,7 @@ PerformanceObserver::Notify(PerformanceEntry* aEntry)
return;
}
nsRefPtr<PerformanceObserverEntryList> list = new PerformanceObserverEntryList(this);
list->AppendEntry(aEntry);
ErrorResult rv;
mCallback->Call(this, *list, *this, rv);
NS_WARN_IF(rv.Failed());
mQueuedEntries.AppendElement(aEntry);
}
static nsString sValidTypeNames[7] = {

View File

@ -59,7 +59,8 @@ public:
void Disconnect();
void Notify(PerformanceEntry* entry);
void Notify();
void QueueEntry(PerformanceEntry* aEntry);
private:
~PerformanceObserver();
@ -69,6 +70,7 @@ private:
nsRefPtr<PerformanceBase> mPerformance;
nsTArray<nsString> mEntryTypes;
bool mConnected;
nsTArray<nsRefPtr<PerformanceEntry>> mQueuedEntries;
};
} // namespace dom

View File

@ -94,10 +94,3 @@ PerformanceObserverEntryList::GetEntriesByName(
}
}
}
void
PerformanceObserverEntryList::AppendEntry(PerformanceEntry* aEntry)
{
mEntries.AppendElement(aEntry);
}

View File

@ -26,8 +26,11 @@ class PerformanceObserverEntryList final : public nsISupports,
~PerformanceObserverEntryList();
public:
explicit PerformanceObserverEntryList(nsISupports* aOwner)
PerformanceObserverEntryList(nsISupports* aOwner,
nsTArray<nsRefPtr<PerformanceEntry>>&
aEntries)
: mOwner(aOwner)
, mEntries(aEntries)
{
}
@ -50,8 +53,6 @@ public:
const Optional<nsAString>& aEntryType,
nsTArray<nsRefPtr<PerformanceEntry>>& aRetval);
void AppendEntry(PerformanceEntry* aEntry);
private:
nsCOMPtr<nsISupports> mOwner;
nsTArray<nsRefPtr<PerformanceEntry>> mEntries;

View File

@ -4409,8 +4409,7 @@ FindSheet(const nsCOMArray<nsIStyleSheet>& aSheets, nsIURI* aSheetURI)
}
nsresult
nsDocument::LoadAdditionalStyleSheet(additionalSheetType aType,
nsIURI* aSheetURI)
nsDocument::LoadAdditionalStyleSheet(additionalSheetType aType, nsIURI* aSheetURI)
{
NS_PRECONDITION(aSheetURI, "null arg");
@ -4419,29 +4418,11 @@ nsDocument::LoadAdditionalStyleSheet(additionalSheetType aType,
return NS_ERROR_INVALID_ARG;
// Loading the sheet sync.
nsRefPtr<css::Loader> loader = new css::Loader();
css::SheetParsingMode parsingMode;
switch (aType) {
case nsIDocument::eAgentSheet:
parsingMode = css::eAgentSheetFeatures;
break;
case nsIDocument::eUserSheet:
parsingMode = css::eUserSheetFeatures;
break;
case nsIDocument::eAuthorSheet:
parsingMode = css::eAuthorSheetFeatures;
break;
default:
MOZ_CRASH("impossible value for aType");
}
nsRefPtr<mozilla::css::Loader> loader = new mozilla::css::Loader();
nsRefPtr<CSSStyleSheet> sheet;
nsresult rv = loader->LoadSheetSync(aSheetURI, parsingMode, true,
getter_AddRefs(sheet));
nsresult rv = loader->LoadSheetSync(aSheetURI, aType == eAgentSheet,
true, getter_AddRefs(sheet));
NS_ENSURE_SUCCESS(rv, rv);
sheet->SetOwningDocument(this);
@ -7934,15 +7915,13 @@ nsDocument::GetViewportInfo(const ScreenIntSize& aDisplaySize)
ScreenSize viewportSize(viewportWidth, viewportWidth * aspectRatio);
return nsViewportInfo(RoundedToInt(viewportSize),
CSSToScreenScale(scaleToFit),
/*allowZoom*/false,
/*allowDoubleTapZoom*/ false);
/*allowZoom*/ true);
}
if (!gfxPrefs::MetaViewportEnabled()) {
return nsViewportInfo(aDisplaySize,
defaultScale,
/*allowZoom*/ false,
/*allowDoubleTapZoom*/ false);
/*allowZoom*/ false);
}
// In cases where the width of the CSS viewport is less than or equal to the width
@ -7953,13 +7932,7 @@ nsDocument::GetViewportInfo(const ScreenIntSize& aDisplaySize)
case DisplayWidthHeight:
return nsViewportInfo(aDisplaySize,
defaultScale,
/*allowZoom*/ true,
/*allowDoubleTapZoom*/ true);
case DisplayWidthHeightNoZoom:
return nsViewportInfo(aDisplaySize,
defaultScale,
/*allowZoom*/ false,
/*allowDoubleTapZoom*/ false);
/*allowZoom*/ true);
case Unknown:
{
nsAutoString viewport;
@ -7981,8 +7954,7 @@ nsDocument::GetViewportInfo(const ScreenIntSize& aDisplaySize)
mViewportType = DisplayWidthHeight;
return nsViewportInfo(aDisplaySize,
defaultScale,
/*allowZoom*/true,
/*allowDoubleTapZoom*/false);
/*allowZoom*/true);
}
}
}
@ -7993,8 +7965,7 @@ nsDocument::GetViewportInfo(const ScreenIntSize& aDisplaySize)
mViewportType = DisplayWidthHeight;
return nsViewportInfo(aDisplaySize,
defaultScale,
/*allowZoom*/true,
/*allowDoubleTapZoom*/false);
/*allowZoom*/true);
}
}
@ -8068,7 +8039,6 @@ nsDocument::GetViewportInfo(const ScreenIntSize& aDisplaySize)
(userScalable.EqualsLiteral("false"))) {
mAllowZoom = false;
}
mAllowDoubleTapZoom = mAllowZoom;
mScaleStrEmpty = scaleStr.IsEmpty();
mWidthStrEmpty = widthStr.IsEmpty();
@ -8079,6 +8049,24 @@ nsDocument::GetViewportInfo(const ScreenIntSize& aDisplaySize)
}
case Specified:
default:
LayoutDeviceToScreenScale effectiveMinScale = mScaleMinFloat;
LayoutDeviceToScreenScale effectiveMaxScale = mScaleMaxFloat;
bool effectiveValidMaxScale = mValidMaxScale;
bool effectiveAllowZoom = mAllowZoom;
if (gfxPrefs::ForceUserScalable()) {
// If the pref to force user-scalable is enabled, we ignore the values
// from the meta-viewport tag for these properties and just assume they
// allow the page to be scalable. Note in particular that this code is
// in the "Specified" branch of the enclosing switch statement, so that
// calls to GetViewportInfo always use the latest value of the
// ForceUserScalable pref. Other codepaths that return nsViewportInfo
// instances are all consistent with ForceUserScalable() already.
effectiveMinScale = kViewportMinScale;
effectiveMaxScale = kViewportMaxScale;
effectiveValidMaxScale = true;
effectiveAllowZoom = true;
}
CSSSize size = mViewportSize;
if (!mValidWidth) {
@ -8101,8 +8089,8 @@ nsDocument::GetViewportInfo(const ScreenIntSize& aDisplaySize)
}
CSSToScreenScale scaleFloat = mScaleFloat * layoutDeviceScale;
CSSToScreenScale scaleMinFloat = mScaleMinFloat * layoutDeviceScale;
CSSToScreenScale scaleMaxFloat = mScaleMaxFloat * layoutDeviceScale;
CSSToScreenScale scaleMinFloat = effectiveMinScale * layoutDeviceScale;
CSSToScreenScale scaleMaxFloat = effectiveMaxScale * layoutDeviceScale;
if (mAutoSize) {
// aDisplaySize is in screen pixels; convert them to CSS pixels for the viewport size.
@ -8127,14 +8115,14 @@ nsDocument::GetViewportInfo(const ScreenIntSize& aDisplaySize)
CSSSize displaySize = ScreenSize(aDisplaySize) / scaleFloat;
size.width = std::max(size.width, displaySize.width);
size.height = std::max(size.height, displaySize.height);
} else if (mValidMaxScale) {
} else if (effectiveValidMaxScale) {
CSSSize displaySize = ScreenSize(aDisplaySize) / scaleMaxFloat;
size.width = std::max(size.width, displaySize.width);
size.height = std::max(size.height, displaySize.height);
}
return nsViewportInfo(scaleFloat, scaleMinFloat, scaleMaxFloat, size,
mAutoSize, mAllowZoom, mAllowDoubleTapZoom);
mAutoSize, effectiveAllowZoom);
}
}
@ -9954,10 +9942,7 @@ nsresult
nsDocument::LoadChromeSheetSync(nsIURI* uri, bool isAgentSheet,
CSSStyleSheet** sheet)
{
css::SheetParsingMode mode =
isAgentSheet ? css::eAgentSheetFeatures
: css::eAuthorSheetFeatures;
return CSSLoader()->LoadSheetSync(uri, mode, isAgentSheet, sheet);
return CSSLoader()->LoadSheetSync(uri, isAgentSheet, isAgentSheet, sheet);
}
class nsDelayedEventDispatcher : public nsRunnable

View File

@ -1850,7 +1850,6 @@ private:
enum ViewportType {
DisplayWidthHeight,
DisplayWidthHeightNoZoom,
Specified,
Unknown
};

View File

@ -812,6 +812,7 @@ NS_IMPL_RELEASE_INHERITED(PerformanceBase, DOMEventTargetHelper)
PerformanceBase::PerformanceBase()
: mResourceTimingBufferSize(kDefaultResourceTimingBufferSize)
, mPendingNotificationObserversTask(false)
{
MOZ_ASSERT(!NS_IsMainThread());
}
@ -819,6 +820,7 @@ PerformanceBase::PerformanceBase()
PerformanceBase::PerformanceBase(nsPIDOMWindow* aWindow)
: DOMEventTargetHelper(aWindow)
, mResourceTimingBufferSize(kDefaultResourceTimingBufferSize)
, mPendingNotificationObserversTask(false)
{
MOZ_ASSERT(NS_IsMainThread());
}
@ -1050,9 +1052,7 @@ PerformanceBase::InsertUserEntry(PerformanceEntry* aEntry)
mUserEntries.InsertElementSorted(aEntry,
PerformanceEntryComparator());
NS_OBSERVER_ARRAY_NOTIFY_XPCOM_OBSERVERS(mObservers,
PerformanceObserver,
Notify, (aEntry));
QueueEntry(aEntry);
}
void
@ -1076,9 +1076,7 @@ PerformanceBase::InsertResourceEntry(PerformanceEntry* aEntry)
// call onresourcetimingbufferfull
DispatchBufferFullEvent();
}
NS_OBSERVER_ARRAY_NOTIFY_XPCOM_OBSERVERS(mObservers,
PerformanceObserver,
Notify, (aEntry));
QueueEntry(aEntry);
}
void
@ -1092,3 +1090,75 @@ PerformanceBase::RemoveObserver(PerformanceObserver* aObserver)
{
mObservers.RemoveElement(aObserver);
}
void
PerformanceBase::NotifyObservers()
{
mPendingNotificationObserversTask = false;
NS_OBSERVER_ARRAY_NOTIFY_XPCOM_OBSERVERS(mObservers,
PerformanceObserver,
Notify, ());
}
void
PerformanceBase::CancelNotificationObservers()
{
mPendingNotificationObserversTask = false;
}
class NotifyObserversTask final : public nsCancelableRunnable
{
public:
explicit NotifyObserversTask(PerformanceBase* aPerformance)
: mPerformance(aPerformance)
{
MOZ_ASSERT(mPerformance);
}
NS_IMETHOD Run() override
{
MOZ_ASSERT(mPerformance);
mPerformance->NotifyObservers();
return NS_OK;
}
NS_IMETHOD Cancel() override
{
mPerformance->CancelNotificationObservers();
mPerformance = nullptr;
return NS_OK;
}
private:
~NotifyObserversTask()
{
}
nsRefPtr<PerformanceBase> mPerformance;
};
void
PerformanceBase::RunNotificationObserversTask()
{
mPendingNotificationObserversTask = true;
nsCOMPtr<nsIRunnable> task = new NotifyObserversTask(this);
nsresult rv = NS_DispatchToCurrentThread(task);
if (NS_WARN_IF(NS_FAILED(rv))) {
mPendingNotificationObserversTask = false;
}
}
void
PerformanceBase::QueueEntry(PerformanceEntry* aEntry)
{
if (mObservers.IsEmpty()) {
return;
}
NS_OBSERVER_ARRAY_NOTIFY_XPCOM_OBSERVERS(mObservers,
PerformanceObserver,
QueueEntry, (aEntry));
if (!mPendingNotificationObserversTask) {
RunNotificationObserversTask();
}
}

View File

@ -325,6 +325,8 @@ public:
void AddObserver(PerformanceObserver* aObserver);
void RemoveObserver(PerformanceObserver* aObserver);
void NotifyObservers();
void CancelNotificationObservers();
protected:
virtual ~PerformanceBase();
@ -358,6 +360,9 @@ protected:
void LogEntry(PerformanceEntry* aEntry, const nsACString& aOwner) const;
void TimingNotification(PerformanceEntry* aEntry, const nsACString& aOwner, uint64_t epoch);
void RunNotificationObserversTask();
void QueueEntry(PerformanceEntry* aEntry);
nsTObserverArray<PerformanceObserver*> mObservers;
private:
@ -366,6 +371,7 @@ private:
uint64_t mResourceTimingBufferSize;
static const uint64_t kDefaultResourceTimingBufferSize = 150;
bool mPendingNotificationObserversTask;
};
// Script "performance" object

View File

@ -1103,8 +1103,7 @@ nsTreeSanitizer::SanitizeStyleSheet(const nsAString& aOriginal,
// Create the CSS parser, and parse the CSS text.
nsCSSParser parser(nullptr, sheet);
rv = parser.ParseSheet(aOriginal, aDocument->GetDocumentURI(), aBaseURI,
aDocument->NodePrincipal(), 0,
mozilla::css::eAuthorSheetFeatures);
aDocument->NodePrincipal(), 0, false);
NS_ENSURE_SUCCESS(rv, true);
// Mark the sheet as complete.
MOZ_ASSERT(!sheet->IsModified(),

View File

@ -26,16 +26,11 @@ class MOZ_STACK_CLASS nsViewportInfo
public:
nsViewportInfo(const mozilla::ScreenIntSize& aDisplaySize,
const mozilla::CSSToScreenScale& aDefaultZoom,
bool aAllowZoom,
bool aAllowDoubleTapZoom) :
bool aAllowZoom) :
mDefaultZoom(aDefaultZoom),
mAutoSize(true),
mAllowZoom(aAllowZoom),
mAllowDoubleTapZoom(aAllowDoubleTapZoom)
mAllowZoom(aAllowZoom)
{
// Don't allow double-tap zooming unless zooming is also allowed
MOZ_ASSERT(mAllowZoom || !mAllowDoubleTapZoom);
mSize = mozilla::ScreenSize(aDisplaySize) / mDefaultZoom;
mozilla::CSSToLayoutDeviceScale pixelRatio(1.0f);
mMinZoom = pixelRatio * kViewportMinScale;
@ -48,19 +43,14 @@ class MOZ_STACK_CLASS nsViewportInfo
const mozilla::CSSToScreenScale& aMaxZoom,
const mozilla::CSSSize& aSize,
bool aAutoSize,
bool aAllowZoom,
bool aAllowDoubleTapZoom) :
bool aAllowZoom) :
mDefaultZoom(aDefaultZoom),
mMinZoom(aMinZoom),
mMaxZoom(aMaxZoom),
mSize(aSize),
mAutoSize(aAutoSize),
mAllowZoom(aAllowZoom),
mAllowDoubleTapZoom(aAllowDoubleTapZoom)
mAllowZoom(aAllowZoom)
{
// Don't allow double-tap zooming unless zooming is also allowed
MOZ_ASSERT(mAllowZoom || !mAllowDoubleTapZoom);
ConstrainViewportValues();
}
@ -73,9 +63,6 @@ class MOZ_STACK_CLASS nsViewportInfo
bool IsAutoSizeEnabled() const { return mAutoSize; }
bool IsZoomAllowed() const { return mAllowZoom; }
bool IsDoubleTapZoomAllowed() const { return mAllowDoubleTapZoom; }
void SetAllowDoubleTapZoom(bool aAllowDoubleTapZoom) { mAllowDoubleTapZoom = aAllowDoubleTapZoom; }
private:
@ -107,11 +94,6 @@ class MOZ_STACK_CLASS nsViewportInfo
// Whether or not the user can zoom in and out on the page. Default is true.
bool mAllowZoom;
// Whether or not the user can double-tap to zoom in. When this is disabled
// we can dispatch click events faster on a single tap because we don't have
// to wait to detect the double-tap
bool mAllowDoubleTapZoom;
};
#endif

View File

@ -10,9 +10,9 @@
<script>
'use strict';
[
"async_test", "test", "setup",
"promise_test", "test", "setup",
"assert_true", "assert_equals", "assert_array_equals",
"assert_throws"
"assert_throws", "assert_unreached"
].forEach(func => {
window[func] = opener[func].bind(opener);
});
@ -29,49 +29,43 @@ function done() {
<body>
<div id="log"></div>
<script>
function promiseXHR(aUrl) {
return new Promise(resolve => {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onload = resolve;
xmlhttp.open("get", aUrl, true);
xmlhttp.send();
});
function makeXHR(aUrl) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("get", aUrl, true);
xmlhttp.send();
}
async_test(t => {
performance.clearResourceTimings();
promise_test(t => {
var promise = new Promise(resolve => {
performance.clearResourceTimings();
var observedEntryList;
var observedEntries = [];
var observer = new PerformanceObserver(list => {
list.getEntries().forEach(entry => observedEntries.push(entry));
observedEntryList = list;
var observer = new PerformanceObserver(list => resolve(list));
observer.observe({entryTypes: ['resource']});
t.add_cleanup(() => observer.disconnect());
});
observer.observe({entryTypes: ['resource']});
t.add_cleanup(() => observer.disconnect());
assert_equals(observedEntries.length, 0);
makeXHR("test-data.json");
promiseXHR("test-data.json").then(t.step_func_done(() => {
assert_equals(observedEntries.length, 1);
assert_array_equals(observedEntries,
return promise.then(list => {
assert_equals(list.getEntries().length, 1);
assert_array_equals(list.getEntries(),
performance.getEntriesByType("resource"),
"Observed 'resource' entries should equal to entries obtained by getEntriesByType.");
// getEntries filtering tests
assert_array_equals(observedEntryList.getEntries({name: "http://mochi.test:8888/tests/dom/base/test/test-data.json"}),
assert_array_equals(list.getEntries({name: "http://mochi.test:8888/tests/dom/base/test/test-data.json"}),
performance.getEntriesByName("http://mochi.test:8888/tests/dom/base/test/test-data.json"),
"getEntries with name filter should return correct results.");
assert_array_equals(observedEntryList.getEntries({entryType: "resource"}),
assert_array_equals(list.getEntries({entryType: "resource"}),
performance.getEntriesByType("resource"),
"getEntries with entryType filter should return correct results.");
assert_array_equals(observedEntryList.getEntries({initiatorType: "xmlhttprequest"}),
assert_array_equals(list.getEntries({initiatorType: "xmlhttprequest"}),
performance.getEntriesByType("resource"),
"getEntries with initiatorType filter should return correct results.");
assert_array_equals(observedEntryList.getEntries({initiatorType: "link"}),
assert_array_equals(list.getEntries({initiatorType: "link"}),
[],
"getEntries with non-existent initiatorType filter should return an empty array.");
}));
});
}, "resource-timing test");
done();

View File

@ -35,213 +35,192 @@ test(t => {
}, "obsrve() should throw TypeError exception if 'entryTypes' attribute value is invalid.");
}, "Test that PerformanceObserver.observe throws exception");
test(t => {
performance.clearMarks();
performance.clearMeasures();
function promiseObserve(test, options) {
return new Promise(resolve => {
performance.clearMarks();
performance.clearMeasures();
var observedEntries = [];
var observer = new PerformanceObserver(list => {
list.getEntries().forEach(entry => observedEntries.push(entry));
var observer = new PerformanceObserver(list => resolve(list));
observer.observe(options);
test.add_cleanup(() => observer.disconnect());
});
observer.observe({entryTypes: ['mark', 'measure']});
t.add_cleanup(() => observer.disconnect());
}
assert_equals(observedEntries.length, 0,
"User timing entries should never be observed.");
assert_equals(performance.getEntriesByType("mark").length, 0,
"There should be no 'mark' entries.");
assert_equals(performance.getEntriesByType("measure").length, 0,
"There should be no 'measure' entries.");
promise_test(t => {
var promise = promiseObserve(t, {entryTypes: ['mark', 'measure']});
performance.mark("test-start");
performance.mark("test-end");
performance.measure("test-measure", "test-start", "test-end");
assert_equals(observedEntries.length, 3,
"There should be three observed entries.");
return promise.then(list => {
assert_equals(list.getEntries().length, 3,
"There should be three observed entries.");
var markEntries = observedEntries.filter(entry => {
return entry.entryType == "mark";
});
assert_array_equals(markEntries, performance.getEntriesByType("mark"),
"Observed 'mark' entries should equal to entries obtained by getEntriesByType.");
var markEntries = list.getEntries().filter(entry => {
return entry.entryType == "mark";
});
assert_array_equals(markEntries, performance.getEntriesByType("mark"),
"Observed 'mark' entries should equal to entries obtained by getEntriesByType.");
var measureEntries = observedEntries.filter(entry => {
return entry.entryType == "measure";
var measureEntries = list.getEntries().filter(entry => {
return entry.entryType == "measure";
});
assert_array_equals(measureEntries, performance.getEntriesByType("measure"),
"Observed 'measure' entries should equal to entries obtained by getEntriesByType.");
});
assert_array_equals(measureEntries, performance.getEntriesByType("measure"),
"Observed 'measure' entries should equal to entries obtained by getEntriesByType.");
}, "Test for user-timing with PerformanceObserver");
test(t => {
performance.clearMarks();
performance.clearMeasures();
promise_test(t => {
var promise = new Promise((resolve, reject) => {
performance.clearMarks();
performance.clearMeasures();
var observedEntries = [];
var observer = new PerformanceObserver(list => {
list.getEntries().forEach(entry => observedEntries.push(entry));
var observer = new PerformanceObserver(list => reject(list));
observer.observe({entryTypes: ['mark', 'measure']});
observer.disconnect();
t.step_timeout(resolve, 100);
});
observer.observe({entryTypes: ['mark', 'measure']});
observer.disconnect();
assert_equals(observedEntries.length, 0,
"User timing entries should be never observed.");
performance.mark("test-start");
performance.mark("test-end");
performance.measure("test-measure", "test-start", "test-end");
assert_equals(performance.getEntriesByType("mark").length, 2);
assert_equals(performance.getEntriesByType("measure").length, 1);
return promise.then(() => {
assert_equals(performance.getEntriesByType("mark").length, 2);
assert_equals(performance.getEntriesByType("measure").length, 1);
}, list => {
assert_unreached("Observer callback should never be called.");
});
assert_equals(observedEntries.length, 0,
"User timing entries should be never observed after disconnecting observer.");
}, "Nothing should be notified after disconnecting observer");
test(t => {
performance.clearMarks();
performance.clearMeasures();
var observedEntryList;
var observer = new PerformanceObserver(list => {
observedEntryList = list;
});
observer.observe({entryTypes: ['mark']});
t.add_cleanup(() => observer.disconnect());
promise_test(t => {
var promise = promiseObserve(t, {entryTypes: ['mark']});
performance.mark("test");
assert_array_equals(observedEntryList.getEntries({"entryType": "mark"}),
performance.getEntriesByType("mark"),
"getEntries with entryType filter should return correct results.");
assert_array_equals(observedEntryList.getEntries({"name": "test"}),
performance.getEntriesByName("test"),
"getEntries with name filter should return correct results.");
return promise.then(list => {
assert_array_equals(list.getEntries({"entryType": "mark"}),
performance.getEntriesByType("mark"),
"getEntries with entryType filter should return correct results.");
assert_array_equals(observedEntryList.getEntries({"name": "test",
"entryType": "mark"}),
performance.getEntriesByName("test"),
"getEntries with name and entryType filter should return correct results.");
assert_array_equals(list.getEntries({"name": "test"}),
performance.getEntriesByName("test"),
"getEntries with name filter should return correct results.");
assert_array_equals(observedEntryList.getEntries({"name": "invalid"}),
[],
"getEntries with non-existent name filter should return an empty array.");
assert_array_equals(list.getEntries({"name": "test",
"entryType": "mark"}),
performance.getEntriesByName("test"),
"getEntries with name and entryType filter should return correct results.");
assert_array_equals(observedEntryList.getEntries({"name": "test",
"entryType": "measure"}),
[],
"getEntries with name filter and non-existent entryType should return an empty array.");
assert_array_equals(list.getEntries({"name": "invalid"}),
[],
"getEntries with non-existent name filter should return an empty array.");
assert_array_equals(observedEntryList.getEntries({"name": "invalid",
"entryType": "mark"}),
[],
"getEntries with non-existent name and entryType filter should return an empty array.");
assert_array_equals(list.getEntries({"name": "test",
"entryType": "measure"}),
[],
"getEntries with name filter and non-existent entryType should return an empty array.");
assert_array_equals(observedEntryList.getEntries({initiatorType: "xmlhttprequest"}),
[],
"getEntries with initiatorType filter should return an empty array.");
assert_array_equals(list.getEntries({"name": "invalid",
"entryType": "mark"}),
[],
"getEntries with non-existent name and entryType filter should return an empty array.");
assert_array_equals(list.getEntries({initiatorType: "xmlhttprequest"}),
[],
"getEntries with initiatorType filter should return an empty array.");
});
}, "Test for PerformanceObserverEntryList.getEntries");
test(t => {
performance.clearMarks();
performance.clearMeasures();
var observedEntryList;
var observer = new PerformanceObserver(list => {
observedEntryList = list;
});
observer.observe({entryTypes: ['mark', 'measure']});
t.add_cleanup(() => observer.disconnect());
promise_test(t => {
var promise = promiseObserve(t, {entryTypes: ['mark', 'measure']});
performance.mark("test");
assert_array_equals(observedEntryList.getEntriesByType("mark"),
performance.getEntriesByType("mark"));
performance.measure("test-measure", "test", "test");
assert_array_equals(observedEntryList.getEntriesByType("measure"),
performance.getEntriesByType("measure"));
return promise.then(list => {
assert_array_equals(list.getEntriesByType("mark"),
performance.getEntriesByType("mark"));
assert_array_equals(list.getEntriesByType("measure"),
performance.getEntriesByType("measure"));
});
}, "Test for PerformanceObserverEntryList.getEntriesByType");
test(t => {
performance.clearMarks();
performance.clearMeasures();
var observedEntryList;
var observer = new PerformanceObserver(list => {
observedEntryList = list;
});
observer.observe({entryTypes: ['mark', 'measure']});
t.add_cleanup(() => observer.disconnect());
promise_test(t => {
var promise = promiseObserve(t, {entryTypes: ['mark', 'measure']});
performance.mark("test");
assert_array_equals(observedEntryList.getEntriesByName("test"),
performance.getEntriesByName("test"));
performance.measure("test-measure", "test", "test");
assert_array_equals(observedEntryList.getEntriesByName("test-measure"),
performance.getEntriesByName("test-measure"));
return promise.then(list => {
assert_array_equals(list.getEntriesByName("test"),
performance.getEntriesByName("test"));
assert_array_equals(list.getEntriesByName("test-measure"),
performance.getEntriesByName("test-measure"));
});
}, "Test for PerformanceObserverEntryList.getEntriesByName");
test(t => {
performance.clearMarks();
performance.clearMeasures();
promise_test(t => {
var promise = new Promise(resolve => {
performance.clearMarks();
performance.clearMeasures();
var observedEntries = [];
var observer = new PerformanceObserver(list => {
list.getEntries().forEach(entry => observedEntries.push(entry));
var observer = new PerformanceObserver(list => resolve(list));
observer.observe({entryTypes: ['mark', 'measure']});
observer.observe({entryTypes: ['mark', 'measure']});
t.add_cleanup(() => observer.disconnect());
});
observer.observe({entryTypes: ['mark', 'measure']});
observer.observe({entryTypes: ['mark', 'measure']});
t.add_cleanup(() => observer.disconnect());
performance.mark("test-start");
performance.mark("test-end");
performance.measure("test-measure", "test-start", "test-end");
assert_equals(observedEntries.length, 3,
"Observed user timing entries should have only three entries.");
return promise.then(list => {
assert_equals(list.getEntries().length, 3,
"Observed user timing entries should have only three entries.");
});
}, "Test that invoking observe method twice affects nothing");
test(t => {
performance.clearMarks();
performance.clearMeasures();
promise_test(t => {
var promise = new Promise(resolve => {
performance.clearMarks();
performance.clearMeasures();
var observedEntries = [];
var observer = new PerformanceObserver(list => {
list.getEntries().forEach(entry => observedEntries.push(entry));
var observer = new PerformanceObserver(list => resolve(list));
observer.observe({entryTypes: ['mark', 'measure']});
observer.observe({entryTypes: ['mark']});
t.add_cleanup(() => observer.disconnect());
});
observer.observe({entryTypes: ['mark', 'measure']});
observer.observe({entryTypes: ['mark']});
t.add_cleanup(() => observer.disconnect());
performance.mark("test-start");
performance.mark("test-end");
performance.measure("test-measure", "test-start", "test-end");
assert_equals(observedEntries.length, 2,
"Observed user timing entries should have only two entries.");
return promise.then(list => {
assert_equals(list.getEntries().length, 2,
"Observed user timing entries should have only two entries.");
});
}, "Test that observing filter is replaced by a new filter");
test(t => {
performance.clearMarks();
performance.clearMeasures();
promise_test(t => {
var promise = new Promise(resolve => {
performance.clearMarks();
performance.clearMeasures();
var observedEntries = [];
var observer = new PerformanceObserver(list => {
list.getEntries().forEach(entry => observedEntries.push(entry));
var observer = new PerformanceObserver(list => resolve(list));
observer.observe({entryTypes: ['mark']});
observer.observe({entryTypes: ['measure']});
t.add_cleanup(() => observer.disconnect());
});
observer.observe({entryTypes: ['mark']});
observer.observe({entryTypes: ['measure']});
t.add_cleanup(() => observer.disconnect());
performance.mark("test-start");
performance.mark("test-end");
performance.measure("test-measure", "test-start", "test-end");
assert_equals(observedEntries.length, 1,
"Observed user timing entries should have only 1 entries.");
return promise.then(list => {
assert_equals(list.getEntries().length, 1,
"Observed user timing entries should have only 1 entries.");
});
}, "Test that observing filter is replaced by a new filter");

View File

@ -169,4 +169,3 @@ PEExpectedVariableNameEOF=identifier for variable name
PEExpectedVariableName=Expected identifier for variable name but found '%1$S'.
PEExpectedVariableFallback=Expected variable reference fallback after ','.
PEExpectedVariableCommaOrCloseParen=Expected ',' or ')' after variable name in variable reference but found '%1$S'.
PEMozDocumentRuleNotAllowed=@-moz-document rules may only be used in user style sheets.

View File

@ -367,7 +367,7 @@ public:
: mRecorder(aRecorder)
, mTimeSlice(aTimeSlice)
, mStopIssued(false)
, mCanRetrieveData(false)
, mIsStartEventFired(false)
, mIsRegisterProfiler(false)
, mNeedSessionEndTask(true)
{
@ -494,10 +494,10 @@ private:
if (!encodedBuf[i].IsEmpty()) {
mEncodedBufferCache->AppendBuffer(encodedBuf[i]);
// Fire the start event when encoded data is available.
if (!mCanRetrieveData) {
if (!mIsStartEventFired) {
NS_DispatchToMainThread(
new DispatchStartEventRunnable(this, NS_LITERAL_STRING("start")));
mCanRetrieveData = true;
mIsStartEventFired = true;
}
}
}
@ -510,6 +510,12 @@ private:
pushBlob = true;
}
if (pushBlob || aForceFlush) {
// Fire the start event before the blob.
if (!mIsStartEventFired) {
NS_DispatchToMainThread(
new DispatchStartEventRunnable(this, NS_LITERAL_STRING("start")));
mIsStartEventFired = true;
}
if (NS_FAILED(NS_DispatchToMainThread(new EncoderErrorNotifierRunnable(this)))) {
MOZ_ASSERT(false, "NS_DispatchToMainThread EncoderErrorNotifierRunnable failed");
}
@ -639,6 +645,9 @@ private:
{
MOZ_ASSERT(NS_IsMainThread());
CleanupStreams();
NS_DispatchToMainThread(
new DispatchStartEventRunnable(this, NS_LITERAL_STRING("start")));
if (NS_FAILED(rv)) {
nsCOMPtr<nsIRunnable> runnable =
NS_NewRunnableMethodWithArg<nsresult>(mRecorder,
@ -724,8 +733,8 @@ private:
const int32_t mTimeSlice;
// Indicate this session's stop has been called.
bool mStopIssued;
// Indicate session has encoded data. This can be changed in recording thread.
bool mCanRetrieveData;
// Indicate the session had fire start event. Encoding thread only.
bool mIsStartEventFired;
// The register flag for "Media_Encoder" thread to profiler
bool mIsRegisterProfiler;
// False if the InitEncoder called successfully, ensure the

View File

@ -1321,14 +1321,6 @@ MediaStreamGraphImpl::ProduceDataForStreamsBlockByBlock(uint32_t aStreamIndex,
ps->ProcessInput(t, next, (next == aTo) ? ProcessedMediaStream::ALLOW_FINISH : 0);
}
}
// Remove references to shared AudioChunk buffers from downstream nodes
// first so that upstream nodes can re-use next iteration.
for (uint32_t i = mStreams.Length(); i--; ) {
AudioNodeStream* ns = mStreams[i]->AsAudioNodeStream();
if (ns) {
ns->ReleaseSharedBuffers();
}
}
t = next;
}
NS_ASSERTION(t == aTo, "Something went wrong with rounding to block boundaries");

View File

@ -134,11 +134,8 @@ OmxVideoTrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
layers::Image* img = (!mLastFrame.GetImage() || mLastFrame.GetForceBlack())
? nullptr : mLastFrame.GetImage();
rv = mEncoder->Encode(img, mFrameWidth, mFrameHeight, totalDurationUs,
OMXCodecWrapper::BUFFER_EOS);
OMXCodecWrapper::BUFFER_EOS, &mEosSetInEncoder);
NS_ENSURE_SUCCESS(rv, rv);
// Keep sending EOS signal until OMXVideoEncoder gets it.
mEosSetInEncoder = true;
}
// Dequeue an encoded frame from the output buffers of OMXCodecWrapper.
@ -219,6 +216,7 @@ OmxAudioTrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
PROFILER_LABEL("OmxAACAudioTrackEncoder", "GetEncodedTrack",
js::ProfileEntry::Category::OTHER);
AudioSegment segment;
bool EOS;
// Move all the samples from mRawSegment to segment. We only hold
// the monitor in this block.
{
@ -234,14 +232,15 @@ OmxAudioTrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
}
segment.AppendFrom(&mRawSegment);
EOS = mEndOfStream;
}
nsresult rv;
if (segment.GetDuration() == 0) {
// Notify EOS at least once, even if segment is empty.
if (mEndOfStream && !mEosSetInEncoder) {
mEosSetInEncoder = true;
rv = mEncoder->Encode(segment, OMXCodecWrapper::BUFFER_EOS);
if (EOS && !mEosSetInEncoder) {
rv = mEncoder->Encode(segment, OMXCodecWrapper::BUFFER_EOS,
&mEosSetInEncoder);
NS_ENSURE_SUCCESS(rv, rv);
}
// Nothing to encode but encoder could still have encoded data for earlier
@ -252,8 +251,7 @@ OmxAudioTrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
// OMX encoder has limited input buffers only so we have to feed input and get
// output more than once if there are too many samples pending in segment.
while (segment.GetDuration() > 0) {
rv = mEncoder->Encode(segment,
mEndOfStream ? OMXCodecWrapper::BUFFER_EOS : 0);
rv = mEncoder->Encode(segment, 0);
NS_ENSURE_SUCCESS(rv, rv);
rv = AppendEncodedFrames(aData);

View File

@ -446,6 +446,7 @@ VP8TrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
{
PROFILER_LABEL("VP8TrackEncoder", "GetEncodedTrack",
js::ProfileEntry::Category::OTHER);
bool EOS;
{
// Move all the samples from mRawSegment to mSourceSegment. We only hold
// the monitor in this block.
@ -461,6 +462,7 @@ VP8TrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
return NS_ERROR_FAILURE;
}
mSourceSegment.AppendFrom(&mRawSegment);
EOS = mEndOfStream;
}
VideoSegment::ChunkIterator iter(mSourceSegment);
@ -534,7 +536,7 @@ VP8TrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
VP8LOG("RemoveLeading %lld\n",totalProcessedDuration);
// End of stream, pull the rest frames in encoder.
if (mEndOfStream) {
if (EOS) {
VP8LOG("mEndOfStream is true\n");
mEncodingComplete = true;
if (vpx_codec_encode(mVPXContext, nullptr, mEncodedTimestamp,

View File

@ -382,7 +382,7 @@ ConvertGrallocImageToNV12(GrallocImage* aSource, uint8_t* aDestination)
nsresult
OMXVideoEncoder::Encode(const Image* aImage, int aWidth, int aHeight,
int64_t aTimestamp, int aInputFlags)
int64_t aTimestamp, int aInputFlags, bool* aSendEOS)
{
MOZ_ASSERT(mStarted, "Configure() should be called before Encode().");
@ -456,6 +456,9 @@ OMXVideoEncoder::Encode(const Image* aImage, int aWidth, int aHeight,
// Queue this input buffer.
result = mCodec->queueInputBuffer(index, 0, dstSize, aTimestamp, aInputFlags);
if (aSendEOS && (aInputFlags & BUFFER_EOS) && result == OK) {
*aSendEOS = true;
}
return result == OK ? NS_OK : NS_ERROR_FAILURE;
}
@ -822,7 +825,8 @@ OMXAudioEncoder::~OMXAudioEncoder()
}
nsresult
OMXAudioEncoder::Encode(AudioSegment& aSegment, int aInputFlags)
OMXAudioEncoder::Encode(AudioSegment& aSegment, int aInputFlags,
bool* aSendEOS)
{
#ifndef MOZ_SAMPLE_TYPE_S16
#error MediaCodec accepts only 16-bit PCM data.
@ -877,7 +881,9 @@ OMXAudioEncoder::Encode(AudioSegment& aSegment, int aInputFlags)
}
result = buffer.Enqueue(mTimestamp, flags);
NS_ENSURE_TRUE(result == OK, NS_ERROR_FAILURE);
if (aSendEOS && (aInputFlags & BUFFER_EOS)) {
*aSendEOS = true;
}
return NS_OK;
}

View File

@ -224,8 +224,13 @@ public:
* stream, set aInputFlags to BUFFER_EOS. Since encoder has limited buffers,
* this function might not be able to encode all chunks in one call, however
* it will remove chunks it consumes from aSegment.
* aSendEOS is the output to tell the caller EOS signal sent into MediaCodec
* because the signal might not be sent due to the dequeueInputBuffer timeout.
* And the value of aSendEOS won't be set to any default value, only set to
* true when EOS signal sent into MediaCodec.
*/
nsresult Encode(mozilla::AudioSegment& aSegment, int aInputFlags = 0);
nsresult Encode(mozilla::AudioSegment& aSegment, int aInputFlags = 0,
bool* aSendEOS = nullptr);
~OMXAudioEncoder();
protected:
@ -298,9 +303,14 @@ public:
* semi-planar YUV420 format stored in the buffer of aImage. aTimestamp gives
* the frame timestamp/presentation time (in microseconds). To notify end of
* stream, set aInputFlags to BUFFER_EOS.
* aSendEOS is the output to tell the caller EOS signal sent into MediaCodec
* because the signal might not be sent due to the dequeueInputBuffer timeout.
* And the value of aSendEOS won't be set to any default value, only set to
* true when EOS signal sent into MediaCodec.
*/
nsresult Encode(const mozilla::layers::Image* aImage, int aWidth, int aHeight,
int64_t aTimestamp, int aInputFlags = 0);
int64_t aTimestamp, int aInputFlags = 0,
bool* aSendEOS = nullptr);
#if ANDROID_VERSION >= 18
/** Set encoding bitrate (in kbps). */

View File

@ -678,7 +678,6 @@ tags=msg
tags=msg
[test_mediarecorder_record_gum_video_timeslice.html]
tags=msg
skip-if = buildapp == 'b2g' || toolkit == 'android' # mimetype check, bug 969289
[test_mediarecorder_record_immediate_stop.html]
tags=msg capturestream
[test_mediarecorder_record_no_timeslice.html]

View File

@ -40,12 +40,10 @@ function startTest() {
is(evt.type, 'dataavailable',
'Event type should dataavailable');
ok(evt.data.size >= 0,
'Blob data size received is greater than or equal to zero');
is(evt.data.type, 'video/webm',
'Blob data received should have type = ' + 'video/webm');
is(mediaRecorder.mimeType, 'video/webm',
'Mime type in ondataavailable = ' + mediaRecorder.mimeType);
'Blob data size ' + evt.data.size + ' received is greater than or equal to zero');
is(mediaRecorder.mimeType, evt.data.type,
'Mime type in MediaRecorder and ondataavailable : '
+ mediaRecorder.mimeType + ' == ' + evt.data.type);
// We'll stop recording upon the 1st blob being received
if (dataAvailableCount === 1) {

View File

@ -957,8 +957,11 @@ AudioContext::UpdateNodeCount(int32_t aDelta)
bool firstNode = mNodeCount == 0;
mNodeCount += aDelta;
MOZ_ASSERT(mNodeCount >= 0);
// mDestinationNode may be null when we're destroying nodes unlinked by CC
if (!firstNode && mDestination) {
// mDestinationNode may be null when we're destroying nodes unlinked by CC.
// Skipping unnecessary calls after shutdown avoids RunInStableState events
// getting stuck in CycleCollectedJSRuntime during final cycle collection
// (bug 1200514).
if (!firstNode && mDestination && !mIsShutDown) {
mDestination->SetIsOnlyNodeForContext(mNodeCount == 1);
}
}

View File

@ -538,6 +538,12 @@ AudioNodeStream::ProcessInput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags)
mEngine->ProcessBlocksOnPorts(this, mInputChunks, mLastChunks, &finished);
}
}
for (auto& chunk : mInputChunks) {
// If the buffer is shared then it won't be reused, so release the
// reference now. Keep the channel data array to save a free/alloc
// pair.
chunk.ReleaseBufferIfShared();
}
for (uint16_t i = 0; i < outputCount; ++i) {
NS_ASSERTION(mLastChunks[i].GetDuration() == WEBAUDIO_BLOCK_SIZE,
"Invalid WebAudio chunk size");
@ -613,22 +619,6 @@ AudioNodeStream::AdvanceOutputSegment()
}
}
void
AudioNodeStream::ReleaseSharedBuffers()
{
// A shared buffer can't be reused, so release the reference now. Keep
// the channel data arrays to save unnecessary free/alloc.
// Release shared output buffers first, as they may be shared with input
// buffers which can be re-used if there are no other references.
for (auto& chunk : mLastChunks) {
chunk.ReleaseBufferIfShared();
}
for (auto& chunk : mInputChunks) {
chunk.ReleaseBufferIfShared();
}
}
StreamTime
AudioNodeStream::GetCurrentPosition()
{

View File

@ -117,14 +117,6 @@ public:
* the output. This is used only for DelayNodeEngine in a feedback loop.
*/
void ProduceOutputBeforeInput(GraphTime aFrom);
/**
* Remove references to shared AudioChunk buffers. Called on downstream
* nodes first after an iteration has called ProcessInput() on the entire
* graph, so that upstream nodes can re-use their buffers on the next
* iteration.
*/
void ReleaseSharedBuffers();
StreamTime GetCurrentPosition();
bool IsAudioParamStream() const
{
@ -192,7 +184,7 @@ protected:
// The engine that will generate output for this node.
nsAutoPtr<AudioNodeEngine> mEngine;
// The mixed input blocks are kept from iteration to iteration to avoid
// reallocating channel data arrays and any buffers for mixing.
// reallocating channel data arrays.
OutputChunks mInputChunks;
// The last block produced by this node.
OutputChunks mLastChunks;

View File

@ -114,9 +114,6 @@ public:
// ProduceBlockBeforeInput() when in a cycle.
if (!mHaveProducedBeforeInput) {
UpdateOutputBlock(aOutput, 0.0);
// Not in cycle, so no need for additional buffer reference.
// See ProduceBlockBeforeInput().
mLastOutput.SetNull(0);
}
mHaveProducedBeforeInput = false;
mBuffer.NextBlock();
@ -159,13 +156,7 @@ public:
if (mLeftOverData <= 0) {
aOutput->SetNull(WEBAUDIO_BLOCK_SIZE);
} else {
// AudioNodeStream::ReleaseSharedBuffers() is called on delay nodes in
// cycles first and so may release the buffer reference in aOutput
// because downstream nodes may still be sharing when called. Therefore
// keep a separate reference to the output buffer for re-use next
// iteration.
UpdateOutputBlock(&mLastOutput, WEBAUDIO_BLOCK_SIZE);
*aOutput = mLastOutput;
UpdateOutputBlock(aOutput, WEBAUDIO_BLOCK_SIZE);
}
mHaveProducedBeforeInput = true;
}
@ -186,7 +177,6 @@ public:
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
}
AudioChunk mLastOutput; // Used only when in a cycle.
AudioNodeStream* mSource;
AudioNodeStream* mDestination;
AudioParamTimeline mDelay;

View File

@ -148,9 +148,7 @@ SVGDocument::EnsureNonSVGUserAgentStyleSheetsLoaded()
NS_NewURI(getter_AddRefs(uri), spec);
if (uri) {
nsRefPtr<CSSStyleSheet> cssSheet;
cssLoader->LoadSheetSync(uri,
mozilla::css::eAgentSheetFeatures,
true, getter_AddRefs(cssSheet));
cssLoader->LoadSheetSync(uri, true, true, getter_AddRefs(cssSheet));
if (cssSheet) {
EnsureOnDemandBuiltInUASheet(cssSheet);
}

View File

@ -0,0 +1,8 @@
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<textarea id="textarea" lang="en"></textarea>
</body>
</html>

View File

@ -5,3 +5,4 @@ skip-if = buildapp == 'b2g' || os == 'android'
[test_bug338427.html]
[test_bug434998.xul]
[test_bug678842.html]
[test_bug717433.html]

View File

@ -0,0 +1,2 @@
# Affix file for British English dictionary
# Fake file, nothing here.

View File

@ -0,0 +1,4 @@
3
Mary
Paul
Peter

View File

@ -1,6 +1,10 @@
[DEFAULT]
skip-if = buildapp == 'b2g' || buildapp == 'mulet'
support-files = bug678842_subframe.html
support-files =
bug678842_subframe.html
bug717433_subframe.html
en-GB/en_GB.dic
en-GB/en_GB.aff
[test_bug348497.html]
[test_bug384147.html]

View File

@ -0,0 +1,98 @@
<!DOCTYPE html>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=717433
-->
<head>
<title>Test for Bug 717433</title>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
</head>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717433">Mozilla Bug 717433</a>
<p id="display"></p>
<iframe id="content"></iframe>
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for Bug 717433 **/
SimpleTest.waitForExplicitFinish();
var content = document.getElementById('content');
// Load a subframe containing an editor with language "en". At first
// load, it will set the dictionary to en-GB or en-US. We set the other one.
// At second load, it will return the current dictionary. We can check that the
// dictionary is correctly remembered between loads.
var firstLoad = true;
var expected = "";
var en_GB;
var hunspell;
var loadListener = function(evt) {
Components.utils.import("resource://gre/modules/AsyncSpellCheckTestHelper.jsm");
if (firstLoad) {
var dir = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties)
.get("CurWorkD", Components.interfaces.nsIFile);
dir.append("tests");
dir.append("editor");
dir.append("composer");
dir.append("test");
hunspell = Components.classes["@mozilla.org/spellchecker/engine;1"]
.getService(Components.interfaces.mozISpellCheckingEngine);
// Install en-GB dictionary.
en_GB = dir.clone();
en_GB.append("en-GB");
is(en_GB.exists(), true, "true expected (en-GB directory should exist)");
hunspell.addDirectory(en_GB);
}
var doc = evt.target.contentDocument;
var elem = doc.getElementById('textarea');
var editor = elem.QueryInterface(Components.interfaces.nsIDOMNSEditableElement).editor;
editor.setSpellcheckUserOverride(true);
var inlineSpellChecker = editor.getInlineSpellChecker(true);
onSpellCheck(elem, function () {
var spellchecker = inlineSpellChecker.spellChecker;
try {
var currentDictonary = spellchecker.GetCurrentDictionary();
} catch(e) {}
if (firstLoad) {
firstLoad = false;
// First time around, we get a random dictionary based on the language "en".
if (currentDictonary == "en-GB") {
spellchecker.SetCurrentDictionary("en-US");
expected = "en-US";
} else if (currentDictonary == "en-US") {
spellchecker.SetCurrentDictionary("en-GB");
expected = "en-GB";
} else {
is(true, false, "Neither en-US nor en-GB are current");
}
content.src = 'http://mochi.test:8888/tests/editor/composer/test/bug717433_subframe.html?firstload=false';
} else {
is(currentDictonary, expected, expected + " expected");
content.removeEventListener('load', loadListener, false);
// Remove the fake en-GB dictionary again, since it's otherwise picked up by later tests.
hunspell.removeDirectory(en_GB);
SimpleTest.finish();
}
});
}
content.addEventListener('load', loadListener, false);
content.src = 'http://mochi.test:8888/tests/editor/composer/test/bug717433_subframe.html?firstload=true';
</script>
</pre>
</body>
</html>

View File

@ -2840,8 +2840,7 @@ nsHTMLEditor::AddOverrideStyleSheet(const nsAString& aURL)
nsRefPtr<CSSStyleSheet> sheet;
// Editor override style sheets may want to style Gecko anonymous boxes
rv = ps->GetDocument()->CSSLoader()->
LoadSheetSync(uaURI, mozilla::css::eAgentSheetFeatures, true,
getter_AddRefs(sheet));
LoadSheetSync(uaURI, true, true, getter_AddRefs(sheet));
// Synchronous loads should ALWAYS return completed
NS_ENSURE_TRUE(sheet, NS_ERROR_NULL_POINTER);

View File

@ -1,10 +1,10 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=520189
https://bugzilla.mozilla.org/show_bug.cgi?id=520182
-->
<head>
<title>Test for Bug 520189</title>
<title>Test for Bug 520182</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
@ -79,7 +79,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=520189
<pre id="test">
<script type="application/javascript">
/** Test for Bug 520189 **/
/** Test for Bug 520182 **/
const dataPayload = "foo<iframe src=\"data:text/html,bar\"></iframe>baz";
const jsPayload = "foo<iframe src=\"javascript:void('bar');\"></iframe>baz";
@ -421,21 +421,13 @@ var tests = [
isIFrame: true,
payload: invalidStyle8Payload,
rootElement() { return document.getElementById("ss").contentDocument.documentElement; },
// The sanitizer currently doesn't discard unrecognized rules when
// that would make the sheet completely empty (see bug 1177546).
// This is harmless, since @-moz-document is inoperative in author
// style sheets (see bug 1035091).
checkResult(html) { todo_is(html.indexOf("@-moz-document"), -1, "Should not have retained the @-moz-document rule"); },
checkResult(html) { is(html.indexOf("@-moz-document"), -1, "Should not have retained the @-moz-document rule"); },
},
{
id: "tt",
payload: invalidStyle8Payload,
rootElement() { return document.getElementById("tt"); },
// The sanitizer currently doesn't discard unrecognized rules when
// that would make the sheet completely empty (see bug 1177546).
// This is harmless, since @-moz-document is inoperative in author
// style sheets (see bug 1035091).
checkResult(html) { todo_is(html.indexOf("@-moz-document"), -1, "Should not have retained the @-moz-document rule"); },
checkResult(html) { is(html.indexOf("@-moz-document"), -1, "Should not have retained the @-moz-document rule"); },
},
{
id: "uu",

View File

@ -1234,7 +1234,7 @@ public:
#if defined(USE_SKIA) && defined(MOZ_ENABLE_FREETYPE)
static already_AddRefed<GlyphRenderingOptions>
CreateCairoGlyphRenderingOptions(FontHinting aHinting, bool aAutoHinting);
CreateCairoGlyphRenderingOptions(FontHinting aHinting, bool aAutoHinting, AntialiasMode aAntialiasMode = AntialiasMode::DEFAULT);
#endif
static already_AddRefed<DrawTarget>
CreateDualDrawTarget(DrawTarget *targetA, DrawTarget *targetB);

View File

@ -10,6 +10,7 @@
#include "ScaledFontCairo.h"
#include "skia/include/core/SkBitmapDevice.h"
#include "FilterNodeSoftware.h"
#include "HelpersSkia.h"
#ifdef USE_SKIA_GPU
#include "skia/include/gpu/SkGpuDevice.h"
@ -571,23 +572,17 @@ DrawTargetSkia::FillGlyphs(ScaledFont *aFont,
paint.mPaint.setLCDRenderText(shouldLCDRenderText);
if (aRenderingOptions && aRenderingOptions->GetType() == FontType::CAIRO) {
switch (static_cast<const GlyphRenderingOptionsCairo*>(aRenderingOptions)->GetHinting()) {
case FontHinting::NONE:
paint.mPaint.setHinting(SkPaint::kNo_Hinting);
break;
case FontHinting::LIGHT:
paint.mPaint.setHinting(SkPaint::kSlight_Hinting);
break;
case FontHinting::NORMAL:
paint.mPaint.setHinting(SkPaint::kNormal_Hinting);
break;
case FontHinting::FULL:
paint.mPaint.setHinting(SkPaint::kFull_Hinting);
break;
const GlyphRenderingOptionsCairo* cairoOptions =
static_cast<const GlyphRenderingOptionsCairo*>(aRenderingOptions);
paint.mPaint.setHinting(GfxHintingToSkiaHinting(cairoOptions->GetHinting()));
if (cairoOptions->GetAutoHinting()) {
paint.mPaint.setAutohinted(true);
}
if (static_cast<const GlyphRenderingOptionsCairo*>(aRenderingOptions)->GetAutoHinting()) {
paint.mPaint.setAutohinted(true);
if (cairoOptions->GetAntialiasMode() == AntialiasMode::NONE) {
paint.mPaint.setAntiAlias(false);
}
} else if (aFont->GetType() == FontType::MAC && shouldLCDRenderText) {
// SkFontHost_mac only supports subpixel antialiasing when hinting is turned off.

View File

@ -758,13 +758,14 @@ Factory::PurgeAllCaches()
#ifdef USE_SKIA_FREETYPE
already_AddRefed<GlyphRenderingOptions>
Factory::CreateCairoGlyphRenderingOptions(FontHinting aHinting, bool aAutoHinting)
Factory::CreateCairoGlyphRenderingOptions(FontHinting aHinting, bool aAutoHinting, AntialiasMode aAntialiasMode)
{
RefPtr<GlyphRenderingOptionsCairo> options =
new GlyphRenderingOptionsCairo();
options->SetHinting(aHinting);
options->SetAutoHinting(aAutoHinting);
options->SetAntialiasMode(aAntialiasMode);
return options.forget();
}
#endif

View File

@ -88,10 +88,24 @@ GfxAntialiasToCairoAntialias(AntialiasMode antialias)
return CAIRO_ANTIALIAS_GRAY;
case AntialiasMode::SUBPIXEL:
return CAIRO_ANTIALIAS_SUBPIXEL;
case AntialiasMode::DEFAULT:
default:
return CAIRO_ANTIALIAS_DEFAULT;
}
return CAIRO_ANTIALIAS_DEFAULT;
}
static inline AntialiasMode
CairoAntialiasToGfxAntialias(cairo_antialias_t aAntialias)
{
switch(aAntialias) {
case CAIRO_ANTIALIAS_NONE:
return AntialiasMode::NONE;
case CAIRO_ANTIALIAS_GRAY:
return AntialiasMode::GRAY;
case CAIRO_ANTIALIAS_SUBPIXEL:
return AntialiasMode::SUBPIXEL;
default:
return AntialiasMode::DEFAULT;
}
}
static inline cairo_filter_t
@ -232,6 +246,23 @@ CairoFormatToGfxFormat(cairo_format_t format)
}
}
static inline FontHinting
CairoHintingToGfxHinting(cairo_hint_style_t aHintStyle)
{
switch (aHintStyle) {
case CAIRO_HINT_STYLE_NONE:
return FontHinting::NONE;
case CAIRO_HINT_STYLE_SLIGHT:
return FontHinting::LIGHT;
case CAIRO_HINT_STYLE_MEDIUM:
return FontHinting::NORMAL;
case CAIRO_HINT_STYLE_FULL:
return FontHinting::FULL;
default:
return FontHinting::NORMAL;
}
}
SurfaceFormat GfxFormatForCairoSurface(cairo_surface_t* surface);
static inline void

View File

@ -296,6 +296,22 @@ ExtendModeToTileMode(ExtendMode aMode)
return SkShader::kClamp_TileMode;
}
static inline SkPaint::Hinting
GfxHintingToSkiaHinting(FontHinting aHinting)
{
switch (aHinting) {
case FontHinting::NONE:
return SkPaint::kNo_Hinting;
case FontHinting::LIGHT:
return SkPaint::kSlight_Hinting;
case FontHinting::NORMAL:
return SkPaint::kNormal_Hinting;
case FontHinting::FULL:
return SkPaint::kFull_Hinting;
}
return SkPaint::kNormal_Hinting;
}
} // namespace gfx
} // namespace mozilla

View File

@ -37,6 +37,7 @@ public:
GlyphRenderingOptionsCairo()
: mHinting(FontHinting::NORMAL)
, mAutoHinting(false)
, mAntialiasMode(AntialiasMode::DEFAULT)
{
}
@ -44,10 +45,13 @@ public:
void SetAutoHinting(bool aAutoHinting) { mAutoHinting = aAutoHinting; }
FontHinting GetHinting() const { return mHinting; }
bool GetAutoHinting() const { return mAutoHinting; }
void SetAntialiasMode(AntialiasMode aAntialiasMode) { mAntialiasMode = aAntialiasMode; }
virtual AntialiasMode GetAntialiasMode() const { return mAntialiasMode; }
virtual FontType GetType() const { return FontType::CAIRO; }
private:
FontHinting mHinting;
bool mAutoHinting;
AntialiasMode mAntialiasMode;
};
} // namespace gfx

View File

@ -307,8 +307,6 @@ CompositorChild::RecvUpdatePluginConfigurations(const nsIntPoint& aContentOffset
// Handle invalidation, this can be costly, avoid if it is not needed.
if (isVisible) {
// invalidate region (widget origin)
gfx::IntRect bounds = aPlugins[pluginsIdx].bounds();
gfx::IntRect rect(0, 0, bounds.width, bounds.height);
#if defined(XP_WIN)
// Work around for flash's crummy sandbox. See bug 762948. This call
// digs down into the window hirearchy, invalidating regions on
@ -330,16 +328,16 @@ CompositorChild::RecvUpdatePluginConfigurations(const nsIntPoint& aContentOffset
}
bool
CompositorChild::RecvUpdatePluginVisibility(const uintptr_t& aOwnerWidget,
nsTArray<uintptr_t>&& aVisibleIdList)
CompositorChild::RecvHideAllPlugins(const uintptr_t& aParentWidget)
{
#if !defined(XP_WIN) && !defined(MOZ_WIDGET_GTK)
NS_NOTREACHED("CompositorChild::RecvUpdatePluginVisibility calls "
NS_NOTREACHED("CompositorChild::RecvHideAllPlugins calls "
"unexpected on this platform.");
return false;
#else
MOZ_ASSERT(NS_IsMainThread());
nsIWidget::UpdateRegisteredPluginWindowVisibility(aOwnerWidget, aVisibleIdList);
nsTArray<uintptr_t> list;
nsIWidget::UpdateRegisteredPluginWindowVisibility(aParentWidget, list);
return true;
#endif // !defined(XP_WIN) && !defined(MOZ_WIDGET_GTK)
}

View File

@ -90,8 +90,7 @@ public:
nsTArray<PluginWindowData>&& aPlugins) override;
virtual bool
RecvUpdatePluginVisibility(const uintptr_t& aOwnerWidget,
nsTArray<uintptr_t>&& aWindowList) override;
RecvHideAllPlugins(const uintptr_t& aParentWidget) override;
/**
* Request that the parent tell us when graphics are ready on GPU.

View File

@ -1013,6 +1013,52 @@ CompositorParent::SetShadowProperties(Layer* aLayer)
}
}
// handles firing of before and after composite events through
// an raii type helper class.
class AutoFireCompositorEvents {
public:
explicit AutoFireCompositorEvents(CompositorParent* aTarget, bool aEnabled) :
mCompositor(aTarget),
mStart(TimeStamp::Now()),
mEnabled(aEnabled),
mWillSent(false),
mDidSent(false)
{
}
~AutoFireCompositorEvents()
{
WillComposite();
DidComposite();
}
void WillComposite() {
if (mEnabled && mCompositor && !mWillSent) {
TimeStamp now = TimeStamp::Now();
mCompositor->CompositeEvent(WILL_COMPOSITE, mStart, now);
}
mWillSent = true;
}
void DidComposite() {
if (mEnabled && mCompositor && !mDidSent) {
TimeStamp now = TimeStamp::Now();
mCompositor->CompositeEvent(DID_COMPOSITE, mStart, now);
}
mDidSent = true;
}
void Cancel() {
mEnabled = false;
}
CompositorParent* mCompositor;
TimeStamp mStart;
bool mEnabled;
bool mWillSent;
bool mDidSent;
};
void
CompositorParent::CompositeToTarget(DrawTarget* aTarget, const gfx::IntRect* aRect)
{
@ -1033,9 +1079,10 @@ CompositorParent::CompositeToTarget(DrawTarget* aTarget, const gfx::IntRect* aRe
}
#endif
// Takes care of fireing 'will' and 'did' composite events.
AutoFireCompositorEvents afce(this, !aTarget);
if (!CanComposite()) {
TimeStamp end = TimeStamp::Now();
DidComposite(start, end);
return;
}
@ -1054,10 +1101,13 @@ CompositorParent::CompositeToTarget(DrawTarget* aTarget, const gfx::IntRect* aRe
mForceCompositionTask->Cancel();
mForceCompositionTask = nullptr;
} else {
afce.Cancel();
return;
}
}
afce.WillComposite();
mCompositionManager->ComputeRotation();
TimeStamp time = mIsTesting ? mTestTime : mCompositorScheduler->GetLastComposeTime();
@ -1077,11 +1127,6 @@ CompositorParent::CompositeToTarget(DrawTarget* aTarget, const gfx::IntRect* aRe
mLayerManager->SetDebugOverlayWantsNextFrame(false);
mLayerManager->EndTransaction(time);
if (!aTarget) {
TimeStamp end = TimeStamp::Now();
DidComposite(start, end);
}
// We're not really taking advantage of the stored composite-again-time here.
// We might be able to skip the next few composites altogether. However,
// that's a bit complex to implement and we'll get most of the advantage
@ -1722,9 +1767,10 @@ public:
virtual AsyncCompositionManager* GetCompositionManager(LayerTransactionParent* aParent) override;
void DidComposite(uint64_t aId,
TimeStamp& aCompositeStart,
TimeStamp& aCompositeEnd);
void CompositeEvent(CallbackType aType,
uint64_t aId,
TimeStamp& aCompositeStart,
TimeStamp& aCompositeEnd);
private:
// Private destructor, to discourage deletion outside of Release():
@ -1745,18 +1791,21 @@ private:
};
void
CompositorParent::DidComposite(TimeStamp& aCompositeStart,
TimeStamp& aCompositeEnd)
CompositorParent::CompositeEvent(CallbackType aType,
TimeStamp& aCompositeStart,
TimeStamp& aCompositeEnd)
{
if (mPendingTransaction) {
unused << SendDidComposite(0, mPendingTransaction, aCompositeStart, aCompositeEnd);
mPendingTransaction = 0;
}
if (mLayerManager) {
nsTArray<ImageCompositeNotification> notifications;
mLayerManager->ExtractImageCompositeNotifications(&notifications);
if (!notifications.IsEmpty()) {
unused << ImageBridgeParent::NotifyImageComposites(notifications);
if (aType == DID_COMPOSITE) {
if (mPendingTransaction) {
unused << SendDidComposite(0, mPendingTransaction, aCompositeStart, aCompositeEnd);
mPendingTransaction = 0;
}
if (mLayerManager) {
nsTArray<ImageCompositeNotification> notifications;
mLayerManager->ExtractImageCompositeNotifications(&notifications);
if (!notifications.IsEmpty()) {
unused << ImageBridgeParent::NotifyImageComposites(notifications);
}
}
}
@ -1765,8 +1814,8 @@ CompositorParent::DidComposite(TimeStamp& aCompositeStart,
it != sIndirectLayerTrees.end(); it++) {
LayerTreeState* lts = &it->second;
if (lts->mParent == this && lts->mCrossProcessParent) {
static_cast<CrossProcessCompositorParent*>(lts->mCrossProcessParent)->DidComposite(
it->first, aCompositeStart, aCompositeEnd);
static_cast<CrossProcessCompositorParent*>(lts->mCrossProcessParent)->CompositeEvent(
aType, it->first, aCompositeStart, aCompositeEnd);
}
}
}
@ -2002,10 +2051,8 @@ UpdatePluginWindowState(uint64_t aId)
// tree contained visible plugins and the new tree does not. All we need
// to do here is hide the plugins for the old tree, so don't waste time
// calculating clipping.
nsTArray<uintptr_t> aVisibleIdList;
uintptr_t parentWidget = (uintptr_t)lts.mParent->GetWidget();
unused << lts.mParent->SendUpdatePluginVisibility(parentWidget,
aVisibleIdList);
unused << lts.mParent->SendHideAllPlugins(parentWidget);
lts.mUpdatedPluginDataAvailable = false;
return;
}
@ -2030,18 +2077,10 @@ UpdatePluginWindowState(uint64_t aId)
}
}
// Hide all plugins, this remote layer tree is no longer active
// Hide all of our plugins, this remote layer tree is no longer active.
if (shouldHidePlugin) {
// hide all the plugins
for (uint32_t pluginsIdx = 0; pluginsIdx < lts.mPluginData.Length();
pluginsIdx++) {
lts.mPluginData[pluginsIdx].visible() = false;
}
nsIntPoint offset;
nsIntRegion region;
unused << lts.mParent->SendUpdatePluginConfigurations(offset,
region,
lts.mPluginData);
uintptr_t parentWidget = (uintptr_t)lts.mParent->GetWidget();
unused << lts.mParent->SendHideAllPlugins(parentWidget);
// Clear because there's no recovering from this until we receive
// new shadow layer plugin data in ShadowLayersUpdated.
lts.mPluginData.Clear();
@ -2050,19 +2089,32 @@ UpdatePluginWindowState(uint64_t aId)
#endif // #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
void
CrossProcessCompositorParent::DidComposite(uint64_t aId,
TimeStamp& aCompositeStart,
TimeStamp& aCompositeEnd)
CrossProcessCompositorParent::CompositeEvent(CallbackType aType,
uint64_t aId,
TimeStamp& aCompositeStart,
TimeStamp& aCompositeEnd)
{
sIndirectLayerTreesLock->AssertCurrentThreadOwns();
LayerTransactionParent *layerTree = sIndirectLayerTrees[aId].mLayerTree;
if (layerTree && layerTree->GetPendingTransactionId()) {
unused << SendDidComposite(aId, layerTree->GetPendingTransactionId(), aCompositeStart, aCompositeEnd);
layerTree->SetPendingTransactionId(0);
}
switch (aType) {
case WILL_COMPOSITE: {
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
UpdatePluginWindowState(aId);
UpdatePluginWindowState(aId);
#endif
break;
}
case DID_COMPOSITE: {
sIndirectLayerTreesLock->AssertCurrentThreadOwns();
LayerTransactionParent *layerTree = sIndirectLayerTrees[aId].mLayerTree;
if (layerTree && layerTree->GetPendingTransactionId()) {
unused << SendDidComposite(aId, layerTree->GetPendingTransactionId(), aCompositeStart, aCompositeEnd);
layerTree->SetPendingTransactionId(0);
}
break;
}
default:
NS_RUNTIMEABORT("not reached");
}
}
void

View File

@ -55,6 +55,12 @@ class CompositorParent;
class LayerManagerComposite;
class LayerTransactionParent;
// CompositeEvent related events
enum CallbackType {
WILL_COMPOSITE,
DID_COMPOSITE
};
struct ScopedLayerTreeRegistration
{
ScopedLayerTreeRegistration(uint64_t aLayersId,
@ -439,7 +445,14 @@ protected:
*/
bool CanComposite();
void DidComposite(TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd);
// Fires before and after composite events
void CompositeEvent(CallbackType aType, TimeStamp& aCompositeStart,
TimeStamp& aCompositeEnd);
void DidComposite(TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd) {
CompositeEvent(DID_COMPOSITE, aCompositeStart, aCompositeEnd);
}
friend class AutoFireCompositorEvents;
nsRefPtr<LayerManagerComposite> mLayerManager;
nsRefPtr<Compositor> mCompositor;

View File

@ -42,7 +42,6 @@ using mozilla::layers::DiagnosticTypes from "mozilla/layers/CompositorTypes.h";
using struct mozilla::layers::FrameMetrics from "FrameMetrics.h";
using mozilla::layers::FrameMetrics::ViewID from "FrameMetrics.h";
using struct mozilla::layers::FenceHandle from "mozilla/layers/FenceUtils.h";
using std::string from "string";
namespace mozilla {
namespace layers {
@ -232,7 +231,6 @@ struct CommonLayerAttributes {
Animation[] animations;
nsIntRegion invalidRegion;
FrameMetrics[] metrics;
string contentDescription;
nsCString displayListLog;
};

View File

@ -70,11 +70,10 @@ child:
PluginWindowData[] aPlugins);
/**
* Sets the list of currently visible plugin windows based on a
* list of plugin window ids.
* Hides all registered plugin widgets associated with a particular chrome
* widget.
*/
async UpdatePluginVisibility(uintptr_t aOwnerWidget,
uintptr_t[] aVisibleIdList);
async HideAllPlugins(uintptr_t aParentWidget);
/**
* Drop any buffers that might be retained on the child compositor

View File

@ -276,6 +276,10 @@ SkScalerContext_CairoFT::SkScalerContext_CairoFT(SkTypeface* typeface, const SkD
// See http://code.google.com/p/skia/issues/detail?id=222.
loadFlags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
#ifdef FT_LOAD_COLOR
loadFlags |= FT_LOAD_COLOR;
#endif
fLoadGlyphFlags = loadFlags;
}

View File

@ -21,6 +21,8 @@
#include "nsDirectoryServiceDefs.h"
#include "nsAppDirectoryServiceDefs.h"
#include "mozilla/gfx/HelpersCairo.h"
#include <fontconfig/fcfreetype.h>
#ifdef MOZ_WIDGET_GTK
@ -902,27 +904,18 @@ gfxFontconfigFont::GetGlyphRenderingOptions(const TextRunDrawParams* aRunParams)
cairo_font_options_t *options = cairo_font_options_create();
cairo_scaled_font_get_font_options(scaled_font, options);
cairo_hint_style_t hint_style = cairo_font_options_get_hint_style(options);
cairo_antialias_t antialias = cairo_font_options_get_antialias(options);
cairo_font_options_destroy(options);
mozilla::gfx::FontHinting hinting;
mozilla::gfx::FontHinting hinting =
mozilla::gfx::CairoHintingToGfxHinting(hint_style);
switch (hint_style) {
case CAIRO_HINT_STYLE_NONE:
hinting = mozilla::gfx::FontHinting::NONE;
break;
case CAIRO_HINT_STYLE_SLIGHT:
hinting = mozilla::gfx::FontHinting::LIGHT;
break;
case CAIRO_HINT_STYLE_FULL:
hinting = mozilla::gfx::FontHinting::FULL;
break;
default:
hinting = mozilla::gfx::FontHinting::NORMAL;
break;
}
mozilla::gfx::AntialiasMode aaMode =
mozilla::gfx::CairoAntialiasToGfxAntialias(antialias);
// We don't want to force the use of the autohinter over the font's built in hints
return mozilla::gfx::Factory::CreateCairoGlyphRenderingOptions(hinting, false);
// The fontconfig AA mode must be passed along because it may override the hinting style.
return mozilla::gfx::Factory::CreateCairoGlyphRenderingOptions(hinting, false, aaMode);
}
#endif

View File

@ -28,6 +28,7 @@
#include <cairo.h>
#include <cairo-ft.h>
#include "mozilla/gfx/HelpersCairo.h"
#include <fontconfig/fcfreetype.h>
#include <pango/pango.h>
@ -2143,27 +2144,18 @@ gfxFcFont::GetGlyphRenderingOptions(const TextRunDrawParams* aRunParams)
cairo_font_options_t *options = cairo_font_options_create();
cairo_scaled_font_get_font_options(scaled_font, options);
cairo_hint_style_t hint_style = cairo_font_options_get_hint_style(options);
cairo_antialias_t antialias = cairo_font_options_get_antialias(options);
cairo_font_options_destroy(options);
mozilla::gfx::FontHinting hinting;
mozilla::gfx::FontHinting hinting =
mozilla::gfx::CairoHintingToGfxHinting(hint_style);
switch (hint_style) {
case CAIRO_HINT_STYLE_NONE:
hinting = mozilla::gfx::FontHinting::NONE;
break;
case CAIRO_HINT_STYLE_SLIGHT:
hinting = mozilla::gfx::FontHinting::LIGHT;
break;
case CAIRO_HINT_STYLE_FULL:
hinting = mozilla::gfx::FontHinting::FULL;
break;
default:
hinting = mozilla::gfx::FontHinting::NORMAL;
break;
}
mozilla::gfx::AntialiasMode aaMode =
mozilla::gfx::CairoAntialiasToGfxAntialias(antialias);
// We don't want to force the use of the autohinter over the font's built in hints
return mozilla::gfx::Factory::CreateCairoGlyphRenderingOptions(hinting, false);
// The fontconfig AA mode must be passed along because it may override the hinting style.
return mozilla::gfx::Factory::CreateCairoGlyphRenderingOptions(hinting, false, aaMode);
}
#endif

View File

@ -187,6 +187,7 @@ private:
DECL_GFX_PREF(Live, "apz.y_stationary_size_multiplier", APZYStationarySizeMultiplier, float, 3.5f);
DECL_GFX_PREF(Live, "apz.zoom_animation_duration_ms", APZZoomAnimationDuration, int32_t, 250);
DECL_GFX_PREF(Live, "browser.ui.zoom.force-user-scalable", ForceUserScalable, bool, false);
DECL_GFX_PREF(Live, "browser.viewport.desktopWidth", DesktopViewportWidth, int32_t, 980);
DECL_GFX_PREF(Live, "dom.meta-viewport.enabled", MetaViewportEnabled, bool, false);

View File

@ -2189,7 +2189,7 @@ InlineTransparentTypedObject::getOrCreateBuffer(JSContext* cx)
ObjectWeakMap*& table = cx->compartment()->lazyArrayBuffers;
if (!table) {
table = cx->new_<ObjectWeakMap>(cx);
if (!table)
if (!table || !table->init())
return nullptr;
}

View File

@ -807,7 +807,7 @@ JSCompartment::setNewObjectMetadata(JSContext* cx, JSObject* obj)
assertSameCompartment(cx, metadata);
if (!objectMetadataTable) {
objectMetadataTable = cx->new_<ObjectWeakMap>(cx);
if (!objectMetadataTable)
if (!objectMetadataTable || !objectMetadataTable->init())
CrashAtUnhandlableOOM("setNewObjectMetadata");
}
if (!objectMetadataTable->add(cx, obj, metadata))

View File

@ -683,9 +683,12 @@ js::InitBareWeakMapCtor(JSContext* cx, HandleObject obj)
ObjectWeakMap::ObjectWeakMap(JSContext* cx)
: map(cx, nullptr)
{}
bool
ObjectWeakMap::init()
{
if (!map.init())
CrashAtUnhandlableOOM("ObjectWeakMap");
return map.init();
}
ObjectWeakMap::~ObjectWeakMap()
@ -696,6 +699,7 @@ ObjectWeakMap::~ObjectWeakMap()
JSObject*
ObjectWeakMap::lookup(const JSObject* obj)
{
MOZ_ASSERT(map.initialized());
if (ObjectValueMap::Ptr p = map.lookup(const_cast<JSObject*>(obj)))
return &p->value().toObject();
return nullptr;
@ -705,6 +709,7 @@ bool
ObjectWeakMap::add(JSContext* cx, JSObject* obj, JSObject* target)
{
MOZ_ASSERT(obj && target);
MOZ_ASSERT(map.initialized());
MOZ_ASSERT(!map.has(obj));
if (!map.put(obj, ObjectValue(*target))) {
@ -720,18 +725,21 @@ ObjectWeakMap::add(JSContext* cx, JSObject* obj, JSObject* target)
void
ObjectWeakMap::clear()
{
MOZ_ASSERT(map.initialized());
map.clear();
}
void
ObjectWeakMap::trace(JSTracer* trc)
{
MOZ_ASSERT(map.initialized());
map.trace(trc);
}
size_t
ObjectWeakMap::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)
{
MOZ_ASSERT(map.initialized());
return map.sizeOfExcludingThis(mallocSizeOf);
}
@ -739,6 +747,7 @@ ObjectWeakMap::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)
void
ObjectWeakMap::checkAfterMovingGC()
{
MOZ_ASSERT(map.initialized());
for (ObjectValueMap::Range r = map.all(); !r.empty(); r.popFront()) {
CheckGCThingAfterMovingGC(r.front().key().get());
CheckGCThingAfterMovingGC(&r.front().value().toObject());

View File

@ -51,11 +51,11 @@ js::DestroyHelperThreadsState()
gHelperThreadState = nullptr;
}
void
bool
js::EnsureHelperThreadsInitialized()
{
MOZ_ASSERT(gHelperThreadState);
gHelperThreadState->ensureInitialized();
return gHelperThreadState->ensureInitialized();
}
static size_t
@ -453,7 +453,7 @@ static const uint32_t HELPER_STACK_SIZE = kDefaultHelperStackSize;
static const uint32_t HELPER_STACK_QUOTA = kDefaultHelperStackQuota;
#endif
void
bool
GlobalHelperThreadState::ensureInitialized()
{
MOZ_ASSERT(CanUseExtraThreads());
@ -462,11 +462,11 @@ GlobalHelperThreadState::ensureInitialized()
AutoLockHelperThreadState lock;
if (threads)
return;
return true;
threads = js_pod_calloc<HelperThread>(threadCount);
if (!threads)
CrashAtUnhandlableOOM("GlobalHelperThreadState::ensureInitialized");
return false;
for (size_t i = 0; i < threadCount; i++) {
HelperThread& helper = threads[i];
@ -474,11 +474,15 @@ GlobalHelperThreadState::ensureInitialized()
helper.thread = PR_CreateThread(PR_USER_THREAD,
HelperThread::ThreadMain, &helper,
PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, HELPER_STACK_SIZE);
if (!helper.thread || !helper.threadData->init())
CrashAtUnhandlableOOM("GlobalHelperThreadState::ensureInitialized");
if (!helper.thread || !helper.threadData->init()) {
finishThreads();
return false;
}
}
resetAsmJSFailureState();
return true;
}
GlobalHelperThreadState::GlobalHelperThreadState()
@ -510,12 +514,7 @@ GlobalHelperThreadState::GlobalHelperThreadState()
void
GlobalHelperThreadState::finish()
{
if (threads) {
MOZ_ASSERT(CanUseExtraThreads());
for (size_t i = 0; i < threadCount; i++)
threads[i].destroy();
js_free(threads);
}
finishThreads();
PR_DestroyCondVar(consumerWakeup);
PR_DestroyCondVar(producerWakeup);
@ -525,6 +524,19 @@ GlobalHelperThreadState::finish()
ionLazyLinkList_.clear();
}
void
GlobalHelperThreadState::finishThreads()
{
if (!threads)
return;
MOZ_ASSERT(CanUseExtraThreads());
for (size_t i = 0; i < threadCount; i++)
threads[i].destroy();
js_free(threads);
threads = nullptr;
}
void
GlobalHelperThreadState::lock()
{

View File

@ -103,8 +103,9 @@ class GlobalHelperThreadState
GlobalHelperThreadState();
void ensureInitialized();
bool ensureInitialized();
void finish();
void finishThreads();
void lock();
void unlock();
@ -351,7 +352,7 @@ void
DestroyHelperThreadsState();
// Initialize helper threads unless already initialized.
void
bool
EnsureHelperThreadsInitialized();
// This allows the JS shell to override GetCPUCount() when passed the

View File

@ -283,10 +283,10 @@ JSRuntime::init(uint32_t maxbytes, uint32_t maxNurseryBytes)
if (!regexpStack.init())
return false;
js::TlsPerThreadData.set(&mainThread);
if (CanUseExtraThreads() && !EnsureHelperThreadsInitialized())
return false;
if (CanUseExtraThreads())
EnsureHelperThreadsInitialized();
js::TlsPerThreadData.set(&mainThread);
if (!gc.init(maxbytes, maxNurseryBytes))
return false;

View File

@ -1921,7 +1921,7 @@ DebugScopes::~DebugScopes()
bool
DebugScopes::init()
{
return liveScopes.init() && missingScopes.init();
return proxiedScopes.init() && missingScopes.init() && liveScopes.init();
}
void

View File

@ -38,6 +38,7 @@ class ObjectWeakMap
public:
explicit ObjectWeakMap(JSContext* cx);
bool init();
~ObjectWeakMap();
JSObject* lookup(const JSObject* obj);

View File

@ -27,6 +27,7 @@ NS_IMPL_ISUPPORTS(ZoomConstraintsClient, nsIDOMEventListener, nsIObserver)
static const nsLiteralString DOM_META_ADDED = NS_LITERAL_STRING("DOMMetaAdded");
static const nsLiteralString DOM_META_CHANGED = NS_LITERAL_STRING("DOMMetaChanged");
static const nsLiteralCString BEFORE_FIRST_PAINT = NS_LITERAL_CSTRING("before-first-paint");
static const nsLiteralCString NS_PREF_CHANGED = NS_LITERAL_CSTRING("nsPref:changed");
using namespace mozilla;
using namespace mozilla::layers;
@ -76,6 +77,8 @@ ZoomConstraintsClient::Destroy()
observerService->RemoveObserver(this, BEFORE_FIRST_PAINT.Data());
}
Preferences::RemoveObserver(this, "browser.ui.zoom.force-user-scalable");
if (mGuid) {
if (nsIWidget* widget = GetWidget(mPresShell)) {
ZCC_LOG("Sending null constraints in %p for { %u, %" PRIu64 " }\n",
@ -111,6 +114,8 @@ ZoomConstraintsClient::Init(nsIPresShell* aPresShell, nsIDocument* aDocument)
if (observerService) {
observerService->AddObserver(this, BEFORE_FIRST_PAINT.Data(), false);
}
Preferences::AddStrongObserver(this, "browser.ui.zoom.force-user-scalable");
}
NS_IMETHODIMP
@ -136,6 +141,13 @@ ZoomConstraintsClient::Observe(nsISupports* aSubject, const char* aTopic, const
if (SameCOMIdentity(aSubject, mDocument) && BEFORE_FIRST_PAINT.EqualsASCII(aTopic)) {
ZCC_LOG("Got a before-first-paint event in %p\n", this);
RefreshZoomConstraints();
} else if (NS_PREF_CHANGED.EqualsASCII(aTopic)) {
ZCC_LOG("Got a pref-change event in %p\n", this);
// We need to run this later because all the pref change listeners need
// to execute before we can be guaranteed that gfxPrefs::ForceUserScalable()
// returns the updated value.
NS_DispatchToMainThread(NS_NewRunnableMethod(
this, &ZoomConstraintsClient::RefreshZoomConstraints));
}
return NS_OK;
}
@ -152,9 +164,14 @@ ComputeZoomConstraintsFromViewportInfo(const nsViewportInfo& aViewportInfo)
{
mozilla::layers::ZoomConstraints constraints;
constraints.mAllowZoom = aViewportInfo.IsZoomAllowed() && gfxPrefs::APZAllowZooming();
constraints.mAllowDoubleTapZoom = aViewportInfo.IsDoubleTapZoomAllowed() && gfxPrefs::APZAllowZooming();
constraints.mMinZoom.scale = aViewportInfo.GetMinZoom().scale;
constraints.mMaxZoom.scale = aViewportInfo.GetMaxZoom().scale;
constraints.mAllowDoubleTapZoom = constraints.mAllowZoom;
if (constraints.mAllowZoom) {
constraints.mMinZoom.scale = aViewportInfo.GetMinZoom().scale;
constraints.mMaxZoom.scale = aViewportInfo.GetMaxZoom().scale;
} else {
constraints.mMinZoom.scale = aViewportInfo.GetDefaultZoom().scale;
constraints.mMaxZoom.scale = aViewportInfo.GetDefaultZoom().scale;
}
return constraints;
}

View File

@ -180,32 +180,17 @@ nsresult
nsStyleSheetService::LoadAndRegisterSheetInternal(nsIURI *aSheetURI,
uint32_t aSheetType)
{
NS_ENSURE_ARG(aSheetType == AGENT_SHEET ||
aSheetType == USER_SHEET ||
aSheetType == AUTHOR_SHEET);
NS_ENSURE_ARG_POINTER(aSheetURI);
css::SheetParsingMode parsingMode;
switch (aSheetType) {
case AGENT_SHEET:
parsingMode = css::eAgentSheetFeatures;
break;
case USER_SHEET:
parsingMode = css::eUserSheetFeatures;
break;
case AUTHOR_SHEET:
parsingMode = css::eAuthorSheetFeatures;
break;
default:
NS_WARNING("invalid sheet type argument");
return NS_ERROR_INVALID_ARG;
}
nsRefPtr<css::Loader> loader = new css::Loader();
nsRefPtr<CSSStyleSheet> sheet;
nsresult rv = loader->LoadSheetSync(aSheetURI, parsingMode, true,
getter_AddRefs(sheet));
// Allow UA sheets, but not user sheets, to use unsafe rules
nsresult rv = loader->LoadSheetSync(aSheetURI, aSheetType == AGENT_SHEET,
true, getter_AddRefs(sheet));
NS_ENSURE_SUCCESS(rv, rv);
if (!mSheets[aSheetType].AppendObject(sheet)) {
@ -234,32 +219,18 @@ NS_IMETHODIMP
nsStyleSheetService::PreloadSheet(nsIURI *aSheetURI, uint32_t aSheetType,
nsIDOMStyleSheet **aSheet)
{
NS_PRECONDITION(aSheet, "Null out param");
NS_ENSURE_ARG(aSheetType == AGENT_SHEET ||
aSheetType == USER_SHEET ||
aSheetType == AUTHOR_SHEET);
NS_ENSURE_ARG_POINTER(aSheetURI);
css::SheetParsingMode parsingMode;
switch (aSheetType) {
case AGENT_SHEET:
parsingMode = css::eAgentSheetFeatures;
break;
case USER_SHEET:
parsingMode = css::eUserSheetFeatures;
break;
case AUTHOR_SHEET:
parsingMode = css::eAuthorSheetFeatures;
break;
default:
NS_WARNING("invalid sheet type argument");
return NS_ERROR_INVALID_ARG;
}
NS_PRECONDITION(aSheet, "Null out param");
nsRefPtr<css::Loader> loader = new css::Loader();
// Allow UA sheets, but not user sheets, to use unsafe rules
nsRefPtr<CSSStyleSheet> sheet;
nsresult rv = loader->LoadSheetSync(aSheetURI, parsingMode, true,
getter_AddRefs(sheet));
nsresult rv = loader->LoadSheetSync(aSheetURI, aSheetType == AGENT_SHEET,
true, getter_AddRefs(sheet));
NS_ENSURE_SUCCESS(rv, rv);
sheet.forget(aSheet);
return NS_OK;

View File

@ -48,6 +48,7 @@
== scoped-style-media.html scoped-style-media-ref.html
== scoped-style-namespace.html scoped-style-namespace-ref.html
== scoped-style-charset.html scoped-style-charset-ref.html
== scoped-style-document.html scoped-style-document-ref.html
HTTP(..) == scoped-style-font-face.html scoped-style-font-face-ref.html
== scoped-style-keyframes.html scoped-style-keyframes-ref.html
== scoped-style-supports.html scoped-style-supports-ref.html

View File

@ -0,0 +1,6 @@
<!DOCTYPE html>
<body>
<p>First</p>
<p style="color: blue">Second</p>
<p>Third</p>
</body>

View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<body>
<p>First</p>
<p>
<style scoped>
@-moz-document regexp("^.*scoped-style-document\\.html$") {
p { color: blue }
}
</style>
Second
</p>
<p>Third</p>
</body>

View File

@ -0,0 +1,21 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>CSS Test: A nested @supports rule with valid syntax and a passing condition must apply rules inside it</title>
<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au" />
<link rel="help" href="http://www.w3.org/TR/css3-conditional/#at-supports" />
<link rel="help" href="http://www.w3.org/TR/css3-conditional/#at-document" />
<meta name="flags" content="" />
<meta name="assert" content="An outer @document rule with an inner @supports rule must apply the rules inside the @supports only if both the @supports and @document conditions pass."/>
<link rel="match" href="support/pass.xht" />
<style type="text/css"><![CDATA[
@-moz-document url-prefix("") {
@supports (color: green) {
html { background-color: green }
}
}
]]></style>
</head>
<body>
</body>
</html>

View File

@ -0,0 +1,20 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>CSS Test: A nested @supports rule with valid syntax and a passing condition must apply rules inside it</title>
<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au" />
<link rel="help" href="http://www.w3.org/TR/css3-conditional/#at-supports" />
<meta name="flags" content="" />
<meta name="assert" content="An inner @document rule with an outer @supports rule must apply the rules inside the @document only if both the @supports and @document conditions pass."/>
<link rel="match" href="support/pass.xht" />
<style type="text/css"><![CDATA[
@supports (color: green) {
@-moz-document url-prefix("") {
html { background-color: green }
}
}
]]></style>
</head>
<body>
</body>
</html>

View File

@ -24,6 +24,8 @@
== css-supports-024.xht support/pass.xht
== css-supports-025.xht support/pass.xht
== css-supports-026.xht support/pass.xht
== css-supports-027.xht support/pass.xht
== css-supports-028.xht support/pass.xht
== css-supports-029.xht support/pass.xht
== css-supports-030.xht support/pass.xht
== css-supports-031.xht support/pass.xht

View File

@ -2309,14 +2309,11 @@ CSSStyleSheet::ParseSheet(const nsAString& aInput)
mInner->mNameSpaceMap = nullptr;
// allow unsafe rules if the style sheet's principal is the system principal
css::SheetParsingMode parsingMode =
nsContentUtils::IsSystemPrincipal(mInner->mPrincipal)
? css::eAgentSheetFeatures
: css::eAuthorSheetFeatures;
bool allowUnsafeRules = nsContentUtils::IsSystemPrincipal(mInner->mPrincipal);
nsCSSParser parser(loader, this);
nsresult rv = parser.ParseSheet(aInput, mInner->mSheetURI, mInner->mBaseURI,
mInner->mPrincipal, 1, parsingMode);
mInner->mPrincipal, 1, allowUnsafeRules);
DidDirty(); // we are always 'dirty' here since we always remove rules first
NS_ENSURE_SUCCESS(rv, rv);

View File

@ -104,12 +104,6 @@ namespace css {
* Data needed to properly load a stylesheet *
*********************************************/
static_assert(eAuthorSheetFeatures == 0 &&
eUserSheetFeatures == 1 &&
eAgentSheetFeatures == 2,
"sheet parsing mode constants won't fit "
"in SheetLoadData::mParsingMode");
class SheetLoadData final : public nsIRunnable,
public nsIUnicharStreamLoaderObserver,
public nsIThreadObserver
@ -143,7 +137,7 @@ public:
nsIURI* aURI,
CSSStyleSheet* aSheet,
bool aSyncLoad,
SheetParsingMode aParsingMode,
bool aAllowUnsafeRules,
bool aUseSystemPrincipal,
const nsCString& aCharset,
nsICSSLoaderObserver* aObserver,
@ -221,12 +215,9 @@ public:
// created.
bool mWasAlternate : 1;
// mParsingMode controls access to nonstandard style constructs that
// are not safe for use on the public Web but necessary in UA sheets
// and/or useful in user sheets. The only values stored in this
// field are 0, 1, and 2; three bits are allocated to avoid issues
// should the enum type be signed.
SheetParsingMode mParsingMode : 3;
// mAllowUnsafeRules is true if we should allow unsafe rules to be parsed
// in the loaded sheet.
bool mAllowUnsafeRules : 1;
// mUseSystemPrincipal is true if the system principal should be used for
// this sheet, no matter what the channel principal is. Only true for sync
@ -342,7 +333,7 @@ SheetLoadData::SheetLoadData(Loader* aLoader,
mIsCancelled(false),
mMustNotify(false),
mWasAlternate(aIsAlternate),
mParsingMode(eAuthorSheetFeatures),
mAllowUnsafeRules(false),
mUseSystemPrincipal(false),
mSheetAlreadyComplete(false),
mOwningElement(aOwningElement),
@ -373,7 +364,7 @@ SheetLoadData::SheetLoadData(Loader* aLoader,
mIsCancelled(false),
mMustNotify(false),
mWasAlternate(false),
mParsingMode(eAuthorSheetFeatures),
mAllowUnsafeRules(false),
mUseSystemPrincipal(false),
mSheetAlreadyComplete(false),
mOwningElement(nullptr),
@ -385,7 +376,7 @@ SheetLoadData::SheetLoadData(Loader* aLoader,
if (mParentData) {
mSyncLoad = mParentData->mSyncLoad;
mIsNonDocumentSheet = mParentData->mIsNonDocumentSheet;
mParsingMode = mParentData->mParsingMode;
mAllowUnsafeRules = mParentData->mAllowUnsafeRules;
mUseSystemPrincipal = mParentData->mUseSystemPrincipal;
++(mParentData->mPendingChildren);
}
@ -398,7 +389,7 @@ SheetLoadData::SheetLoadData(Loader* aLoader,
nsIURI* aURI,
CSSStyleSheet* aSheet,
bool aSyncLoad,
SheetParsingMode aParsingMode,
bool aAllowUnsafeRules,
bool aUseSystemPrincipal,
const nsCString& aCharset,
nsICSSLoaderObserver* aObserver,
@ -416,7 +407,7 @@ SheetLoadData::SheetLoadData(Loader* aLoader,
mIsCancelled(false),
mMustNotify(false),
mWasAlternate(false),
mParsingMode(aParsingMode),
mAllowUnsafeRules(aAllowUnsafeRules),
mUseSystemPrincipal(aUseSystemPrincipal),
mSheetAlreadyComplete(false),
mOwningElement(nullptr),
@ -426,10 +417,6 @@ SheetLoadData::SheetLoadData(Loader* aLoader,
mCharsetHint(aCharset)
{
NS_PRECONDITION(mLoader, "Must have a loader!");
NS_PRECONDITION(aParsingMode == eAuthorSheetFeatures ||
aParsingMode == eUserSheetFeatures ||
aParsingMode == eAgentSheetFeatures,
"Unrecognized sheet parsing mode");
NS_POSTCONDITION(!mUseSystemPrincipal || mSyncLoad,
"Shouldn't use system principal for async loads");
@ -1758,7 +1745,7 @@ Loader::ParseSheet(const nsAString& aInput,
nsresult rv = parser.ParseSheet(aInput, sheetURI, baseURI,
aLoadData->mSheet->Principal(),
aLoadData->mLineNumber,
aLoadData->mParsingMode);
aLoadData->mAllowUnsafeRules);
mParsingDatas.RemoveElementAt(mParsingDatas.Length() - 1);
if (NS_FAILED(rv)) {
@ -2266,13 +2253,12 @@ Loader::LoadChildSheet(CSSStyleSheet* aParentSheet,
}
nsresult
Loader::LoadSheetSync(nsIURI* aURL,
SheetParsingMode aParsingMode,
Loader::LoadSheetSync(nsIURI* aURL, bool aAllowUnsafeRules,
bool aUseSystemPrincipal,
CSSStyleSheet** aSheet)
{
LOG(("css::Loader::LoadSheetSync"));
return InternalLoadNonDocumentSheet(aURL, aParsingMode,
return InternalLoadNonDocumentSheet(aURL, aAllowUnsafeRules,
aUseSystemPrincipal, nullptr,
EmptyCString(), aSheet, nullptr);
}
@ -2286,7 +2272,7 @@ Loader::LoadSheet(nsIURI* aURL,
{
LOG(("css::Loader::LoadSheet(aURL, aObserver, aSheet) api call"));
NS_PRECONDITION(aSheet, "aSheet is null");
return InternalLoadNonDocumentSheet(aURL, eAuthorSheetFeatures, false,
return InternalLoadNonDocumentSheet(aURL, false, false,
aOriginPrincipal, aCharset,
aSheet, aObserver);
}
@ -2301,7 +2287,7 @@ Loader::LoadSheet(nsIURI* aURL,
const nsAString& aIntegrity)
{
LOG(("css::Loader::LoadSheet(aURL, aObserver) api call"));
return InternalLoadNonDocumentSheet(aURL, eAuthorSheetFeatures, false,
return InternalLoadNonDocumentSheet(aURL, false, false,
aOriginPrincipal, aCharset,
nullptr, aObserver, aCORSMode,
aReferrerPolicy, aIntegrity);
@ -2309,7 +2295,7 @@ Loader::LoadSheet(nsIURI* aURL,
nsresult
Loader::InternalLoadNonDocumentSheet(nsIURI* aURL,
SheetParsingMode aParsingMode,
bool aAllowUnsafeRules,
bool aUseSystemPrincipal,
nsIPrincipal* aOriginPrincipal,
const nsCString& aCharset,
@ -2366,7 +2352,7 @@ Loader::InternalLoadNonDocumentSheet(nsIURI* aURL,
}
SheetLoadData* data =
new SheetLoadData(this, aURL, sheet, syncLoad, aParsingMode,
new SheetLoadData(this, aURL, sheet, syncLoad, aAllowUnsafeRules,
aUseSystemPrincipal, aCharset, aObserver,
aOriginPrincipal, mDocument);

View File

@ -142,33 +142,6 @@ enum StyleSheetState {
eSheetComplete
};
/**
* Enum defining the mode in which a sheet is to be parsed. This is
* usually, but not always, the same as the cascade level at which the
* sheet will apply (see nsStyleSet.h). Most of the Loader APIs only
* support loading of author sheets.
*
* Author sheets are the normal case: styles embedded in or linked
* from HTML pages. They are also the most restricted.
*
* User sheets can do anything author sheets can do, and also get
* access to a few CSS extensions that are not yet suitable for
* exposure on the public Web, but are very useful for expressing
* user style overrides, such as @-moz-document rules.
*
* Agent sheets have access to all author- and user-sheet features
* plus more extensions that are necessary for internal use but,
* again, not yet suitable for exposure on the public Web. Some of
* these are outright unsafe to expose; in particular, incorrect
* styling of anonymous box pseudo-elements can violate layout
* invariants.
*/
enum SheetParsingMode {
eAuthorSheetFeatures = 0,
eUserSheetFeatures,
eAgentSheetFeatures
};
class Loader final {
typedef mozilla::net::ReferrerPolicy ReferrerPolicy;
@ -283,8 +256,13 @@ public:
* method can be used to load sheets not associated with a document.
*
* @param aURL the URL of the sheet to load
* @param aParsingMode the mode in which to parse the sheet
* (see comments at enum SheetParsingMode, above).
* @param aEnableUnsafeRules whether unsafe rules are enabled for this
* sheet load
* Unsafe rules are rules that can violate key Gecko invariants if misused.
* In particular, most anonymous box pseudoelements must be very carefully
* styled or we will have severe problems. Therefore unsafe rules should
* never be enabled for stylesheets controlled by untrusted sites; preferably
* unsafe rules should only be enabled for agent sheets.
* @param aUseSystemPrincipal if true, give the resulting sheet the system
* principal no matter where it's being loaded from.
* @param [out] aSheet the loaded, complete sheet.
@ -297,25 +275,22 @@ public:
* whether the data could be parsed as CSS and doesn't indicate anything
* about the status of child sheets of the returned sheet.
*/
nsresult LoadSheetSync(nsIURI* aURL,
SheetParsingMode aParsingMode,
nsresult LoadSheetSync(nsIURI* aURL, bool aEnableUnsafeRules,
bool aUseSystemPrincipal,
CSSStyleSheet** aSheet);
/**
* As above, but defaults aParsingMode to eAuthorSheetFeatures and
* aUseSystemPrincipal to false.
* As above, but aUseSystemPrincipal and aEnableUnsafeRules are assumed false.
*/
nsresult LoadSheetSync(nsIURI* aURL, CSSStyleSheet** aSheet) {
return LoadSheetSync(aURL, eAuthorSheetFeatures, false, aSheet);
return LoadSheetSync(aURL, false, false, aSheet);
}
/**
* Asynchronously load the stylesheet at aURL. If a successful result is
* returned, aObserver is guaranteed to be notified asynchronously once the
* sheet is loaded and marked complete. This method can be used to load
* sheets not associated with a document. This method cannot be used to
* load user or agent sheets.
* sheets not associated with a document.
*
* @param aURL the URL of the sheet to load
* @param aOriginPrincipal the principal to use for security checks. This
@ -471,7 +446,7 @@ private:
ImportRule* aParentRule);
nsresult InternalLoadNonDocumentSheet(nsIURI* aURL,
SheetParsingMode aParsingMode,
bool aAllowUnsafeRules,
bool aUseSystemPrincipal,
nsIPrincipal* aOriginPrincipal,
const nsCString& aCharset,

View File

@ -6,6 +6,7 @@
@import # { }
@namespace # { }
@media # { }
@-moz-document # { }
@font-face # { }
@page # { }
@-non-mozilla # { }

View File

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="data:text/css,@-moz-document domain(example.com) {}';">
<link rel="stylesheet" href="data:text/css,@-moz-document domain(example.com) {}';">
<script>
// Force a unique inner for the second linked sheet
document.styleSheets[1].cssRules[0];
</script>
</head>
</html>

View File

@ -49,7 +49,9 @@ load 478321-1.xhtml
load 512851-1.xhtml
load 539613-1.xhtml
load 588627-1.html
skip load long-url-list-stack-overflow.html # skipped due to being slow (bug 477490)
load 495269-1.html
load 495269-2.html
load 498036-1.html
load 509155-1.html
load 509156-1.html

View File

@ -0,0 +1,23 @@
<!DOCTYPE html>
<html>
<head>
<style id="s"></style>
<script type="text/javascript">
// Duplicates the string 2^n times
function exp(s, n)
{
for (var i = 0; i < n; ++i)
s += s;
return s;
}
var stylesheet = "@-moz-document url(http://www.w3.org/)" + exp(", url-prefix(file:///)", 20) + " { }";
document.getElementById("s").textContent = stylesheet;
</script>
</head>
<body>
<div></div>
</body>
</html>

Some files were not shown because too many files have changed in this diff Show More