Merge latest green fx-team changeset and mozilla-central

This commit is contained in:
Ed Morley 2013-07-09 08:52:05 +01:00
commit dfb24cc390
178 changed files with 3163 additions and 1659 deletions

View File

@ -1,4 +1,4 @@
{ {
"revision": "09cdef3222986569ee93081d7ef0e7f9cc0894f9", "revision": "58d73404571f7619b478116dfec8faced97be13d",
"repo_path": "/integration/gaia-central" "repo_path": "/integration/gaia-central"
} }

View File

@ -5,7 +5,7 @@
#aboutDialogContainer { #aboutDialogContainer {
background-image: url("chrome://branding/content/about-background.png"); background-image: url("chrome://branding/content/about-background.png");
background-repeat: no-repeat; background-repeat: no-repeat;
background-color: #000; background-color: rgb(19,8,36);
color: #fff; color: #fff;
} }

View File

@ -5,7 +5,7 @@
#aboutDialogContainer { #aboutDialogContainer {
background-image: url("chrome://branding/content/about-background.png"); background-image: url("chrome://branding/content/about-background.png");
background-repeat: no-repeat; background-repeat: no-repeat;
background-color: #000; background-color: rgb(10,17,37);
color: #fff; color: #fff;
} }

View File

@ -185,6 +185,32 @@ let Util = {
aElement instanceof Ci.nsIDOMHTMLTextAreaElement); aElement instanceof Ci.nsIDOMHTMLTextAreaElement);
}, },
isEditableContent: function isEditableContent(aElement) {
if (!aElement)
return false;
if (aElement.isContentEditable || aElement.designMode == "on")
return true;
return false;
},
isEditable: function isEditable(aElement) {
if (!aElement)
return false;
if (this.isTextInput(aElement) || this.isEditableContent(aElement))
return true;
// If a body element is editable and the body is the child of an
// iframe or div we can assume this is an advanced HTML editor
if ((aElement instanceof Ci.nsIDOMHTMLIFrameElement ||
aElement instanceof Ci.nsIDOMHTMLDivElement) &&
aElement.contentDocument &&
this.isEditableContent(aElement.contentDocument.body)) {
return true;
}
return aElement.ownerDocument && aElement.ownerDocument.designMode == "on";
},
isMultilineInput: function isMultilineInput(aElement) { isMultilineInput: function isMultilineInput(aElement) {
return (aElement instanceof Ci.nsIDOMHTMLTextAreaElement); return (aElement instanceof Ci.nsIDOMHTMLTextAreaElement);
}, },

View File

@ -4,6 +4,8 @@
- License, v. 2.0. If a copy of the MPL was not distributed with this - License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<!-- When not in use, make sure you disable this or it will run continuously
in the background sucking up cpu. -->
<bindings <bindings
xmlns="http://www.mozilla.org/xbl" xmlns="http://www.mozilla.org/xbl"
xmlns:xbl="http://www.mozilla.org/xbl" xmlns:xbl="http://www.mozilla.org/xbl"
@ -11,7 +13,7 @@
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<binding id="cssthrobberBinding" extends="xul:box"> <binding id="cssthrobberBinding" extends="xul:box">
<content> <content>
<html:div class="progressContainer"> <html:div anonid="container" id="container" class="progressContainer">
<html:div class="progressBall" /> <html:div class="progressBall" />
<html:div class="progressBall" /> <html:div class="progressBall" />
<html:div class="progressBall" /> <html:div class="progressBall" />
@ -19,5 +21,20 @@
<html:div class="progressBall" /> <html:div class="progressBall" />
</html:div> </html:div>
</content> </content>
<implementation>
<field name="container" readonly="true">document.getAnonymousElementByAttribute(this, "anonid", "container");</field>
<property name="enabled">
<setter>
<![CDATA[
if (val) {
this.container.setAttribute("enabled", true);
} else {
this.container.removeAttribute("enabled");
}
return val;
]]>
</setter>
</property>
</implementation>
</binding> </binding>
</bindings> </bindings>

View File

@ -73,9 +73,7 @@ var Browser = {
BrowserTouchHandler.init(); BrowserTouchHandler.init();
PopupBlockerObserver.init(); PopupBlockerObserver.init();
// Warning, total hack ahead. All of the real-browser related scrolling code // Init the touch scrollbox
// lies in a pretend scrollbox here. Let's not land this as-is. Maybe it's time
// to redo all the dragging code.
this.contentScrollbox = Elements.browsers; this.contentScrollbox = Elements.browsers;
this.contentScrollboxScroller = { this.contentScrollboxScroller = {
scrollBy: function(aDx, aDy) { scrollBy: function(aDx, aDy) {
@ -147,10 +145,6 @@ var Browser = {
messageManager.addMessageListener("Browser:TapOnSelection", this); messageManager.addMessageListener("Browser:TapOnSelection", this);
messageManager.addMessageListener("Browser:PluginClickToPlayClicked", this); messageManager.addMessageListener("Browser:PluginClickToPlayClicked", this);
// Let everyone know what kind of mouse input we are
// starting with:
InputSourceHelper.fireUpdate();
Task.spawn(function() { Task.spawn(function() {
// Activation URIs come from protocol activations, secondary tiles, and file activations // Activation URIs come from protocol activations, secondary tiles, and file activations
let activationURI = yield this.getShortcutOrURI(MetroUtils.activationURI); let activationURI = yield this.getShortcutOrURI(MetroUtils.activationURI);
@ -199,6 +193,9 @@ var Browser = {
loadStartupURI(); loadStartupURI();
} }
// Notify about our input type
InputSourceHelper.fireUpdate();
// Broadcast a UIReady message so add-ons know we are finished with startup // Broadcast a UIReady message so add-ons know we are finished with startup
let event = document.createEvent("Events"); let event = document.createEvent("Events");
event.initEvent("UIReady", true, false); event.initEvent("UIReady", true, false);

View File

@ -52,7 +52,7 @@
<broadcasterset id="broadcasterset"> <broadcasterset id="broadcasterset">
<broadcaster id="bcast_contentShowing" disabled="false"/> <broadcaster id="bcast_contentShowing" disabled="false"/>
<broadcaster id="bcast_urlbarState" mode="view"/> <broadcaster id="bcast_urlbarState" mode="view"/>
<broadcaster id="bcast_preciseInput" input="imprecise"/> <broadcaster id="bcast_preciseInput" input="precise"/>
<broadcaster id="bcast_windowState" viewstate=""/> <broadcaster id="bcast_windowState" viewstate=""/>
</broadcasterset> </broadcasterset>
@ -288,6 +288,7 @@
completeselectedindex="true" completeselectedindex="true"
placeholder="&urlbar.emptytext;" placeholder="&urlbar.emptytext;"
flex="1" flex="1"
onpaste="this.focus();"
ontextentered="BrowserUI.handleUrlbarEnter(param);" ontextentered="BrowserUI.handleUrlbarEnter(param);"
onkeydown="BrowserUI.navEditKeyPress();" onkeydown="BrowserUI.navEditKeyPress();"
onblur="BrowserUI._urlbarBlurred();"/> onblur="BrowserUI._urlbarBlurred();"/>
@ -446,10 +447,10 @@
<button label="&sync.setup.remove;" oncommand="Sync.disconnect();" /> <button label="&sync.setup.remove;" oncommand="Sync.disconnect();" />
</hbox> </hbox>
</vbox> </vbox>
<vbox id="sync-disconnectthrobber" collapsed="true"> <vbox id="sync-disconnectpanel">
<hbox> <hbox>
<spacer flex="1" /> <spacer flex="1" />
<cssthrobber id="syncdisconnectthrobber" /> <cssthrobber id="sync-disconnectthrobber"/>
<label>&sync.removethrobber.label;</label> <label>&sync.removethrobber.label;</label>
<spacer flex="1" /> <spacer flex="1" />
</hbox> </hbox>
@ -492,8 +493,7 @@
<deck id="clear-notification" flex="2" selectedIndex="0" align="center"> <deck id="clear-notification" flex="2" selectedIndex="0" align="center">
<spacer id="clear-notification-empty"/> <spacer id="clear-notification-empty"/>
<hbox id="clear-notification-clearing" align="center"> <hbox id="clear-notification-clearing" align="center">
<!-- TODO: we need a more metro-y throbber. See bug 852622 --> <cssthrobber id="clearprivacythrobber"/>
<image src="chrome://browser/skin/images/throbber.png" />
</hbox> </hbox>
<description id="clear-notification-done">&clearPrivateData.done;</description> <description id="clear-notification-done">&clearPrivateData.done;</description>
</deck> </deck>

View File

@ -291,7 +291,7 @@ let Content = {
this.formAssistant.focusSync = false; this.formAssistant.focusSync = false;
// A tap on a form input triggers touch input caret selection // A tap on a form input triggers touch input caret selection
if (Util.isTextInput(element) && if (Util.isEditable(element) &&
aEvent.mozInputSource == Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH) { aEvent.mozInputSource == Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH) {
let { offsetX, offsetY } = Util.translateToTopLevelWindow(element); let { offsetX, offsetY } = Util.translateToTopLevelWindow(element);
sendAsyncMessage("Content:SelectionCaret", { sendAsyncMessage("Content:SelectionCaret", {

View File

@ -224,7 +224,7 @@ var SelectionHandler = {
} }
// This should never happen, but we check to make sure // This should never happen, but we check to make sure
if (!this._targetIsEditable || !Util.isTextInput(this._targetElement)) { if (!this._targetIsEditable) {
this._onFail("Unexpected, coordiates didn't find a text input element."); this._onFail("Unexpected, coordiates didn't find a text input element.");
return; return;
} }
@ -402,7 +402,7 @@ var SelectionHandler = {
this._contentWindow = contentWindow; this._contentWindow = contentWindow;
this._contentOffset = offset; this._contentOffset = offset;
this._domWinUtils = utils; this._domWinUtils = utils;
this._targetIsEditable = this._isTextInput(this._targetElement); this._targetIsEditable = Util.isEditable(this._targetElement);
return true; return true;
}, },
@ -618,12 +618,6 @@ var SelectionHandler = {
}; };
}, },
_isTextInput: function _isTextInput(aElement) {
return ((aElement instanceof Ci.nsIDOMHTMLInputElement &&
aElement.mozIsTextField(false)) ||
aElement instanceof Ci.nsIDOMHTMLTextAreaElement);
},
_getDocShell: function _getDocShell(aWindow) { _getDocShell: function _getDocShell(aWindow) {
if (aWindow == null) if (aWindow == null)
return null; return null;

View File

@ -135,6 +135,9 @@ var ChromeSelectionHandler = {
this._handleSelectionPoint(aMsg.change, pos, true); this._handleSelectionPoint(aMsg.change, pos, true);
this._selectionMoveActive = false; this._selectionMoveActive = false;
// Clear any existing scroll timers
this._clearTimers();
// Update the position of our selection monocles // Update the position of our selection monocles
this._updateSelectionUI("end", true, true); this._updateSelectionUI("end", true, true);
}, },

View File

@ -1157,49 +1157,52 @@ var GestureModule = {
*/ */
var InputSourceHelper = { var InputSourceHelper = {
isPrecise: false, isPrecise: false,
treatMouseAsTouch: false,
init: function ish_init() { init: function ish_init() {
// debug feature, make all input imprecise // debug feature, make all input imprecise
try { window.addEventListener("mousemove", this, true);
this.treatMouseAsTouch = Services.prefs.getBoolPref(kDebugMouseInputPref); window.addEventListener("mousedown", this, true);
} catch (e) {} window.addEventListener("touchstart", this, true);
if (!this.treatMouseAsTouch) { },
window.addEventListener("mousemove", this, true);
window.addEventListener("mousedown", this, true); _precise: function () {
if (!this.isPrecise) {
this.isPrecise = true;
this._fire("MozPrecisePointer");
} }
}, },
_imprecise: function () {
if (this.isPrecise) {
this.isPrecise = false;
this._fire("MozImprecisePointer");
}
},
handleEvent: function ish_handleEvent(aEvent) { handleEvent: function ish_handleEvent(aEvent) {
if (aEvent.type == "touchstart") {
this._imprecise();
return;
}
switch (aEvent.mozInputSource) { switch (aEvent.mozInputSource) {
case Ci.nsIDOMMouseEvent.MOZ_SOURCE_MOUSE: case Ci.nsIDOMMouseEvent.MOZ_SOURCE_MOUSE:
case Ci.nsIDOMMouseEvent.MOZ_SOURCE_PEN: case Ci.nsIDOMMouseEvent.MOZ_SOURCE_PEN:
case Ci.nsIDOMMouseEvent.MOZ_SOURCE_ERASER: case Ci.nsIDOMMouseEvent.MOZ_SOURCE_ERASER:
case Ci.nsIDOMMouseEvent.MOZ_SOURCE_CURSOR: case Ci.nsIDOMMouseEvent.MOZ_SOURCE_CURSOR:
if (!this.isPrecise && !this.treatMouseAsTouch) { this._precise();
this.isPrecise = true;
this._fire("MozPrecisePointer");
}
break; break;
case Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH: case Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH:
if (this.isPrecise) { this._imprecise();
this.isPrecise = false;
this._fire("MozImprecisePointer");
}
break; break;
} }
}, },
fireUpdate: function fireUpdate() { fireUpdate: function fireUpdate() {
if (this.treatMouseAsTouch) { if (this.isPrecise) {
this._fire("MozImprecisePointer"); this._fire("MozPrecisePointer");
} else { } else {
if (this.isPrecise) { this._fire("MozImprecisePointer");
this._fire("MozPrecisePointer");
} else {
this._fire("MozImprecisePointer");
}
} }
}, },

View File

@ -243,7 +243,7 @@ SelectionPrototype.prototype = {
clientPoint.yPos -= halfLineHeight; clientPoint.yPos -= halfLineHeight;
// Modify selection based on monocle movement // Modify selection based on monocle movement
if (this._targetIsEditable) { if (this._targetIsEditable && !Util.isEditableContent(this._targetElement)) {
this._adjustEditableSelection(aMarker, clientPoint, aEndOfSelection); this._adjustEditableSelection(aMarker, clientPoint, aEndOfSelection);
} else { } else {
this._adjustSelectionAtPoint(aMarker, clientPoint, aEndOfSelection); this._adjustSelectionAtPoint(aMarker, clientPoint, aEndOfSelection);
@ -307,8 +307,7 @@ SelectionPrototype.prototype = {
let cp = let cp =
this._contentWindow.document.caretPositionFromPoint(constrainedPoint.xPos, this._contentWindow.document.caretPositionFromPoint(constrainedPoint.xPos,
constrainedPoint.yPos); constrainedPoint.yPos);
if (!cp || (cp.offsetNode != this._targetElement && if (!cp || !this._offsetNodeIsValid(cp.offsetNode)) {
this._contentWindow.document.getBindingParent(cp.offsetNode) != this._targetElement)) {
return; return;
} }
if (aMarker == "start") { if (aMarker == "start") {
@ -319,6 +318,19 @@ SelectionPrototype.prototype = {
} }
}, },
/*
* Make sure caretPositionFromPoint gave us an offset node that equals our
* editable, or in the case of getBindingParent identifies an anonymous
* element in chrome content within our target element. (navbar)
*/
_offsetNodeIsValid: function (aNode) {
if (aNode == this._targetElement ||
this._contentWindow.document.getBindingParent(aNode) == this._targetElement) {
return true;
}
return false;
},
/* /*
* _adjustSelectionAtPoint * _adjustSelectionAtPoint
* *

View File

@ -1,86 +1,88 @@
// -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*- // -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
/* This Source Code Form is subject to the terms of the Mozilla Public /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict"; "use strict";
var SanitizeUI = { var SanitizeUI = {
_sanitizer: null, _sanitizer: null,
_privDataElement: null, _privDataElement: null,
get _privData() { get _privData() {
if (this._privDataElement === null) { if (this._privDataElement === null) {
this._privDataElement = document.getElementById("prefs-privdata"); this._privDataElement = document.getElementById("prefs-privdata");
} }
return this._privDataElement; return this._privDataElement;
}, },
init: function () { init: function () {
this._sanitizer = new Sanitizer(); this._sanitizer = new Sanitizer();
this._privData.addEventListener("CheckboxStateChange", this, true); this._privData.addEventListener("CheckboxStateChange", this, true);
}, },
_clearNotificationTimeout: null, _clearNotificationTimeout: null,
onSanitize: function onSanitize() { onSanitize: function onSanitize() {
let button = document.getElementById("prefs-clear-data"); let button = document.getElementById("prefs-clear-data");
let clearNotificationDeck = document.getElementById("clear-notification"); let clearNotificationDeck = document.getElementById("clear-notification");
let clearNotificationEmpty = document.getElementById("clear-notification-empty"); let clearNotificationEmpty = document.getElementById("clear-notification-empty");
let clearNotificationClearing = document.getElementById("clear-notification-clearing"); let clearNotificationClearing = document.getElementById("clear-notification-clearing");
let clearNotificationDone = document.getElementById("clear-notification-done"); let clearNotificationDone = document.getElementById("clear-notification-done");
let allCheckboxes = SanitizeUI._privData.querySelectorAll("checkbox"); let allCheckboxes = SanitizeUI._privData.querySelectorAll("checkbox");
let allSelected = SanitizeUI._privData.querySelectorAll( let allSelected = SanitizeUI._privData.querySelectorAll(
"#prefs-privdata-history[checked], " + "#prefs-privdata-history[checked], " +
"#prefs-privdata-other[checked] + #prefs-privdata-subitems .privdata-subitem-item[checked]"); "#prefs-privdata-other[checked] + #prefs-privdata-subitems .privdata-subitem-item[checked]");
// disable button and checkboxes temporarily to indicate something is happening // disable button and checkboxes temporarily to indicate something is happening
button.disabled = true; button.disabled = true;
for (let checkbox of allCheckboxes) { for (let checkbox of allCheckboxes) {
checkbox.disabled = true; checkbox.disabled = true;
} }
clearNotificationDeck.selectedPanel = clearNotificationClearing; clearNotificationDeck.selectedPanel = clearNotificationClearing;
document.getElementById("clearprivacythrobber").enabled = true;
// Run asynchronously to let UI update
setTimeout(function() { // Run asynchronously to let UI update
for (let item of allSelected) { setTimeout(function() {
let itemName = item.getAttribute("itemName"); for (let item of allSelected) {
let itemName = item.getAttribute("itemName");
try {
SanitizeUI._sanitizer.clearItem(itemName); try {
} catch(e) { SanitizeUI._sanitizer.clearItem(itemName);
Components.utils.reportError("Error sanitizing " + itemName + ": " + e); } catch(e) {
} Components.utils.reportError("Error sanitizing " + itemName + ": " + e);
} }
}
button.disabled = false;
for (let checkbox of allCheckboxes) { button.disabled = false;
checkbox.disabled = false; for (let checkbox of allCheckboxes) {
} checkbox.disabled = false;
clearNotificationDeck.selectedPanel = clearNotificationDone; }
clearNotificationDeck.selectedPanel = clearNotificationDone;
// Clear notifications after 4 seconds document.getElementById("clearprivacythrobber").enabled = false;
clearTimeout(SanitizeUI._clearNotificationTimeout);
SanitizeUI._clearNotificationTimeout = setTimeout(function() { // Clear notifications after 4 seconds
clearNotificationDeck.selectedPanel = clearNotificationEmpty; clearTimeout(SanitizeUI._clearNotificationTimeout);
}, 4000); SanitizeUI._clearNotificationTimeout = setTimeout(function() {
}, 0); clearNotificationDeck.selectedPanel = clearNotificationEmpty;
}, }, 4000);
}, 0);
/* Disable the clear button when nothing is selected */ },
_onCheckboxChange: function _onCheckboxChange() {
let anySelected = SanitizeUI._privData.querySelector( /* Disable the clear button when nothing is selected */
"#prefs-privdata-history[checked], " + _onCheckboxChange: function _onCheckboxChange() {
"#prefs-privdata-other[checked] + #prefs-privdata-subitems .privdata-subitem-item[checked]"); let anySelected = SanitizeUI._privData.querySelector(
"#prefs-privdata-history[checked], " +
let clearButton = document.getElementById("prefs-clear-data"); "#prefs-privdata-other[checked] + #prefs-privdata-subitems .privdata-subitem-item[checked]");
clearButton.disabled = !anySelected;
}, let clearButton = document.getElementById("prefs-clear-data");
clearButton.disabled = !anySelected;
handleEvent: function (aEvent) { },
switch (aEvent.type) {
case "CheckboxStateChange": handleEvent: function (aEvent) {
this._onCheckboxChange(); switch (aEvent.type) {
break; case "CheckboxStateChange":
} this._onCheckboxChange();
}, break;
}
},
}; };

View File

@ -448,8 +448,8 @@ let Sync = {
}); });
let settingids = ["device", "connect", "connected", "disconnect", "lastsync", "pairdevice", let settingids = ["device", "connect", "connected", "disconnect", "lastsync", "pairdevice",
"errordescription", "accountinfo", "disconnectwarnpanel", "disconnectthrobber", "errordescription", "accountinfo", "disconnectwarnpanel", "disconnectpanel",
"disconnectwarntitle", "description"]; "disconnectthrobber", "disconnectwarntitle", "description"];
settingids.forEach(function(id) { settingids.forEach(function(id) {
elements[id] = document.getElementById("sync-" + id); elements[id] = document.getElementById("sync-" + id);
}); });
@ -471,6 +471,7 @@ let Sync = {
let pairdevice = this._elements.pairdevice; let pairdevice = this._elements.pairdevice;
let accountinfo = this._elements.accountinfo; let accountinfo = this._elements.accountinfo;
let description = this._elements.description; let description = this._elements.description;
let disconnectpanel = this._elements.disconnectpanel;
let disconnectthrobber = this._elements.disconnectthrobber; let disconnectthrobber = this._elements.disconnectthrobber;
// This gets updated when an error occurs // This gets updated when an error occurs
@ -481,10 +482,11 @@ let Sync = {
// If we're in the process of disconnecting we are no longer configured. // If we're in the process of disconnecting we are no longer configured.
if (this._disconnecting) { if (this._disconnecting) {
isConfigured = false; isConfigured = false;
// display the throbber with the appropriate message disconnectpanel.collapsed = false;
disconnectthrobber.collapsed = false; disconnectthrobber.enabled = true;
} else { } else {
disconnectthrobber.collapsed = true; disconnectpanel.collapsed = true;
disconnectthrobber.enabled = false;
} }
connect.collapsed = isConfigured; connect.collapsed = isConfigured;

View File

@ -20,6 +20,7 @@ PERF_TEST_FILES = \
browser_msgmgr_01.js \ browser_msgmgr_01.js \
msgmanagerecho.js \ msgmanagerecho.js \
browser_layers_01.js \ browser_layers_01.js \
browser_firstx.js \
$(NULL) $(NULL)
PERF_RESOURCE_FILES = \ PERF_RESOURCE_FILES = \

View File

@ -0,0 +1,29 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function test() {
let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
Services.scriptloader.loadSubScript(testDir + "/perfhelpers.js", this);
runTests();
}
gTests.push({
desc: "first x metrics",
run: function run() {
PerfTest.declareTest("5F2A456E-2BB2-4073-A751-936F222FEAE0",
"startup perf metrics", "browser", "ux",
"Tracks various metrics reported by nsIAppStartup.getStartupInfo(). Values are in msec.");
let startup = Cc["@mozilla.org/toolkit/app-startup;1"].getService(Ci.nsIAppStartup).getStartupInfo();
PerfTest.declareNumericalResults([
{ value: startup['start'] - startup.process, desc: "start" },
{ value: startup['main'] - startup.process, desc: "main", shareAxis: 0 },
{ value: startup['startupCrashDetectionBegin'] - startup.process, desc: "startupCrashDetectionBegin", shareAxis: 0 },
{ value: startup['firstPaint'] - startup.process, desc: "firstPaint", shareAxis: 0 },
{ value: startup['sessionRestored'] - startup.process, desc: "sessionRestored", shareAxis: 0 },
{ value: startup['createTopLevelWindow'] - startup.process, desc: "createTopLevelWindow", shareAxis: 0 },
{ value: startup['firstLoadURI'] - startup.process, desc: "firstLoadURI", shareAxis: 0 },
]);
}
});

View File

@ -50,6 +50,8 @@ BROWSER_TESTS += \
browser_selection_frame_inputs.js \ browser_selection_frame_inputs.js \
browser_selection_frame_inputs.html \ browser_selection_frame_inputs.html \
browser_selection_urlbar.js \ browser_selection_urlbar.js \
browser_selection_contenteditable.js \
browser_selection_contenteditable.html \
$(NULL) $(NULL)
endif endif

View File

@ -25,6 +25,8 @@ function setUpAndTearDown() {
yield waitForCondition(function () { yield waitForCondition(function () {
return !SelectionHelperUI.isSelectionUIVisible; return !SelectionHelperUI.isSelectionUIVisible;
}, kCommonWaitMs, kCommonPollMs); }, kCommonWaitMs, kCommonPollMs);
InputSourceHelper.isPrecise = false;
InputSourceHelper.fireUpdate();
} }
gTests.push({ gTests.push({
@ -42,7 +44,6 @@ gTests.push({
yield hideContextUI(); yield hideContextUI();
gWindow = Browser.selectedTab.browser.contentWindow; gWindow = Browser.selectedTab.browser.contentWindow;
InputSourceHelper.isPrecise = false;
}, },
}); });

View File

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<head>
<style>
HTML {
height: 100%;
cursor: text;
margin: 50px;
}
BODY {
height: 100%;
border: 0;
margin: 0;
}
div {
border: solid 1px gray;
min-width: 800px;
width: 800px;
max-width: 800px;
}
</style>
<title>Content editable selection test page</title>
</head>
<body style="font-size: 12pt;" contenteditable="true">
<div id="testdiv">Testing sending an email in the outlook.com email client.</div>
</body>
</html>

View File

@ -0,0 +1,76 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
let gWindow = null;
const kMarkerOffsetY = 12;
const kCommonWaitMs = 5000;
const kCommonPollMs = 100;
///////////////////////////////////////////////////
// content editable tests
///////////////////////////////////////////////////
gTests.push({
desc: "normalize browser",
run: function test() {
info(chromeRoot + "browser_selection_contenteditable.html");
yield addTab(chromeRoot + "browser_selection_contenteditable.html");
yield waitForCondition(function () {
return !StartUI.isStartPageVisible;
}, kCommonWaitMs, kCommonPollMs);
yield hideContextUI();
gWindow = Browser.selectedTab.browser.contentWindow;
InputSourceHelper.isPrecise = false;
InputSourceHelper.fireUpdate();
},
});
gTests.push({
desc: "simple test to make sure content editable selection works",
run: function test() {
let div = gWindow.document.getElementById("testdiv");
ok(div, "have the div");
sendElementTap(gWindow, div, 295); // end of 'outlook.com'
yield waitForCondition(function () {
return SelectionHelperUI.isCaretUIVisible;
}, kCommonWaitMs, kCommonPollMs);
let xpos = SelectionHelperUI.caretMark.xPos;
let ypos = SelectionHelperUI.caretMark.yPos + 10;
var touchdrag = new TouchDragAndHold();
yield touchdrag.start(gWindow, xpos, ypos, 100, ypos); // start of 'sending'
touchdrag.end();
yield waitForCondition(function () {
return !SelectionHelperUI.hasActiveDrag;
}, kCommonWaitMs, kCommonPollMs);
yield SelectionHelperUI.pingSelectionHandler();
let str = getTrimmedSelection(gWindow).toString();
is(str, "sending an email in the outlook.com", "selected string matches");
},
tearDown: function () {
emptyClipboard();
if (gWindow)
clearSelection(gWindow);
yield waitForCondition(function () {
return !SelectionHelperUI.isSelectionUIVisible;
}, kCommonWaitMs, kCommonPollMs);
}
});
function test() {
if (!isLandscapeMode()) {
todo(false, "browser_selection_tests need landscape mode to run.");
return;
}
setDevPixelEqualToPx();
runTests();
}

View File

@ -25,6 +25,8 @@ function setUpAndTearDown() {
yield waitForCondition(function () { yield waitForCondition(function () {
return !SelectionHelperUI.isSelectionUIVisible; return !SelectionHelperUI.isSelectionUIVisible;
}, kCommonWaitMs, kCommonPollMs); }, kCommonWaitMs, kCommonPollMs);
InputSourceHelper.isPrecise = false;
InputSourceHelper.fireUpdate();
} }
gTests.push({ gTests.push({
@ -43,8 +45,6 @@ gTests.push({
gWindow = Browser.selectedTab.browser.contentWindow; gWindow = Browser.selectedTab.browser.contentWindow;
gFrame = gWindow.document.getElementById("frame1"); gFrame = gWindow.document.getElementById("frame1");
InputSourceHelper.isPrecise = false;
}, },
}); });
@ -144,7 +144,7 @@ gTests.push({
ok(menuItem, "menu item exists"); ok(menuItem, "menu item exists");
ok(!menuItem.hidden, "menu item visible"); ok(!menuItem.hidden, "menu item visible");
let popupPromise = waitForEvent(document, "popuphidden"); let popupPromise = waitForEvent(document, "popuphidden");
EventUtils.synthesizeMouse(menuItem, 10, 10, {}, gWindow); sendElementTap(gWindow, menuItem);
yield popupPromise; yield popupPromise;
ok(popupPromise && !(popupPromise instanceof Error), "promise error"); ok(popupPromise && !(popupPromise instanceof Error), "promise error");
@ -185,7 +185,6 @@ gTests.push({
gFrame.contentDocument.defaultView.scrollBy(0, 200); gFrame.contentDocument.defaultView.scrollBy(0, 200);
yield scrollPromise; yield scrollPromise;
InputSourceHelper.isPrecise = false;
sendContextMenuClick(114, 130); sendContextMenuClick(114, 130);
yield waitForCondition(function () { yield waitForCondition(function () {

View File

@ -28,6 +28,8 @@ function setUpAndTearDown() {
yield waitForCondition(function () { yield waitForCondition(function () {
return !SelectionHelperUI.isSelectionUIVisible; return !SelectionHelperUI.isSelectionUIVisible;
}, kCommonWaitMs, kCommonPollMs); }, kCommonWaitMs, kCommonPollMs);
InputSourceHelper.isPrecise = false;
InputSourceHelper.fireUpdate();
} }
gTests.push({ gTests.push({
@ -51,8 +53,6 @@ gTests.push({
ok(gWindow != null, "gWindow"); ok(gWindow != null, "gWindow");
ok(gFrame != null, "gFrame"); ok(gFrame != null, "gFrame");
ok(gInput != null, "gInput"); ok(gInput != null, "gInput");
InputSourceHelper.isPrecise = false;
}, },
}); });
@ -75,7 +75,7 @@ gTests.push({
ok(menuItem, "menu item exists"); ok(menuItem, "menu item exists");
ok(!menuItem.hidden, "menu item visible"); ok(!menuItem.hidden, "menu item visible");
let popupPromise = waitForEvent(document, "popuphidden"); let popupPromise = waitForEvent(document, "popuphidden");
EventUtils.synthesizeMouse(menuItem, 10, 10, {}, gWindow); sendElementTap(gWindow, menuItem);
yield popupPromise; yield popupPromise;
yield waitForCondition(function () { yield waitForCondition(function () {
@ -109,7 +109,7 @@ gTests.push({
ok(menuItem, "menu item exists"); ok(menuItem, "menu item exists");
ok(!menuItem.hidden, "menu item visible"); ok(!menuItem.hidden, "menu item visible");
let popupPromise = waitForEvent(document, "popuphidden"); let popupPromise = waitForEvent(document, "popuphidden");
EventUtils.synthesizeMouse(menuItem, 10, 10, {}, gWindow); sendElementTap(gWindow, menuItem);
yield popupPromise; yield popupPromise;
yield waitForCondition(function () { yield waitForCondition(function () {

View File

@ -28,6 +28,8 @@ function setUpAndTearDown() {
yield waitForCondition(function () { yield waitForCondition(function () {
return !SelectionHelperUI.isSelectionUIVisible; return !SelectionHelperUI.isSelectionUIVisible;
}, kCommonWaitMs, kCommonPollMs); }, kCommonWaitMs, kCommonPollMs);
InputSourceHelper.isPrecise = false;
InputSourceHelper.fireUpdate();
} }
gTests.push({ gTests.push({
@ -50,8 +52,6 @@ gTests.push({
ok(gWindow != null, "gWindow"); ok(gWindow != null, "gWindow");
ok(gFrame != null, "gFrame"); ok(gFrame != null, "gFrame");
ok(gTextArea != null, "gTextArea"); ok(gTextArea != null, "gTextArea");
InputSourceHelper.isPrecise = false;
}, },
}); });
@ -74,7 +74,7 @@ gTests.push({
ok(menuItem, "menu item exists"); ok(menuItem, "menu item exists");
ok(!menuItem.hidden, "menu item visible"); ok(!menuItem.hidden, "menu item visible");
let popupPromise = waitForEvent(document, "popuphidden"); let popupPromise = waitForEvent(document, "popuphidden");
EventUtils.synthesizeMouse(menuItem, 10, 10, {}, gWindow); sendElementTap(gWindow, menuItem);
yield popupPromise; yield popupPromise;
yield waitForCondition(function () { yield waitForCondition(function () {
@ -89,7 +89,7 @@ gTests.push({
}); });
gTests.push({ gTests.push({
desc: "drag selection", desc: "drag selection 1",
setUp: setUpAndTearDown, setUp: setUpAndTearDown,
tearDown: setUpAndTearDown, tearDown: setUpAndTearDown,
run: function test() { run: function test() {
@ -107,7 +107,7 @@ gTests.push({
ok(menuItem, "menu item exists"); ok(menuItem, "menu item exists");
ok(!menuItem.hidden, "menu item visible"); ok(!menuItem.hidden, "menu item visible");
let popupPromise = waitForEvent(document, "popuphidden"); let popupPromise = waitForEvent(document, "popuphidden");
EventUtils.synthesizeMouse(menuItem, 10, 10, {}, gWindow); sendElementTap(gWindow, menuItem);
yield popupPromise; yield popupPromise;
yield waitForCondition(function () { yield waitForCondition(function () {
@ -154,7 +154,7 @@ gTests.push({
ok(menuItem, "menu item exists"); ok(menuItem, "menu item exists");
ok(!menuItem.hidden, "menu item visible"); ok(!menuItem.hidden, "menu item visible");
let popupPromise = waitForEvent(document, "popuphidden"); let popupPromise = waitForEvent(document, "popuphidden");
EventUtils.synthesizeMouse(menuItem, 10, 10, {}, gWindow); sendElementTap(gWindow, menuItem);
yield popupPromise; yield popupPromise;
let string = ""; let string = "";
@ -166,7 +166,7 @@ gTests.push({
}); });
gTests.push({ gTests.push({
desc: "drag selection", desc: "drag selection 2",
setUp: setUpAndTearDown, setUp: setUpAndTearDown,
tearDown: setUpAndTearDown, tearDown: setUpAndTearDown,
run: function test() { run: function test() {
@ -188,7 +188,7 @@ gTests.push({
ok(menuItem, "menu item exists"); ok(menuItem, "menu item exists");
ok(!menuItem.hidden, "menu item visible"); ok(!menuItem.hidden, "menu item visible");
let popupPromise = waitForEvent(document, "popuphidden"); let popupPromise = waitForEvent(document, "popuphidden");
EventUtils.synthesizeMouse(menuItem, 10, 10, {}, gWindow); sendElementTap(gWindow, menuItem);
yield popupPromise; yield popupPromise;
yield waitForCondition(function () { yield waitForCondition(function () {
@ -235,7 +235,7 @@ gTests.push({
ok(menuItem, "menu item exists"); ok(menuItem, "menu item exists");
ok(!menuItem.hidden, "menu item visible"); ok(!menuItem.hidden, "menu item visible");
let popupPromise = waitForEvent(document, "popuphidden"); let popupPromise = waitForEvent(document, "popuphidden");
EventUtils.synthesizeMouse(menuItem, 10, 10, {}, gWindow); sendElementTap(gWindow, menuItem);
yield popupPromise; yield popupPromise;
let string = ""; let string = "";

View File

@ -25,6 +25,8 @@ function setUpAndTearDown() {
yield waitForCondition(function () { yield waitForCondition(function () {
return !SelectionHelperUI.isSelectionUIVisible; return !SelectionHelperUI.isSelectionUIVisible;
}, kCommonWaitMs, kCommonPollMs); }, kCommonWaitMs, kCommonPollMs);
InputSourceHelper.isPrecise = false;
InputSourceHelper.fireUpdate();
} }
/* /*
@ -49,7 +51,6 @@ gTests.push({
gWindow = Browser.selectedTab.browser.contentWindow; gWindow = Browser.selectedTab.browser.contentWindow;
gInput = gWindow.document.getElementById("a"); gInput = gWindow.document.getElementById("a");
InputSourceHelper.isPrecise = false;
}, },
}); });
@ -72,7 +73,7 @@ gTests.push({
ok(menuItem, "menu item exists"); ok(menuItem, "menu item exists");
ok(!menuItem.hidden, "menu item visible"); ok(!menuItem.hidden, "menu item visible");
let popupPromise = waitForEvent(document, "popuphidden"); let popupPromise = waitForEvent(document, "popuphidden");
EventUtils.synthesizeMouse(menuItem, 10, 10, {}, gWindow); sendElementTap(gWindow, menuItem);
yield popupPromise; yield popupPromise;
yield waitForCondition(function () { yield waitForCondition(function () {
@ -101,7 +102,7 @@ gTests.push({
ok(menuItem, "menu item exists"); ok(menuItem, "menu item exists");
ok(!menuItem.hidden, "menu item visible"); ok(!menuItem.hidden, "menu item visible");
let popupPromise = waitForEvent(document, "popuphidden"); let popupPromise = waitForEvent(document, "popuphidden");
EventUtils.synthesizeMouse(menuItem, 10, 10, {}, gWindow); sendElementTap(gWindow, menuItem);
yield popupPromise; yield popupPromise;
yield waitForCondition(function () { yield waitForCondition(function () {
@ -147,7 +148,7 @@ gTests.push({
ok(menuItem, "menu item exists"); ok(menuItem, "menu item exists");
ok(!menuItem.hidden, "menu item visible"); ok(!menuItem.hidden, "menu item visible");
let popupPromise = waitForEvent(document, "popuphidden"); let popupPromise = waitForEvent(document, "popuphidden");
EventUtils.synthesizeMouse(menuItem, 10, 10, {}, gWindow); sendElementTap(gWindow, menuItem);
yield popupPromise; yield popupPromise;
yield waitForCondition(function () { yield waitForCondition(function () {

View File

@ -25,6 +25,8 @@ function setUpAndTearDown() {
yield waitForCondition(function () { yield waitForCondition(function () {
return !SelectionHelperUI.isSelectionUIVisible; return !SelectionHelperUI.isSelectionUIVisible;
}, kCommonWaitMs, kCommonPollMs); }, kCommonWaitMs, kCommonPollMs);
InputSourceHelper.isPrecise = false;
InputSourceHelper.fireUpdate();
} }
gTests.push({ gTests.push({
@ -42,7 +44,6 @@ gTests.push({
yield hideContextUI(); yield hideContextUI();
gWindow = Browser.selectedTab.browser.contentWindow; gWindow = Browser.selectedTab.browser.contentWindow;
InputSourceHelper.isPrecise = false;
}, },
}); });
@ -65,7 +66,7 @@ gTests.push({
ok(menuItem, "menu item exists"); ok(menuItem, "menu item exists");
ok(!menuItem.hidden, "menu item visible"); ok(!menuItem.hidden, "menu item visible");
let popupPromise = waitForEvent(document, "popuphidden"); let popupPromise = waitForEvent(document, "popuphidden");
EventUtils.synthesizeMouse(menuItem, 10, 10, {}, gWindow); sendElementTap(gWindow, menuItem);
yield popupPromise; yield popupPromise;
ok(popupPromise && !(popupPromise instanceof Error), "promise error"); ok(popupPromise && !(popupPromise instanceof Error), "promise error");
@ -101,7 +102,7 @@ gTests.push({
ok(menuItem, "menu item exists"); ok(menuItem, "menu item exists");
ok(!menuItem.hidden, "menu item visible"); ok(!menuItem.hidden, "menu item visible");
let popupPromise = waitForEvent(document, "popuphidden"); let popupPromise = waitForEvent(document, "popuphidden");
EventUtils.synthesizeMouse(menuItem, 10, 10, {}, gWindow); sendElementTap(gWindow, menuItem);
yield popupPromise; yield popupPromise;
ok(popupPromise && !(popupPromise instanceof Error), "promise error"); ok(popupPromise && !(popupPromise instanceof Error), "promise error");

View File

@ -19,9 +19,6 @@ const kCommonPollMs = 100;
gTests.push({ gTests.push({
desc: "normalize browser", desc: "normalize browser",
run: function test() { run: function test() {
InputSourceHelper.isPrecise = false;
InputSourceHelper.fireUpdate();
info(chromeRoot + "res/textblock01.html"); info(chromeRoot + "res/textblock01.html");
yield addTab(chromeRoot + "res/textblock01.html"); yield addTab(chromeRoot + "res/textblock01.html");
@ -30,6 +27,9 @@ gTests.push({
}); });
yield hideContextUI(); yield hideContextUI();
InputSourceHelper.isPrecise = false;
InputSourceHelper.fireUpdate();
}, },
}); });

View File

@ -561,26 +561,21 @@ flyoutpanel > settings:first-child {
width: 400px; width: 400px;
} }
#sync-disconnectpanel {
margin-top: 25px;
}
#sync-disconnectwarntitle { #sync-disconnectwarntitle {
font-weight: bold; font-weight: bold;
} }
#sync-disconnectthrobber { #sync-disconnectthrobber .progressContainer {
margin-top: 25px;
}
#disconnectthrobber {
width: 25px;
height: 25px;
}
#syncdisconnectthrobber .progressContainer {
width: 25px; width: 25px;
height: 25px; height: 25px;
margin-right: 10px; margin-right: 10px;
} }
#syncdisconnectthrobber .progressBall { #sync-disconnectthrobber .progressBall {
margin: 2px; margin: 2px;
width: 22px; width: 22px;
height: 22px; height: 22px;
@ -712,6 +707,21 @@ setting[type="radio"] > vbox {
width: 50%; width: 50%;
} }
#clear-notification {
max-height: 25px;
}
#clearprivacythrobber .progressContainer {
width: 25px;
height: 25px;
}
#clearprivacythrobber .progressBall {
margin: 2px;
width: 22px;
height: 22px;
}
#clear-notification-done { #clear-notification-done {
font-weight: bold; font-weight: bold;
} }

View File

@ -5,41 +5,38 @@
%filter substitution %filter substitution
%include defines.inc %include defines.inc
.progressContainer { #container[enabled] .progressBall {
}
.progressBall {
position: absolute; position: absolute;
opacity: 0; opacity: 0;
transform: rotate(225deg); transform: rotate(225deg);
animation: orbit 7.15s infinite; animation: orbit 7.15s infinite;
} }
.progressBall:nth-child(1) { #container[enabled] .progressBall:nth-child(1) {
animation-delay: 1.56s; animation-delay: 1.56s;
} }
.progressBall:nth-child(2) { #container[enabled] .progressBall:nth-child(2) {
animation-delay: 0.31s; animation-delay: 0.31s;
} }
.progressBall:nth-child(3) { #container[enabled] .progressBall:nth-child(3) {
animation-delay: 0.62s; animation-delay: 0.62s;
} }
.progressBall:nth-child(4) { #container[enabled] .progressBall:nth-child(4) {
animation-delay: 0.94s; animation-delay: 0.94s;
} }
.progressBall:nth-child(5) { #container[enabled] .progressBall:nth-child(5) {
animation-delay: 1.25s; animation-delay: 1.25s;
} }
.progressBall:nth-child(1)::after, #container[enabled] .progressBall:nth-child(1)::after,
.progressBall:nth-child(2)::after, #container[enabled] .progressBall:nth-child(2)::after,
.progressBall:nth-child(3)::after, #container[enabled] .progressBall:nth-child(3)::after,
.progressBall:nth-child(4)::after, #container[enabled] .progressBall:nth-child(4)::after,
.progressBall:nth-child(5)::after { #container[enabled] .progressBall:nth-child(5)::after {
content: ""; content: "";
display: block; display: block;
width: 5px; width: 5px;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@ -70,7 +70,6 @@ chrome.jar:
skin/images/errorpage-warning.png (images/errorpage-warning.png) skin/images/errorpage-warning.png (images/errorpage-warning.png)
skin/images/errorpage-larry-white.png (images/errorpage-larry-white.png) skin/images/errorpage-larry-white.png (images/errorpage-larry-white.png)
skin/images/errorpage-larry-black.png (images/errorpage-larry-black.png) skin/images/errorpage-larry-black.png (images/errorpage-larry-black.png)
skin/images/throbber.png (images/throbber.png)
skin/images/alert-downloads-30.png (images/alert-downloads-30.png) skin/images/alert-downloads-30.png (images/alert-downloads-30.png)
skin/images/identity-default-hdpi.png (images/identity-default-hdpi.png) skin/images/identity-default-hdpi.png (images/identity-default-hdpi.png)
skin/images/identity-ssl-hdpi.png (images/identity-ssl-hdpi.png) skin/images/identity-ssl-hdpi.png (images/identity-ssl-hdpi.png)

View File

@ -5,7 +5,7 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */ * You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ChildIterator.h" #include "ChildIterator.h"
#include "nsXBLChildrenElement.h" #include "mozilla/dom/XBLChildrenElement.h"
namespace mozilla { namespace mozilla {
namespace dom { namespace dom {
@ -19,7 +19,7 @@ ExplicitChildIterator::GetNextChild()
MOZ_ASSERT(mChild->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)); MOZ_ASSERT(mChild->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL));
MOZ_ASSERT(!mDefaultChild); MOZ_ASSERT(!mDefaultChild);
nsXBLChildrenElement* point = static_cast<nsXBLChildrenElement*>(mChild); XBLChildrenElement* point = static_cast<XBLChildrenElement*>(mChild);
if (mIndexInInserted < point->mInsertedChildren.Length()) { if (mIndexInInserted < point->mInsertedChildren.Length()) {
return point->mInsertedChildren[mIndexInInserted++]; return point->mInsertedChildren[mIndexInInserted++];
} }
@ -46,7 +46,7 @@ ExplicitChildIterator::GetNextChild()
// Iterate until we find a non-<children>, or a <children> with content. // Iterate until we find a non-<children>, or a <children> with content.
while (mChild && while (mChild &&
mChild->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) { mChild->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) {
nsXBLChildrenElement* point = static_cast<nsXBLChildrenElement*>(mChild); XBLChildrenElement* point = static_cast<XBLChildrenElement*>(mChild);
if (!point->mInsertedChildren.IsEmpty()) { if (!point->mInsertedChildren.IsEmpty()) {
mIndexInInserted = 1; mIndexInInserted = 1;
return point->mInsertedChildren[0]; return point->mInsertedChildren[0];
@ -97,7 +97,7 @@ nsIContent* FlattenedChildIterator::Get()
MOZ_ASSERT(!mIsFirst); MOZ_ASSERT(!mIsFirst);
if (mIndexInInserted) { if (mIndexInInserted) {
nsXBLChildrenElement* point = static_cast<nsXBLChildrenElement*>(mChild); XBLChildrenElement* point = static_cast<XBLChildrenElement*>(mChild);
return point->mInsertedChildren[mIndexInInserted - 1]; return point->mInsertedChildren[mIndexInInserted - 1];
} }
return mDefaultChild ? mDefaultChild : mChild; return mDefaultChild ? mDefaultChild : mChild;
@ -109,7 +109,7 @@ nsIContent* FlattenedChildIterator::GetPreviousChild()
if (mIndexInInserted) { if (mIndexInInserted) {
// NB: mIndexInInserted points one past the last returned child so we need // NB: mIndexInInserted points one past the last returned child so we need
// to look *two* indices back in order to return the previous child. // to look *two* indices back in order to return the previous child.
nsXBLChildrenElement* point = static_cast<nsXBLChildrenElement*>(mChild); XBLChildrenElement* point = static_cast<XBLChildrenElement*>(mChild);
if (--mIndexInInserted) { if (--mIndexInInserted) {
return point->mInsertedChildren[mIndexInInserted - 1]; return point->mInsertedChildren[mIndexInInserted - 1];
} }
@ -133,7 +133,7 @@ nsIContent* FlattenedChildIterator::GetPreviousChild()
// Iterate until we find a non-<children>, or a <children> with content. // Iterate until we find a non-<children>, or a <children> with content.
while (mChild && while (mChild &&
mChild->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) { mChild->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) {
nsXBLChildrenElement* point = static_cast<nsXBLChildrenElement*>(mChild); XBLChildrenElement* point = static_cast<XBLChildrenElement*>(mChild);
if (!point->mInsertedChildren.IsEmpty()) { if (!point->mInsertedChildren.IsEmpty()) {
mIndexInInserted = point->InsertedChildrenLength(); mIndexInInserted = point->InsertedChildrenLength();
return point->mInsertedChildren[mIndexInInserted - 1]; return point->mInsertedChildren[mIndexInInserted - 1];

View File

@ -18,7 +18,7 @@
#include "nsDataHashtable.h" #include "nsDataHashtable.h"
#include "nsString.h" #include "nsString.h"
#include "nsINodeInfo.h" #include "nsINodeInfo.h"
#include "nsXBLChildrenElement.h" #include "mozilla/dom/XBLChildrenElement.h"
using namespace mozilla; using namespace mozilla;
using namespace mozilla::dom; using namespace mozilla::dom;
@ -205,7 +205,7 @@ NS_NewElement(nsIContent** aResult,
return NS_NewSVGElement(aResult, aNodeInfo, aFromParser); return NS_NewSVGElement(aResult, aNodeInfo, aFromParser);
} }
if (ns == kNameSpaceID_XBL && aNodeInfo.get()->Equals(nsGkAtoms::children)) { if (ns == kNameSpaceID_XBL && aNodeInfo.get()->Equals(nsGkAtoms::children)) {
NS_ADDREF(*aResult = new nsXBLChildrenElement(aNodeInfo)); NS_ADDREF(*aResult = new XBLChildrenElement(aNodeInfo));
return NS_OK; return NS_OK;
} }
return NS_NewXMLElement(aResult, aNodeInfo); return NS_NewXMLElement(aResult, aNodeInfo);

View File

@ -96,6 +96,8 @@
#include <limits> #include <limits>
#include "nsIColorPicker.h"
// input type=date // input type=date
#include "js/Date.h" #include "js/Date.h"
@ -377,6 +379,103 @@ HTMLInputElement::nsFilePickerShownCallback::Done(int16_t aResult)
NS_IMPL_ISUPPORTS1(HTMLInputElement::nsFilePickerShownCallback, NS_IMPL_ISUPPORTS1(HTMLInputElement::nsFilePickerShownCallback,
nsIFilePickerShownCallback) nsIFilePickerShownCallback)
class nsColorPickerShownCallback MOZ_FINAL
: public nsIColorPickerShownCallback
{
public:
nsColorPickerShownCallback(HTMLInputElement* aInput,
nsIColorPicker* aColorPicker)
: mInput(aInput)
, mColorPicker(aColorPicker)
, mValueChanged(false)
{}
NS_DECL_ISUPPORTS
NS_IMETHOD Update(const nsAString& aColor) MOZ_OVERRIDE;
NS_IMETHOD Done(const nsAString& aColor) MOZ_OVERRIDE;
private:
/**
* Updates the internals of the object using aColor as the new value.
* If aTrustedUpdate is true, it will consider that aColor is a new value.
* Otherwise, it will check that aColor is different from the current value.
*/
nsresult UpdateInternal(const nsAString& aColor, bool aTrustedUpdate);
nsRefPtr<HTMLInputElement> mInput;
nsCOMPtr<nsIColorPicker> mColorPicker;
bool mValueChanged;
};
nsresult
nsColorPickerShownCallback::UpdateInternal(const nsAString& aColor,
bool aTrustedUpdate)
{
bool valueChanged = false;
nsAutoString oldValue;
if (aTrustedUpdate) {
valueChanged = true;
} else {
mInput->GetValue(oldValue);
}
mInput->SetValue(aColor);
if (!aTrustedUpdate) {
nsAutoString newValue;
mInput->GetValue(newValue);
if (!oldValue.Equals(newValue)) {
valueChanged = true;
}
}
if (valueChanged) {
mValueChanged = true;
return nsContentUtils::DispatchTrustedEvent(mInput->OwnerDoc(),
static_cast<nsIDOMHTMLInputElement*>(mInput.get()),
NS_LITERAL_STRING("input"), true,
false);
}
return NS_OK;
}
NS_IMETHODIMP
nsColorPickerShownCallback::Update(const nsAString& aColor)
{
return UpdateInternal(aColor, true);
}
NS_IMETHODIMP
nsColorPickerShownCallback::Done(const nsAString& aColor)
{
/**
* When Done() is called, we might be at the end of a serie of Update() calls
* in which case mValueChanged is set to true and a change event will have to
* be fired but we might also be in a one shot Done() call situation in which
* case we should fire a change event iif the value actually changed.
* UpdateInternal(bool) is taking care of that logic for us.
*/
nsresult rv = NS_OK;
if (!aColor.IsEmpty()) {
UpdateInternal(aColor, false);
}
if (mValueChanged) {
rv = nsContentUtils::DispatchTrustedEvent(mInput->OwnerDoc(),
static_cast<nsIDOMHTMLInputElement*>(mInput.get()),
NS_LITERAL_STRING("change"), true,
false);
}
return rv;
}
NS_IMPL_ISUPPORTS1(nsColorPickerShownCallback, nsIColorPickerShownCallback)
HTMLInputElement::AsyncClickHandler::AsyncClickHandler(HTMLInputElement* aInput) HTMLInputElement::AsyncClickHandler::AsyncClickHandler(HTMLInputElement* aInput)
: mInput(aInput) : mInput(aInput)
{ {
@ -400,8 +499,50 @@ HTMLInputElement::AsyncClickHandler::Run()
nsresult nsresult
HTMLInputElement::AsyncClickHandler::InitColorPicker() HTMLInputElement::AsyncClickHandler::InitColorPicker()
{ {
// TODO // Get parent nsPIDOMWindow object.
return NS_OK; nsCOMPtr<nsIDocument> doc = mInput->OwnerDoc();
nsCOMPtr<nsPIDOMWindow> win = doc->GetWindow();
if (!win) {
return NS_ERROR_FAILURE;
}
// Check if page is allowed to open the popup
if (mPopupControlState > openControlled) {
nsCOMPtr<nsIPopupWindowManager> pm =
do_GetService(NS_POPUPWINDOWMANAGER_CONTRACTID);
if (!pm) {
return NS_OK;
}
uint32_t permission;
pm->TestPermission(doc->NodePrincipal(), &permission);
if (permission == nsIPopupWindowManager::DENY_POPUP) {
nsGlobalWindow::FirePopupBlockedEvent(doc, win, nullptr, EmptyString(), EmptyString());
return NS_OK;
}
}
// Get Loc title
nsXPIDLString title;
nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
"ColorPicker", title);
nsCOMPtr<nsIColorPicker> colorPicker = do_CreateInstance("@mozilla.org/colorpicker;1");
if (!colorPicker) {
return NS_ERROR_FAILURE;
}
nsAutoString initialValue;
mInput->GetValueInternal(initialValue);
nsresult rv = colorPicker->Init(win, title, initialValue);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIColorPickerShownCallback> callback =
new nsColorPickerShownCallback(mInput, colorPicker);
return colorPicker->Open(callback);
} }
nsresult nsresult

View File

@ -24,7 +24,6 @@
#include "mozilla/Decimal.h" #include "mozilla/Decimal.h"
class nsDOMFileList; class nsDOMFileList;
class nsIFilePicker;
class nsIRadioGroupContainer; class nsIRadioGroupContainer;
class nsIRadioGroupVisitor; class nsIRadioGroupVisitor;
class nsIRadioVisitor; class nsIRadioVisitor;

View File

@ -62,6 +62,10 @@ MOCHITEST_FILES = \
test_input_event.html \ test_input_event.html \
test_input_number_rounding.html \ test_input_number_rounding.html \
test_valueAsDate_pref.html \ test_valueAsDate_pref.html \
test_input_color_picker_initial.html \
test_input_color_picker_update.html \
test_input_color_picker_popup.html \
test_input_color_input_change_events.html \
$(NULL) $(NULL)
include $(topsrcdir)/config/rules.mk include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,120 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=885996
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1234567</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript;version=1.8">
/** Test that update() modifies the element value such as done() when it is
* not called as a concellation.
*/
SimpleTest.waitForExplicitFinish();
var MockColorPicker = SpecialPowers.MockColorPicker;
var test = runTest();
SimpleTest.waitForFocus(function() {
test.next();
});
function runTest() {
MockColorPicker.init(window);
var element = null;
MockColorPicker.showCallback = function(picker, update) {
is(picker.initialColor, element.value);
var inputEvent = false;
var changeEvent = false;
element.oninput = function() {
inputEvent = true;
};
element.onchange = function() {
changeEvent = true;
};
if (element.dataset.type == 'update') {
update('#f00ba4');
is(inputEvent, true, 'input event should have been received');
is(changeEvent, false, 'change event should not have been received');
inputEvent = changeEvent = false;
is(element.value, '#f00ba4');
MockColorPicker.returnColor = '#f00ba7';
isnot(element.value, MockColorPicker.returnColor);
} else if (element.dataset.type == 'cancel') {
MockColorPicker.returnColor = '#bababa';
isnot(element.value, MockColorPicker.returnColor);
} else if (element.dataset.type == 'done') {
MockColorPicker.returnColor = '#098766';
isnot(element.value, MockColorPicker.returnColor);
} else if (element.dataset.type == 'noop-done') {
MockColorPicker.returnColor = element.value;
is(element.value, MockColorPicker.returnColor);
}
SimpleTest.executeSoon(function() {
if (element.dataset.type == 'cancel') {
isnot(element.value, MockColorPicker.returnColor);
is(inputEvent, false, 'no input event should have been sent');
is(changeEvent, false, 'no change event should have been sent');
} else if (element.dataset.type == 'noop-done') {
is(element.value, MockColorPicker.returnColor);
is(inputEvent, false, 'no input event should have been sent');
is(changeEvent, false, 'no change event should have been sent');
} else {
is(element.value, MockColorPicker.returnColor);
is(inputEvent, true, 'input event should have been sent');
is(changeEvent, true, 'change event should have been sent');
}
changeEvent = false;
element.blur();
setTimeout(function() {
is(changeEvent, false, "change event should not be fired on blur");
test.next();
});
});
return element.dataset.type == 'cancel' ? "" : MockColorPicker.returnColor;
};
for (var i = 0; i < document.getElementsByTagName('input').length; ++i) {
element = document.getElementsByTagName('input')[i];
element.focus();
synthesizeMouseAtCenter(element, {});
yield;
};
MockColorPicker.cleanup();
SimpleTest.finish();
yield;
}
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=885996">Mozilla Bug 885996</a>
<p id="display"></p>
<div id="content">
<input type='color' data-type='update'>
<input type='color' data-type='cancel'>
<input type='color' data-type='done'>
<input type='color' data-type='noop-done'>
</div>
<pre id="test">
</pre>
</body>
</html>

View File

@ -0,0 +1,79 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=885996
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1234567</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript;version=1.8">
/** Test that the initial value of the nsIColorPicker is the current value of
the <input type='color'> element. **/
SimpleTest.waitForExplicitFinish();
var MockColorPicker = SpecialPowers.MockColorPicker;
var test = runTest();
SimpleTest.waitForFocus(function() {
test.next();
});
function runTest() {
MockColorPicker.init(window);
var element = null;
MockColorPicker.showCallback = function(picker) {
is(picker.initialColor, element.value);
SimpleTest.executeSoon(function() {
test.next();
});
return "";
};
for (var i = 0; i < document.getElementsByTagName('input').length; ++i) {
element = document.getElementsByTagName('input')[i];
if (element.parentElement.id === 'dynamic-values') {
element.value = '#deadbe';
}
synthesizeMouseAtCenter(element, {});
yield;
};
MockColorPicker.cleanup();
SimpleTest.finish();
yield;
}
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=885996">Mozilla Bug 885996</a>
<p id="display"></p>
<div id="content">
<div id='valid-values'>
<input type='color' value='#ff00ff'>
<input type='color' value='#ab3275'>
<input type='color' value='#abcdef'>
<input type='color' value='#ABCDEF'>
</div>
<div id='invalid-values'>
<input type='color' value='ffffff'>
<input type='color' value='#abcdez'>
<input type='color' value='#0123456'>
</div>
<div id='dynamic-values'>
<input type='color' value='#ab4594'>
<input type='color' value='#984534'>
<input type='color' value='#f8b9a0'>
</div>
</div>
<pre id="test">
</pre>
</body>
</html>

View File

@ -0,0 +1,139 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=885996
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1234567</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript;version=1.8">
/** Test the behaviour of the <input type='color'> when clicking on it from
different ways. **/
SimpleTest.waitForExplicitFinish();
var MockColorPicker = SpecialPowers.MockColorPicker;
var test = runTest();
var testData = [
{ id: 'normal', result: true },
{ id: 'hidden', result: false },
{ id: 'normal', type: 'untrusted', result: true },
{ id: 'normal', type: 'prevent-default-1', result: false },
{ id: 'normal', type: 'prevent-default-2', result: false },
{ id: 'normal', type: 'click-method', result: true },
{ id: 'normal', type: 'right-click', result: false },
{ id: 'normal', type: 'middle-click', result: false },
{ id: 'label-1', result: true },
{ id: 'label-2', result: true },
{ id: 'label-3', result: true },
{ id: 'label-4', result: true },
{ id: 'button-click', result: true },
{ id: 'button-down', result: true },
{ id: 'button-up', result: true },
{ id: 'div-click', result: true },
{ id: 'div-click-on-demand', result: true },
];
var currentTest = null;
SimpleTest.waitForFocus(function() {
test.next();
});
function runTest() {
MockColorPicker.init(window);
var element = null;
MockColorPicker.showCallback = function(picker) {
ok(currentTest.result);
SimpleTest.executeSoon(function() {
test.next();
});
return "";
};
while (testData.length != 0) {
var currentTest = testData.shift();
element = document.getElementById(currentTest.id);
// To make sure we can actually click on the element.
element.focus();
switch (currentTest.type) {
case 'untrusted':
var e = document.createEvent('MouseEvents');
e.initEvent('click', true, false);
document.getElementById(element.dispatchEvent(e));
break;
case 'prevent-default-1':
element.onclick = function() {
return false;
};
element.click();
element.onclick = function() {};
break;
case 'prevent-default-2':
element.onclick = function(e) {
e.preventDefault();
};
element.click();
element.onclick = function() {};
break;
case 'click-method':
element.click();
break;
case 'right-click':
synthesizeMouseAtCenter(element, { button: 2 });
break;
case 'middle-click':
synthesizeMouseAtCenter(element, { button: 1 });
break;
default:
synthesizeMouseAtCenter(element, {});
}
if (!currentTest.result) {
setTimeout(function() {
setTimeout(function() {
ok(true);
SimpleTest.executeSoon(function() {
test.next();
});
});
});
}
yield;
};
MockColorPicker.cleanup();
SimpleTest.finish();
yield;
}
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=885996">Mozilla Bug 885996</a>
<p id="display"></p>
<div id="content">
<input type='color' id='normal'>
<input type='color' id='hidden' hidden>
<label id='label-1'>foo<input type='color'></label>
<label id='label-2' for='labeled-2'>foo</label><input id='labeled-2' type='color'></label>
<label id='label-3'>foo<input type='color'></label>
<label id='label-4' for='labeled-4'>foo</label><input id='labeled-4' type='color'></label>
<input id='by-button' type='color'>
<button id='button-click' onclick="document.getElementById('by-button').click();">click</button>
<button id='button-down' onclick="document.getElementById('by-button').click();">click</button>
<button id='button-up' onclick="document.getElementById('by-button').click();">click</button>
<div id='div-click' onclick="document.getElementById('by-button').click();">click</div>
<div id='div-click-on-demand' onclick="var i=document.createElement('input'); i.type='color'; i.click();">click</div>
</div>
<pre id="test">
</pre>
</body>
</html>

View File

@ -0,0 +1,86 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=885996
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1234567</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript;version=1.8">
/** Test that update() modifies the element value such as done() when it is
* not called as a concellation.
*/
SimpleTest.waitForExplicitFinish();
var MockColorPicker = SpecialPowers.MockColorPicker;
var test = runTest();
SimpleTest.waitForFocus(function() {
test.next();
});
function runTest() {
MockColorPicker.init(window);
var element = null;
MockColorPicker.showCallback = function(picker, update) {
is(picker.initialColor, element.value);
if (element.dataset.type == 'update') {
update('#f00ba4');
is(element.value, '#f00ba4');
MockColorPicker.returnColor = '#f00ba7';
isnot(element.value, MockColorPicker.returnColor);
} else if (element.dataset.type == 'cancel') {
MockColorPicker.returnColor = '#bababa';
isnot(element.value, MockColorPicker.returnColor);
} else if (element.dataset.type == 'done') {
MockColorPicker.returnColor = '#098766';
isnot(element.value, MockColorPicker.returnColor);
}
SimpleTest.executeSoon(function() {
if (element.dataset.type == 'cancel') {
isnot(element.value, MockColorPicker.returnColor);
} else {
is(element.value, MockColorPicker.returnColor);
}
test.next();
});
return element.dataset.type == 'cancel' ? "" : MockColorPicker.returnColor;
};
for (var i = 0; i < document.getElementsByTagName('input').length; ++i) {
element = document.getElementsByTagName('input')[i];
synthesizeMouseAtCenter(element, {});
yield;
};
MockColorPicker.cleanup();
SimpleTest.finish();
yield;
}
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=885996">Mozilla Bug 885996</a>
<p id="display"></p>
<div id="content">
<input type='color' data-type='update'>
<input type='color' data-type='cancel'>
<input type='color' data-type='done'>
</div>
<pre id="test">
</pre>
</body>
</html>

View File

@ -4,40 +4,43 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsXBLChildrenElement.h" #include "mozilla/dom/XBLChildrenElement.h"
#include "nsCharSeparatedTokenizer.h" #include "nsCharSeparatedTokenizer.h"
#include "mozilla/dom/NodeListBinding.h" #include "mozilla/dom/NodeListBinding.h"
nsXBLChildrenElement::~nsXBLChildrenElement() namespace mozilla {
namespace dom {
XBLChildrenElement::~XBLChildrenElement()
{ {
} }
NS_IMPL_ADDREF_INHERITED(nsXBLChildrenElement, Element) NS_IMPL_ADDREF_INHERITED(XBLChildrenElement, Element)
NS_IMPL_RELEASE_INHERITED(nsXBLChildrenElement, Element) NS_IMPL_RELEASE_INHERITED(XBLChildrenElement, Element)
NS_INTERFACE_TABLE_HEAD(nsXBLChildrenElement) NS_INTERFACE_TABLE_HEAD(XBLChildrenElement)
NS_INTERFACE_TABLE_INHERITED2(nsXBLChildrenElement, nsIDOMNode, NS_INTERFACE_TABLE_INHERITED2(XBLChildrenElement, nsIDOMNode,
nsIDOMElement) nsIDOMElement)
NS_ELEMENT_INTERFACE_TABLE_TO_MAP_SEGUE NS_ELEMENT_INTERFACE_TABLE_TO_MAP_SEGUE
NS_INTERFACE_MAP_END_INHERITING(Element) NS_INTERFACE_MAP_END_INHERITING(Element)
NS_IMPL_ELEMENT_CLONE(nsXBLChildrenElement) NS_IMPL_ELEMENT_CLONE(XBLChildrenElement)
nsIAtom* nsIAtom*
nsXBLChildrenElement::GetIDAttributeName() const XBLChildrenElement::GetIDAttributeName() const
{ {
return nullptr; return nullptr;
} }
nsIAtom* nsIAtom*
nsXBLChildrenElement::DoGetID() const XBLChildrenElement::DoGetID() const
{ {
return nullptr; return nullptr;
} }
nsresult nsresult
nsXBLChildrenElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, XBLChildrenElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
bool aNotify) bool aNotify)
{ {
if (aAttribute == nsGkAtoms::includes && if (aAttribute == nsGkAtoms::includes &&
aNameSpaceID == kNameSpaceID_None) { aNameSpaceID == kNameSpaceID_None) {
@ -48,10 +51,10 @@ nsXBLChildrenElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
} }
bool bool
nsXBLChildrenElement::ParseAttribute(int32_t aNamespaceID, XBLChildrenElement::ParseAttribute(int32_t aNamespaceID,
nsIAtom* aAttribute, nsIAtom* aAttribute,
const nsAString& aValue, const nsAString& aValue,
nsAttrValue& aResult) nsAttrValue& aResult)
{ {
if (aAttribute == nsGkAtoms::includes && if (aAttribute == nsGkAtoms::includes &&
aNamespaceID == kNameSpaceID_None) { aNamespaceID == kNameSpaceID_None) {
@ -66,6 +69,11 @@ nsXBLChildrenElement::ParseAttribute(int32_t aNamespaceID,
return false; return false;
} }
} // namespace mozilla
} // namespace dom
using namespace mozilla::dom;
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(nsAnonymousContentList, mParent) NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(nsAnonymousContentList, mParent)
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsAnonymousContentList) NS_IMPL_CYCLE_COLLECTING_ADDREF(nsAnonymousContentList)
@ -94,7 +102,7 @@ nsAnonymousContentList::GetLength(uint32_t* aLength)
child; child;
child = child->GetNextSibling()) { child = child->GetNextSibling()) {
if (child->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) { if (child->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) {
nsXBLChildrenElement* point = static_cast<nsXBLChildrenElement*>(child); XBLChildrenElement* point = static_cast<XBLChildrenElement*>(child);
if (!point->mInsertedChildren.IsEmpty()) { if (!point->mInsertedChildren.IsEmpty()) {
count += point->mInsertedChildren.Length(); count += point->mInsertedChildren.Length();
} }
@ -135,7 +143,7 @@ nsAnonymousContentList::Item(uint32_t aIndex)
child; child;
child = child->GetNextSibling()) { child = child->GetNextSibling()) {
if (child->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) { if (child->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) {
nsXBLChildrenElement* point = static_cast<nsXBLChildrenElement*>(child); XBLChildrenElement* point = static_cast<XBLChildrenElement*>(child);
if (!point->mInsertedChildren.IsEmpty()) { if (!point->mInsertedChildren.IsEmpty()) {
if (remIndex < point->mInsertedChildren.Length()) { if (remIndex < point->mInsertedChildren.Length()) {
return point->mInsertedChildren[remIndex]; return point->mInsertedChildren[remIndex];
@ -176,7 +184,7 @@ nsAnonymousContentList::IndexOf(nsIContent* aContent)
child; child;
child = child->GetNextSibling()) { child = child->GetNextSibling()) {
if (child->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) { if (child->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) {
nsXBLChildrenElement* point = static_cast<nsXBLChildrenElement*>(child); XBLChildrenElement* point = static_cast<XBLChildrenElement*>(child);
if (!point->mInsertedChildren.IsEmpty()) { if (!point->mInsertedChildren.IsEmpty()) {
uint32_t insIndex = point->mInsertedChildren.IndexOf(aContent); uint32_t insIndex = point->mInsertedChildren.IndexOf(aContent);
if (insIndex != point->mInsertedChildren.NoIndex) { if (insIndex != point->mInsertedChildren.NoIndex) {

View File

@ -12,26 +12,23 @@
#include "nsBindingManager.h" #include "nsBindingManager.h"
#include "mozilla/dom/nsXMLElement.h" #include "mozilla/dom/nsXMLElement.h"
class nsAnonymousContentList;
namespace mozilla { namespace mozilla {
namespace dom { namespace dom {
class ExplicitChildIterator; class ExplicitChildIterator;
} class XBLChildrenElement : public nsXMLElement
}
class nsAnonymousContentList;
class nsXBLChildrenElement : public nsXMLElement
{ {
public: public:
friend class mozilla::dom::ExplicitChildIterator; friend class mozilla::dom::ExplicitChildIterator;
friend class nsAnonymousContentList; friend class nsAnonymousContentList;
nsXBLChildrenElement(already_AddRefed<nsINodeInfo> aNodeInfo) XBLChildrenElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsXMLElement(aNodeInfo) : nsXMLElement(aNodeInfo)
{ {
} }
~nsXBLChildrenElement(); ~XBLChildrenElement();
// nsISupports // nsISupports
NS_DECL_ISUPPORTS_INHERITED NS_DECL_ISUPPORTS_INHERITED
@ -148,6 +145,9 @@ private:
nsTArray<nsCOMPtr<nsIAtom> > mIncludes; nsTArray<nsCOMPtr<nsIAtom> > mIncludes;
}; };
} // namespace dom
} // namespace mozilla
class nsAnonymousContentList : public nsINodeList class nsAnonymousContentList : public nsINodeList
{ {
public: public:

View File

@ -12,13 +12,16 @@ EXPORTS += [
'nsXBLService.h', 'nsXBLService.h',
] ]
EXPORTS.mozilla.dom += [
'XBLChildrenElement.h',
]
CPP_SOURCES += [ CPP_SOURCES += [
'nsBindingManager.cpp', 'nsBindingManager.cpp',
'nsXBLBinding.cpp', 'nsXBLBinding.cpp',
'nsXBLContentSink.cpp', 'nsXBLContentSink.cpp',
'nsXBLDocumentInfo.cpp', 'nsXBLDocumentInfo.cpp',
'nsXBLEventHandler.cpp', 'nsXBLEventHandler.cpp',
'nsXBLChildrenElement.cpp',
'nsXBLProtoImpl.cpp', 'nsXBLProtoImpl.cpp',
'nsXBLProtoImplField.cpp', 'nsXBLProtoImplField.cpp',
'nsXBLProtoImplMethod.cpp', 'nsXBLProtoImplMethod.cpp',
@ -30,5 +33,6 @@ CPP_SOURCES += [
'nsXBLSerialize.cpp', 'nsXBLSerialize.cpp',
'nsXBLService.cpp', 'nsXBLService.cpp',
'nsXBLWindowKeyHandler.cpp', 'nsXBLWindowKeyHandler.cpp',
'XBLChildrenElement.cpp',
] ]

View File

@ -27,7 +27,7 @@
#include "nsXBLBinding.h" #include "nsXBLBinding.h"
#include "nsXBLPrototypeBinding.h" #include "nsXBLPrototypeBinding.h"
#include "nsXBLDocumentInfo.h" #include "nsXBLDocumentInfo.h"
#include "nsXBLChildrenElement.h" #include "mozilla/dom/XBLChildrenElement.h"
#include "nsIStyleRuleProcessor.h" #include "nsIStyleRuleProcessor.h"
#include "nsRuleProcessorData.h" #include "nsRuleProcessorData.h"
@ -48,6 +48,7 @@
#include "mozilla/dom/NodeListBinding.h" #include "mozilla/dom/NodeListBinding.h"
using namespace mozilla; using namespace mozilla;
using namespace mozilla::dom;
// //
// Generic pldhash table stuff for mapping one nsISupports to another // Generic pldhash table stuff for mapping one nsISupports to another
@ -970,7 +971,7 @@ nsBindingManager::AppendAllSheets(nsTArray<nsCSSStyleSheet*>& aArray)
static void static void
InsertAppendedContent(nsBindingManager* aManager, InsertAppendedContent(nsBindingManager* aManager,
nsXBLChildrenElement* aPoint, XBLChildrenElement* aPoint,
nsIContent* aFirstNewContent) nsIContent* aFirstNewContent)
{ {
uint32_t insertionIndex; uint32_t insertionIndex;
@ -1008,7 +1009,7 @@ nsBindingManager::ContentAppended(nsIDocument* aDocument,
} }
// Try to find insertion points for all the new kids. // Try to find insertion points for all the new kids.
nsXBLChildrenElement* point = nullptr; XBLChildrenElement* point = nullptr;
nsIContent* parent = aContainer; nsIContent* parent = aContainer;
bool first = true; bool first = true;
do { do {
@ -1081,7 +1082,7 @@ nsBindingManager::ContentRemoved(nsIDocument* aDocument,
{ {
SetInsertionParent(aChild, nullptr); SetInsertionParent(aChild, nullptr);
nsXBLChildrenElement* point = nullptr; XBLChildrenElement* point = nullptr;
nsIContent* parent = aContainer; nsIContent* parent = aContainer;
do { do {
nsXBLBinding* binding = GetBindingWithContent(parent); nsXBLBinding* binding = GetBindingWithContent(parent);
@ -1118,7 +1119,7 @@ void
nsBindingManager::ClearInsertionPointsRecursively(nsIContent* aContent) nsBindingManager::ClearInsertionPointsRecursively(nsIContent* aContent)
{ {
if (aContent->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) { if (aContent->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) {
static_cast<nsXBLChildrenElement*>(aContent)->ClearInsertedChildrenAndInsertionParents(this); static_cast<XBLChildrenElement*>(aContent)->ClearInsertedChildrenAndInsertionParents(this);
} }
uint32_t childCount = aContent->GetChildCount(); uint32_t childCount = aContent->GetChildCount();
@ -1211,7 +1212,7 @@ nsBindingManager::HandleChildInsertion(nsIContent* aContainer,
uint32_t(aContainer->IndexOf(aChild)) == aIndexInContainer, uint32_t(aContainer->IndexOf(aChild)) == aIndexInContainer,
"Child not at the right index?"); "Child not at the right index?");
nsXBLChildrenElement* point = nullptr; XBLChildrenElement* point = nullptr;
nsIContent* parent = aContainer; nsIContent* parent = aContainer;
while (parent) { while (parent) {
nsXBLBinding* binding = GetBindingWithContent(parent); nsXBLBinding* binding = GetBindingWithContent(parent);
@ -1263,7 +1264,7 @@ nsBindingManager::FindNestedInsertionPoint(nsIContent* aContainer,
nsIContent* parent = aContainer; nsIContent* parent = aContainer;
if (aContainer->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) { if (aContainer->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) {
if (static_cast<nsXBLChildrenElement*>(aContainer)-> if (static_cast<XBLChildrenElement*>(aContainer)->
HasInsertedChildren()) { HasInsertedChildren()) {
return nullptr; return nullptr;
} }
@ -1276,7 +1277,7 @@ nsBindingManager::FindNestedInsertionPoint(nsIContent* aContainer,
break; break;
} }
nsXBLChildrenElement* point = binding->FindInsertionPointFor(aChild); XBLChildrenElement* point = binding->FindInsertionPointFor(aChild);
if (!point) { if (!point) {
return nullptr; return nullptr;
} }
@ -1299,7 +1300,7 @@ nsBindingManager::FindNestedSingleInsertionPoint(nsIContent* aContainer,
nsIContent* parent = aContainer; nsIContent* parent = aContainer;
if (aContainer->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) { if (aContainer->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) {
if (static_cast<nsXBLChildrenElement*>(aContainer)-> if (static_cast<XBLChildrenElement*>(aContainer)->
HasInsertedChildren()) { HasInsertedChildren()) {
return nullptr; return nullptr;
} }
@ -1317,7 +1318,7 @@ nsBindingManager::FindNestedSingleInsertionPoint(nsIContent* aContainer,
return nullptr; return nullptr;
} }
nsXBLChildrenElement* point = binding->GetDefaultInsertionPoint(); XBLChildrenElement* point = binding->GetDefaultInsertionPoint();
if (!point) { if (!point) {
return nullptr; return nullptr;
} }

View File

@ -48,7 +48,7 @@
#include "nsIPrincipal.h" #include "nsIPrincipal.h"
#include "nsIScriptSecurityManager.h" #include "nsIScriptSecurityManager.h"
#include "nsGUIEvent.h" #include "nsGUIEvent.h"
#include "nsXBLChildrenElement.h" #include "mozilla/dom/XBLChildrenElement.h"
#include "prprf.h" #include "prprf.h"
#include "nsNodeUtils.h" #include "nsNodeUtils.h"
@ -338,7 +338,7 @@ nsXBLBinding::GenerateAnonymousContent()
// order. // order.
for (nsIContent* child = mContent; child; child = child->GetNextNode(mContent)) { for (nsIContent* child = mContent; child; child = child->GetNextNode(mContent)) {
if (child->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) { if (child->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) {
nsXBLChildrenElement* point = static_cast<nsXBLChildrenElement*>(child); XBLChildrenElement* point = static_cast<XBLChildrenElement*>(child);
if (point->IsDefaultInsertion()) { if (point->IsDefaultInsertion()) {
mDefaultInsertionPoint = point; mDefaultInsertionPoint = point;
} else { } else {
@ -361,7 +361,7 @@ nsXBLBinding::GenerateAnonymousContent()
} else if (!mInsertionPoints.IsEmpty()) { } else if (!mInsertionPoints.IsEmpty()) {
ExplicitChildIterator iter(mBoundElement); ExplicitChildIterator iter(mBoundElement);
for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) { for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) {
nsXBLChildrenElement* point = FindInsertionPointForInternal(child); XBLChildrenElement* point = FindInsertionPointForInternal(child);
if (point) { if (point) {
point->AppendInsertedChild(child, bindingManager); point->AppendInsertedChild(child, bindingManager);
} }
@ -404,7 +404,7 @@ nsXBLBinding::GenerateAnonymousContent()
} }
} }
nsXBLChildrenElement* XBLChildrenElement*
nsXBLBinding::FindInsertionPointFor(nsIContent* aChild) nsXBLBinding::FindInsertionPointFor(nsIContent* aChild)
{ {
// XXX We should get rid of this function as it causes us to traverse the // XXX We should get rid of this function as it causes us to traverse the
@ -417,11 +417,11 @@ nsXBLBinding::FindInsertionPointFor(nsIContent* aChild)
: nullptr; : nullptr;
} }
nsXBLChildrenElement* XBLChildrenElement*
nsXBLBinding::FindInsertionPointForInternal(nsIContent* aChild) nsXBLBinding::FindInsertionPointForInternal(nsIContent* aChild)
{ {
for (uint32_t i = 0; i < mInsertionPoints.Length(); ++i) { for (uint32_t i = 0; i < mInsertionPoints.Length(); ++i) {
nsXBLChildrenElement* point = mInsertionPoints[i]; XBLChildrenElement* point = mInsertionPoints[i];
if (point->Includes(aChild)) { if (point->Includes(aChild)) {
return point; return point;
} }
@ -681,7 +681,7 @@ nsXBLBinding::UnhookEventHandlers()
static void static void
UpdateInsertionParent(nsBindingManager* aBindingManager, UpdateInsertionParent(nsBindingManager* aBindingManager,
nsXBLChildrenElement* aPoint, XBLChildrenElement* aPoint,
nsIContent* aOldBoundElement) nsIContent* aOldBoundElement)
{ {
if (aPoint->IsDefaultInsertion()) { if (aPoint->IsDefaultInsertion()) {

View File

@ -22,7 +22,15 @@ class nsIContent;
class nsIAtom; class nsIAtom;
class nsIDocument; class nsIDocument;
class nsIScriptContext; class nsIScriptContext;
class nsXBLChildrenElement;
namespace mozilla {
namespace dom {
class XBLChildrenElement;
}
}
class nsAnonymousContentList; class nsAnonymousContentList;
struct JSContext; struct JSContext;
class JSObject; class JSObject;
@ -136,14 +144,14 @@ public:
bool AllowScripts(); // XXX make const bool AllowScripts(); // XXX make const
nsXBLChildrenElement* FindInsertionPointFor(nsIContent* aChild); mozilla::dom::XBLChildrenElement* FindInsertionPointFor(nsIContent* aChild);
bool HasFilteredInsertionPoints() bool HasFilteredInsertionPoints()
{ {
return !mInsertionPoints.IsEmpty(); return !mInsertionPoints.IsEmpty();
} }
nsXBLChildrenElement* GetDefaultInsertionPoint() mozilla::dom::XBLChildrenElement* GetDefaultInsertionPoint()
{ {
return mDefaultInsertionPoint; return mDefaultInsertionPoint;
} }
@ -176,11 +184,11 @@ protected:
// attribute. These points must be up-to-date with respect to their parent's // attribute. These points must be up-to-date with respect to their parent's
// children, even if their parent has another binding attached to it, // children, even if their parent has another binding attached to it,
// preventing us from rendering their contents directly. // preventing us from rendering their contents directly.
nsRefPtr<nsXBLChildrenElement> mDefaultInsertionPoint; nsRefPtr<mozilla::dom::XBLChildrenElement> mDefaultInsertionPoint;
nsTArray<nsRefPtr<nsXBLChildrenElement> > mInsertionPoints; nsTArray<nsRefPtr<mozilla::dom::XBLChildrenElement> > mInsertionPoints;
nsRefPtr<nsAnonymousContentList> mAnonymousContentList; nsRefPtr<nsAnonymousContentList> mAnonymousContentList;
nsXBLChildrenElement* FindInsertionPointForInternal(nsIContent* aChild); mozilla::dom::XBLChildrenElement* FindInsertionPointForInternal(nsIContent* aChild);
}; };
#endif // nsXBLBinding_h_ #endif // nsXBLBinding_h_

View File

@ -35,7 +35,9 @@ AlarmsManager.prototype = {
classID : ALARMSMANAGER_CID, classID : ALARMSMANAGER_CID,
QueryInterface : XPCOMUtils.generateQI([nsIDOMMozAlarmsManager, Ci.nsIDOMGlobalPropertyInitializer]), QueryInterface : XPCOMUtils.generateQI([nsIDOMMozAlarmsManager,
Ci.nsIDOMGlobalPropertyInitializer,
Ci.nsISupportsWeakReference]),
classInfo : XPCOMUtils.generateCI({ classID: ALARMSMANAGER_CID, classInfo : XPCOMUtils.generateCI({ classID: ALARMSMANAGER_CID,
contractID: ALARMSMANAGER_CONTRACTID, contractID: ALARMSMANAGER_CONTRACTID,
@ -162,7 +164,7 @@ AlarmsManager.prototype = {
this._cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsISyncMessageSender); this._cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsISyncMessageSender);
// Add the valid messages to be listened. // Add the valid messages to be listened.
this.initHelper(aWindow, ["AlarmsManager:Add:Return:OK", "AlarmsManager:Add:Return:KO", this.initDOMRequestHelper(aWindow, ["AlarmsManager:Add:Return:OK", "AlarmsManager:Add:Return:KO",
"AlarmsManager:GetAll:Return:OK", "AlarmsManager:GetAll:Return:KO"]); "AlarmsManager:GetAll:Return:OK", "AlarmsManager:GetAll:Return:KO"]);
// Get the manifest URL if this is an installed app // Get the manifest URL if this is an installed app

View File

@ -242,7 +242,7 @@ WebappsRegistry.prototype = {
// nsIDOMGlobalPropertyInitializer implementation // nsIDOMGlobalPropertyInitializer implementation
init: function(aWindow) { init: function(aWindow) {
this.initHelper(aWindow, ["Webapps:Install:Return:OK", "Webapps:Install:Return:KO", this.initDOMRequestHelper(aWindow, ["Webapps:Install:Return:OK", "Webapps:Install:Return:KO",
"Webapps:GetInstalled:Return:OK", "Webapps:GetInstalled:Return:OK",
"Webapps:GetSelf:Return:OK", "Webapps:GetSelf:Return:OK",
"Webapps:CheckInstalled:Return:OK" ]); "Webapps:CheckInstalled:Return:OK" ]);
@ -264,7 +264,8 @@ WebappsRegistry.prototype = {
classID: Components.ID("{fff440b3-fae2-45c1-bf03-3b5a2e432270}"), classID: Components.ID("{fff440b3-fae2-45c1-bf03-3b5a2e432270}"),
QueryInterface: XPCOMUtils.generateQI([Ci.mozIDOMApplicationRegistry, QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference,
Ci.mozIDOMApplicationRegistry,
#ifdef MOZ_B2G #ifdef MOZ_B2G
Ci.mozIDOMApplicationRegistry2, Ci.mozIDOMApplicationRegistry2,
#elifdef MOZ_WIDGET_ANDROID #elifdef MOZ_WIDGET_ANDROID
@ -364,7 +365,7 @@ WebappsApplication.prototype = {
this._downloadError = null; this._downloadError = null;
this.initHelper(aWindow, ["Webapps:OfflineCache", this.initDOMRequestHelper(aWindow, ["Webapps:OfflineCache",
"Webapps:CheckForUpdate:Return:OK", "Webapps:CheckForUpdate:Return:OK",
"Webapps:CheckForUpdate:Return:KO", "Webapps:CheckForUpdate:Return:KO",
"Webapps:Launch:Return:OK", "Webapps:Launch:Return:OK",
@ -636,7 +637,8 @@ WebappsApplication.prototype = {
classID: Components.ID("{723ed303-7757-4fb0-b261-4f78b1f6bd22}"), classID: Components.ID("{723ed303-7757-4fb0-b261-4f78b1f6bd22}"),
QueryInterface: XPCOMUtils.generateQI([Ci.mozIDOMApplication]), QueryInterface: XPCOMUtils.generateQI([Ci.mozIDOMApplication,
Ci.nsISupportsWeakReference]),
classInfo: XPCOMUtils.generateCI({classID: Components.ID("{723ed303-7757-4fb0-b261-4f78b1f6bd22}"), classInfo: XPCOMUtils.generateCI({classID: Components.ID("{723ed303-7757-4fb0-b261-4f78b1f6bd22}"),
contractID: "@mozilla.org/webapps/application;1", contractID: "@mozilla.org/webapps/application;1",
@ -649,7 +651,7 @@ WebappsApplication.prototype = {
* mozIDOMApplicationMgmt object * mozIDOMApplicationMgmt object
*/ */
function WebappsApplicationMgmt(aWindow) { function WebappsApplicationMgmt(aWindow) {
this.initHelper(aWindow, ["Webapps:GetAll:Return:OK", this.initDOMRequestHelper(aWindow, ["Webapps:GetAll:Return:OK",
"Webapps:GetAll:Return:KO", "Webapps:GetAll:Return:KO",
"Webapps:Uninstall:Return:OK", "Webapps:Uninstall:Return:OK",
"Webapps:Uninstall:Broadcast:Return:OK", "Webapps:Uninstall:Broadcast:Return:OK",
@ -787,7 +789,7 @@ WebappsApplicationMgmt.prototype = {
classID: Components.ID("{8c1bca96-266f-493a-8d57-ec7a95098c15}"), classID: Components.ID("{8c1bca96-266f-493a-8d57-ec7a95098c15}"),
QueryInterface: XPCOMUtils.generateQI([Ci.mozIDOMApplicationMgmt]), QueryInterface: XPCOMUtils.generateQI([Ci.mozIDOMApplicationMgmt, Ci.nsISupportsWeakReference]),
classInfo: XPCOMUtils.generateCI({classID: Components.ID("{8c1bca96-266f-493a-8d57-ec7a95098c15}"), classInfo: XPCOMUtils.generateCI({classID: Components.ID("{8c1bca96-266f-493a-8d57-ec7a95098c15}"),
contractID: "@mozilla.org/webapps/application-mgmt;1", contractID: "@mozilla.org/webapps/application-mgmt;1",

View File

@ -3,10 +3,10 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */ * You can obtain one at http://mozilla.org/MPL/2.0/. */
/** /**
* helper object for APIs that deal with DOMRequest and need to release them properly * Helper object for APIs that deal with DOMRequests and need to release them
* when the window goes out of scope * when the window goes out of scope.
*/ */
const Cu = Components.utils; const Cu = Components.utils;
const Cc = Components.classes; const Cc = Components.classes;
const Ci = Components.interfaces; const Ci = Components.interfaces;
@ -19,10 +19,109 @@ XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
"@mozilla.org/childprocessmessagemanager;1", "@mozilla.org/childprocessmessagemanager;1",
"nsIMessageListenerManager"); "nsIMessageListenerManager");
/**
* We use DOMRequestIpcHelperMessageListener to avoid leaking objects which
* "inherit" from DOMRequestIpcHelper.
*
* The issue is that the message manager will hold a strong ref to the message
* listener we register with it. But we don't want to hold a strong ref to the
* DOMRequestIpcHelper object, because that object may be arbitrarily large.
*
* So instead the message manager holds a strong ref to the
* DOMRequestIpcHelperMessageListener, and that holds a /weak/ ref to its
* DOMRequestIpcHelper.
*
* Additionally, we want to unhook all of these message listeners when the
* appropriate window is destroyed. We use DOMRequestIpcHelperMessageListener
* for this, too.
*/
this.DOMRequestIpcHelperMessageListener = function(aHelper, aWindow, aMessages) {
this._weakHelper = Cu.getWeakReference(aHelper);
this._messages = aMessages;
this._messages.forEach(function(msgName) {
cpmm.addMessageListener(msgName, this);
}, this);
Services.obs.addObserver(this, "inner-window-destroyed", /* weakRef */ true);
// aWindow may be null; in that case, the DOMRequestIpcHelperMessageListener
// is not tied to a particular window and lives forever.
if (aWindow) {
let util = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
this._innerWindowID = util.currentInnerWindowID;
}
}
DOMRequestIpcHelperMessageListener.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIMessageListener,
Ci.nsIObserver,
Ci.nsISupportsWeakReference]),
observe: function(aSubject, aTopic, aData) {
if (aTopic !== "inner-window-destroyed") {
return;
}
let wId = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data;
if (wId != this._innerWindowID) {
return;
}
this.destroy();
},
receiveMessage: function(aMsg) {
let helper = this._weakHelper.get();
if (helper) {
helper.receiveMessage(aMsg);
} else {
this.destroy();
}
},
destroy: function() {
Services.obs.removeObserver(this, "inner-window-destroyed");
this._messages.forEach(function(msgName) {
cpmm.removeMessageListener(msgName, this);
}, this);
this._messages = null;
let helper = this._weakHelper.get();
if (helper) {
helper.destroyDOMRequestHelper();
}
}
}
this.DOMRequestIpcHelper = function DOMRequestIpcHelper() { this.DOMRequestIpcHelper = function DOMRequestIpcHelper() {
} }
DOMRequestIpcHelper.prototype = { DOMRequestIpcHelper.prototype = {
/**
* An object which "inherits" from DOMRequestIpcHelper and declares its own
* queryInterface method MUST implement Ci.nsISupportsWeakReference.
*/
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference]),
initDOMRequestHelper: function(aWindow, aMessages) {
this._DOMRequestIpcHelperMessageListener =
new DOMRequestIpcHelperMessageListener(this, aWindow, aMessages);
this._window = aWindow;
this._requests = [];
this._id = this._getRandomId();
if (this._window) {
// We don't use this.innerWindowID, but other classes rely on it.
let util = this._window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
this.innerWindowID = util.currentInnerWindowID;
}
},
getRequestId: function(aRequest) { getRequestId: function(aRequest) {
let id = "id" + this._getRandomId(); let id = "id" + this._getRandomId();
this._requests[id] = aRequest; this._requests[id] = aRequest;
@ -51,48 +150,22 @@ DOMRequestIpcHelper.prototype = {
return Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator).generateUUID().toString(); return Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator).generateUUID().toString();
}, },
observe: function(aSubject, aTopic, aData) { destroyDOMRequestHelper: function() {
if (aTopic !== "inner-window-destroyed") { // This function is re-entrant --
// DOMRequestIpcHelperMessageListener.destroy() calls back into this
// function, and this.uninit() may also call it.
if (this._destroyed) {
return; return;
} }
this._destroyed = true;
let wId = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data; this._DOMRequestIpcHelperMessageListener.destroy();
if (wId == this.innerWindowID) {
Services.obs.removeObserver(this, "inner-window-destroyed");
this._requests = [];
this._window = null;
this.removeMessageListener();
if(this.uninit)
this.uninit();
}
},
initRequests: function initRequests() {
this._requests = []; this._requests = [];
}, this._window = null;
initMessageListener: function initMessageListener(aMessages) { if(this.uninit) {
this._messages = aMessages; this.uninit();
this._messages.forEach(function(msgName) { }
cpmm.addMessageListener(msgName, this);
}, this);
},
initHelper: function(aWindow, aMessages) {
this.initMessageListener(aMessages);
this.initRequests();
this._id = this._getRandomId();
Services.obs.addObserver(this, "inner-window-destroyed", false);
this._window = aWindow;
let util = this._window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
this.innerWindowID = util.currentInnerWindowID;
},
removeMessageListener: function removeMessageListener() {
this._messages.forEach(function(msgName) {
cpmm.removeMessageListener(msgName, this);
}, this);
this._messages = null;
}, },
createRequest: function() { createRequest: function() {

View File

@ -911,7 +911,7 @@ ContactManager.prototype = {
}, },
init: function(aWindow) { init: function(aWindow) {
this.initHelper(aWindow, ["Contacts:Find:Return:OK", "Contacts:Find:Return:KO", this.initDOMRequestHelper(aWindow, ["Contacts:Find:Return:OK", "Contacts:Find:Return:KO",
"Contacts:Clear:Return:OK", "Contacts:Clear:Return:KO", "Contacts:Clear:Return:OK", "Contacts:Clear:Return:KO",
"Contact:Save:Return:OK", "Contact:Save:Return:KO", "Contact:Save:Return:OK", "Contact:Save:Return:KO",
"Contact:Remove:Return:OK", "Contact:Remove:Return:KO", "Contact:Remove:Return:OK", "Contact:Remove:Return:KO",
@ -929,7 +929,9 @@ ContactManager.prototype = {
}, },
classID : CONTACTMANAGER_CID, classID : CONTACTMANAGER_CID,
QueryInterface : XPCOMUtils.generateQI([nsIDOMContactManager, Ci.nsIDOMGlobalPropertyInitializer]), QueryInterface : XPCOMUtils.generateQI([nsIDOMContactManager,
Ci.nsIDOMGlobalPropertyInitializer,
Ci.nsISupportsWeakReference]),
classInfo : XPCOMUtils.generateCI({classID: CONTACTMANAGER_CID, classInfo : XPCOMUtils.generateCI({classID: CONTACTMANAGER_CID,
contractID: CONTACTMANAGER_CONTRACTID, contractID: CONTACTMANAGER_CONTRACTID,

View File

@ -42,7 +42,8 @@ DOMFMRadioChild.prototype = {
}), }),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMFMRadio, QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMFMRadio,
Ci.nsIDOMGlobalPropertyInitializer]), Ci.nsIDOMGlobalPropertyInitializer,
Ci.nsISupportsWeakReference]),
// nsIDOMGlobalPropertyInitializer implementation // nsIDOMGlobalPropertyInitializer implementation
init: function(aWindow) { init: function(aWindow) {
@ -72,7 +73,7 @@ DOMFMRadioChild.prototype = {
"DOMFMRadio:frequencyChange", "DOMFMRadio:frequencyChange",
"DOMFMRadio:powerStateChange", "DOMFMRadio:powerStateChange",
"DOMFMRadio:antennaChange"]; "DOMFMRadio:antennaChange"];
this.initHelper(aWindow, messages); this.initDOMRequestHelper(aWindow, messages);
let els = Cc["@mozilla.org/eventlistenerservice;1"] let els = Cc["@mozilla.org/eventlistenerservice;1"]
.getService(Ci.nsIEventListenerService); .getService(Ci.nsIEventListenerService);

View File

@ -27,3 +27,4 @@ NoFilesSelected=No files selected.
# <input type='file' multiple> when there are more than one selected file. # <input type='file' multiple> when there are more than one selected file.
# %S will be a number greater or equal to 2. # %S will be a number greater or equal to 2.
XFilesSelected=%S files selected. XFilesSelected=%S files selected.
ColorPicker=Choose a color

View File

@ -248,7 +248,7 @@ SystemMessageManager.prototype = {
// nsIDOMGlobalPropertyInitializer implementation. // nsIDOMGlobalPropertyInitializer implementation.
init: function sysMessMgr_init(aWindow) { init: function sysMessMgr_init(aWindow) {
debug("init"); debug("init");
this.initHelper(aWindow, ["SystemMessageManager:Message", this.initDOMRequestHelper(aWindow, ["SystemMessageManager:Message",
"SystemMessageManager:GetPendingMessages:Return"]); "SystemMessageManager:GetPendingMessages:Return"]);
let principal = aWindow.document.nodePrincipal; let principal = aWindow.document.nodePrincipal;
@ -307,7 +307,8 @@ SystemMessageManager.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMNavigatorSystemMessages, QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMNavigatorSystemMessages,
Ci.nsIDOMGlobalPropertyInitializer, Ci.nsIDOMGlobalPropertyInitializer,
Ci.nsIObserver]), Ci.nsIObserver,
Ci.nsISupportsWeakReference]),
classInfo: XPCOMUtils.generateCI({ classInfo: XPCOMUtils.generateCI({
classID: Components.ID("{bc076ea0-609b-4d8f-83d7-5af7cbdc3bb2}"), classID: Components.ID("{bc076ea0-609b-4d8f-83d7-5af7cbdc3bb2}"),

View File

@ -219,7 +219,7 @@ NetworkStatsManager.prototype = {
return null; return null;
} }
this.initHelper(aWindow, ["NetworkStats:Get:Return", this.initDOMRequestHelper(aWindow, ["NetworkStats:Get:Return",
"NetworkStats:Clear:Return"]); "NetworkStats:Clear:Return"]);
}, },
@ -232,7 +232,8 @@ NetworkStatsManager.prototype = {
classID : NETWORKSTATSMANAGER_CID, classID : NETWORKSTATSMANAGER_CID,
QueryInterface : XPCOMUtils.generateQI([nsIDOMMozNetworkStatsManager, QueryInterface : XPCOMUtils.generateQI([nsIDOMMozNetworkStatsManager,
Ci.nsIDOMGlobalPropertyInitializer]), Ci.nsIDOMGlobalPropertyInitializer,
Ci.nsISupportsWeakReference]),
classInfo : XPCOMUtils.generateCI({classID: NETWORKSTATSMANAGER_CID, classInfo : XPCOMUtils.generateCI({classID: NETWORKSTATSMANAGER_CID,
contractID: NETWORKSTATSMANAGER_CONTRACTID, contractID: NETWORKSTATSMANAGER_CONTRACTID,

View File

@ -31,7 +31,8 @@ PaymentContentHelper.prototype = {
__proto__: DOMRequestIpcHelper.prototype, __proto__: DOMRequestIpcHelper.prototype,
QueryInterface: XPCOMUtils.generateQI([Ci.nsINavigatorPayment, QueryInterface: XPCOMUtils.generateQI([Ci.nsINavigatorPayment,
Ci.nsIDOMGlobalPropertyInitializer]), Ci.nsIDOMGlobalPropertyInitializer,
Ci.nsISupportsWeakReference]),
classID: PAYMENTCONTENTHELPER_CID, classID: PAYMENTCONTENTHELPER_CID,
classInfo: XPCOMUtils.generateCI({ classInfo: XPCOMUtils.generateCI({
classID: PAYMENTCONTENTHELPER_CID, classID: PAYMENTCONTENTHELPER_CID,
@ -78,7 +79,7 @@ PaymentContentHelper.prototype = {
init: function(aWindow) { init: function(aWindow) {
this._window = aWindow; this._window = aWindow;
this.initHelper(aWindow, PAYMENT_IPC_MSG_NAMES); this.initDOMRequestHelper(aWindow, PAYMENT_IPC_MSG_NAMES);
return this.pay.bind(this); return this.pay.bind(this);
}, },

View File

@ -34,7 +34,8 @@ Push.prototype = {
classID : PUSH_CID, classID : PUSH_CID,
QueryInterface : XPCOMUtils.generateQI([Ci.nsIDOMGlobalPropertyInitializer]), QueryInterface : XPCOMUtils.generateQI([Ci.nsIDOMGlobalPropertyInitializer,
Ci.nsISupportsWeakReference]),
init: function(aWindow) { init: function(aWindow) {
debug("init()"); debug("init()");
@ -58,9 +59,7 @@ Push.prototype = {
if (perm != Ci.nsIPermissionManager.ALLOW_ACTION) if (perm != Ci.nsIPermissionManager.ALLOW_ACTION)
return null; return null;
this.initHelper(aWindow, []); this.initDOMRequestHelper(aWindow, [
this.initMessageListener([
"PushService:Register:OK", "PushService:Register:OK",
"PushService:Register:KO", "PushService:Register:KO",
"PushService:Unregister:OK", "PushService:Unregister:OK",

View File

@ -375,8 +375,7 @@ function RILContentHelper() {
}; };
this.voicemailInfo = new VoicemailInfo(); this.voicemailInfo = new VoicemailInfo();
this.initRequests(); this.initDOMRequestHelper(/* aWindow */ null, RIL_IPC_MSG_NAMES);
this.initMessageListener(RIL_IPC_MSG_NAMES);
this._windowsMap = []; this._windowsMap = [];
Services.obs.addObserver(this, "xpcom-shutdown", false); Services.obs.addObserver(this, "xpcom-shutdown", false);
} }
@ -389,7 +388,8 @@ RILContentHelper.prototype = {
Ci.nsIVoicemailProvider, Ci.nsIVoicemailProvider,
Ci.nsITelephonyProvider, Ci.nsITelephonyProvider,
Ci.nsIIccProvider, Ci.nsIIccProvider,
Ci.nsIObserver]), Ci.nsIObserver,
Ci.nsISupportsWeakReference]),
classID: RILCONTENTHELPER_CID, classID: RILCONTENTHELPER_CID,
classInfo: XPCOMUtils.generateCI({classID: RILCONTENTHELPER_CID, classInfo: XPCOMUtils.generateCI({classID: RILCONTENTHELPER_CID,
classDescription: "RILContentHelper", classDescription: "RILContentHelper",
@ -1236,7 +1236,7 @@ RILContentHelper.prototype = {
observe: function observe(subject, topic, data) { observe: function observe(subject, topic, data) {
if (topic == "xpcom-shutdown") { if (topic == "xpcom-shutdown") {
this.removeMessageListener(); this.destroyDOMRequestHelper();
Services.obs.removeObserver(this, "xpcom-shutdown"); Services.obs.removeObserver(this, "xpcom-shutdown");
} }
}, },

View File

@ -15,8 +15,9 @@ dictionary SocketsDict {
}; };
dictionary HttpConnInfoDict { dictionary HttpConnInfoDict {
sequence<unsigned long> rtt; sequence<unsigned long> rtt;
sequence<unsigned long> ttl; sequence<unsigned long> ttl;
sequence<DOMString> protocolVersion;
}; };
dictionary HttpConnDict { dictionary HttpConnDict {

View File

@ -56,7 +56,8 @@ DOMWifiManager.prototype = {
flags: Ci.nsIClassInfo.DOM_OBJECT}), flags: Ci.nsIClassInfo.DOM_OBJECT}),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMWifiManager, QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMWifiManager,
Ci.nsIDOMGlobalPropertyInitializer]), Ci.nsIDOMGlobalPropertyInitializer,
Ci.nsISupportsWeakReference]),
// nsIDOMGlobalPropertyInitializer implementation // nsIDOMGlobalPropertyInitializer implementation
init: function(aWindow) { init: function(aWindow) {
@ -93,7 +94,7 @@ DOMWifiManager.prototype = {
"WifiManager:onwpstimeout", "WifiManager:onwpsfail", "WifiManager:onwpstimeout", "WifiManager:onwpsfail",
"WifiManager:onwpsoverlap", "WifiManager:connectionInfoUpdate", "WifiManager:onwpsoverlap", "WifiManager:connectionInfoUpdate",
"WifiManager:onconnectingfailed"]; "WifiManager:onconnectingfailed"];
this.initHelper(aWindow, messages); this.initDOMRequestHelper(aWindow, messages);
this._mm = Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsISyncMessageSender); this._mm = Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsISyncMessageSender);
var state = this._mm.sendSyncMessage("WifiManager:getState")[0]; var state = this._mm.sendSyncMessage("WifiManager:getState")[0];

View File

@ -156,13 +156,13 @@ DataSourceSurfaceD2D::DataSourceSurfaceD2D(SourceSurfaceD2D* aSourceSurface)
return; return;
} }
D2D1_RENDER_TARGET_PROPERTIES rtProps = D2D1::RenderTargetProperties( D2D1_RENDER_TARGET_PROPERTIES rtProps = D2D1::RenderTargetProperties(
D2D1_RENDER_TARGET_TYPE_DEFAULT, D2D1_RENDER_TARGET_TYPE_DEFAULT,
D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED)); D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED));
RefPtr<ID2D1RenderTarget> renderTarget; RefPtr<ID2D1RenderTarget> renderTarget;
hr = DrawTargetD2D::factory()->CreateDxgiSurfaceRenderTarget(dxgiSurface, hr = DrawTargetD2D::factory()->CreateDxgiSurfaceRenderTarget(dxgiSurface,
&rtProps, &rtProps,
byRef(renderTarget)); byRef(renderTarget));
if (FAILED(hr)) { if (FAILED(hr)) {
gfxWarning() << "Failed to create render target. Code: " << hr; gfxWarning() << "Failed to create render target. Code: " << hr;

View File

@ -1,7 +1,7 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "SanityChecks.h" #include "SanityChecks.h"

View File

@ -1,7 +1,7 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#pragma once #pragma once

View File

@ -1,7 +1,7 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "TestBase.h" #include "TestBase.h"

View File

@ -26,7 +26,7 @@ class TestBase
public: public:
TestBase() {} TestBase() {}
typedef void (TestBase::*TestCall)(); typedef void (TestBase::*TestCall)();
int RunTests(int *aFailures); int RunTests(int *aFailures);

View File

@ -1,7 +1,7 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "TestDrawTargetBase.h" #include "TestDrawTargetBase.h"
#include <sstream> #include <sstream>

View File

@ -1,7 +1,7 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#pragma once #pragma once

View File

@ -1,20 +1,20 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "TestDrawTargetD2D.h" #include "TestDrawTargetD2D.h"
using namespace mozilla::gfx; using namespace mozilla::gfx;
TestDrawTargetD2D::TestDrawTargetD2D() TestDrawTargetD2D::TestDrawTargetD2D()
{ {
::D3D10CreateDevice1(nullptr, ::D3D10CreateDevice1(nullptr,
D3D10_DRIVER_TYPE_HARDWARE, D3D10_DRIVER_TYPE_HARDWARE,
nullptr, nullptr,
D3D10_CREATE_DEVICE_BGRA_SUPPORT | D3D10_CREATE_DEVICE_BGRA_SUPPORT |
D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS, D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS,
D3D10_FEATURE_LEVEL_10_0, D3D10_FEATURE_LEVEL_10_0,
D3D10_1_SDK_VERSION, D3D10_1_SDK_VERSION,
byRef(mDevice)); byRef(mDevice));
Factory::SetDirect3D10Device(mDevice); Factory::SetDirect3D10Device(mDevice);

View File

@ -1,7 +1,7 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#pragma once #pragma once
@ -16,4 +16,4 @@ public:
private: private:
mozilla::RefPtr<ID3D10Device1> mDevice; mozilla::RefPtr<ID3D10Device1> mDevice;
}; };

View File

@ -1,7 +1,7 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "TestPoint.h" #include "TestPoint.h"

View File

@ -1,7 +1,7 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#pragma once #pragma once

View File

@ -1,7 +1,7 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "TestScaling.h" #include "TestScaling.h"

View File

@ -1,7 +1,7 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#pragma once #pragma once

View File

@ -17,7 +17,21 @@ using namespace mozilla::gfx;
namespace layers { namespace layers {
class TextureSourceBasic : public TextureHost /**
* A texture source interface that can be used by the software Compositor.
*/
class TextureSourceBasic
{
public:
virtual ~TextureSourceBasic() {}
virtual gfx::SourceSurface* GetSurface() = 0;
};
/**
* Texture source and host implementaion for software compositing.
*/
class TextureHostBasic : public TextureHost
, public TextureSourceBasic
{ {
public: public:
virtual IntSize GetSize() const MOZ_OVERRIDE { return mSize; } virtual IntSize GetSize() const MOZ_OVERRIDE { return mSize; }
@ -31,7 +45,7 @@ public:
mCompositor = static_cast<BasicCompositor*>(aCompositor); mCompositor = static_cast<BasicCompositor*>(aCompositor);
} }
virtual const char *Name() { return "TextureSourceBasic"; } virtual const char *Name() { return "TextureHostBasic"; }
protected: protected:
virtual void UpdateImpl(const SurfaceDescriptor& aImage, virtual void UpdateImpl(const SurfaceDescriptor& aImage,
@ -91,7 +105,7 @@ DeserializerToPlanarYCbCrImageData(YCbCrImageDataDeserializer& aDeserializer, Pl
aData.mPicSize = aDeserializer.GetYSize(); aData.mPicSize = aDeserializer.GetYSize();
} }
class YCbCrTextureHostBasic : public TextureSourceBasic class YCbCrTextureHostBasic : public TextureHostBasic
{ {
public: public:
virtual void UpdateImpl(const SurfaceDescriptor& aImage, virtual void UpdateImpl(const SurfaceDescriptor& aImage,
@ -160,7 +174,7 @@ CreateBasicTextureHost(SurfaceDescriptorType aDescriptorType,
MOZ_ASSERT(aDescriptorType == SurfaceDescriptor::TShmem || MOZ_ASSERT(aDescriptorType == SurfaceDescriptor::TShmem ||
aDescriptorType == SurfaceDescriptor::TMemoryImage, aDescriptorType == SurfaceDescriptor::TMemoryImage,
"We can only support Shmem currently"); "We can only support Shmem currently");
return new TextureSourceBasic(); return new TextureHostBasic();
} }
BasicCompositor::BasicCompositor(nsIWidget *aWidget) BasicCompositor::BasicCompositor(nsIWidget *aWidget)

View File

@ -1,7 +1,7 @@
/* This Source Code Form is subject to the terms of the Mozilla Public /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#if 0 #if 0
// //
// FX Version: fx_4_0 // FX Version: fx_4_0

View File

@ -1,7 +1,7 @@
/* This Source Code Form is subject to the terms of the Mozilla Public /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#if 0 #if 0
// //
// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111 // Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111

View File

@ -75,8 +75,10 @@ ShaderProgramFromTargetAndFormat(GLenum aTarget,
{ {
switch(aTarget) { switch(aTarget) {
case LOCAL_GL_TEXTURE_EXTERNAL: case LOCAL_GL_TEXTURE_EXTERNAL:
MOZ_ASSERT(aFormat == gfx::FORMAT_R8G8B8A8);
return RGBALayerExternalProgramType; return RGBALayerExternalProgramType;
case LOCAL_GL_TEXTURE_RECTANGLE_ARB: case LOCAL_GL_TEXTURE_RECTANGLE_ARB:
MOZ_ASSERT(aFormat == gfx::FORMAT_R8G8B8A8);
return RGBARectLayerProgramType; return RGBARectLayerProgramType;
default: default:
return ShaderProgramFromSurfaceFormat(aFormat); return ShaderProgramFromSurfaceFormat(aFormat);

View File

@ -110,6 +110,107 @@ TEST(AsyncPanZoomController, SimpleTransform) {
EXPECT_EQ(viewTransformOut, ViewTransform()); EXPECT_EQ(viewTransformOut, ViewTransform());
} }
TEST(AsyncPanZoomController, ComplexTransform) {
TimeStamp testStartTime = TimeStamp::Now();
AsyncPanZoomController::SetFrameTime(testStartTime);
// This test assumes there is a page that gets rendered to
// two layers. In CSS pixels, the first layer is 50x50 and
// the second layer is 25x50. The widget scale factor is 3.0
// and the presShell resolution is 2.0. Therefore, these layers
// end up being 300x300 and 150x300 in layer pixels.
//
// The second (child) layer has an additional CSS transform that
// stretches it by 2.0 on the x-axis. Therefore, after applying
// CSS transforms, the two layers are the same size in screen
// pixels.
//
// The screen itself is 24x24 in screen pixels (therefore 4x4 in
// CSS pixels). The displayport is 1 extra CSS pixel on all
// sides.
nsRefPtr<MockContentController> mcc = new MockContentController();
nsRefPtr<AsyncPanZoomController> apzc = new AsyncPanZoomController(mcc);
const char* layerTreeSyntax = "c(c)";
// LayerID 0 1
nsIntRegion layerVisibleRegion[] = {
nsIntRegion(nsIntRect(0, 0, 300, 300)),
nsIntRegion(nsIntRect(0, 0, 150, 300)),
};
gfx3DMatrix transforms[] = {
gfx3DMatrix(),
gfx3DMatrix(),
};
transforms[0].ScalePost(0.5f, 0.5f, 1.0f); // this results from the 2.0 resolution on the root layer
transforms[1].ScalePost(2.0f, 1.0f, 1.0f); // this is the 2.0 x-axis CSS transform on the child layer
nsTArray<nsRefPtr<Layer> > layers;
nsRefPtr<LayerManager> lm;
nsRefPtr<Layer> root = CreateLayerTree(layerTreeSyntax, layerVisibleRegion, transforms, lm, layers);
FrameMetrics metrics;
metrics.mCompositionBounds = ScreenIntRect(0, 0, 24, 24);
metrics.mDisplayPort = CSSRect(-1, -1, 6, 6);
metrics.mViewport = CSSRect(0, 0, 4, 4);
metrics.mScrollOffset = CSSPoint(10, 10);
metrics.mScrollableRect = CSSRect(0, 0, 50, 50);
metrics.mResolution = LayoutDeviceToLayerScale(2);
metrics.mZoom = ScreenToScreenScale(1);
metrics.mDevPixelsPerCSSPixel = CSSToLayoutDeviceScale(3);
metrics.mScrollId = FrameMetrics::ROOT_SCROLL_ID;
FrameMetrics childMetrics = metrics;
childMetrics.mScrollId = FrameMetrics::START_SCROLL_ID;
layers[0]->AsContainerLayer()->SetFrameMetrics(metrics);
layers[1]->AsContainerLayer()->SetFrameMetrics(childMetrics);
ScreenPoint pointOut;
ViewTransform viewTransformOut;
// Both the parent and child layer should behave exactly the same here, because
// the CSS transform on the child layer does not affect the SampleContentTransformForFrame code
// initial transform
apzc->NotifyLayersUpdated(metrics, true);
apzc->SampleContentTransformForFrame(testStartTime, layers[0]->AsContainerLayer(), &viewTransformOut, pointOut);
EXPECT_EQ(ViewTransform(LayerPoint(), LayoutDeviceToScreenScale(2)), viewTransformOut);
EXPECT_EQ(ScreenPoint(60, 60), pointOut);
apzc->NotifyLayersUpdated(childMetrics, true);
apzc->SampleContentTransformForFrame(testStartTime, layers[1]->AsContainerLayer(), &viewTransformOut, pointOut);
EXPECT_EQ(ViewTransform(LayerPoint(), LayoutDeviceToScreenScale(2)), viewTransformOut);
EXPECT_EQ(ScreenPoint(60, 60), pointOut);
// do an async scroll by 5 pixels and check the transform
metrics.mScrollOffset += CSSPoint(5, 0);
apzc->NotifyLayersUpdated(metrics, true);
apzc->SampleContentTransformForFrame(testStartTime, layers[0]->AsContainerLayer(), &viewTransformOut, pointOut);
EXPECT_EQ(ViewTransform(LayerPoint(-30, 0), LayoutDeviceToScreenScale(2)), viewTransformOut);
EXPECT_EQ(ScreenPoint(90, 60), pointOut);
childMetrics.mScrollOffset += CSSPoint(5, 0);
apzc->NotifyLayersUpdated(childMetrics, true);
apzc->SampleContentTransformForFrame(testStartTime, layers[1]->AsContainerLayer(), &viewTransformOut, pointOut);
EXPECT_EQ(ViewTransform(LayerPoint(-30, 0), LayoutDeviceToScreenScale(2)), viewTransformOut);
EXPECT_EQ(ScreenPoint(90, 60), pointOut);
// do an async zoom of 1.5x and check the transform
metrics.mZoom.scale *= 1.5f;
apzc->NotifyLayersUpdated(metrics, true);
apzc->SampleContentTransformForFrame(testStartTime, layers[0]->AsContainerLayer(), &viewTransformOut, pointOut);
EXPECT_EQ(ViewTransform(LayerPoint(-30, 0), LayoutDeviceToScreenScale(3)), viewTransformOut);
EXPECT_EQ(ScreenPoint(135, 90), pointOut);
childMetrics.mZoom.scale *= 1.5f;
apzc->NotifyLayersUpdated(childMetrics, true);
apzc->SampleContentTransformForFrame(testStartTime, layers[0]->AsContainerLayer(), &viewTransformOut, pointOut);
EXPECT_EQ(ViewTransform(LayerPoint(-30, 0), LayoutDeviceToScreenScale(3)), viewTransformOut);
EXPECT_EQ(ScreenPoint(135, 90), pointOut);
}
TEST(AsyncPanZoomController, Pan) { TEST(AsyncPanZoomController, Pan) {
TimeStamp testStartTime = TimeStamp::Now(); TimeStamp testStartTime = TimeStamp::Now();
AsyncPanZoomController::SetFrameTime(testStartTime); AsyncPanZoomController::SetFrameTime(testStartTime);

View File

@ -1419,409 +1419,14 @@ gfxFontUtils::ReadNames(hb_blob_t *aNameTable, uint32_t aNameID,
#ifdef XP_WIN #ifdef XP_WIN
// Embedded OpenType (EOT) handling
// needed for dealing with downloadable fonts on Windows
//
// EOT version 0x00020001
// based on http://www.w3.org/Submission/2008/SUBM-EOT-20080305/
//
// EOT header consists of a fixed-size portion containing general font
// info, followed by a variable-sized portion containing name data,
// followed by the actual TT/OT font data (non-byte values are always
// stored in big-endian format)
//
// EOT header is stored in *little* endian order!!
#pragma pack(1)
struct EOTFixedHeader {
uint32_t eotSize; // Total structure length in PRUint8s (including string and font data)
uint32_t fontDataSize; // Length of the OpenType font (FontData) in PRUint8s
uint32_t version; // Version number of this format - 0x00010000
uint32_t flags; // Processing Flags
uint8_t panose[10]; // The PANOSE value for this font - See http://www.microsoft.com/typography/otspec/os2.htm#pan
uint8_t charset; // In Windows this is derived from TEXTMETRIC.tmCharSet. This value specifies the character set of the font. DEFAULT_CHARSET (0x01) indicates no preference. - See http://msdn2.microsoft.com/en-us/library/ms534202.aspx
uint8_t italic; // If the bit for ITALIC is set in OS/2.fsSelection, the value will be 0x01 - See http://www.microsoft.com/typography/otspec/os2.htm#fss
uint32_t weight; // The weight value for this font - See http://www.microsoft.com/typography/otspec/os2.htm#wtc
uint16_t fsType; // Type flags that provide information about embedding permissions - See http://www.microsoft.com/typography/otspec/os2.htm#fst
uint16_t magicNumber; // Magic number for EOT file - 0x504C. Used to check for data corruption.
uint32_t unicodeRange1; // OS/2.UnicodeRange1 (bits 0-31) - See http://www.microsoft.com/typography/otspec/os2.htm#ur
uint32_t unicodeRange2; // OS/2.UnicodeRange2 (bits 32-63) - See http://www.microsoft.com/typography/otspec/os2.htm#ur
uint32_t unicodeRange3; // OS/2.UnicodeRange3 (bits 64-95) - See http://www.microsoft.com/typography/otspec/os2.htm#ur
uint32_t unicodeRange4; // OS/2.UnicodeRange4 (bits 96-127) - See http://www.microsoft.com/typography/otspec/os2.htm#ur
uint32_t codePageRange1; // CodePageRange1 (bits 0-31) - See http://www.microsoft.com/typography/otspec/os2.htm#cpr
uint32_t codePageRange2; // CodePageRange2 (bits 32-63) - See http://www.microsoft.com/typography/otspec/os2.htm#cpr
uint32_t checkSumAdjustment; // head.CheckSumAdjustment - See http://www.microsoft.com/typography/otspec/head.htm
uint32_t reserved[4]; // Reserved - must be 0
uint16_t padding1; // Padding to maintain long alignment. Padding value must always be set to 0x0000.
enum {
EOT_VERSION = 0x00020001,
EOT_MAGIC_NUMBER = 0x504c,
EOT_DEFAULT_CHARSET = 0x01,
EOT_EMBED_PRINT_PREVIEW = 0x0004,
EOT_FAMILY_NAME_INDEX = 0, // order of names in variable portion of EOT header
EOT_STYLE_NAME_INDEX = 1,
EOT_VERSION_NAME_INDEX = 2,
EOT_FULL_NAME_INDEX = 3,
EOT_NUM_NAMES = 4
};
};
#pragma pack()
// EOT headers are only used on Windows
// EOT variable-sized header (version 0x00020001 - contains 4 name
// fields, each with the structure):
//
// // number of bytes in the name array
// uint16_t size;
// // array of UTF-16 chars, total length = <size> bytes
// // note: english version of name record string
// uint8_t name[size];
//
// This structure is used for the following names, each separated by two
// bytes of padding (always 0 with no padding after the rootString):
//
// familyName - based on name ID = 1
// styleName - based on name ID = 2
// versionName - based on name ID = 5
// fullName - based on name ID = 4
// rootString - used to restrict font usage to a specific domain
//
#if DEBUG
static void
DumpEOTHeader(uint8_t *aHeader, uint32_t aHeaderLen)
{
uint32_t offset = 0;
uint8_t *ch = aHeader;
printf("\n\nlen == %d\n\n", aHeaderLen);
while (offset < aHeaderLen) {
printf("%7.7x ", offset);
int i;
for (i = 0; i < 16; i++) {
printf("%2.2x ", *ch++);
}
printf("\n");
offset += 16;
}
}
#endif
nsresult
gfxFontUtils::MakeEOTHeader(const uint8_t *aFontData, uint32_t aFontDataLength,
FallibleTArray<uint8_t> *aHeader,
FontDataOverlay *aOverlay)
{
NS_ASSERTION(aFontData && aFontDataLength != 0, "null font data");
NS_ASSERTION(aHeader, "null header");
NS_ASSERTION(aHeader->Length() == 0, "non-empty header passed in");
NS_ASSERTION(aOverlay, "null font overlay struct passed in");
aOverlay->overlaySrc = 0;
if (!aHeader->AppendElements(sizeof(EOTFixedHeader)))
return NS_ERROR_OUT_OF_MEMORY;
EOTFixedHeader *eotHeader = reinterpret_cast<EOTFixedHeader*>(aHeader->Elements());
memset(eotHeader, 0, sizeof(EOTFixedHeader));
uint32_t fontDataSize = aFontDataLength;
// set up header fields
eotHeader->fontDataSize = fontDataSize;
eotHeader->version = EOTFixedHeader::EOT_VERSION;
eotHeader->flags = 0; // don't specify any special processing
eotHeader->charset = EOTFixedHeader::EOT_DEFAULT_CHARSET;
eotHeader->fsType = EOTFixedHeader::EOT_EMBED_PRINT_PREVIEW;
eotHeader->magicNumber = EOTFixedHeader::EOT_MAGIC_NUMBER;
// read in the sfnt header
if (sizeof(SFNTHeader) > aFontDataLength)
return NS_ERROR_FAILURE;
const SFNTHeader *sfntHeader = reinterpret_cast<const SFNTHeader*>(aFontData);
if (!IsValidSFNTVersion(sfntHeader->sfntVersion))
return NS_ERROR_FAILURE;
// iterate through the table headers to find the head, name and OS/2 tables
bool foundHead = false, foundOS2 = false, foundName = false, foundGlyphs = false;
uint32_t headOffset, headLen, nameOffset, nameLen, os2Offset, os2Len;
uint32_t i, numTables;
numTables = sfntHeader->numTables;
if (sizeof(SFNTHeader) + sizeof(TableDirEntry) * numTables > aFontDataLength)
return NS_ERROR_FAILURE;
uint64_t dataLength(aFontDataLength);
// table directory entries begin immediately following SFNT header
const TableDirEntry *dirEntry = reinterpret_cast<const TableDirEntry*>(aFontData + sizeof(SFNTHeader));
for (i = 0; i < numTables; i++, dirEntry++) {
// sanity check on offset, length values
if (uint64_t(dirEntry->offset) + uint64_t(dirEntry->length) > dataLength)
return NS_ERROR_FAILURE;
switch (dirEntry->tag) {
case TRUETYPE_TAG('h','e','a','d'):
foundHead = true;
headOffset = dirEntry->offset;
headLen = dirEntry->length;
if (headLen < sizeof(HeadTable))
return NS_ERROR_FAILURE;
break;
case TRUETYPE_TAG('n','a','m','e'):
foundName = true;
nameOffset = dirEntry->offset;
nameLen = dirEntry->length;
break;
case TRUETYPE_TAG('O','S','/','2'):
foundOS2 = true;
os2Offset = dirEntry->offset;
os2Len = dirEntry->length;
break;
case TRUETYPE_TAG('g','l','y','f'): // TrueType-style quadratic glyph table
foundGlyphs = true;
break;
case TRUETYPE_TAG('C','F','F',' '): // PS-style cubic glyph table
foundGlyphs = true;
break;
default:
break;
}
if (foundHead && foundName && foundOS2 && foundGlyphs)
break;
}
// require these three tables on Windows
if (!foundHead || !foundName || !foundOS2)
return NS_ERROR_FAILURE;
// at this point, all table offset/length values are within bounds
// read in the data from those tables
// -- head table data
const HeadTable *headData = reinterpret_cast<const HeadTable*>(aFontData + headOffset);
if (headData->tableVersionNumber != HeadTable::HEAD_VERSION ||
headData->magicNumber != HeadTable::HEAD_MAGIC_NUMBER) {
return NS_ERROR_FAILURE;
}
eotHeader->checkSumAdjustment = headData->checkSumAdjustment;
// -- name table data
// -- first, read name table header
const NameHeader *nameHeader = reinterpret_cast<const NameHeader*>(aFontData + nameOffset);
uint32_t nameStringsBase = uint32_t(nameHeader->stringOffset);
uint32_t nameCount = nameHeader->count;
// -- sanity check the number of name records
if (uint64_t(nameCount) * sizeof(NameRecord) + uint64_t(nameOffset) > dataLength)
return NS_ERROR_FAILURE;
// bug 496573 -- dummy names in case the font didn't contain English names
const nsString dummyNames[EOTFixedHeader::EOT_NUM_NAMES] = {
NS_LITERAL_STRING("Unknown"),
NS_LITERAL_STRING("Regular"),
EmptyString(),
dummyNames[EOTFixedHeader::EOT_FAMILY_NAME_INDEX]
};
// -- iterate through name records, look for specific name ids with
// matching platform/encoding/etc. and store offset/lengths
NameRecordData names[EOTFixedHeader::EOT_NUM_NAMES] = {0};
const NameRecord *nameRecord = reinterpret_cast<const NameRecord*>(aFontData + nameOffset + sizeof(NameHeader));
uint32_t needNames = (1 << EOTFixedHeader::EOT_FAMILY_NAME_INDEX) |
(1 << EOTFixedHeader::EOT_STYLE_NAME_INDEX) |
(1 << EOTFixedHeader::EOT_FULL_NAME_INDEX) |
(1 << EOTFixedHeader::EOT_VERSION_NAME_INDEX);
for (i = 0; i < nameCount; i++, nameRecord++) {
// looking for Microsoft English US name strings, skip others
if (uint32_t(nameRecord->platformID) != PLATFORM_ID_MICROSOFT ||
uint32_t(nameRecord->encodingID) != ENCODING_ID_MICROSOFT_UNICODEBMP ||
uint32_t(nameRecord->languageID) != LANG_ID_MICROSOFT_EN_US)
continue;
uint32_t index;
switch ((uint32_t)nameRecord->nameID) {
case NAME_ID_FAMILY:
index = EOTFixedHeader::EOT_FAMILY_NAME_INDEX;
break;
case NAME_ID_STYLE:
index = EOTFixedHeader::EOT_STYLE_NAME_INDEX;
break;
case NAME_ID_FULL:
index = EOTFixedHeader::EOT_FULL_NAME_INDEX;
break;
case NAME_ID_VERSION:
index = EOTFixedHeader::EOT_VERSION_NAME_INDEX;
break;
default:
continue;
}
names[index].offset = nameRecord->offset;
names[index].length = nameRecord->length;
needNames &= ~(1 << index);
if (needNames == 0)
break;
}
// -- expand buffer if needed to include variable-length portion
uint32_t eotVariableLength = 0;
for (i = 0; i < EOTFixedHeader::EOT_NUM_NAMES; i++) {
if (!(needNames & (1 << i))) {
eotVariableLength += names[i].length & (~1);
} else {
eotVariableLength += dummyNames[i].Length() * sizeof(PRUnichar);
}
}
eotVariableLength += EOTFixedHeader::EOT_NUM_NAMES * (2 /* size */
+ 2 /* padding */) +
2 /* null root string size */;
if (!aHeader->AppendElements(eotVariableLength))
return NS_ERROR_OUT_OF_MEMORY;
// append the string data to the end of the EOT header
uint8_t *eotEnd = aHeader->Elements() + sizeof(EOTFixedHeader);
uint32_t strOffset, strLen;
for (i = 0; i < EOTFixedHeader::EOT_NUM_NAMES; i++) {
if (!(needNames & (1 << i))) {
uint32_t namelen = names[i].length;
uint32_t nameoff = names[i].offset; // offset from base of string storage
// sanity check the name string location
if (uint64_t(nameOffset) + uint64_t(nameStringsBase) +
uint64_t(nameoff) + uint64_t(namelen) > dataLength) {
return NS_ERROR_FAILURE;
}
strOffset = nameOffset + nameStringsBase + nameoff;
// output 2-byte str size
strLen = namelen & (~1); // UTF-16 string len must be even
*((uint16_t*) eotEnd) = uint16_t(strLen);
eotEnd += 2;
// length is number of UTF-16 chars, not bytes
CopySwapUTF16(reinterpret_cast<const uint16_t*>(aFontData + strOffset),
reinterpret_cast<uint16_t*>(eotEnd),
(strLen >> 1));
} else {
// bug 496573 -- English names are not present.
// supply an artificial one.
strLen = dummyNames[i].Length() * sizeof(PRUnichar);
*((uint16_t*) eotEnd) = uint16_t(strLen);
eotEnd += 2;
memcpy(eotEnd, dummyNames[i].BeginReading(), strLen);
}
eotEnd += strLen;
// add 2-byte zero padding to the end of each string
*eotEnd++ = 0;
*eotEnd++ = 0;
// Note: Microsoft's WEFT tool produces name strings which
// include an extra null at the end of each string, in addition
// to the 2-byte zero padding that separates the string fields.
// Don't think this is important to imitate...
}
// append null root string size
*eotEnd++ = 0;
*eotEnd++ = 0;
NS_ASSERTION(eotEnd == aHeader->Elements() + aHeader->Length(),
"header length calculation incorrect");
// bug 496573 -- fonts with a fullname that does not begin with the
// family name cause the EOT font loading API to hiccup
uint32_t famOff = names[EOTFixedHeader::EOT_FAMILY_NAME_INDEX].offset;
uint32_t famLen = names[EOTFixedHeader::EOT_FAMILY_NAME_INDEX].length;
uint32_t fullOff = names[EOTFixedHeader::EOT_FULL_NAME_INDEX].offset;
uint32_t fullLen = names[EOTFixedHeader::EOT_FULL_NAME_INDEX].length;
const uint8_t *nameStrings = aFontData + nameOffset + nameStringsBase;
// assure that the start of the fullname matches the family name
if (famLen <= fullLen
&& memcmp(nameStrings + famOff, nameStrings + fullOff, famLen)) {
aOverlay->overlaySrc = nameOffset + nameStringsBase + famOff;
aOverlay->overlaySrcLen = famLen;
aOverlay->overlayDest = nameOffset + nameStringsBase + fullOff;
}
// -- OS/2 table data
const OS2Table *os2Data = reinterpret_cast<const OS2Table*>(aFontData + os2Offset);
memcpy(eotHeader->panose, os2Data->panose, sizeof(eotHeader->panose));
eotHeader->italic = (uint16_t) os2Data->fsSelection & 0x01;
eotHeader->weight = os2Data->usWeightClass;
eotHeader->unicodeRange1 = os2Data->unicodeRange1;
eotHeader->unicodeRange2 = os2Data->unicodeRange2;
eotHeader->unicodeRange3 = os2Data->unicodeRange3;
eotHeader->unicodeRange4 = os2Data->unicodeRange4;
eotHeader->codePageRange1 = os2Data->codePageRange1;
eotHeader->codePageRange2 = os2Data->codePageRange2;
eotHeader->eotSize = aHeader->Length() + fontDataSize;
// DumpEOTHeader(aHeader->Elements(), aHeader->Length());
return NS_OK;
}
/* static */ /* static */
bool bool
gfxFontUtils::IsCffFont(const uint8_t* aFontData, bool& hasVertical) gfxFontUtils::IsCffFont(const uint8_t* aFontData)
{ {
// this is only called after aFontData has passed basic validation, // this is only called after aFontData has passed basic validation,
// so we know there is enough data present to allow us to read the version! // so we know there is enough data present to allow us to read the version!
const SFNTHeader *sfntHeader = reinterpret_cast<const SFNTHeader*>(aFontData); const SFNTHeader *sfntHeader = reinterpret_cast<const SFNTHeader*>(aFontData);
uint32_t i;
uint32_t numTables = sfntHeader->numTables;
const TableDirEntry *dirEntry =
reinterpret_cast<const TableDirEntry*>(aFontData + sizeof(SFNTHeader));
hasVertical = false;
for (i = 0; i < numTables; i++, dirEntry++) {
if (dirEntry->tag == TRUETYPE_TAG('v','h','e','a')) {
hasVertical = true;
break;
}
}
return (sfntHeader->sfntVersion == TRUETYPE_TAG('O','T','T','O')); return (sfntHeader->sfntVersion == TRUETYPE_TAG('O','T','T','O'));
} }
#endif #endif

View File

@ -800,21 +800,10 @@ public:
uint32_t aUnicode, uint32_t aVarSelector = 0); uint32_t aUnicode, uint32_t aVarSelector = 0);
#ifdef XP_WIN #ifdef XP_WIN
// given a TrueType/OpenType data file, produce a EOT-format header
// for use with Windows T2Embed API AddFontResource type API's
// effectively hide existing fonts with matching names aHeaderLen is
// the size of the header buffer on input, the actual size of the
// EOT header on output
static nsresult
MakeEOTHeader(const uint8_t *aFontData, uint32_t aFontDataLength,
FallibleTArray<uint8_t> *aHeader, FontDataOverlay *aOverlay);
// determine whether a font (which has already been sanitized, so is known // determine whether a font (which has already been sanitized, so is known
// to be a valid sfnt) is CFF format rather than TrueType // to be a valid sfnt) is CFF format rather than TrueType
static bool static bool
IsCffFont(const uint8_t* aFontData, bool& hasVertical); IsCffFont(const uint8_t* aFontData);
#endif #endif
// determine the format of font data // determine the format of font data

View File

@ -31,7 +31,6 @@
#include "mozilla/Telemetry.h" #include "mozilla/Telemetry.h"
#include <usp10.h> #include <usp10.h>
#include <t2embapi.h>
using namespace mozilla; using namespace mozilla;
@ -66,58 +65,26 @@ BuildKeyNameFromFontName(nsAString &aName)
// Implementation of gfxPlatformFontList for Win32 GDI, // Implementation of gfxPlatformFontList for Win32 GDI,
// using GDI font enumeration APIs to get the list of fonts // using GDI font enumeration APIs to get the list of fonts
typedef LONG
(WINAPI *TTLoadEmbeddedFontProc)(HANDLE* phFontReference, ULONG ulFlags,
ULONG* pulPrivStatus, ULONG ulPrivs,
ULONG* pulStatus,
READEMBEDPROC lpfnReadFromStream,
LPVOID lpvReadStream,
LPWSTR szWinFamilyName,
LPSTR szMacFamilyName,
TTLOADINFO* pTTLoadInfo);
typedef LONG
(WINAPI *TTDeleteEmbeddedFontProc)(HANDLE hFontReference, ULONG ulFlags,
ULONG* pulStatus);
static TTLoadEmbeddedFontProc TTLoadEmbeddedFontPtr = nullptr;
static TTDeleteEmbeddedFontProc TTDeleteEmbeddedFontPtr = nullptr;
class WinUserFontData : public gfxUserFontData { class WinUserFontData : public gfxUserFontData {
public: public:
WinUserFontData(HANDLE aFontRef, bool aIsEmbedded) WinUserFontData(HANDLE aFontRef)
: mFontRef(aFontRef), mIsEmbedded(aIsEmbedded) : mFontRef(aFontRef)
{ } { }
virtual ~WinUserFontData() virtual ~WinUserFontData()
{ {
if (mIsEmbedded) { DebugOnly<BOOL> success;
ULONG pulStatus; success = RemoveFontMemResourceEx(mFontRef);
LONG err;
err = TTDeleteEmbeddedFontPtr(mFontRef, 0, &pulStatus);
#if DEBUG #if DEBUG
if (err != E_NONE) { if (!success) {
char buf[256]; char buf[256];
sprintf(buf, "error deleting embedded font handle (%p) - TTDeleteEmbeddedFont returned %8.8x", mFontRef, err); sprintf(buf, "error deleting font handle (%p) - RemoveFontMemResourceEx failed", mFontRef);
NS_ASSERTION(err == E_NONE, buf); NS_ASSERTION(success, buf);
}
#endif
} else {
DebugOnly<BOOL> success;
success = RemoveFontMemResourceEx(mFontRef);
#if DEBUG
if (!success) {
char buf[256];
sprintf(buf, "error deleting font handle (%p) - RemoveFontMemResourceEx failed", mFontRef);
NS_ASSERTION(success, buf);
}
#endif
} }
#endif
} }
HANDLE mFontRef; HANDLE mFontRef;
bool mIsEmbedded;
}; };
BYTE BYTE
@ -599,8 +566,6 @@ GDIFontFamily::FindStyleVariations()
gfxGDIFontList::gfxGDIFontList() gfxGDIFontList::gfxGDIFontList()
{ {
mFontSubstitutes.Init(50); mFontSubstitutes.Init(50);
InitializeFontEmbeddingProcs();
} }
static void static void
@ -790,104 +755,6 @@ gfxGDIFontList::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
return fe; return fe;
} }
void gfxGDIFontList::InitializeFontEmbeddingProcs()
{
static HMODULE fontlib = LoadLibraryW(L"t2embed.dll");
if (!fontlib)
return;
TTLoadEmbeddedFontPtr = (TTLoadEmbeddedFontProc)
GetProcAddress(fontlib, "TTLoadEmbeddedFont");
TTDeleteEmbeddedFontPtr = (TTDeleteEmbeddedFontProc)
GetProcAddress(fontlib, "TTDeleteEmbeddedFont");
}
// used to control stream read by Windows TTLoadEmbeddedFont API
class EOTFontStreamReader {
public:
EOTFontStreamReader(const uint8_t *aFontData, uint32_t aLength, uint8_t *aEOTHeader,
uint32_t aEOTHeaderLen, FontDataOverlay *aNameOverlay)
: mCurrentChunk(0), mChunkOffset(0)
{
NS_ASSERTION(aFontData, "null font data ptr passed in");
NS_ASSERTION(aEOTHeader, "null EOT header ptr passed in");
NS_ASSERTION(aNameOverlay, "null name overlay struct passed in");
if (aNameOverlay->overlaySrc) {
mNumChunks = 4;
// 0 : EOT header
mDataChunks[0].mData = aEOTHeader;
mDataChunks[0].mLength = aEOTHeaderLen;
// 1 : start of font data to overlayDest
mDataChunks[1].mData = aFontData;
mDataChunks[1].mLength = aNameOverlay->overlayDest;
// 2 : overlay data
mDataChunks[2].mData = aFontData + aNameOverlay->overlaySrc;
mDataChunks[2].mLength = aNameOverlay->overlaySrcLen;
// 3 : rest of font data
mDataChunks[3].mData = aFontData + aNameOverlay->overlayDest + aNameOverlay->overlaySrcLen;
mDataChunks[3].mLength = aLength - aNameOverlay->overlayDest - aNameOverlay->overlaySrcLen;
} else {
mNumChunks = 2;
// 0 : EOT header
mDataChunks[0].mData = aEOTHeader;
mDataChunks[0].mLength = aEOTHeaderLen;
// 1 : font data
mDataChunks[1].mData = aFontData;
mDataChunks[1].mLength = aLength;
}
}
~EOTFontStreamReader()
{
}
struct FontDataChunk {
const uint8_t *mData;
uint32_t mLength;
};
uint32_t mNumChunks;
FontDataChunk mDataChunks[4];
uint32_t mCurrentChunk;
uint32_t mChunkOffset;
unsigned long Read(void *outBuffer, const unsigned long aBytesToRead)
{
uint32_t bytesLeft = aBytesToRead; // bytes left in the out buffer
uint8_t *out = static_cast<uint8_t*> (outBuffer);
while (mCurrentChunk < mNumChunks && bytesLeft) {
FontDataChunk& currentChunk = mDataChunks[mCurrentChunk];
uint32_t bytesToCopy = std::min(bytesLeft,
currentChunk.mLength - mChunkOffset);
memcpy(out, currentChunk.mData + mChunkOffset, bytesToCopy);
bytesLeft -= bytesToCopy;
mChunkOffset += bytesToCopy;
out += bytesToCopy;
NS_ASSERTION(mChunkOffset <= currentChunk.mLength, "oops, buffer overrun");
if (mChunkOffset == currentChunk.mLength) {
mCurrentChunk++;
mChunkOffset = 0;
}
}
return aBytesToRead - bytesLeft;
}
static unsigned long ReadEOTStream(void *aReadStream, void *outBuffer,
const unsigned long aBytesToRead)
{
EOTFontStreamReader *eotReader =
static_cast<EOTFontStreamReader*> (aReadStream);
return eotReader->Read(outBuffer, aBytesToRead);
}
};
gfxFontEntry* gfxFontEntry*
gfxGDIFontList::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry, gfxGDIFontList::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
const uint8_t *aFontData, const uint8_t *aFontData,
@ -904,95 +771,48 @@ gfxGDIFontList::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
}; };
FontDataDeleter autoDelete(aFontData); FontDataDeleter autoDelete(aFontData);
bool hasVertical; bool isCFF = gfxFontUtils::IsCffFont(aFontData);
bool isCFF = gfxFontUtils::IsCffFont(aFontData, hasVertical);
nsresult rv; nsresult rv;
HANDLE fontRef = nullptr; HANDLE fontRef = nullptr;
bool isEmbedded = false;
nsAutoString uniqueName; nsAutoString uniqueName;
rv = gfxFontUtils::MakeUniqueUserFontName(uniqueName); rv = gfxFontUtils::MakeUniqueUserFontName(uniqueName);
if (NS_FAILED(rv)) if (NS_FAILED(rv))
return nullptr; return nullptr;
// for TTF fonts, first try using the t2embed library if available FallibleTArray<uint8_t> newFontData;
if (!isCFF && TTLoadEmbeddedFontPtr && TTDeleteEmbeddedFontPtr) {
// TrueType-style glyphs, use EOT library
AutoFallibleTArray<uint8_t,2048> eotHeader;
uint8_t *buffer;
uint32_t eotlen;
isEmbedded = true; rv = gfxFontUtils::RenameFont(uniqueName, aFontData, aLength, &newFontData);
uint32_t nameLen = std::min<uint32_t>(uniqueName.Length(), LF_FACESIZE - 1);
nsAutoString fontName(Substring(uniqueName, 0, nameLen)); if (NS_FAILED(rv))
return nullptr;
FontDataOverlay overlayNameData = {0, 0, 0}; DWORD numFonts = 0;
rv = gfxFontUtils::MakeEOTHeader(aFontData, aLength, &eotHeader, uint8_t *fontData = reinterpret_cast<uint8_t*> (newFontData.Elements());
&overlayNameData); uint32_t fontLength = newFontData.Length();
if (NS_SUCCEEDED(rv)) { NS_ASSERTION(fontData, "null font data after renaming");
// load in embedded font data // http://msdn.microsoft.com/en-us/library/ms533942(VS.85).aspx
eotlen = eotHeader.Length(); // "A font that is added by AddFontMemResourceEx is always private
buffer = reinterpret_cast<uint8_t*> (eotHeader.Elements()); // to the process that made the call and is not enumerable."
fontRef = AddFontMemResourceEx(fontData, fontLength,
int32_t ret; 0 /* reserved */, &numFonts);
ULONG privStatus, pulStatus; if (!fontRef)
EOTFontStreamReader eotReader(aFontData, aLength, buffer, eotlen, return nullptr;
&overlayNameData);
ret = TTLoadEmbeddedFontPtr(&fontRef, TTLOAD_PRIVATE, &privStatus, // only load fonts with a single face contained in the data
LICENSE_PREVIEWPRINT, &pulStatus, // AddFontMemResourceEx generates an additional face name for
EOTFontStreamReader::ReadEOTStream, // vertical text if the font supports vertical writing but since
&eotReader, // the font is referenced via the name this can be ignored
(PRUnichar*)(fontName.get()), 0, 0); if (fontRef && numFonts > 2) {
if (ret != E_NONE) { RemoveFontMemResourceEx(fontRef);
fontRef = nullptr; return nullptr;
char buf[256];
sprintf(buf, "font (%s) not loaded using TTLoadEmbeddedFont - error %8.8x",
NS_ConvertUTF16toUTF8(aProxyEntry->Name()).get(), ret);
NS_WARNING(buf);
}
}
}
// load CFF fonts or fonts that failed with t2embed loader
if (fontRef == nullptr) {
// Postscript-style glyphs, swizzle name table, load directly
FallibleTArray<uint8_t> newFontData;
isEmbedded = false;
rv = gfxFontUtils::RenameFont(uniqueName, aFontData, aLength, &newFontData);
if (NS_FAILED(rv))
return nullptr;
DWORD numFonts = 0;
uint8_t *fontData = reinterpret_cast<uint8_t*> (newFontData.Elements());
uint32_t fontLength = newFontData.Length();
NS_ASSERTION(fontData, "null font data after renaming");
// http://msdn.microsoft.com/en-us/library/ms533942(VS.85).aspx
// "A font that is added by AddFontMemResourceEx is always private
// to the process that made the call and is not enumerable."
fontRef = AddFontMemResourceEx(fontData, fontLength,
0 /* reserved */, &numFonts);
if (!fontRef)
return nullptr;
// only load fonts with a single face contained in the data
// AddFontMemResourceEx generates an additional face name for
// vertical text if the font supports vertical writing
if (fontRef && numFonts != 1 + !!hasVertical) {
RemoveFontMemResourceEx(fontRef);
return nullptr;
}
} }
// make a new font entry using the unique name // make a new font entry using the unique name
WinUserFontData *winUserFontData = new WinUserFontData(fontRef, isEmbedded); WinUserFontData *winUserFontData = new WinUserFontData(fontRef);
uint16_t w = (aProxyEntry->mWeight == 0 ? 400 : aProxyEntry->mWeight); uint16_t w = (aProxyEntry->mWeight == 0 ? 400 : aProxyEntry->mWeight);
GDIFontEntry *fe = GDIFontEntry::CreateFontEntry(uniqueName, GDIFontEntry *fe = GDIFontEntry::CreateFontEntry(uniqueName,

View File

@ -332,8 +332,6 @@ private:
gfxGDIFontList(); gfxGDIFontList();
void InitializeFontEmbeddingProcs();
nsresult GetFontSubstitutes(); nsresult GetFontSubstitutes();
static int CALLBACK EnumFontFamExProc(ENUMLOGFONTEXW *lpelfe, static int CALLBACK EnumFontFamExProc(ENUMLOGFONTEXW *lpelfe,

View File

@ -327,9 +327,10 @@ bool LaunchApp(const std::wstring& cmdline,
if (!createdOK) if (!createdOK)
return false; return false;
gProcessLog.print("==> process %d launched child process %d\n", gProcessLog.print("==> process %d launched child process %d (%S)\n",
GetCurrentProcId(), GetCurrentProcId(),
process_info.dwProcessId); process_info.dwProcessId,
cmdline.c_str());
// Handles must be closed or they will leak // Handles must be closed or they will leak
CloseHandle(process_info.hThread); CloseHandle(process_info.hThread);

View File

@ -1675,10 +1675,18 @@ public:
m_formatter.immediate32(imm); m_formatter.immediate32(imm);
} }
// Intentionally left undefined. If you need this operation, consider // Note that this instruction sign-extends its 32-bit immediate field to 64
// naming it movq_i32r_signExtended to highlight the fact the operand size // bits and loads the 64-bit value into a 64-bit register.
// is not 32; the 32-bit immediate is sign-extended. //
void movq_i32r(int imm, RegisterID dst); // Note also that this is similar to the movl_i32r instruction, except that
// movl_i32r *zero*-extends its 32-bit immediate, and it has smaller code
// size, so it's preferred for values which could use either.
void movq_i32r(int imm, RegisterID dst) {
spew("movq $%d, %s",
imm, nameIReg(dst));
m_formatter.oneByteOp64(OP_GROUP11_EvIz, GROUP11_MOV, dst);
m_formatter.immediate32(imm);
}
void movq_i64r(int64_t imm, RegisterID dst) void movq_i64r(int64_t imm, RegisterID dst)
{ {

View File

@ -1436,7 +1436,7 @@ ion::UnsplitEdges(LIRGraph *lir)
// over-conservative, but we're attempting to keep everything in MIR // over-conservative, but we're attempting to keep everything in MIR
// current as we modify the LIR, so only proceed if the MIR is simple. // current as we modify the LIR, so only proceed if the MIR is simple.
if (mirBlock->numPredecessors() == 0 || mirBlock->numSuccessors() != 1 || if (mirBlock->numPredecessors() == 0 || mirBlock->numSuccessors() != 1 ||
!mirBlock->resumePointsEmpty() || !mirBlock->begin()->isGoto()) !mirBlock->begin()->isGoto())
{ {
continue; continue;
} }

View File

@ -7097,8 +7097,8 @@ IonBuilder::jsop_arguments_getelem()
return true; return true;
} }
// inlined not constant not supported, yet. // inlined not constant not supported, yet.
return abort("NYI inlined not constant get argument element"); return abort("NYI inlined not constant get argument element");
} }
bool bool

View File

@ -1290,6 +1290,14 @@ MMul::canOverflow()
return !range() || !range()->isInt32(); return !range() || !range()->isInt32();
} }
bool
MUrsh::canOverflow()
{
if (!canOverflow_)
return false;
return !range() || !range()->isInt32();
}
static inline bool static inline bool
KnownNonStringPrimitive(MDefinition *op) KnownNonStringPrimitive(MDefinition *op)
{ {

View File

@ -2895,25 +2895,7 @@ class MUrsh : public MShiftInstruction
void infer(BaselineInspector *inspector, jsbytecode *pc); void infer(BaselineInspector *inspector, jsbytecode *pc);
bool canOverflow() { bool canOverflow();
// solution is only negative when lhs < 0 and rhs & 0x1f == 0
MDefinition *lhs = getOperand(0);
MDefinition *rhs = getOperand(1);
if (lhs->isConstant()) {
Value lhsv = lhs->toConstant()->value();
if (lhsv.isInt32() && lhsv.toInt32() >= 0)
return false;
}
if (rhs->isConstant()) {
Value rhsv = rhs->toConstant()->value();
if (rhsv.isInt32() && rhsv.toInt32() % 32 != 0)
return false;
}
return canOverflow_;
}
bool fallible() { bool fallible() {
return canOverflow(); return canOverflow();

View File

@ -609,6 +609,9 @@ class MIRGraph
ReversePostorderIterator rpoBegin() { ReversePostorderIterator rpoBegin() {
return blocks_.begin(); return blocks_.begin();
} }
ReversePostorderIterator rpoBegin(MBasicBlock *at) {
return blocks_.begin(at);
}
ReversePostorderIterator rpoEnd() { ReversePostorderIterator rpoEnd() {
return blocks_.end(); return blocks_.end();
} }

View File

@ -465,11 +465,22 @@ Range::or_(const Range *lhs, const Range *rhs)
int64_t lower = INT32_MIN; int64_t lower = INT32_MIN;
int64_t upper = INT32_MAX; int64_t upper = INT32_MAX;
// If the sign bits are the same, the result has the same sign. if (lhs->lower_ >= 0 && rhs->lower_ >= 0) {
if (lhs->lower_ >= 0 && rhs->lower_ >= 0) // Both operands are non-negative, so the result won't be greater than either.
lower = 0; lower = Max(lhs->lower_, rhs->lower_);
else if (lhs->upper_ < 0 || rhs->upper_ < 0) // The result will have leading zeros where both operands have leading zeros.
upper = -1; upper = UINT32_MAX >> Min(js_bitscan_clz32(lhs->upper_),
js_bitscan_clz32(rhs->upper_));
} else {
// The result will have leading ones where either operand has leading ones.
if (lhs->upper_ < 0)
lower = Max(lower, (int64_t)(int32_t)~(UINT32_MAX >> js_bitscan_clz32(~lhs->lower_)));
if (rhs->upper_ < 0)
lower = Max(lower, (int64_t)(int32_t)~(UINT32_MAX >> js_bitscan_clz32(~rhs->lower_)));
// If either operand is negative, the result is negative.
if (lhs->upper_ < 0 && rhs->upper_ < 0)
upper = -1;
}
return new Range(lower, upper); return new Range(lower, upper);
} }
@ -480,11 +491,31 @@ Range::xor_(const Range *lhs, const Range *rhs)
int64_t lower = INT32_MIN; int64_t lower = INT32_MIN;
int64_t upper = INT32_MAX; int64_t upper = INT32_MAX;
// If the sign bits are identical, the result is non-negative. if (lhs->lower_ >= 0 && rhs->lower_ >= 0) {
if (lhs->lower_ >= 0 && rhs->lower_ >= 0) // Both operands are non-negative. The result will be non-negative and
// not greater than either.
lower = 0; lower = 0;
else if (lhs->upper_ < 0 && rhs->upper_ < 0) upper = UINT32_MAX >> Min(js_bitscan_clz32(lhs->upper_),
js_bitscan_clz32(rhs->upper_));
} else if (lhs->upper_ < 0 && rhs->upper_ < 0) {
// Both operands are negative. The result will be non-negative and
// will have leading zeros where both operands have leading ones.
lower = 0; lower = 0;
upper = UINT32_MAX >> Min(js_bitscan_clz32(~lhs->lower_),
js_bitscan_clz32(~rhs->lower_));
} else if (lhs->upper_ < 0 && rhs->lower_ >= 0) {
// One operand is negative and the other is non-negative. The result
// will have leading ones where the negative operand has leading ones
// and the non-negative operand has leading zeros.
upper = -1;
lower = (int32_t)~(UINT32_MAX >> Min(js_bitscan_clz32(~lhs->lower_),
js_bitscan_clz32(rhs->upper_)));
} else if (lhs->lower_ >= 0 && rhs->upper_ < 0) {
// One operand is negative and the other is non-negative. As above.
upper = -1;
lower = (int32_t)~(UINT32_MAX >> Min(js_bitscan_clz32(lhs->upper_),
js_bitscan_clz32(~rhs->lower_)));
}
return new Range(lower, upper); return new Range(lower, upper);
} }
@ -492,16 +523,7 @@ Range::xor_(const Range *lhs, const Range *rhs)
Range * Range *
Range::not_(const Range *op) Range::not_(const Range *op)
{ {
int64_t lower = INT32_MIN; return new Range(~op->upper_, ~op->lower_);
int64_t upper = INT32_MAX;
// Not inverts all bits, including the sign bit.
if (op->lower_ >= 0)
upper = -1;
else if (op->upper_ < 0)
lower = 0;
return new Range(lower, upper);
} }
Range * Range *
@ -528,12 +550,12 @@ Range::lsh(const Range *lhs, int32_t c)
// If the shift doesn't loose bits or shift bits into the sign bit, we // If the shift doesn't loose bits or shift bits into the sign bit, we
// can simply compute the correct range by shifting. // can simply compute the correct range by shifting.
if (((uint32_t)lhs->lower_ << shift << 1 >> shift >> 1) == lhs->lower_ && if ((int32_t)((uint32_t)lhs->lower_ << shift << 1 >> shift >> 1) == lhs->lower_ &&
((uint32_t)lhs->upper_ << shift << 1 >> shift >> 1) == lhs->upper_) (int32_t)((uint32_t)lhs->upper_ << shift << 1 >> shift >> 1) == lhs->upper_)
{ {
return new Range( return new Range(
(int64_t)lhs->lower_ << shift, (uint32_t)lhs->lower_ << shift,
(int64_t)lhs->upper_ << shift); (uint32_t)lhs->upper_ << shift);
} }
return new Range(INT32_MIN, INT32_MAX); return new Range(INT32_MIN, INT32_MAX);
@ -1022,6 +1044,8 @@ RangeAnalysis::markBlocksInLoopBody(MBasicBlock *header, MBasicBlock *current)
void void
RangeAnalysis::analyzeLoop(MBasicBlock *header) RangeAnalysis::analyzeLoop(MBasicBlock *header)
{ {
JS_ASSERT(header->hasUniqueBackedge());
// Try to compute an upper bound on the number of times the loop backedge // Try to compute an upper bound on the number of times the loop backedge
// will be taken. Look for tests that dominate the backedge and which have // will be taken. Look for tests that dominate the backedge and which have
// an edge leaving the loop body. // an edge leaving the loop body.
@ -1075,17 +1099,14 @@ RangeAnalysis::analyzeLoop(MBasicBlock *header)
// Try to compute symbolic bounds for the phi nodes at the head of this // Try to compute symbolic bounds for the phi nodes at the head of this
// loop, expressed in terms of the iteration bound just computed. // loop, expressed in terms of the iteration bound just computed.
for (MDefinitionIterator iter(header); iter; iter++) { for (MPhiIterator iter(header->phisBegin()); iter != header->phisEnd(); iter++)
MDefinition *def = *iter; analyzeLoopPhi(header, iterationBound, *iter);
if (def->isPhi())
analyzeLoopPhi(header, iterationBound, def->toPhi());
}
// Try to hoist any bounds checks from the loop using symbolic bounds. // Try to hoist any bounds checks from the loop using symbolic bounds.
Vector<MBoundsCheck *, 0, IonAllocPolicy> hoistedChecks; Vector<MBoundsCheck *, 0, IonAllocPolicy> hoistedChecks;
for (ReversePostorderIterator iter(graph_.rpoBegin()); iter != graph_.rpoEnd(); iter++) { for (ReversePostorderIterator iter(graph_.rpoBegin(header)); iter != graph_.rpoEnd(); iter++) {
MBasicBlock *block = *iter; MBasicBlock *block = *iter;
if (!block->isMarked()) if (!block->isMarked())
continue; continue;
@ -1236,8 +1257,7 @@ RangeAnalysis::analyzeLoopPhi(MBasicBlock *header, LoopIterationBound *loopBound
// but is required to change at most N and be either nondecreasing or // but is required to change at most N and be either nondecreasing or
// nonincreasing. // nonincreasing.
if (phi->numOperands() != 2) JS_ASSERT(phi->numOperands() == 2);
return;
MBasicBlock *preLoop = header->loopPredecessor(); MBasicBlock *preLoop = header->loopPredecessor();
JS_ASSERT(!preLoop->isMarked() && preLoop->successorWithPhis() == header); JS_ASSERT(!preLoop->isMarked() && preLoop->successorWithPhis() == header);

View File

@ -362,12 +362,27 @@ class Assembler : public AssemblerX86Shared
} }
CodeOffsetLabel movWithPatch(const ImmWord &word, const Register &dest) { CodeOffsetLabel movWithPatch(const ImmWord &word, const Register &dest) {
movq(word, dest); masm.movq_i64r(word.value, dest.code());
return masm.currentOffset(); return masm.currentOffset();
} }
// Load an ImmWord value into a register. Note that this instruction will
// attempt to optimize its immediate field size. When a full 64-bit
// immediate is needed for a relocation, use movWithPatch.
void movq(ImmWord word, const Register &dest) { void movq(ImmWord word, const Register &dest) {
masm.movq_i64r(word.value, dest.code()); // Load a 64-bit immediate into a register. If the value falls into
// certain ranges, we can use specialized instructions which have
// smaller encodings.
if (word.value <= UINT32_MAX) {
// movl has a 32-bit unsigned (effectively) immediate field.
masm.movl_i32r((uint32_t)word.value, dest.code());
} else if ((intptr_t)word.value >= INT32_MIN && (intptr_t)word.value <= INT32_MAX) {
// movq has a 32-bit signed immediate field.
masm.movq_i32r((int32_t)(intptr_t)word.value, dest.code());
} else {
// Otherwise use movabs.
masm.movq_i64r(word.value, dest.code());
}
} }
void movq(ImmGCPtr ptr, const Register &dest) { void movq(ImmGCPtr ptr, const Register &dest) {
masm.movq_i64r(ptr.value, dest.code()); masm.movq_i64r(ptr.value, dest.code());
@ -523,16 +538,7 @@ class Assembler : public AssemblerX86Shared
} }
void mov(ImmWord word, const Register &dest) { void mov(ImmWord word, const Register &dest) {
// If the word value is in [0,UINT32_MAX], we can use the more compact movq(word, dest);
// movl instruction, which has a 32-bit immediate field which it
// zero-extends into the 64-bit register.
if (word.value <= UINT32_MAX) {
uint32_t value32 = static_cast<uint32_t>(word.value);
Imm32 imm32(static_cast<int32_t>(value32));
movl(imm32, dest);
} else {
movq(word, dest);
}
} }
void mov(const Imm32 &imm32, const Register &dest) { void mov(const Imm32 &imm32, const Register &dest) {
movl(imm32, dest); movl(imm32, dest);

View File

@ -161,9 +161,12 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
template <typename T> template <typename T>
void storeValue(const Value &val, const T &dest) { void storeValue(const Value &val, const T &dest) {
jsval_layout jv = JSVAL_TO_IMPL(val); jsval_layout jv = JSVAL_TO_IMPL(val);
movq(ImmWord(jv.asBits), ScratchReg); if (val.isMarkable()) {
if (val.isMarkable()) movWithPatch(ImmWord(jv.asBits), ScratchReg);
writeDataRelocation(val); writeDataRelocation(val);
} else {
mov(ImmWord(jv.asBits), ScratchReg);
}
movq(ScratchReg, Operand(dest)); movq(ScratchReg, Operand(dest));
} }
void storeValue(ValueOperand val, BaseIndex dest) { void storeValue(ValueOperand val, BaseIndex dest) {
@ -213,7 +216,7 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
void moveValue(const Value &val, const Register &dest) { void moveValue(const Value &val, const Register &dest) {
jsval_layout jv = JSVAL_TO_IMPL(val); jsval_layout jv = JSVAL_TO_IMPL(val);
movq(ImmWord(jv.asPtr), dest); movWithPatch(ImmWord(jv.asPtr), dest);
writeDataRelocation(val); writeDataRelocation(val);
} }
void moveValue(const Value &src, const ValueOperand &dest) { void moveValue(const Value &src, const ValueOperand &dest) {

View File

@ -88,7 +88,7 @@ JSCompartment::init(JSContext *cx)
{ {
/* /*
* As a hack, we clear our timezone cache every time we create a new * As a hack, we clear our timezone cache every time we create a new
* compartment. This ensures that the cache is always relatively fresh, but * compartment. This ensures that the cache is always relatively fresh, but
* shouldn't interfere with benchmarks which create tons of date objects * shouldn't interfere with benchmarks which create tons of date objects
* (unless they also create tons of iframes, which seems unlikely). * (unless they also create tons of iframes, which seems unlikely).
*/ */

View File

@ -500,9 +500,11 @@ def process_test_results(results, num_tests, options):
doing = 'after %s' % res.test.path doing = 'after %s' % res.test.path
if not ok: if not ok:
failures.append(res) failures.append(res)
pb.message("FAIL - %s" % res.test.path) if res.timed_out:
if res.timed_out: pb.message("TIMEOUT - %s" % res.test.path)
timeouts += 1 timeouts += 1
else:
pb.message("FAIL - %s" % res.test.path)
if options.tinderbox: if options.tinderbox:
if ok: if ok:

View File

@ -70,7 +70,6 @@
#include "nsRuleNode.h" #include "nsRuleNode.h"
#include "nsIDOMMutationEvent.h" #include "nsIDOMMutationEvent.h"
#include "ChildIterator.h" #include "ChildIterator.h"
#include "nsXBLChildrenElement.h"
#include "nsCSSRendering.h" #include "nsCSSRendering.h"
#include "nsError.h" #include "nsError.h"
#include "nsLayoutUtils.h" #include "nsLayoutUtils.h"

View File

@ -112,8 +112,6 @@ skip-if(B2G) HTTP(..) == name-collision.html name-collision-ref.html # bug 77348
skip-if(B2G) HTTP(..) == name-collision-bad-url.html name-collision-bad-url-ref.html # bug 773482 skip-if(B2G) HTTP(..) == name-collision-bad-url.html name-collision-bad-url-ref.html # bug 773482
HTTP(..) == name-collision-with-prefs-font.html name-collision-with-prefs-font-ref.html # bug 668758 HTTP(..) == name-collision-with-prefs-font.html name-collision-with-prefs-font-ref.html # bug 668758
# t2embed lib on windows is picky about fullname
HTTP(..) == load-badfullname.html load-badfullname-ref.html HTTP(..) == load-badfullname.html load-badfullname-ref.html
# 507960-1-* : a collection of tests using DeLarge from openfontlibrary.org # 507960-1-* : a collection of tests using DeLarge from openfontlibrary.org

View File

@ -61,7 +61,6 @@
#include "mozilla/LookAndFeel.h" #include "mozilla/LookAndFeel.h"
#include "mozilla/Likely.h" #include "mozilla/Likely.h"
#include "mozilla/Util.h" #include "mozilla/Util.h"
#include "nsXBLChildrenElement.h"
using namespace mozilla; using namespace mozilla;
using namespace mozilla::dom; using namespace mozilla::dom;

View File

@ -1,5 +1,5 @@
#define VERSION "1.3.0" #define VERSION "1.3.0"
#define BUILD "2013-05-25" #define BUILD "2013-05-25"
#define PACKAGE_NAME "libjpeg-turbo" #define PACKAGE_NAME "libjpeg-turbo"
/* Need to use Mozilla-specific function inlining. */ /* Need to use Mozilla-specific function inlining. */

View File

@ -995,8 +995,8 @@ gsmsdp_negotiate_offer_crypto (fsmdef_dcb_t *dcb_p, cc_sdp_t *cc_sdp_p,
negotiated_transport = SDP_TRANSPORT_RTPSAVPF; negotiated_transport = SDP_TRANSPORT_RTPSAVPF;
break; break;
case SDP_TRANSPORT_SCTPDTLS: case SDP_TRANSPORT_DTLSSCTP:
negotiated_transport = SDP_TRANSPORT_SCTPDTLS; negotiated_transport = SDP_TRANSPORT_DTLSSCTP;
break; break;
default: default:
@ -1076,8 +1076,8 @@ gsmsdp_negotiate_answer_crypto (fsmdef_dcb_t *dcb_p, cc_sdp_t *cc_sdp_p,
negotiated_transport = SDP_TRANSPORT_RTPSAVPF; negotiated_transport = SDP_TRANSPORT_RTPSAVPF;
break; break;
case SDP_TRANSPORT_SCTPDTLS: case SDP_TRANSPORT_DTLSSCTP:
negotiated_transport = SDP_TRANSPORT_SCTPDTLS; negotiated_transport = SDP_TRANSPORT_DTLSSCTP;
break; break;
default: default:
@ -1315,7 +1315,7 @@ gsmsdp_init_sdp_media_transport (fsmdef_dcb_t *dcb_p, void *sdp_p,
config_get_value(CFGID_SDPMODE, &sdpmode, sizeof(sdpmode)); config_get_value(CFGID_SDPMODE, &sdpmode, sizeof(sdpmode));
if (SDP_MEDIA_APPLICATION == media->type) { if (SDP_MEDIA_APPLICATION == media->type) {
media->transport = SDP_TRANSPORT_SCTPDTLS; media->transport = SDP_TRANSPORT_DTLSSCTP;
} else if (rtpsavpf) { } else if (rtpsavpf) {
media->transport = SDP_TRANSPORT_RTPSAVPF; media->transport = SDP_TRANSPORT_RTPSAVPF;
} else if (sdpmode) { } else if (sdpmode) {

View File

@ -179,7 +179,7 @@ typedef enum {
SDP_TRANSPORT_RTPSAVP, SDP_TRANSPORT_RTPSAVP,
SDP_TRANSPORT_TCP, SDP_TRANSPORT_TCP,
SDP_TRANSPORT_RTPSAVPF, SDP_TRANSPORT_RTPSAVPF,
SDP_TRANSPORT_SCTPDTLS, SDP_TRANSPORT_DTLSSCTP,
SDP_MAX_TRANSPORT_TYPES, SDP_MAX_TRANSPORT_TYPES,
SDP_TRANSPORT_UNSUPPORTED, SDP_TRANSPORT_UNSUPPORTED,
SDP_TRANSPORT_INVALID SDP_TRANSPORT_INVALID

View File

@ -229,7 +229,7 @@ const sdp_namearray_t sdp_transport[SDP_MAX_TRANSPORT_TYPES] =
{"RTP/SAVP", sizeof("RTP/SAVP")}, {"RTP/SAVP", sizeof("RTP/SAVP")},
{"tcp", sizeof("tcp")}, {"tcp", sizeof("tcp")},
{"RTP/SAVPF", sizeof("RTP/SAVPF")}, {"RTP/SAVPF", sizeof("RTP/SAVPF")},
{"SCTP/DTLS", sizeof("SCTP/DTLS")} {"DTLS/SCTP", sizeof("DTLS/SCTP")}
}; };
/* Note: These *must* be in the same order as the enum type. */ /* Note: These *must* be in the same order as the enum type. */

View File

@ -1196,14 +1196,14 @@ sdp_result_e sdp_parse_media (sdp_t *sdp_p, u16 level, const char *ptr)
} }
} }
/* TODO(ehugg): This block is for forward /* TODO(ehugg): Remove this next block when backward
compatibility with FF24. Should be in FF23 only. compatibility with versions earlier than FF24
See Bug 886134 */ is no longer required. See Bug 886134 */
#define DATACHANNEL_NEW_TRANSPORT "DTLS/SCTP" #define DATACHANNEL_OLD_TRANSPORT "SCTP/DTLS"
if (mca_p->transport == SDP_TRANSPORT_UNSUPPORTED) { if (mca_p->transport == SDP_TRANSPORT_UNSUPPORTED) {
if (cpr_strncasecmp(tmp, DATACHANNEL_NEW_TRANSPORT, if (cpr_strncasecmp(tmp, DATACHANNEL_OLD_TRANSPORT,
strlen(DATACHANNEL_NEW_TRANSPORT)) == 0) { strlen(DATACHANNEL_OLD_TRANSPORT)) == 0) {
mca_p->transport = SDP_TRANSPORT_SCTPDTLS; mca_p->transport = SDP_TRANSPORT_DTLSSCTP;
} }
} }
@ -1231,7 +1231,7 @@ sdp_result_e sdp_parse_media (sdp_t *sdp_p, u16 level, const char *ptr)
(mca_p->transport == SDP_TRANSPORT_UDPTL) || (mca_p->transport == SDP_TRANSPORT_UDPTL) ||
(mca_p->transport == SDP_TRANSPORT_UDPSPRT) || (mca_p->transport == SDP_TRANSPORT_UDPSPRT) ||
(mca_p->transport == SDP_TRANSPORT_LOCAL) || (mca_p->transport == SDP_TRANSPORT_LOCAL) ||
(mca_p->transport == SDP_TRANSPORT_SCTPDTLS)) { (mca_p->transport == SDP_TRANSPORT_DTLSSCTP)) {
/* Port format is simply <port>. Make sure that either /* Port format is simply <port>. Make sure that either
* the choose param is allowed or that the choose value * the choose param is allowed or that the choose value
* wasn't specified. * wasn't specified.
@ -1383,8 +1383,8 @@ sdp_result_e sdp_parse_media (sdp_t *sdp_p, u16 level, const char *ptr)
sdp_parse_payload_types(sdp_p, mca_p, ptr); sdp_parse_payload_types(sdp_p, mca_p, ptr);
} }
/* Parse SCTP/DTLS port */ /* Parse DTLS/SCTP port */
if (mca_p->transport == SDP_TRANSPORT_SCTPDTLS) { if (mca_p->transport == SDP_TRANSPORT_DTLSSCTP) {
ptr = sdp_getnextstrtok(ptr, port, sizeof(port), " \t", &result); ptr = sdp_getnextstrtok(ptr, port, sizeof(port), " \t", &result);
if (result != SDP_SUCCESS) { if (result != SDP_SUCCESS) {
sdp_parse_error(sdp_p->peerconnection, sdp_parse_error(sdp_p->peerconnection,
@ -1565,7 +1565,7 @@ sdp_result_e sdp_build_media (sdp_t *sdp_p, u16 level, flex_string *fs)
flex_string_sprintf(fs, "%s", flex_string_sprintf(fs, "%s",
sdp_get_transport_name(mca_p->transport)); sdp_get_transport_name(mca_p->transport));
if(mca_p->transport != SDP_TRANSPORT_SCTPDTLS) { if(mca_p->transport != SDP_TRANSPORT_DTLSSCTP) {
/* Build the format lists */ /* Build the format lists */
for (i=0; i < mca_p->num_payloads; i++) { for (i=0; i < mca_p->num_payloads; i++) {
@ -1577,7 +1577,7 @@ sdp_result_e sdp_build_media (sdp_t *sdp_p, u16 level, flex_string *fs)
} }
} }
} else { } else {
/* Add port to SDP if transport is SCTP/DTLS */ /* Add port to SDP if transport is DTLS/SCTP */
flex_string_sprintf(fs, " %u ", (u32)mca_p->sctpport); flex_string_sprintf(fs, " %u ", (u32)mca_p->sctpport);
} }

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