merge fx-team to m-c
@ -177,7 +177,7 @@ EXTRA_BUILDID := -$(MOZ_SYMBOLS_EXTRA_BUILDID)
|
||||
endif
|
||||
|
||||
SYMBOL_INDEX_NAME = \
|
||||
$(MOZ_APP_NAME)-$(MOZ_APP_VERSION)-$(OS_TARGET)-$(BUILDID)$(EXTRA_BUILDID)-symbols.txt
|
||||
$(MOZ_APP_NAME)-$(MOZ_APP_VERSION)-$(OS_TARGET)-$(BUILDID)-$(CPU_ARCH)$(EXTRA_BUILDID)-symbols.txt
|
||||
|
||||
buildsymbols:
|
||||
ifdef MOZ_CRASHREPORTER
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "Accessible-inl.h"
|
||||
#include "nsAccUtils.h"
|
||||
#include "nsHyperTextAccessible.h"
|
||||
#include "nsDocAccessible.h"
|
||||
#include "States.h"
|
||||
|
||||
#include "nsArrayUtils.h"
|
||||
@ -217,6 +218,10 @@ nsAccessiblePivot::MoveNext(nsIAccessibleTraversalRule* aRule, bool* aResult)
|
||||
NS_ENSURE_ARG(aResult);
|
||||
NS_ENSURE_ARG(aRule);
|
||||
|
||||
if (mPosition && (mPosition->IsDefunct() ||
|
||||
!mPosition->Document()->IsInDocument(mPosition)))
|
||||
return NS_ERROR_NOT_IN_TREE;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
nsAccessible* accessible = SearchForward(mPosition, aRule, false, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
@ -234,6 +239,10 @@ nsAccessiblePivot::MovePrevious(nsIAccessibleTraversalRule* aRule, bool* aResult
|
||||
NS_ENSURE_ARG(aResult);
|
||||
NS_ENSURE_ARG(aRule);
|
||||
|
||||
if (mPosition && (mPosition->IsDefunct() ||
|
||||
!mPosition->Document()->IsInDocument(mPosition)))
|
||||
return NS_ERROR_NOT_IN_TREE;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
nsAccessible* accessible = SearchBackward(mPosition, aRule, false, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
@ -250,6 +259,10 @@ nsAccessiblePivot::MoveFirst(nsIAccessibleTraversalRule* aRule, bool* aResult)
|
||||
{
|
||||
NS_ENSURE_ARG(aResult);
|
||||
NS_ENSURE_ARG(aRule);
|
||||
|
||||
if (mRoot && mRoot->IsDefunct())
|
||||
return NS_ERROR_NOT_IN_TREE;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
nsAccessible* accessible = SearchForward(mRoot, aRule, true, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
@ -267,6 +280,9 @@ nsAccessiblePivot::MoveLast(nsIAccessibleTraversalRule* aRule, bool* aResult)
|
||||
NS_ENSURE_ARG(aResult);
|
||||
NS_ENSURE_ARG(aRule);
|
||||
|
||||
if (mRoot && mRoot->IsDefunct())
|
||||
return NS_ERROR_NOT_IN_TREE;
|
||||
|
||||
*aResult = false;
|
||||
nsresult rv = NS_OK;
|
||||
nsAccessible* lastAccessible = mRoot;
|
||||
@ -334,6 +350,9 @@ nsAccessiblePivot::RemoveObserver(nsIAccessiblePivotObserver* aObserver)
|
||||
bool
|
||||
nsAccessiblePivot::IsRootDescendant(nsAccessible* aAccessible)
|
||||
{
|
||||
if (!mRoot || mRoot->IsDefunct())
|
||||
return false;
|
||||
|
||||
nsAccessible* accessible = aAccessible;
|
||||
do {
|
||||
if (accessible == mRoot)
|
||||
|
@ -49,6 +49,10 @@
|
||||
class nsAccessible;
|
||||
class nsIAccessibleTraversalRule;
|
||||
|
||||
// raised when current pivot's position is needed but it is not in the tree.
|
||||
#define NS_ERROR_NOT_IN_TREE \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_GENERAL, 0x26)
|
||||
|
||||
/**
|
||||
* Class represents an accessible pivot.
|
||||
*/
|
||||
|
@ -88,9 +88,6 @@ nsHTMLSelectListAccessible::NativeState()
|
||||
role
|
||||
nsHTMLSelectListAccessible::NativeRole()
|
||||
{
|
||||
if (mParent && mParent->Role() == roles::COMBOBOX)
|
||||
return roles::COMBOBOX_LIST;
|
||||
|
||||
return roles::LISTBOX;
|
||||
}
|
||||
|
||||
@ -710,6 +707,12 @@ nsHTMLComboboxListAccessible::IsPrimaryForNode() const
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLComboboxAccessible: nsAccessible
|
||||
|
||||
role
|
||||
nsHTMLComboboxListAccessible::NativeRole()
|
||||
{
|
||||
return roles::COMBOBOX_LIST;
|
||||
}
|
||||
|
||||
PRUint64
|
||||
nsHTMLComboboxListAccessible::NativeState()
|
||||
{
|
||||
|
@ -258,6 +258,7 @@ public:
|
||||
virtual bool IsPrimaryForNode() const;
|
||||
|
||||
// nsAccessible
|
||||
virtual mozilla::a11y::role NativeRole();
|
||||
virtual PRUint64 NativeState();
|
||||
virtual void GetBoundsRect(nsRect& aBounds, nsIFrame** aBoundingFrame);
|
||||
|
||||
|
@ -48,14 +48,14 @@ var AccessFu = {
|
||||
} catch (x) {
|
||||
}
|
||||
|
||||
this.processPreferences(accessPref);
|
||||
this._processPreferences(accessPref);
|
||||
},
|
||||
|
||||
/**
|
||||
* Start AccessFu mode, this primarily means controlling the virtual cursor
|
||||
* with arrow keys.
|
||||
*/
|
||||
enable: function enable() {
|
||||
_enable: function _enable() {
|
||||
if (this._enabled)
|
||||
return;
|
||||
this._enabled = true;
|
||||
@ -79,7 +79,7 @@ var AccessFu = {
|
||||
/**
|
||||
* Disable AccessFu and return to default interaction mode.
|
||||
*/
|
||||
disable: function disable() {
|
||||
_disable: function _disable() {
|
||||
if (!this._enabled)
|
||||
return;
|
||||
this._enabled = false;
|
||||
@ -98,7 +98,7 @@ var AccessFu = {
|
||||
this.chromeWin.removeEventListener('TabOpen', this, true);
|
||||
},
|
||||
|
||||
processPreferences: function processPreferences(aPref) {
|
||||
_processPreferences: function _processPreferences(aPref) {
|
||||
if (Services.appinfo.OS == 'Android') {
|
||||
if (aPref == ACCESSFU_AUTO) {
|
||||
if (!this._observingSystemSettings) {
|
||||
@ -118,9 +118,9 @@ var AccessFu = {
|
||||
}
|
||||
|
||||
if (aPref == ACCESSFU_ENABLE)
|
||||
this.enable();
|
||||
this._enable();
|
||||
else
|
||||
this.disable();
|
||||
this._disable();
|
||||
},
|
||||
|
||||
addPresenter: function addPresenter(presenter) {
|
||||
@ -171,19 +171,19 @@ var AccessFu = {
|
||||
switch (aTopic) {
|
||||
case 'Accessibility:Settings':
|
||||
if (JSON.parse(aData).enabled)
|
||||
this.enable();
|
||||
this._enable();
|
||||
else
|
||||
this.disable();
|
||||
this._disable();
|
||||
break;
|
||||
case 'nsPref:changed':
|
||||
if (aData == 'accessfu')
|
||||
this.processPreferences(this.prefsBranch.getIntPref('accessfu'));
|
||||
this._processPreferences(this.prefsBranch.getIntPref('accessfu'));
|
||||
break;
|
||||
case 'accessible-event':
|
||||
let event;
|
||||
try {
|
||||
event = aSubject.QueryInterface(Ci.nsIAccessibleEvent);
|
||||
this.handleAccEvent(event);
|
||||
this._handleAccEvent(event);
|
||||
} catch (ex) {
|
||||
dump(ex);
|
||||
return;
|
||||
@ -191,7 +191,7 @@ var AccessFu = {
|
||||
}
|
||||
},
|
||||
|
||||
handleAccEvent: function handleAccEvent(aEvent) {
|
||||
_handleAccEvent: function _handleAccEvent(aEvent) {
|
||||
switch (aEvent.eventType) {
|
||||
case Ci.nsIAccessibleEvent.EVENT_VIRTUALCURSOR_CHANGED:
|
||||
{
|
||||
@ -199,6 +199,21 @@ var AccessFu = {
|
||||
QueryInterface(Ci.nsIAccessibleCursorable).virtualCursor;
|
||||
let event = aEvent.
|
||||
QueryInterface(Ci.nsIAccessibleVirtualCursorChangeEvent);
|
||||
let position = pivot.position;
|
||||
let doc = aEvent.DOMNode;
|
||||
|
||||
if (doc instanceof Ci.nsIDOMDocument && position.DOMNode) {
|
||||
// Set the caret to the start of the pivot position, and move
|
||||
// the focus in the same manner as browse with caret mode.
|
||||
// This blurs the focus on the previous pivot position (if it
|
||||
// was activated), and keeps us in a predictable spot for tab
|
||||
// focus.
|
||||
let sel = doc.getSelection();
|
||||
sel.collapse(position.DOMNode, 0);
|
||||
Cc["@mozilla.org/focus-manager;1"]
|
||||
.getService(Ci.nsIFocusManager).moveFocus(
|
||||
doc.defaultView, null, Ci.nsIFocusManager.MOVEFOCUS_CARET, 0);
|
||||
}
|
||||
|
||||
let newContext = this.getNewContext(event.oldAccessible,
|
||||
pivot.position);
|
||||
@ -251,13 +266,13 @@ var AccessFu = {
|
||||
let state = {};
|
||||
docAcc.getState(state, {});
|
||||
if (state.value & Ci.nsIAccessibleStates.STATE_BUSY &&
|
||||
this.isNotChromeDoc(docAcc))
|
||||
this._isNotChromeDoc(docAcc))
|
||||
this.presenters.forEach(
|
||||
function(p) { p.tabStateChanged(docAcc, 'loading'); }
|
||||
);
|
||||
delete this._pendingDocuments[aEvent.DOMNode];
|
||||
}
|
||||
if (this.isBrowserDoc(docAcc))
|
||||
if (this._isBrowserDoc(docAcc))
|
||||
// A new top-level content document has been attached
|
||||
this.presenters.forEach(
|
||||
function(p) { p.tabStateChanged(docAcc, 'newdoc'); }
|
||||
@ -267,7 +282,7 @@ var AccessFu = {
|
||||
}
|
||||
case Ci.nsIAccessibleEvent.EVENT_DOCUMENT_LOAD_COMPLETE:
|
||||
{
|
||||
if (this.isNotChromeDoc(aEvent.accessible)) {
|
||||
if (this._isNotChromeDoc(aEvent.accessible)) {
|
||||
this.presenters.forEach(
|
||||
function(p) {
|
||||
p.tabStateChanged(aEvent.accessible, 'loaded');
|
||||
@ -296,7 +311,7 @@ var AccessFu = {
|
||||
}
|
||||
case Ci.nsIAccessibleEvent.EVENT_FOCUS:
|
||||
{
|
||||
if (this.isBrowserDoc(aEvent.accessible)) {
|
||||
if (this._isBrowserDoc(aEvent.accessible)) {
|
||||
// The document recieved focus, call tabSelected to present current tab.
|
||||
this.presenters.forEach(
|
||||
function(p) { p.tabSelected(aEvent.accessible); });
|
||||
@ -342,7 +357,7 @@ var AccessFu = {
|
||||
* @param {nsIAccessible} aDocAcc the accessible to check.
|
||||
* @return {boolean} true if this is a top-level content document.
|
||||
*/
|
||||
isBrowserDoc: function isBrowserDoc(aDocAcc) {
|
||||
_isBrowserDoc: function _isBrowserDoc(aDocAcc) {
|
||||
let parent = aDocAcc.parent;
|
||||
if (!parent)
|
||||
return false;
|
||||
@ -360,7 +375,7 @@ var AccessFu = {
|
||||
* @param {nsIDOMDocument} aDocument the document to check.
|
||||
* @return {boolean} true if this is not a chrome document.
|
||||
*/
|
||||
isNotChromeDoc: function isNotChromeDoc(aDocument) {
|
||||
_isNotChromeDoc: function _isNotChromeDoc(aDocument) {
|
||||
let location = aDocument.DOMNode.location;
|
||||
if (!location)
|
||||
return false;
|
||||
|
@ -52,7 +52,9 @@ Presenter.prototype = {
|
||||
/**
|
||||
* Text has changed, either by the user or by the system. TODO.
|
||||
*/
|
||||
textChanged: function textChanged(aIsInserted, aStartOffset, aLength, aText, aModifiedText) {},
|
||||
textChanged: function textChanged(aIsInserted, aStartOffset,
|
||||
aLength, aText,
|
||||
aModifiedText) {},
|
||||
|
||||
/**
|
||||
* Text selection has changed. TODO.
|
||||
@ -95,228 +97,236 @@ Presenter.prototype = {
|
||||
|
||||
function VisualPresenter() {}
|
||||
|
||||
VisualPresenter.prototype = new Presenter();
|
||||
VisualPresenter.prototype = {
|
||||
__proto__: Presenter.prototype,
|
||||
|
||||
/**
|
||||
* The padding in pixels between the object and the highlight border.
|
||||
*/
|
||||
VisualPresenter.prototype.BORDER_PADDING = 2;
|
||||
/**
|
||||
* The padding in pixels between the object and the highlight border.
|
||||
*/
|
||||
BORDER_PADDING: 2,
|
||||
|
||||
VisualPresenter.prototype.attach = function(aWindow) {
|
||||
this.chromeWin = aWindow;
|
||||
attach: function VisualPresenter_attach(aWindow) {
|
||||
this.chromeWin = aWindow;
|
||||
|
||||
// Add stylesheet
|
||||
let stylesheetURL = 'chrome://global/content/accessibility/AccessFu.css';
|
||||
this.stylesheet = aWindow.document.createProcessingInstruction(
|
||||
'xml-stylesheet', 'href="' + stylesheetURL + '" type="text/css"');
|
||||
aWindow.document.insertBefore(this.stylesheet, aWindow.document.firstChild);
|
||||
// Add stylesheet
|
||||
let stylesheetURL = 'chrome://global/content/accessibility/AccessFu.css';
|
||||
this.stylesheet = aWindow.document.createProcessingInstruction(
|
||||
'xml-stylesheet', 'href="' + stylesheetURL + '" type="text/css"');
|
||||
aWindow.document.insertBefore(this.stylesheet, aWindow.document.firstChild);
|
||||
|
||||
// Add highlight box
|
||||
this.highlightBox = this.chromeWin.document.
|
||||
createElementNS('http://www.w3.org/1999/xhtml', 'div');
|
||||
this.chromeWin.document.documentElement.appendChild(this.highlightBox);
|
||||
this.highlightBox.id = 'virtual-cursor-box';
|
||||
// Add highlight box
|
||||
this.highlightBox = this.chromeWin.document.
|
||||
createElementNS('http://www.w3.org/1999/xhtml', 'div');
|
||||
this.chromeWin.document.documentElement.appendChild(this.highlightBox);
|
||||
this.highlightBox.id = 'virtual-cursor-box';
|
||||
|
||||
// Add highlight inset for inner shadow
|
||||
let inset = this.chromeWin.document.
|
||||
createElementNS('http://www.w3.org/1999/xhtml', 'div');
|
||||
inset.id = 'virtual-cursor-inset';
|
||||
// Add highlight inset for inner shadow
|
||||
let inset = this.chromeWin.document.
|
||||
createElementNS('http://www.w3.org/1999/xhtml', 'div');
|
||||
inset.id = 'virtual-cursor-inset';
|
||||
|
||||
this.highlightBox.appendChild(inset);
|
||||
};
|
||||
this.highlightBox.appendChild(inset);
|
||||
},
|
||||
|
||||
VisualPresenter.prototype.detach = function() {
|
||||
this.chromeWin.document.removeChild(this.stylesheet);
|
||||
this.highlightBox.parentNode.removeChild(this.highlightBox);
|
||||
this.highlightBox = this.stylesheet = null;
|
||||
};
|
||||
detach: function VisualPresenter_detach() {
|
||||
this.chromeWin.document.removeChild(this.stylesheet);
|
||||
this.highlightBox.parentNode.removeChild(this.highlightBox);
|
||||
this.highlightBox = this.stylesheet = null;
|
||||
},
|
||||
|
||||
VisualPresenter.prototype.viewportChanged = function() {
|
||||
if (this._currentObject)
|
||||
this.highlight(this._currentObject);
|
||||
};
|
||||
viewportChanged: function VisualPresenter_viewportChanged() {
|
||||
if (this._currentObject)
|
||||
this._highlight(this._currentObject);
|
||||
},
|
||||
|
||||
VisualPresenter.prototype.pivotChanged = function(aObject, aNewContext) {
|
||||
this._currentObject = aObject;
|
||||
pivotChanged: function VisualPresenter_pivotChanged(aObject, aNewContext) {
|
||||
this._currentObject = aObject;
|
||||
|
||||
if (!aObject) {
|
||||
this.hide();
|
||||
return;
|
||||
if (!aObject) {
|
||||
this._hide();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
aObject.scrollTo(Ci.nsIAccessibleScrollType.SCROLL_TYPE_ANYWHERE);
|
||||
this._highlight(aObject);
|
||||
} catch (e) {
|
||||
dump('Error getting bounds: ' + e);
|
||||
return;
|
||||
}
|
||||
},
|
||||
|
||||
tabSelected: function VisualPresenter_tabSelected(aDocObj) {
|
||||
let vcPos = aDocObj ? aDocObj.QueryInterface(Ci.nsIAccessibleCursorable).
|
||||
virtualCursor.position : null;
|
||||
|
||||
this.pivotChanged(vcPos);
|
||||
},
|
||||
|
||||
tabStateChanged: function VisualPresenter_tabStateChanged(aDocObj,
|
||||
aPageState) {
|
||||
if (aPageState == 'newdoc')
|
||||
this.pivotChanged(null);
|
||||
},
|
||||
|
||||
// Internals
|
||||
|
||||
_hide: function _hide() {
|
||||
this.highlightBox.style.display = 'none';
|
||||
},
|
||||
|
||||
_highlight: function _highlight(aObject) {
|
||||
let vp = (Services.appinfo.OS == 'Android') ?
|
||||
this.chromeWin.BrowserApp.selectedTab.getViewport() :
|
||||
{ zoom: 1.0, offsetY: 0 };
|
||||
|
||||
let bounds = this._getBounds(aObject, vp.zoom);
|
||||
|
||||
// First hide it to avoid flickering when changing the style.
|
||||
this.highlightBox.style.display = 'none';
|
||||
this.highlightBox.style.top = bounds.top + 'px';
|
||||
this.highlightBox.style.left = bounds.left + 'px';
|
||||
this.highlightBox.style.width = bounds.width + 'px';
|
||||
this.highlightBox.style.height = bounds.height + 'px';
|
||||
this.highlightBox.style.display = 'block';
|
||||
},
|
||||
|
||||
_getBounds: function _getBounds(aObject, aZoom, aStart, aEnd) {
|
||||
let objX = {}, objY = {}, objW = {}, objH = {};
|
||||
|
||||
if (aEnd >= 0 && aStart >= 0 && aEnd != aStart) {
|
||||
// TODO: Get bounds for text ranges. Leaving this blank until we have
|
||||
// proper text navigation in the virtual cursor.
|
||||
}
|
||||
|
||||
aObject.getBounds(objX, objY, objW, objH);
|
||||
|
||||
// Can't specify relative coords in nsIAccessible.getBounds, so we do it.
|
||||
let docX = {}, docY = {};
|
||||
let docRoot = aObject.rootDocument.QueryInterface(Ci.nsIAccessible);
|
||||
docRoot.getBounds(docX, docY, {}, {});
|
||||
|
||||
let rv = {
|
||||
left: Math.round((objX.value - docX.value - this.BORDER_PADDING) * aZoom),
|
||||
top: Math.round((objY.value - docY.value - this.BORDER_PADDING) * aZoom),
|
||||
width: Math.round((objW.value + (this.BORDER_PADDING * 2)) * aZoom),
|
||||
height: Math.round((objH.value + (this.BORDER_PADDING * 2)) * aZoom)
|
||||
};
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
try {
|
||||
aObject.scrollTo(Ci.nsIAccessibleScrollType.SCROLL_TYPE_ANYWHERE);
|
||||
this.highlight(aObject);
|
||||
} catch (e) {
|
||||
dump('Error getting bounds: ' + e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
VisualPresenter.prototype.tabSelected = function(aDocObj) {
|
||||
let vcPos = aDocObj ?
|
||||
aDocObj.QueryInterface(Ci.nsIAccessibleCursorable).virtualCursor.position :
|
||||
null;
|
||||
|
||||
this.pivotChanged(vcPos);
|
||||
};
|
||||
|
||||
VisualPresenter.prototype.tabStateChanged = function(aDocObj, aPageState) {
|
||||
if (aPageState == "newdoc")
|
||||
this.pivotChanged(null);
|
||||
};
|
||||
|
||||
// Internals
|
||||
|
||||
VisualPresenter.prototype.hide = function hide() {
|
||||
this.highlightBox.style.display = 'none';
|
||||
};
|
||||
|
||||
VisualPresenter.prototype.highlight = function(aObject) {
|
||||
let vp = (Services.appinfo.OS == 'Android') ?
|
||||
this.chromeWin.BrowserApp.selectedTab.getViewport() :
|
||||
{ zoom: 1.0, offsetY: 0 };
|
||||
|
||||
let bounds = this.getBounds(aObject, vp.zoom);
|
||||
|
||||
// First hide it to avoid flickering when changing the style.
|
||||
this.highlightBox.style.display = 'none';
|
||||
this.highlightBox.style.top = bounds.top + 'px';
|
||||
this.highlightBox.style.left = bounds.left + 'px';
|
||||
this.highlightBox.style.width = bounds.width + 'px';
|
||||
this.highlightBox.style.height = bounds.height + 'px';
|
||||
this.highlightBox.style.display = 'block';
|
||||
};
|
||||
|
||||
VisualPresenter.prototype.getBounds = function(aObject, aZoom, aStart, aEnd) {
|
||||
let objX = {}, objY = {}, objW = {}, objH = {};
|
||||
|
||||
if (aEnd >= 0 && aStart >= 0 && aEnd != aStart) {
|
||||
// TODO: Get bounds for text ranges. Leaving this blank until we have
|
||||
// proper text navigation in the virtual cursor.
|
||||
}
|
||||
|
||||
aObject.getBounds(objX, objY, objW, objH);
|
||||
|
||||
// Can't specify relative coords in nsIAccessible.getBounds, so we do it.
|
||||
let docX = {}, docY = {};
|
||||
let docRoot = aObject.rootDocument.QueryInterface(Ci.nsIAccessible);
|
||||
docRoot.getBounds(docX, docY, {}, {});
|
||||
|
||||
let rv = {
|
||||
left: Math.round((objX.value - docX.value - this.BORDER_PADDING) * aZoom),
|
||||
top: Math.round((objY.value - docY.value - this.BORDER_PADDING) * aZoom),
|
||||
width: Math.round((objW.value + (this.BORDER_PADDING * 2)) * aZoom),
|
||||
height: Math.round((objH.value + (this.BORDER_PADDING * 2)) * aZoom)
|
||||
};
|
||||
|
||||
return rv;
|
||||
};
|
||||
|
||||
/**
|
||||
* Android presenter. Fires Android a11y events.
|
||||
*/
|
||||
|
||||
const ANDROID_TYPE_VIEW_CLICKED = 0x01;
|
||||
const ANDROID_TYPE_VIEW_LONG_CLICKED = 0x02;
|
||||
const ANDROID_TYPE_VIEW_SELECTED = 0x04;
|
||||
const ANDROID_TYPE_VIEW_FOCUSED = 0x08;
|
||||
const ANDROID_TYPE_VIEW_TEXT_CHANGED = 0x10;
|
||||
const ANDROID_TYPE_WINDOW_STATE_CHANGED = 0x20;
|
||||
|
||||
function AndroidPresenter() {}
|
||||
|
||||
AndroidPresenter.prototype = new Presenter();
|
||||
AndroidPresenter.prototype = {
|
||||
__proto__: Presenter.prototype,
|
||||
|
||||
// Android AccessibilityEvent type constants.
|
||||
ANDROID_VIEW_CLICKED: 0x01,
|
||||
ANDROID_VIEW_LONG_CLICKED: 0x02,
|
||||
ANDROID_VIEW_SELECTED: 0x04,
|
||||
ANDROID_VIEW_FOCUSED: 0x08,
|
||||
ANDROID_VIEW_TEXT_CHANGED: 0x10,
|
||||
ANDROID_WINDOW_STATE_CHANGED: 0x20,
|
||||
|
||||
pivotChanged: function AndroidPresenter_pivotChanged(aObject, aNewContext) {
|
||||
let output = [];
|
||||
for (let i in aNewContext)
|
||||
output.push.apply(output,
|
||||
UtteranceGenerator.genForObject(aNewContext[i]));
|
||||
|
||||
AndroidPresenter.prototype.pivotChanged = function(aObject, aNewContext) {
|
||||
let output = [];
|
||||
for (let i in aNewContext)
|
||||
output.push.apply(output,
|
||||
UtteranceGenerator.genForObject(aNewContext[i]));
|
||||
UtteranceGenerator.genForObject(aObject, true));
|
||||
|
||||
output.push.apply(output,
|
||||
UtteranceGenerator.genForObject(aObject, true));
|
||||
this.sendMessageToJava({
|
||||
gecko: {
|
||||
type: 'Accessibility:Event',
|
||||
eventType: this.ANDROID_VIEW_FOCUSED,
|
||||
text: output
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
this.sendMessageToJava({
|
||||
gecko: {
|
||||
type: 'Accessibility:Event',
|
||||
eventType: ANDROID_TYPE_VIEW_FOCUSED,
|
||||
text: output
|
||||
actionInvoked: function AndroidPresenter_actionInvoked(aObject, aActionName) {
|
||||
this.sendMessageToJava({
|
||||
gecko: {
|
||||
type: 'Accessibility:Event',
|
||||
eventType: this.ANDROID_VIEW_CLICKED,
|
||||
text: UtteranceGenerator.genForAction(aObject, aActionName)
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
tabSelected: function AndroidPresenter_tabSelected(aDocObj) {
|
||||
// Send a pivot change message with the full context utterance for this doc.
|
||||
let vcDoc = aDocObj.QueryInterface(Ci.nsIAccessibleCursorable);
|
||||
let context = [];
|
||||
|
||||
let parent = vcDoc.virtualCursor.position || aDocObj;
|
||||
while ((parent = parent.parent)) {
|
||||
context.push(parent);
|
||||
if (parent == aDocObj)
|
||||
break;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
AndroidPresenter.prototype.actionInvoked = function(aObject, aActionName) {
|
||||
this.sendMessageToJava({
|
||||
gecko: {
|
||||
context.reverse();
|
||||
|
||||
this.pivotChanged(vcDoc.virtualCursor.position || aDocObj, context);
|
||||
},
|
||||
|
||||
tabStateChanged: function AndroidPresenter_tabStateChanged(aDocObj,
|
||||
aPageState) {
|
||||
let stateUtterance = UtteranceGenerator.
|
||||
genForTabStateChange(aDocObj, aPageState);
|
||||
|
||||
if (!stateUtterance.length)
|
||||
return;
|
||||
|
||||
this.sendMessageToJava({
|
||||
gecko: {
|
||||
type: 'Accessibility:Event',
|
||||
eventType: this.ANDROID_VIEW_TEXT_CHANGED,
|
||||
text: stateUtterance,
|
||||
addedCount: stateUtterance.join(' ').length,
|
||||
removedCount: 0,
|
||||
fromIndex: 0
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
textChanged: function AndroidPresenter_textChanged(aIsInserted, aStart,
|
||||
aLength, aText,
|
||||
aModifiedText) {
|
||||
let androidEvent = {
|
||||
type: 'Accessibility:Event',
|
||||
eventType: ANDROID_TYPE_VIEW_CLICKED,
|
||||
text: UtteranceGenerator.genForAction(aObject, aActionName)
|
||||
eventType: this.ANDROID_VIEW_TEXT_CHANGED,
|
||||
text: [aText],
|
||||
fromIndex: aStart
|
||||
};
|
||||
|
||||
if (aIsInserted) {
|
||||
androidEvent.addedCount = aLength;
|
||||
androidEvent.beforeText =
|
||||
aText.substring(0, aStart) + aText.substring(aStart + aLength);
|
||||
} else {
|
||||
androidEvent.removedCount = aLength;
|
||||
androidEvent.beforeText =
|
||||
aText.substring(0, aStart) + aModifiedText + aText.substring(aStart);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
AndroidPresenter.prototype.tabSelected = function(aDocObj) {
|
||||
// Send a pivot change message with the full context utterance for this doc.
|
||||
let vcDoc = aDocObj.QueryInterface(Ci.nsIAccessibleCursorable);
|
||||
let context = [];
|
||||
this.sendMessageToJava({gecko: androidEvent});
|
||||
},
|
||||
|
||||
let parent = vcDoc.virtualCursor.position || aDocObj;
|
||||
while ((parent = parent.parent)) {
|
||||
context.push(parent);
|
||||
if (parent == aDocObj)
|
||||
break;
|
||||
sendMessageToJava: function AndroidPresenter_sendMessageTojava(aMessage) {
|
||||
return Cc['@mozilla.org/android/bridge;1'].
|
||||
getService(Ci.nsIAndroidBridge).
|
||||
handleGeckoMessage(JSON.stringify(aMessage));
|
||||
}
|
||||
|
||||
context.reverse();
|
||||
|
||||
this.pivotChanged(vcDoc.virtualCursor.position || aDocObj, context);
|
||||
};
|
||||
|
||||
AndroidPresenter.prototype.tabStateChanged = function(aDocObj, aPageState) {
|
||||
let stateUtterance = UtteranceGenerator.
|
||||
genForTabStateChange(aDocObj, aPageState);
|
||||
|
||||
if (!stateUtterance.length)
|
||||
return;
|
||||
|
||||
this.sendMessageToJava({
|
||||
gecko: {
|
||||
type: 'Accessibility:Event',
|
||||
eventType: ANDROID_TYPE_VIEW_TEXT_CHANGED,
|
||||
text: stateUtterance,
|
||||
addedCount: stateUtterance.join(' ').length,
|
||||
removedCount: 0,
|
||||
fromIndex: 0
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
AndroidPresenter.prototype.textChanged = function(aIsInserted, aStart, aLength, aText, aModifiedText) {
|
||||
let androidEvent = {
|
||||
type: 'Accessibility:Event',
|
||||
eventType: ANDROID_TYPE_VIEW_TEXT_CHANGED,
|
||||
text: [aText],
|
||||
fromIndex: aStart
|
||||
};
|
||||
|
||||
if (aIsInserted) {
|
||||
androidEvent.addedCount = aLength;
|
||||
androidEvent.beforeText =
|
||||
aText.substring(0, aStart) + aText.substring(aStart + aLength);
|
||||
} else {
|
||||
androidEvent.removedCount = aLength;
|
||||
androidEvent.beforeText =
|
||||
aText.substring(0, aStart) + aModifiedText + aText.substring(aStart);
|
||||
}
|
||||
|
||||
this.sendMessageToJava({gecko: androidEvent});
|
||||
};
|
||||
|
||||
AndroidPresenter.prototype.sendMessageToJava = function(aMessage) {
|
||||
return Cc['@mozilla.org/android/bridge;1'].
|
||||
getService(Ci.nsIAndroidBridge).
|
||||
handleGeckoMessage(JSON.stringify(aMessage));
|
||||
};
|
||||
|
||||
/**
|
||||
@ -325,8 +335,10 @@ AndroidPresenter.prototype.sendMessageToJava = function(aMessage) {
|
||||
|
||||
function DummyAndroidPresenter() {}
|
||||
|
||||
DummyAndroidPresenter.prototype = new AndroidPresenter();
|
||||
DummyAndroidPresenter.prototype = {
|
||||
__proto__: AndroidPresenter.prototype,
|
||||
|
||||
DummyAndroidPresenter.prototype.sendMessageToJava = function(aMessage) {
|
||||
dump(JSON.stringify(aMessage, null, 2) + '\n');
|
||||
sendMessageToJava: function DummyAndroidPresenter_sendMessageToJava(aMsg) {
|
||||
dump(JSON.stringify(aMsg, null, 2) + '\n');
|
||||
}
|
||||
};
|
||||
|
@ -65,10 +65,10 @@ var UtteranceGenerator = {
|
||||
* @return {Array} Two string array. The first string describes the object
|
||||
* and its states. The second string is the object's name. Some object
|
||||
* types may have the description or name omitted, instead an empty string
|
||||
* is returned as a placeholder. Whether the object's description or it's role
|
||||
* is included is determined by {@link verbosityRoleMap}.
|
||||
* is returned as a placeholder. Whether the object's description or it's
|
||||
* role is included is determined by {@link verbosityRoleMap}.
|
||||
*/
|
||||
genForObject: function(aAccessible, aForceName) {
|
||||
genForObject: function genForObject(aAccessible, aForceName) {
|
||||
let roleString = gAccRetrieval.getStringRole(aAccessible.role);
|
||||
|
||||
let func = this.objectUtteranceFunctions[roleString] ||
|
||||
@ -91,7 +91,7 @@ var UtteranceGenerator = {
|
||||
* {@link gActionMap}.
|
||||
* @return {Array} A one string array with the action.
|
||||
*/
|
||||
genForAction: function(aObject, aActionName) {
|
||||
genForAction: function genForAction(aObject, aActionName) {
|
||||
return [gStringBundle.GetStringFromName(this.gActionMap[aActionName])];
|
||||
},
|
||||
|
||||
@ -103,7 +103,7 @@ var UtteranceGenerator = {
|
||||
* {@link Presenter.tabStateChanged}.
|
||||
* @return {Array} The tab state utterace.
|
||||
*/
|
||||
genForTabStateChange: function (aObject, aTabState) {
|
||||
genForTabStateChange: function genForTabStateChange(aObject, aTabState) {
|
||||
switch (aTabState) {
|
||||
case 'newtab':
|
||||
return [gStringBundle.GetStringFromName('tabNew')];
|
||||
@ -177,7 +177,8 @@ var UtteranceGenerator = {
|
||||
objectUtteranceFunctions: {
|
||||
defaultFunc: function defaultFunc(aAccessible, aRoleStr, aFlags) {
|
||||
let name = (aFlags & INCLUDE_NAME) ? (aAccessible.name || '') : '';
|
||||
let desc = (aFlags & INCLUDE_ROLE) ? this._getLocalizedRole(aRoleStr) : '';
|
||||
let desc = (aFlags & INCLUDE_ROLE) ?
|
||||
this._getLocalizedRole(aRoleStr) : '';
|
||||
|
||||
let utterance = [];
|
||||
|
||||
@ -207,7 +208,7 @@ var UtteranceGenerator = {
|
||||
return utterance;
|
||||
},
|
||||
|
||||
heading: function(aAccessible, aRoleStr, aFlags) {
|
||||
heading: function heading(aAccessible, aRoleStr, aFlags) {
|
||||
let name = (aFlags & INCLUDE_NAME) ? (aAccessible.name || '') : '';
|
||||
let level = {};
|
||||
aAccessible.groupPosition(level, {}, {});
|
||||
@ -220,7 +221,7 @@ var UtteranceGenerator = {
|
||||
return utterance;
|
||||
},
|
||||
|
||||
listitem: function(aAccessible, aRoleStr, aFlags) {
|
||||
listitem: function listitem(aAccessible, aRoleStr, aFlags) {
|
||||
let name = (aFlags & INCLUDE_NAME) ? (aAccessible.name || '') : '';
|
||||
let localizedRole = this._getLocalizedRole(aRoleStr);
|
||||
let itemno = {};
|
||||
|
@ -18,16 +18,20 @@ var gAccRetrieval = Cc['@mozilla.org/accessibleRetrieval;1'].
|
||||
getService(Ci.nsIAccessibleRetrieval);
|
||||
|
||||
var VirtualCursorController = {
|
||||
NOT_EDITABLE: 0,
|
||||
SINGLE_LINE_EDITABLE: 1,
|
||||
MULTI_LINE_EDITABLE: 2,
|
||||
|
||||
attach: function attach(aWindow) {
|
||||
this.chromeWin = aWindow;
|
||||
this.chromeWin.document.addEventListener('keypress', this.onkeypress, true);
|
||||
this.chromeWin.document.addEventListener('keypress', this, true);
|
||||
},
|
||||
|
||||
detach: function detach() {
|
||||
this.chromeWin.document.removeEventListener('keypress', this.onkeypress, true);
|
||||
this.chromeWin.document.removeEventListener('keypress', this, true);
|
||||
},
|
||||
|
||||
getBrowserApp: function getBrowserApp() {
|
||||
_getBrowserApp: function _getBrowserApp() {
|
||||
switch (Services.appinfo.OS) {
|
||||
case 'Android':
|
||||
return this.chromeWin.BrowserApp;
|
||||
@ -36,39 +40,49 @@ var VirtualCursorController = {
|
||||
}
|
||||
},
|
||||
|
||||
onkeypress: function onkeypress(aEvent) {
|
||||
let document = VirtualCursorController.getBrowserApp().
|
||||
selectedBrowser.contentDocument;
|
||||
|
||||
dump('keypress ' + aEvent.keyCode + '\n');
|
||||
handleEvent: function handleEvent(aEvent) {
|
||||
let document = this._getBrowserApp().selectedBrowser.contentDocument;
|
||||
let target = aEvent.target;
|
||||
|
||||
switch (aEvent.keyCode) {
|
||||
case aEvent.DOM_VK_END:
|
||||
VirtualCursorController.moveForward(document, true);
|
||||
this.moveForward(document, true);
|
||||
break;
|
||||
case aEvent.DOM_VK_HOME:
|
||||
VirtualCursorController.moveBackward(document, true);
|
||||
this.moveBackward(document, true);
|
||||
break;
|
||||
case aEvent.DOM_VK_RIGHT:
|
||||
VirtualCursorController.moveForward(document, aEvent.shiftKey);
|
||||
if (this._isEditableText(target) &&
|
||||
target.selectionEnd != target.textLength)
|
||||
// Don't move forward if caret is not at end of entry.
|
||||
// XXX: Fix for rtl
|
||||
return;
|
||||
this.moveForward(document, aEvent.shiftKey);
|
||||
break;
|
||||
case aEvent.DOM_VK_LEFT:
|
||||
VirtualCursorController.moveBackward(document, aEvent.shiftKey);
|
||||
if (this._isEditableText(target) &&
|
||||
target.selectionEnd != 0)
|
||||
// Don't move backward if caret is not at start of entry.
|
||||
// XXX: Fix for rtl
|
||||
return;
|
||||
this.moveBackward(document, aEvent.shiftKey);
|
||||
break;
|
||||
case aEvent.DOM_VK_UP:
|
||||
if (this._isEditableText(target) == this.MULTI_LINE_EDITABLE &&
|
||||
target.selectionEnd != 0)
|
||||
// Don't blur content if caret is not at start of text area.
|
||||
return;
|
||||
if (Services.appinfo.OS == 'Android')
|
||||
// Return focus to browser chrome, which in Android is a native widget.
|
||||
// Return focus to native Android browser chrome.
|
||||
Cc['@mozilla.org/android/bridge;1'].
|
||||
getService(Ci.nsIAndroidBridge).handleGeckoMessage(
|
||||
JSON.stringify({ gecko: { type: 'ToggleChrome:Focus' } }));
|
||||
break;
|
||||
case aEvent.DOM_VK_RETURN:
|
||||
// XXX: It is true that desktop does not map the keypad enter key to
|
||||
// DOM_VK_ENTER. So for desktop we require a ctrl+return instead.
|
||||
if (Services.appinfo.OS == 'Android' || !aEvent.ctrlKey)
|
||||
return;
|
||||
case aEvent.DOM_VK_ENTER:
|
||||
VirtualCursorController.activateCurrent(document);
|
||||
if (this._isEditableText(target))
|
||||
return;
|
||||
this.activateCurrent(document);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
@ -78,6 +92,18 @@ var VirtualCursorController = {
|
||||
aEvent.stopPropagation();
|
||||
},
|
||||
|
||||
_isEditableText: function _isEditableText(aElement) {
|
||||
// XXX: Support contentEditable and design mode
|
||||
if (aElement instanceof Ci.nsIDOMHTMLInputElement &&
|
||||
aElement.mozIsTextField(false))
|
||||
return this.SINGLE_LINE_EDITABLE;
|
||||
|
||||
if (aElement instanceof Ci.nsIDOMHTMLTextAreaElement)
|
||||
return this.MULTI_LINE_EDITABLE;
|
||||
|
||||
return this.NOT_EDITABLE;
|
||||
},
|
||||
|
||||
moveForward: function moveForward(document, last) {
|
||||
let virtualCursor = this.getVirtualCursor(document);
|
||||
if (last) {
|
||||
@ -110,7 +136,7 @@ var VirtualCursorController = {
|
||||
},
|
||||
|
||||
SimpleTraversalRule: {
|
||||
getMatchRoles: function(aRules) {
|
||||
getMatchRoles: function SimpleTraversalRule_getmatchRoles(aRules) {
|
||||
aRules.value = this._matchRoles;
|
||||
return this._matchRoles.length;
|
||||
},
|
||||
@ -118,7 +144,7 @@ var VirtualCursorController = {
|
||||
preFilter: Ci.nsIAccessibleTraversalRule.PREFILTER_DEFUNCT |
|
||||
Ci.nsIAccessibleTraversalRule.PREFILTER_INVISIBLE,
|
||||
|
||||
match: function(aAccessible) {
|
||||
match: function SimpleTraversalRule_match(aAccessible) {
|
||||
switch (aAccessible.role) {
|
||||
case Ci.nsIAccessibleRole.ROLE_COMBOBOX:
|
||||
// We don't want to ignore the subtree because this is often
|
||||
|
@ -8,6 +8,8 @@ const FILTER_MATCH = nsIAccessibleTraversalRule.FILTER_MATCH;
|
||||
const FILTER_IGNORE = nsIAccessibleTraversalRule.FILTER_IGNORE;
|
||||
const FILTER_IGNORE_SUBTREE = nsIAccessibleTraversalRule.FILTER_IGNORE_SUBTREE;
|
||||
|
||||
const NS_ERROR_NOT_IN_TREE = 0x80780026;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Traversal rules
|
||||
|
||||
@ -68,13 +70,13 @@ var ObjectTraversalRule =
|
||||
/**
|
||||
* A checker for virtual cursor changed events.
|
||||
*/
|
||||
function virtualCursorChangedChecker(aDocAcc, aIdOrNameOrAcc, aTextOffsets)
|
||||
function VCChangedChecker(aDocAcc, aIdOrNameOrAcc, aTextOffsets)
|
||||
{
|
||||
this.__proto__ = new invokerChecker(EVENT_VIRTUALCURSOR_CHANGED, aDocAcc);
|
||||
|
||||
this.check = function virtualCursorChangedChecker_check(aEvent)
|
||||
this.check = function VCChangedChecker_check(aEvent)
|
||||
{
|
||||
SimpleTest.info("virtualCursorChangedChecker_check");
|
||||
SimpleTest.info("VCChangedChecker_check");
|
||||
|
||||
var event = null;
|
||||
try {
|
||||
@ -100,7 +102,7 @@ function virtualCursorChangedChecker(aDocAcc, aIdOrNameOrAcc, aTextOffsets)
|
||||
"wrong end offset");
|
||||
}
|
||||
|
||||
var prevPosAndOffset = virtualCursorChangedChecker.
|
||||
var prevPosAndOffset = VCChangedChecker.
|
||||
getPreviousPosAndOffset(aDocAcc.virtualCursor);
|
||||
|
||||
if (prevPosAndOffset) {
|
||||
@ -114,36 +116,36 @@ function virtualCursorChangedChecker(aDocAcc, aIdOrNameOrAcc, aTextOffsets)
|
||||
};
|
||||
}
|
||||
|
||||
virtualCursorChangedChecker.prevPosAndOffset = {};
|
||||
VCChangedChecker.prevPosAndOffset = {};
|
||||
|
||||
virtualCursorChangedChecker.storePreviousPosAndOffset =
|
||||
VCChangedChecker.storePreviousPosAndOffset =
|
||||
function storePreviousPosAndOffset(aPivot)
|
||||
{
|
||||
virtualCursorChangedChecker.prevPosAndOffset[aPivot] =
|
||||
VCChangedChecker.prevPosAndOffset[aPivot] =
|
||||
{position: aPivot.position,
|
||||
startOffset: aPivot.startOffset,
|
||||
endOffset: aPivot.endOffset};
|
||||
};
|
||||
|
||||
virtualCursorChangedChecker.getPreviousPosAndOffset =
|
||||
VCChangedChecker.getPreviousPosAndOffset =
|
||||
function getPreviousPosAndOffset(aPivot)
|
||||
{
|
||||
return virtualCursorChangedChecker.prevPosAndOffset[aPivot];
|
||||
return VCChangedChecker.prevPosAndOffset[aPivot];
|
||||
};
|
||||
|
||||
/**
|
||||
* Set a text range in the pivot and wait for virtual cursor change event.
|
||||
*
|
||||
* @param aDocAcc document that manages the virtual cursor
|
||||
* @param aTextAccessible accessible to set to virtual cursor's position
|
||||
* @param aTextOffsets start and end offsets of text range to set in virtual
|
||||
* cursor
|
||||
* @param aDocAcc [in] document that manages the virtual cursor
|
||||
* @param aTextAccessible [in] accessible to set to virtual cursor's position
|
||||
* @param aTextOffsets [in] start and end offsets of text range to set in
|
||||
* virtual cursor.
|
||||
*/
|
||||
function setVirtualCursorRangeInvoker(aDocAcc, aTextAccessible, aTextOffsets)
|
||||
function setVCRangeInvoker(aDocAcc, aTextAccessible, aTextOffsets)
|
||||
{
|
||||
this.invoke = function virtualCursorChangedInvoker_invoke()
|
||||
{
|
||||
virtualCursorChangedChecker.
|
||||
VCChangedChecker.
|
||||
storePreviousPosAndOffset(aDocAcc.virtualCursor);
|
||||
SimpleTest.info(prettyName(aTextAccessible) + " " + aTextOffsets);
|
||||
aDocAcc.virtualCursor.setTextRange(aTextAccessible,
|
||||
@ -151,45 +153,44 @@ function setVirtualCursorRangeInvoker(aDocAcc, aTextAccessible, aTextOffsets)
|
||||
aTextOffsets[1]);
|
||||
};
|
||||
|
||||
this.getID = function setVirtualCursorRangeInvoker_getID()
|
||||
this.getID = function setVCRangeInvoker_getID()
|
||||
{
|
||||
return "Set offset in " + prettyName(aTextAccessible) +
|
||||
" to (" + aTextOffsets[0] + ", " + aTextOffsets[1] + ")";
|
||||
}
|
||||
};
|
||||
|
||||
this.eventSeq = [
|
||||
new virtualCursorChangedChecker(aDocAcc, aTextAccessible, aTextOffsets)
|
||||
new VCChangedChecker(aDocAcc, aTextAccessible, aTextOffsets)
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the pivot and wait for virtual cursor change event.
|
||||
*
|
||||
* @param aDocAcc document that manages the virtual cursor
|
||||
* @param aPivotMoveMethod method to test (ie. "moveNext", "moveFirst", etc.)
|
||||
* @param aRule traversal rule object
|
||||
* @param aIdOrNameOrAcc id, accessivle or accessible name to expect virtual
|
||||
* cursor to land on after performing move method.
|
||||
* @param aDocAcc [in] document that manages the virtual cursor
|
||||
* @param aPivotMoveMethod [in] method to test (ie. "moveNext", "moveFirst", etc.)
|
||||
* @param aRule [in] traversal rule object
|
||||
* @param aIdOrNameOrAcc [in] id, accessivle or accessible name to expect
|
||||
* virtual cursor to land on after performing move method.
|
||||
*/
|
||||
function setVirtualCursorPosInvoker(aDocAcc, aPivotMoveMethod, aRule,
|
||||
aIdOrNameOrAcc)
|
||||
function setVCPosInvoker(aDocAcc, aPivotMoveMethod, aRule, aIdOrNameOrAcc)
|
||||
{
|
||||
this.invoke = function virtualCursorChangedInvoker_invoke()
|
||||
{
|
||||
virtualCursorChangedChecker.
|
||||
VCChangedChecker.
|
||||
storePreviousPosAndOffset(aDocAcc.virtualCursor);
|
||||
var moved = aDocAcc.virtualCursor[aPivotMoveMethod](aRule);
|
||||
SimpleTest.ok((aIdOrNameOrAcc && moved) || (!aIdOrNameOrAcc && !moved),
|
||||
"moved pivot");
|
||||
};
|
||||
|
||||
this.getID = function setVirtualCursorPosInvoker_getID()
|
||||
this.getID = function setVCPosInvoker_getID()
|
||||
{
|
||||
return "Do " + (aIdOrNameOrAcc ? "" : "no-op ") + aPivotMoveMethod;
|
||||
}
|
||||
};
|
||||
|
||||
if (aIdOrNameOrAcc) {
|
||||
this.eventSeq = [ new virtualCursorChangedChecker(aDocAcc, aIdOrNameOrAcc) ];
|
||||
this.eventSeq = [ new VCChangedChecker(aDocAcc, aIdOrNameOrAcc) ];
|
||||
} else {
|
||||
this.eventSeq = [];
|
||||
this.unexpectedEventSeq = [
|
||||
@ -202,45 +203,137 @@ function setVirtualCursorPosInvoker(aDocAcc, aPivotMoveMethod, aRule,
|
||||
* Add invokers to a queue to test a rule and an expected sequence of element ids
|
||||
* or accessible names for that rule in the given document.
|
||||
*
|
||||
* @param aQueue event queue in which to push invoker sequence.
|
||||
* @param aDocAcc the managing document of the virtual cursor we are testing
|
||||
* @param aRule the traversal rule to use in the invokers
|
||||
* @param aSequence a sequence of accessible names or elemnt ids to expect with
|
||||
* the given rule in the given document
|
||||
* @param aQueue [in] event queue in which to push invoker sequence.
|
||||
* @param aDocAcc [in] the managing document of the virtual cursor we are testing
|
||||
* @param aRule [in] the traversal rule to use in the invokers
|
||||
* @param aSequence [in] a sequence of accessible names or elemnt ids to expect with
|
||||
* the given rule in the given document
|
||||
*/
|
||||
function queueTraversalSequence(aQueue, aDocAcc, aRule, aSequence)
|
||||
{
|
||||
aDocAcc.virtualCursor.position = null;
|
||||
|
||||
for (var i = 0; i < aSequence.length; i++) {
|
||||
var invoker = new setVirtualCursorPosInvoker(aDocAcc, "moveNext",
|
||||
aRule, aSequence[i]);
|
||||
var invoker =
|
||||
new setVCPosInvoker(aDocAcc, "moveNext", aRule, aSequence[i]);
|
||||
aQueue.push(invoker);
|
||||
}
|
||||
|
||||
// No further more matches for given rule, expect no virtual cursor changes.
|
||||
aQueue.push(new setVirtualCursorPosInvoker(aDocAcc, "moveNext", aRule, null));
|
||||
aQueue.push(new setVCPosInvoker(aDocAcc, "moveNext", aRule, null));
|
||||
|
||||
for (var i = aSequence.length-2; i >= 0; i--) {
|
||||
var invoker = new setVirtualCursorPosInvoker(aDocAcc, "movePrevious",
|
||||
aRule, aSequence[i])
|
||||
var invoker =
|
||||
new setVCPosInvoker(aDocAcc, "movePrevious", aRule, aSequence[i]);
|
||||
aQueue.push(invoker);
|
||||
}
|
||||
|
||||
// No previous more matches for given rule, expect no virtual cursor changes.
|
||||
aQueue.push(new setVirtualCursorPosInvoker(aDocAcc, "movePrevious", aRule, null));
|
||||
aQueue.push(new setVCPosInvoker(aDocAcc, "movePrevious", aRule, null));
|
||||
|
||||
aQueue.push(new setVirtualCursorPosInvoker(
|
||||
aDocAcc, "moveLast", aRule, aSequence[aSequence.length - 1]));
|
||||
aQueue.push(new setVCPosInvoker(aDocAcc, "moveLast", aRule,
|
||||
aSequence[aSequence.length - 1]));
|
||||
|
||||
// No further more matches for given rule, expect no virtual cursor changes.
|
||||
aQueue.push(new setVirtualCursorPosInvoker(aDocAcc, "moveNext", aRule, null));
|
||||
aQueue.push(new setVCPosInvoker(aDocAcc, "moveNext", aRule, null));
|
||||
|
||||
aQueue.push(new setVirtualCursorPosInvoker(
|
||||
aDocAcc, "moveFirst", aRule, aSequence[0]));
|
||||
aQueue.push(new setVCPosInvoker(aDocAcc, "moveFirst", aRule, aSequence[0]));
|
||||
|
||||
// No previous more matches for given rule, expect no virtual cursor changes.
|
||||
aQueue.push(new setVirtualCursorPosInvoker(aDocAcc, "movePrevious", aRule, null));
|
||||
aQueue.push(new setVCPosInvoker(aDocAcc, "movePrevious", aRule, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* A checker for removing an accessible while the virtual cursor is on it.
|
||||
*/
|
||||
function removeVCPositionChecker(aDocAcc, aHiddenParentAcc)
|
||||
{
|
||||
this.__proto__ = new invokerChecker(EVENT_REORDER, aHiddenParentAcc);
|
||||
|
||||
this.check = function removeVCPositionChecker_check(aEvent) {
|
||||
var errorResult = 0;
|
||||
try {
|
||||
aDocAcc.virtualCursor.moveNext(ObjectTraversalRule);
|
||||
} catch (x) {
|
||||
errorResult = x.result;
|
||||
}
|
||||
SimpleTest.is(
|
||||
errorResult, NS_ERROR_NOT_IN_TREE,
|
||||
"Expecting NOT_IN_TREE error when moving pivot from invalid position.");
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Put the virtual cursor's position on an object, and then remove it.
|
||||
*
|
||||
* @param aDocAcc [in] document that manages the virtual cursor
|
||||
* @param aPosNode [in] DOM node to hide after virtual cursor's position is
|
||||
* set to it.
|
||||
*/
|
||||
function removeVCPositionInvoker(aDocAcc, aPosNode)
|
||||
{
|
||||
this.accessible = getAccessible(aPosNode);
|
||||
this.invoke = function removeVCPositionInvoker_invoke()
|
||||
{
|
||||
aDocAcc.virtualCursor.position = this.accessible;
|
||||
aPosNode.parentNode.removeChild(aPosNode);
|
||||
};
|
||||
|
||||
this.getID = function removeVCPositionInvoker_getID()
|
||||
{
|
||||
return "Bring virtual cursor to accessible, and remove its DOM node.";
|
||||
};
|
||||
|
||||
this.eventSeq = [
|
||||
new removeVCPositionChecker(aDocAcc, this.accessible.parent)
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* A checker for removing the pivot root and then calling moveFirst, and
|
||||
* checking that an exception is thrown.
|
||||
*/
|
||||
function removeVCRootChecker(aPivot)
|
||||
{
|
||||
this.__proto__ = new invokerChecker(EVENT_REORDER, aPivot.root.parent);
|
||||
|
||||
this.check = function removeVCRootChecker_check(aEvent) {
|
||||
var errorResult = 0;
|
||||
try {
|
||||
aPivot.moveLast(ObjectTraversalRule);
|
||||
} catch (x) {
|
||||
errorResult = x.result;
|
||||
}
|
||||
SimpleTest.is(
|
||||
errorResult, NS_ERROR_NOT_IN_TREE,
|
||||
"Expecting NOT_IN_TREE error when moving pivot from invalid position.");
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a pivot, remove its root, and perform an operation where the root is
|
||||
* needed.
|
||||
*
|
||||
* @param aRootNode [in] DOM node of which accessible will be the root of the
|
||||
* pivot. Should have more than one child.
|
||||
*/
|
||||
function removeVCRootInvoker(aRootNode)
|
||||
{
|
||||
this.pivot = gAccRetrieval.createAccessiblePivot(getAccessible(aRootNode));
|
||||
this.invoke = function removeVCRootInvoker_invoke()
|
||||
{
|
||||
this.pivot.position = this.pivot.root.firstChild;
|
||||
aRootNode.parentNode.removeChild(aRootNode);
|
||||
};
|
||||
|
||||
this.getID = function removeVCRootInvoker_getID()
|
||||
{
|
||||
return "Remove root of pivot from tree.";
|
||||
};
|
||||
|
||||
this.eventSeq = [
|
||||
new removeVCRootChecker(this.pivot)
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -17,10 +17,11 @@
|
||||
<iframe
|
||||
src="data:text/html,<html><body>An <i>embedded</i> document.</body></html>">
|
||||
</iframe>
|
||||
<p>
|
||||
<a href="http://mozilla.org" title="Link 1 title">Link 1</a>
|
||||
<a href="http://mozilla.org" title="Link 2 title">Link 2</a>
|
||||
<a href="http://mozilla.org" title="Link 3 title">Link 3</a>
|
||||
</p>
|
||||
<div id="hide-me">Hide me</div>
|
||||
<p id="links">
|
||||
<a href="http://mozilla.org" title="Link 1 title">Link 1</a>
|
||||
<a href="http://mozilla.org" title="Link 2 title">Link 2</a>
|
||||
<a href="http://mozilla.org" title="Link 3 title">Link 3</a>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -60,15 +60,22 @@
|
||||
'dolor', ' sit amet. Integer vitae urna leo, id ',
|
||||
'semper', ' nulla. ', 'Second Section Title',
|
||||
'Sed accumsan luctus lacus, vitae mollis arcu tristique vulputate.',
|
||||
'An ', 'embedded', ' document.', 'Link 1', 'Link 2', 'Link 3']);
|
||||
'An ', 'embedded', ' document.', 'Hide me', 'Link 1', 'Link 2',
|
||||
'Link 3']);
|
||||
|
||||
// Just a random smoke test to see if our setTextRange works.
|
||||
gQueue.push(
|
||||
new setVirtualCursorRangeInvoker(
|
||||
new setVCRangeInvoker(
|
||||
docAcc,
|
||||
getAccessible(doc.getElementById('paragraph-2'), nsIAccessibleText),
|
||||
[2,6]));
|
||||
|
||||
gQueue.push(new removeVCPositionInvoker(
|
||||
docAcc, doc.getElementById('hide-me')));
|
||||
|
||||
gQueue.push(new removeVCRootInvoker(
|
||||
doc.getElementById('links')));
|
||||
|
||||
gQueue.invoke();
|
||||
}
|
||||
|
||||
|
@ -186,8 +186,6 @@ ifdef MOZ_DEBUG
|
||||
MAC_APP_NAME := $(MAC_APP_NAME)Debug
|
||||
endif
|
||||
|
||||
LOWER_MAC_APP_NAME = $(shell echo $(MAC_APP_NAME) | tr '[A-Z]' '[a-z]')
|
||||
|
||||
AB_CD = $(MOZ_UI_LOCALE)
|
||||
|
||||
AB := $(firstword $(subst -, ,$(AB_CD)))
|
||||
@ -201,6 +199,8 @@ else
|
||||
APPFILES = MacOS
|
||||
endif
|
||||
|
||||
MAC_BUNDLE_VERSION = $(shell $(PYTHON) $(srcdir)/macversion.py --version=$(MOZ_APP_VERSION) --buildid=$(DEPTH)/config/buildid)
|
||||
|
||||
libs-preqs = \
|
||||
$(call mkdir_deps,$(dist_dest)/Contents/MacOS) \
|
||||
$(call mkdir_deps,$(dist_dest)/Contents/Resources/$(AB).lproj) \
|
||||
@ -210,7 +210,7 @@ libs-preqs = \
|
||||
libs repackage:: $(PROGRAM) $(libs-preqs)
|
||||
rsync -a --exclude "*.in" $(srcdir)/macbuild/Contents $(dist_dest) --exclude English.lproj
|
||||
rsync -a --exclude "*.in" $(srcdir)/macbuild/Contents/Resources/English.lproj/ $(dist_dest)/Contents/Resources/$(AB).lproj
|
||||
sed -e "s/%APP_VERSION%/$(MOZ_APP_VERSION)/" -e "s/%MAC_APP_NAME%/$(MAC_APP_NAME)/" -e "s/%LOWER_MAC_APP_NAME%/$(LOWER_MAC_APP_NAME)/" $(srcdir)/macbuild/Contents/Info.plist.in > $(dist_dest)/Contents/Info.plist
|
||||
sed -e "s/%APP_VERSION%/$(MOZ_APP_VERSION)/" -e "s/%MAC_APP_NAME%/$(MAC_APP_NAME)/" -e "s/%MOZ_MACBUNDLE_ID%/$(MOZ_MACBUNDLE_ID)/" -e "s/%MAC_BUNDLE_VERSION%/$(MAC_BUNDLE_VERSION)/" $(srcdir)/macbuild/Contents/Info.plist.in > $(dist_dest)/Contents/Info.plist
|
||||
sed -e "s/%MAC_APP_NAME%/$(MAC_APP_NAME)/" $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | iconv -f UTF-8 -t UTF-16 > $(dist_dest)/Contents/Resources/$(AB).lproj/InfoPlist.strings
|
||||
rsync -a $(DIST)/bin/ $(dist_dest)/Contents/$(APPFILES)
|
||||
ifdef LIBXUL_SDK
|
||||
|
@ -149,7 +149,7 @@
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>firefox</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>org.mozilla.%LOWER_MAC_APP_NAME%</string>
|
||||
<string>%MOZ_MACBUNDLE_ID%</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
@ -200,7 +200,7 @@
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>%APP_VERSION%</string>
|
||||
<string>%MAC_BUNDLE_VERSION%</string>
|
||||
<key>NSAppleScriptEnabled</key>
|
||||
<true/>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
|
40
browser/app/macversion.py
Normal file
@ -0,0 +1,40 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
from optparse import OptionParser
|
||||
import sys
|
||||
import re
|
||||
|
||||
o = OptionParser()
|
||||
o.add_option("--buildid", dest="buildid")
|
||||
o.add_option("--version", dest="version")
|
||||
|
||||
(options, args) = o.parse_args()
|
||||
|
||||
if not options.buildid:
|
||||
print >>sys.stderr, "--buildid is required"
|
||||
sys.exit(1)
|
||||
|
||||
if not options.version:
|
||||
print >>sys.stderr, "--version is required"
|
||||
sys.exit(1)
|
||||
|
||||
# We want to build a version number that matches the format allowed for
|
||||
# CFBundleVersion (nnnnn[.nn[.nn]]). We'll incorporate both the version
|
||||
# number as well as the date, so that it changes at least daily (for nightly
|
||||
# builds), but also so that newly-built older versions (e.g. beta build) aren't
|
||||
# considered "newer" than previously-built newer versions (e.g. a trunk nightly)
|
||||
|
||||
buildid = open(options.buildid, 'r').read()
|
||||
|
||||
# extract only the major version (i.e. "14" from "14.0b1")
|
||||
majorVersion = re.match(r'^(\d+)[^\d].*', options.version).group(1)
|
||||
# last two digits of the year
|
||||
twodigityear = buildid[2:4]
|
||||
month = buildid[4:6]
|
||||
if month[0] == '0':
|
||||
month = month[1]
|
||||
day = buildid[6:8]
|
||||
if day[0] == '0':
|
||||
day = day[1]
|
||||
|
||||
print '%s.%s.%s' % (majorVersion + twodigityear, month, day)
|
@ -65,11 +65,6 @@
|
||||
margin: 0 40px;
|
||||
}
|
||||
|
||||
.text-link:-moz-focusring,
|
||||
.bottom-link:-moz-focusring {
|
||||
outline: 1px dotted;
|
||||
}
|
||||
|
||||
#currentChannel {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
@ -308,12 +308,30 @@
|
||||
</menu>
|
||||
#include browser-charsetmenu.inc
|
||||
<menuseparator/>
|
||||
#ifdef XP_MACOSX
|
||||
<menuitem id="enterFullScreenItem"
|
||||
accesskey="&enterFullScreenCmd.accesskey;"
|
||||
label="&enterFullScreenCmd.label;"
|
||||
key="key_fullScreen">
|
||||
<observes element="View:FullScreen" attribute="oncommand"/>
|
||||
<observes element="View:FullScreen" attribute="disabled"/>
|
||||
</menuitem>
|
||||
<menuitem id="exitFullScreenItem"
|
||||
accesskey="&exitFullScreenCmd.accesskey;"
|
||||
label="&exitFullScreenCmd.label;"
|
||||
key="key_fullScreen"
|
||||
hidden="true">
|
||||
<observes element="View:FullScreen" attribute="oncommand"/>
|
||||
<observes element="View:FullScreen" attribute="disabled"/>
|
||||
</menuitem>
|
||||
#else
|
||||
<menuitem id="fullScreenItem"
|
||||
accesskey="&fullScreenCmd.accesskey;"
|
||||
label="&fullScreenCmd.label;"
|
||||
key="key_fullScreen"
|
||||
type="checkbox"
|
||||
observes="View:FullScreen"/>
|
||||
#endif
|
||||
<menuitem id="menu_showAllTabs"
|
||||
hidden="true"
|
||||
accesskey="&showAllTabsCmd.accesskey;"
|
||||
|
@ -341,7 +341,8 @@
|
||||
<key keycode="VK_F6" command="Browser:FocusNextFrame" modifiers="shift"/>
|
||||
<key id="key_fullScreen" keycode="VK_F11" command="View:FullScreen"/>
|
||||
#else
|
||||
<key id="key_fullScreen" key="&fullScreenCmd.macCommandKey;" command="View:FullScreen" modifiers="accel,shift"/>
|
||||
<key id="key_fullScreen" key="&fullScreenCmd.macCommandKey;" command="View:FullScreen" modifiers="accel,control"/>
|
||||
<key id="key_fullScreen_old" key="&fullScreenCmd.macCommandKey;" command="View:FullScreen" modifiers="accel,shift"/>
|
||||
<key keycode="VK_F11" command="View:FullScreen"/>
|
||||
#endif
|
||||
<key key="&reloadCmd.commandkey;" command="Browser:Reload" modifiers="accel" id="key_reload"/>
|
||||
|
@ -3958,6 +3958,12 @@ var FullScreen = {
|
||||
// fullscreen menuitem, menubars, and the appmenu.
|
||||
document.getElementById("View:FullScreen").setAttribute("checked", enterFS);
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
// Make sure the menu items are adjusted.
|
||||
document.getElementById("enterFullScreenItem").hidden = enterFS;
|
||||
document.getElementById("exitFullScreenItem").hidden = !enterFS;
|
||||
#endif
|
||||
|
||||
// On OS X Lion we don't want to hide toolbars when entering fullscreen, unless
|
||||
// we're entering DOM fullscreen, in which case we should hide the toolbars.
|
||||
// If we're leaving fullscreen, then we'll go through the exit code below to
|
||||
|
@ -5,20 +5,25 @@ const dm = Cc["@mozilla.org/download-manager;1"].getService(Ci.nsIDownloadManage
|
||||
const bhist = Cc["@mozilla.org/browser/global-history;2"].getService(Ci.nsIBrowserHistory);
|
||||
const formhist = Cc["@mozilla.org/satchel/form-history;1"].getService(Ci.nsIFormHistory2);
|
||||
|
||||
const kUsecPerMin = 60 * 1000000;
|
||||
|
||||
let tempScope = {};
|
||||
Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader)
|
||||
.loadSubScript("chrome://browser/content/sanitize.js", tempScope);
|
||||
let Sanitizer = tempScope.Sanitizer;
|
||||
|
||||
function test() {
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
setupDownloads();
|
||||
setupFormHistory();
|
||||
setupHistory(onHistoryReady);
|
||||
}
|
||||
|
||||
function onHistoryReady() {
|
||||
var hoursSinceMidnight = new Date().getHours();
|
||||
var minutesSinceMidnight = hoursSinceMidnight * 60 + new Date().getMinutes();
|
||||
|
||||
setupHistory();
|
||||
setupFormHistory();
|
||||
setupDownloads();
|
||||
|
||||
// Should test cookies here, but nsICookieManager/nsICookieService
|
||||
// doesn't let us fake creation times. bug 463127
|
||||
|
||||
@ -271,37 +276,46 @@ function test() {
|
||||
|
||||
ok(!downloadExists(5555550), "Year old download should now be deleted");
|
||||
|
||||
finish();
|
||||
}
|
||||
|
||||
function setupHistory() {
|
||||
bhist.addPageWithDetails(makeURI("http://10minutes.com/"), "10 minutes ago", now_uSec - 10*60*1000000);
|
||||
bhist.addPageWithDetails(makeURI("http://1hour.com/"), "Less than 1 hour ago", now_uSec - 45*60*1000000);
|
||||
bhist.addPageWithDetails(makeURI("http://1hour10minutes.com/"), "1 hour 10 minutes ago", now_uSec - 70*60*1000000);
|
||||
bhist.addPageWithDetails(makeURI("http://2hour.com/"), "Less than 2 hours ago", now_uSec - 90*60*1000000);
|
||||
bhist.addPageWithDetails(makeURI("http://2hour10minutes.com/"), "2 hours 10 minutes ago", now_uSec - 130*60*1000000);
|
||||
bhist.addPageWithDetails(makeURI("http://4hour.com/"), "Less than 4 hours ago", now_uSec - 180*60*1000000);
|
||||
bhist.addPageWithDetails(makeURI("http://4hour10minutes.com/"), "4 hours 10 minutesago", now_uSec - 250*60*1000000);
|
||||
|
||||
function setupHistory(aCallback) {
|
||||
let places = [];
|
||||
|
||||
function addPlace(aURI, aTitle, aVisitDate) {
|
||||
places.push({
|
||||
uri: aURI,
|
||||
title: aTitle,
|
||||
visits: [{
|
||||
visitDate: aVisitDate,
|
||||
transitionType: Ci.nsINavHistoryService.TRANSITION_LINK
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
addPlace(makeURI("http://10minutes.com/"), "10 minutes ago", now_uSec - 10 * kUsecPerMin);
|
||||
addPlace(makeURI("http://1hour.com/"), "Less than 1 hour ago", now_uSec - 45 * kUsecPerMin);
|
||||
addPlace(makeURI("http://1hour10minutes.com/"), "1 hour 10 minutes ago", now_uSec - 70 * kUsecPerMin);
|
||||
addPlace(makeURI("http://2hour.com/"), "Less than 2 hours ago", now_uSec - 90 * kUsecPerMin);
|
||||
addPlace(makeURI("http://2hour10minutes.com/"), "2 hours 10 minutes ago", now_uSec - 130 * kUsecPerMin);
|
||||
addPlace(makeURI("http://4hour.com/"), "Less than 4 hours ago", now_uSec - 180 * kUsecPerMin);
|
||||
addPlace(makeURI("http://4hour10minutes.com/"), "4 hours 10 minutesago", now_uSec - 250 * kUsecPerMin);
|
||||
|
||||
let today = new Date();
|
||||
today.setHours(0);
|
||||
today.setMinutes(0);
|
||||
today.setSeconds(1);
|
||||
bhist.addPageWithDetails(makeURI("http://today.com/"), "Today", today.valueOf() * 1000);
|
||||
|
||||
addPlace(makeURI("http://today.com/"), "Today", today.getTime() * 1000);
|
||||
|
||||
let lastYear = new Date();
|
||||
lastYear.setFullYear(lastYear.getFullYear() - 1);
|
||||
bhist.addPageWithDetails(makeURI("http://before-today.com/"), "Before Today", lastYear.valueOf() * 1000);
|
||||
|
||||
// Confirm everything worked
|
||||
ok(bhist.isVisited(makeURI("http://10minutes.com/")), "Pretend visit to 10minutes.com should exist");
|
||||
ok(bhist.isVisited(makeURI("http://1hour.com")), "Pretend visit to 1hour.com should exist");
|
||||
ok(bhist.isVisited(makeURI("http://1hour10minutes.com/")), "Pretend visit to 1hour10minutes.com should exist");
|
||||
ok(bhist.isVisited(makeURI("http://2hour.com")), "Pretend visit to 2hour.com should exist");
|
||||
ok(bhist.isVisited(makeURI("http://2hour10minutes.com/")), "Pretend visit to 2hour10minutes.com should exist");
|
||||
ok(bhist.isVisited(makeURI("http://4hour.com")), "Pretend visit to 4hour.com should exist");
|
||||
ok(bhist.isVisited(makeURI("http://4hour10minutes.com/")), "Pretend visit to 4hour10minutes.com should exist");
|
||||
ok(bhist.isVisited(makeURI("http://today.com")), "Pretend visit to today.com should exist");
|
||||
ok(bhist.isVisited(makeURI("http://before-today.com")), "Pretend visit to before-today.com should exist");
|
||||
addPlace(makeURI("http://before-today.com/"), "Before Today", lastYear.getTime() * 1000);
|
||||
|
||||
PlacesUtils.asyncHistory.updatePlaces(places, {
|
||||
handleError: function () ok(false, "Unexpected error in adding visit."),
|
||||
handleResult: function () { },
|
||||
handleCompletion: function () aCallback()
|
||||
});
|
||||
}
|
||||
|
||||
function setupFormHistory() {
|
||||
@ -321,25 +335,25 @@ function setupFormHistory() {
|
||||
|
||||
// Artifically age the entries to the proper vintage.
|
||||
let db = formhist.DBConnection;
|
||||
let timestamp = now_uSec - 10*60*1000000;
|
||||
let timestamp = now_uSec - 10 * kUsecPerMin;
|
||||
db.executeSimpleSQL("UPDATE moz_formhistory SET firstUsed = " +
|
||||
timestamp + " WHERE fieldname = '10minutes'");
|
||||
timestamp = now_uSec - 45*60*1000000;
|
||||
timestamp = now_uSec - 45 * kUsecPerMin;
|
||||
db.executeSimpleSQL("UPDATE moz_formhistory SET firstUsed = " +
|
||||
timestamp + " WHERE fieldname = '1hour'");
|
||||
timestamp = now_uSec - 70*60*1000000;
|
||||
timestamp = now_uSec - 70 * kUsecPerMin;
|
||||
db.executeSimpleSQL("UPDATE moz_formhistory SET firstUsed = " +
|
||||
timestamp + " WHERE fieldname = '1hour10minutes'");
|
||||
timestamp = now_uSec - 90*60*1000000;
|
||||
timestamp = now_uSec - 90 * kUsecPerMin;
|
||||
db.executeSimpleSQL("UPDATE moz_formhistory SET firstUsed = " +
|
||||
timestamp + " WHERE fieldname = '2hour'");
|
||||
timestamp = now_uSec - 130*60*1000000;
|
||||
timestamp = now_uSec - 130 * kUsecPerMin;
|
||||
db.executeSimpleSQL("UPDATE moz_formhistory SET firstUsed = " +
|
||||
timestamp + " WHERE fieldname = '2hour10minutes'");
|
||||
timestamp = now_uSec - 180*60*1000000;
|
||||
timestamp = now_uSec - 180 * kUsecPerMin;
|
||||
db.executeSimpleSQL("UPDATE moz_formhistory SET firstUsed = " +
|
||||
timestamp + " WHERE fieldname = '4hour'");
|
||||
timestamp = now_uSec - 250*60*1000000;
|
||||
timestamp = now_uSec - 250 * kUsecPerMin;
|
||||
db.executeSimpleSQL("UPDATE moz_formhistory SET firstUsed = " +
|
||||
timestamp + " WHERE fieldname = '4hour10minutes'");
|
||||
|
||||
@ -347,13 +361,13 @@ function setupFormHistory() {
|
||||
today.setHours(0);
|
||||
today.setMinutes(0);
|
||||
today.setSeconds(1);
|
||||
timestamp = today.valueOf() * 1000;
|
||||
timestamp = today.getTime() * 1000;
|
||||
db.executeSimpleSQL("UPDATE moz_formhistory SET firstUsed = " +
|
||||
timestamp + " WHERE fieldname = 'today'");
|
||||
|
||||
let lastYear = new Date();
|
||||
lastYear.setFullYear(lastYear.getFullYear() - 1);
|
||||
timestamp = lastYear.valueOf() * 1000;
|
||||
timestamp = lastYear.getTime() * 1000;
|
||||
db.executeSimpleSQL("UPDATE moz_formhistory SET firstUsed = " +
|
||||
timestamp + " WHERE fieldname = 'b4today'");
|
||||
|
||||
@ -377,8 +391,8 @@ function setupDownloads() {
|
||||
name: "fakefile-10-minutes",
|
||||
source: "https://bugzilla.mozilla.org/show_bug.cgi?id=480169",
|
||||
target: "fakefile-10-minutes",
|
||||
startTime: now_uSec - 10*60*1000000, // 10 minutes ago, in uSec
|
||||
endTime: now_uSec - 11*60*1000000, // 1 minute later
|
||||
startTime: now_uSec - 10 * kUsecPerMin, // 10 minutes ago, in uSec
|
||||
endTime: now_uSec - 11 * kUsecPerMin, // 1 minute later
|
||||
state: Ci.nsIDownloadManager.DOWNLOAD_FINISHED,
|
||||
currBytes: 0, maxBytes: -1, preferredAction: 0, autoResume: 0
|
||||
};
|
||||
@ -404,8 +418,8 @@ function setupDownloads() {
|
||||
name: "fakefile-1-hour",
|
||||
source: "https://bugzilla.mozilla.org/show_bug.cgi?id=453440",
|
||||
target: "fakefile-1-hour",
|
||||
startTime: now_uSec - 45*60*1000000, // 45 minutes ago, in uSec
|
||||
endTime: now_uSec - 44*60*1000000, // 1 minute later
|
||||
startTime: now_uSec - 45 * kUsecPerMin, // 45 minutes ago, in uSec
|
||||
endTime: now_uSec - 44 * kUsecPerMin, // 1 minute later
|
||||
state: Ci.nsIDownloadManager.DOWNLOAD_FINISHED,
|
||||
currBytes: 0, maxBytes: -1, preferredAction: 0, autoResume: 0
|
||||
};
|
||||
@ -425,8 +439,8 @@ function setupDownloads() {
|
||||
name: "fakefile-1-hour-10-minutes",
|
||||
source: "https://bugzilla.mozilla.org/show_bug.cgi?id=480169",
|
||||
target: "fakefile-1-hour-10-minutes",
|
||||
startTime: now_uSec - 70*60*1000000, // 70 minutes ago, in uSec
|
||||
endTime: now_uSec - 71*60*1000000, // 1 minute later
|
||||
startTime: now_uSec - 70 * kUsecPerMin, // 70 minutes ago, in uSec
|
||||
endTime: now_uSec - 71 * kUsecPerMin, // 1 minute later
|
||||
state: Ci.nsIDownloadManager.DOWNLOAD_FINISHED,
|
||||
currBytes: 0, maxBytes: -1, preferredAction: 0, autoResume: 0
|
||||
};
|
||||
@ -446,8 +460,8 @@ function setupDownloads() {
|
||||
name: "fakefile-2-hour",
|
||||
source: "https://bugzilla.mozilla.org/show_bug.cgi?id=453440",
|
||||
target: "fakefile-2-hour",
|
||||
startTime: now_uSec - 90*60*1000000, // 90 minutes ago, in uSec
|
||||
endTime: now_uSec - 89*60*1000000, // 1 minute later
|
||||
startTime: now_uSec - 90 * kUsecPerMin, // 90 minutes ago, in uSec
|
||||
endTime: now_uSec - 89 * kUsecPerMin, // 1 minute later
|
||||
state: Ci.nsIDownloadManager.DOWNLOAD_FINISHED,
|
||||
currBytes: 0, maxBytes: -1, preferredAction: 0, autoResume: 0
|
||||
};
|
||||
@ -467,8 +481,8 @@ function setupDownloads() {
|
||||
name: "fakefile-2-hour-10-minutes",
|
||||
source: "https://bugzilla.mozilla.org/show_bug.cgi?id=480169",
|
||||
target: "fakefile-2-hour-10-minutes",
|
||||
startTime: now_uSec - 130*60*1000000, // 130 minutes ago, in uSec
|
||||
endTime: now_uSec - 131*60*1000000, // 1 minute later
|
||||
startTime: now_uSec - 130 * kUsecPerMin, // 130 minutes ago, in uSec
|
||||
endTime: now_uSec - 131 * kUsecPerMin, // 1 minute later
|
||||
state: Ci.nsIDownloadManager.DOWNLOAD_FINISHED,
|
||||
currBytes: 0, maxBytes: -1, preferredAction: 0, autoResume: 0
|
||||
};
|
||||
@ -488,8 +502,8 @@ function setupDownloads() {
|
||||
name: "fakefile-4-hour",
|
||||
source: "https://bugzilla.mozilla.org/show_bug.cgi?id=453440",
|
||||
target: "fakefile-4-hour",
|
||||
startTime: now_uSec - 180*60*1000000, // 180 minutes ago, in uSec
|
||||
endTime: now_uSec - 179*60*1000000, // 1 minute later
|
||||
startTime: now_uSec - 180 * kUsecPerMin, // 180 minutes ago, in uSec
|
||||
endTime: now_uSec - 179 * kUsecPerMin, // 1 minute later
|
||||
state: Ci.nsIDownloadManager.DOWNLOAD_FINISHED,
|
||||
currBytes: 0, maxBytes: -1, preferredAction: 0, autoResume: 0
|
||||
};
|
||||
@ -509,8 +523,8 @@ function setupDownloads() {
|
||||
name: "fakefile-4-hour-10-minutes",
|
||||
source: "https://bugzilla.mozilla.org/show_bug.cgi?id=480169",
|
||||
target: "fakefile-4-hour-10-minutes",
|
||||
startTime: now_uSec - 250*60*1000000, // 250 minutes ago, in uSec
|
||||
endTime: now_uSec - 251*60*1000000, // 1 minute later
|
||||
startTime: now_uSec - 250 * kUsecPerMin, // 250 minutes ago, in uSec
|
||||
endTime: now_uSec - 251 * kUsecPerMin, // 1 minute later
|
||||
state: Ci.nsIDownloadManager.DOWNLOAD_FINISHED,
|
||||
currBytes: 0, maxBytes: -1, preferredAction: 0, autoResume: 0
|
||||
};
|
||||
@ -535,8 +549,8 @@ function setupDownloads() {
|
||||
name: "fakefile-today",
|
||||
source: "https://bugzilla.mozilla.org/show_bug.cgi?id=453440",
|
||||
target: "fakefile-today",
|
||||
startTime: today.valueOf() * 1000, // 12:00:30am this morning, in uSec
|
||||
endTime: (today.valueOf() + 1000) * 1000, // 1 second later
|
||||
startTime: today.getTime() * 1000, // 12:00:30am this morning, in uSec
|
||||
endTime: (today.getTime() + 1000) * 1000, // 1 second later
|
||||
state: Ci.nsIDownloadManager.DOWNLOAD_FINISHED,
|
||||
currBytes: 0, maxBytes: -1, preferredAction: 0, autoResume: 0
|
||||
};
|
||||
@ -558,8 +572,8 @@ function setupDownloads() {
|
||||
name: "fakefile-old",
|
||||
source: "https://bugzilla.mozilla.org/show_bug.cgi?id=453440",
|
||||
target: "fakefile-old",
|
||||
startTime: lastYear.valueOf() * 1000, // 1 year ago, in uSec
|
||||
endTime: (lastYear.valueOf() + 1000) * 1000, // 1 second later
|
||||
startTime: lastYear.getTime() * 1000, // 1 year ago, in uSec
|
||||
endTime: (lastYear.getTime() + 1000) * 1000, // 1 second later
|
||||
state: Ci.nsIDownloadManager.DOWNLOAD_FINISHED,
|
||||
currBytes: 0, maxBytes: -1, preferredAction: 0, autoResume: 0
|
||||
};
|
||||
|
@ -60,6 +60,8 @@ const dm = Cc["@mozilla.org/download-manager;1"].
|
||||
const formhist = Cc["@mozilla.org/satchel/form-history;1"].
|
||||
getService(Ci.nsIFormHistory2);
|
||||
|
||||
const kUsecPerMin = 60 * 1000000;
|
||||
|
||||
// Add tests here. Each is a function that's called by doNextTest().
|
||||
var gAllTests = [
|
||||
|
||||
@ -831,8 +833,8 @@ function addDownloadWithMinutesAgo(aMinutesAgo) {
|
||||
name: name,
|
||||
source: "https://bugzilla.mozilla.org/show_bug.cgi?id=480169",
|
||||
target: name,
|
||||
startTime: now_uSec - (aMinutesAgo * 60 * 1000000),
|
||||
endTime: now_uSec - ((aMinutesAgo + 1) *60 * 1000000),
|
||||
startTime: now_uSec - (aMinutesAgo * kUsecPerMin),
|
||||
endTime: now_uSec - ((aMinutesAgo + 1) * kUsecPerMin),
|
||||
state: Ci.nsIDownloadManager.DOWNLOAD_FINISHED,
|
||||
currBytes: 0, maxBytes: -1, preferredAction: 0, autoResume: 0
|
||||
};
|
||||
@ -872,7 +874,7 @@ function addFormEntryWithMinutesAgo(aMinutesAgo) {
|
||||
|
||||
// Artifically age the entry to the proper vintage.
|
||||
let db = formhist.DBConnection;
|
||||
let timestamp = now_uSec - (aMinutesAgo * 60 * 1000000);
|
||||
let timestamp = now_uSec - (aMinutesAgo * kUsecPerMin);
|
||||
db.executeSimpleSQL("UPDATE moz_formhistory SET firstUsed = " +
|
||||
timestamp + " WHERE fieldname = '" + name + "'");
|
||||
|
||||
@ -889,10 +891,12 @@ function addFormEntryWithMinutesAgo(aMinutesAgo) {
|
||||
*/
|
||||
function addHistoryWithMinutesAgo(aMinutesAgo) {
|
||||
let pURI = makeURI("http://" + aMinutesAgo + "-minutes-ago.com/");
|
||||
PlacesUtils.bhistory
|
||||
.addPageWithDetails(pURI,
|
||||
aMinutesAgo + " minutes ago",
|
||||
now_uSec - (aMinutesAgo * 60 * 1000 * 1000));
|
||||
PlacesUtils.history.addVisit(pURI,
|
||||
now_uSec - aMinutesAgo * kUsecPerMin,
|
||||
null,
|
||||
Ci.nsINavHistoryService.TRANSITION_LINK,
|
||||
false,
|
||||
0);
|
||||
is(PlacesUtils.bhistory.isVisited(pURI), true,
|
||||
"Sanity check: history visit " + pURI.spec +
|
||||
" should exist after creating it");
|
||||
|
@ -501,10 +501,12 @@ function addFormEntryWithMinutesAgo(aMinutesAgo) {
|
||||
*/
|
||||
function addHistoryWithMinutesAgo(aMinutesAgo) {
|
||||
let pURI = makeURI("http://" + aMinutesAgo + "-minutes-ago.com/");
|
||||
PlacesUtils.bhistory
|
||||
.addPageWithDetails(pURI,
|
||||
aMinutesAgo + " minutes ago",
|
||||
now_uSec - (aMinutesAgo * 60 * 1000 * 1000));
|
||||
PlacesUtils.history.addVisit(pURI,
|
||||
now_uSec - (aMinutesAgo * 60 * 1000 * 1000),
|
||||
null,
|
||||
Ci.nsINavHistoryService.TRANSITION_LINK,
|
||||
false,
|
||||
0);
|
||||
is(PlacesUtils.bhistory.isVisited(pURI), true,
|
||||
"Sanity check: history visit " + pURI.spec +
|
||||
" should exist after creating it");
|
||||
|
@ -17,7 +17,7 @@ let bhist = Cc["@mozilla.org/browser/global-history;2"]
|
||||
|
||||
function runTests() {
|
||||
clearHistory();
|
||||
fillHistory();
|
||||
yield fillHistory();
|
||||
yield addNewTabPageTab();
|
||||
|
||||
is(getCell(0).site.url, URL, "first site is our fake site");
|
||||
@ -29,9 +29,23 @@ function runTests() {
|
||||
}
|
||||
|
||||
function fillHistory() {
|
||||
let uri = makeURI(URL);
|
||||
for (let i = 59; i > 0; i--)
|
||||
bhist.addPageWithDetails(uri, "fake site", NOW - i * 60 * 1000000);
|
||||
let visits = [];
|
||||
for (let i = 59; i > 0; i--) {
|
||||
visits.push({
|
||||
visitDate: NOW - i * 60 * 1000000,
|
||||
transitionType: Ci.nsINavHistoryService.TRANSITION_LINK
|
||||
});
|
||||
}
|
||||
let place = {
|
||||
uri: makeURI(URL),
|
||||
title: "fake site",
|
||||
visits: visits
|
||||
};
|
||||
PlacesUtils.asyncHistory.updatePlaces(place, {
|
||||
handleError: function () do_throw("Unexpected error in adding visit."),
|
||||
handleResult: function () { },
|
||||
handleCompletion: function () TestRunner.next()
|
||||
});
|
||||
}
|
||||
|
||||
function clearHistory() {
|
||||
|
@ -50,13 +50,49 @@ function do_test()
|
||||
const TITLE_2 = "Title 2";
|
||||
|
||||
do_test_pending();
|
||||
waitForClearHistory(function() {
|
||||
PlacesUtils.bhistory.addPageWithDetails(TEST_URI, TITLE_1, Date.now() * 1000);
|
||||
waitForClearHistory(function () {
|
||||
let place = {
|
||||
uri: TEST_URI,
|
||||
title: TITLE_1,
|
||||
visits: [{
|
||||
visitDate: Date.now() * 1000,
|
||||
transitionType: Ci.nsINavHistoryService.TRANSITION_LINK
|
||||
}]
|
||||
};
|
||||
PlacesUtils.asyncHistory.updatePlaces(place, {
|
||||
handleError: function () do_throw("Unexpected error in adding visit."),
|
||||
handleResult: function () { },
|
||||
handleCompletion: function () afterAddFirstVisit()
|
||||
});
|
||||
});
|
||||
|
||||
function afterAddFirstVisit()
|
||||
{
|
||||
do_check_eq(PlacesUtils.history.getPageTitle(TEST_URI), TITLE_1);
|
||||
|
||||
pb.privateBrowsingEnabled = true;
|
||||
|
||||
PlacesUtils.bhistory.addPageWithDetails(TEST_URI, TITLE_2, Date.now() * 2000);
|
||||
let place = {
|
||||
uri: TEST_URI,
|
||||
title: TITLE_2,
|
||||
visits: [{
|
||||
visitDate: Date.now() * 2000,
|
||||
transitionType: Ci.nsINavHistoryService.TRANSITION_LINK
|
||||
}]
|
||||
};
|
||||
|
||||
PlacesUtils.asyncHistory.updatePlaces(place, {
|
||||
handleError: function (aResultCode) {
|
||||
// We expect this error in Private Browsing mode.
|
||||
do_check_eq(aResultCode, Cr.NS_ERROR_ILLEGAL_VALUE);
|
||||
},
|
||||
handleResult: function () do_throw("Unexpected success adding visit."),
|
||||
handleCompletion: function () afterAddSecondVisit()
|
||||
});
|
||||
}
|
||||
|
||||
function afterAddSecondVisit()
|
||||
{
|
||||
do_check_eq(PlacesUtils.history.getPageTitle(TEST_URI), TITLE_1);
|
||||
|
||||
pb.privateBrowsingEnabled = false;
|
||||
@ -73,7 +109,7 @@ function do_test()
|
||||
do_check_eq(PlacesUtils.history.getPageTitle(TEST_URI), TITLE_1);
|
||||
|
||||
waitForClearHistory(do_test_finished);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Support running tests on both the service itself and its wrapper
|
||||
|
@ -43,7 +43,9 @@
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Constants
|
||||
//// Globals
|
||||
|
||||
Cu.import("resource://gre/modules/PlacesUtils.jsm");
|
||||
|
||||
let pb = Cc[PRIVATEBROWSING_CONTRACT_ID].
|
||||
getService(Ci.nsIPrivateBrowsingService);
|
||||
@ -88,9 +90,9 @@ function uri(aURIString)
|
||||
function add_visit(aURI)
|
||||
{
|
||||
check_visited(aURI, false);
|
||||
let bh = Cc["@mozilla.org/browser/global-history;2"].
|
||||
getService(Ci.nsIBrowserHistory);
|
||||
bh.addPageWithDetails(aURI, aURI.spec, Date.now() * 1000);
|
||||
PlacesUtils.history.addVisit(aURI, Date.now() * 1000, null,
|
||||
Ci.nsINavHistoryService.TRANSITION_LINK, false,
|
||||
0);
|
||||
check_visited(aURI, true);
|
||||
}
|
||||
|
||||
@ -104,10 +106,8 @@ function add_visit(aURI)
|
||||
*/
|
||||
function check_visited(aURI, aIsVisited)
|
||||
{
|
||||
let gh = Cc["@mozilla.org/browser/global-history;2"].
|
||||
getService(Ci.nsIGlobalHistory2);
|
||||
let checker = aIsVisited ? do_check_true : do_check_false;
|
||||
checker(gh.isVisited(aURI));
|
||||
checker(PlacesUtils.ghistory2.isVisited(aURI));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -362,9 +362,7 @@ function test_history_not_cleared_with_uri_contains_domain()
|
||||
check_visited(TEST_URI, true);
|
||||
|
||||
// Clear history since we left something there from this test.
|
||||
let bh = Cc["@mozilla.org/browser/global-history;2"].
|
||||
getService(Ci.nsIBrowserHistory);
|
||||
bh.removeAllPages();
|
||||
PlacesUtils.bhistory.removeAllPages();
|
||||
}
|
||||
|
||||
// Cookie Service
|
||||
|
18
browser/config/mozconfigs/linux32/debug-asan
Normal file
@ -0,0 +1,18 @@
|
||||
# Use at least -O1 for optimization to avoid stack space
|
||||
# exhaustions caused by Clang function inlining.
|
||||
ac_add_options --enable-debug
|
||||
ac_add_options --enable-optimize="-O1"
|
||||
|
||||
# ASan specific options on Linux
|
||||
ac_add_options --enable-valgrind
|
||||
|
||||
. $topsrcdir/build/unix/mozconfig.asan
|
||||
|
||||
# Avoid dependency on libstdc++ 4.5
|
||||
ac_add_options --enable-stdcxx-compat
|
||||
|
||||
# Enable parallel compiling
|
||||
mk_add_options MOZ_MAKE_FLAGS="-j4"
|
||||
|
||||
# Package js shell.
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
20
browser/config/mozconfigs/linux32/nightly-asan
Normal file
@ -0,0 +1,20 @@
|
||||
# We still need to build with debug symbols
|
||||
ac_add_options --disable-debug
|
||||
ac_add_options --enable-optimize="-O2 -g"
|
||||
|
||||
# ASan specific options on Linux
|
||||
ac_add_options --enable-valgrind
|
||||
|
||||
# Other options
|
||||
ac_add_options --enable-codesighs
|
||||
|
||||
. $topsrcdir/build/unix/mozconfig.asan
|
||||
|
||||
# Avoid dependency on libstdc++ 4.5
|
||||
ac_add_options --enable-stdcxx-compat
|
||||
|
||||
# Enable parallel compiling
|
||||
mk_add_options MOZ_MAKE_FLAGS="-j4"
|
||||
|
||||
# Package js shell.
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
18
browser/config/mozconfigs/linux64/debug-asan
Normal file
@ -0,0 +1,18 @@
|
||||
# Use at least -O1 for optimization to avoid stack space
|
||||
# exhaustions caused by Clang function inlining.
|
||||
ac_add_options --enable-debug
|
||||
ac_add_options --enable-optimize="-O1"
|
||||
|
||||
# ASan specific options on Linux
|
||||
ac_add_options --enable-valgrind
|
||||
|
||||
. $topsrcdir/build/unix/mozconfig.asan
|
||||
|
||||
# Avoid dependency on libstdc++ 4.5
|
||||
ac_add_options --enable-stdcxx-compat
|
||||
|
||||
# Enable parallel compiling
|
||||
mk_add_options MOZ_MAKE_FLAGS="-j4"
|
||||
|
||||
# Package js shell.
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
20
browser/config/mozconfigs/linux64/nightly-asan
Normal file
@ -0,0 +1,20 @@
|
||||
# We still need to build with debug symbols
|
||||
ac_add_options --disable-debug
|
||||
ac_add_options --enable-optimize="-O2 -g"
|
||||
|
||||
# ASan specific options on Linux
|
||||
ac_add_options --enable-valgrind
|
||||
|
||||
# Other options
|
||||
ac_add_options --enable-codesighs
|
||||
|
||||
. $topsrcdir/build/unix/mozconfig.asan
|
||||
|
||||
# Avoid dependency on libstdc++ 4.5
|
||||
ac_add_options --enable-stdcxx-compat
|
||||
|
||||
# Enable parallel compiling
|
||||
mk_add_options MOZ_MAKE_FLAGS="-j4"
|
||||
|
||||
# Package js shell.
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
@ -77,6 +77,12 @@ can reach it easily. -->
|
||||
<!ENTITY pageInfoCmd.label "Page Info">
|
||||
<!ENTITY pageInfoCmd.accesskey "I">
|
||||
<!ENTITY pageInfoCmd.commandkey "i">
|
||||
<!-- LOCALIZATION NOTE (enterFullScreenCmd.label, exitFullScreenCmd.label):
|
||||
These should match what Safari and other Apple applications use on OS X Lion. -->
|
||||
<!ENTITY enterFullScreenCmd.label "Enter Full Screen">
|
||||
<!ENTITY enterFullScreenCmd.accesskey "F">
|
||||
<!ENTITY exitFullScreenCmd.label "Exit Full Screen">
|
||||
<!ENTITY exitFullScreenCmd.accesskey "F">
|
||||
<!ENTITY fullScreenCmd.label "Full Screen">
|
||||
<!ENTITY fullScreenCmd.accesskey "F">
|
||||
<!ENTITY fullScreenCmd.macCommandKey "f">
|
||||
|
@ -588,10 +588,8 @@ MacNativeApp.prototype = {
|
||||
<string>MOZB</string>\n\
|
||||
<key>CFBundleVersion</key>\n\
|
||||
<string>0</string>\n\
|
||||
#ifdef DEBUG
|
||||
<key>FirefoxBinary</key>\n\
|
||||
<string>org.mozilla.NightlyDebug</string>\n\
|
||||
#endif
|
||||
#expand <string>__MOZ_MACBUNDLE_ID__</string>\n\
|
||||
</dict>\n\
|
||||
</plist>';
|
||||
|
||||
|
Before Width: | Height: | Size: 900 B After Width: | Height: | Size: 708 B |
Before Width: | Height: | Size: 553 B After Width: | Height: | Size: 672 B |
Before Width: | Height: | Size: 541 B After Width: | Height: | Size: 520 B |
Before Width: | Height: | Size: 306 B After Width: | Height: | Size: 500 B |
Before Width: | Height: | Size: 900 B After Width: | Height: | Size: 708 B |
Before Width: | Height: | Size: 553 B After Width: | Height: | Size: 672 B |
@ -40,6 +40,7 @@ package com.mozilla.SUTAgentAndroid;
|
||||
import java.io.File;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.InetAddress;
|
||||
import org.apache.http.conn.util.InetAddressUtils;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketException;
|
||||
import java.util.Enumeration;
|
||||
@ -665,7 +666,7 @@ public class SUTAgentAndroid extends Activity
|
||||
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();)
|
||||
{
|
||||
InetAddress inetAddress = enumIpAddr.nextElement();
|
||||
if (!inetAddress.isLoopbackAddress())
|
||||
if (!inetAddress.isLoopbackAddress() && InetAddressUtils.isIPv4Address(inetAddress.getHostAddress()))
|
||||
{
|
||||
return inetAddress.getHostAddress().toString();
|
||||
}
|
||||
|
@ -277,5 +277,13 @@ build_one_stage({"PATH" : stage1_tool_inst_dir + "/bin:/bin:/usr/bin",
|
||||
"RANLIB" : "true" },
|
||||
stage2_dir, False)
|
||||
|
||||
stage2_tool_inst_dir = stage2_dir + '/inst'
|
||||
stage3_dir = build_dir + '/stage3'
|
||||
build_one_stage({"PATH" : stage2_tool_inst_dir + "/bin:/bin:/usr/bin",
|
||||
"CC" : "gcc -fgnu89-inline",
|
||||
"CXX" : "g++",
|
||||
"RANLIB" : "true" },
|
||||
stage3_dir, False)
|
||||
|
||||
build_tar_package(aux_inst_dir + "/bin/tar",
|
||||
"toolchain.tar", stage2_dir, "inst")
|
||||
"toolchain.tar", stage3_dir, "inst")
|
||||
|
20
build/unix/mozconfig.asan
Normal file
@ -0,0 +1,20 @@
|
||||
# Use Clang r155417
|
||||
export CC="/tools/clang-3.0/bin/clang -fgnu89-inline"
|
||||
export CXX="/tools/clang-3.0/bin/clang++"
|
||||
|
||||
# Mandatory flags for ASan
|
||||
export ASANFLAGS="-faddress-sanitizer -Dxmalloc=myxmalloc -fPIC"
|
||||
export CFLAGS="$ASANFLAGS"
|
||||
export CXXFLAGS="$ASANFLAGS"
|
||||
export LDFLAGS="-faddress-sanitizer"
|
||||
|
||||
# Enable ASan specific code and build workarounds
|
||||
ac_add_options --enable-address-sanitizer
|
||||
|
||||
# Mandatory options required for ASan builds (both on Linux and Mac)
|
||||
export MOZ_DEBUG_SYMBOLS=1
|
||||
ac_add_options --enable-debug-symbols
|
||||
ac_add_options --disable-install-strip
|
||||
ac_add_options --disable-jemalloc
|
||||
ac_add_options --disable-crashreporter
|
||||
ac_add_options --disable-elf-hack
|
@ -1,12 +1,13 @@
|
||||
export INCLUDE=/c/tools/msvs10/vc/include:/c/tools/msvs10/vc/atlmfc/include:/c/tools/sdks/v7.0/include:/c/tools/sdks/v7.0/include/atl:/c/tools/sdks/dx10/include
|
||||
export LIBPATH=/c/tools/msvs10/vc/lib:/c/tools/msvs10/vc/atlmfc/lib
|
||||
export LIB=/c/tools/msvs10/vc/lib:/c/tools/msvs10/vc/atlmfc/lib:/c/tools/sdks/v7.0/lib:/c/tools/sdks/dx10/lib
|
||||
export PATH="/c/tools/msvs10/Common7/IDE:/c/tools/msvs10/VC/BIN:/c/tools/msvs10/Common7/Tools:/c/tools/msvs10/VC/VCPackages:${PATH}"
|
||||
export WIN32_REDIST_DIR=/c/tools/msvs10/VC/redist/x86/Microsoft.VC100.CRT
|
||||
|
||||
export MOZ_TOOLS=C:/mozilla-build/moztools
|
||||
export PATH="/c/tools/msvs10/Common7/IDE:/c/tools/msvs10/VC/BIN:/c/tools/msvs10/Common7/Tools:/c/tools/msvs10/VC/VCPackages:/c/mozilla-build/moztools:/c/Tools/sdks/v7.0/bin:${PATH}"
|
||||
|
||||
mk_add_options "export LIB=$LIB"
|
||||
mk_add_options "export LIBPATH=$LIBPATH"
|
||||
mk_add_options "export PATH=$PATH"
|
||||
mk_add_options "export INCLUDE=$INCLUDE"
|
||||
mk_add_options "export WIN32_REDIST_DIR=$WIN32_REDIST_DIR"
|
||||
mk_add_options "export MOZ_TOOLS=$MOZ_TOOLS"
|
||||
|
@ -61,6 +61,7 @@ MOZ_APP_UA_NAME = @MOZ_APP_UA_NAME@
|
||||
MOZ_APP_VERSION = @MOZ_APP_VERSION@
|
||||
MOZ_APP_MAXVERSION = @MOZ_APP_MAXVERSION@
|
||||
MOZ_MACBUNDLE_NAME = @MOZ_MACBUNDLE_NAME@
|
||||
MOZ_MACBUNDLE_ID = @MOZ_MACBUNDLE_ID@
|
||||
MOZ_APP_STATIC_INI = @MOZ_APP_STATIC_INI@
|
||||
|
||||
MOZ_PKG_SPECIAL = @MOZ_PKG_SPECIAL@
|
||||
@ -164,6 +165,7 @@ MOZ_ZIPWRITER = @MOZ_ZIPWRITER@
|
||||
MOZ_OGG = @MOZ_OGG@
|
||||
MOZ_RAW = @MOZ_RAW@
|
||||
MOZ_SYDNEYAUDIO = @MOZ_SYDNEYAUDIO@
|
||||
MOZ_SPEEX_RESAMPLER = @MOZ_SPEEX_RESAMPLER@
|
||||
MOZ_CUBEB = @MOZ_CUBEB@
|
||||
MOZ_WAVE = @MOZ_WAVE@
|
||||
MOZ_MEDIA = @MOZ_MEDIA@
|
||||
|
@ -22,8 +22,8 @@ ifndef INCLUDED_VERSION_MK
|
||||
include $(topsrcdir)/config/version.mk
|
||||
endif
|
||||
|
||||
USE_AUTOTARGETS_MK = 1
|
||||
include $(topsrcdir)/config/makefiles/makeutils.mk
|
||||
include $(topsrcdir)/config/makefiles/autotargets.mk
|
||||
|
||||
ifdef SDK_XPIDLSRCS
|
||||
XPIDLSRCS += $(SDK_XPIDLSRCS)
|
||||
@ -361,25 +361,25 @@ ifndef TARGETS
|
||||
TARGETS = $(LIBRARY) $(SHARED_LIBRARY) $(PROGRAM) $(SIMPLE_PROGRAMS) $(HOST_LIBRARY) $(HOST_PROGRAM) $(HOST_SIMPLE_PROGRAMS) $(JAVA_LIBRARY)
|
||||
endif
|
||||
|
||||
COBJS = $(CSRCS:.c=.$(OBJ_SUFFIX))
|
||||
SOBJS = $(SSRCS:.S=.$(OBJ_SUFFIX))
|
||||
CCOBJS = $(patsubst %.cc,%.$(OBJ_SUFFIX),$(filter %.cc,$(CPPSRCS)))
|
||||
CPPOBJS = $(patsubst %.cpp,%.$(OBJ_SUFFIX),$(filter %.cpp,$(CPPSRCS)))
|
||||
CMOBJS = $(CMSRCS:.m=.$(OBJ_SUFFIX))
|
||||
CMMOBJS = $(CMMSRCS:.mm=.$(OBJ_SUFFIX))
|
||||
ASOBJS = $(ASFILES:.$(ASM_SUFFIX)=.$(OBJ_SUFFIX))
|
||||
ifndef OBJS
|
||||
_OBJS = \
|
||||
$(JRI_STUB_CFILES) \
|
||||
$(addsuffix .$(OBJ_SUFFIX), $(JMC_GEN)) \
|
||||
$(CSRCS:.c=.$(OBJ_SUFFIX)) \
|
||||
$(SSRCS:.S=.$(OBJ_SUFFIX)) \
|
||||
$(patsubst %.cc,%.$(OBJ_SUFFIX),$(CPPSRCS:.cpp=.$(OBJ_SUFFIX))) \
|
||||
$(CMSRCS:.m=.$(OBJ_SUFFIX)) \
|
||||
$(CMMSRCS:.mm=.$(OBJ_SUFFIX)) \
|
||||
$(ASFILES:.$(ASM_SUFFIX)=.$(OBJ_SUFFIX))
|
||||
OBJS = $(strip $(_OBJS))
|
||||
_OBJS = $(COBJS) $(SOBJS) $(CCOBJS) $(CPPOBJS) $(CMOBJS) $(CMMOBJS) $(ASOBJS)
|
||||
OBJS = $(strip $(_OBJS))
|
||||
endif
|
||||
|
||||
HOST_COBJS = $(addprefix host_,$(HOST_CSRCS:.c=.$(OBJ_SUFFIX)))
|
||||
HOST_CCOBJS = $(addprefix host_,$(patsubst %.cc,%.$(OBJ_SUFFIX),$(filter %.cc,$(HOST_CPPSRCS))))
|
||||
HOST_CPPOBJS = $(addprefix host_,$(patsubst %.cpp,%.$(OBJ_SUFFIX),$(filter %.cpp,$(HOST_CPPSRCS))))
|
||||
HOST_CMOBJS = $(addprefix host_,$(HOST_CMSRCS:.m=.$(OBJ_SUFFIX)))
|
||||
HOST_CMMOBJS = $(addprefix host_,$(HOST_CMMSRCS:.mm=.$(OBJ_SUFFIX)))
|
||||
ifndef HOST_OBJS
|
||||
_HOST_OBJS = \
|
||||
$(addprefix host_,$(HOST_CSRCS:.c=.$(OBJ_SUFFIX))) \
|
||||
$(addprefix host_,$(patsubst %.cc,%.$(OBJ_SUFFIX),$(HOST_CPPSRCS:.cpp=.$(OBJ_SUFFIX)))) \
|
||||
$(addprefix host_,$(HOST_CMSRCS:.m=.$(OBJ_SUFFIX))) \
|
||||
$(addprefix host_,$(HOST_CMMSRCS:.mm=.$(OBJ_SUFFIX)))
|
||||
_HOST_OBJS = $(HOST_COBJS) $(HOST_CCOBJS) $(HOST_CPPOBJS) $(HOST_CMOBJS) $(HOST_CMMOBJS)
|
||||
HOST_OBJS = $(strip $(_HOST_OBJS))
|
||||
endif
|
||||
|
||||
@ -1090,32 +1090,27 @@ endif # MOZ_AUTO_DEPS
|
||||
$(OBJS) $(HOST_OBJS): $(GLOBAL_DEPS)
|
||||
|
||||
# Rules for building native targets must come first because of the host_ prefix
|
||||
host_%.$(OBJ_SUFFIX): %.c
|
||||
$(HOST_COBJS): host_%.$(OBJ_SUFFIX): %.c
|
||||
$(REPORT_BUILD)
|
||||
$(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
|
||||
|
||||
host_%.$(OBJ_SUFFIX): %.cpp
|
||||
$(HOST_CPPOBJS): host_%.$(OBJ_SUFFIX): %.cpp
|
||||
$(REPORT_BUILD)
|
||||
$(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
|
||||
|
||||
host_%.$(OBJ_SUFFIX): %.cc
|
||||
$(HOST_CCOBJS): host_%.$(OBJ_SUFFIX): %.cc
|
||||
$(REPORT_BUILD)
|
||||
$(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
|
||||
|
||||
host_%.$(OBJ_SUFFIX): %.m
|
||||
$(HOST_CMOBJS): host_%.$(OBJ_SUFFIX): %.m
|
||||
$(REPORT_BUILD)
|
||||
$(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CFLAGS) $(HOST_CMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
|
||||
|
||||
host_%.$(OBJ_SUFFIX): %.mm
|
||||
$(HOST_CMMOBJS): host_%.$(OBJ_SUFFIX): %.mm
|
||||
$(REPORT_BUILD)
|
||||
$(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(HOST_CMMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
|
||||
|
||||
%:: %.c $(GLOBAL_DEPS)
|
||||
$(REPORT_BUILD)
|
||||
@$(MAKE_DEPS_AUTO_CC)
|
||||
$(ELOG) $(CC) $(CFLAGS) $(LDFLAGS) $(OUTOPTION)$@ $(_VPATH_SRCS)
|
||||
|
||||
%.$(OBJ_SUFFIX): %.c
|
||||
$(COBJS): %.$(OBJ_SUFFIX): %.c
|
||||
$(REPORT_BUILD)
|
||||
@$(MAKE_DEPS_AUTO_CC)
|
||||
$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(_VPATH_SRCS)
|
||||
@ -1135,26 +1130,22 @@ qrc_%.cpp: %.qrc
|
||||
ifdef ASFILES
|
||||
# The AS_DASH_C_FLAG is needed cause not all assemblers (Solaris) accept
|
||||
# a '-c' flag.
|
||||
%.$(OBJ_SUFFIX): %.$(ASM_SUFFIX)
|
||||
$(ASOBJS): %.$(OBJ_SUFFIX): %.$(ASM_SUFFIX)
|
||||
$(AS) $(ASOUTOPTION)$@ $(ASFLAGS) $(AS_DASH_C_FLAG) $(_VPATH_SRCS)
|
||||
endif
|
||||
|
||||
%.$(OBJ_SUFFIX): %.S
|
||||
$(SOBJS): %.$(OBJ_SUFFIX): %.S
|
||||
$(AS) -o $@ $(ASFLAGS) -c $<
|
||||
|
||||
%:: %.cpp $(GLOBAL_DEPS)
|
||||
@$(MAKE_DEPS_AUTO_CXX)
|
||||
$(CCC) $(OUTOPTION)$@ $(CXXFLAGS) $(_VPATH_SRCS) $(LDFLAGS)
|
||||
|
||||
#
|
||||
# Please keep the next two rules in sync.
|
||||
#
|
||||
%.$(OBJ_SUFFIX): %.cc
|
||||
$(CCOBJS): %.$(OBJ_SUFFIX): %.cc
|
||||
$(REPORT_BUILD)
|
||||
@$(MAKE_DEPS_AUTO_CXX)
|
||||
$(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
|
||||
|
||||
%.$(OBJ_SUFFIX): %.cpp
|
||||
$(CPPOBJS): %.$(OBJ_SUFFIX): %.cpp
|
||||
$(REPORT_BUILD)
|
||||
@$(MAKE_DEPS_AUTO_CXX)
|
||||
ifdef STRICT_CPLUSPLUS_SUFFIX
|
||||
@ -1165,12 +1156,12 @@ else
|
||||
$(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
|
||||
endif #STRICT_CPLUSPLUS_SUFFIX
|
||||
|
||||
$(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.mm
|
||||
$(CMMOBJS): $(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.mm
|
||||
$(REPORT_BUILD)
|
||||
@$(MAKE_DEPS_AUTO_CXX)
|
||||
$(ELOG) $(CCC) -o $@ -c $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $(_VPATH_SRCS)
|
||||
|
||||
$(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.m
|
||||
$(CMOBJS): $(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.m
|
||||
$(REPORT_BUILD)
|
||||
@$(MAKE_DEPS_AUTO_CC)
|
||||
$(ELOG) $(CC) -o $@ -c $(COMPILE_CFLAGS) $(COMPILE_CMFLAGS) $(_VPATH_SRCS)
|
||||
@ -1605,8 +1596,7 @@ chrome::
|
||||
$(LOOP_OVER_DIRS)
|
||||
$(LOOP_OVER_TOOL_DIRS)
|
||||
|
||||
$(FINAL_TARGET)/chrome:
|
||||
$(NSINSTALL) -D $@
|
||||
$(FINAL_TARGET)/chrome: $(call mkdir_deps,$(FINAL_TARGET)/chrome)
|
||||
|
||||
ifneq (,$(wildcard $(JAR_MANIFEST)))
|
||||
ifndef NO_DIST_INSTALL
|
||||
|
@ -1047,6 +1047,7 @@ vpx/vpx_codec.h
|
||||
vpx/vpx_decoder.h
|
||||
vpx/vp8dx.h
|
||||
sydneyaudio/sydney_audio.h
|
||||
speex/speex_resampler.h
|
||||
vorbis/codec.h
|
||||
theora/theoradec.h
|
||||
tremor/ivorbiscodec.h
|
||||
|
16
configure.in
@ -4548,6 +4548,7 @@ MOZ_AUTH_EXTENSION=1
|
||||
MOZ_OGG=1
|
||||
MOZ_RAW=
|
||||
MOZ_SYDNEYAUDIO=
|
||||
MOZ_SPEEX_RESAMPLER=1
|
||||
MOZ_CUBEB=
|
||||
MOZ_VORBIS=
|
||||
MOZ_TREMOR=
|
||||
@ -5795,6 +5796,10 @@ if test -n "$MOZ_SYDNEYAUDIO"; then
|
||||
AC_DEFINE(MOZ_SYDNEYAUDIO)
|
||||
fi
|
||||
|
||||
if test -n "$MOZ_SPEEX_RESAMPLER"; then
|
||||
AC_DEFINE(MOZ_SPEEX_RESAMPLER)
|
||||
fi
|
||||
|
||||
if test -n "$MOZ_CUBEB"; then
|
||||
case "$target" in
|
||||
*-mingw*)
|
||||
@ -8508,6 +8513,16 @@ else
|
||||
fi
|
||||
AC_SUBST(MOZ_MACBUNDLE_NAME)
|
||||
|
||||
dnl Mac bundle identifier (based on MOZ_APP_DISPLAYNAME)
|
||||
MOZ_MACBUNDLE_ID=`echo $MOZ_APP_DISPLAYNAME | tr '[A-Z]' '[a-z]'`
|
||||
MOZ_MACBUNDLE_ID=${MOZ_DISTRIBUTION_ID}.${MOZ_MACBUNDLE_ID}
|
||||
if test "$MOZ_DEBUG"; then
|
||||
MOZ_MACBUNDLE_ID=${MOZ_MACBUNDLE_ID}debug
|
||||
fi
|
||||
|
||||
AC_DEFINE_UNQUOTED(MOZ_MACBUNDLE_ID,$MOZ_MACBUNDLE_ID)
|
||||
AC_SUBST(MOZ_MACBUNDLE_ID)
|
||||
|
||||
# The following variables are available to branding and application
|
||||
# configuration ($BRANDING/configure.sh and $APPLICATION/confvars.sh):
|
||||
# - MOZ_APP_VENDOR: Used for application.ini's "Vendor" field, which also
|
||||
@ -8715,6 +8730,7 @@ AC_SUBST(MOZ_APP_EXTRA_LIBS)
|
||||
|
||||
AC_SUBST(MOZ_MEDIA)
|
||||
AC_SUBST(MOZ_SYDNEYAUDIO)
|
||||
AC_SUBST(MOZ_SPEEX_RESAMPLER)
|
||||
AC_SUBST(MOZ_CUBEB)
|
||||
AC_SUBST(MOZ_WAVE)
|
||||
AC_SUBST(MOZ_VORBIS)
|
||||
|
@ -70,7 +70,7 @@ nsDOMMultipartFile::GetSize(PRUint64* aLength)
|
||||
length += l;
|
||||
}
|
||||
|
||||
NS_ENSURE_TRUE(length.valid(), NS_ERROR_FAILURE);
|
||||
NS_ENSURE_TRUE(length.isValid(), NS_ERROR_FAILURE);
|
||||
|
||||
mLength = length.value();
|
||||
}
|
||||
|
@ -39,9 +39,8 @@
|
||||
#define nsDOMBlobBuilder_h
|
||||
|
||||
#include "nsDOMFile.h"
|
||||
#include "CheckedInt.h"
|
||||
|
||||
#include "mozilla/StandardInteger.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
@ -128,10 +127,10 @@ protected:
|
||||
|
||||
// Start at 1 or we'll loop forever.
|
||||
CheckedUint32 bufferLen = NS_MAX<PRUint32>(mDataBufferLen, 1);
|
||||
while (bufferLen.valid() && bufferLen.value() < mDataLen + aSize)
|
||||
while (bufferLen.isValid() && bufferLen.value() < mDataLen + aSize)
|
||||
bufferLen *= 2;
|
||||
|
||||
if (!bufferLen.valid())
|
||||
if (!bufferLen.isValid())
|
||||
return false;
|
||||
|
||||
// PR_ memory functions are still fallible
|
||||
|
@ -61,8 +61,8 @@
|
||||
#include "nsIUUIDGenerator.h"
|
||||
#include "nsBlobProtocolHandler.h"
|
||||
#include "nsStringStream.h"
|
||||
#include "CheckedInt.h"
|
||||
#include "nsJSUtils.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
#include "plbase64.h"
|
||||
@ -227,7 +227,7 @@ ParseSize(PRInt64 aSize, PRInt64& aStart, PRInt64& aEnd)
|
||||
newEndOffset = aSize;
|
||||
}
|
||||
|
||||
if (!newStartOffset.valid() || !newEndOffset.valid() ||
|
||||
if (!newStartOffset.isValid() || !newEndOffset.isValid() ||
|
||||
newStartOffset.value() >= newEndOffset.value()) {
|
||||
aStart = aEnd = 0;
|
||||
}
|
||||
|
@ -2133,11 +2133,8 @@ nsGenericElement::SetScrollTop(PRInt32 aScrollTop)
|
||||
nsIScrollableFrame* sf = GetScrollFrame();
|
||||
if (sf) {
|
||||
nsPoint pt = sf->GetScrollPosition();
|
||||
pt.y = nsPresContext::CSSPixelsToAppUnits(aScrollTop);
|
||||
nscoord halfPixel = nsPresContext::CSSPixelsToAppUnits(0.5f);
|
||||
// Don't allow pt.y + halfPixel since that would round up to the next CSS pixel.
|
||||
nsRect range(pt.x, pt.y - halfPixel, 0, halfPixel*2 - 1);
|
||||
sf->ScrollTo(pt, nsIScrollableFrame::INSTANT, &range);
|
||||
sf->ScrollToCSSPixels(nsIntPoint(nsPresContext::AppUnitsToIntCSSPixels(pt.x),
|
||||
aScrollTop));
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
@ -2166,11 +2163,8 @@ nsGenericElement::SetScrollLeft(PRInt32 aScrollLeft)
|
||||
nsIScrollableFrame* sf = GetScrollFrame();
|
||||
if (sf) {
|
||||
nsPoint pt = sf->GetScrollPosition();
|
||||
pt.x = nsPresContext::CSSPixelsToAppUnits(aScrollLeft);
|
||||
nscoord halfPixel = nsPresContext::CSSPixelsToAppUnits(0.5f);
|
||||
// Don't allow pt.x + halfPixel since that would round up to the next CSS pixel.
|
||||
nsRect range(pt.x - halfPixel, pt.y, halfPixel*2 - 1, 0);
|
||||
sf->ScrollTo(pt, nsIScrollableFrame::INSTANT, &range);
|
||||
sf->ScrollToCSSPixels(nsIntPoint(aScrollLeft,
|
||||
nsPresContext::AppUnitsToIntCSSPixels(pt.y)));
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 sw=2 et tw=80: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
@ -109,6 +110,7 @@
|
||||
#include "nsIDOMFormData.h"
|
||||
|
||||
#include "nsWrapperCacheInlines.h"
|
||||
#include "nsStreamListenerWrapper.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
@ -3046,9 +3048,6 @@ nsXMLHttpRequest::Send(JSContext *aCx, nsIVariant* aVariant, const Nullable<Requ
|
||||
if (mState & XML_HTTP_REQUEST_MULTIPART) {
|
||||
Telemetry::Accumulate(Telemetry::MULTIPART_XHR_RESPONSE, 1);
|
||||
listener = new nsMultipartProxyListener(listener);
|
||||
if (!listener) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
} else {
|
||||
Telemetry::Accumulate(Telemetry::MULTIPART_XHR_RESPONSE, 0);
|
||||
}
|
||||
@ -3062,9 +3061,18 @@ nsXMLHttpRequest::Send(JSContext *aCx, nsIVariant* aVariant, const Nullable<Requ
|
||||
// a same-origin request right now, since it could be redirected.
|
||||
listener = new nsCORSListenerProxy(listener, mPrincipal, mChannel,
|
||||
withCredentials, true, &rv);
|
||||
NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
else {
|
||||
// Because of bug 682305, we can't let listener be the XHR object itself
|
||||
// because JS wouldn't be able to use it. So if we haven't otherwise
|
||||
// created a listener around 'this', do so now.
|
||||
|
||||
listener = new nsStreamListenerWrapper(listener);
|
||||
}
|
||||
|
||||
NS_ASSERTION(listener != this,
|
||||
"Using an object as a listener that can't be exposed to JS");
|
||||
|
||||
// Bypass the network cache in cases where it makes no sense:
|
||||
// 1) Multipart responses are very large and would likely be doomed by the
|
||||
|
@ -75,6 +75,7 @@ _CHROME_FILES = \
|
||||
test_bug650784.html \
|
||||
test_bug752226-3.xul \
|
||||
test_bug752226-4.xul \
|
||||
test_bug682305.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
|
159
content/base/test/chrome/test_bug682305.html
Normal file
@ -0,0 +1,159 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=682305
|
||||
-->
|
||||
<head>
|
||||
<title>XMLHttpRequest send and channel implemented in JS</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/ChromeUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=682305">Mozilla Bug 682305</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="application/javascript;version=1.8">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
/*
|
||||
* Register a custom nsIProtocolHandler service
|
||||
* in order to be able to implement *and use* an
|
||||
* nsIChannel component written in Javascript.
|
||||
*/
|
||||
|
||||
var Cc = Components.classes;
|
||||
var Ci = Components.interfaces;
|
||||
var Cr = Components.results;
|
||||
var Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
var SimpleURI = Cc["@mozilla.org/network/simple-uri;1"];
|
||||
var ios = Cc["@mozilla.org/network/io-service;1"]
|
||||
.getService(Ci.nsIIOService);
|
||||
|
||||
var PROTOCOL_SCHEME = "jsproto";
|
||||
|
||||
|
||||
function CustomChannel(uri) {
|
||||
this.URI = this.originalURI = uri;
|
||||
}
|
||||
CustomChannel.prototype = {
|
||||
URI: null,
|
||||
originalURI: null,
|
||||
contentCharset: "utf-8",
|
||||
contentLength: 0,
|
||||
contentType: "text/plain",
|
||||
owner: Cc["@mozilla.org/systemprincipal;1"].createInstance(Ci.nsIPrincipal),
|
||||
securityInfo: null,
|
||||
notificationCallbacks: null,
|
||||
loadFlags: 0,
|
||||
loadGroup: null,
|
||||
name: null,
|
||||
status: Cr.NS_OK,
|
||||
asyncOpen: function(listener, context) {
|
||||
let stream = this.open();
|
||||
try {
|
||||
listener.onStartRequest(this, context);
|
||||
} catch(e) {}
|
||||
try {
|
||||
listener.onDataAvailable(this, context, stream, 0, stream.available());
|
||||
} catch(e) {}
|
||||
try {
|
||||
listener.onStopRequest(this, context, Cr.NS_OK);
|
||||
} catch(e) {}
|
||||
},
|
||||
open: function() {
|
||||
let data = "bar";
|
||||
let stream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(Ci.nsIStringInputStream);
|
||||
stream.setData(data, data.length);
|
||||
return stream;
|
||||
},
|
||||
isPending: function() {
|
||||
return false;
|
||||
},
|
||||
cancel: function() {
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
suspend: function() {
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
resume: function() {
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIChannel, Ci.nsIRequest])
|
||||
};
|
||||
|
||||
|
||||
function CustomProtocol() {}
|
||||
CustomProtocol.prototype = {
|
||||
get scheme() {
|
||||
return PROTOCOL_SCHEME;
|
||||
},
|
||||
get protocolFlags() {
|
||||
return (Ci.nsIProtocolHandler.URI_NORELATIVE |
|
||||
Ci.nsIProtocolHandler.URI_IS_LOCAL_RESOURCE |
|
||||
Ci.nsIProtocolHandler.URI_DANGEROUS_TO_LOAD);
|
||||
},
|
||||
get defaultPort() {
|
||||
return -1;
|
||||
},
|
||||
allowPort: function allowPort() {
|
||||
return false;
|
||||
},
|
||||
newURI: function newURI(spec, charset, baseURI) {
|
||||
var uri = SimpleURI.createInstance(Ci.nsIURI)
|
||||
uri.spec = spec;
|
||||
return uri.QueryInterface(Ci.nsIURI);
|
||||
},
|
||||
newChannel: function newChannel(URI) {
|
||||
return new CustomChannel(URI);
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
|
||||
Ci.nsISupportsWeakReference,
|
||||
Ci.nsIProtocolHandler])
|
||||
};
|
||||
|
||||
var gFactory = {
|
||||
register: function() {
|
||||
var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
|
||||
|
||||
var classID = Components.ID("{ed064287-1e76-49ba-a28d-dc74394a8334}");
|
||||
var description = PROTOCOL_SCHEME + ": protocol";
|
||||
var contractID = "@mozilla.org/network/protocol;1?name=" + PROTOCOL_SCHEME;
|
||||
var factory = XPCOMUtils._getFactory(CustomProtocol);
|
||||
|
||||
registrar.registerFactory(classID, description, contractID, factory);
|
||||
|
||||
this.unregister = function() {
|
||||
registrar.unregisterFactory(classID, factory);
|
||||
delete this.unregister;
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// Register the custom procotol handler
|
||||
gFactory.register();
|
||||
|
||||
// Then, checks if XHR works with it
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", PROTOCOL_SCHEME + ":foo", true);
|
||||
xhr.onload = function () {
|
||||
is(xhr.responseText, "bar", "protocol doesn't work");
|
||||
gFactory.unregister();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
try {
|
||||
xhr.send(null);
|
||||
} catch(e) {
|
||||
ok(false, e);
|
||||
}
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -40,7 +40,7 @@
|
||||
|
||||
#include "prtypes.h"
|
||||
|
||||
#include "CheckedInt.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
|
||||
class nsHTMLCanvasElement;
|
||||
class nsIPrincipal;
|
||||
@ -63,9 +63,9 @@ inline bool CheckSaneSubrectSize(PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h,
|
||||
CheckedInt32 checked_ymost = CheckedInt32(y) + h;
|
||||
|
||||
return w >= 0 && h >= 0 && x >= 0 && y >= 0 &&
|
||||
checked_xmost.valid() &&
|
||||
checked_xmost.isValid() &&
|
||||
checked_xmost.value() <= realWidth &&
|
||||
checked_ymost.valid() &&
|
||||
checked_ymost.isValid() &&
|
||||
checked_ymost.value() <= realHeight;
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,7 @@
|
||||
|
||||
#include "nsDOMError.h"
|
||||
#include "nsIDOMCanvasRenderingContext2D.h"
|
||||
#include "CheckedInt.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "nsMathUtils.h"
|
||||
#include "CustomQS_Canvas.h"
|
||||
|
||||
@ -169,7 +169,7 @@ CreateImageData(JSContext* cx, JSObject* obj, uint32_t w, uint32_t h, jsval* vp)
|
||||
h = 1;
|
||||
|
||||
CheckedInt<uint32_t> len = CheckedInt<uint32_t>(w) * h * 4;
|
||||
if (!len.valid()) {
|
||||
if (!len.isValid()) {
|
||||
return xpc_qsThrow(cx, NS_ERROR_DOM_INDEX_SIZE_ERR);
|
||||
}
|
||||
|
||||
|
@ -425,7 +425,7 @@ WebGLContext::SetDimensions(PRInt32 width, PRInt32 height)
|
||||
// If incrementing the generation would cause overflow,
|
||||
// don't allow it. Allowing this would allow us to use
|
||||
// resource handles created from older context generations.
|
||||
if (!(mGeneration+1).valid())
|
||||
if (!(mGeneration + 1).isValid())
|
||||
return NS_ERROR_FAILURE; // exit without changing the value of mGeneration
|
||||
|
||||
gl::ContextFormat format(gl::ContextFormat::BasicRGBA32);
|
||||
|
@ -64,9 +64,9 @@
|
||||
#include "GLContextProvider.h"
|
||||
#include "Layers.h"
|
||||
|
||||
#include "CheckedInt.h"
|
||||
#include "nsDataHashtable.h"
|
||||
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/dom/ImageData.h"
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
@ -481,7 +481,7 @@ public:
|
||||
private:
|
||||
WebGLMonotonicHandle NextMonotonicHandle() {
|
||||
++mCurrentMonotonicHandle;
|
||||
if (!mCurrentMonotonicHandle.valid())
|
||||
if (!mCurrentMonotonicHandle.isValid())
|
||||
NS_RUNTIMEABORT("ran out of monotonic ids!");
|
||||
return mCurrentMonotonicHandle.value();
|
||||
}
|
||||
@ -1748,7 +1748,7 @@ public:
|
||||
|
||||
bool HasImageInfoAt(size_t level, size_t face) const {
|
||||
CheckedUint32 checked_index = CheckedUint32(level) * mFacesCount + face;
|
||||
return checked_index.valid() &&
|
||||
return checked_index.isValid() &&
|
||||
checked_index.value() < mImageInfos.Length() &&
|
||||
ImageInfoAt(level, face).mIsDefined;
|
||||
}
|
||||
@ -2328,7 +2328,7 @@ public:
|
||||
|
||||
bool NextGeneration()
|
||||
{
|
||||
if (!(mGeneration+1).valid())
|
||||
if (!(mGeneration + 1).isValid())
|
||||
return false; // must exit without changing mGeneration
|
||||
++mGeneration;
|
||||
return true;
|
||||
|
@ -687,7 +687,7 @@ WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
|
||||
return ErrorInvalidOperation("BufferData: no buffer bound!");
|
||||
|
||||
CheckedUint32 checked_neededByteLength = CheckedUint32(byteOffset) + data->mLength;
|
||||
if (!checked_neededByteLength.valid())
|
||||
if (!checked_neededByteLength.isValid())
|
||||
return ErrorInvalidOperation("bufferSubData: integer overflow computing the needed byte length");
|
||||
|
||||
if (checked_neededByteLength.value() > boundBuffer->ByteLength())
|
||||
@ -726,7 +726,7 @@ WebGLContext::BufferSubData(WebGLenum target, WebGLsizeiptr byteOffset,
|
||||
return ErrorInvalidOperation("BufferSubData: no buffer bound!");
|
||||
|
||||
CheckedUint32 checked_neededByteLength = CheckedUint32(byteOffset) + data.mLength;
|
||||
if (!checked_neededByteLength.valid())
|
||||
if (!checked_neededByteLength.isValid())
|
||||
return ErrorInvalidOperation("bufferSubData: integer overflow computing the needed byte length");
|
||||
|
||||
if (checked_neededByteLength.value() > boundBuffer->ByteLength())
|
||||
@ -941,7 +941,7 @@ WebGLContext::CopyTexSubImage2D_base(WebGLenum target,
|
||||
CheckedUint32 checked_neededByteLength =
|
||||
GetImageSize(height, width, texelSize, mPixelStoreUnpackAlignment);
|
||||
|
||||
if (!checked_neededByteLength.valid())
|
||||
if (!checked_neededByteLength.isValid())
|
||||
return ErrorInvalidOperation("%s: integer overflow computing the needed buffer size", info);
|
||||
|
||||
PRUint32 bytesNeeded = checked_neededByteLength.value();
|
||||
@ -1562,7 +1562,7 @@ WebGLContext::DoFakeVertexAttrib0(WebGLuint vertexCount)
|
||||
|
||||
CheckedUint32 checked_dataSize = CheckedUint32(vertexCount) * 4 * sizeof(WebGLfloat);
|
||||
|
||||
if (!checked_dataSize.valid()) {
|
||||
if (!checked_dataSize.isValid()) {
|
||||
ErrorOutOfMemory("Integer overflow trying to construct a fake vertex attrib 0 array for a draw-operation "
|
||||
"with %d vertices. Try reducing the number of vertices.", vertexCount);
|
||||
return false;
|
||||
@ -1779,7 +1779,7 @@ WebGLContext::DrawArrays(GLenum mode, WebGLint first, WebGLsizei count)
|
||||
|
||||
CheckedInt32 checked_firstPlusCount = CheckedInt32(first) + count;
|
||||
|
||||
if (!checked_firstPlusCount.valid())
|
||||
if (!checked_firstPlusCount.isValid())
|
||||
return ErrorInvalidOperation("drawArrays: overflow in first+count");
|
||||
|
||||
if (checked_firstPlusCount.value() > maxAllowedCount)
|
||||
@ -1847,7 +1847,7 @@ WebGLContext::DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type,
|
||||
return ErrorInvalidEnum("DrawElements: type must be UNSIGNED_SHORT or UNSIGNED_BYTE");
|
||||
}
|
||||
|
||||
if (!checked_byteCount.valid())
|
||||
if (!checked_byteCount.isValid())
|
||||
return ErrorInvalidValue("DrawElements: overflow in byteCount");
|
||||
|
||||
// If there is no current program, this is silently ignored.
|
||||
@ -1863,7 +1863,7 @@ WebGLContext::DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type,
|
||||
|
||||
CheckedUint32 checked_neededByteCount = checked_byteCount + byteOffset;
|
||||
|
||||
if (!checked_neededByteCount.valid())
|
||||
if (!checked_neededByteCount.isValid())
|
||||
return ErrorInvalidOperation("DrawElements: overflow in byteOffset+byteCount");
|
||||
|
||||
if (checked_neededByteCount.value() > mBoundElementArrayBuffer->ByteLength())
|
||||
@ -1880,7 +1880,7 @@ WebGLContext::DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type,
|
||||
|
||||
CheckedInt32 checked_maxIndexPlusOne = CheckedInt32(maxIndex) + 1;
|
||||
|
||||
if (!checked_maxIndexPlusOne.valid() ||
|
||||
if (!checked_maxIndexPlusOne.isValid() ||
|
||||
checked_maxIndexPlusOne.value() > maxAllowedCount)
|
||||
{
|
||||
// the index array contains invalid indices for the current drawing state, but they
|
||||
@ -1893,7 +1893,7 @@ WebGLContext::DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type,
|
||||
|
||||
CheckedInt32 checked_maxIndexInSubArrayPlusOne = CheckedInt32(maxIndexInSubArray) + 1;
|
||||
|
||||
if (!checked_maxIndexInSubArrayPlusOne.valid() ||
|
||||
if (!checked_maxIndexInSubArrayPlusOne.isValid() ||
|
||||
checked_maxIndexInSubArrayPlusOne.value() > maxAllowedCount)
|
||||
{
|
||||
return ErrorInvalidOperation(
|
||||
@ -3883,7 +3883,7 @@ WebGLContext::ReadPixels(WebGLint x, WebGLint y, WebGLsizei width,
|
||||
CheckedUint32 checked_alignedRowSize =
|
||||
RoundedToNextMultipleOf(checked_plainRowSize, mPixelStorePackAlignment);
|
||||
|
||||
if (!checked_neededByteLength.valid())
|
||||
if (!checked_neededByteLength.isValid())
|
||||
return ErrorInvalidOperation("ReadPixels: integer overflow computing the needed buffer size");
|
||||
|
||||
if (checked_neededByteLength.value() > dataByteLen)
|
||||
@ -5601,7 +5601,7 @@ WebGLContext::TexImage2D_base(WebGLenum target, WebGLint level, WebGLenum intern
|
||||
CheckedUint32 checked_alignedRowSize =
|
||||
RoundedToNextMultipleOf(checked_plainRowSize.value(), mPixelStoreUnpackAlignment);
|
||||
|
||||
if (!checked_neededByteLength.valid())
|
||||
if (!checked_neededByteLength.isValid())
|
||||
return ErrorInvalidOperation("texImage2D: integer overflow computing the needed buffer size");
|
||||
|
||||
PRUint32 bytesNeeded = checked_neededByteLength.value();
|
||||
@ -5842,7 +5842,7 @@ WebGLContext::TexSubImage2D_base(WebGLenum target, WebGLint level,
|
||||
CheckedUint32 checked_alignedRowSize =
|
||||
RoundedToNextMultipleOf(checked_plainRowSize.value(), mPixelStoreUnpackAlignment);
|
||||
|
||||
if (!checked_neededByteLength.valid())
|
||||
if (!checked_neededByteLength.isValid())
|
||||
return ErrorInvalidOperation("texSubImage2D: integer overflow computing the needed buffer size");
|
||||
|
||||
PRUint32 bytesNeeded = checked_neededByteLength.value();
|
||||
|
@ -40,8 +40,7 @@
|
||||
#include "WebGLContext.h"
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
#include "CheckedInt.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
|
||||
#include "jsfriendapi.h"
|
||||
|
||||
@ -143,8 +142,8 @@ WebGLContext::ValidateBuffers(PRInt32 *maxAllowedCount, const char *info)
|
||||
CheckedInt32 checked_sizeOfLastElement
|
||||
= CheckedInt32(vd.componentSize()) * vd.size;
|
||||
|
||||
if (!checked_byteLength.valid() ||
|
||||
!checked_sizeOfLastElement.valid())
|
||||
if (!checked_byteLength.isValid() ||
|
||||
!checked_sizeOfLastElement.isValid())
|
||||
{
|
||||
ErrorInvalidOperation("%s: integer overflow occured while checking vertex attrib %d", info, i);
|
||||
return false;
|
||||
@ -156,7 +155,7 @@ WebGLContext::ValidateBuffers(PRInt32 *maxAllowedCount, const char *info)
|
||||
CheckedInt32 checked_maxAllowedCount
|
||||
= ((checked_byteLength - checked_sizeOfLastElement) / vd.actualStride()) + 1;
|
||||
|
||||
if (!checked_maxAllowedCount.valid()) {
|
||||
if (!checked_maxAllowedCount.isValid()) {
|
||||
ErrorInvalidOperation("%s: integer overflow occured while checking vertex attrib %d", info, i);
|
||||
return false;
|
||||
}
|
||||
@ -401,7 +400,7 @@ bool WebGLContext::ValidateCompressedTextureSize(WebGLint level, WebGLenum forma
|
||||
{
|
||||
CheckedUint32 calculated_byteLength = 0;
|
||||
CheckedUint32 checked_byteLength = byteLength;
|
||||
if (!checked_byteLength.valid()) {
|
||||
if (!checked_byteLength.isValid()) {
|
||||
ErrorInvalidValue("%s: data length out of bounds", info);
|
||||
return false;
|
||||
}
|
||||
@ -411,7 +410,7 @@ bool WebGLContext::ValidateCompressedTextureSize(WebGLint level, WebGLenum forma
|
||||
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
|
||||
{
|
||||
calculated_byteLength = ((CheckedUint32(width) + 3) / 4) * ((CheckedUint32(height) + 3) / 4) * 8;
|
||||
if (!calculated_byteLength.valid() || !(checked_byteLength == calculated_byteLength)) {
|
||||
if (!calculated_byteLength.isValid() || !(checked_byteLength == calculated_byteLength)) {
|
||||
ErrorInvalidValue("%s: data size does not match dimensions", info);
|
||||
return false;
|
||||
}
|
||||
@ -421,7 +420,7 @@ bool WebGLContext::ValidateCompressedTextureSize(WebGLint level, WebGLenum forma
|
||||
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
||||
{
|
||||
calculated_byteLength = ((CheckedUint32(width) + 3) / 4) * ((CheckedUint32(height) + 3) / 4) * 16;
|
||||
if (!calculated_byteLength.valid() || !(checked_byteLength == calculated_byteLength)) {
|
||||
if (!calculated_byteLength.isValid() || !(checked_byteLength == calculated_byteLength)) {
|
||||
ErrorInvalidValue("%s: data size does not match dimensions", info);
|
||||
return false;
|
||||
}
|
||||
|
@ -108,7 +108,6 @@
|
||||
#include "nsIMemoryReporter.h"
|
||||
#include "nsStyleUtil.h"
|
||||
#include "CanvasImageCache.h"
|
||||
#include "CheckedInt.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@ -116,6 +115,7 @@
|
||||
#include "jsfriendapi.h"
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/ImageData.h"
|
||||
#include "mozilla/dom/PBrowserParent.h"
|
||||
@ -3926,14 +3926,14 @@ nsCanvasRenderingContext2D::GetImageDataArray(JSContext* aCx,
|
||||
MOZ_ASSERT(aWidth && aHeight);
|
||||
|
||||
CheckedInt<uint32_t> len = CheckedInt<uint32_t>(aWidth) * aHeight * 4;
|
||||
if (!len.valid()) {
|
||||
if (!len.isValid()) {
|
||||
return NS_ERROR_DOM_INDEX_SIZE_ERR;
|
||||
}
|
||||
|
||||
CheckedInt<int32_t> rightMost = CheckedInt<int32_t>(aX) + aWidth;
|
||||
CheckedInt<int32_t> bottomMost = CheckedInt<int32_t>(aY) + aHeight;
|
||||
|
||||
if (!rightMost.valid() || !bottomMost.valid()) {
|
||||
if (!rightMost.isValid() || !bottomMost.isValid()) {
|
||||
return NS_ERROR_DOM_SYNTAX_ERR;
|
||||
}
|
||||
|
||||
@ -4066,7 +4066,7 @@ nsCanvasRenderingContext2D::PutImageData_explicit(PRInt32 x, PRInt32 y, PRUint32
|
||||
|
||||
CheckedInt32 checkedDirtyX = CheckedInt32(dirtyX) + dirtyWidth;
|
||||
|
||||
if (!checkedDirtyX.valid())
|
||||
if (!checkedDirtyX.isValid())
|
||||
return NS_ERROR_DOM_INDEX_SIZE_ERR;
|
||||
|
||||
dirtyX = checkedDirtyX.value();
|
||||
@ -4078,7 +4078,7 @@ nsCanvasRenderingContext2D::PutImageData_explicit(PRInt32 x, PRInt32 y, PRUint32
|
||||
|
||||
CheckedInt32 checkedDirtyY = CheckedInt32(dirtyY) + dirtyHeight;
|
||||
|
||||
if (!checkedDirtyY.valid())
|
||||
if (!checkedDirtyY.isValid())
|
||||
return NS_ERROR_DOM_INDEX_SIZE_ERR;
|
||||
|
||||
dirtyY = checkedDirtyY.value();
|
||||
|
@ -104,7 +104,6 @@
|
||||
#include "nsIMemoryReporter.h"
|
||||
#include "nsStyleUtil.h"
|
||||
#include "CanvasImageCache.h"
|
||||
#include "CheckedInt.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@ -112,6 +111,7 @@
|
||||
#include "jsfriendapi.h"
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/ImageData.h"
|
||||
#include "mozilla/dom/PBrowserParent.h"
|
||||
@ -4095,14 +4095,14 @@ nsCanvasRenderingContext2DAzure::GetImageDataArray(JSContext* aCx,
|
||||
MOZ_ASSERT(aWidth && aHeight);
|
||||
|
||||
CheckedInt<uint32_t> len = CheckedInt<uint32_t>(aWidth) * aHeight * 4;
|
||||
if (!len.valid()) {
|
||||
if (!len.isValid()) {
|
||||
return NS_ERROR_DOM_INDEX_SIZE_ERR;
|
||||
}
|
||||
|
||||
CheckedInt<int32_t> rightMost = CheckedInt<int32_t>(aX) + aWidth;
|
||||
CheckedInt<int32_t> bottomMost = CheckedInt<int32_t>(aY) + aHeight;
|
||||
|
||||
if (!rightMost.valid() || !bottomMost.valid()) {
|
||||
if (!rightMost.isValid() || !bottomMost.isValid()) {
|
||||
return NS_ERROR_DOM_SYNTAX_ERR;
|
||||
}
|
||||
|
||||
@ -4233,7 +4233,7 @@ nsCanvasRenderingContext2DAzure::PutImageData_explicit(PRInt32 x, PRInt32 y, PRU
|
||||
|
||||
CheckedInt32 checkedDirtyX = CheckedInt32(dirtyX) + dirtyWidth;
|
||||
|
||||
if (!checkedDirtyX.valid())
|
||||
if (!checkedDirtyX.isValid())
|
||||
return NS_ERROR_DOM_INDEX_SIZE_ERR;
|
||||
|
||||
dirtyX = checkedDirtyX.value();
|
||||
@ -4245,7 +4245,7 @@ nsCanvasRenderingContext2DAzure::PutImageData_explicit(PRInt32 x, PRInt32 y, PRU
|
||||
|
||||
CheckedInt32 checkedDirtyY = CheckedInt32(dirtyY) + dirtyHeight;
|
||||
|
||||
if (!checkedDirtyY.valid())
|
||||
if (!checkedDirtyY.isValid())
|
||||
return NS_ERROR_DOM_INDEX_SIZE_ERR;
|
||||
|
||||
dirtyY = checkedDirtyY.value();
|
||||
|
@ -38,10 +38,10 @@
|
||||
#include "nsHTMLCanvasElement.h"
|
||||
|
||||
#include "mozilla/Base64.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "prmem.h"
|
||||
#include "nsDOMFile.h"
|
||||
#include "CheckedInt.h"
|
||||
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIXPConnect.h"
|
||||
|
@ -3310,17 +3310,15 @@ nsHTMLInputElement::AllowDrop()
|
||||
void
|
||||
nsHTMLInputElement::AddedToRadioGroup()
|
||||
{
|
||||
// Make sure not to notify if we're still being created by the parser
|
||||
bool notify = !mParserCreating;
|
||||
|
||||
//
|
||||
// If the input element is not in a form and
|
||||
// not in a document, we just need to return.
|
||||
//
|
||||
if (!mForm && !(IsInDoc() && GetParent())) {
|
||||
// If the element is neither in a form nor a document, there is no group so we
|
||||
// should just stop here.
|
||||
if (!mForm && !IsInDoc()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure not to notify if we're still being created by the parser
|
||||
bool notify = !mParserCreating;
|
||||
|
||||
//
|
||||
// If the input element is checked, and we add it to the group, it will
|
||||
// deselect whatever is currently selected in that group
|
||||
|
@ -98,6 +98,9 @@
|
||||
#include "nsDOMMediaStream.h"
|
||||
#include "nsIScriptError.h"
|
||||
|
||||
#include "nsCSSParser.h"
|
||||
#include "nsIMediaList.h"
|
||||
|
||||
#ifdef MOZ_OGG
|
||||
#include "nsOggDecoder.h"
|
||||
#endif
|
||||
@ -850,6 +853,12 @@ void nsHTMLMediaElement::LoadFromSourceChildren()
|
||||
"Should delay load event (if in document) during load");
|
||||
NS_ASSERTION(mIsLoadingFromSourceChildren,
|
||||
"Must remember we're loading from source children");
|
||||
|
||||
nsIDocument* parentDoc = OwnerDoc()->GetParentDocument();
|
||||
if (parentDoc) {
|
||||
parentDoc->FlushPendingNotifications(Flush_Layout);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
nsIContent* child = GetNextSource();
|
||||
if (!child) {
|
||||
@ -876,11 +885,25 @@ void nsHTMLMediaElement::LoadFromSourceChildren()
|
||||
GetCanPlay(type) == CANPLAY_NO) {
|
||||
DispatchAsyncSourceError(child);
|
||||
const PRUnichar* params[] = { type.get(), src.get() };
|
||||
ReportLoadError("MediaLoadUnsupportedType", params, ArrayLength(params));
|
||||
ReportLoadError("MediaLoadUnsupportedTypeAttribute", params, ArrayLength(params));
|
||||
continue;
|
||||
}
|
||||
LOG(PR_LOG_DEBUG, ("%p Trying load from <source>=%s type=%s", this,
|
||||
NS_ConvertUTF16toUTF8(src).get(), NS_ConvertUTF16toUTF8(type).get()));
|
||||
nsAutoString media;
|
||||
if (child->GetAttr(kNameSpaceID_None, nsGkAtoms::media, media) && !media.IsEmpty()) {
|
||||
nsCSSParser cssParser;
|
||||
nsRefPtr<nsMediaList> mediaList(new nsMediaList());
|
||||
cssParser.ParseMediaList(media, NULL, 0, mediaList, false);
|
||||
nsIPresShell* presShell = OwnerDoc()->GetShell();
|
||||
if (presShell && !mediaList->Matches(presShell->GetPresContext(), NULL)) {
|
||||
DispatchAsyncSourceError(child);
|
||||
const PRUnichar* params[] = { media.get(), src.get() };
|
||||
ReportLoadError("MediaLoadSourceMediaNotMatched", params, ArrayLength(params));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
LOG(PR_LOG_DEBUG, ("%p Trying load from <source>=%s type=%s media=%s", this,
|
||||
NS_ConvertUTF16toUTF8(src).get(), NS_ConvertUTF16toUTF8(type).get(),
|
||||
NS_ConvertUTF16toUTF8(media).get()));
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
NewURIFromString(src, getter_AddRefs(uri));
|
||||
|
@ -114,6 +114,7 @@ NS_IMPL_ELEMENT_CLONE(nsHTMLSourceElement)
|
||||
|
||||
NS_IMPL_URI_ATTR(nsHTMLSourceElement, Src, src)
|
||||
NS_IMPL_STRING_ATTR(nsHTMLSourceElement, Type, type)
|
||||
NS_IMPL_STRING_ATTR(nsHTMLSourceElement, Media, media)
|
||||
|
||||
nsresult
|
||||
nsHTMLSourceElement::BindToTree(nsIDocument *aDocument,
|
||||
|
@ -243,32 +243,88 @@ nsMathMLElement::GetAttributeMappingFunction() const
|
||||
return &MapMathMLAttributesInto;
|
||||
}
|
||||
|
||||
// ================
|
||||
// Utilities for parsing and retrieving numeric values
|
||||
|
||||
/*
|
||||
The REC says:
|
||||
An explicit plus sign ('+') is not allowed as part of a numeric value
|
||||
except when it is specifically listed in the syntax (as a quoted '+'
|
||||
or "+"),
|
||||
|
||||
Units allowed
|
||||
ID Description
|
||||
em ems (font-relative unit traditionally used for horizontal lengths)
|
||||
ex exs (font-relative unit traditionally used for vertical lengths)
|
||||
px pixels, or pixel size of a "typical computer display"
|
||||
in inches (1 inch = 2.54 centimeters)
|
||||
cm centimeters
|
||||
mm millimeters
|
||||
pt points (1 point = 1/72 inch)
|
||||
pc picas (1 pica = 12 points)
|
||||
% percentage of default value
|
||||
|
||||
Implementation here:
|
||||
The numeric value is valid only if it is of the form [-] nnn.nnn
|
||||
[h/v-unit]
|
||||
*/
|
||||
|
||||
/* static */ bool
|
||||
nsMathMLElement::ParseNamedSpaceValue(const nsString& aString,
|
||||
nsCSSValue& aCSSValue,
|
||||
PRUint32 aFlags)
|
||||
{
|
||||
PRInt32 i = 0;
|
||||
// See if it is one of the 'namedspace' (ranging -7/18em, -6/18, ... 7/18em)
|
||||
if (aString.EqualsLiteral("veryverythinmathspace")) {
|
||||
i = 1;
|
||||
} else if (aString.EqualsLiteral("verythinmathspace")) {
|
||||
i = 2;
|
||||
} else if (aString.EqualsLiteral("thinmathspace")) {
|
||||
i = 3;
|
||||
} else if (aString.EqualsLiteral("mediummathspace")) {
|
||||
i = 4;
|
||||
} else if (aString.EqualsLiteral("thickmathspace")) {
|
||||
i = 5;
|
||||
} else if (aString.EqualsLiteral("verythickmathspace")) {
|
||||
i = 6;
|
||||
} else if (aString.EqualsLiteral("veryverythickmathspace")) {
|
||||
i = 7;
|
||||
} else if (aFlags & PARSE_ALLOW_NEGATIVE) {
|
||||
if (aString.EqualsLiteral("negativeveryverythinmathspace")) {
|
||||
i = -1;
|
||||
} else if (aString.EqualsLiteral("negativeverythinmathspace")) {
|
||||
i = -2;
|
||||
} else if (aString.EqualsLiteral("negativethinmathspace")) {
|
||||
i = -3;
|
||||
} else if (aString.EqualsLiteral("negativemediummathspace")) {
|
||||
i = -4;
|
||||
} else if (aString.EqualsLiteral("negativethickmathspace")) {
|
||||
i = -5;
|
||||
} else if (aString.EqualsLiteral("negativeverythickmathspace")) {
|
||||
i = -6;
|
||||
} else if (aString.EqualsLiteral("negativeveryverythickmathspace")) {
|
||||
i = -7;
|
||||
}
|
||||
}
|
||||
if (0 != i) {
|
||||
aCSSValue.SetFloatValue(float(i)/float(18), eCSSUnit_EM);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// The REC says:
|
||||
//
|
||||
// "Most presentation elements have attributes that accept values representing
|
||||
// lengths to be used for size, spacing or similar properties. The syntax of a
|
||||
// length is specified as
|
||||
//
|
||||
// number | number unit | namedspace
|
||||
//
|
||||
// There should be no space between the number and the unit of a length."
|
||||
//
|
||||
// "A trailing '%' represents a percent of the default value. The default
|
||||
// value, or how it is obtained, is listed in the table of attributes for each
|
||||
// element. [...] A number without a unit is intepreted as a multiple of the
|
||||
// default value."
|
||||
//
|
||||
// "The possible units in MathML are:
|
||||
//
|
||||
// Unit Description
|
||||
// em an em (font-relative unit traditionally used for horizontal lengths)
|
||||
// ex an ex (font-relative unit traditionally used for vertical lengths)
|
||||
// px pixels, or size of a pixel in the current display
|
||||
// in inches (1 inch = 2.54 centimeters)
|
||||
// cm centimeters
|
||||
// mm millimeters
|
||||
// pt points (1 point = 1/72 inch)
|
||||
// pc picas (1 pica = 12 points)
|
||||
// % percentage of default value"
|
||||
//
|
||||
// The numbers are defined that way:
|
||||
// - unsigned-number: "a string of decimal digits with up to one decimal point
|
||||
// (U+002E), representing a non-negative terminating decimal number (a type of
|
||||
// rational number)"
|
||||
// - number: "an optional prefix of '-' (U+002D), followed by an unsigned
|
||||
// number, representing a terminating decimal number (a type of rational
|
||||
// number)"
|
||||
//
|
||||
/* static */ bool
|
||||
nsMathMLElement::ParseNumericValue(const nsString& aString,
|
||||
nsCSSValue& aCSSValue,
|
||||
@ -281,6 +337,10 @@ nsMathMLElement::ParseNumericValue(const nsString& aString,
|
||||
if (!stringLength)
|
||||
return false;
|
||||
|
||||
if (ParseNamedSpaceValue(aString, aCSSValue, aFlags)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsAutoString number, unit;
|
||||
|
||||
// see if the negative sign is there
|
||||
@ -289,10 +349,6 @@ nsMathMLElement::ParseNumericValue(const nsString& aString,
|
||||
if (c == '-') {
|
||||
number.Append(c);
|
||||
i++;
|
||||
|
||||
// skip any space after the negative sign
|
||||
if (i < stringLength && nsCRT::IsAsciiSpace(str[i]))
|
||||
i++;
|
||||
}
|
||||
|
||||
// Gather up characters that make up the number
|
||||
@ -358,6 +414,14 @@ nsMathMLElement::MapMathMLAttributesInto(const nsMappedAttributes* aAttributes,
|
||||
nsRuleData* aData)
|
||||
{
|
||||
if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Font)) {
|
||||
// scriptsizemultiplier
|
||||
//
|
||||
// "Specifies the multiplier to be used to adjust font size due to changes
|
||||
// in scriptlevel.
|
||||
//
|
||||
// values: number
|
||||
// default: 0.71
|
||||
//
|
||||
const nsAttrValue* value =
|
||||
aAttributes->GetAttr(nsGkAtoms::scriptsizemultiplier_);
|
||||
nsCSSValue* scriptSizeMultiplier =
|
||||
@ -377,6 +441,18 @@ nsMathMLElement::MapMathMLAttributesInto(const nsMappedAttributes* aAttributes,
|
||||
}
|
||||
}
|
||||
|
||||
// scriptminsize
|
||||
//
|
||||
// "Specifies the minimum font size allowed due to changes in scriptlevel.
|
||||
// Note that this does not limit the font size due to changes to mathsize."
|
||||
//
|
||||
// values: length
|
||||
// default: 8pt
|
||||
//
|
||||
// We don't allow negative values.
|
||||
// XXXfredw Should we allow unitless values? (bug 411227)
|
||||
// XXXfredw Does a relative unit give a multiple of the default value?
|
||||
//
|
||||
value = aAttributes->GetAttr(nsGkAtoms::scriptminsize_);
|
||||
nsCSSValue* scriptMinSize = aData->ValueForScriptMinSize();
|
||||
if (value && value->Type() == nsAttrValue::eString &&
|
||||
@ -384,6 +460,17 @@ nsMathMLElement::MapMathMLAttributesInto(const nsMappedAttributes* aAttributes,
|
||||
ParseNumericValue(value->GetStringValue(), *scriptMinSize, 0);
|
||||
}
|
||||
|
||||
// scriptlevel
|
||||
//
|
||||
// "Changes the scriptlevel in effect for the children. When the value is
|
||||
// given without a sign, it sets scriptlevel to the specified value; when a
|
||||
// sign is given, it increments ("+") or decrements ("-") the current
|
||||
// value. (Note that large decrements can result in negative values of
|
||||
// scriptlevel, but these values are considered legal.)"
|
||||
//
|
||||
// values: ( "+" | "-" )? unsigned-integer
|
||||
// default: inherited
|
||||
//
|
||||
value = aAttributes->GetAttr(nsGkAtoms::scriptlevel_);
|
||||
nsCSSValue* scriptLevel = aData->ValueForScriptLevel();
|
||||
if (value && value->Type() == nsAttrValue::eString &&
|
||||
@ -408,6 +495,28 @@ nsMathMLElement::MapMathMLAttributesInto(const nsMappedAttributes* aAttributes,
|
||||
}
|
||||
}
|
||||
|
||||
// mathsize
|
||||
//
|
||||
// "Specifies the size to display the token content. The values 'small' and
|
||||
// 'big' choose a size smaller or larger than the current font size, but
|
||||
// leave the exact proportions unspecified; 'normal' is allowed for
|
||||
// completeness, but since it is equivalent to '100%' or '1em', it has no
|
||||
// effect."
|
||||
//
|
||||
// values: "small" | "normal" | "big" | length
|
||||
// default: inherited
|
||||
//
|
||||
// fontsize
|
||||
//
|
||||
// "Specified the size for the token. Deprecated in favor of mathsize."
|
||||
//
|
||||
// values: length
|
||||
// default: inherited
|
||||
//
|
||||
// In both cases, we don't allow negative values.
|
||||
// XXXfredw Should we allow unitless values? (bug 411227)
|
||||
// XXXfredw Does a relative unit give a multiple of the default value?
|
||||
//
|
||||
bool parseSizeKeywords = true;
|
||||
value = aAttributes->GetAttr(nsGkAtoms::mathsize_);
|
||||
if (!value) {
|
||||
@ -435,6 +544,14 @@ nsMathMLElement::MapMathMLAttributesInto(const nsMappedAttributes* aAttributes,
|
||||
}
|
||||
}
|
||||
|
||||
// fontfamily
|
||||
//
|
||||
// "Should be the name of a font that may be available to a MathML renderer,
|
||||
// or a CSS font specification; See Section 6.5 Using CSS with MathML and
|
||||
// CSS for more information. Deprecated in favor of mathvariant."
|
||||
//
|
||||
// values: string
|
||||
//
|
||||
value = aAttributes->GetAttr(nsGkAtoms::fontfamily_);
|
||||
nsCSSValue* fontFamily = aData->ValueForFontFamily();
|
||||
if (value && value->Type() == nsAttrValue::eString &&
|
||||
@ -443,6 +560,24 @@ nsMathMLElement::MapMathMLAttributesInto(const nsMappedAttributes* aAttributes,
|
||||
}
|
||||
}
|
||||
|
||||
// mathbackground
|
||||
//
|
||||
// "Specifies the background color to be used to fill in the bounding box of
|
||||
// the element and its children. The default, 'transparent', lets the
|
||||
// background color, if any, used in the current rendering context to show
|
||||
// through."
|
||||
//
|
||||
// values: color | "transparent"
|
||||
// default: "transparent"
|
||||
//
|
||||
// background
|
||||
//
|
||||
// "Specified the background color to be used to fill in the bounding box of
|
||||
// the element and its children. Deprecated in favor of mathbackground."
|
||||
//
|
||||
// values: color | "transparent"
|
||||
// default: "transparent"
|
||||
//
|
||||
if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Background)) {
|
||||
const nsAttrValue* value =
|
||||
aAttributes->GetAttr(nsGkAtoms::mathbackground_);
|
||||
@ -458,6 +593,23 @@ nsMathMLElement::MapMathMLAttributesInto(const nsMappedAttributes* aAttributes,
|
||||
}
|
||||
}
|
||||
|
||||
// mathcolor
|
||||
//
|
||||
// "Specifies the foreground color to use when drawing the components of this
|
||||
// element, such as the content for token elements or any lines, surds, or
|
||||
// other decorations. It also establishes the default mathcolor used for
|
||||
// child elements when used on a layout element."
|
||||
//
|
||||
// values: color
|
||||
// default: inherited
|
||||
//
|
||||
// color
|
||||
//
|
||||
// "Specified the color for the token. Deprecated in favor of mathcolor."
|
||||
//
|
||||
// values: color
|
||||
// default: inherited
|
||||
//
|
||||
if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Color)) {
|
||||
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::mathcolor_);
|
||||
if (!value) {
|
||||
|
@ -89,6 +89,10 @@ public:
|
||||
PARSE_ALLOW_UNITLESS = 0x01, // unitless 0 will be turned into 0px
|
||||
PARSE_ALLOW_NEGATIVE = 0x02
|
||||
};
|
||||
static bool ParseNamedSpaceValue(const nsString& aString,
|
||||
nsCSSValue& aCSSValue,
|
||||
PRUint32 aFlags);
|
||||
|
||||
static bool ParseNumericValue(const nsString& aString,
|
||||
nsCSSValue& aCSSValue,
|
||||
PRUint32 aFlags);
|
||||
|
@ -40,13 +40,12 @@
|
||||
#define VideoUtils_h
|
||||
|
||||
#include "mozilla/ReentrantMonitor.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
|
||||
#include "nsRect.h"
|
||||
#include "nsIThreadManager.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#include "CheckedInt.h"
|
||||
|
||||
using mozilla::CheckedInt64;
|
||||
using mozilla::CheckedUint64;
|
||||
using mozilla::CheckedInt32;
|
||||
|
@ -446,23 +446,18 @@ void nsBuiltinDecoder::MetadataLoaded(PRUint32 aChannels,
|
||||
return;
|
||||
}
|
||||
|
||||
// Only inform the element of MetadataLoaded if not doing a load() in order
|
||||
// to fulfill a seek, otherwise we'll get multiple metadataloaded events.
|
||||
bool notifyElement = true;
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
mDuration = mDecoderStateMachine ? mDecoderStateMachine->GetDuration() : -1;
|
||||
// Duration has changed so we should recompute playback rate
|
||||
UpdatePlaybackRate();
|
||||
|
||||
notifyElement = mNextState != PLAY_STATE_SEEKING;
|
||||
}
|
||||
|
||||
if (mDuration == -1) {
|
||||
SetInfinite(true);
|
||||
}
|
||||
|
||||
if (mElement && notifyElement) {
|
||||
if (mElement) {
|
||||
// Make sure the element and the frame (if any) are told about
|
||||
// our new size.
|
||||
Invalidate();
|
||||
@ -482,7 +477,7 @@ void nsBuiltinDecoder::MetadataLoaded(PRUint32 aChannels,
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
bool resourceIsLoaded = !mResourceLoaded && mResource &&
|
||||
mResource->IsDataCachedToEndOfResource(mDecoderPosition);
|
||||
if (mElement && notifyElement) {
|
||||
if (mElement) {
|
||||
mElement->FirstFrameLoaded(resourceIsLoaded);
|
||||
}
|
||||
|
||||
@ -567,11 +562,13 @@ void nsBuiltinDecoder::DecodeError()
|
||||
|
||||
bool nsBuiltinDecoder::IsSeeking() const
|
||||
{
|
||||
return mPlayState == PLAY_STATE_SEEKING || mNextState == PLAY_STATE_SEEKING;
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
||||
return mPlayState == PLAY_STATE_SEEKING;
|
||||
}
|
||||
|
||||
bool nsBuiltinDecoder::IsEnded() const
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
||||
return mPlayState == PLAY_STATE_ENDED || mPlayState == PLAY_STATE_SHUTDOWN;
|
||||
}
|
||||
|
||||
@ -580,6 +577,7 @@ void nsBuiltinDecoder::PlaybackEnded()
|
||||
if (mShuttingDown || mPlayState == nsBuiltinDecoder::PLAY_STATE_SEEKING)
|
||||
return;
|
||||
|
||||
printf("nsBuiltinDecoder::PlaybackEnded mPlayState=%d\n", mPlayState);
|
||||
PlaybackPositionChanged();
|
||||
ChangeState(PLAY_STATE_ENDED);
|
||||
|
||||
@ -794,6 +792,7 @@ void nsBuiltinDecoder::SeekingStopped()
|
||||
seekWasAborted = true;
|
||||
} else {
|
||||
UnpinForSeek();
|
||||
printf("nsBuiltinDecoder::SeekingStopped, next state=%d\n", mNextState);
|
||||
ChangeState(mNextState);
|
||||
}
|
||||
}
|
||||
@ -827,6 +826,7 @@ void nsBuiltinDecoder::SeekingStoppedAtEnd()
|
||||
seekWasAborted = true;
|
||||
} else {
|
||||
UnpinForSeek();
|
||||
printf("nsBuiltinDecoder::SeekingStoppedAtEnd, next state=PLAY_STATE_ENDED\n");
|
||||
fireEnded = true;
|
||||
ChangeState(PLAY_STATE_ENDED);
|
||||
}
|
||||
@ -909,6 +909,9 @@ void nsBuiltinDecoder::PlaybackPositionChanged()
|
||||
// current time after the seek has started but before it has
|
||||
// completed.
|
||||
mCurrentTime = mDecoderStateMachine->GetCurrentTime();
|
||||
} else {
|
||||
printf("Suppressed timeupdate during seeking: currentTime=%f, new time=%f\n",
|
||||
mCurrentTime, mDecoderStateMachine->GetCurrentTime());
|
||||
}
|
||||
mDecoderStateMachine->ClearPositionChangeFlag();
|
||||
}
|
||||
|
@ -470,8 +470,8 @@ public:
|
||||
// Call on the main thread only.
|
||||
virtual void NetworkError();
|
||||
|
||||
// Call from any thread safely. Return true if we are currently
|
||||
// seeking in the media resource.
|
||||
// Return true if we are currently seeking in the media resource.
|
||||
// Call on the main thread only.
|
||||
virtual bool IsSeeking() const;
|
||||
|
||||
// Return true if the decoder has reached the end of playback.
|
||||
@ -742,17 +742,21 @@ public:
|
||||
// Data about MediaStreams that are being fed by this decoder.
|
||||
nsTArray<OutputMediaStream> mOutputStreams;
|
||||
|
||||
// Set to one of the valid play states. It is protected by the
|
||||
// monitor mReentrantMonitor. This monitor must be acquired when reading or
|
||||
// writing the state. Any change to the state on the main thread
|
||||
// must call NotifyAll on the monitor so the decode thread can wake up.
|
||||
// Set to one of the valid play states.
|
||||
// This can only be changed on the main thread while holding the decoder
|
||||
// monitor. Thus, it can be safely read while holding the decoder monitor
|
||||
// OR on the main thread.
|
||||
// Any change to the state on the main thread must call NotifyAll on the
|
||||
// monitor so the decode thread can wake up.
|
||||
PlayState mPlayState;
|
||||
|
||||
// The state to change to after a seek or load operation. It must only
|
||||
// be changed from the main thread. The decoder monitor must be acquired
|
||||
// when writing to the state, or when reading from a non-main thread.
|
||||
// The state to change to after a seek or load operation.
|
||||
// This can only be changed on the main thread while holding the decoder
|
||||
// monitor. Thus, it can be safely read while holding the decoder monitor
|
||||
// OR on the main thread.
|
||||
// Any change to the state must call NotifyAll on the monitor.
|
||||
PlayState mNextState;
|
||||
// This can only be PLAY_STATE_PAUSED or PLAY_STATE_PLAYING.
|
||||
PlayState mNextState;
|
||||
|
||||
// True when we have fully loaded the resource and reported that
|
||||
// to the element (i.e. reached NETWORK_LOADED state).
|
||||
|
@ -164,8 +164,8 @@ VideoData* VideoData::Create(nsVideoInfo& aInfo,
|
||||
// the frame we've been supplied without indexing out of bounds.
|
||||
CheckedUint32 xLimit = aPicture.x + CheckedUint32(aPicture.width);
|
||||
CheckedUint32 yLimit = aPicture.y + CheckedUint32(aPicture.height);
|
||||
if (!xLimit.valid() || xLimit.value() > aBuffer.mPlanes[0].mStride ||
|
||||
!yLimit.valid() || yLimit.value() > aBuffer.mPlanes[0].mHeight)
|
||||
if (!xLimit.isValid() || xLimit.value() > aBuffer.mPlanes[0].mStride ||
|
||||
!yLimit.isValid() || yLimit.value() > aBuffer.mPlanes[0].mHeight)
|
||||
{
|
||||
// The specified picture dimensions can't be contained inside the video
|
||||
// frame, we'll stomp memory if we try to copy it. Fail.
|
||||
@ -346,7 +346,7 @@ nsresult nsBuiltinDecoderReader::DecodeToTarget(PRInt64 aTarget)
|
||||
break;
|
||||
CheckedInt64 startFrame = UsecsToFrames(audio->mTime, mInfo.mAudioRate);
|
||||
CheckedInt64 targetFrame = UsecsToFrames(aTarget, mInfo.mAudioRate);
|
||||
if (!startFrame.valid() || !targetFrame.valid()) {
|
||||
if (!startFrame.isValid() || !targetFrame.isValid()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (startFrame.value() + audio->mFrames <= targetFrame.value()) {
|
||||
@ -390,7 +390,7 @@ nsresult nsBuiltinDecoderReader::DecodeToTarget(PRInt64 aTarget)
|
||||
audio->mAudioData.get() + (framesToPrune * channels),
|
||||
frames * channels * sizeof(AudioDataValue));
|
||||
CheckedInt64 duration = FramesToUsecs(frames, mInfo.mAudioRate);
|
||||
if (!duration.valid()) {
|
||||
if (!duration.isValid()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
nsAutoPtr<AudioData> data(new AudioData(audio->mOffset,
|
||||
|
@ -547,7 +547,7 @@ void nsBuiltinDecoderStateMachine::SendOutputStreamAudio(AudioData* aAudio,
|
||||
CheckedInt64 audioWrittenOffset = UsecsToFrames(mInfo.mAudioRate,
|
||||
aStream->mAudioFramesWrittenBaseTime + mStartTime) + aStream->mAudioFramesWritten;
|
||||
CheckedInt64 frameOffset = UsecsToFrames(mInfo.mAudioRate, aAudio->mTime);
|
||||
if (!audioWrittenOffset.valid() || !frameOffset.valid())
|
||||
if (!audioWrittenOffset.isValid() || !frameOffset.isValid())
|
||||
return;
|
||||
if (audioWrittenOffset.value() < frameOffset.value()) {
|
||||
// Write silence to catch up
|
||||
@ -1115,7 +1115,7 @@ void nsBuiltinDecoderStateMachine::AudioLoop()
|
||||
// samples.
|
||||
CheckedInt64 sampleTime = UsecsToFrames(s->mTime, rate);
|
||||
CheckedInt64 missingFrames = sampleTime - playedFrames;
|
||||
if (!missingFrames.valid() || !sampleTime.valid()) {
|
||||
if (!missingFrames.isValid() || !sampleTime.isValid()) {
|
||||
NS_WARNING("Int overflow adding in AudioLoop()");
|
||||
break;
|
||||
}
|
||||
@ -1139,7 +1139,7 @@ void nsBuiltinDecoderStateMachine::AudioLoop()
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
CheckedInt64 playedUsecs = FramesToUsecs(audioDuration, rate) + audioStartTime;
|
||||
if (!playedUsecs.valid()) {
|
||||
if (!playedUsecs.isValid()) {
|
||||
NS_WARNING("Int overflow calculating audio end time");
|
||||
break;
|
||||
}
|
||||
@ -2198,6 +2198,7 @@ nsresult nsBuiltinDecoderStateMachine::RunStateMachine()
|
||||
PRInt64 videoTime = HasVideo() ? mVideoFrameEndTime : 0;
|
||||
PRInt64 clockTime = NS_MAX(mEndTime, NS_MAX(videoTime, GetAudioClock()));
|
||||
UpdatePlaybackPosition(clockTime);
|
||||
printf("nsBuiltinDecoderStateMachine::RunStateMachine queuing nsBuiltinDecoder::PlaybackEnded\n");
|
||||
nsCOMPtr<nsIRunnable> event =
|
||||
NS_NewRunnableMethod(mDecoder, &nsBuiltinDecoder::PlaybackEnded);
|
||||
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
|
||||
|
@ -353,10 +353,10 @@ PRInt64 nsTheoraState::Time(th_info* aInfo, PRInt64 aGranulepos)
|
||||
ogg_int64_t pframe = aGranulepos - (iframe << shift);
|
||||
PRInt64 frameno = iframe + pframe - TH_VERSION_CHECK(aInfo, 3, 2, 1);
|
||||
CheckedInt64 t = ((CheckedInt64(frameno) + 1) * USECS_PER_S) * aInfo->fps_denominator;
|
||||
if (!t.valid())
|
||||
if (!t.isValid())
|
||||
return -1;
|
||||
t /= aInfo->fps_numerator;
|
||||
return t.valid() ? t.value() : -1;
|
||||
return t.isValid() ? t.value() : -1;
|
||||
}
|
||||
|
||||
PRInt64 nsTheoraState::StartTime(PRInt64 granulepos) {
|
||||
@ -364,7 +364,7 @@ PRInt64 nsTheoraState::StartTime(PRInt64 granulepos) {
|
||||
return -1;
|
||||
}
|
||||
CheckedInt64 t = (CheckedInt64(th_granule_frame(mCtx, granulepos)) * USECS_PER_S) * mInfo.fps_denominator;
|
||||
if (!t.valid())
|
||||
if (!t.isValid())
|
||||
return -1;
|
||||
return t.value() / mInfo.fps_numerator;
|
||||
}
|
||||
@ -622,7 +622,7 @@ PRInt64 nsVorbisState::Time(vorbis_info* aInfo, PRInt64 aGranulepos)
|
||||
return -1;
|
||||
}
|
||||
CheckedInt64 t = CheckedInt64(aGranulepos) * USECS_PER_S;
|
||||
if (!t.valid())
|
||||
if (!t.isValid())
|
||||
t = 0;
|
||||
return t.value() / aInfo->rate;
|
||||
}
|
||||
@ -884,7 +884,7 @@ PRInt64 nsOpusState::Time(PRInt64 granulepos)
|
||||
|
||||
// Ogg Opus always runs at a granule rate of 48 kHz.
|
||||
CheckedInt64 t = CheckedInt64(granulepos - mPreSkip) * USECS_PER_S;
|
||||
return t.valid() ? t.value() / mRate : -1;
|
||||
return t.isValid() ? t.value() / mRate : -1;
|
||||
}
|
||||
|
||||
bool nsOpusState::IsHeader(ogg_packet* aPacket)
|
||||
@ -1048,7 +1048,7 @@ bool nsSkeletonState::DecodeIndex(ogg_packet* aPacket)
|
||||
|
||||
// Extract the start time.
|
||||
CheckedInt64 t = CheckedInt64(LEInt64(p + INDEX_FIRST_NUMER_OFFSET)) * USECS_PER_S;
|
||||
if (!t.valid()) {
|
||||
if (!t.isValid()) {
|
||||
return (mActive = false);
|
||||
} else {
|
||||
startTime = t.value() / timeDenom;
|
||||
@ -1056,7 +1056,7 @@ bool nsSkeletonState::DecodeIndex(ogg_packet* aPacket)
|
||||
|
||||
// Extract the end time.
|
||||
t = LEInt64(p + INDEX_LAST_NUMER_OFFSET) * USECS_PER_S;
|
||||
if (!t.valid()) {
|
||||
if (!t.isValid()) {
|
||||
return (mActive = false);
|
||||
} else {
|
||||
endTime = t.value() / timeDenom;
|
||||
@ -1065,7 +1065,7 @@ bool nsSkeletonState::DecodeIndex(ogg_packet* aPacket)
|
||||
// Check the numKeyPoints value read, ensure we're not going to run out of
|
||||
// memory while trying to decode the index packet.
|
||||
CheckedInt64 minPacketSize = (CheckedInt64(numKeyPoints) * MIN_KEY_POINT_SIZE) + INDEX_KEYPOINT_OFFSET;
|
||||
if (!minPacketSize.valid())
|
||||
if (!minPacketSize.isValid())
|
||||
{
|
||||
return (mActive = false);
|
||||
}
|
||||
@ -1103,7 +1103,7 @@ bool nsSkeletonState::DecodeIndex(ogg_packet* aPacket)
|
||||
p = ReadVariableLengthInt(p, limit, delta);
|
||||
offset += delta;
|
||||
if (p == limit ||
|
||||
!offset.valid() ||
|
||||
!offset.isValid() ||
|
||||
offset.value() > mLength ||
|
||||
offset.value() < 0)
|
||||
{
|
||||
@ -1111,14 +1111,14 @@ bool nsSkeletonState::DecodeIndex(ogg_packet* aPacket)
|
||||
}
|
||||
p = ReadVariableLengthInt(p, limit, delta);
|
||||
time += delta;
|
||||
if (!time.valid() ||
|
||||
if (!time.isValid() ||
|
||||
time.value() > endTime ||
|
||||
time.value() < startTime)
|
||||
{
|
||||
return (mActive = false);
|
||||
}
|
||||
CheckedInt64 timeUsecs = time * USECS_PER_S;
|
||||
if (!timeUsecs.valid())
|
||||
if (!timeUsecs.isValid())
|
||||
return mActive = false;
|
||||
timeUsecs /= timeDenom;
|
||||
keyPoints->Add(offset.value(), timeUsecs.value());
|
||||
@ -1228,8 +1228,8 @@ nsresult nsSkeletonState::GetDuration(const nsTArray<PRUint32>& aTracks,
|
||||
}
|
||||
NS_ASSERTION(endTime > startTime, "Duration must be positive");
|
||||
CheckedInt64 duration = CheckedInt64(endTime) - startTime;
|
||||
aDuration = duration.valid() ? duration.value() : 0;
|
||||
return duration.valid() ? NS_OK : NS_ERROR_FAILURE;
|
||||
aDuration = duration.isValid() ? duration.value() : 0;
|
||||
return duration.isValid() ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
bool nsSkeletonState::DecodeHeader(ogg_packet* aPacket)
|
||||
|
@ -87,7 +87,7 @@ nsresult nsRawReader::ReadMetadata(nsVideoInfo* aInfo)
|
||||
|
||||
CheckedUint32 dummy = CheckedUint32(static_cast<PRUint32>(mMetadata.frameWidth)) *
|
||||
static_cast<PRUint32>(mMetadata.frameHeight);
|
||||
NS_ENSURE_TRUE(dummy.valid(), NS_ERROR_FAILURE);
|
||||
NS_ENSURE_TRUE(dummy.isValid(), NS_ERROR_FAILURE);
|
||||
|
||||
if (mMetadata.aspectDenominator == 0 ||
|
||||
mMetadata.framerateDenominator == 0)
|
||||
@ -268,7 +268,7 @@ nsresult nsRawReader::Seek(PRInt64 aTime, PRInt64 aStartTime, PRInt64 aEndTime,
|
||||
|
||||
CheckedUint32 offset = CheckedUint32(mCurrentFrame) * mFrameSize;
|
||||
offset += sizeof(nsRawVideoHeader);
|
||||
NS_ENSURE_TRUE(offset.valid(), NS_ERROR_FAILURE);
|
||||
NS_ENSURE_TRUE(offset.isValid(), NS_ERROR_FAILURE);
|
||||
|
||||
nsresult rv = resource->Seek(nsISeekableStream::NS_SEEK_SET, offset.value());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -161,6 +161,7 @@ _TEST_FILES = \
|
||||
use_large_cache.js \
|
||||
test_audiowrite.html \
|
||||
test_mozHasAudio.html \
|
||||
test_source_media.html \
|
||||
$(NULL)
|
||||
|
||||
# Don't run in suite
|
||||
|
58
content/media/test/test_source_media.html
Normal file
@ -0,0 +1,58 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Media test: media attribute for the source element.</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
<script type="text/javascript" src="manifest.js"></script>
|
||||
<script type="text/javascript" src="../../html/content/test/reflect.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script type="text/javascript">
|
||||
var testCount = 0;
|
||||
function notifyFinished() {
|
||||
testCount++;
|
||||
if (testCount == 2) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
reflectString({
|
||||
element: document.createElement("source"),
|
||||
attribute: "media",
|
||||
});
|
||||
|
||||
var media = getPlayableVideo(gSmallTests);
|
||||
|
||||
if (media == null) {
|
||||
todo(false, "No media supported.");
|
||||
SimpleTest.finish();
|
||||
} else {
|
||||
var v = document.createElement('video');
|
||||
v.innerHTML = "<source src=\"" + media.name + "?fail\" media=\"not all\">" +
|
||||
"<source src=\""+ media.name + "?pass\" media=\"all\">";
|
||||
var v2 = document.createElement("video");
|
||||
v2.innerHTML = "<source src=\""+ media.name +"?pass\">" +
|
||||
"<source src=\""+ media.name + "?fail\" media=\"all\">";
|
||||
document.body.appendChild(v);
|
||||
document.body.appendChild(v2);
|
||||
|
||||
v.addEventListener("loadedmetadata", function(e) {
|
||||
ok(/pass/.test(e.target.currentSrc),
|
||||
"The source has been chosen according to the media attribute.");
|
||||
notifyFinished();
|
||||
});
|
||||
v2.addEventListener("loadedmetadata", function(e) {
|
||||
ok(/pass/.test(e.target.currentSrc),
|
||||
"If no media attribute is specified, it defaults to \'all\'.")
|
||||
notifyFinished();
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -209,10 +209,8 @@ void nsWebMBufferedParser::Append(const unsigned char* aBuffer, PRUint32 aLength
|
||||
mCurrentOffset += aLength;
|
||||
}
|
||||
|
||||
void nsWebMBufferedState::CalculateBufferedForRange(nsTimeRanges* aBuffered,
|
||||
PRInt64 aStartOffset, PRInt64 aEndOffset,
|
||||
PRUint64 aTimecodeScale,
|
||||
PRInt64 aStartTimeOffsetNS)
|
||||
bool nsWebMBufferedState::CalculateBufferedForRange(PRInt64 aStartOffset, PRInt64 aEndOffset,
|
||||
PRUint64* aStartTime, PRUint64* aEndTime)
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
|
||||
@ -220,7 +218,7 @@ void nsWebMBufferedState::CalculateBufferedForRange(nsTimeRanges* aBuffered,
|
||||
PRUint32 start;
|
||||
mTimeMapping.GreatestIndexLtEq(aStartOffset, start);
|
||||
if (start == mTimeMapping.Length()) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find the first nsWebMTimeDataOffset at or before aEndOffset.
|
||||
@ -233,7 +231,7 @@ void nsWebMBufferedState::CalculateBufferedForRange(nsTimeRanges* aBuffered,
|
||||
|
||||
// Range is empty.
|
||||
if (end <= start) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
NS_ASSERTION(mTimeMapping[start].mOffset >= aStartOffset &&
|
||||
@ -252,9 +250,9 @@ void nsWebMBufferedState::CalculateBufferedForRange(nsTimeRanges* aBuffered,
|
||||
// from the ranges' start and end timestamps, so that those timestamps are
|
||||
// normalized in the range [0,duration].
|
||||
|
||||
double startTime = (mTimeMapping[start].mTimecode * aTimecodeScale - aStartTimeOffsetNS) / NS_PER_S;
|
||||
double endTime = (mTimeMapping[end].mTimecode * aTimecodeScale - aStartTimeOffsetNS) / NS_PER_S;
|
||||
aBuffered->Add(startTime, endTime);
|
||||
*aStartTime = mTimeMapping[start].mTimecode;
|
||||
*aEndTime = mTimeMapping[end].mTimecode;
|
||||
return true;
|
||||
}
|
||||
|
||||
void nsWebMBufferedState::NotifyDataArrived(const char* aBuffer, PRUint32 aLength, PRInt64 aOffset)
|
||||
|
@ -225,10 +225,8 @@ public:
|
||||
}
|
||||
|
||||
void NotifyDataArrived(const char* aBuffer, PRUint32 aLength, PRInt64 aOffset);
|
||||
void CalculateBufferedForRange(nsTimeRanges* aBuffered,
|
||||
PRInt64 aStartOffset, PRInt64 aEndOffset,
|
||||
PRUint64 aTimecodeScale,
|
||||
PRInt64 aStartTimeOffsetNS);
|
||||
bool CalculateBufferedForRange(PRInt64 aStartOffset, PRInt64 aEndOffset,
|
||||
PRUint64* aStartTime, PRUint64* aEndTime);
|
||||
|
||||
private:
|
||||
// Synchronizes access to the mTimeMapping array.
|
||||
|
@ -448,12 +448,12 @@ bool nsWebMReader::DecodeAudioPacket(nestegg_packet* aPacket, PRInt64 aOffset)
|
||||
// from after the gap.
|
||||
CheckedInt64 tstamp_frames = UsecsToFrames(tstamp_usecs, rate);
|
||||
CheckedInt64 decoded_frames = UsecsToFrames(mAudioStartUsec, rate);
|
||||
if (!tstamp_frames.valid() || !decoded_frames.valid()) {
|
||||
if (!tstamp_frames.isValid() || !decoded_frames.isValid()) {
|
||||
NS_WARNING("Int overflow converting WebM times to frames");
|
||||
return false;
|
||||
}
|
||||
decoded_frames += mAudioFrames;
|
||||
if (!decoded_frames.valid()) {
|
||||
if (!decoded_frames.isValid()) {
|
||||
NS_WARNING("Int overflow adding decoded_frames");
|
||||
return false;
|
||||
}
|
||||
@ -461,7 +461,7 @@ bool nsWebMReader::DecodeAudioPacket(nestegg_packet* aPacket, PRInt64 aOffset)
|
||||
#ifdef DEBUG
|
||||
CheckedInt64 usecs = FramesToUsecs(tstamp_frames.value() - decoded_frames.value(), rate);
|
||||
LOG(PR_LOG_DEBUG, ("WebMReader detected gap of %lld, %lld frames, in audio stream\n",
|
||||
usecs.valid() ? usecs.value(): -1,
|
||||
usecs.isValid() ? usecs.value() : -1,
|
||||
tstamp_frames.value() - decoded_frames.value()));
|
||||
#endif
|
||||
mPacketCount++;
|
||||
@ -501,18 +501,18 @@ bool nsWebMReader::DecodeAudioPacket(nestegg_packet* aPacket, PRInt64 aOffset)
|
||||
}
|
||||
|
||||
CheckedInt64 duration = FramesToUsecs(frames, rate);
|
||||
if (!duration.valid()) {
|
||||
if (!duration.isValid()) {
|
||||
NS_WARNING("Int overflow converting WebM audio duration");
|
||||
return false;
|
||||
}
|
||||
CheckedInt64 total_duration = FramesToUsecs(total_frames, rate);
|
||||
if (!total_duration.valid()) {
|
||||
if (!total_duration.isValid()) {
|
||||
NS_WARNING("Int overflow converting WebM audio total_duration");
|
||||
return false;
|
||||
}
|
||||
|
||||
CheckedInt64 time = total_duration + tstamp_usecs;
|
||||
if (!time.valid()) {
|
||||
if (!time.isValid()) {
|
||||
NS_WARNING("Int overflow adding total_duration and tstamp_usecs");
|
||||
nestegg_free_packet(aPacket);
|
||||
return false;
|
||||
@ -791,24 +791,45 @@ nsresult nsWebMReader::GetBuffered(nsTimeRanges* aBuffered, PRInt64 aStartTime)
|
||||
}
|
||||
|
||||
// Special case completely cached files. This also handles local files.
|
||||
if (resource->IsDataCachedToEndOfResource(0)) {
|
||||
bool isFullyCached = resource->IsDataCachedToEndOfResource(0);
|
||||
if (isFullyCached) {
|
||||
uint64_t duration = 0;
|
||||
if (nestegg_duration(mContext, &duration) == 0) {
|
||||
aBuffered->Add(0, duration / NS_PER_S);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
|
||||
PRUint32 bufferedLength = 0;
|
||||
aBuffered->GetLength(&bufferedLength);
|
||||
|
||||
// Either we the file is not fully cached, or we couldn't find a duration in
|
||||
// the WebM bitstream.
|
||||
if (!isFullyCached || !bufferedLength) {
|
||||
MediaResource* resource = mDecoder->GetResource();
|
||||
nsTArray<MediaByteRange> ranges;
|
||||
nsresult res = resource->GetCachedRanges(ranges);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
||||
PRInt64 startTimeOffsetNS = aStartTime * NS_PER_USEC;
|
||||
for (PRUint32 index = 0; index < ranges.Length(); index++) {
|
||||
mBufferedState->CalculateBufferedForRange(aBuffered,
|
||||
ranges[index].mStart,
|
||||
ranges[index].mEnd,
|
||||
timecodeScale,
|
||||
startTimeOffsetNS);
|
||||
PRUint64 start, end;
|
||||
bool rv = mBufferedState->CalculateBufferedForRange(ranges[index].mStart,
|
||||
ranges[index].mEnd,
|
||||
&start, &end);
|
||||
if (rv) {
|
||||
double startTime = start * timecodeScale / NS_PER_S - aStartTime;
|
||||
double endTime = end * timecodeScale / NS_PER_S - aStartTime;
|
||||
|
||||
// If this range extends to the end of the file, the true end time
|
||||
// is the file's duration.
|
||||
if (resource->IsDataCachedToEndOfResource(ranges[index].mStart)) {
|
||||
uint64_t duration = 0;
|
||||
if (nestegg_duration(mContext, &duration) == 0) {
|
||||
endTime = duration / NS_PER_S;
|
||||
}
|
||||
}
|
||||
|
||||
aBuffered->Add(startTime, endTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,17 +67,17 @@ BrowserElementParent.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
_observeInProcessBrowserFrameShown: function(frameLoader, data) {
|
||||
_observeInProcessBrowserFrameShown: function(frameLoader) {
|
||||
debug("In-process browser frame shown " + frameLoader);
|
||||
this._setUpMessageManagerListeners(frameLoader, data);
|
||||
this._setUpMessageManagerListeners(frameLoader);
|
||||
},
|
||||
|
||||
_observeRemoteBrowserFrameShown: function(frameLoader, data) {
|
||||
_observeRemoteBrowserFrameShown: function(frameLoader) {
|
||||
debug("Remote browser frame shown " + frameLoader);
|
||||
this._setUpMessageManagerListeners(frameLoader, data);
|
||||
this._setUpMessageManagerListeners(frameLoader);
|
||||
},
|
||||
|
||||
_setUpMessageManagerListeners: function(frameLoader, data) {
|
||||
_setUpMessageManagerListeners: function(frameLoader) {
|
||||
let frameElement = frameLoader.QueryInterface(Ci.nsIFrameLoader).ownerElement;
|
||||
if (!frameElement) {
|
||||
debug("No frame element?");
|
||||
@ -150,10 +150,10 @@ BrowserElementParent.prototype = {
|
||||
}
|
||||
break;
|
||||
case 'remote-browser-frame-shown':
|
||||
this._observeRemoteBrowserFrameShown(subject, data);
|
||||
this._observeRemoteBrowserFrameShown(subject);
|
||||
break;
|
||||
case 'in-process-browser-frame-shown':
|
||||
this._observeInProcessBrowserFrameShown(subject, data);
|
||||
this._observeInProcessBrowserFrameShown(subject);
|
||||
break;
|
||||
case 'content-document-global-created':
|
||||
this._observeContentGlobalCreated(subject);
|
||||
|
@ -5877,7 +5877,7 @@ DefineIDBInterfaceConstants(JSContext *cx, JSObject *obj, const nsIID *aIID)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class nsDOMConstructor : public nsIDOMDOMConstructor
|
||||
class nsDOMConstructor MOZ_FINAL : public nsIDOMDOMConstructor
|
||||
{
|
||||
protected:
|
||||
nsDOMConstructor(const PRUnichar* aName,
|
||||
|
@ -5328,12 +5328,7 @@ nsGlobalWindow::ScrollTo(PRInt32 aXScroll, PRInt32 aYScroll)
|
||||
if (aYScroll > maxpx) {
|
||||
aYScroll = maxpx;
|
||||
}
|
||||
nsPoint pt(nsPresContext::CSSPixelsToAppUnits(aXScroll),
|
||||
nsPresContext::CSSPixelsToAppUnits(aYScroll));
|
||||
nscoord halfPixel = nsPresContext::CSSPixelsToAppUnits(0.5f);
|
||||
// Don't allow pt.x/y + halfPixel since that would round up to the next CSS pixel.
|
||||
nsRect range(pt.x - halfPixel, pt.y - halfPixel, halfPixel*2 - 1, halfPixel*2 - 1);
|
||||
sf->ScrollTo(pt, nsIScrollableFrame::INSTANT, &range);
|
||||
sf->ScrollToCSSPixels(nsIntPoint(aXScroll, aYScroll));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -138,18 +138,25 @@ inline bool
|
||||
IsArrayLike(JSContext* cx, JSObject* obj)
|
||||
{
|
||||
MOZ_ASSERT(obj);
|
||||
// For simplicity, check for security wrappers up front
|
||||
// For simplicity, check for security wrappers up front. In case we
|
||||
// have a security wrapper, don't forget to enter the compartment of
|
||||
// the underlying object after unwrapping.
|
||||
JSAutoEnterCompartment ac;
|
||||
if (js::IsWrapper(obj)) {
|
||||
obj = XPCWrapper::Unwrap(cx, obj, false);
|
||||
if (!obj) {
|
||||
// Let's say it's not
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ac.enter(cx, obj)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// XXXbz need to detect platform objects (including listbinding
|
||||
// ones) with indexGetters here!
|
||||
return JS_IsArrayObject(cx, obj);
|
||||
return JS_IsArrayObject(cx, obj) || JS_IsTypedArrayObject(obj, cx);
|
||||
}
|
||||
|
||||
inline bool
|
||||
@ -582,6 +589,84 @@ ThrowingConstructor(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
JSBool
|
||||
ThrowingConstructorWorkers(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
|
||||
template<class T>
|
||||
class NonNull
|
||||
{
|
||||
public:
|
||||
NonNull()
|
||||
#ifdef DEBUG
|
||||
: inited(false)
|
||||
#endif
|
||||
{}
|
||||
|
||||
operator T&() {
|
||||
MOZ_ASSERT(inited);
|
||||
MOZ_ASSERT(ptr, "NonNull<T> was set to null");
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
void operator=(T* t) {
|
||||
ptr = t;
|
||||
MOZ_ASSERT(ptr);
|
||||
#ifdef DEBUG
|
||||
inited = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
T** Slot() {
|
||||
#ifdef DEBUG
|
||||
inited = true;
|
||||
#endif
|
||||
return &ptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
T* ptr;
|
||||
#ifdef DEBUG
|
||||
bool inited;
|
||||
#endif
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class OwningNonNull
|
||||
{
|
||||
public:
|
||||
OwningNonNull()
|
||||
#ifdef DEBUG
|
||||
: inited(false)
|
||||
#endif
|
||||
{}
|
||||
|
||||
operator T&() {
|
||||
MOZ_ASSERT(inited);
|
||||
MOZ_ASSERT(ptr, "OwningNonNull<T> was set to null");
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
void operator=(T* t) {
|
||||
init(t);
|
||||
}
|
||||
|
||||
void operator=(const already_AddRefed<T>& t) {
|
||||
init(t);
|
||||
}
|
||||
|
||||
protected:
|
||||
template<typename U>
|
||||
void init(U t) {
|
||||
ptr = t;
|
||||
MOZ_ASSERT(ptr);
|
||||
#ifdef DEBUG
|
||||
inited = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
nsRefPtr<T> ptr;
|
||||
#ifdef DEBUG
|
||||
bool inited;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -1115,12 +1115,12 @@ class CastableObjectUnwrapper():
|
||||
|
||||
def __str__(self):
|
||||
return string.Template(
|
||||
""" {
|
||||
nsresult rv = UnwrapObject<${protoID}>(cx, ${source}, &${target});
|
||||
if (NS_FAILED(rv)) {
|
||||
${codeOnFailure}
|
||||
}
|
||||
}""").substitute(self.substitution)
|
||||
"""{
|
||||
nsresult rv = UnwrapObject<${protoID}>(cx, ${source}, ${target});
|
||||
if (NS_FAILED(rv)) {
|
||||
${codeOnFailure}
|
||||
}
|
||||
}""").substitute(self.substitution)
|
||||
|
||||
class FailureFatalCastableObjectUnwrapper(CastableObjectUnwrapper):
|
||||
"""
|
||||
@ -1150,128 +1150,300 @@ class CallbackObjectUnwrapper:
|
||||
|
||||
def __str__(self):
|
||||
if self.descriptor.workers:
|
||||
return string.Template("""
|
||||
${target} = ${source};""").substitute(self.substitution)
|
||||
return string.Template(
|
||||
"${target} = ${source};"
|
||||
).substitute(self.substitution)
|
||||
|
||||
return string.Template("""
|
||||
nsresult rv;
|
||||
XPCCallContext ccx(JS_CALLER, cx);
|
||||
if (!ccx.IsValid()) {
|
||||
rv = NS_ERROR_XPC_BAD_CONVERT_JS;
|
||||
${codeOnFailure}
|
||||
}
|
||||
return string.Template(
|
||||
"""nsresult rv;
|
||||
XPCCallContext ccx(JS_CALLER, cx);
|
||||
if (!ccx.IsValid()) {
|
||||
rv = NS_ERROR_XPC_BAD_CONVERT_JS;
|
||||
${codeOnFailure}
|
||||
}
|
||||
|
||||
const nsIID& iid = NS_GET_IID(${nativeType});
|
||||
nsRefPtr<nsXPCWrappedJS> wrappedJS;
|
||||
rv = nsXPCWrappedJS::GetNewOrUsed(ccx, ${source}, iid,
|
||||
NULL, getter_AddRefs(wrappedJS));
|
||||
if (NS_FAILED(rv) || !wrappedJS) {
|
||||
${codeOnFailure}
|
||||
}
|
||||
const nsIID& iid = NS_GET_IID(${nativeType});
|
||||
nsRefPtr<nsXPCWrappedJS> wrappedJS;
|
||||
rv = nsXPCWrappedJS::GetNewOrUsed(ccx, ${source}, iid,
|
||||
NULL, getter_AddRefs(wrappedJS));
|
||||
if (NS_FAILED(rv) || !wrappedJS) {
|
||||
${codeOnFailure}
|
||||
}
|
||||
|
||||
${target} = do_QueryObject(wrappedJS.get());
|
||||
if (!${target}) {
|
||||
${codeOnFailure}
|
||||
}""").substitute(self.substitution)
|
||||
// Use a temp nsCOMPtr for the null-check, because ${target} might be
|
||||
// OwningNonNull, not an nsCOMPtr.
|
||||
nsCOMPtr<${nativeType}> tmp = do_QueryObject(wrappedJS.get());
|
||||
if (!tmp) {
|
||||
${codeOnFailure}
|
||||
}
|
||||
${target} = tmp.forget();""").substitute(self.substitution)
|
||||
|
||||
def getArgumentConversionTemplate(type, descriptor):
|
||||
if type.isSequence() or type.isArray():
|
||||
raise TypeError("Can't handle sequence or array arguments yet")
|
||||
def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
|
||||
isDefinitelyObject=False,
|
||||
isSequenceMember=False):
|
||||
"""
|
||||
Get a template for converting a JS value to a native object based on the
|
||||
given type and descriptor. If failureCode is given, then we're actually
|
||||
testing whether we can convert the argument to the desired type. That
|
||||
means that failures to convert due to the JS value being the wrong type of
|
||||
value need to use failureCode instead of throwing exceptions. Failures to
|
||||
convert that are due to JS exceptions (from toString or valueOf methods) or
|
||||
out of memory conditions need to throw exceptions no matter what
|
||||
failureCode is.
|
||||
|
||||
if descriptor is not None:
|
||||
assert(type.isInterface())
|
||||
If isDefinitelyObject is True, that means we know the value
|
||||
isObject() and we have no need to recheck that.
|
||||
|
||||
The return value from this function is a tuple consisting of three things:
|
||||
|
||||
1) A string representing the conversion code. This will have template
|
||||
substitution performed on it as follows:
|
||||
|
||||
${val} replaced by an expression for the JS::Value in question
|
||||
${valPtr} is a pointer to the JS::Value in question
|
||||
${holderName} replaced by the holder's name, if any
|
||||
${declName} replaced by the declaration's name
|
||||
|
||||
2) A CGThing representing the native C++ type we're converting to
|
||||
(declType). This is allowed to be None if the conversion code is
|
||||
supposed to be used as-is.
|
||||
3) A CGThing representing the type of a "holder" (holderType) which will
|
||||
hold a possible reference to the C++ thing whose type we returned in #1,
|
||||
or None if no such holder is needed.
|
||||
|
||||
${declName} must be in scope before the generated code is entered.
|
||||
|
||||
If holderType is not None then ${holderName} must be in scope
|
||||
before the generated code is entered.
|
||||
"""
|
||||
|
||||
# A helper function for wrapping up the template body for
|
||||
# possibly-nullable objecty stuff
|
||||
def wrapObjectTemplate(templateBody, isDefinitelyObject, type,
|
||||
codeToSetNull, isWorker):
|
||||
if not isDefinitelyObject:
|
||||
# Handle the non-object cases by wrapping up the whole
|
||||
# thing in an if cascade.
|
||||
templateBody = (
|
||||
"if (${val}.isObject()) {\n" +
|
||||
CGIndenter(CGGeneric(templateBody)).define() + "\n")
|
||||
if type.nullable():
|
||||
templateBody += (
|
||||
"} else if (${val}.isNullOrUndefined()) {\n"
|
||||
" %s;\n" % codeToSetNull)
|
||||
templateBody += (
|
||||
"} else {\n"
|
||||
" return Throw<%s>(cx, NS_ERROR_XPC_BAD_CONVERT_JS);\n"
|
||||
"}" % toStringBool(not isWorker))
|
||||
return templateBody
|
||||
|
||||
if type.isArray():
|
||||
raise TypeError("Can't handle array arguments yet")
|
||||
|
||||
if type.isSequence():
|
||||
if isSequenceMember:
|
||||
raise TypeError("Can't handle sequences of sequences")
|
||||
if failureCode is not None:
|
||||
raise TypeError("Can't handle sequences when failureCode is not None")
|
||||
nullable = type.nullable();
|
||||
if nullable:
|
||||
type = type.inner;
|
||||
|
||||
elementType = type.inner;
|
||||
# We don't know anything about the object-ness of the things
|
||||
# we wrap, so don't pass through isDefinitelyObject
|
||||
(elementTemplate, elementDeclType,
|
||||
elementHolderType) = getJSToNativeConversionTemplate(
|
||||
elementType, descriptorProvider, isSequenceMember=True)
|
||||
if elementHolderType is not None:
|
||||
raise TypeError("Shouldn't need holders for sequences")
|
||||
|
||||
# Have to make sure to use a fallible array, because it's trivial for
|
||||
# page JS to create things with very large lengths.
|
||||
typeName = CGWrapper(elementDeclType, pre="nsTArray< ", post=" >")
|
||||
if nullable:
|
||||
typeName = CGWrapper(typeName, pre="Nullable< ", post=" >")
|
||||
templateBody = ("""JSObject* seq = &${val}.toObject();\n
|
||||
if (!IsArrayLike(cx, seq)) {
|
||||
return Throw<%s>(cx, NS_ERROR_XPC_BAD_CONVERT_JS);
|
||||
}
|
||||
uint32_t length;
|
||||
// JS_GetArrayLength actually works on all objects
|
||||
if (!JS_GetArrayLength(cx, seq, &length)) {
|
||||
return false;
|
||||
}
|
||||
// Jump through a hoop to do a fallible allocation but later end up with
|
||||
// an infallible array.
|
||||
FallibleTArray< %s > arr;
|
||||
if (!arr.SetCapacity(length)) {
|
||||
return Throw<%s>(cx, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
jsval temp;
|
||||
if (!JS_GetElement(cx, seq, i, &temp)) {
|
||||
return false;
|
||||
}
|
||||
""" % (toStringBool(descriptorProvider.workers),
|
||||
elementDeclType.define(),
|
||||
toStringBool(descriptorProvider.workers)))
|
||||
|
||||
templateBody += CGIndenter(CGGeneric(
|
||||
string.Template(elementTemplate).substitute(
|
||||
{
|
||||
"val" : "temp",
|
||||
"declName" : "*arr.AppendElement()"
|
||||
}
|
||||
))).define()
|
||||
|
||||
templateBody += """
|
||||
}
|
||||
// And the other half of the hoop-jump"""
|
||||
if nullable:
|
||||
templateBody += """
|
||||
${declName}.SetValue().SwapElements(arr);
|
||||
"""
|
||||
else:
|
||||
templateBody += """
|
||||
${declName}.SwapElements(arr);
|
||||
"""
|
||||
templateBody = wrapObjectTemplate(templateBody, isDefinitelyObject,
|
||||
type, "${declName}.SetNull()",
|
||||
descriptorProvider.workers)
|
||||
return (templateBody, typeName, None)
|
||||
|
||||
if type.isInterface() and not type.isArrayBuffer():
|
||||
descriptor = descriptorProvider.getDescriptor(
|
||||
type.unroll().inner.identifier.name)
|
||||
# This is an interface that we implement as a concrete class
|
||||
# or an XPCOM interface.
|
||||
|
||||
# Allow null pointers for nullable types and old-binding classes
|
||||
argIsPointer = type.nullable() or type.unroll().inner.isExternal()
|
||||
|
||||
# Sequences and non-worker callbacks have to hold a strong ref to the
|
||||
# thing being passed down.
|
||||
forceOwningType = (descriptor.interface.isCallback() and
|
||||
not descriptor.workers) or isSequenceMember
|
||||
|
||||
typeName = descriptor.nativeType
|
||||
typePtr = typeName + "*"
|
||||
|
||||
# Compute a few things:
|
||||
# - declType is the type we want to return as the first element of our
|
||||
# tuple.
|
||||
# - holderType is the type we want to return as the third element
|
||||
# of our tuple.
|
||||
# - declInit is the initializer expression for our decl, if any.
|
||||
# - target is where a pointer to the object is being stored
|
||||
|
||||
# Set up some sensible defaults for these things insofar as we can.
|
||||
holderType = None
|
||||
if argIsPointer:
|
||||
nameSuffix = ""
|
||||
if forceOwningType:
|
||||
declType = "nsRefPtr<" + typeName + ">"
|
||||
else:
|
||||
declType = typePtr
|
||||
target = "&${declName}"
|
||||
else:
|
||||
nameSuffix = "_ptr"
|
||||
if forceOwningType:
|
||||
declType = "OwningNonNull<" + typeName + ">"
|
||||
else:
|
||||
declType = "NonNull<" + typeName + ">"
|
||||
target = "${declName}.Slot()"
|
||||
|
||||
# If we're going to QI, we want an nsCOMPtr. But note that XPConnect
|
||||
# unwrapping may or may not QI, and we don't know whether it will. So
|
||||
# we use a raw pointer for the isExternal() case, and if a ref is needed
|
||||
# it'll be handled by the xpc_qsSelfRef we put on the stack later.
|
||||
if descriptor.castable or type.unroll().inner.isExternal() or descriptor.workers:
|
||||
declType = " ${typeName}*"
|
||||
else:
|
||||
declType = " nsCOMPtr<${typeName}>"
|
||||
template = declType + " ${name}%s;\n" % nameSuffix
|
||||
|
||||
# We have to be very careful here to put anything that might need to
|
||||
# hold references across the C++ call in |template| and not
|
||||
# |templateBody|, since things in |templateBody| will go out of scope
|
||||
# before the call happens.
|
||||
templateBody = " if (${argVal}.isObject()) {"
|
||||
templateBody = ""
|
||||
if descriptor.castable:
|
||||
templateBody += str(FailureFatalCastableObjectUnwrapper(
|
||||
descriptor,
|
||||
"&${argVal}.toObject()",
|
||||
"${name}"+nameSuffix)).replace("\n", "\n ") + "\n"
|
||||
if failureCode is not None:
|
||||
templateBody += str(CastableObjectUnwrapper(
|
||||
descriptor,
|
||||
"&${val}.toObject()",
|
||||
target,
|
||||
failureCode))
|
||||
else:
|
||||
templateBody += str(FailureFatalCastableObjectUnwrapper(
|
||||
descriptor,
|
||||
"&${val}.toObject()",
|
||||
target))
|
||||
elif descriptor.interface.isCallback():
|
||||
templateBody += str(CallbackObjectUnwrapper(
|
||||
descriptor,
|
||||
"&${argVal}.toObject()",
|
||||
"${name}"+nameSuffix)) + "\n"
|
||||
"&${val}.toObject()",
|
||||
"${declName}",
|
||||
codeOnFailure=failureCode))
|
||||
elif descriptor.workers:
|
||||
templateBody += """
|
||||
${name}%s = &${argVal}.toObject();
|
||||
MOZ_ASSERT(${name}%s);
|
||||
""" % (nameSuffix, nameSuffix)
|
||||
templateBody += "${declName} = &${val}.toObject();"
|
||||
else:
|
||||
template += " xpc_qsSelfRef tmpRef_${name};\n"
|
||||
template += " jsval tmpVal_${name} = ${argVal};\n"
|
||||
templateBody += """
|
||||
${typeName}* tmp;
|
||||
if (NS_FAILED(xpc_qsUnwrapArg<${typeName}>(cx, ${argVal}, &tmp, &tmpRef_${name}.ptr,
|
||||
&tmpVal_${name}))) {
|
||||
return Throw<%s>(cx, NS_ERROR_XPC_BAD_CONVERT_JS);
|
||||
}
|
||||
MOZ_ASSERT(tmp);
|
||||
${name}%s = tmp;
|
||||
""" % (toStringBool(not descriptor.workers), nameSuffix)
|
||||
|
||||
if type.nullable():
|
||||
# Either external, or new-binding non-castable. We always have a
|
||||
# holder for these, because we don't actually know whether we have
|
||||
# to addref when unwrapping or not. So we just pass an
|
||||
# getter_AddRefs(nsCOMPtr) to XPConnect and if we'll need a release
|
||||
# it'll put a non-null pointer in there.
|
||||
if forceOwningType:
|
||||
# Don't return a holderType in this case; our declName
|
||||
# will just own stuff.
|
||||
templateBody += "nsCOMPtr<" + typeName + "> ${holderName};"
|
||||
else:
|
||||
holderType = "nsCOMPtr<" + typeName + ">"
|
||||
templateBody += (
|
||||
" } else if (${argVal}.isNullOrUndefined()) {\n"
|
||||
" ${name}%s = NULL;\n" % nameSuffix)
|
||||
"jsval tmpVal = ${val};\n" +
|
||||
typePtr + " tmp;\n"
|
||||
"if (NS_FAILED(xpc_qsUnwrapArg<" + typeName + ">(cx, ${val}, &tmp, getter_AddRefs(${holderName}), &tmpVal))) {\n")
|
||||
if failureCode is not None:
|
||||
templateBody += " " + failureCode + "\n"
|
||||
else:
|
||||
templateBody += (
|
||||
" return Throw<%s>(cx, NS_ERROR_XPC_BAD_CONVERT_JS);\n"
|
||||
% toStringBool(not descriptor.workers))
|
||||
templateBody += ("}\n"
|
||||
"MOZ_ASSERT(tmp);\n")
|
||||
|
||||
templateBody += (
|
||||
" } else {\n"
|
||||
" return Throw<%s>(cx, NS_ERROR_XPC_BAD_CONVERT_JS);\n"
|
||||
" }\n" % toStringBool(not descriptor.workers))
|
||||
if not isDefinitelyObject:
|
||||
# Our tmpVal will go out of scope, so we can't rely on it
|
||||
# for rooting
|
||||
templateBody += (
|
||||
"if (tmpVal != ${val} && !${holderName}) {\n"
|
||||
" // We have to have a strong ref, because we got this off\n"
|
||||
" // some random object that might get GCed\n"
|
||||
" ${holderName} = tmp;\n"
|
||||
"}\n")
|
||||
|
||||
template += templateBody
|
||||
# And store our tmp, before it goes out of scope.
|
||||
templateBody += "${declName} = tmp;"
|
||||
|
||||
if not argIsPointer:
|
||||
template += " ${typeName} &${name} = *${name}_ptr;\n"
|
||||
|
||||
return template
|
||||
templateBody = wrapObjectTemplate(templateBody, isDefinitelyObject,
|
||||
type, "${declName} = NULL",
|
||||
descriptor.workers)
|
||||
|
||||
declType = CGGeneric(declType)
|
||||
if holderType is not None:
|
||||
holderType = CGGeneric(holderType)
|
||||
return (templateBody, declType, holderType)
|
||||
|
||||
if type.isArrayBuffer():
|
||||
if isSequenceMember:
|
||||
raise TypeError("Can't handle sequences of arraybuffers")
|
||||
declType = "JSObject*"
|
||||
template = (
|
||||
" JSObject* ${name};\n"
|
||||
" if (${argVal}.isObject() && JS_IsArrayBufferObject(&${argVal}.toObject(), cx)) {\n"
|
||||
" ${name} = &${argVal}.toObject();\n"
|
||||
" }")
|
||||
"if (${val}.isObject() && JS_IsArrayBufferObject(&${val}.toObject(), cx)) {\n"
|
||||
" ${declName} = &${val}.toObject();\n"
|
||||
"}")
|
||||
if type.nullable():
|
||||
template += (
|
||||
" else if (${argVal}.isNullOrUndefined()) {\n"
|
||||
" ${name} = NULL;\n"
|
||||
" }")
|
||||
" else if (${val}.isNullOrUndefined()) {\n"
|
||||
" ${declName} = NULL;\n"
|
||||
"}")
|
||||
|
||||
template += (
|
||||
# XXXbz We don't know whether we're on workers, so play it safe
|
||||
" else {\n"
|
||||
" return Throw<false>(cx, NS_ERROR_XPC_BAD_CONVERT_JS);\n"
|
||||
" }")
|
||||
" return Throw<false>(cx, NS_ERROR_XPC_BAD_CONVERT_JS);\n"
|
||||
"}")
|
||||
|
||||
return template
|
||||
|
||||
if type.isInterface():
|
||||
raise TypeError("Interface type with no descriptor: " + type)
|
||||
return (template, CGGeneric(declType), None)
|
||||
|
||||
if type.isString():
|
||||
if isSequenceMember:
|
||||
raise TypeError("Can't handle sequences of strings")
|
||||
# XXXbz Need to figure out string behavior based on extended args? Also, how to
|
||||
# detect them?
|
||||
|
||||
@ -1285,12 +1457,12 @@ def getArgumentConversionTemplate(type, descriptor):
|
||||
undefinedBehavior = "eStringify"
|
||||
|
||||
return (
|
||||
" const xpc_qsDOMString ${name}(cx, ${argVal}, ${argPtr},\n"
|
||||
" xpc_qsDOMString::%s,\n"
|
||||
" xpc_qsDOMString::%s);\n"
|
||||
" if (!${name}.IsValid()) {\n"
|
||||
" return false;\n"
|
||||
" }\n" % (nullBehavior, undefinedBehavior))
|
||||
"const xpc_qsDOMString ${declName}(cx, ${val}, ${valPtr},\n"
|
||||
" xpc_qsDOMString::%s,\n"
|
||||
" xpc_qsDOMString::%s);\n"
|
||||
"if (!${declName}.IsValid()) {\n"
|
||||
" return false;\n"
|
||||
"}" % (nullBehavior, undefinedBehavior), None, None)
|
||||
|
||||
if type.isEnum():
|
||||
if type.nullable():
|
||||
@ -1298,46 +1470,74 @@ def getArgumentConversionTemplate(type, descriptor):
|
||||
"yet")
|
||||
enum = type.inner.identifier.name
|
||||
return (
|
||||
" %(enumtype)s ${name};\n"
|
||||
" {\n"
|
||||
" bool ok;\n"
|
||||
" ${name} = static_cast<%(enumtype)s>(FindEnumStringIndex(cx, ${argVal}, %(values)s, &ok));\n"
|
||||
" if (!ok) {\n"
|
||||
" return false;\n"
|
||||
" }\n"
|
||||
" }" % { "enumtype" : enum,
|
||||
"values" : enum + "Values::strings" })
|
||||
"{\n"
|
||||
" bool ok;\n"
|
||||
" ${declName} = static_cast<%(enumtype)s>(FindEnumStringIndex(cx, ${val}, %(values)s, &ok));\n"
|
||||
" if (!ok) {\n"
|
||||
" return false;\n"
|
||||
" }\n"
|
||||
"}" % { "enumtype" : enum,
|
||||
"values" : enum + "Values::strings" },
|
||||
CGGeneric(enum), None)
|
||||
|
||||
if type.isCallback():
|
||||
if isSequenceMember:
|
||||
raise TypeError("Can't handle sequences of callbacks")
|
||||
# XXXbz we're going to assume that callback types are always
|
||||
# nullable and always have [TreatNonCallableAsNull] for now.
|
||||
return (
|
||||
" JSObject* ${name};\n"
|
||||
" if (${argVal}.isObject() && JS_ObjectIsCallable(cx, &${argVal}.toObject())) {\n"
|
||||
" ${name} = &${argVal}.toObject();\n"
|
||||
" } else {\n"
|
||||
" ${name} = NULL;\n"
|
||||
" }\n")
|
||||
"if (${val}.isObject() && JS_ObjectIsCallable(cx, &${val}.toObject())) {\n"
|
||||
" ${declName} = &${val}.toObject();\n"
|
||||
"} else {\n"
|
||||
" ${declName} = NULL;\n"
|
||||
"}", CGGeneric("JSObject*"), None)
|
||||
|
||||
if type.isAny():
|
||||
return " JS::Value ${name} = ${argVal};\n"
|
||||
if isSequenceMember:
|
||||
raise TypeError("Can't handle sequences of 'any'")
|
||||
return ("${declName} = ${val};", CGGeneric("JS::Value"), None)
|
||||
|
||||
if not type.isPrimitive():
|
||||
raise TypeError("Need conversion for argument type '%s'" % type)
|
||||
|
||||
# XXXbz need to add support for [EnforceRange] and [Clamp]
|
||||
typeName = builtinNames[type.tag()]
|
||||
if type.nullable():
|
||||
return (" Nullable<${typeName}> ${name};\n"
|
||||
" if (${argVal}.isNullOrUndefined()) {\n"
|
||||
" ${name}.SetNull();\n"
|
||||
" } else if (!ValueToPrimitive<${typeName}>(cx, ${argVal}, &${name}.SetValue())) {\n"
|
||||
" return false;\n"
|
||||
" }\n")
|
||||
return ("if (${val}.isNullOrUndefined()) {\n"
|
||||
" ${declName}.SetNull();\n"
|
||||
"} else if (!ValueToPrimitive<" + typeName + ">(cx, ${val}, &${declName}.SetValue())) {\n"
|
||||
" return false;\n"
|
||||
"}", CGGeneric("Nullable<" + typeName + ">"), None)
|
||||
else:
|
||||
return (" ${typeName} ${name};\n"
|
||||
" if (!ValueToPrimitive<${typeName}>(cx, ${argVal}, &${name})) {\n"
|
||||
" return false;\n"
|
||||
" }\n")
|
||||
return ("if (!ValueToPrimitive<" + typeName + ">(cx, ${val}, &${declName})) {\n"
|
||||
" return false;\n"
|
||||
"}", CGGeneric(typeName), None)
|
||||
|
||||
def instantiateJSToNativeConversionTemplate(templateTuple, replacements):
|
||||
"""
|
||||
Take a tuple as returned by getJSToNativeConversionTemplate and a set of
|
||||
replacements as required by the strings in such a tuple, and generate code
|
||||
to convert into stack C++ types.
|
||||
"""
|
||||
(templateBody, declType, holderType) = templateTuple
|
||||
result = CGList([], "\n")
|
||||
if holderType is not None:
|
||||
result.append(
|
||||
CGList([holderType, CGGeneric(" "),
|
||||
CGGeneric(replacements["holderName"]),
|
||||
CGGeneric(";")]))
|
||||
if declType is not None:
|
||||
result.append(
|
||||
CGList([declType, CGGeneric(" "),
|
||||
CGGeneric(replacements["declName"]),
|
||||
CGGeneric(";")]))
|
||||
result.append(CGGeneric(
|
||||
string.Template(templateBody).substitute(replacements)
|
||||
))
|
||||
# Add an empty CGGeneric to get an extra newline after the argument
|
||||
# conversion.
|
||||
result.append(CGGeneric(""))
|
||||
return result;
|
||||
|
||||
def convertConstIDLValueToJSVal(value):
|
||||
if isinstance(value, IDLNullValue):
|
||||
@ -1363,7 +1563,6 @@ def convertIDLDefaultValueToJSVal(value):
|
||||
assert False # Not implemented!
|
||||
return convertConstIDLValueToJSVal(value)
|
||||
|
||||
unindenter = re.compile("^ ", re.MULTILINE)
|
||||
class CGArgumentConverter(CGThing):
|
||||
"""
|
||||
A class that takes an IDL argument object, its index in the
|
||||
@ -1375,44 +1574,38 @@ class CGArgumentConverter(CGThing):
|
||||
self.argument = argument
|
||||
# XXXbz should optional jsval args get JSVAL_VOID? What about
|
||||
# others?
|
||||
self.replacementVariables = {
|
||||
replacer = {
|
||||
"index" : index,
|
||||
"argc" : argc,
|
||||
"argv" : argv,
|
||||
"defaultValue" : "JSVAL_VOID",
|
||||
"name" : "arg%d" % index
|
||||
"defaultValue" : "JSVAL_VOID"
|
||||
}
|
||||
self.replacementVariables = {
|
||||
"declName" : "arg%d" % index,
|
||||
"holderName" : ("arg%d" % index) + "_holder"
|
||||
}
|
||||
if argument.optional:
|
||||
if argument.defaultValue:
|
||||
self.replacementVariables["defaultValue"] = convertIDLDefaultValueToJSVal(argument.defaultValue)
|
||||
self.replacementVariables["argVal"] = string.Template(
|
||||
replacer["defaultValue"] = convertIDLDefaultValueToJSVal(argument.defaultValue)
|
||||
self.replacementVariables["val"] = string.Template(
|
||||
"(${index} < ${argc} ? ${argv}[${index}] : ${defaultValue})"
|
||||
).substitute(self.replacementVariables)
|
||||
self.replacementVariables["argPtr"] = string.Template(
|
||||
).substitute(replacer)
|
||||
self.replacementVariables["valPtr"] = string.Template(
|
||||
"(${index} < ${argc} ? &${argv}[${index}] : NULL)"
|
||||
).substitute(self.replacementVariables)
|
||||
).substitute(replacer)
|
||||
else:
|
||||
self.replacementVariables["argVal"] = string.Template(
|
||||
self.replacementVariables["val"] = string.Template(
|
||||
"${argv}[${index}]"
|
||||
).substitute(self.replacementVariables)
|
||||
self.replacementVariables["argPtr"] = (
|
||||
"&" + self.replacementVariables["argVal"])
|
||||
self.descriptor = None
|
||||
if argument.type.isPrimitive():
|
||||
self.replacementVariables["typeName"] = builtinNames[argument.type.tag()]
|
||||
elif argument.type.isInterface() and not argument.type.isArrayBuffer():
|
||||
descriptor = descriptorProvider.getDescriptor(
|
||||
argument.type.unroll().inner.identifier.name)
|
||||
self.descriptor = descriptor
|
||||
self.replacementVariables["typeName"] = descriptor.nativeType
|
||||
).substitute(replacer)
|
||||
self.replacementVariables["valPtr"] = (
|
||||
"&" + self.replacementVariables["val"])
|
||||
self.descriptorProvider = descriptorProvider
|
||||
|
||||
def define(self):
|
||||
return string.Template(
|
||||
re.sub(unindenter,
|
||||
"",
|
||||
getArgumentConversionTemplate(self.argument.type,
|
||||
self.descriptor))
|
||||
).substitute(self.replacementVariables)
|
||||
return instantiateJSToNativeConversionTemplate(
|
||||
getJSToNativeConversionTemplate(self.argument.type,
|
||||
self.descriptorProvider),
|
||||
self.replacementVariables).define()
|
||||
|
||||
def getWrapTemplateForType(type, descriptorProvider, result, successCode):
|
||||
"""
|
||||
@ -1460,8 +1653,45 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode):
|
||||
if type is None or type.isVoid():
|
||||
return setValue("JSVAL_VOID")
|
||||
|
||||
if type.isSequence() or type.isArray():
|
||||
raise TypeError("Can't handle sequence or array return values yet")
|
||||
if type.isArray():
|
||||
raise TypeError("Can't handle array return values yet")
|
||||
|
||||
if type.isSequence():
|
||||
if type.nullable():
|
||||
# Nullable sequences are Nullable< nsTArray<T> >
|
||||
return """
|
||||
if (%s.IsNull()) {
|
||||
%s
|
||||
}
|
||||
%s""" % (result, CGIndenter(CGGeneric(setValue("JSVAL_NULL"))).define(),
|
||||
getWrapTemplateForType(type.inner, descriptorProvider,
|
||||
"%s.Value()" % result, successCode))
|
||||
|
||||
# Now do non-nullable sequences. We use setting the element
|
||||
# in the array as our succcess code because when we succeed in
|
||||
# wrapping that's what we should do.
|
||||
innerTemplate = wrapForType(
|
||||
type.inner, descriptorProvider,
|
||||
{
|
||||
'result' : "%s[i]" % result,
|
||||
'successCode': ("if (!JS_SetElement(cx, returnArray, i, &tmp)) {\n"
|
||||
" return false;\n"
|
||||
"}"),
|
||||
'jsvalRef': "tmp",
|
||||
'jsvalPtr': "&tmp"
|
||||
}
|
||||
)
|
||||
innerTemplate = CGIndenter(CGGeneric(innerTemplate)).define()
|
||||
return ("""
|
||||
uint32_t length = %s.Length();
|
||||
JSObject *returnArray = JS_NewArrayObject(cx, length, NULL);
|
||||
if (!returnArray) {
|
||||
return false;
|
||||
}
|
||||
jsval tmp;
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
%s
|
||||
}\n""" % (result, innerTemplate)) + setValue("JS::ObjectValue(*returnArray)")
|
||||
|
||||
if type.isInterface() and not type.isArrayBuffer():
|
||||
descriptor = descriptorProvider.getDescriptor(type.unroll().inner.identifier.name)
|
||||
@ -1582,6 +1812,51 @@ def wrapForType(type, descriptorProvider, templateValues):
|
||||
defaultValues = {'obj': 'obj'}
|
||||
return string.Template(wrap).substitute(defaultValues, **templateValues)
|
||||
|
||||
def getRetvalDeclarationForType(returnType, descriptorProvider,
|
||||
resultAlreadyAddRefed):
|
||||
if returnType is None or returnType.isVoid():
|
||||
# Nothing to declare
|
||||
result = None
|
||||
elif returnType.isPrimitive() and returnType.tag() in builtinNames:
|
||||
result = CGGeneric(builtinNames[returnType.tag()])
|
||||
if returnType.nullable():
|
||||
result = CGWrapper(result, pre="Nullable<", post=">")
|
||||
elif returnType.isString():
|
||||
result = CGGeneric("nsString")
|
||||
elif returnType.isEnum():
|
||||
if returnType.nullable():
|
||||
raise TypeError("We don't support nullable enum return values")
|
||||
result = CGGeneric(returnType.inner.identifier.name)
|
||||
elif returnType.isInterface() and not returnType.isArrayBuffer():
|
||||
result = CGGeneric(descriptorProvider.getDescriptor(
|
||||
returnType.unroll().inner.identifier.name).nativeType)
|
||||
if resultAlreadyAddRefed:
|
||||
result = CGWrapper(result, pre="nsRefPtr<", post=">")
|
||||
else:
|
||||
result = CGWrapper(result, post="*")
|
||||
elif returnType.isCallback():
|
||||
# XXXbz we're going to assume that callback types are always
|
||||
# nullable for now.
|
||||
result = CGGeneric("JSObject*")
|
||||
elif returnType.tag() is IDLType.Tags.any:
|
||||
result = CGGeneric("JS::Value")
|
||||
elif returnType.isSequence():
|
||||
nullable = returnType.nullable()
|
||||
if nullable:
|
||||
returnType = returnType.inner
|
||||
# Assume no need to addref for now
|
||||
result = CGWrapper(getRetvalDeclarationForType(returnType.inner,
|
||||
descriptorProvider,
|
||||
False),
|
||||
pre="nsTArray< ", post=" >")
|
||||
if nullable:
|
||||
result = CGWrapper(result, pre="Nullable< ", post=" >")
|
||||
else:
|
||||
raise TypeError("Don't know how to declare return value for %s" %
|
||||
returnType)
|
||||
return result
|
||||
|
||||
|
||||
class CGCallGenerator(CGThing):
|
||||
"""
|
||||
A class to generate an actual call to a C++ object. Assumes that the C++
|
||||
@ -1594,42 +1869,16 @@ class CGCallGenerator(CGThing):
|
||||
isFallible = errorReport is not None
|
||||
|
||||
args = CGList([CGGeneric("arg" + str(i)) for i in range(argCount)], ", ")
|
||||
resultOutParam = returnType is not None and returnType.isString()
|
||||
resultOutParam = (returnType is not None and
|
||||
(returnType.isString() or returnType.isSequence()))
|
||||
# Return values that go in outparams go here
|
||||
if resultOutParam:
|
||||
args.append(CGGeneric("result"))
|
||||
if isFallible:
|
||||
args.append(CGGeneric("rv"))
|
||||
|
||||
if returnType is None or returnType.isVoid():
|
||||
# Nothing to declare
|
||||
result = None
|
||||
elif returnType.isPrimitive() and returnType.tag() in builtinNames:
|
||||
result = CGGeneric(builtinNames[returnType.tag()])
|
||||
if returnType.nullable():
|
||||
result = CGWrapper(result, pre="Nullable<", post=">")
|
||||
elif returnType.isString():
|
||||
result = CGGeneric("nsString")
|
||||
elif returnType.isEnum():
|
||||
if returnType.nullable():
|
||||
raise TypeError("We don't support nullable enum return values")
|
||||
result = CGGeneric(returnType.inner.identifier.name)
|
||||
elif returnType.isInterface() and not returnType.isArrayBuffer():
|
||||
result = CGGeneric(descriptorProvider.getDescriptor(
|
||||
returnType.unroll().inner.identifier.name).nativeType)
|
||||
if resultAlreadyAddRefed:
|
||||
result = CGWrapper(result, pre="nsRefPtr<", post=">")
|
||||
else:
|
||||
result = CGWrapper(result, post="*")
|
||||
elif returnType.isCallback():
|
||||
# XXXbz we're going to assume that callback types are always
|
||||
# nullable for now.
|
||||
result = CGGeneric("JSObject*")
|
||||
elif returnType.tag() is IDLType.Tags.any:
|
||||
result = CGGeneric("JS::Value")
|
||||
else:
|
||||
raise TypeError("Don't know how to declare return value for %s" %
|
||||
returnType)
|
||||
result = getRetvalDeclarationForType(returnType, descriptorProvider,
|
||||
resultAlreadyAddRefed)
|
||||
|
||||
# Build up our actual call
|
||||
self.cgRoot = CGList([], "\n")
|
||||
@ -1958,63 +2207,24 @@ class CGMethodCall(CGThing):
|
||||
caseBody.append(CGIndenter(CGGeneric("do {")));
|
||||
type = sig[1][distinguishingIndex].type
|
||||
|
||||
# XXXbz this duplicates some argument-unwrapping code!
|
||||
interfaceDesc = descriptor.getDescriptor(
|
||||
type.unroll().inner.identifier.name)
|
||||
argIsPointer = (type.nullable() or
|
||||
type.unroll().inner.isExternal())
|
||||
if argIsPointer:
|
||||
nameSuffix = ""
|
||||
else:
|
||||
nameSuffix = "_ptr"
|
||||
if (interfaceDesc.castable or
|
||||
type.unroll().inner.isExternal() or
|
||||
interfaceDesc.workers):
|
||||
declType = " ${typeName}*"
|
||||
else:
|
||||
declType = " nsCOMPtr<${typeName}>"
|
||||
template = declType + " ${name}%s;\n" % nameSuffix
|
||||
if interfaceDesc.castable:
|
||||
template += str(CastableObjectUnwrapper(
|
||||
interfaceDesc,
|
||||
"&${argVal}.toObject()",
|
||||
"${name}"+nameSuffix,
|
||||
"break;")) + "\n"
|
||||
elif interfaceDesc.workers:
|
||||
template += """
|
||||
${name}%s = &${argVal}.toObject();
|
||||
MOZ_ASSERT(${name}%s);
|
||||
""" % (nameSuffix, nameSuffix)
|
||||
else:
|
||||
template += " xpc_qsSelfRef tmpRef_${name};\n"
|
||||
template += " jsval tmpVal_${name} = ${argVal};\n"
|
||||
template += """
|
||||
${typeName}* tmp;
|
||||
if (NS_FAILED(xpc_qsUnwrapArg<${typeName}>(cx, ${argVal}, &tmp, &tmpRef_${name}.ptr,
|
||||
&tmpVal_${name}))) {
|
||||
break;
|
||||
}
|
||||
MOZ_ASSERT(tmp);
|
||||
${name}%s = tmp;
|
||||
""" % nameSuffix
|
||||
|
||||
if not argIsPointer:
|
||||
template += " ${typeName} &${name} = *${name}_ptr;\n"
|
||||
|
||||
testCode = string.Template(template).substitute(
|
||||
testCode = instantiateJSToNativeConversionTemplate(
|
||||
getJSToNativeConversionTemplate(type, descriptor,
|
||||
failureCode="break;",
|
||||
isDefinitelyObject=True),
|
||||
{
|
||||
"typeName": interfaceDesc.nativeType,
|
||||
"name" : "arg%d" % distinguishingIndex,
|
||||
"argVal" : distinguishingArg
|
||||
}
|
||||
)
|
||||
caseBody.append(CGIndenter(CGGeneric(testCode)));
|
||||
"declName" : "arg%d" % distinguishingIndex,
|
||||
"holderName" : ("arg%d" % distinguishingIndex) + "_holder",
|
||||
"val" : distinguishingArg
|
||||
})
|
||||
|
||||
# Indent by 4, since we need to indent further than our "do" statement
|
||||
caseBody.append(CGIndenter(testCode, 4));
|
||||
# If we got this far, we know we unwrapped to the right
|
||||
# interface, so just do the call. Start conversion with
|
||||
# distinguishingIndex + 1, since we already converted
|
||||
# distinguishingIndex.
|
||||
caseBody.append(CGIndenter(CGIndenter(
|
||||
getPerSignatureCall(sig, distinguishingIndex + 1))))
|
||||
caseBody.append(CGIndenter(
|
||||
getPerSignatureCall(sig, distinguishingIndex + 1), 4))
|
||||
caseBody.append(CGIndenter(CGGeneric("} while (0);")))
|
||||
|
||||
caseBody.append(CGGeneric("}"))
|
||||
@ -2022,7 +2232,7 @@ class CGMethodCall(CGThing):
|
||||
# XXXbz Now we're supposed to check for distinguishingArg being
|
||||
# an array or a platform object that supports indexed
|
||||
# properties... skip that last for now. It's a bit of a pain.
|
||||
pickFirstSignature("%s.isObject() && IsArrayLike(cx, &%s.toObject()" %
|
||||
pickFirstSignature("%s.isObject() && IsArrayLike(cx, &%s.toObject())" %
|
||||
(distinguishingArg, distinguishingArg),
|
||||
lambda s:
|
||||
(s[1][distinguishingIndex].type.isArray() or
|
||||
@ -2168,8 +2378,9 @@ class CGAbstractBindingMethod(CGAbstractStaticMethod):
|
||||
CGAbstractStaticMethod.__init__(self, descriptor, name, "JSBool", args)
|
||||
|
||||
def definition_body(self):
|
||||
unwrapThis = CGGeneric(
|
||||
str(FailureFatalCastableObjectUnwrapper(self.descriptor, "obj", "self")))
|
||||
unwrapThis = CGIndenter(CGGeneric(
|
||||
str(FailureFatalCastableObjectUnwrapper(self.descriptor,
|
||||
"obj", "&self"))))
|
||||
return CGList([ self.getThis(), unwrapThis,
|
||||
self.generate_code() ], "\n").define()
|
||||
|
||||
|
@ -47,6 +47,10 @@ public:
|
||||
|
||||
private:
|
||||
nsresult mResult;
|
||||
|
||||
// Not to be implemented, to make sure people always pass this by
|
||||
// reference, not by value.
|
||||
ErrorResult(const ErrorResult&) MOZ_DELETE;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -52,6 +52,11 @@ public:
|
||||
return mValue;
|
||||
}
|
||||
|
||||
T& Value() {
|
||||
MOZ_ASSERT(!mIsNull);
|
||||
return mValue;
|
||||
}
|
||||
|
||||
bool IsNull() const {
|
||||
return mIsNull;
|
||||
}
|
||||
|
@ -814,10 +814,10 @@ class IDLSequenceType(IDLType):
|
||||
return False
|
||||
|
||||
def isPrimitive(self):
|
||||
return self.inner.isPrimitive()
|
||||
return False;
|
||||
|
||||
def isString(self):
|
||||
return self.inner.isString()
|
||||
return False;
|
||||
|
||||
def isVoid(self):
|
||||
return False
|
||||
|
@ -104,16 +104,16 @@ class ToggleBtTask : public nsRunnable
|
||||
}
|
||||
|
||||
// return 1 if it's enabled, 0 if it's disabled, and -1 on error
|
||||
int isEnabled = sBluedroidFunctions.bt_is_enabled();
|
||||
int isEnabled = IsBluetoothEnabled();
|
||||
|
||||
if ((isEnabled == 1 && mEnabled) || (isEnabled == 0 && !mEnabled)) {
|
||||
result = true;
|
||||
} else if (isEnabled < 0) {
|
||||
result = false;
|
||||
} else if (mEnabled) {
|
||||
result = (sBluedroidFunctions.bt_enable() == 0) ? true : false;
|
||||
result = (EnableBluetooth() == 0) ? true : false;
|
||||
} else {
|
||||
result = (sBluedroidFunctions.bt_disable() == 0) ? true : false;
|
||||
result = (DisableBluetooth() == 0) ? true : false;
|
||||
}
|
||||
#else
|
||||
result = true;
|
||||
|
@ -14,6 +14,21 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
namespace bluetooth {
|
||||
|
||||
static struct BluedroidFunctions {
|
||||
bool initialized;
|
||||
bool tried_initialization;
|
||||
|
||||
BluedroidFunctions() :
|
||||
initialized(false),
|
||||
tried_initialization(false)
|
||||
{
|
||||
}
|
||||
|
||||
int (* bt_enable)();
|
||||
int (* bt_disable)();
|
||||
int (* bt_is_enabled)();
|
||||
} sBluedroidFunctions;
|
||||
|
||||
bool EnsureBluetoothInit() {
|
||||
if (sBluedroidFunctions.tried_initialization)
|
||||
{
|
||||
@ -49,6 +64,22 @@ bool EnsureBluetoothInit() {
|
||||
return true;
|
||||
}
|
||||
|
||||
int IsBluetoothEnabled()
|
||||
{
|
||||
return sBluedroidFunctions.bt_is_enabled();
|
||||
}
|
||||
|
||||
int EnableBluetooth()
|
||||
{
|
||||
return sBluedroidFunctions.bt_enable();
|
||||
}
|
||||
|
||||
int DisableBluetooth()
|
||||
{
|
||||
return sBluedroidFunctions.bt_disable();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,22 +11,11 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
namespace bluetooth {
|
||||
|
||||
static struct BluedroidFunctions {
|
||||
bool initialized;
|
||||
bool tried_initialization;
|
||||
|
||||
BluedroidFunctions() :
|
||||
initialized(false),
|
||||
tried_initialization(false)
|
||||
{
|
||||
}
|
||||
|
||||
int (* bt_enable)();
|
||||
int (* bt_disable)();
|
||||
int (* bt_is_enabled)();
|
||||
} sBluedroidFunctions;
|
||||
|
||||
bool EnsureBluetoothInit();
|
||||
int IsBluetoothEnabled();
|
||||
int EnableBluetooth();
|
||||
int DisableBluetooth();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -52,9 +52,9 @@ class nsIThread;
|
||||
|
||||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
|
||||
class CheckPermissionsHelper : public nsIRunnable,
|
||||
public nsIInterfaceRequestor,
|
||||
public nsIObserver
|
||||
class CheckPermissionsHelper MOZ_FINAL : public nsIRunnable,
|
||||
public nsIInterfaceRequestor,
|
||||
public nsIObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
@ -55,9 +55,9 @@ class nsPIDOMWindow;
|
||||
|
||||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
|
||||
class CheckQuotaHelper : public nsIRunnable,
|
||||
public nsIInterfaceRequestor,
|
||||
public nsIObserver
|
||||
class CheckQuotaHelper MOZ_FINAL : public nsIRunnable,
|
||||
public nsIInterfaceRequestor,
|
||||
public nsIObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
@ -63,7 +63,7 @@ class ContinueObjectStoreHelper;
|
||||
class ContinueIndexHelper;
|
||||
class ContinueIndexObjectHelper;
|
||||
|
||||
class IDBCursor : public nsIIDBCursorWithValue
|
||||
class IDBCursor MOZ_FINAL : public nsIIDBCursorWithValue
|
||||
{
|
||||
friend class ContinueHelper;
|
||||
friend class ContinueObjectStoreHelper;
|
||||
|
@ -57,7 +57,7 @@ struct DatabaseInfo;
|
||||
class IDBDatabase;
|
||||
struct ObjectStoreInfo;
|
||||
|
||||
class IDBFactory : public nsIIDBFactory
|
||||
class IDBFactory MOZ_FINAL : public nsIIDBFactory
|
||||
{
|
||||
typedef nsTArray<nsRefPtr<ObjectStoreInfo> > ObjectStoreInfoArray;
|
||||
|
||||
|
@ -55,7 +55,7 @@ class AsyncConnectionHelper;
|
||||
class IDBObjectStore;
|
||||
struct IndexInfo;
|
||||
|
||||
class IDBIndex : public nsIIDBIndex
|
||||
class IDBIndex MOZ_FINAL : public nsIIDBIndex
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
|
@ -51,7 +51,7 @@ class mozIStorageStatement;
|
||||
|
||||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
|
||||
class IDBKeyRange : public nsIIDBKeyRange
|
||||
class IDBKeyRange MOZ_FINAL : public nsIIDBKeyRange
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
|
@ -63,7 +63,7 @@ struct IndexUpdateInfo;
|
||||
struct StructuredCloneReadInfo;
|
||||
struct StructuredCloneWriteInfo;
|
||||
|
||||
class IDBObjectStore : public nsIIDBObjectStore
|
||||
class IDBObjectStore MOZ_FINAL : public nsIIDBObjectStore
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
|
@ -219,7 +219,7 @@ private:
|
||||
nsTArray<nsRefPtr<FileInfo> > mCreatedFileInfos;
|
||||
};
|
||||
|
||||
class CommitHelper : public nsIRunnable
|
||||
class CommitHelper MOZ_FINAL : public nsIRunnable
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
@ -263,7 +263,7 @@ private:
|
||||
bool mAborted;
|
||||
};
|
||||
|
||||
class UpdateRefcountFunction : public mozIStorageFunction
|
||||
class UpdateRefcountFunction MOZ_FINAL : public mozIStorageFunction
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
@ -125,7 +125,7 @@ GetBaseFilename(const nsAString& aFilename,
|
||||
return true;
|
||||
}
|
||||
|
||||
class QuotaCallback : public mozIStorageQuotaCallback
|
||||
class QuotaCallback MOZ_FINAL : public mozIStorageQuotaCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
@ -69,8 +69,8 @@ class AsyncConnectionHelper;
|
||||
|
||||
class CheckQuotaHelper;
|
||||
|
||||
class IndexedDatabaseManager : public nsIIndexedDatabaseManager,
|
||||
public nsIObserver
|
||||
class IndexedDatabaseManager MOZ_FINAL : public nsIIndexedDatabaseManager,
|
||||
public nsIObserver
|
||||
{
|
||||
friend class IDBDatabase;
|
||||
|
||||
@ -243,7 +243,7 @@ private:
|
||||
// directory that contains them before dispatching itself back to the main
|
||||
// thread. When back on the main thread the runnable will notify the
|
||||
// IndexedDatabaseManager that the job has been completed.
|
||||
class OriginClearRunnable : public nsIRunnable
|
||||
class OriginClearRunnable MOZ_FINAL : public nsIRunnable
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
@ -272,7 +272,7 @@ private:
|
||||
// before dispatching itself back to the main thread. When on the main thread
|
||||
// the runnable will call the callback and then notify the
|
||||
// IndexedDatabaseManager that the job has been completed.
|
||||
class AsyncUsageRunnable : public nsIRunnable
|
||||
class AsyncUsageRunnable MOZ_FINAL : public nsIRunnable
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
@ -326,7 +326,7 @@ private:
|
||||
|
||||
// A callback runnable used by the TransactionPool when it's safe to proceed
|
||||
// with a SetVersion/DeleteDatabase/etc.
|
||||
class WaitForTransactionsToFinishRunnable : public nsIRunnable
|
||||
class WaitForTransactionsToFinishRunnable MOZ_FINAL : public nsIRunnable
|
||||
{
|
||||
public:
|
||||
WaitForTransactionsToFinishRunnable(SynchronizedOp* aOp)
|
||||
@ -345,7 +345,7 @@ private:
|
||||
SynchronizedOp* mOp;
|
||||
};
|
||||
|
||||
class AsyncDeleteFileRunnable : public nsIRunnable
|
||||
class AsyncDeleteFileRunnable MOZ_FINAL : public nsIRunnable
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
@ -853,7 +853,7 @@ UpgradeSchemaFrom7To8(mozIStorageConnection* aConnection)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class CompressDataBlobsFunction : public mozIStorageFunction
|
||||
class CompressDataBlobsFunction MOZ_FINAL : public mozIStorageFunction
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
@ -1095,7 +1095,7 @@ UpgradeSchemaFrom10_0To11_0(mozIStorageConnection* aConnection)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class EncodeKeysFunction : public mozIStorageFunction
|
||||
class EncodeKeysFunction MOZ_FINAL : public mozIStorageFunction
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|