Merge from mozilla-central.

This commit is contained in:
David Anderson 2012-05-15 10:22:19 -07:00
commit 95e5988f43
276 changed files with 6637 additions and 3034 deletions

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

@ -11,6 +11,7 @@
#include "States.h"
#include "nsBlockFrame.h"
#include "nsBulletFrame.h"
using namespace mozilla;
using namespace mozilla::a11y;
@ -85,15 +86,15 @@ HTMLLIAccessible::GetBounds(PRInt32* aX, PRInt32* aY,
PRInt32* aWidth, PRInt32* aHeight)
{
nsresult rv = nsAccessibleWrap::GetBounds(aX, aY, aWidth, aHeight);
if (NS_FAILED(rv) || !mBullet)
if (NS_FAILED(rv) || !mBullet || mBullet->IsInside())
return rv;
PRInt32 bulletX = 0, bulletY = 0, bulletWidth = 0, bulletHeight = 0;
rv = mBullet->GetBounds(&bulletX, &bulletY, &bulletWidth, &bulletHeight);
NS_ENSURE_SUCCESS(rv, rv);
*aWidth += *aX - bulletX;
*aX = bulletX; // Move x coordinate of list item over to cover bullet as well
*aWidth += bulletWidth;
return NS_OK;
}
@ -144,6 +145,13 @@ HTMLLIAccessible::CacheChildren()
////////////////////////////////////////////////////////////////////////////////
// HTMLListBulletAccessible: nsAccessNode
nsIFrame*
HTMLListBulletAccessible::GetFrame() const
{
nsBlockFrame* blockFrame = do_QueryFrame(mContent->GetPrimaryFrame());
return blockFrame ? blockFrame->GetBullet() : nsnull;
}
bool
HTMLListBulletAccessible::IsPrimaryForNode() const
{
@ -199,3 +207,13 @@ HTMLListBulletAccessible::AppendTextTo(nsAString& aText, PRUint32 aStartOffset,
aText.Append(Substring(bulletText, aStartOffset, aLength));
}
////////////////////////////////////////////////////////////////////////////////
// HTMLListBulletAccessible: public
bool
HTMLListBulletAccessible::IsInside() const
{
nsBlockFrame* blockFrame = do_QueryFrame(mContent->GetPrimaryFrame());
return blockFrame ? blockFrame->HasInsideBullet() : false;
}

View File

@ -80,6 +80,7 @@ public:
virtual ~HTMLListBulletAccessible() { }
// nsAccessNode
virtual nsIFrame* GetFrame() const;
virtual bool IsPrimaryForNode() const;
// nsAccessible
@ -88,6 +89,13 @@ public:
virtual PRUint64 NativeState();
virtual void AppendTextTo(nsAString& aText, PRUint32 aStartOffset = 0,
PRUint32 aLength = PR_UINT32_MAX);
// HTMLListBulletAccessible
/**
* Return true if the bullet is inside of list item element boundaries.
*/
bool IsInside() const;
};
} // namespace a11y

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:
{
@ -251,13 +251,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 +267,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 +296,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 +342,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 +360,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

@ -20,14 +20,15 @@ var gAccRetrieval = Cc['@mozilla.org/accessibleRetrieval;1'].
var VirtualCursorController = {
attach: function attach(aWindow) {
this.chromeWin = aWindow;
this.chromeWin.document.addEventListener('keypress', this.onkeypress, true);
this.chromeWin.document.addEventListener('keypress', this._onkeypress, true);
},
detach: function detach() {
this.chromeWin.document.removeEventListener('keypress', this.onkeypress, true);
this.chromeWin.document.removeEventListener('keypress', this._onkeypress,
true);
},
getBrowserApp: function getBrowserApp() {
_getBrowserApp: function _getBrowserApp() {
switch (Services.appinfo.OS) {
case 'Android':
return this.chromeWin.BrowserApp;
@ -36,8 +37,8 @@ var VirtualCursorController = {
}
},
onkeypress: function onkeypress(aEvent) {
let document = VirtualCursorController.getBrowserApp().
_onkeypress: function _onkeypress(aEvent) {
let document = VirtualCursorController._getBrowserApp().
selectedBrowser.contentDocument;
dump('keypress ' + aEvent.keyCode + '\n');
@ -57,7 +58,7 @@ var VirtualCursorController = {
break;
case aEvent.DOM_VK_UP:
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' } }));
@ -110,7 +111,7 @@ var VirtualCursorController = {
},
SimpleTraversalRule: {
getMatchRoles: function(aRules) {
getMatchRoles: function SimpleTraversalRule_getmatchRoles(aRules) {
aRules.value = this._matchRoles;
return this._matchRoles.length;
},
@ -118,7 +119,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

@ -46,6 +46,7 @@ include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
_TEST_FILES =\
test_list.html \
test_select.html \
test_zoom.html \
$(NULL)

View File

@ -0,0 +1,81 @@
<!DOCTYPE html>
<html>
<head>
<title>Accessible boundaries when page is zoomed</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<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="../common.js"></script>
<script type="application/javascript"
src="../role.js"></script>
<script type="application/javascript"
src="../layout.js"></script>
<script type="application/javascript">
function doTest()
{
// Inside list
var li = getAccessible("insidelist_item");
testBounds(li);
var [xLI, yLI, widthLI, heightLI] = getBounds(li);
var bullet = li.firstChild;
var [x, y, width, height] = getBounds(bullet);
is(x, xLI,
"Bullet x should match to list item x");
ok(y >= yLI,
"Bullet y= " + y + " should be not less than list item y=" + yLI);
ok(width < widthLI,
"Bullet width should be lesser list item width");
ok(height <= heightLI,
"Bullet height= " + height + " should be not greater than list item height=" + heightLI);
// Outside list
li = getAccessible("outsidelist_item");
var [xLIElm, yLIElm, widthLIElm, heightLIElm] = getBoundsForDOMElm(li);
[xLI, yLI, widthLI, heightLI] = getBounds(li);
ok(xLI < xLIElm,
"Outside list item x=" + xLI + " should be lesser than list item element x=" + xLIElm);
is(yLI, yLIElm,
"Outside list item y should match to list item element y");
ok(widthLI > widthLIElm,
"Outside list item width=" + widthLI + " should be greater than list item element width=" + widthLIElm);
is(heightLI, heightLIElm,
"Outside list item height should match to list item element height");
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=754627"
title="GetBounds on bullet return wrong values">
Mozilla Bug 754627
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<ul style="list-style-position: inside;">
<li id="insidelist_item">item</li>
</ul>
<ul style="list-style-position: outside;">
<li id="outsidelist_item">item</li>
</ul>
</body>
</html>

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

@ -1126,58 +1126,34 @@
#ifndef XP_UNIX
<svg:svg height="0">
<svg:mask id="winstripe-keyhole-forward-mask" maskContentUnits="objectBoundingBox">
<svg:rect x="0" y="0" width="1" height="1" fill="white"/>
<svg:circle cx="-0.34" cy="0.5" r="0.61"/>
</svg:mask>
<svg:mask id="winstripe-urlbar-back-button-mask" maskContentUnits="userSpaceOnUse">
<svg:rect x="0" y="0" width="10000" height="50" fill="white"/>
<svg:circle cx="-11" cy="18" r="15"/>
</svg:mask>
<svg:clipPath id="winstripe-keyhole-forward-clip-path" clipPathUnits="objectBoundingBox">
<svg:path d="M 0,0 C 0.16,0.11 0.28,0.29 0.28,0.5 0.28,0.71 0.16,0.89 0,1 L 1,1 1,0 0,0 z"/>
</svg:clipPath>
<svg:clipPath id="winstripe-urlbar-back-button-clip-path" clipPathUnits="userSpaceOnUse">
<svg:path d="M 0,0 0,7.8 C 2.5,11 4,14 4,18 4,22 2.5,25 0,28 l 0,22 10000,0 0,-50 L 0,0 z"/>
</svg:clipPath>
</svg:svg>
#endif
#ifdef XP_MACOSX
<svg:svg height="0">
<svg:mask id="pinstripe-keyhole-forward-mask" maskContentUnits="objectBoundingBox">
<svg:rect x="0" y="0" width="1" height="1" fill="white"/>
<svg:circle cx="-0.41" cy="0.5" r="0.65"/>
</svg:mask>
<svg:mask id="pinstripe-urlbar-back-button-mask" maskContentUnits="userSpaceOnUse">
<svg:rect x="0" y="-5" width="10000" height="55" fill="white"/>
<svg:circle cx="-9" cy="11" r="15"/>
</svg:mask>
<svg:mask id="pinstripe-tab-ontop-left-curve-mask" maskContentUnits="userSpaceOnUse">
<svg:circle cx="9" cy="3" r="3" fill="white"/>
<svg:rect x="9" y="0" width="3" height="3" fill="white"/>
<svg:rect x="6" y="3" width="6" height="19" fill="white"/>
<svg:rect x="1" y="17" width="5" height="5" fill="white"/>
<svg:circle cx="1" cy="17" r="5"/>
<svg:rect x="0" y="22" width="12" height="1" fill="white"/>
</svg:mask>
<svg:mask id="pinstripe-tab-ontop-right-curve-mask" maskContentUnits="userSpaceOnUse">
<svg:circle cx="3" cy="3" r="3" fill="white"/>
<svg:rect x="0" y="0" width="3" height="3" fill="white"/>
<svg:rect x="0" y="3" width="6" height="19" fill="white"/>
<svg:rect x="6" y="17" width="5" height="5" fill="white"/>
<svg:circle cx="11" cy="17" r="5"/>
<svg:rect x="0" y="22" width="12" height="1" fill="white"/>
</svg:mask>
<svg:mask id="pinstripe-tab-onbottom-left-curve-mask" maskContentUnits="userSpaceOnUse">
<svg:circle cx="9" cy="20" r="3" fill="white"/>
<svg:rect x="9" y="20" width="3" height="3" fill="white"/>
<svg:rect x="6" y="1" width="6" height="19" fill="white"/>
<svg:rect x="1" y="1" width="5" height="5" fill="white"/>
<svg:circle cx="1" cy="6" r="5"/>
<svg:rect x="0" y="0" width="12" height="1" fill="white"/>
</svg:mask>
<svg:mask id="pinstripe-tab-onbottom-right-curve-mask" maskContentUnits="userSpaceOnUse">
<svg:circle cx="3" cy="20" r="3" fill="white"/>
<svg:rect x="0" y="20" width="3" height="3" fill="white"/>
<svg:rect x="0" y="1" width="6" height="19" fill="white"/>
<svg:rect x="6" y="1" width="5" height="5" fill="white"/>
<svg:circle cx="11" cy="6" r="5"/>
<svg:rect x="0" y="0" width="12" height="1" fill="white"/>
</svg:mask>
<svg:clipPath id="pinstripe-keyhole-forward-clip-path" clipPathUnits="objectBoundingBox">
<svg:path d="M 0,0 C 0.15,0.12 0.25,0.3 0.25,0.5 0.25,0.7 0.15,0.88 0,1 L 1,1 1,0 0,0 z"/>
</svg:clipPath>
<svg:clipPath id="pinstripe-urlbar-back-button-clip-path" clipPathUnits="userSpaceOnUse">
<svg:path d="m 0,-5 0,4.03 C 3.6,1.8 6,6.1 6,11 6,16 3.6,20 0,23 l 0,27 10000,0 0,-55 L 0,-5 z"/>
</svg:clipPath>
<svg:clipPath id="pinstripe-tab-ontop-left-curve-clip-path" clipPathUnits="userSpaceOnUse">
<svg:path d="M 9,0 C 7.3,0 6,1.3 6,3 l 0,14 c 0,3 -2.2,5 -5,5 l -1,0 0,1 12,0 0,-1 0,-19 0,-3 -3,0 z"/>
</svg:clipPath>
<svg:clipPath id="pinstripe-tab-ontop-right-curve-clip-path" clipPathUnits="userSpaceOnUse">
<svg:path d="m 0,0 0,3 0,19 0,1 12,0 0,-1 -1,0 C 8.2,22 6,20 6,17 L 6,3 C 6,1.3 4.7,0 3,0 L 0,0 z"/>
</svg:clipPath>
<svg:clipPath id="pinstripe-tab-onbottom-left-curve-clip-path" clipPathUnits="userSpaceOnUse">
<svg:path d="m 0,0 0,1 1,0 c 2.8,0 5,2.2 5,5 l 0,14 c 0,2 1.3,3 3,3 l 3,0 0,-3 L 12,1 12,0 0,0 z"/>
</svg:clipPath>
<svg:clipPath id="pinstripe-tab-onbottom-right-curve-clip-path" clipPathUnits="userSpaceOnUse">
<svg:path d="m 0,0 0,1 0,19 0,3 3,0 c 1.7,0 3,-1 3,-3 L 6,6 C 6,3.2 8.2,1 11,1 L 12,1 12,0 0,0 z"/>
</svg:clipPath>
</svg:svg>
#endif

View File

@ -630,7 +630,7 @@
if (topLevel) {
// The document loaded correctly, clear the value if we should
if (this.mBrowser.userTypedClear > 0 ||
(aRequest && !Components.isSuccessCode(aRequest.status)))
(aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_ERROR_PAGE))
this.mBrowser.userTypedValue = null;
// Clear out the missing plugins list since it's related to the

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

@ -1,181 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
const PREF_DISK_CACHE_SSL = "browser.cache.disk_cache_ssl";
let pb = Cc["@mozilla.org/privatebrowsing;1"].
getService(Ci.nsIPrivateBrowsingService);
let contentWindow;
let newTab;
function test() {
waitForExplicitFinish();
newTab = gBrowser.addTab();
HttpRequestObserver.register();
registerCleanupFunction(function () {
HttpRequestObserver.unregister();
if (gBrowser.tabs[1])
gBrowser.removeTab(gBrowser.tabs[1]);
hideTabView();
Services.prefs.clearUserPref(PREF_DISK_CACHE_SSL);
pb.privateBrowsingEnabled = false;
});
showTabView(function() {
contentWindow = TabView.getContentWindow();
test1();
});
}
function test1() {
// page with cache-control: no-store, should not save thumbnail
HttpRequestObserver.cacheControlValue = "no-store";
whenStorageDenied(newTab, function () {
let tabItem = newTab._tabViewTabItem;
ok(!contentWindow.StoragePolicy.canStoreThumbnailForTab(newTab),
"Should not save the thumbnail for tab");
whenDeniedToSaveImageData(tabItem, test2);
tabItem.saveThumbnail({synchronously: true});
HttpRequestObserver.cacheControlValue = null;
});
newTab.linkedBrowser.loadURI("http://www.example.com/browser/browser/components/tabview/test/dummy_page.html");
}
function test2() {
// page with cache-control: private, should save thumbnail
HttpRequestObserver.cacheControlValue = "private";
newTab.linkedBrowser.loadURI("http://www.example.com/");
afterAllTabsLoaded(function() {
let tabItem = newTab._tabViewTabItem;
ok(contentWindow.StoragePolicy.canStoreThumbnailForTab(newTab),
"Should save the thumbnail for tab");
whenSavedCachedImageData(tabItem, test3);
tabItem.saveThumbnail({synchronously: true});
});
}
function test3() {
// page with cache-control: private with https caching enabled, should save thumbnail
HttpRequestObserver.cacheControlValue = "private";
Services.prefs.setBoolPref(PREF_DISK_CACHE_SSL, true);
newTab.linkedBrowser.loadURI("https://example.com/browser/browser/components/tabview/test/dummy_page.html");
afterAllTabsLoaded(function() {
let tabItem = newTab._tabViewTabItem;
ok(contentWindow.StoragePolicy.canStoreThumbnailForTab(newTab),
"Should save the thumbnail for tab");
whenSavedCachedImageData(tabItem, test4);
tabItem.saveThumbnail({synchronously: true});
});
}
function test4() {
// page with cache-control: public with https caching disabled, should save thumbnail
HttpRequestObserver.cacheControlValue = "public";
Services.prefs.setBoolPref(PREF_DISK_CACHE_SSL, false);
newTab.linkedBrowser.loadURI("https://example.com/browser/browser/components/tabview/test/");
afterAllTabsLoaded(function() {
let tabItem = newTab._tabViewTabItem;
ok(contentWindow.StoragePolicy.canStoreThumbnailForTab(newTab),
"Should save the thumbnail for tab");
whenSavedCachedImageData(tabItem, test5);
tabItem.saveThumbnail({synchronously: true});
});
}
function test5() {
// page with cache-control: private with https caching disabled, should not save thumbnail
HttpRequestObserver.cacheControlValue = "private";
whenStorageDenied(newTab, function () {
let tabItem = newTab._tabViewTabItem;
ok(!contentWindow.StoragePolicy.canStoreThumbnailForTab(newTab),
"Should not save the thumbnail for tab");
whenDeniedToSaveImageData(tabItem, function () {
gBrowser.removeTab(newTab);
test6();
});
tabItem.saveThumbnail({synchronously: true});
});
newTab.linkedBrowser.loadURI("https://example.com/");
}
// ensure that no thumbnails are saved while in private browsing mode
function test6() {
HttpRequestObserver.cacheControlValue = "public";
togglePrivateBrowsing(function () {
let tab = gBrowser.tabs[0];
ok(!contentWindow.StoragePolicy.canStoreThumbnailForTab(tab),
"Should not save the thumbnail for tab");
togglePrivateBrowsing(finish);
});
}
let HttpRequestObserver = {
cacheControlValue: null,
observe: function(subject, topic, data) {
if (topic == "http-on-examine-response" && this.cacheControlValue) {
let httpChannel = subject.QueryInterface(Ci.nsIHttpChannel);
httpChannel.setResponseHeader("Cache-Control", this.cacheControlValue, false);
}
},
register: function() {
Services.obs.addObserver(this, "http-on-examine-response", false);
},
unregister: function() {
Services.obs.removeObserver(this, "http-on-examine-response");
}
};
function whenSavedCachedImageData(tabItem, callback) {
tabItem.addSubscriber("savedCachedImageData", function onSaved() {
tabItem.removeSubscriber("savedCachedImageData", onSaved);
callback();
});
}
function whenDeniedToSaveImageData(tabItem, callback) {
tabItem.addSubscriber("deniedToSaveImageData", function onDenied() {
tabItem.removeSubscriber("deniedToSaveImageData", onDenied);
callback();
});
}
function whenStorageDenied(tab, callback) {
let mm = tab.linkedBrowser.messageManager;
mm.addMessageListener("Panorama:StoragePolicy:denied", function onDenied() {
mm.removeMessageListener("Panorama:StoragePolicy:denied", onDenied);
executeSoon(callback);
});
}

View File

@ -245,14 +245,16 @@ let PageThumbs = {
};
let PageThumbsStorage = {
getFileForURL: function Storage_getFileForURL(aURL) {
getFileForURL: function Storage_getFileForURL(aURL, aOptions) {
let hash = this._calculateMD5Hash(aURL);
let parts = [THUMBNAIL_DIRECTORY, hash[0], hash[1], hash.slice(2) + ".png"];
return FileUtils.getFile("ProfD", parts);
let parts = [THUMBNAIL_DIRECTORY, hash[0], hash[1]];
let file = FileUtils.getDir("ProfD", parts, aOptions && aOptions.createPath);
file.append(hash.slice(2) + ".png");
return file;
},
write: function Storage_write(aURL, aDataStream, aCallback) {
let file = this.getFileForURL(aURL);
let file = this.getFileForURL(aURL, {createPath: true});
let fos = FileUtils.openSafeFileOutputStream(file);
NetUtil.asyncCopy(aDataStream, fos, function (aResult) {

View File

@ -16,6 +16,7 @@ _BROWSER_FILES = \
browser_thumbnails_redirect.js \
browser_thumbnails_storage.js \
browser_thumbnails_bug726727.js \
browser_thumbnails_bug753755.js \
head.js \
background_red.html \
background_red_redirect.sjs \

View File

@ -0,0 +1,15 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Make sure that PageThumbsStorage.getFileForURL(url) doesn't implicitly
* create the file's parent path.
*/
function runTests() {
let url = "http://non.existant.url/";
let file = PageThumbsStorage.getFileForURL(url);
ok(!file.exists() && !file.parent.exists(), "file and path don't exist");
let file = PageThumbsStorage.getFileForURL(url, {createPath: true});
ok(!file.exists() && file.parent.exists(), "path exists, file doesn't");
}

View File

@ -18,7 +18,7 @@ XPCOMUtils.defineLazyGetter(this, "Sanitizer", function () {
* be removed when the user sanitizes their history.
*/
function runTests() {
clearHistory();
yield clearHistory();
// create a thumbnail
yield addTab(URL);
@ -72,7 +72,7 @@ function clearHistory(aUseRange) {
executeSoon(function () {
if (PageThumbsStorage.getFileForURL(URL).exists())
clearHistory(aFile, aUseRange);
clearHistory(aUseRange);
else
next();
});

View File

@ -29,9 +29,12 @@ let TestRunner = {
*/
run: function () {
waitForExplicitFinish();
this._iter = runTests();
this.next();
if (this._iter)
this.next();
else
finish();
},
/**

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

View File

@ -544,7 +544,7 @@ toolbar[mode="icons"] #forward-button {
}
#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #forward-button {
mask: url(chrome://browser/content/browser.xul#pinstripe-keyhole-forward-mask);
clip-path: url(chrome://browser/content/browser.xul#pinstripe-keyhole-forward-clip-path);
}
@conditionalForwardWithUrlbar@ > #forward-button:not(:-moz-lwtheme) {
@ -951,7 +951,7 @@ toolbar[mode="icons"] #zoom-in-button {
}
@conditionalForwardWithUrlbar@[forwarddisabled] + #urlbar-container {
mask: url("chrome://browser/content/browser.xul#pinstripe-urlbar-back-button-mask");
clip-path: url("chrome://browser/content/browser.xul#pinstripe-urlbar-back-button-clip-path");
}
@conditionalForwardWithUrlbar@[forwarddisabled] + #urlbar-container > #urlbar {
@ -970,7 +970,7 @@ toolbar[mode="icons"] #zoom-in-button {
@conditionalForwardWithUrlbar@ + #urlbar-container:-moz-locale-dir(rtl),
@conditionalForwardWithUrlbar@ + #urlbar-container > #urlbar:-moz-locale-dir(rtl) {
/* let pinstripe-urlbar-back-button-mask clip the urlbar's right side for RTL */
/* let pinstripe-urlbar-back-button-clip-path clip the urlbar's right side for RTL */
-moz-transform: scaleX(-1);
}
@ -1806,22 +1806,22 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
@TABSONTOP_TAB_STACK@ > .tab-background > .tab-background-start:-moz-locale-dir(ltr),
@TABSONTOP_TAB_STACK@ > .tab-background > .tab-background-end:-moz-locale-dir(rtl) {
mask: url(chrome://browser/content/browser.xul#pinstripe-tab-ontop-left-curve-mask);
clip-path: url(chrome://browser/content/browser.xul#pinstripe-tab-ontop-left-curve-clip-path);
}
@TABSONTOP_TAB_STACK@ > .tab-background > .tab-background-end:-moz-locale-dir(ltr),
@TABSONTOP_TAB_STACK@ > .tab-background > .tab-background-start:-moz-locale-dir(rtl) {
mask: url(chrome://browser/content/browser.xul#pinstripe-tab-ontop-right-curve-mask);
clip-path: url(chrome://browser/content/browser.xul#pinstripe-tab-ontop-right-curve-clip-path);
}
@TABSONBOTTOM_TAB_STACK@ > .tab-background > .tab-background-start:-moz-locale-dir(ltr),
@TABSONBOTTOM_TAB_STACK@ > .tab-background > .tab-background-end:-moz-locale-dir(rtl) {
mask: url(chrome://browser/content/browser.xul#pinstripe-tab-onbottom-left-curve-mask);
clip-path: url(chrome://browser/content/browser.xul#pinstripe-tab-onbottom-left-curve-clip-path);
}
@TABSONBOTTOM_TAB_STACK@ > .tab-background > .tab-background-end:-moz-locale-dir(ltr),
@TABSONBOTTOM_TAB_STACK@ > .tab-background > .tab-background-start:-moz-locale-dir(rtl) {
mask: url(chrome://browser/content/browser.xul#pinstripe-tab-onbottom-right-curve-mask);
clip-path: url(chrome://browser/content/browser.xul#pinstripe-tab-onbottom-right-curve-clip-path);
}
.tab-background-start[selected="true"]:not(:-moz-lwtheme),

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

View File

@ -817,7 +817,7 @@ toolbar[mode=full] .toolbarbutton-1 > .toolbarbutton-menubutton-button {
border-color: hsla(210,54%,20%,.3) hsla(210,54%,20%,.35) hsla(210,54%,20%,.4);
box-shadow: 0 1px 1px hsla(210,54%,20%,.1) inset,
0 0 1px hsla(210,54%,20%,.2) inset,
/* allows winstripe-keyhole-forward-mask to be used for non-hover as well as hover: */
/* allows winstripe-keyhole-forward-clip-path to be used for non-hover as well as hover: */
0 1px 0 hsla(210,54%,20%,0),
0 0 2px hsla(210,54%,20%,0);
text-shadow: none;
@ -896,7 +896,7 @@ toolbar[mode=full] .toolbarbutton-1 > .toolbarbutton-menubutton-button {
@conditionalForwardWithUrlbar@ > #forward-button > .toolbarbutton-icon {
/*mask: url(keyhole-forward-mask.svg#mask); XXX: this regresses twinopen */
mask: url(chrome://browser/content/browser.xul#winstripe-keyhole-forward-mask);
clip-path: url(chrome://browser/content/browser.xul#winstripe-keyhole-forward-clip-path);
-moz-margin-start: -6px !important;
border-left-style: none;
border-radius: 0;
@ -1258,7 +1258,7 @@ toolbar[mode=full] .toolbarbutton-1 > .toolbarbutton-menubutton-button {
}
@conditionalForwardWithUrlbar@[forwarddisabled] + #urlbar-container {
mask: url("chrome://browser/content/browser.xul#winstripe-urlbar-back-button-mask");
clip-path: url("chrome://browser/content/browser.xul#winstripe-urlbar-back-button-clip-path");
}
@conditionalForwardWithUrlbar@[forwarddisabled] + #urlbar-container > #urlbar {

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

@ -362,7 +362,7 @@ browser.jar:
skin/classic/aero/browser/devtools/layout-background.png (devtools/layout-background.png)
skin/classic/aero/browser/devtools/layoutview.css (devtools/layoutview.css)
skin/classic/aero/browser/devtools/layout-buttons.png (devtools/layout-buttons.png)
skin/classic/aera/browser/devtools/inspector-option-icon.png (devtools/inspector-option-icon.png)
skin/classic/aero/browser/devtools/inspector-option-icon.png (devtools/inspector-option-icon.png)
#ifdef MOZ_SERVICES_SYNC
skin/classic/aero/browser/sync-throbber.png
skin/classic/aero/browser/sync-16.png

View File

@ -479,7 +479,7 @@ class ShutdownLeakLogger(object):
self.currentTest = {"fileName": fileName, "windows": set(), "docShells": set()}
elif line.startswith("INFO TEST-END"):
# don't track a test if no windows or docShells leaked
if self.currentTest["windows"] or self.currentTest["docShells"]:
if self.currentTest and (self.currentTest["windows"] or self.currentTest["docShells"]):
self.tests.append(self.currentTest)
self.currentTest = None
elif line.startswith("INFO TEST-START | Shutdown"):

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

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

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

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*)
@ -8013,7 +8018,7 @@ dnl ========================================================
if test -z "$SKIP_PATH_CHECKS"; then
if test -z "${GLIB_CFLAGS}" -o -z "${GLIB_LIBS}" ; then
if test "$MOZ_ENABLE_GTK2" -o "$MOZ_ENABLE_QT" -o "$USE_ELF_DYNSTR_GC" ; then
if test "$MOZ_ENABLE_GTK2" -o "$USE_ELF_DYNSTR_GC" ; then
PKG_CHECK_MODULES(GLIB, glib-2.0 >= 1.3.7 gobject-2.0)
fi
fi
@ -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

@ -107,6 +107,6 @@ load 713417.html
load 713417-2.html
load 715056.html
load 741163-1.html
load 752226-1.html
load 752226-2.html
asserts(0-1) load 752226-1.html
asserts(0-1) load 752226-2.html
HTTP(..) load xhr_abortinprogress.html

View File

@ -1669,11 +1669,4 @@ extern const nsIID kThisPtrOffsetsSID;
NS_DEFINE_STATIC_IID_ACCESSOR(nsINode, NS_INODE_IID)
#define NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER \
nsContentUtils::TraceWrapper(tmp, aCallback, aClosure);
#define NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER \
nsContentUtils::ReleaseWrapper(s, tmp);
#endif /* nsINode_h___ */

View File

@ -607,16 +607,7 @@ nsDOMMemoryFile::GetInternalStream(nsIInputStream **aStream)
DOMCI_DATA(FileList, nsDOMFileList)
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMFileList)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMFileList)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMFileList)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsDOMFileList)
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(nsDOMFileList)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMFileList)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY

View File

@ -58,16 +58,7 @@ nsDOMTokenList::nsDOMTokenList(nsGenericElement *aElement, nsIAtom* aAttrAtom)
nsDOMTokenList::~nsDOMTokenList() { }
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMTokenList)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMTokenList)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMTokenList)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsDOMTokenList)
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(nsDOMTokenList)
DOMCI_DATA(DOMTokenList, nsDOMTokenList)

View File

@ -1717,17 +1717,9 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(nsChildContentList)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsChildContentList)
// If nsChildContentList is changed so that any additional fields are
// traversed by the cycle collector, then CAN_SKIP must be updated.
NS_IMPL_CYCLE_COLLECTION_CLASS(nsChildContentList)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsChildContentList)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsChildContentList)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsChildContentList)
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_TRACE_END
// traversed by the cycle collector, then CAN_SKIP must be updated to
// check that the additional fields are null.
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(nsChildContentList)
// nsChildContentList only ever has a single child, its wrapper, so if
// the wrapper is black, the list can't be part of a garbage cycle.
@ -2141,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;
}
@ -2174,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

@ -1403,19 +1403,7 @@ NAME_NOT_SUPPORTED(WebGLRenderbuffer)
// WebGLExtension
NS_IMPL_CYCLE_COLLECTION_CLASS(WebGLExtension)
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(WebGLExtension)
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(WebGLExtension)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(WebGLExtension)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLExtension)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebGLExtension)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY

View File

@ -84,18 +84,7 @@ nsPaintRequest::GetReason(nsAString& aResult)
DOMCI_DATA(PaintRequestList, nsPaintRequestList)
NS_IMPL_CYCLE_COLLECTION_CLASS(nsPaintRequestList)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsPaintRequestList)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mParent)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsPaintRequestList)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParent)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsPaintRequestList)
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(nsPaintRequestList, mParent)
NS_INTERFACE_TABLE_HEAD(nsPaintRequestList)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY

View File

@ -103,18 +103,7 @@ nsClientRect::GetHeight(float* aResult)
DOMCI_DATA(ClientRectList, nsClientRectList)
NS_IMPL_CYCLE_COLLECTION_CLASS(nsClientRectList)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsClientRectList)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mParent)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsClientRectList)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParent)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsClientRectList)
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(nsClientRectList, mParent)
NS_INTERFACE_TABLE_HEAD(nsClientRectList)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY

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

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

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

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

@ -1827,13 +1827,11 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
nsWindowSH::InvalidateGlobalScopePolluter(cx, currentInner->mJSObject);
}
// The API we're really looking for here is to go clear all of the
// Xray wrappers associated with our outer window. However, we
// don't expose that API because the implementation would be
// identical to that of JS_TransplantObject, so we just call that
// instead.
// We're reusing the inner window, but this still counts as a navigation,
// so all expandos and such defined on the outer window should go away. Force
// all Xray wrappers to be recomputed.
xpc_UnmarkGrayObject(mJSObject);
if (!JS_TransplantObject(cx, mJSObject, mJSObject)) {
if (!JS_RefreshCrossCompartmentWrappers(cx, mJSObject)) {
return NS_ERROR_FAILURE;
}
} else {
@ -5330,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

@ -246,4 +246,40 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsWrapperCache, NS_WRAPPERCACHE_IID)
return NS_OK; \
}
// Cycle collector macros for wrapper caches.
#define NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER \
nsContentUtils::TraceWrapper(tmp, aCallback, aClosure);
#define NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER \
nsContentUtils::ReleaseWrapper(s, tmp);
#define NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(_class) \
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(_class) \
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER \
NS_IMPL_CYCLE_COLLECTION_TRACE_END
#define NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(_class) \
NS_IMPL_CYCLE_COLLECTION_CLASS(_class) \
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class) \
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER \
NS_IMPL_CYCLE_COLLECTION_UNLINK_END \
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class) \
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS \
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END \
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(_class)
#define NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(_class, _field) \
NS_IMPL_CYCLE_COLLECTION_CLASS(_class) \
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class) \
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(_field) \
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER \
NS_IMPL_CYCLE_COLLECTION_UNLINK_END \
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class) \
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(_field) \
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS \
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END \
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(_class)
#endif /* nsWrapperCache_h___ */

View File

@ -11,7 +11,7 @@ VPATH = \
include $(DEPTH)/config/autoconf.mk
ifeq ($(MOZ_BUILD_APP),b2g)
ifeq ($(MOZ_BUILD_APP), $(filter $(MOZ_BUILD_APP),b2g mail))
VPATH += $(srcdir)/fallback
endif
@ -24,7 +24,7 @@ EXTRA_COMPONENTS = \
ContactManager.manifest \
$(NULL)
ifeq ($(MOZ_BUILD_APP),b2g)
ifeq ($(MOZ_BUILD_APP), $(filter $(MOZ_BUILD_APP),b2g mail))
EXTRA_JS_MODULES = \
ContactService.jsm \
ContactDB.jsm \

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

View File

@ -90,7 +90,7 @@ CheckOverlapAndMergeObjectStores(nsTArray<nsString>& aLockedStores,
BEGIN_INDEXEDDB_NAMESPACE
class FinishTransactionRunnable : public nsIRunnable
class FinishTransactionRunnable MOZ_FINAL : public nsIRunnable
{
public:
NS_DECL_ISUPPORTS

View File

@ -91,7 +91,7 @@ public:
bool HasTransactionsForDatabase(IDBDatabase* aDatabase);
protected:
class TransactionQueue : public nsIRunnable
class TransactionQueue MOZ_FINAL : public nsIRunnable
{
public:
NS_DECL_ISUPPORTS

View File

@ -154,22 +154,31 @@ static dom::ConstantSpec gLibcProperties[] =
INT_CONSTANT(EINVAL),
INT_CONSTANT(EIO),
INT_CONSTANT(EISDIR),
#if defined(ELOOP) // not defined with VC9
INT_CONSTANT(ELOOP),
#endif // defined(ELOOP)
INT_CONSTANT(EMFILE),
INT_CONSTANT(ENAMETOOLONG),
INT_CONSTANT(ENFILE),
INT_CONSTANT(ELOOP),
INT_CONSTANT(ENOENT),
INT_CONSTANT(ENOMEM),
INT_CONSTANT(ENOSPC),
INT_CONSTANT(ENOTDIR),
INT_CONSTANT(ENXIO),
#if defined(EOPNOTSUPP) // not defined with VC 9
INT_CONSTANT(EOPNOTSUPP),
#endif // defined(EOPNOTSUPP)
#if defined(EOVERFLOW) // not defined with VC 9
INT_CONSTANT(EOVERFLOW),
#endif // defined(EOVERFLOW)
INT_CONSTANT(EPERM),
INT_CONSTANT(ERANGE),
#if defined(ETIMEDOUT) // not defined with VC 9
INT_CONSTANT(ETIMEDOUT),
#endif // defined(ETIMEDOUT)
#if defined(EWOULDBLOCK) // not defined with VC 9
INT_CONSTANT(EWOULDBLOCK),
#endif // defined(EWOULDBLOCK)
INT_CONSTANT(EXDEV),
PROP_END

View File

@ -166,6 +166,8 @@ AudioManager::SetPhoneState(PRInt32 aState)
if (AudioSystem::setPhoneState(aState)) {
return NS_ERROR_FAILURE;
}
mPhoneState = aState;
return NS_OK;
}

View File

@ -25,6 +25,7 @@ const RIL_IPC_MSG_NAMES = [
"RIL:DataInfoChanged",
"RIL:EnumerateCalls",
"RIL:CallStateChanged",
"RIL:CallError",
];
const kVoiceChangedTopic = "mobile-connection-voice-changed";
@ -231,22 +232,26 @@ RILContentHelper.prototype = {
case "RIL:CallStateChanged":
this._deliverTelephonyCallback("callStateChanged",
[msg.json.callIndex, msg.json.state,
msg.json.number]);
msg.json.number, msg.json.isActive]);
break;
case "RIL:CallError":
this._deliverTelephonyCallback("notifyError",
[msg.json.callIndex,
msg.json.error]);
break;
}
},
handleEnumerateCalls: function handleEnumerateCalls(message) {
debug("handleEnumerateCalls: " + JSON.stringify(message));
handleEnumerateCalls: function handleEnumerateCalls(calls) {
debug("handleEnumerateCalls: " + JSON.stringify(calls));
let callback = this._enumerationTelephonyCallbacks.shift();
let calls = message.calls;
let activeCallIndex = message.activeCallIndex;
for (let i in calls) {
let call = calls[i];
let keepGoing;
try {
keepGoing =
callback.enumerateCallState(call.callIndex, call.state, call.number,
call.callIndex == activeCallIndex);
call.isActive);
} catch (e) {
debug("callback handler for 'enumerateCallState' threw an " +
" exception: " + e);

View File

@ -288,6 +288,9 @@ RadioInterfaceLayer.prototype = {
// This one will handle its own notifications.
this.handleEnumerateCalls(message.calls);
break;
case "callError":
this.handleCallError(message);
break;
case "voiceregistrationstatechange":
this.updateVoiceConnection(message);
break;
@ -437,28 +440,29 @@ RadioInterfaceLayer.prototype = {
/**
* Track the active call and update the audio system as its state changes.
*
* XXX Needs some more work to support hold/resume.
*/
_activeCall: null,
updateCallAudioState: function updateCallAudioState() {
if (!this._activeCall) {
// Disable audio.
gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_NORMAL;
debug("No active call, put audio system into PHONE_STATE_NORMAL.");
debug("No active call, put audio system into PHONE_STATE_NORMAL: "
+ gAudioManager.phoneState);
return;
}
switch (this._activeCall.state) {
case nsIRadioInterfaceLayer.CALL_STATE_INCOMING:
gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_RINGTONE;
debug("Incoming call, put audio system into PHONE_STATE_RINGTONE.");
debug("Incoming call, put audio system into PHONE_STATE_RINGTONE: "
+ gAudioManager.phoneState);
break;
case nsIRadioInterfaceLayer.CALL_STATE_DIALING: // Fall through...
case nsIRadioInterfaceLayer.CALL_STATE_CONNECTED:
gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_IN_CALL;
gAudioManager.setForceForUse(nsIAudioManager.USE_COMMUNICATION,
nsIAudioManager.FORCE_NONE);
debug("Active call, put audio system into PHONE_STATE_IN_CALL.");
debug("Active call, put audio system into PHONE_STATE_IN_CALL: "
+ gAudioManager.phoneState);
break;
}
},
@ -470,11 +474,12 @@ RadioInterfaceLayer.prototype = {
handleCallStateChange: function handleCallStateChange(call) {
debug("handleCallStateChange: " + JSON.stringify(call));
call.state = convertRILCallState(call.state);
if (call.state == nsIRadioInterfaceLayer.CALL_STATE_DIALING ||
call.state == nsIRadioInterfaceLayer.CALL_STATE_ALERTING ||
call.state == nsIRadioInterfaceLayer.CALL_STATE_CONNECTED) {
// This is now the active call.
if (call.isActive) {
this._activeCall = call;
} else if (this._activeCall &&
this._activeCall.callIndex == call.callIndex) {
// Previously active call is not active now.
this._activeCall = null;
}
this.updateCallAudioState();
ppmm.sendAsyncMessage("RIL:CallStateChanged", call);
@ -485,7 +490,7 @@ RadioInterfaceLayer.prototype = {
*/
handleCallDisconnected: function handleCallDisconnected(call) {
debug("handleCallDisconnected: " + JSON.stringify(call));
if (this._activeCall && this._activeCall.callIndex == call.callIndex) {
if (call.isActive) {
this._activeCall = null;
}
this.updateCallAudioState();
@ -498,12 +503,17 @@ RadioInterfaceLayer.prototype = {
*/
handleEnumerateCalls: function handleEnumerateCalls(calls) {
debug("handleEnumerateCalls: " + JSON.stringify(calls));
let activeCallIndex = this._activeCall ? this._activeCall.callIndex : -1;
for (let i in calls) {
calls[i].state = convertRILCallState(calls[i].state);
}
ppmm.sendAsyncMessage("RIL:EnumerateCalls",
{calls: calls, activeCallIndex: activeCallIndex});
ppmm.sendAsyncMessage("RIL:EnumerateCalls", calls);
},
/**
* Handle call error.
*/
handleCallError: function handleCallError(message) {
ppmm.sendAsyncMessage("RIL:CallError", message);
},
portAddressedSmsApps: null,
@ -738,6 +748,10 @@ RadioInterfaceLayer.prototype = {
nsIAudioManager.PHONE_STATE_IN_COMMUNICATION :
nsIAudioManager.PHONE_STATE_IN_CALL; //XXX why is this needed?
gAudioManager.microphoneMuted = value;
if (!this._activeCall) {
gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_NORMAL;
}
},
get speakerEnabled() {
@ -752,6 +766,10 @@ RadioInterfaceLayer.prototype = {
let force = value ? nsIAudioManager.FORCE_SPEAKER :
nsIAudioManager.FORCE_NONE;
gAudioManager.setForceForUse(nsIAudioManager.USE_COMMUNICATION, force);
if (!this._activeCall) {
gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_NORMAL;
}
},
/**

View File

@ -44,7 +44,7 @@ interface nsIDOMMozMobileConnectionInfo;
interface nsIDOMDOMRequest;
interface nsIDOMWindow;
[scriptable, uuid(03eafd60-d138-4f09-81b4-90cd4996b3c7)]
[scriptable, uuid(c14c71b8-afba-403b-8320-94593de9380f)]
interface nsIRILTelephonyCallback : nsISupports
{
/**
@ -56,10 +56,13 @@ interface nsIRILTelephonyCallback : nsISupports
* One of the nsIRadioInterfaceLayer::CALL_STATE_* values.
* @param number
* Number of the other party.
* @param isActive
* Indicates whether this call is the currently active one.
*/
void callStateChanged(in unsigned long callIndex,
in unsigned short callState,
in AString number);
in AString number,
in boolean isActive);
/**
* Called when nsIRILContentHelper is asked to enumerate the current
@ -81,6 +84,17 @@ interface nsIRILTelephonyCallback : nsISupports
in unsigned short callState,
in AString number,
in boolean isActive);
/**
* Called when RIL error occurs.
*
* @param callIndex
* Call identifier assigned by the RIL. -1 if no connection
* @param error
* Error from RIL.
*/
void notifyError(in long callIndex,
in AString error);
};
[scriptable, uuid(66a55943-e63b-4731-aece-9c04bfc14019)]

View File

@ -1352,6 +1352,17 @@ const GECKO_NETWORK_STATE_SUSPENDED = 2;
const GECKO_NETWORK_STATE_DISCONNECTING = 3;
const GECKO_NETWORK_STATE_DISCONNECTED = 4;
const CALL_FAIL_UNOBTAINABLE_NUMBER = 1;
const CALL_FAIL_NORMAL = 16;
const CALL_FAIL_BUSY = 17;
const CALL_FAIL_CONGESTION = 34;
const CALL_FAIL_ACM_LIMIT_EXCEEDED = 68;
const CALL_FAIL_CALL_BARRED = 240;
const CALL_FAIL_FDN_BLOCKED = 241;
const CALL_FAIL_IMSI_UNKNOWN_IN_VLR = 242;
const CALL_FAIL_IMEI_NOT_ACCEPTED = 243;
const CALL_FAIL_ERROR_UNSPECIFIED = 0xffff;
// Other Gecko-specific constants
const GECKO_RADIOSTATE_UNAVAILABLE = null;
const GECKO_RADIOSTATE_OFF = "off";
@ -1365,6 +1376,29 @@ const GECKO_CARDSTATE_NETWORK_LOCKED = "network_locked";
const GECKO_CARDSTATE_NOT_READY = null;
const GECKO_CARDSTATE_READY = "ready";
const GECKO_CALL_ERROR_BAD_NUMBER = "BadNumberError";
const GECKO_CALL_ERROR_NORMAL_CALL_CLEARING = "NormalCallClearingError";
const GECKO_CALL_ERROR_BUSY = "BusyError";
const GECKO_CALL_ERROR_CONGESTION = "CongestionError";
const GECKO_CALL_ERROR_INCOMING_CALL_EXCEEDED = "IncomingCallExceededError";
const GECKO_CALL_ERROR_BARRED = "BarredError";
const GECKO_CALL_ERROR_FDN_BLOCKED = "FDNBlockedError";
const GECKO_CALL_ERROR_SUBSCRIBER_UNKNOWN = "SubscriberUnknownError";
const GECKO_CALL_ERROR_DEVICE_NOT_ACCEPTED = "DeviceNotAcceptedError";
const GECKO_CALL_ERROR_UNSPECIFIED = "UnspecifiedError";
const RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR = {};
RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_UNOBTAINABLE_NUMBER] = GECKO_CALL_ERROR_BAD_NUMBER;
RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_NORMAL] = GECKO_CALL_ERROR_NORMAL_CALL_CLEARING;
RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_BUSY] = GECKO_CALL_ERROR_BUSY;
RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_CONGESTION] = GECKO_CALL_ERROR_CONGESTION;
RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_ACM_LIMIT_EXCEEDED] = GECKO_CALL_ERROR_INCOMING_CALL_EXCEEDED;
RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_CALL_BARRED] = GECKO_CALL_ERROR_BARRED;
RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_FDN_BLOCKED] = GECKO_CALL_ERROR_FDN_BLOCKED;
RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_IMSI_UNKNOWN_IN_VLR] = GECKO_CALL_ERROR_SUBSCRIBER_UNKNOWN;
RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_IMEI_NOT_ACCEPTED] = GECKO_CALL_ERROR_DEVICE_NOT_ACCEPTED;
RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[CALL_FAIL_ERROR_UNSPECIFIED] = GECKO_CALL_ERROR_UNSPECIFIED;
const GECKO_RADIO_TECH = [
null,
"gprs",

View File

@ -299,15 +299,7 @@ let Buf = {
// Strings are \0\0 delimited, but that isn't part of the length. And
// if the string length is even, the delimiter is two characters wide.
// It's insane, I know.
let delimiter = this.readUint16();
if (!(string_len & 1)) {
delimiter |= this.readUint16();
}
if (DEBUG) {
if (delimiter != 0) {
debug("Something's wrong, found string delimiter: " + delimiter);
}
}
this.readStringDelimiter(string_len);
return s;
},
@ -319,6 +311,18 @@ let Buf = {
}
return strings;
},
readStringDelimiter: function readStringDelimiter(length) {
let delimiter = this.readUint16();
if (!(length & 1)) {
delimiter |= this.readUint16();
}
if (DEBUG) {
if (delimiter != 0) {
debug("Something's wrong, found string delimiter: " + delimiter);
}
}
},
readParcelSize: function readParcelSize() {
return this.readUint8Unchecked() << 24 |
@ -363,10 +367,7 @@ let Buf = {
// Strings are \0\0 delimited, but that isn't part of the length. And
// if the string length is even, the delimiter is two characters wide.
// It's insane, I know.
this.writeUint16(0);
if (!(value.length & 1)) {
this.writeUint16(0);
}
this.writeStringDelimiter(value.length);
},
writeStringList: function writeStringList(strings) {
@ -375,6 +376,13 @@ let Buf = {
this.writeString(strings[i]);
}
},
writeStringDelimiter: function writeStringDelimiter(length) {
this.writeUint16(0);
if (!(length & 1)) {
this.writeUint16(0);
}
},
writeParcelSize: function writeParcelSize(value) {
/**
@ -644,10 +652,15 @@ let RIL = {
networkSelectionMode: null,
/**
* Active calls
* Valid calls.
*/
currentCalls: {},
/**
* Current calls length.
*/
currentCallsLength: null,
/**
* Existing data calls.
*/
@ -899,15 +912,7 @@ let RIL = {
return;
}
this.iccInfo.MSISDN = GsmPDUHelper.readAddress(len);
let delimiter = Buf.readUint16();
if (!(length & 1)) {
delimiter |= Buf.readUint16();
}
if (DEBUG) {
if (delimiter != 0) {
debug("Something's wrong, found string delimiter: " + delimiter);
}
}
Buf.readStringDelimiter(length);
if (DEBUG) debug("MSISDN: " + this.iccInfo.MSISDN);
if (this.iccInfo.MSISDN) {
@ -938,15 +943,7 @@ let RIL = {
// Each octet is encoded into two chars.
let len = length / 2;
this.iccInfo.AD = GsmPDUHelper.readHexOctetArray(len);
let delimiter = Buf.readUint16();
if (!(length & 1)) {
delimiter |= Buf.readUint16();
}
if (DEBUG) {
if (delimiter != 0) {
debug("Something's wrong, found string delimiter: " + delimiter);
}
}
Buf.readStringDelimiter(length);
if (DEBUG) {
let str = "";
@ -1005,15 +1002,7 @@ let RIL = {
// Each octet is encoded into two chars.
let len = length / 2;
this.iccInfo.UST = GsmPDUHelper.readHexOctetArray(len);
let delimiter = Buf.readUint16();
if (!(length & 1)) {
delimiter |= Buf.readUint16();
}
if (DEBUG) {
if (delimiter != 0) {
debug("Something's wrong, found string delimiter: " + delimiter);
}
}
Buf.readStringDelimiter(length);
if (DEBUG) {
let str = "";
@ -1460,8 +1449,8 @@ let RIL = {
/**
* Get failure casue code for the most recently failed PDP context.
*/
getFailCauseCode: function getFailCauseCode() {
Buf.simpleRequest(REQUEST_LAST_CALL_FAIL_CAUSE);
getFailCauseCode: function getFailCauseCode(options) {
Buf.simpleRequest(REQUEST_LAST_CALL_FAIL_CAUSE, options);
},
/**
@ -1605,15 +1594,7 @@ let RIL = {
// Length of a record, data[14]
let recordSize = GsmPDUHelper.readHexOctet();
let delimiter = Buf.readUint16();
if (!(length & 1)) {
delimiter |= Buf.readUint16();
}
if (DEBUG) {
if (delimiter != 0) {
debug("Something's wrong, found string delimiter: " + delimiter);
}
}
Buf.readStringDelimiter(length);
switch (options.type) {
case EF_TYPE_LINEAR_FIXED:
@ -1749,12 +1730,19 @@ let RIL = {
},
/**
* Helpers for processing call state.
* Helpers for processing call state and handle the active call.
*/
_processCalls: function _processCalls(newCalls) {
// Go through the calls we currently have on file and see if any of them
// changed state. Remove them from the newCalls map as we deal with them
// so that only new calls remain in the map after we're done.
let lastCallsLength = this.currentCallsLength;
if (newCalls) {
this.currentCallsLength = newCalls.length;
} else {
this.currentCallsLength = 0;
}
for each (let currentCall in this.currentCalls) {
let newCall;
if (newCalls) {
@ -1764,9 +1752,12 @@ let RIL = {
if (newCall) {
// Call is still valid.
if (newCall.state != currentCall.state) {
// State has changed.
if (newCall.state != currentCall.state ||
this.currentCallsLength != lastCallsLength) {
// State has changed. Active call may have changed as valid
// calls change.
currentCall.state = newCall.state;
currentCall.isActive = this._isActiveCall(currentCall.state);
this._handleChangedCallState(currentCall);
}
} else {
@ -1788,6 +1779,7 @@ let RIL = {
}
// Add to our map.
this.currentCalls[newCall.callIndex] = newCall;
newCall.isActive = this._isActiveCall(newCall.state);
this._handleChangedCallState(newCall);
}
}
@ -1809,6 +1801,24 @@ let RIL = {
this.sendDOMMessage(message);
},
_isActiveCall: function _isActiveCall(callState) {
switch (callState) {
case CALL_STATE_INCOMING:
case CALL_STATE_DIALING:
case CALL_STATE_ALERTING:
case CALL_STATE_ACTIVE:
return true;
case CALL_STATE_HOLDING:
return false;
case CALL_STATE_WAITING:
if (this.currentCallsLength == 1) {
return true;
} else {
return false;
}
}
},
_processDataCallList: function _processDataCallList(datacalls) {
for each (let currentDataCall in this.currentDataCalls) {
let updatedDataCall;
@ -1882,15 +1892,7 @@ let RIL = {
if (DEBUG) debug(message);
// Read string delimiters. See Buf.readString().
let delimiter = Buf.readUint16();
if (!(messageStringLength & 1)) {
delimiter |= Buf.readUint16();
}
if (DEBUG) {
if (delimiter != 0) {
debug("Something's wrong, found string delimiter: " + delimiter);
}
}
Buf.readStringDelimiter(length);
return message;
},
@ -2254,11 +2256,21 @@ RIL[REQUEST_GET_CURRENT_CALLS] = function REQUEST_GET_CURRENT_CALLS(length, opti
};
}
call.isActive = false;
calls[call.callIndex] = call;
}
calls.length = calls_length;
this._processCalls(calls);
};
RIL[REQUEST_DIAL] = null;
RIL[REQUEST_DIAL] = function REQUEST_DIAL(length, options) {
if (options.rilRequestError) {
// The connection is not established yet.
options.callIndex = -1;
this.getFailCauseCode(options);
return;
}
};
RIL[REQUEST_GET_IMSI] = function REQUEST_GET_IMSI(length, options) {
if (options.rilRequestError) {
return;
@ -2306,7 +2318,20 @@ RIL[REQUEST_SWITCH_HOLDING_AND_ACTIVE] = function REQUEST_SWITCH_HOLDING_AND_ACT
};
RIL[REQUEST_CONFERENCE] = null;
RIL[REQUEST_UDUB] = null;
RIL[REQUEST_LAST_CALL_FAIL_CAUSE] = null;
RIL[REQUEST_LAST_CALL_FAIL_CAUSE] = function REQUEST_LAST_CALL_FAIL_CAUSE(length, options) {
let num = 0;
if (length) {
num = Buf.readUint32();
}
if (!num) {
return;
}
let failCause = Buf.readUint32();
options.type = "callError";
options.error = RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[failCause];
this.sendDOMMessage(options);
};
RIL[REQUEST_SIGNAL_STRENGTH] = function REQUEST_SIGNAL_STRENGTH(length, options) {
if (options.rilRequestError) {
return;
@ -3004,26 +3029,6 @@ let GsmPDUHelper = {
return number;
},
/**
* Read a string from Buf and convert it to BCD
*
* @return the decimal as a number.
*/
readStringAsBCD: function readStringAsBCD() {
let length = Buf.readUint32();
let bcd = this.readSwappedNibbleBCD(length / 2);
let delimiter = Buf.readUint16();
if (!(length & 1)) {
delimiter |= Buf.readUint16();
}
if (DEBUG) {
if (delimiter != 0) {
debug("Something's wrong, found string delimiter: " + delimiter);
}
}
return bcd;
},
/**
* Write numerical data as swapped nibble BCD.
*
@ -3476,7 +3481,7 @@ let GsmPDUHelper = {
encoding = PDU_DCS_MSG_CODING_16BITS_ALPHABET;
break;
case 0x30:
if (!dcs & 0x04) {
if (dcs & 0x04) {
encoding = PDU_DCS_MSG_CODING_8BITS_ALPHABET;
}
break;

View File

@ -404,7 +404,7 @@ NS_IMPL_EVENT_HANDLER(Telephony, callschanged)
NS_IMETHODIMP
Telephony::CallStateChanged(PRUint32 aCallIndex, PRUint16 aCallState,
const nsAString& aNumber)
const nsAString& aNumber, bool aIsActive)
{
NS_ASSERTION(aCallIndex != kOutgoingPlaceholderCallIndex,
"This should never happen!");
@ -445,7 +445,7 @@ Telephony::CallStateChanged(PRUint32 aCallIndex, PRUint16 aCallState,
modifiedCall->ChangeState(aCallState);
// See if this should replace our current active call.
if (aCallState == nsIRadioInterfaceLayer::CALL_STATE_CONNECTED) {
if (aIsActive) {
mActiveCall = modifiedCall;
}
@ -500,6 +500,31 @@ Telephony::EnumerateCallState(PRUint32 aCallIndex, PRUint16 aCallState,
return NS_OK;
}
NS_IMETHODIMP
Telephony::NotifyError(PRInt32 aCallIndex,
const nsAString& aError)
{
PRInt32 index = -1;
PRInt32 length = mCalls.Length();
// The connection is not established yet, remove the latest call object
if (aCallIndex == -1) {
if (length > 0) {
index = length - 1;
}
} else {
if (aCallIndex < 0 || aCallIndex >= length) {
return NS_ERROR_INVALID_ARG;
}
index = aCallIndex;
}
if (index != -1) {
mCalls[index]->NotifyError(aError);
}
return NS_OK;
}
nsresult
NS_NewTelephony(nsPIDOMWindow* aWindow, nsIDOMTelephony** aTelephony)
{

View File

@ -43,6 +43,7 @@
#include "CallEvent.h"
#include "Telephony.h"
#include "DOMError.h"
USING_TELEPHONY_NAMESPACE
@ -62,6 +63,7 @@ TelephonyCall::Create(Telephony* aTelephony, const nsAString& aNumber,
call->mTelephony = aTelephony;
call->mNumber = aNumber;
call->mCallIndex = aCallIndex;
call->mError = nsnull;
call->ChangeStateInternal(aCallState, false);
@ -150,6 +152,27 @@ TelephonyCall::ChangeStateInternal(PRUint16 aCallState, bool aFireEvents)
}
}
void
TelephonyCall::NotifyError(const nsAString& aError)
{
// Set the error string
NS_ASSERTION(!mError, "Already have an error?");
mError = DOMError::CreateWithName(aError);
// Do the state transitions
ChangeStateInternal(nsIRadioInterfaceLayer::CALL_STATE_DISCONNECTED, true);
// Notify the error event
nsRefPtr<CallEvent> event = CallEvent::Create(this);
NS_ASSERTION(event, "This should never fail!");
if (NS_FAILED(event->Dispatch(ToIDOMEventTarget(),
NS_LITERAL_STRING("error")))) {
NS_WARNING("Failed to dispatch error event!");
}
}
NS_IMPL_CYCLE_COLLECTION_CLASS(TelephonyCall)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(TelephonyCall,
@ -167,6 +190,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(TelephonyCall,
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(holding)
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(held)
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(resuming)
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(error)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(TelephonyCall,
@ -183,6 +207,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(TelephonyCall,
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(holding)
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(held)
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(resuming)
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(error)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TelephonyCall)
@ -209,6 +234,13 @@ TelephonyCall::GetState(nsAString& aState)
return NS_OK;
}
NS_IMETHODIMP
TelephonyCall::GetError(nsIDOMDOMError** aError)
{
NS_IF_ADDREF(*aError = mError);
return NS_OK;
}
NS_IMETHODIMP
TelephonyCall::Answer()
{
@ -289,3 +321,4 @@ NS_IMPL_EVENT_HANDLER(TelephonyCall, disconnected)
NS_IMPL_EVENT_HANDLER(TelephonyCall, holding)
NS_IMPL_EVENT_HANDLER(TelephonyCall, held)
NS_IMPL_EVENT_HANDLER(TelephonyCall, resuming)
NS_IMPL_EVENT_HANDLER(TelephonyCall, error)

View File

@ -63,11 +63,13 @@ class TelephonyCall : public nsDOMEventTargetHelper,
NS_DECL_EVENT_HANDLER(holding)
NS_DECL_EVENT_HANDLER(held)
NS_DECL_EVENT_HANDLER(resuming)
NS_DECL_EVENT_HANDLER(error)
nsRefPtr<Telephony> mTelephony;
nsString mNumber;
nsString mState;
nsCOMPtr<nsIDOMDOMError> mError;
PRUint32 mCallIndex;
PRUint16 mCallState;
@ -130,6 +132,9 @@ public:
return mOutgoing;
}
void
NotifyError(const nsAString& aError);
private:
TelephonyCall()
: mCallIndex(kOutgoingPlaceholderCallIndex),

View File

@ -38,16 +38,19 @@
* ***** END LICENSE BLOCK ***** */
#include "nsIDOMEventTarget.idl"
#include "nsIDOMDOMError.idl"
interface nsIDOMEventListener;
[scriptable, builtinclass, uuid(2fb9502b-2054-4eda-8db7-3726c39144f7)]
[scriptable, builtinclass, uuid(d902afb1-2e1d-412e-bfa3-cb6a9453a4db)]
interface nsIDOMTelephonyCall : nsIDOMEventTarget
{
readonly attribute DOMString number;
readonly attribute DOMString state;
readonly attribute nsIDOMDOMError error;
void answer();
void hangUp();
void hold();
@ -65,4 +68,6 @@ interface nsIDOMTelephonyCall : nsIDOMEventTarget
attribute nsIDOMEventListener onholding;
attribute nsIDOMEventListener onheld;
attribute nsIDOMEventListener onresuming;
attribute nsIDOMEventListener onerror;
};

View File

@ -16,7 +16,7 @@
#ifdef MOZ_TABLETS_ONLY
<supports-screens android:smallScreens="false"
android:normalScreens="false"
android:largeScreens="true"
android:largeScreens="false"
android:xlargeScreens="true" />
#endif

View File

@ -88,7 +88,8 @@ struct Rect :
{
*aOut = IntRect(int32_t(X()), int32_t(Y()),
int32_t(Width()), int32_t(Height()));
return Rect(aOut->x, aOut->y, aOut->width, aOut->height).IsEqualEdges(*this);
return Rect(Float(aOut->x), Float(aOut->y),
Float(aOut->width), Float(aOut->height)).IsEqualEdges(*this);
}
};

View File

@ -4031,7 +4031,13 @@ _cairo_image_surface_glyphs (void *abstract_surface,
composite_glyphs_info_t glyph_info;
cairo_clip_t local_clip;
cairo_bool_t have_clip = FALSE;
#ifdef MOZ_GFX_OPTIMIZE_MOBILE
// For performance reasons we don't want to use two passes for overlapping glyphs
// on mobile
cairo_bool_t overlap = FALSE;
#else
cairo_bool_t overlap;
#endif
cairo_status_t status;
cairo_rectangle_int_t rect;
@ -4045,7 +4051,12 @@ _cairo_image_surface_glyphs (void *abstract_surface,
scaled_font,
glyphs, num_glyphs,
clip,
#ifdef MOZ_GFX_OPTIMIZE_MOBILE
NULL);
#else
&overlap);
#endif
if (unlikely (status))
return status;

View File

@ -185,17 +185,8 @@ CFLAGS += -Wno-missing-field-initializers
endif # GNU_CC
# special rule for pixman-mmx to get the right cflags
pixman-mmx.$(OBJ_SUFFIX): pixman-mmx.c $(GLOBAL_DEPS)
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CC)
$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(MMX_CFLAGS) $(_VPATH_SRCS)
pixman-mmx.$(OBJ_SUFFIX): COMPILE_CFLAGS += $(MMX_CFLAGS)
pixman-sse2.$(OBJ_SUFFIX): pixman-sse2.c $(GLOBAL_DEPS)
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CC)
$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(SSE2_CFLAGS) $(_VPATH_SRCS)
pixman-sse2.$(OBJ_SUFFIX): COMPILE_CFLAGS += $(SSE2_CFLAGS)
pixman-arm-neon.$(OBJ_SUFFIX): pixman-arm-neon.c $(GLOBAL_DEPS)
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CC)
$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(ARM_NEON_CFLAGS) $(_VPATH_SRCS)
pixman-arm-neon.$(OBJ_SUFFIX): COMPILE_CFLAGS += $(ARM_NEON_CFLAGS)

View File

@ -101,12 +101,6 @@ CFLAGS += -Wno-missing-field-initializers
endif # GNU_CC
# special rules for transform-sse*.c to get the right cflags. (taken from pixman/src/Makefile.in)
transform-sse1.$(OBJ_SUFFIX): transform-sse1.c $(GLOBAL_DEPS)
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CC)
$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(SSE1_FLAGS) $(_VPATH_SRCS)
transform-sse1.$(OBJ_SUFFIX): COMPILE_CFLAGS += $(SSE1_FLAGS)
transform-sse2.$(OBJ_SUFFIX): transform-sse2.c $(GLOBAL_DEPS)
$(REPORT_BUILD)
@$(MAKE_DEPS_AUTO_CC)
$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(SSE2_FLAGS) $(_VPATH_SRCS)
transform-sse2.$(OBJ_SUFFIX): COMPILE_CFLAGS += $(SSE2_FLAGS)

191
gfx/skia/arm-fixes.patch Normal file
View File

@ -0,0 +1,191 @@
diff --git a/gfx/skia/include/core/SkMath.h b/gfx/skia/include/core/SkMath.h
--- a/gfx/skia/include/core/SkMath.h
+++ b/gfx/skia/include/core/SkMath.h
@@ -148,20 +148,17 @@ static inline bool SkIsPow2(int value) {
}
///////////////////////////////////////////////////////////////////////////////
/** SkMulS16(a, b) multiplies a * b, but requires that a and b are both int16_t.
With this requirement, we can generate faster instructions on some
architectures.
*/
-#if defined(__arm__) \
- && !defined(__thumb__) \
- && !defined(__ARM_ARCH_4T__) \
- && !defined(__ARM_ARCH_5T__)
+#ifdef SK_ARM_HAS_EDSP
static inline int32_t SkMulS16(S16CPU x, S16CPU y) {
SkASSERT((int16_t)x == x);
SkASSERT((int16_t)y == y);
int32_t product;
asm("smulbb %0, %1, %2 \n"
: "=r"(product)
: "r"(x), "r"(y)
);
diff --git a/gfx/skia/include/core/SkPostConfig.h b/gfx/skia/include/core/SkPostConfig.h
--- a/gfx/skia/include/core/SkPostConfig.h
+++ b/gfx/skia/include/core/SkPostConfig.h
@@ -300,8 +300,53 @@
#endif
#endif
//////////////////////////////////////////////////////////////////////
#ifndef SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
#define SK_ALLOW_STATIC_GLOBAL_INITIALIZERS 1
#endif
+
+//////////////////////////////////////////////////////////////////////
+// ARM defines
+
+#if defined(__GNUC__) && defined(__arm__)
+
+# define SK_ARM_ARCH 3
+
+# if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__) \
+ || defined(_ARM_ARCH_4)
+# undef SK_ARM_ARCH
+# define SK_ARM_ARCH 4
+# endif
+
+# if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
+ || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
+ || defined(__ARM_ARCH_5TEJ__) || defined(_ARM_ARCH_5)
+# undef SK_ARM_ARCH
+# define SK_ARM_ARCH 5
+# endif
+
+# if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
+ || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \
+ || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) \
+ || defined(__ARM_ARCH_6M__) || defined(_ARM_ARCH_6)
+# undef SK_ARM_ARCH
+# define SK_ARM_ARCH 6
+# endif
+
+# if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
+ || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
+ || defined(__ARM_ARCH_7EM__) || defined(_ARM_ARCH_7)
+# undef SK_ARM_ARCH
+# define SK_ARM_ARCH 7
+# endif
+
+# undef SK_ARM_HAS_EDSP
+# if defined(__thumb2__) && (SK_ARM_ARCH >= 6) \
+ || !defined(__thumb__) \
+ && ((SK_ARM_ARCH > 5) || defined(__ARM_ARCH_5E__) \
+ || defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_5TEJ__))
+# define SK_ARM_HAS_EDSP 1
+# endif
+
+#endif
diff --git a/gfx/skia/src/opts/SkBitmapProcState_opts_arm.cpp b/gfx/skia/src/opts/SkBitmapProcState_opts_arm.cpp
--- a/gfx/skia/src/opts/SkBitmapProcState_opts_arm.cpp
+++ b/gfx/skia/src/opts/SkBitmapProcState_opts_arm.cpp
@@ -6,17 +6,17 @@
* found in the LICENSE file.
*/
#include "SkBitmapProcState.h"
#include "SkColorPriv.h"
#include "SkUtils.h"
-#if __ARM_ARCH__ >= 6 && !defined(SK_CPU_BENDIAN)
+#if SK_ARM_ARCH >= 6 && !defined(SK_CPU_BENDIAN)
void SI8_D16_nofilter_DX_arm(
const SkBitmapProcState& s,
const uint32_t* SK_RESTRICT xy,
int count,
uint16_t* SK_RESTRICT colors) __attribute__((optimize("O1")));
void SI8_D16_nofilter_DX_arm(const SkBitmapProcState& s,
const uint32_t* SK_RESTRICT xy,
@@ -177,17 +177,17 @@ void SI8_opaque_D32_nofilter_DX_arm(cons
: [xx] "+r" (xx), [count] "+r" (count), [colors] "+r" (colors)
: [table] "r" (table), [srcAddr] "r" (srcAddr)
: "memory", "cc", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11"
);
}
s.fBitmap->getColorTable()->unlockColors(false);
}
-#endif //__ARM_ARCH__ >= 6 && !defined(SK_CPU_BENDIAN)
+#endif // SK_ARM_ARCH >= 6 && !defined(SK_CPU_BENDIAN)
///////////////////////////////////////////////////////////////////////////////
/* If we replace a sampleproc, then we null-out the associated shaderproc,
otherwise the shader won't even look at the matrix/sampler
*/
void SkBitmapProcState::platformProcs() {
bool doFilter = fDoFilter;
@@ -195,17 +195,17 @@ void SkBitmapProcState::platformProcs()
bool justDx = false;
if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) {
justDx = true;
}
switch (fBitmap->config()) {
case SkBitmap::kIndex8_Config:
-#if __ARM_ARCH__ >= 6 && !defined(SK_CPU_BENDIAN)
+#if SK_ARM_ARCH >= 6 && !defined(SK_CPU_BENDIAN)
if (justDx && !doFilter) {
#if 0 /* crashing on android device */
fSampleProc16 = SI8_D16_nofilter_DX_arm;
fShaderProc16 = NULL;
#endif
if (isOpaque) {
// this one is only very slighty faster than the C version
fSampleProc32 = SI8_opaque_D32_nofilter_DX_arm;
diff --git a/gfx/skia/src/opts/SkBlitRow_opts_arm.cpp b/gfx/skia/src/opts/SkBlitRow_opts_arm.cpp
--- a/gfx/skia/src/opts/SkBlitRow_opts_arm.cpp
+++ b/gfx/skia/src/opts/SkBlitRow_opts_arm.cpp
@@ -669,18 +669,23 @@ static void __attribute((noinline,optimi
/* Double Loop */
"1: \n\t" /* <double loop> */
"ldm %[src]!, {r5, r6} \n\t" /* loading src pointers into r5 and r6 */
"ldm %[dst], {r7, r8} \n\t" /* loading dst pointers into r7 and r8 */
/* dst1_scale and dst2_scale*/
"lsr r9, r5, #24 \n\t" /* src >> 24 */
"lsr r10, r6, #24 \n\t" /* src >> 24 */
+#ifdef SK_ARM_HAS_EDSP
"smulbb r9, r9, %[alpha] \n\t" /* r9 = SkMulS16 r9 with src_scale */
"smulbb r10, r10, %[alpha] \n\t" /* r10 = SkMulS16 r10 with src_scale */
+#else
+ "mul r9, r9, %[alpha] \n\t" /* r9 = SkMulS16 r9 with src_scale */
+ "mul r10, r10, %[alpha] \n\t" /* r10 = SkMulS16 r10 with src_scale */
+#endif
"lsr r9, r9, #8 \n\t" /* r9 >> 8 */
"lsr r10, r10, #8 \n\t" /* r10 >> 8 */
"rsb r9, r9, #256 \n\t" /* dst1_scale = r9 = 255 - r9 + 1 */
"rsb r10, r10, #256 \n\t" /* dst2_scale = r10 = 255 - r10 + 1 */
/* ---------------------- */
/* src1, src1_scale */
@@ -739,17 +744,21 @@ static void __attribute((noinline,optimi
/* else get into the single loop */
/* Single Loop */
"2: \n\t" /* <single loop> */
"ldr r5, [%[src]], #4 \n\t" /* loading src pointer into r5: r5=src */
"ldr r7, [%[dst]] \n\t" /* loading dst pointer into r7: r7=dst */
"lsr r6, r5, #24 \n\t" /* src >> 24 */
"and r8, r12, r5, lsr #8 \n\t" /* ag = r8 = r5 masked by r12 lsr by #8 */
+#ifdef SK_ARM_HAS_EDSP
"smulbb r6, r6, %[alpha] \n\t" /* r6 = SkMulS16 with src_scale */
+#else
+ "mul r6, r6, %[alpha] \n\t" /* r6 = SkMulS16 with src_scale */
+#endif
"and r9, r12, r5 \n\t" /* rb = r9 = r5 masked by r12 */
"lsr r6, r6, #8 \n\t" /* r6 >> 8 */
"mul r8, r8, %[alpha] \n\t" /* ag = r8 times scale */
"rsb r6, r6, #256 \n\t" /* r6 = 255 - r6 + 1 */
/* src, src_scale */
"mul r9, r9, %[alpha] \n\t" /* rb = r9 times scale */
"and r8, r8, r12, lsl #8 \n\t" /* ag masked by reverse mask (r12) */

View File

@ -153,10 +153,7 @@ static inline bool SkIsPow2(int value) {
With this requirement, we can generate faster instructions on some
architectures.
*/
#if defined(__arm__) \
&& !defined(__thumb__) \
&& !defined(__ARM_ARCH_4T__) \
&& !defined(__ARM_ARCH_5T__)
#ifdef SK_ARM_HAS_EDSP
static inline int32_t SkMulS16(S16CPU x, S16CPU y) {
SkASSERT((int16_t)x == x);
SkASSERT((int16_t)y == y);

View File

@ -305,3 +305,48 @@
#ifndef SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
#define SK_ALLOW_STATIC_GLOBAL_INITIALIZERS 1
#endif
//////////////////////////////////////////////////////////////////////
// ARM defines
#if defined(__GNUC__) && defined(__arm__)
# define SK_ARM_ARCH 3
# if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__) \
|| defined(_ARM_ARCH_4)
# undef SK_ARM_ARCH
# define SK_ARM_ARCH 4
# endif
# if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
|| defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
|| defined(__ARM_ARCH_5TEJ__) || defined(_ARM_ARCH_5)
# undef SK_ARM_ARCH
# define SK_ARM_ARCH 5
# endif
# if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
|| defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \
|| defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) \
|| defined(__ARM_ARCH_6M__) || defined(_ARM_ARCH_6)
# undef SK_ARM_ARCH
# define SK_ARM_ARCH 6
# endif
# if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
|| defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
|| defined(__ARM_ARCH_7EM__) || defined(_ARM_ARCH_7)
# undef SK_ARM_ARCH
# define SK_ARM_ARCH 7
# endif
# undef SK_ARM_HAS_EDSP
# if defined(__thumb2__) && (SK_ARM_ARCH >= 6) \
|| !defined(__thumb__) \
&& ((SK_ARM_ARCH > 5) || defined(__ARM_ARCH_5E__) \
|| defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_5TEJ__))
# define SK_ARM_HAS_EDSP 1
# endif
#endif

View File

@ -11,7 +11,7 @@
#include "SkColorPriv.h"
#include "SkUtils.h"
#if __ARM_ARCH__ >= 6 && !defined(SK_CPU_BENDIAN)
#if SK_ARM_ARCH >= 6 && !defined(SK_CPU_BENDIAN)
void SI8_D16_nofilter_DX_arm(
const SkBitmapProcState& s,
const uint32_t* SK_RESTRICT xy,
@ -182,7 +182,7 @@ void SI8_opaque_D32_nofilter_DX_arm(const SkBitmapProcState& s,
s.fBitmap->getColorTable()->unlockColors(false);
}
#endif //__ARM_ARCH__ >= 6 && !defined(SK_CPU_BENDIAN)
#endif // SK_ARM_ARCH >= 6 && !defined(SK_CPU_BENDIAN)
///////////////////////////////////////////////////////////////////////////////
@ -200,7 +200,7 @@ void SkBitmapProcState::platformProcs() {
switch (fBitmap->config()) {
case SkBitmap::kIndex8_Config:
#if __ARM_ARCH__ >= 6 && !defined(SK_CPU_BENDIAN)
#if SK_ARM_ARCH >= 6 && !defined(SK_CPU_BENDIAN)
if (justDx && !doFilter) {
#if 0 /* crashing on android device */
fSampleProc16 = SI8_D16_nofilter_DX_arm;

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