merge fx-team to m-c

This commit is contained in:
Rob Campbell 2012-05-16 12:03:18 -07:00
commit 781fd2f3b9
390 changed files with 10395 additions and 4591 deletions

View File

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

View File

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

View File

@ -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.
*/

View File

@ -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()
{

View File

@ -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);

View File

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

View File

@ -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');
}
};

View File

@ -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 = {};

View File

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

View File

@ -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)
];
}
/**

View File

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

View File

@ -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();
}

View File

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

View File

@ -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
View 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)

View File

@ -65,11 +65,6 @@
margin: 0 40px;
}
.text-link:-moz-focusring,
.bottom-link:-moz-focusring {
outline: 1px dotted;
}
#currentChannel {
margin: 0;
padding: 0;

View File

@ -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;"

View File

@ -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"/>

View File

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

View File

@ -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
};

View File

@ -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");

View File

@ -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");

View File

@ -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() {

View File

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

View File

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

View 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

View 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

View 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

View 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

View File

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

View File

@ -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>';

Binary file not shown.

Before

Width:  |  Height:  |  Size: 900 B

After

Width:  |  Height:  |  Size: 708 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 553 B

After

Width:  |  Height:  |  Size: 672 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 541 B

After

Width:  |  Height:  |  Size: 520 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 306 B

After

Width:  |  Height:  |  Size: 500 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 900 B

After

Width:  |  Height:  |  Size: 708 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 553 B

After

Width:  |  Height:  |  Size: 672 B

View File

@ -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();
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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();
}

View File

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

View File

@ -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;
}

View File

@ -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;
}

View File

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

View File

@ -75,6 +75,7 @@ _CHROME_FILES = \
test_bug650784.html \
test_bug752226-3.xul \
test_bug752226-4.xul \
test_bug682305.html \
$(NULL)
libs:: $(_TEST_FILES)

View 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>

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);

View File

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

View File

@ -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();

View File

@ -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;
}

View File

@ -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();

View File

@ -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();

View File

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

View File

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

View File

@ -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));

View File

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

View File

@ -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) {

View File

@ -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);

View File

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

View File

@ -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();
}

View File

@ -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).

View File

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

View File

@ -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);

View File

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

View File

@ -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);

View File

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

View 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>

View File

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

View File

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

View File

@ -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);
}
}
}

View File

@ -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);

View File

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

View File

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

View File

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

View File

@ -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()

View File

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

View File

@ -52,6 +52,11 @@ public:
return mValue;
}
T& Value() {
MOZ_ASSERT(!mIsNull);
return mValue;
}
bool IsNull() const {
return mIsNull;
}

View File

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

View File

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

View File

@ -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();
}
}
}
}

View File

@ -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();
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -125,7 +125,7 @@ GetBaseFilename(const nsAString& aFilename,
return true;
}
class QuotaCallback : public mozIStorageQuotaCallback
class QuotaCallback MOZ_FINAL : public mozIStorageQuotaCallback
{
public:
NS_DECL_ISUPPORTS

View File

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

View File

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

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