зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central into services-central
This commit is contained in:
Коммит
1cf0cbda1b
|
@ -47,6 +47,9 @@ _OPT\.OBJ/
|
|||
\.cproject$
|
||||
\.settings/
|
||||
|
||||
# Ignore the directory that JetBrains IDEs create
|
||||
\.idea/
|
||||
|
||||
# Python stuff installed at build time.
|
||||
^python/psutil/.*\.so
|
||||
^python/psutil/.*\.pyd
|
||||
|
|
3
CLOBBER
3
CLOBBER
|
@ -17,4 +17,5 @@
|
|||
#
|
||||
# Modifying this file will now automatically clobber the buildbot machines \o/
|
||||
#
|
||||
Bug 870180 - CPOWs
|
||||
Bug 889503 - Move Settings API to WebIDL.
|
||||
Requires a clobber due to Bug 890744.
|
||||
|
|
|
@ -772,9 +772,9 @@ HyperTextAccessible::GetRelativeOffset(nsIPresShell* aPresShell,
|
|||
}
|
||||
|
||||
int32_t
|
||||
HyperTextAccessible::FindBoundary(int32_t aOffset, nsDirection aDirection,
|
||||
nsSelectionAmount aAmount,
|
||||
EWordMovementType aWordMovementType)
|
||||
HyperTextAccessible::FindOffset(int32_t aOffset, nsDirection aDirection,
|
||||
nsSelectionAmount aAmount,
|
||||
EWordMovementType aWordMovementType)
|
||||
{
|
||||
// Convert hypertext offset to frame-relative offset.
|
||||
int32_t offsetInFrame = aOffset, notUsedOffset = aOffset;
|
||||
|
@ -803,6 +803,81 @@ HyperTextAccessible::FindBoundary(int32_t aOffset, nsDirection aDirection,
|
|||
aWordMovementType);
|
||||
}
|
||||
|
||||
int32_t
|
||||
HyperTextAccessible::FindLineBoundary(int32_t aOffset,
|
||||
EWhichLineBoundary aWhichLineBoundary)
|
||||
{
|
||||
// Note: empty last line doesn't have own frame (a previous line contains '\n'
|
||||
// character instead) thus when it makes a difference we need to process this
|
||||
// case separately (otherwise operations are performed on previous line).
|
||||
switch (aWhichLineBoundary) {
|
||||
case ePrevLineBegin: {
|
||||
// Fetch a previous line and move to its start (as arrow up and home keys
|
||||
// were pressed).
|
||||
if (IsEmptyLastLineOffset(aOffset))
|
||||
return FindOffset(aOffset, eDirPrevious, eSelectBeginLine);
|
||||
|
||||
int32_t tmpOffset = FindOffset(aOffset, eDirPrevious, eSelectLine);
|
||||
return FindOffset(tmpOffset, eDirPrevious, eSelectBeginLine);
|
||||
}
|
||||
|
||||
case ePrevLineEnd: {
|
||||
if (IsEmptyLastLineOffset(aOffset))
|
||||
return aOffset - 1;
|
||||
|
||||
// If offset is at first line then return 0 (first line start).
|
||||
int32_t tmpOffset = FindOffset(aOffset, eDirPrevious, eSelectBeginLine);
|
||||
if (tmpOffset == 0)
|
||||
return 0;
|
||||
|
||||
// Otherwise move to end of previous line (as arrow up and end keys were
|
||||
// pressed).
|
||||
tmpOffset = FindOffset(aOffset, eDirPrevious, eSelectLine);
|
||||
return FindOffset(tmpOffset, eDirNext, eSelectEndLine);
|
||||
}
|
||||
|
||||
case eThisLineBegin:
|
||||
if (IsEmptyLastLineOffset(aOffset))
|
||||
return aOffset;
|
||||
|
||||
// Move to begin of the current line (as home key was pressed).
|
||||
return FindOffset(aOffset, eDirPrevious, eSelectBeginLine);
|
||||
|
||||
case eThisLineEnd:
|
||||
if (IsEmptyLastLineOffset(aOffset))
|
||||
return aOffset;
|
||||
|
||||
// Move to end of the current line (as end key was pressed).
|
||||
return FindOffset(aOffset, eDirNext, eSelectEndLine);
|
||||
|
||||
case eNextLineBegin: {
|
||||
if (IsEmptyLastLineOffset(aOffset))
|
||||
return aOffset;
|
||||
|
||||
// Move to begin of the next line if any (arrow down and home keys),
|
||||
// otherwise end of the current line (arrow down only).
|
||||
int32_t tmpOffset = FindOffset(aOffset, eDirNext, eSelectLine);
|
||||
if (tmpOffset == CharacterCount())
|
||||
return tmpOffset;
|
||||
|
||||
return FindOffset(tmpOffset, eDirPrevious, eSelectBeginLine);
|
||||
}
|
||||
|
||||
case eNextLineEnd: {
|
||||
if (IsEmptyLastLineOffset(aOffset))
|
||||
return aOffset;
|
||||
|
||||
// Move to next line end (as down arrow and end key were pressed).
|
||||
int32_t tmpOffset = FindOffset(aOffset, eDirNext, eSelectLine);
|
||||
if (tmpOffset != CharacterCount())
|
||||
return FindOffset(tmpOffset, eDirNext, eSelectEndLine);
|
||||
return tmpOffset;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
Gets the specified text relative to aBoundaryType, which means:
|
||||
BOUNDARY_CHAR The character before/at/after the offset is returned.
|
||||
|
@ -1029,54 +1104,21 @@ HyperTextAccessible::GetTextBeforeOffset(int32_t aOffset,
|
|||
return GetText(*aStartOffset, *aEndOffset, aText);
|
||||
}
|
||||
|
||||
case BOUNDARY_LINE_START: {
|
||||
case BOUNDARY_LINE_START:
|
||||
if (aOffset == nsIAccessibleText::TEXT_OFFSET_CARET)
|
||||
offset = AdjustCaretOffset(offset);
|
||||
|
||||
// If we are at last empty then home key and get the text (last empty line
|
||||
// doesn't have own frame).
|
||||
if (IsEmptyLastLineOffset(offset)) {
|
||||
*aStartOffset = FindLineBoundary(offset, eDirPrevious, eSelectBeginLine);
|
||||
*aEndOffset = offset;
|
||||
return GetText(*aStartOffset, *aEndOffset, aText);
|
||||
}
|
||||
|
||||
// Home key, up arrow, home key.
|
||||
*aEndOffset = FindLineBoundary(offset, eDirPrevious, eSelectBeginLine);
|
||||
*aStartOffset = FindLineBoundary(offset, eDirPrevious, eSelectLine);
|
||||
*aStartOffset = FindLineBoundary(*aStartOffset, eDirPrevious, eSelectBeginLine);
|
||||
|
||||
*aStartOffset = FindLineBoundary(offset, ePrevLineBegin);
|
||||
*aEndOffset = FindLineBoundary(offset, eThisLineBegin);
|
||||
return GetText(*aStartOffset, *aEndOffset, aText);
|
||||
}
|
||||
|
||||
case BOUNDARY_LINE_END: {
|
||||
case BOUNDARY_LINE_END:
|
||||
if (aOffset == nsIAccessibleText::TEXT_OFFSET_CARET)
|
||||
offset = AdjustCaretOffset(offset);
|
||||
|
||||
// Nothing if we are at first line.
|
||||
int32_t tmpOffset = FindLineBoundary(offset, eDirPrevious, eSelectBeginLine);
|
||||
if (tmpOffset == 0) {
|
||||
*aStartOffset = *aEndOffset = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Up arrow, end key to find previous line endings.
|
||||
if (IsEmptyLastLineOffset(offset)) { // no own frame for a last line
|
||||
tmpOffset = FindLineBoundary(offset, eDirPrevious, eSelectLine);
|
||||
*aStartOffset = FindLineBoundary(tmpOffset, eDirNext, eSelectEndLine);
|
||||
*aEndOffset = offset - 1;
|
||||
return GetText(*aStartOffset, *aEndOffset, aText);
|
||||
}
|
||||
|
||||
tmpOffset = FindLineBoundary(offset, eDirPrevious, eSelectLine);
|
||||
*aEndOffset = FindLineBoundary(tmpOffset, eDirNext, eSelectEndLine);
|
||||
tmpOffset = FindLineBoundary(*aEndOffset, eDirPrevious, eSelectLine);
|
||||
*aStartOffset = FindLineBoundary(tmpOffset, eDirNext, eSelectEndLine);
|
||||
if (*aStartOffset == *aEndOffset) // we are at second line
|
||||
*aStartOffset = 0;
|
||||
|
||||
*aEndOffset = FindLineBoundary(offset, ePrevLineEnd);
|
||||
*aStartOffset = FindLineBoundary(*aEndOffset, ePrevLineEnd);
|
||||
return GetText(*aStartOffset, *aEndOffset, aText);
|
||||
}
|
||||
|
||||
case BOUNDARY_ATTRIBUTE_RANGE:
|
||||
return GetTextHelper(eGetBefore, aBoundaryType, aOffset,
|
||||
|
@ -1118,56 +1160,22 @@ HyperTextAccessible::GetTextAtOffset(int32_t aOffset,
|
|||
*aStartOffset = FindWordBoundary(*aEndOffset, eDirPrevious, eEndWord);
|
||||
return GetText(*aStartOffset, *aEndOffset, aText);
|
||||
|
||||
case BOUNDARY_LINE_START: {
|
||||
// Empty last line doesn't have own frame (a previous line contains '\n'
|
||||
// character instead) thus we can't operate on last line separately
|
||||
// from previous line.
|
||||
if (IsEmptyLastLineOffset(offset)) {
|
||||
*aStartOffset = *aEndOffset = offset;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
case BOUNDARY_LINE_START:
|
||||
if (aOffset == nsIAccessibleText::TEXT_OFFSET_CARET)
|
||||
offset = AdjustCaretOffset(offset);
|
||||
|
||||
// Start offset is begin of the current line (as the home key was
|
||||
// pressed). End offset is begin of the next line if any (arrow down and
|
||||
// home keys), otherwise end of the current line (arrow down only).
|
||||
*aStartOffset = FindLineBoundary(offset, eDirPrevious, eSelectBeginLine);
|
||||
*aEndOffset = FindLineBoundary(offset, eDirNext, eSelectLine);
|
||||
int32_t tmpOffset = FindLineBoundary(*aEndOffset, eDirPrevious, eSelectBeginLine);
|
||||
if (tmpOffset != *aStartOffset)
|
||||
*aEndOffset = tmpOffset;
|
||||
|
||||
*aStartOffset = FindLineBoundary(offset, eThisLineBegin);
|
||||
*aEndOffset = FindLineBoundary(offset, eNextLineBegin);
|
||||
return GetText(*aStartOffset, *aEndOffset, aText);
|
||||
}
|
||||
|
||||
case BOUNDARY_LINE_END: {
|
||||
// Empty last line doesn't have own frame (a previous line contains '\n'
|
||||
// character instead) thus we can't operate on last line separately
|
||||
// from the previous line.
|
||||
if (IsEmptyLastLineOffset(offset)) {
|
||||
*aStartOffset = offset - 1;
|
||||
*aEndOffset = offset;
|
||||
aText.AssignLiteral("\n");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
case BOUNDARY_LINE_END:
|
||||
if (aOffset == nsIAccessibleText::TEXT_OFFSET_CARET)
|
||||
offset = AdjustCaretOffset(offset);
|
||||
|
||||
// In contrast to word end boundary we follow the spec here.
|
||||
// End offset is end of the current line (as the end key was pressed).
|
||||
// Start offset is end of the previous line if any (up arrow and end keys),
|
||||
// otherwise 0 offset (up arrow only).
|
||||
*aEndOffset = FindLineBoundary(offset, eDirNext, eSelectEndLine);
|
||||
int32_t tmpOffset = FindLineBoundary(offset, eDirPrevious, eSelectLine);
|
||||
*aStartOffset = FindLineBoundary(tmpOffset, eDirNext, eSelectEndLine);
|
||||
if (*aStartOffset == *aEndOffset)
|
||||
*aStartOffset = 0;
|
||||
|
||||
*aStartOffset = FindLineBoundary(offset, ePrevLineEnd);
|
||||
*aEndOffset = FindLineBoundary(offset, eThisLineEnd);
|
||||
return GetText(*aStartOffset, *aEndOffset, aText);
|
||||
}
|
||||
|
||||
case BOUNDARY_ATTRIBUTE_RANGE:
|
||||
return GetTextHelper(eGetAt, aBoundaryType, aOffset,
|
||||
|
@ -1223,36 +1231,16 @@ HyperTextAccessible::GetTextAfterOffset(int32_t aOffset,
|
|||
if (aOffset == nsIAccessibleText::TEXT_OFFSET_CARET)
|
||||
offset = AdjustCaretOffset(offset);
|
||||
|
||||
// Down arrow, home key, down arrow, home key.
|
||||
*aStartOffset = FindLineBoundary(offset, eDirNext, eSelectLine);
|
||||
if (*aStartOffset != CharacterCount()) {
|
||||
*aStartOffset = FindLineBoundary(*aStartOffset, eDirPrevious, eSelectBeginLine);
|
||||
*aEndOffset = FindLineBoundary(*aStartOffset, eDirNext, eSelectLine);
|
||||
if (*aEndOffset != CharacterCount())
|
||||
*aEndOffset = FindLineBoundary(*aEndOffset, eDirPrevious, eSelectBeginLine);
|
||||
} else {
|
||||
*aEndOffset = CharacterCount();
|
||||
}
|
||||
*aStartOffset = FindLineBoundary(offset, eNextLineBegin);
|
||||
*aEndOffset = FindLineBoundary(*aStartOffset, eNextLineBegin);
|
||||
return GetText(*aStartOffset, *aEndOffset, aText);
|
||||
|
||||
case BOUNDARY_LINE_END:
|
||||
if (aOffset == nsIAccessibleText::TEXT_OFFSET_CARET)
|
||||
offset = AdjustCaretOffset(offset);
|
||||
|
||||
// Empty last line doesn't have own frame (a previous line contains '\n'
|
||||
// character instead) thus we can't operate on last line separately
|
||||
// from the previous line.
|
||||
if (IsEmptyLastLineOffset(offset)) {
|
||||
*aStartOffset = *aEndOffset = offset;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// End key, down arrow, end key.
|
||||
*aStartOffset = FindLineBoundary(offset, eDirNext, eSelectEndLine);
|
||||
*aEndOffset = FindLineBoundary(*aStartOffset, eDirNext, eSelectLine);
|
||||
if (*aEndOffset != CharacterCount())
|
||||
*aEndOffset = FindLineBoundary(*aEndOffset, eDirNext, eSelectEndLine);
|
||||
|
||||
*aStartOffset = FindLineBoundary(offset, eThisLineEnd);
|
||||
*aEndOffset = FindLineBoundary(offset, eNextLineEnd);
|
||||
return GetText(*aStartOffset, *aEndOffset, aText);
|
||||
|
||||
case BOUNDARY_ATTRIBUTE_RANGE:
|
||||
|
|
|
@ -302,24 +302,37 @@ protected:
|
|||
int32_t FindWordBoundary(int32_t aOffset, nsDirection aDirection,
|
||||
EWordMovementType aWordMovementType)
|
||||
{
|
||||
return FindBoundary(aOffset, aDirection, eSelectWord, aWordMovementType);
|
||||
return FindOffset(aOffset, aDirection, eSelectWord, aWordMovementType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an offset of the found line boundary.
|
||||
* Used to get begin/end of previous/this/next line. Note: end of line
|
||||
* is an offset right before '\n' character if any, the offset is right after
|
||||
* '\n' character is begin of line. In case of wrap word breaks these offsets
|
||||
* are equal.
|
||||
*/
|
||||
int32_t FindLineBoundary(int32_t aOffset, nsDirection aDirection,
|
||||
nsSelectionAmount aAmount)
|
||||
{
|
||||
return FindBoundary(aOffset, aDirection, aAmount, eDefaultBehavior);
|
||||
}
|
||||
enum EWhichLineBoundary {
|
||||
ePrevLineBegin,
|
||||
ePrevLineEnd,
|
||||
eThisLineBegin,
|
||||
eThisLineEnd,
|
||||
eNextLineBegin,
|
||||
eNextLineEnd
|
||||
};
|
||||
|
||||
/**
|
||||
* Return an offset of the found word or line boundary. Helper.
|
||||
* Return an offset for requested line boundary. See constants above.
|
||||
*/
|
||||
int32_t FindBoundary(int32_t aOffset, nsDirection aDirection,
|
||||
nsSelectionAmount aAmount,
|
||||
EWordMovementType aWordMovementType = eDefaultBehavior);
|
||||
int32_t FindLineBoundary(int32_t aOffset,
|
||||
EWhichLineBoundary aWhichLineBoundary);
|
||||
|
||||
/**
|
||||
* Return an offset corresponding to the given direction and selection amount
|
||||
* relative the given offset. A helper used to find word or line boundaries.
|
||||
*/
|
||||
int32_t FindOffset(int32_t aOffset, nsDirection aDirection,
|
||||
nsSelectionAmount aAmount,
|
||||
EWordMovementType aWordMovementType = eDefaultBehavior);
|
||||
|
||||
/*
|
||||
* This does the work for nsIAccessibleText::GetText[At|Before|After]Offset
|
||||
|
|
|
@ -274,9 +274,7 @@ this.AccessFu = {
|
|||
case 'Accessibility:Focus':
|
||||
this._focused = JSON.parse(aData);
|
||||
if (this._focused) {
|
||||
let mm = Utils.getMessageManager(Utils.CurrentBrowser);
|
||||
mm.sendAsyncMessage('AccessFu:VirtualCursor',
|
||||
{action: 'whereIsIt', move: true});
|
||||
this.showCurrent(true);
|
||||
}
|
||||
break;
|
||||
case 'Accessibility:MoveCaret':
|
||||
|
@ -327,20 +325,24 @@ this.AccessFu = {
|
|||
case 'TabSelect':
|
||||
{
|
||||
if (this._focused) {
|
||||
let mm = Utils.getMessageManager(Utils.CurrentBrowser);
|
||||
// We delay this for half a second so the awesomebar could close,
|
||||
// and we could use the current coordinates for the content item.
|
||||
// XXX TODO figure out how to avoid magic wait here.
|
||||
Utils.win.setTimeout(
|
||||
function () {
|
||||
mm.sendAsyncMessage('AccessFu:VirtualCursor', {action: 'whereIsIt'});
|
||||
}, 500);
|
||||
this.showCurrent(false);
|
||||
}.bind(this), 500);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
showCurrent: function showCurrent(aMove) {
|
||||
let mm = Utils.getMessageManager(Utils.CurrentBrowser);
|
||||
mm.sendAsyncMessage('AccessFu:ShowCurrent', { move: aMove });
|
||||
},
|
||||
|
||||
announce: function announce(aAnnouncement) {
|
||||
this._output(Presentation.announce(aAnnouncement),
|
||||
Utils.CurrentBrowser);
|
||||
|
@ -632,8 +634,7 @@ var Input = {
|
|||
switch (gestureName) {
|
||||
case 'dwell1':
|
||||
case 'explore1':
|
||||
this.moveCursor('moveToPoint', 'SimpleTouch', 'gesture',
|
||||
aGesture.x, aGesture.y);
|
||||
this.moveToPoint('SimpleTouch', aGesture.x, aGesture.y);
|
||||
break;
|
||||
case 'doubletap1':
|
||||
this.activateCurrent();
|
||||
|
@ -754,12 +755,18 @@ var Input = {
|
|||
aEvent.stopPropagation();
|
||||
},
|
||||
|
||||
moveCursor: function moveCursor(aAction, aRule, aInputType, aX, aY) {
|
||||
moveToPoint: function moveToPoint(aRule, aX, aY) {
|
||||
let mm = Utils.getMessageManager(Utils.CurrentBrowser);
|
||||
mm.sendAsyncMessage('AccessFu:VirtualCursor',
|
||||
mm.sendAsyncMessage('AccessFu:MoveToPoint', {rule: aRule,
|
||||
x: aX, y: aY,
|
||||
origin: 'top'});
|
||||
},
|
||||
|
||||
moveCursor: function moveCursor(aAction, aRule, aInputType) {
|
||||
let mm = Utils.getMessageManager(Utils.CurrentBrowser);
|
||||
mm.sendAsyncMessage('AccessFu:MoveCursor',
|
||||
{action: aAction, rule: aRule,
|
||||
x: aX, y: aY, origin: 'top',
|
||||
inputType: aInputType});
|
||||
origin: 'top', inputType: aInputType});
|
||||
},
|
||||
|
||||
moveCaret: function moveCaret(aDetails) {
|
||||
|
|
|
@ -234,7 +234,8 @@ this.Utils = {
|
|||
|
||||
inHiddenSubtree: function inHiddenSubtree(aAccessible) {
|
||||
for (let acc=aAccessible; acc; acc=acc.parent) {
|
||||
if (JSON.parse(Utils.getAttributes(acc).hidden)) {
|
||||
let hidden = Utils.getAttributes(acc).hidden;
|
||||
if (hidden && JSON.parse(hidden)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,100 +26,136 @@ Logger.debug('content-script.js');
|
|||
|
||||
let eventManager = null;
|
||||
|
||||
function virtualCursorControl(aMessage) {
|
||||
if (Logger.logLevel >= Logger.DEBUG)
|
||||
Logger.debug(aMessage.name, JSON.stringify(aMessage.json));
|
||||
function moveCursor(aMessage) {
|
||||
if (Logger.logLevel >= Logger.DEBUG) {
|
||||
Logger.debug(aMessage.name, JSON.stringify(aMessage.json, null, ' '));
|
||||
}
|
||||
|
||||
try {
|
||||
let vc = Utils.getVirtualCursor(content.document);
|
||||
let origin = aMessage.json.origin;
|
||||
if (origin != 'child') {
|
||||
if (forwardMessage(vc, aMessage))
|
||||
return;
|
||||
}
|
||||
let vc = Utils.getVirtualCursor(content.document);
|
||||
let origin = aMessage.json.origin;
|
||||
let action = aMessage.json.action;
|
||||
let rule = TraversalRules[aMessage.json.rule];
|
||||
|
||||
let details = aMessage.json;
|
||||
let rule = TraversalRules[details.rule];
|
||||
let moved = 0;
|
||||
switch (details.action) {
|
||||
case 'moveFirst':
|
||||
case 'moveLast':
|
||||
moved = vc[details.action](rule);
|
||||
break;
|
||||
case 'moveNext':
|
||||
case 'movePrevious':
|
||||
try {
|
||||
if (origin == 'parent' && vc.position == null) {
|
||||
if (details.action == 'moveNext')
|
||||
moved = vc.moveFirst(rule);
|
||||
else
|
||||
moved = vc.moveLast(rule);
|
||||
} else {
|
||||
moved = vc[details.action](rule);
|
||||
function moveCursorInner() {
|
||||
try {
|
||||
if (origin == 'parent' &&
|
||||
!Utils.isAliveAndVisible(vc.position)) {
|
||||
// We have a bad position in this frame, move vc to last or first item.
|
||||
if (action == 'moveNext') {
|
||||
return vc.moveFirst(rule);
|
||||
} else if (action == 'movePrevious') {
|
||||
return vc.moveLast(rule);
|
||||
}
|
||||
} catch (x) {
|
||||
}
|
||||
|
||||
return vc[action](rule);
|
||||
} catch (x) {
|
||||
if (action == 'moveNext' || action == 'movePrevious') {
|
||||
// If we are trying to move next/prev put the vc on the focused item.
|
||||
let acc = Utils.AccRetrieval.
|
||||
getAccessibleFor(content.document.activeElement);
|
||||
moved = vc.moveNext(rule, acc, true);
|
||||
return vc.moveNext(rule, acc, true);
|
||||
} else {
|
||||
throw x;
|
||||
}
|
||||
break;
|
||||
case 'moveToPoint':
|
||||
if (!this._ppcp) {
|
||||
this._ppcp = Utils.getPixelsPerCSSPixel(content);
|
||||
}
|
||||
moved = vc.moveToPoint(rule,
|
||||
details.x * this._ppcp, details.y * this._ppcp,
|
||||
true);
|
||||
break;
|
||||
case 'whereIsIt':
|
||||
if (!forwardMessage(vc, aMessage)) {
|
||||
if (!vc.position && aMessage.json.move)
|
||||
vc.moveFirst(TraversalRules.Simple);
|
||||
else {
|
||||
sendAsyncMessage('AccessFu:Present', Presentation.pivotChanged(
|
||||
vc.position, null, Ci.nsIAccessiblePivot.REASON_NONE));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (moved == true) {
|
||||
forwardMessage(vc, aMessage);
|
||||
} else if (moved == false && details.action != 'moveToPoint') {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
if (origin != 'child' &&
|
||||
forwardToChild(aMessage, moveCursor, vc.position)) {
|
||||
// We successfully forwarded the move to the child document.
|
||||
return;
|
||||
}
|
||||
|
||||
if (moveCursorInner()) {
|
||||
// If we moved, try forwarding the message to the new position,
|
||||
// it may be a frame with a vc of its own.
|
||||
forwardToChild(aMessage, moveCursor, vc.position);
|
||||
} else {
|
||||
// If we did not move, we probably reached the end or start of the
|
||||
// document, go back to parent content and move us out of the iframe.
|
||||
if (origin == 'parent') {
|
||||
vc.position = null;
|
||||
}
|
||||
aMessage.json.origin = 'child';
|
||||
sendAsyncMessage('AccessFu:VirtualCursor', aMessage.json);
|
||||
forwardToParent(aMessage);
|
||||
}
|
||||
} catch (x) {
|
||||
Logger.logException(x, 'Failed to move virtual cursor');
|
||||
Logger.logException(x, 'Cursor move failed');
|
||||
}
|
||||
}
|
||||
|
||||
function forwardMessage(aVirtualCursor, aMessage) {
|
||||
try {
|
||||
let acc = aVirtualCursor.position;
|
||||
if (acc && acc.role == ROLE_INTERNAL_FRAME) {
|
||||
let mm = Utils.getMessageManager(acc.DOMNode);
|
||||
mm.addMessageListener(aMessage.name, virtualCursorControl);
|
||||
aMessage.json.origin = 'parent';
|
||||
if (Utils.isContentProcess) {
|
||||
// XXX: OOP content's screen offset is 0,
|
||||
// so we remove the real screen offset here.
|
||||
aMessage.json.x -= content.mozInnerScreenX;
|
||||
aMessage.json.y -= content.mozInnerScreenY;
|
||||
}
|
||||
mm.sendAsyncMessage(aMessage.name, aMessage.json);
|
||||
return true;
|
||||
}
|
||||
} catch (x) {
|
||||
// Frame may be hidden, we regard this case as false.
|
||||
function moveToPoint(aMessage) {
|
||||
if (Logger.logLevel >= Logger.DEBUG) {
|
||||
Logger.debug(aMessage.name, JSON.stringify(aMessage.json, null, ' '));
|
||||
}
|
||||
return false;
|
||||
|
||||
let vc = Utils.getVirtualCursor(content.document);
|
||||
let details = aMessage.json;
|
||||
let rule = TraversalRules[details.rule];
|
||||
|
||||
try {
|
||||
if (!this._ppcp) {
|
||||
this._ppcp = Utils.getPixelsPerCSSPixel(content);
|
||||
}
|
||||
vc.moveToPoint(rule, details.x * this._ppcp, details.y * this._ppcp, true);
|
||||
forwardToChild(aMessage, moveToPoint, vc.position);
|
||||
} catch (x) {
|
||||
Logger.logException(x, 'Failed move to point');
|
||||
}
|
||||
}
|
||||
|
||||
function showCurrent(aMessage) {
|
||||
if (Logger.logLevel >= Logger.DEBUG) {
|
||||
Logger.debug(aMessage.name, JSON.stringify(aMessage.json, null, ' '));
|
||||
}
|
||||
|
||||
let vc = Utils.getVirtualCursor(content.document);
|
||||
|
||||
if (!forwardToChild(vc, showCurrent, aMessage)) {
|
||||
if (!vc.position && aMessage.json.move) {
|
||||
vc.moveFirst(TraversalRules.Simple);
|
||||
} else {
|
||||
sendAsyncMessage('AccessFu:Present', Presentation.pivotChanged(
|
||||
vc.position, null, Ci.nsIAccessiblePivot.REASON_NONE));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function forwardToParent(aMessage) {
|
||||
// XXX: This is a silly way to make a deep copy
|
||||
let newJSON = JSON.parse(JSON.stringify(aMessage.json));
|
||||
newJSON.origin = 'child';
|
||||
sendAsyncMessage(aMessage.name, newJSON);
|
||||
}
|
||||
|
||||
function forwardToChild(aMessage, aListener, aVCPosition) {
|
||||
let acc = aVCPosition || Utils.getVirtualCursor(content.document).position;
|
||||
|
||||
if (!Utils.isAliveAndVisible(acc) || acc.role != ROLE_INTERNAL_FRAME) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Logger.logLevel >= Logger.DEBUG) {
|
||||
Logger.debug('forwardToChild', Logger.accessibleToString(acc),
|
||||
aMessage.name, JSON.stringify(aMessage.json, null, ' '));
|
||||
}
|
||||
|
||||
let mm = Utils.getMessageManager(acc.DOMNode);
|
||||
mm.addMessageListener(aMessage.name, aListener);
|
||||
// XXX: This is a silly way to make a deep copy
|
||||
let newJSON = JSON.parse(JSON.stringify(aMessage.json));
|
||||
newJSON.origin = 'parent';
|
||||
if (Utils.isContentProcess) {
|
||||
// XXX: OOP content's screen offset is 0,
|
||||
// so we remove the real screen offset here.
|
||||
newJSON.x -= content.mozInnerScreenX;
|
||||
newJSON.y -= content.mozInnerScreenY;
|
||||
}
|
||||
mm.sendAsyncMessage(aMessage.name, newJSON);
|
||||
return true;
|
||||
}
|
||||
|
||||
function activateCurrent(aMessage) {
|
||||
|
@ -174,23 +210,24 @@ function activateCurrent(aMessage) {
|
|||
return;
|
||||
}
|
||||
|
||||
let vc = Utils.getVirtualCursor(content.document);
|
||||
if (!forwardMessage(vc, aMessage))
|
||||
activateAccessible(vc.position);
|
||||
let position = Utils.getVirtualCursor(content.document).position;
|
||||
if (!forwardToChild(aMessage, activateCurrent, position)) {
|
||||
activateAccessible(position);
|
||||
}
|
||||
}
|
||||
|
||||
function activateContextMenu(aMessage) {
|
||||
function sendContextMenuCoordinates(aAccessible) {
|
||||
let objX = {}, objY = {}, objW = {}, objH = {};
|
||||
aAccessible.getBounds(objX, objY, objW, objH);
|
||||
let x = objX.value + objW.value / 2;
|
||||
let y = objY.value + objH.value / 2;
|
||||
sendAsyncMessage('AccessFu:ActivateContextMenu', {x: x, y: y});
|
||||
let bounds = Utils.getBounds(aAccessible);
|
||||
sendAsyncMessage('AccessFu:ActivateContextMenu',
|
||||
{ x: bounds.left + bounds.width / 2,
|
||||
y: bounds.top + bounds.height / 2 });
|
||||
}
|
||||
|
||||
let vc = Utils.getVirtualCursor(content.document);
|
||||
if (!forwardMessage(vc, aMessage))
|
||||
sendContextMenuCoordinates(vc.position);
|
||||
let position = Utils.getVirtualCursor(content.document).position;
|
||||
if (!forwardToChild(aMessage, activateContextMenu, position)) {
|
||||
sendContextMenuCoordinates(position);
|
||||
}
|
||||
}
|
||||
|
||||
function moveCaret(aMessage) {
|
||||
|
@ -315,15 +352,14 @@ function scroll(aMessage) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (aMessage.json.origin != 'child') {
|
||||
if (forwardMessage(vc, aMessage))
|
||||
return;
|
||||
if (aMessage.json.origin != 'child' &&
|
||||
forwardToChild(aMessage, scroll, vc.position)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!tryToScroll()) {
|
||||
// Failed to scroll anything in this document. Try in parent document.
|
||||
aMessage.json.origin = 'child';
|
||||
sendAsyncMessage('AccessFu:Scroll', aMessage.json);
|
||||
forwardToParent(aMessage);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -334,7 +370,9 @@ addMessageListener(
|
|||
if (m.json.buildApp)
|
||||
Utils.MozBuildApp = m.json.buildApp;
|
||||
|
||||
addMessageListener('AccessFu:VirtualCursor', virtualCursorControl);
|
||||
addMessageListener('AccessFu:MoveToPoint', moveToPoint);
|
||||
addMessageListener('AccessFu:MoveCursor', moveCursor);
|
||||
addMessageListener('AccessFu:ShowCurrent', showCurrent);
|
||||
addMessageListener('AccessFu:Activate', activateCurrent);
|
||||
addMessageListener('AccessFu:ContextMenu', activateContextMenu);
|
||||
addMessageListener('AccessFu:Scroll', scroll);
|
||||
|
@ -351,7 +389,9 @@ addMessageListener(
|
|||
function(m) {
|
||||
Logger.debug('AccessFu:Stop');
|
||||
|
||||
removeMessageListener('AccessFu:VirtualCursor', virtualCursorControl);
|
||||
removeMessageListener('AccessFu:MoveToPoint', moveToPoint);
|
||||
removeMessageListener('AccessFu:MoveCursor', moveCursor);
|
||||
removeMessageListener('AccessFu:ShowCurrent', showCurrent);
|
||||
removeMessageListener('AccessFu:Activate', activateCurrent);
|
||||
removeMessageListener('AccessFu:ContextMenu', activateContextMenu);
|
||||
removeMessageListener('AccessFu:Scroll', scroll);
|
||||
|
|
|
@ -14,8 +14,8 @@ EXPORT_LIBRARY = 1
|
|||
LIBXUL_LIBRARY = 1
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
|
||||
LOCAL_INCLUDES += \
|
||||
-I$(srcdir) \
|
||||
|
|
|
@ -235,7 +235,13 @@ let FormAssistant = {
|
|||
|
||||
this._documentEncoder = null;
|
||||
if (this._editor) {
|
||||
this._editor.removeEditorObserver(this);
|
||||
// When the nsIFrame of the input element is reconstructed by
|
||||
// CSS restyling, the editor observers are removed. Catch
|
||||
// [nsIEditor.removeEditorObserver] failure exception if that
|
||||
// happens.
|
||||
try {
|
||||
this._editor.removeEditorObserver(this);
|
||||
} catch (e) {}
|
||||
this._editor = null;
|
||||
}
|
||||
|
||||
|
|
|
@ -179,6 +179,16 @@ SettingsListener.observe('language.current', 'en-US', function(value) {
|
|||
function(value) {
|
||||
Services.prefs.setBoolPref('ril.radio.disabled', value);
|
||||
});
|
||||
|
||||
SettingsListener.observe('wap.UAProf.url', '',
|
||||
function(value) {
|
||||
Services.prefs.setCharPref('wap.UAProf.url', value);
|
||||
});
|
||||
|
||||
SettingsListener.observe('wap.UAProf.tagname', 'x-wap-profile',
|
||||
function(value) {
|
||||
Services.prefs.setCharPref('wap.UAProf.tagname', value);
|
||||
});
|
||||
})();
|
||||
|
||||
//=================== DeviceInfo ====================
|
||||
|
|
|
@ -61,6 +61,15 @@ DirectoryProvider.prototype = {
|
|||
persistent.value = true;
|
||||
return file;
|
||||
}
|
||||
if (prop == "ProfD") {
|
||||
let dir = Cc["@mozilla.org/file/local;1"]
|
||||
.createInstance(Ci.nsILocalFile);
|
||||
dir.initWithPath(LOCAL_DIR+"/tests/profile");
|
||||
if (dir.exists()) {
|
||||
persistent.value = true;
|
||||
return dir;
|
||||
}
|
||||
}
|
||||
if (prop == "coreAppsDir") {
|
||||
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile)
|
||||
file.initWithPath("/system/b2g");
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"revision": "37d94f0bacee10e768aca70b2ea6acab378ebed5",
|
||||
"revision": "34a53279dad496e201616f5e782bd58ef6d38ae5",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
|
|
@ -525,6 +525,7 @@
|
|||
@BINPATH@/components/ActivityProxy.js
|
||||
@BINPATH@/components/ActivityRequestHandler.js
|
||||
@BINPATH@/components/ActivityWrapper.js
|
||||
@BINPATH@/components/ActivityMessageConfigurator.js
|
||||
|
||||
@BINPATH@/components/TCPSocket.js
|
||||
@BINPATH@/components/TCPSocketParentIntermediary.js
|
||||
|
|
|
@ -6868,7 +6868,7 @@ var gIdentityHandler = {
|
|||
continue;
|
||||
let menuitem = document.createElement("menuitem");
|
||||
menuitem.setAttribute("value", state);
|
||||
menuitem.setAttribute("label", SitePermissions.getStateLabel(state));
|
||||
menuitem.setAttribute("label", SitePermissions.getStateLabel(aPermission, state));
|
||||
menupopup.appendChild(menuitem);
|
||||
}
|
||||
menulist.appendChild(menupopup);
|
||||
|
|
|
@ -134,7 +134,7 @@ function createRow(aPartId) {
|
|||
for (let state of SitePermissions.getAvailableStates(aPartId)) {
|
||||
let radio = document.createElement("radio");
|
||||
radio.setAttribute("id", aPartId + "#" + state);
|
||||
radio.setAttribute("label", SitePermissions.getStateLabel(state));
|
||||
radio.setAttribute("label", SitePermissions.getStateLabel(aPartId, state));
|
||||
radio.setAttribute("command", commandId);
|
||||
radiogroup.appendChild(radio);
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@ let Cu = Components.utils;
|
|||
|
||||
const appStartup = Services.startup;
|
||||
|
||||
Cu.import("resource://gre/modules/ResetProfile.jsm");
|
||||
|
||||
let defaultToReset = false;
|
||||
|
||||
function restartApp() {
|
||||
|
@ -69,7 +71,7 @@ function onLoad() {
|
|||
if (appStartup.automaticSafeModeNecessary) {
|
||||
document.getElementById("autoSafeMode").hidden = false;
|
||||
document.getElementById("safeMode").hidden = true;
|
||||
if (resetSupported()) {
|
||||
if (ResetProfile.resetSupported()) {
|
||||
populateResetPane("resetProfileItems");
|
||||
document.getElementById("resetProfile").hidden = false;
|
||||
} else {
|
||||
|
@ -77,7 +79,7 @@ function onLoad() {
|
|||
document.documentElement.getButton("extra1").hidden = true;
|
||||
}
|
||||
} else {
|
||||
if (!resetSupported()) {
|
||||
if (!ResetProfile.resetSupported()) {
|
||||
// Hide the reset button and text if it's not supported.
|
||||
document.documentElement.getButton("extra1").hidden = true;
|
||||
document.getElementById("resetProfileInstead").hidden = true;
|
||||
|
|
|
@ -51,7 +51,6 @@ endif
|
|||
# The following tests are disabled because they are unreliable:
|
||||
# browser_bug423833.js is bug 428712
|
||||
# browser_sanitize-download-history.js is bug 432425
|
||||
# browser_aboutHome.js is bug 890409
|
||||
#
|
||||
# browser_sanitizeDialog_treeView.js is disabled until the tree view is added
|
||||
# back to the clear recent history dialog (sanitize.xul), if it ever is (bug
|
||||
|
@ -72,6 +71,7 @@ MOCHITEST_BROWSER_FILES = \
|
|||
blockPluginVulnerableNoUpdate.xml \
|
||||
blockPluginVulnerableUpdatable.xml \
|
||||
browser_aboutHealthReport.js \
|
||||
browser_aboutHome.js \
|
||||
browser_aboutSyncProgress.js \
|
||||
browser_addKeywordSearch.js \
|
||||
browser_addon_bar_aomlistener.js \
|
||||
|
|
|
@ -104,23 +104,23 @@ let gTests = [
|
|||
let numSearchesBefore = 0;
|
||||
let deferred = Promise.defer();
|
||||
let doc = gBrowser.contentDocument;
|
||||
let engineName = doc.documentElement.getAttribute("searchEngineName");
|
||||
|
||||
// We rely on the listener in browser.js being installed and fired before
|
||||
// this one. If this ever changes, we should add an executeSoon() or similar.
|
||||
doc.addEventListener("AboutHomeSearchEvent", function onSearch(e) {
|
||||
let engineName = doc.documentElement.getAttribute("searchEngineName");
|
||||
is(e.detail, engineName, "Detail is search engine name");
|
||||
|
||||
gBrowser.stop();
|
||||
|
||||
getNumberOfSearches().then(num => {
|
||||
getNumberOfSearches(engineName).then(num => {
|
||||
is(num, numSearchesBefore + 1, "One more search recorded.");
|
||||
deferred.resolve();
|
||||
});
|
||||
}, true, true);
|
||||
|
||||
// Get the current number of recorded searches.
|
||||
getNumberOfSearches().then(num => {
|
||||
getNumberOfSearches(engineName).then(num => {
|
||||
numSearchesBefore = num;
|
||||
|
||||
info("Perform a search.");
|
||||
|
@ -263,6 +263,7 @@ function test()
|
|||
{
|
||||
waitForExplicitFinish();
|
||||
requestLongerTimeout(2);
|
||||
ignoreAllUncaughtExceptions();
|
||||
|
||||
Task.spawn(function () {
|
||||
for (let test of gTests) {
|
||||
|
@ -394,9 +395,12 @@ function promiseBrowserAttributes(aTab)
|
|||
/**
|
||||
* Retrieves the number of about:home searches recorded for the current day.
|
||||
*
|
||||
* @param aEngineName
|
||||
* name of the setup search engine.
|
||||
*
|
||||
* @return {Promise} Returns a promise resolving to the number of searches.
|
||||
*/
|
||||
function getNumberOfSearches() {
|
||||
function getNumberOfSearches(aEngineName) {
|
||||
let reporter = Components.classes["@mozilla.org/datareporting/service;1"]
|
||||
.getService()
|
||||
.wrappedJSObject
|
||||
|
@ -419,17 +423,15 @@ function getNumberOfSearches() {
|
|||
// different days. Tests are always run with an empty profile so there
|
||||
// are no searches from yesterday, normally. Should the test happen to run
|
||||
// past midnight we make sure to count them in as well.
|
||||
return getNumberOfSearchesByDate(data, now) +
|
||||
getNumberOfSearchesByDate(data, yday);
|
||||
return getNumberOfSearchesByDate(aEngineName, data, now) +
|
||||
getNumberOfSearchesByDate(aEngineName, data, yday);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getNumberOfSearchesByDate(aData, aDate) {
|
||||
function getNumberOfSearchesByDate(aEngineName, aData, aDate) {
|
||||
if (aData.days.hasDay(aDate)) {
|
||||
let doc = gBrowser.contentDocument;
|
||||
let engineName = doc.documentElement.getAttribute("searchEngineName");
|
||||
let id = Services.search.getEngineByName(engineName).identifier;
|
||||
let id = Services.search.getEngineByName(aEngineName).identifier;
|
||||
|
||||
let day = aData.days.getDay(aDate);
|
||||
let field = id + ".abouthome";
|
||||
|
|
|
@ -200,8 +200,24 @@ function checkSocialUI(win) {
|
|||
let active = Social.providers.length > 0 && !win.SocialUI._chromeless &&
|
||||
!PrivateBrowsingUtils.isWindowPrivate(win);
|
||||
|
||||
// some local helpers to avoid log-spew for the many checks made here.
|
||||
let numGoodTests = 0, numTests = 0;
|
||||
function _ok(what, msg) {
|
||||
numTests++;
|
||||
if (!ok)
|
||||
ok(what, msg)
|
||||
else
|
||||
++numGoodTests;
|
||||
}
|
||||
function _is(a, b, msg) {
|
||||
numTests++;
|
||||
if (a != b)
|
||||
is(a, b, msg)
|
||||
else
|
||||
++numGoodTests;
|
||||
}
|
||||
function isbool(a, b, msg) {
|
||||
is(!!a, !!b, msg);
|
||||
_is(!!a, !!b, msg);
|
||||
}
|
||||
isbool(win.SocialSidebar.canShow, enabled, "social sidebar active?");
|
||||
if (enabled)
|
||||
|
@ -216,15 +232,15 @@ function checkSocialUI(win) {
|
|||
isbool(!doc.getElementById("social-toolbar-item").hidden, active, "toolbar items visible?");
|
||||
if (active) {
|
||||
if (!enabled) {
|
||||
ok(!win.SocialToolbar.button.style.listStyleImage, "toolbar button is default icon");
|
||||
_ok(!win.SocialToolbar.button.style.listStyleImage, "toolbar button is default icon");
|
||||
} else {
|
||||
is(win.SocialToolbar.button.style.listStyleImage, 'url("' + Social.defaultProvider.iconURL + '")', "toolbar button has provider icon");
|
||||
_is(win.SocialToolbar.button.style.listStyleImage, 'url("' + Social.defaultProvider.iconURL + '")', "toolbar button has provider icon");
|
||||
}
|
||||
}
|
||||
// the menus should always have the provider name
|
||||
if (provider) {
|
||||
for (let id of ["menu_socialSidebar", "menu_socialAmbientMenu"])
|
||||
is(document.getElementById(id).getAttribute("label"), Social.provider.name, "element has the provider name");
|
||||
_is(document.getElementById(id).getAttribute("label"), Social.provider.name, "element has the provider name");
|
||||
}
|
||||
|
||||
// and for good measure, check all the social commands.
|
||||
|
@ -232,10 +248,12 @@ function checkSocialUI(win) {
|
|||
isbool(!doc.getElementById("Social:ToggleNotifications").hidden, enabled, "Social:ToggleNotifications visible?");
|
||||
isbool(!doc.getElementById("Social:FocusChat").hidden, enabled && Social.haveLoggedInUser(), "Social:FocusChat visible?");
|
||||
isbool(doc.getElementById("Social:FocusChat").getAttribute("disabled"), enabled ? "false" : "true", "Social:FocusChat disabled?");
|
||||
is(doc.getElementById("Social:TogglePageMark").getAttribute("disabled"), canMark ? "false" : "true", "Social:TogglePageMark enabled?");
|
||||
_is(doc.getElementById("Social:TogglePageMark").getAttribute("disabled"), canMark ? "false" : "true", "Social:TogglePageMark enabled?");
|
||||
|
||||
// broadcasters.
|
||||
isbool(!doc.getElementById("socialActiveBroadcaster").hidden, active, "socialActiveBroadcaster hidden?");
|
||||
// and report on overall success of failure of the various checks here.
|
||||
is(numGoodTests, numTests, "The Social UI tests succeeded.")
|
||||
}
|
||||
|
||||
// blocklist testing
|
||||
|
|
|
@ -14,6 +14,7 @@ MOCHITEST_BROWSER_FILES = \
|
|||
head.js \
|
||||
browser_privatebrowsing_aboutHomeButtonAfterWindowClose.js \
|
||||
browser_privatebrowsing_aboutSessionRestore.js \
|
||||
browser_privatebrowsing_cache.js \
|
||||
browser_privatebrowsing_certexceptionsui.js \
|
||||
browser_privatebrowsing_concurrent.js \
|
||||
browser_privatebrowsing_concurrent_page.html \
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// Check about:cache after private browsing
|
||||
// This test covers MozTrap test 6047
|
||||
// bug 880621
|
||||
|
||||
let tmp = {};
|
||||
|
||||
Cc["@mozilla.org/moz/jssubscript-loader;1"]
|
||||
.getService(Ci.mozIJSSubScriptLoader)
|
||||
.loadSubScript("chrome://browser/content/sanitize.js", tmp);
|
||||
|
||||
let Sanitizer = tmp.Sanitizer;
|
||||
|
||||
function test() {
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
sanitizeCache();
|
||||
|
||||
let nrEntriesR1 = get_device_entry_count("disk");
|
||||
is (nrEntriesR1, 0, "Disk cache reports 0KB and has no entries");
|
||||
|
||||
get_cache_for_private_window();
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
let prefs = Services.prefs.getBranch("privacy.cpd.");
|
||||
|
||||
prefs.clearUserPref("history");
|
||||
prefs.clearUserPref("downloads");
|
||||
prefs.clearUserPref("cache");
|
||||
prefs.clearUserPref("cookies");
|
||||
prefs.clearUserPref("formdata");
|
||||
prefs.clearUserPref("offlineApps");
|
||||
prefs.clearUserPref("passwords");
|
||||
prefs.clearUserPref("sessions");
|
||||
prefs.clearUserPref("siteSettings");
|
||||
}
|
||||
|
||||
function sanitizeCache() {
|
||||
|
||||
let s = new Sanitizer();
|
||||
s.ignoreTimespan = false;
|
||||
s.prefDomain = "privacy.cpd.";
|
||||
|
||||
let prefs = gPrefService.getBranch(s.prefDomain);
|
||||
prefs.setBoolPref("history", false);
|
||||
prefs.setBoolPref("downloads", false);
|
||||
prefs.setBoolPref("cache", true);
|
||||
prefs.setBoolPref("cookies", false);
|
||||
prefs.setBoolPref("formdata", false);
|
||||
prefs.setBoolPref("offlineApps", false);
|
||||
prefs.setBoolPref("passwords", false);
|
||||
prefs.setBoolPref("sessions", false);
|
||||
prefs.setBoolPref("siteSettings", false);
|
||||
|
||||
s.sanitize();
|
||||
}
|
||||
|
||||
function get_cache_service() {
|
||||
return Components.classes["@mozilla.org/network/cache-service;1"]
|
||||
.getService(Components.interfaces.nsICacheService);
|
||||
}
|
||||
|
||||
function get_device_entry_count(device) {
|
||||
var cs = get_cache_service();
|
||||
var entry_count = -1;
|
||||
|
||||
var visitor = {
|
||||
visitDevice: function (deviceID, deviceInfo) {
|
||||
if (device == deviceID) {
|
||||
entry_count = deviceInfo.entryCount;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
visitEntry: function (deviceID, entryInfo) {
|
||||
do_throw("nsICacheVisitor.visitEntry should not be called " +
|
||||
"when checking the availability of devices");
|
||||
}
|
||||
};
|
||||
|
||||
cs.visitEntries(visitor);
|
||||
return entry_count;
|
||||
}
|
||||
|
||||
function get_cache_for_private_window () {
|
||||
let win = OpenBrowserWindow({private: true});
|
||||
win.addEventListener("load", function () {
|
||||
win.removeEventListener("load", arguments.callee, false);
|
||||
|
||||
executeSoon(function() {
|
||||
|
||||
ok(true, "The private window got loaded");
|
||||
|
||||
let tab = win.gBrowser.addTab("http://example.org");
|
||||
win.gBrowser.selectedTab = tab;
|
||||
let newTabBrowser = win.gBrowser.getBrowserForTab(tab);
|
||||
|
||||
newTabBrowser.addEventListener("load", function eventHandler() {
|
||||
newTabBrowser.removeEventListener("load", eventHandler, true);
|
||||
|
||||
executeSoon(function() {
|
||||
|
||||
let nrEntriesP = get_device_entry_count("memory");
|
||||
is (nrEntriesP, 1, "Memory cache reports some entries from example.org domain");
|
||||
|
||||
let nrEntriesR2 = get_device_entry_count("disk");
|
||||
is (nrEntriesR2, 0, "Disk cache reports 0KB and has no entries");
|
||||
|
||||
cleanup();
|
||||
|
||||
win.close();
|
||||
finish();
|
||||
});
|
||||
}, true);
|
||||
});
|
||||
}, false);
|
||||
}
|
|
@ -95,7 +95,6 @@ MOCHITEST_BROWSER_TESTS = \
|
|||
browser_dbg_bug737803_editor_actual_location.js \
|
||||
browser_dbg_bug786070_hide_nonenums.js \
|
||||
browser_dbg_bug868163_highight_on_pause.js \
|
||||
browser_dbg_bug883220_raise_on_pause.js \
|
||||
browser_dbg_displayName.js \
|
||||
browser_dbg_pause-exceptions.js \
|
||||
browser_dbg_pause-exceptions-reload.js \
|
||||
|
@ -148,8 +147,11 @@ MOCHITEST_BROWSER_PAGES = \
|
|||
test-pause-exceptions-reload.html \
|
||||
$(NULL)
|
||||
|
||||
# Bug 888811 & bug 891176:
|
||||
# Disable browser_dbg_bug883220_raise_on_pause.js due to frequent failures
|
||||
ifneq (Linux,$(OS_ARCH))
|
||||
MOCHITEST_BROWSER_TESTS += \
|
||||
browser_dbg_bug883220_raise_on_pause.js \
|
||||
browser_dbg_createChrome.js \
|
||||
$(NULL)
|
||||
else
|
||||
|
|
|
@ -26,7 +26,9 @@ const { PROFILE_IDLE, PROFILE_COMPLETED, PROFILE_RUNNING } = require("devtools/p
|
|||
function Cleopatra(panel, opts) {
|
||||
let doc = panel.document;
|
||||
let win = panel.window;
|
||||
let { uid, name, showPlatformData } = opts;
|
||||
let { uid, name } = opts;
|
||||
let spd = opts.showPlatformData;
|
||||
let ext = opts.external;
|
||||
|
||||
EventEmitter.decorate(this);
|
||||
|
||||
|
@ -41,7 +43,7 @@ function Cleopatra(panel, opts) {
|
|||
this.iframe = doc.createElement("iframe");
|
||||
this.iframe.setAttribute("flex", "1");
|
||||
this.iframe.setAttribute("id", "profiler-cleo-" + uid);
|
||||
this.iframe.setAttribute("src", "cleopatra.html?uid=" + uid + "&showPlatformData=" + showPlatformData);
|
||||
this.iframe.setAttribute("src", "cleopatra.html?uid=" + uid + "&spd=" + spd + "&ext=" + ext);
|
||||
this.iframe.setAttribute("hidden", "true");
|
||||
|
||||
// Append our iframe and subscribe to postMessage events.
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
var gInstanceUID;
|
||||
var gParsedQS;
|
||||
var gHideSourceLinks;
|
||||
|
||||
function getParam(key) {
|
||||
if (gParsedQS)
|
||||
|
@ -93,6 +94,7 @@ window.addEventListener("message", onParentMessage);
|
|||
* in the light mode and creates all the UI we need.
|
||||
*/
|
||||
function initUI() {
|
||||
gHideSourceLinks = getParam("ext") === "true";
|
||||
gLightMode = true;
|
||||
|
||||
gFileList = { profileParsingFinished: function () {} };
|
||||
|
@ -106,25 +108,6 @@ function initUI() {
|
|||
|
||||
container.appendChild(gMainArea);
|
||||
document.body.appendChild(container);
|
||||
|
||||
var startButton = document.createElement("button");
|
||||
startButton.innerHTML = gStrings.getStr("profiler.start");
|
||||
startButton.addEventListener("click", function (event) {
|
||||
event.target.setAttribute("disabled", true);
|
||||
notifyParent("start");
|
||||
}, false);
|
||||
|
||||
var stopButton = document.createElement("button");
|
||||
stopButton.innerHTML = gStrings.getStr("profiler.stop");
|
||||
stopButton.addEventListener("click", function (event) {
|
||||
event.target.setAttribute("disabled", true);
|
||||
notifyParent("stop");
|
||||
}, false);
|
||||
|
||||
var message = document.createElement("div");
|
||||
message.className = "message";
|
||||
message.innerHTML = "To start profiling click the button above.";
|
||||
gMainArea.appendChild(message);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -224,7 +207,8 @@ function enterFinishedProfileUI() {
|
|||
}
|
||||
}
|
||||
|
||||
if (getParam("showPlatformData") !== "true")
|
||||
// Show platform data?
|
||||
if (getParam("spd") !== "true")
|
||||
toggleJavascriptOnly();
|
||||
}
|
||||
|
||||
|
|
|
@ -458,7 +458,7 @@ TreeView.prototype = {
|
|||
'<span class="resourceIcon" data-resource="' + node.library + '"></span> ' +
|
||||
'<span class="functionName">' + nodeName + '</span>' +
|
||||
'<span class="libraryName">' + libName + '</span>' +
|
||||
(nodeName === '(total)' ? '' :
|
||||
((nodeName === '(total)' || gHideSourceLinks) ? '' :
|
||||
'<input type="button" value="Focus Callstack" title="Focus Callstack" class="focusCallstackButton" tabindex="-1">');
|
||||
},
|
||||
_resolveChildren: function TreeView__resolveChildren(div, childrenCollapsedValue) {
|
||||
|
|
|
@ -4,14 +4,18 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const { Cu } = require("chrome");
|
||||
const { Cu, Cc, Ci, components } = require("chrome");
|
||||
|
||||
const {
|
||||
PROFILE_IDLE,
|
||||
PROFILE_RUNNING,
|
||||
PROFILE_COMPLETED,
|
||||
SHOW_PLATFORM_DATA
|
||||
SHOW_PLATFORM_DATA,
|
||||
L10N_BUNDLE
|
||||
} = require("devtools/profiler/consts");
|
||||
|
||||
const { TextEncoder } = Cu.import("resource://gre/modules/commonjs/toolkit/loader.js", {});
|
||||
|
||||
var EventEmitter = require("devtools/shared/event-emitter");
|
||||
var promise = require("sdk/core/promise");
|
||||
var Cleopatra = require("devtools/profiler/cleopatra");
|
||||
|
@ -21,6 +25,11 @@ var ProfilerController = require("devtools/profiler/controller");
|
|||
Cu.import("resource:///modules/devtools/gDevTools.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/Console.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
|
||||
Cu.import("resource://gre/modules/osfile.jsm");
|
||||
Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||
|
||||
loader.lazyGetter(this, "L10N", () => new ViewHelpers.L10N(L10N_BUNDLE));
|
||||
|
||||
/**
|
||||
* Profiler panel. It is responsible for creating and managing
|
||||
|
@ -80,7 +89,8 @@ ProfilerPanel.prototype = {
|
|||
let doc = this.document;
|
||||
|
||||
return {
|
||||
get record() doc.querySelector("#profiler-start")
|
||||
get record() doc.querySelector("#profiler-start"),
|
||||
get import() doc.querySelector("#profiler-import"),
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -104,7 +114,7 @@ ProfilerPanel.prototype = {
|
|||
this._runningUid = profile ? profile.uid : null;
|
||||
|
||||
if (this._runningUid)
|
||||
btn.setAttribute("checked", true)
|
||||
btn.setAttribute("checked", true);
|
||||
else
|
||||
btn.removeAttribute("checked");
|
||||
},
|
||||
|
@ -152,13 +162,22 @@ ProfilerPanel.prototype = {
|
|||
let deferred = promise.defer();
|
||||
|
||||
this.controller = new ProfilerController(this.target);
|
||||
|
||||
this.sidebar = new Sidebar(this.document.querySelector("#profiles-list"));
|
||||
this.sidebar.widget.addEventListener("select", (ev) => {
|
||||
if (!ev.detail)
|
||||
return;
|
||||
|
||||
let profile = this.profiles.get(ev.detail.attachment.uid);
|
||||
this.sidebar.on("save", (_, uid) => {
|
||||
let profile = this.profiles.get(uid);
|
||||
|
||||
if (!profile.data)
|
||||
return void Cu.reportError("Can't save profile because there's no data.");
|
||||
|
||||
this.openFileDialog({ mode: "save", name: profile.name }).then((file) => {
|
||||
if (file)
|
||||
this.saveProfile(file, profile.data);
|
||||
});
|
||||
});
|
||||
|
||||
this.sidebar.on("select", (_, uid) => {
|
||||
let profile = this.profiles.get(uid);
|
||||
this.activeProfile = profile;
|
||||
|
||||
if (profile.isReady) {
|
||||
|
@ -175,18 +194,18 @@ ProfilerPanel.prototype = {
|
|||
btn.addEventListener("click", () => this.toggleRecording(), false);
|
||||
btn.removeAttribute("disabled");
|
||||
|
||||
let imp = this.controls.import;
|
||||
imp.addEventListener("click", () => {
|
||||
this.openFileDialog({ mode: "open" }).then((file) => {
|
||||
if (file)
|
||||
this.loadProfile(file);
|
||||
});
|
||||
}, false);
|
||||
imp.removeAttribute("disabled");
|
||||
|
||||
// Import queued profiles.
|
||||
for (let [name, data] of this.controller.profiles) {
|
||||
let profile = this.createProfile(name);
|
||||
profile.isStarted = false;
|
||||
profile.isFinished = true;
|
||||
profile.data = data.data;
|
||||
profile.parse(data.data, () => this.emit("parsed"));
|
||||
|
||||
this.sidebar.setProfileState(profile, PROFILE_COMPLETED);
|
||||
if (!this.sidebar.selectedItem) {
|
||||
this.sidebar.selectedItem = this.sidebar.getItemByProfile(profile);
|
||||
}
|
||||
this.importProfile(name, data.data);
|
||||
}
|
||||
|
||||
this.isReady = true;
|
||||
|
@ -195,15 +214,7 @@ ProfilerPanel.prototype = {
|
|||
});
|
||||
|
||||
this.controller.on("profileEnd", (_, data) => {
|
||||
let profile = this.createProfile(data.name);
|
||||
profile.isStarted = false;
|
||||
profile.isFinished = true;
|
||||
profile.data = data.data;
|
||||
profile.parse(data.data, () => this.emit("parsed"));
|
||||
|
||||
this.sidebar.setProfileState(profile, PROFILE_COMPLETED);
|
||||
if (!this.sidebar.selectedItem)
|
||||
this.sidebar.selectedItem = this.sidebar.getItemByProfile(profile);
|
||||
this.importProfile(data.name, data.data);
|
||||
|
||||
if (this.recordingProfile && !data.fromConsole)
|
||||
this.recordingProfile = null;
|
||||
|
@ -227,9 +238,9 @@ ProfilerPanel.prototype = {
|
|||
* @param string name
|
||||
* (optional) name of the new profile
|
||||
*
|
||||
* @return ProfilerPanel
|
||||
* @return Profile
|
||||
*/
|
||||
createProfile: function (name) {
|
||||
createProfile: function (name, opts={}) {
|
||||
if (name && this.getProfileByName(name)) {
|
||||
return this.getProfileByName(name);
|
||||
}
|
||||
|
@ -239,7 +250,8 @@ ProfilerPanel.prototype = {
|
|||
let profile = new Cleopatra(this, {
|
||||
uid: uid,
|
||||
name: name,
|
||||
showPlatformData: this.showPlatformData
|
||||
showPlatformData: this.showPlatformData,
|
||||
external: opts.external
|
||||
});
|
||||
|
||||
this.profiles.set(uid, profile);
|
||||
|
@ -249,6 +261,30 @@ ProfilerPanel.prototype = {
|
|||
return profile;
|
||||
},
|
||||
|
||||
/**
|
||||
* Imports profile data
|
||||
*
|
||||
* @param string name, new profile name
|
||||
* @param object data, profile data to import
|
||||
* @param object opts, (optional) if property 'external' is found
|
||||
* Cleopatra will hide arrow buttons.
|
||||
*
|
||||
* @return Profile
|
||||
*/
|
||||
importProfile: function (name, data, opts={}) {
|
||||
let profile = this.createProfile(name, { external: opts.external });
|
||||
profile.isStarted = false;
|
||||
profile.isFinished = true;
|
||||
profile.data = data;
|
||||
profile.parse(data, () => this.emit("parsed"));
|
||||
|
||||
this.sidebar.setProfileState(profile, PROFILE_COMPLETED);
|
||||
if (!this.sidebar.selectedItem)
|
||||
this.sidebar.selectedItem = this.sidebar.getItemByProfile(profile);
|
||||
|
||||
return profile;
|
||||
},
|
||||
|
||||
/**
|
||||
* Starts or stops profile recording.
|
||||
*/
|
||||
|
@ -422,7 +458,7 @@ ProfilerPanel.prototype = {
|
|||
*/
|
||||
displaySource: function PP_displaySource(data, onOpen=function() {}) {
|
||||
let win = this.window;
|
||||
let panelWin, timeout;
|
||||
let panelWin;
|
||||
|
||||
function onSourceShown(event) {
|
||||
if (event.detail.url !== data.uri) {
|
||||
|
@ -455,6 +491,81 @@ ProfilerPanel.prototype = {
|
|||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Opens a normal file dialog.
|
||||
*
|
||||
* @params object opts, (optional) property 'mode' can be used to
|
||||
* specify which dialog to open. Can be either
|
||||
* 'save' or 'open' (default is 'open').
|
||||
* @return promise
|
||||
*/
|
||||
openFileDialog: function (opts={}) {
|
||||
let deferred = promise.defer();
|
||||
|
||||
let picker = Ci.nsIFilePicker;
|
||||
let fp = Cc["@mozilla.org/filepicker;1"].createInstance(picker);
|
||||
let { name, mode } = opts;
|
||||
let save = mode === "save";
|
||||
let title = L10N.getStr(save ? "profiler.saveFileAs" : "profiler.openFile");
|
||||
|
||||
fp.init(this.window, title, save ? picker.modeSave : picker.modeOpen);
|
||||
fp.appendFilter("JSON", "*.json");
|
||||
fp.appendFilters(picker.filterText | picker.filterAll);
|
||||
|
||||
if (save)
|
||||
fp.defaultString = (name || "profile") + ".json";
|
||||
|
||||
fp.open((result) => {
|
||||
deferred.resolve(result === picker.returnCancel ? null : fp.file);
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
/**
|
||||
* Saves profile data to disk
|
||||
*
|
||||
* @param File file
|
||||
* @param object data
|
||||
*
|
||||
* @return promise
|
||||
*/
|
||||
saveProfile: function (file, data) {
|
||||
let encoder = new TextEncoder();
|
||||
let buffer = encoder.encode(JSON.stringify({ profile: data }, null, " "));
|
||||
let opts = { tmpPath: file.path + ".tmp" };
|
||||
|
||||
return OS.File.writeAtomic(file.path, buffer, opts);
|
||||
},
|
||||
|
||||
/**
|
||||
* Reads profile data from disk
|
||||
*
|
||||
* @param File file
|
||||
* @return promise
|
||||
*/
|
||||
loadProfile: function (file) {
|
||||
let deferred = promise.defer();
|
||||
let ch = NetUtil.newChannel(file);
|
||||
ch.contentType = "application/json";
|
||||
|
||||
NetUtil.asyncFetch(ch, (input, status) => {
|
||||
if (!components.isSuccessCode(status)) throw new Error(status);
|
||||
|
||||
let conv = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
|
||||
.createInstance(Ci.nsIScriptableUnicodeConverter);
|
||||
conv.charset = "UTF-8";
|
||||
|
||||
let data = NetUtil.readInputStreamToString(input, input.available());
|
||||
data = conv.ConvertToUnicode(data);
|
||||
this.importProfile(file.leafName, JSON.parse(data).profile, { external: true });
|
||||
|
||||
deferred.resolve();
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
/**
|
||||
* Cleanup.
|
||||
*/
|
||||
|
|
|
@ -20,7 +20,13 @@
|
|||
<vbox class="profiler-sidebar">
|
||||
<toolbar class="devtools-toolbar">
|
||||
<hbox id="profiler-controls">
|
||||
<toolbarbutton id="profiler-start" class="devtools-toolbarbutton"/>
|
||||
<toolbarbutton id="profiler-start"
|
||||
class="devtools-toolbarbutton"
|
||||
disabled="true"/>
|
||||
<toolbarbutton id="profiler-import"
|
||||
class="devtools-toolbarbutton"
|
||||
disabled="true"
|
||||
label="&importProfile.label;"/>
|
||||
</hbox>
|
||||
</toolbar>
|
||||
|
||||
|
|
|
@ -25,27 +25,58 @@ function Sidebar(el) {
|
|||
this.document = el.ownerDocument;
|
||||
this.widget = new SideMenuWidget(el);
|
||||
this.widget.notice = L10N.getStr("profiler.sidebarNotice");
|
||||
|
||||
this.widget.addEventListener("select", (ev) => {
|
||||
if (!ev.detail)
|
||||
return;
|
||||
|
||||
this.emit("select", parseInt(ev.detail.value, 10));
|
||||
});
|
||||
}
|
||||
|
||||
Sidebar.prototype = Heritage.extend(WidgetMethods, {
|
||||
/**
|
||||
* Adds a new item for a profile to the sidebar. Markup
|
||||
* example:
|
||||
*
|
||||
* <vbox id="profile-1" class="profiler-sidebar-item">
|
||||
* <h3>Profile 1</h3>
|
||||
* <hbox>
|
||||
* <span flex="1">Completed</span>
|
||||
* <a>Save</a>
|
||||
* </hbox>
|
||||
* </vbox>
|
||||
*
|
||||
*/
|
||||
addProfile: function (profile) {
|
||||
let doc = this.document;
|
||||
let box = doc.createElement("vbox");
|
||||
let vbox = doc.createElement("vbox");
|
||||
let hbox = doc.createElement("hbox");
|
||||
let h3 = doc.createElement("h3");
|
||||
let span = doc.createElement("span");
|
||||
let save = doc.createElement("a");
|
||||
|
||||
box.id = "profile-" + profile.uid;
|
||||
box.className = "profiler-sidebar-item";
|
||||
vbox.id = "profile-" + profile.uid;
|
||||
vbox.className = "profiler-sidebar-item";
|
||||
|
||||
h3.textContent = profile.name;
|
||||
span.setAttribute("flex", 1);
|
||||
span.textContent = L10N.getStr("profiler.stateIdle");
|
||||
|
||||
box.appendChild(h3);
|
||||
box.appendChild(span);
|
||||
save.textContent = L10N.getStr("profiler.save");
|
||||
save.addEventListener("click", (ev) => {
|
||||
ev.preventDefault();
|
||||
this.emit("save", profile.uid);
|
||||
});
|
||||
|
||||
this.push([box], {
|
||||
hbox.appendChild(span);
|
||||
hbox.appendChild(save);
|
||||
|
||||
vbox.appendChild(h3);
|
||||
vbox.appendChild(hbox);
|
||||
|
||||
this.push([vbox, profile.uid], {
|
||||
attachment: {
|
||||
uid: profile.uid,
|
||||
name: profile.name,
|
||||
state: PROFILE_IDLE
|
||||
}
|
||||
|
@ -57,21 +88,24 @@ Sidebar.prototype = Heritage.extend(WidgetMethods, {
|
|||
},
|
||||
|
||||
getItemByProfile: function (profile) {
|
||||
return this.getItemForPredicate(item => item.attachment.uid === profile.uid);
|
||||
return this.getItemByValue(profile.uid.toString());
|
||||
},
|
||||
|
||||
setProfileState: function (profile, state) {
|
||||
let item = this.getItemByProfile(profile);
|
||||
let label = item.target.querySelector(".profiler-sidebar-item > span");
|
||||
let label = item.target.querySelector(".profiler-sidebar-item > hbox > span");
|
||||
|
||||
switch (state) {
|
||||
case PROFILE_IDLE:
|
||||
item.target.setAttribute("state", "idle");
|
||||
label.textContent = L10N.getStr("profiler.stateIdle");
|
||||
break;
|
||||
case PROFILE_RUNNING:
|
||||
item.target.setAttribute("state", "running");
|
||||
label.textContent = L10N.getStr("profiler.stateRunning");
|
||||
break;
|
||||
case PROFILE_COMPLETED:
|
||||
item.target.setAttribute("state", "completed");
|
||||
label.textContent = L10N.getStr("profiler.stateCompleted");
|
||||
break;
|
||||
default: // Wrong state, do nothing.
|
||||
|
|
|
@ -23,6 +23,7 @@ MOCHITEST_BROWSER_TESTS = \
|
|||
browser_profiler_console_api_content.js \
|
||||
browser_profiler_escape.js \
|
||||
browser_profiler_gecko_data.js \
|
||||
browser_profiler_io.js \
|
||||
head.js \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const URL = "data:text/html;charset=utf8,<p>browser_profiler_io</p>";
|
||||
|
||||
let temp = {};
|
||||
Cu.import("resource://gre/modules/FileUtils.jsm", temp);
|
||||
let FileUtils = temp.FileUtils;
|
||||
let gTab, gPanel;
|
||||
|
||||
let gData = {
|
||||
"libs": "[]", // This property is not important for this test.
|
||||
"meta": {
|
||||
"version": 2,
|
||||
"interval": 1,
|
||||
"stackwalk": 0,
|
||||
"jank": 0,
|
||||
"processType": 0,
|
||||
"platform": "Macintosh",
|
||||
"oscpu": "Intel Mac OS X 10.8",
|
||||
"misc": "rv:25.0",
|
||||
"abi": "x86_64-gcc3",
|
||||
"toolkit": "cocoa",
|
||||
"product": "Firefox"
|
||||
},
|
||||
"threads": [
|
||||
{
|
||||
"samples": [
|
||||
{
|
||||
"name": "(root)",
|
||||
"frames": [
|
||||
{
|
||||
"location": "Startup::XRE_Main",
|
||||
"line": 3871
|
||||
},
|
||||
{
|
||||
"location": "Events::ProcessGeckoEvents",
|
||||
"line": 355
|
||||
},
|
||||
{
|
||||
"location": "Events::ProcessGeckoEvents",
|
||||
"line": 355
|
||||
}
|
||||
],
|
||||
"responsiveness": -0.002963,
|
||||
"time": 8.120823
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
setUp(URL, function onSetUp(tab, browser, panel) {
|
||||
gTab = tab;
|
||||
gPanel = panel;
|
||||
|
||||
let file = FileUtils.getFile("TmpD", ["tmpprofile.json"]);
|
||||
file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, parseInt("666", 8));
|
||||
|
||||
gPanel.saveProfile(file, gData).then(() => {dump("\n\nsup\n\n");}, () => {dump("\n\n:(((\n\n")})
|
||||
.then(gPanel.loadProfile.bind(gPanel, file))
|
||||
.then(checkData);
|
||||
});
|
||||
}
|
||||
|
||||
function checkData() {
|
||||
let profile = gPanel.activeProfile;
|
||||
let item = gPanel.sidebar.getItemByProfile(profile);
|
||||
let data = profile.data;
|
||||
|
||||
is(item.attachment.state, PROFILE_COMPLETED, "Profile is COMPLETED");
|
||||
is(gData.meta.oscpu, data.meta.oscpu, "Meta data is correct");
|
||||
is(gData.threads[0].samples.length, 1, "There's one sample");
|
||||
is(gData.threads[0].samples[0].name, "(root)", "Sample is correct");
|
||||
|
||||
tearDown(gTab, () => { gPanel = null; gTab = null; });
|
||||
}
|
|
@ -8,16 +8,56 @@
|
|||
|
||||
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-consoleiframes.html";
|
||||
|
||||
let expectedMessages = [
|
||||
{
|
||||
text: "main file",
|
||||
category: CATEGORY_WEBDEV,
|
||||
severity: SEVERITY_LOG,
|
||||
},
|
||||
{
|
||||
text: "blah",
|
||||
category: CATEGORY_JS,
|
||||
severity: SEVERITY_ERROR
|
||||
},
|
||||
{
|
||||
text: "iframe 2",
|
||||
category: CATEGORY_WEBDEV,
|
||||
severity: SEVERITY_LOG
|
||||
},
|
||||
{
|
||||
text: "iframe 3",
|
||||
category: CATEGORY_WEBDEV,
|
||||
severity: SEVERITY_LOG
|
||||
}
|
||||
];
|
||||
|
||||
// "iframe 1" console messages can be coalesced into one if they follow each
|
||||
// other in the sequence of messages (depending on timing). If they do not, then
|
||||
// they will be displayed in the console output independently, as separate
|
||||
// messages. This is why we need to match any of the following two rules.
|
||||
let expectedMessagesAny = [
|
||||
{
|
||||
name: "iframe 1 (count: 2)",
|
||||
text: "iframe 1",
|
||||
category: CATEGORY_WEBDEV,
|
||||
severity: SEVERITY_LOG,
|
||||
count: 2
|
||||
},
|
||||
{
|
||||
name: "iframe 1 (repeats: 2)",
|
||||
text: "iframe 1",
|
||||
category: CATEGORY_WEBDEV,
|
||||
severity: SEVERITY_LOG,
|
||||
repeats: 2
|
||||
},
|
||||
];
|
||||
|
||||
function test()
|
||||
{
|
||||
expectUncaughtException();
|
||||
addTab(TEST_URI);
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
|
||||
// Test for cached nsIConsoleMessages.
|
||||
Services.console.logStringMessage("test1 for bug859756");
|
||||
|
||||
info("open web console");
|
||||
openConsole(null, consoleOpened);
|
||||
}, true);
|
||||
|
@ -29,31 +69,16 @@ function consoleOpened(hud)
|
|||
|
||||
waitForMessages({
|
||||
webconsole: hud,
|
||||
messages: [
|
||||
{
|
||||
text: "main file",
|
||||
category: CATEGORY_WEBDEV,
|
||||
severity: SEVERITY_LOG,
|
||||
},
|
||||
{
|
||||
text: "blah",
|
||||
category: CATEGORY_JS,
|
||||
severity: SEVERITY_ERROR
|
||||
},
|
||||
{
|
||||
text: "iframe 1",
|
||||
category: CATEGORY_WEBDEV,
|
||||
severity: SEVERITY_LOG,
|
||||
count: 2
|
||||
},
|
||||
{
|
||||
text: "iframe 2",
|
||||
category: CATEGORY_WEBDEV,
|
||||
severity: SEVERITY_LOG
|
||||
}
|
||||
],
|
||||
messages: expectedMessages,
|
||||
}).then(() => {
|
||||
closeConsole(null, onWebConsoleClose);
|
||||
info("first messages matched");
|
||||
waitForMessages({
|
||||
webconsole: hud,
|
||||
messages: expectedMessagesAny,
|
||||
matchCondition: "any",
|
||||
}).then(() => {
|
||||
closeConsole(null, onWebConsoleClose);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -66,34 +91,17 @@ function onWebConsoleClose()
|
|||
function onBrowserConsoleOpen(hud)
|
||||
{
|
||||
ok(hud, "browser console opened");
|
||||
Services.console.logStringMessage("test2 for bug859756");
|
||||
|
||||
waitForMessages({
|
||||
webconsole: hud,
|
||||
messages: [
|
||||
{
|
||||
text: "main file",
|
||||
category: CATEGORY_WEBDEV,
|
||||
severity: SEVERITY_LOG,
|
||||
},
|
||||
{
|
||||
text: "blah",
|
||||
category: CATEGORY_JS,
|
||||
severity: SEVERITY_ERROR
|
||||
},
|
||||
{
|
||||
text: "iframe 1",
|
||||
category: CATEGORY_WEBDEV,
|
||||
severity: SEVERITY_LOG,
|
||||
count: 2
|
||||
},
|
||||
{
|
||||
text: "iframe 2",
|
||||
category: CATEGORY_WEBDEV,
|
||||
severity: SEVERITY_LOG
|
||||
}
|
||||
],
|
||||
messages: expectedMessages,
|
||||
}).then(() => {
|
||||
closeConsole(null, finishTest);
|
||||
info("first messages matched");
|
||||
waitForMessages({
|
||||
webconsole: hud,
|
||||
messages: expectedMessagesAny,
|
||||
matchCondition: "any",
|
||||
}).then(() => {
|
||||
closeConsole(null, finishTest);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -17,12 +17,10 @@ function tab1Loaded(aEvent) {
|
|||
browser.removeEventListener(aEvent.type, tab1Loaded, true);
|
||||
|
||||
win2 = OpenBrowserWindow();
|
||||
win2.addEventListener("load", win2Loaded, true);
|
||||
whenDelayedStartupFinished(win2, win2Loaded);
|
||||
}
|
||||
|
||||
function win2Loaded(aEvent) {
|
||||
win2.removeEventListener(aEvent.type, win2Loaded, true);
|
||||
|
||||
function win2Loaded() {
|
||||
tab2 = win2.gBrowser.addTab(TEST_URI);
|
||||
win2.gBrowser.selectedTab = tab2;
|
||||
tab2.linkedBrowser.addEventListener("load", tab2Loaded, true);
|
||||
|
@ -35,17 +33,14 @@ function tab2Loaded(aEvent) {
|
|||
function onWebConsoleOpen() {
|
||||
consolesOpened++;
|
||||
if (consolesOpened == 2) {
|
||||
Services.obs.removeObserver(onWebConsoleOpen, "web-console-created");
|
||||
executeSoon(closeConsoles);
|
||||
}
|
||||
}
|
||||
|
||||
Services.obs.addObserver(onWebConsoleOpen, "web-console-created", false);
|
||||
|
||||
function openConsoles() {
|
||||
try {
|
||||
let target1 = TargetFactory.forTab(tab1);
|
||||
gDevTools.showToolbox(target1, "webconsole");
|
||||
gDevTools.showToolbox(target1, "webconsole").then(onWebConsoleOpen);
|
||||
}
|
||||
catch (ex) {
|
||||
ok(false, "gDevTools.showToolbox(target1) exception: " + ex);
|
||||
|
@ -54,7 +49,7 @@ function tab2Loaded(aEvent) {
|
|||
|
||||
try {
|
||||
let target2 = TargetFactory.forTab(tab2);
|
||||
gDevTools.showToolbox(target2, "webconsole");
|
||||
gDevTools.showToolbox(target2, "webconsole").then(onWebConsoleOpen);
|
||||
}
|
||||
catch (ex) {
|
||||
ok(false, "gDevTools.showToolbox(target2) exception: " + ex);
|
||||
|
@ -62,25 +57,13 @@ function tab2Loaded(aEvent) {
|
|||
}
|
||||
}
|
||||
|
||||
let consolesClosed = 0;
|
||||
function onWebConsoleClose()
|
||||
{
|
||||
consolesClosed++;
|
||||
if (consolesClosed == 2) {
|
||||
Services.obs.removeObserver(onWebConsoleClose, "web-console-destroyed");
|
||||
executeSoon(testEnd);
|
||||
}
|
||||
}
|
||||
|
||||
function closeConsoles() {
|
||||
Services.obs.addObserver(onWebConsoleClose, "web-console-destroyed", false);
|
||||
|
||||
try {
|
||||
let target1 = TargetFactory.forTab(tab1);
|
||||
gDevTools.closeToolbox(target1).then(function() {
|
||||
try {
|
||||
let target2 = TargetFactory.forTab(tab2);
|
||||
gDevTools.closeToolbox(target2);
|
||||
gDevTools.closeToolbox(target2).then(testEnd);
|
||||
}
|
||||
catch (ex) {
|
||||
ok(false, "gDevTools.closeToolbox(target2) exception: " + ex);
|
||||
|
|
|
@ -35,15 +35,14 @@ function performTest() {
|
|||
Services.obs.removeObserver(TestObserver, "console-api-log-event");
|
||||
TestObserver = null;
|
||||
|
||||
waitForSuccess({
|
||||
name: "console.log() message",
|
||||
validatorFn: function()
|
||||
{
|
||||
return hud.outputNode.textContent.indexOf("foobarBug613013") > -1;
|
||||
},
|
||||
successFn: finishTest,
|
||||
failureFn: finishTest,
|
||||
});
|
||||
waitForMessages({
|
||||
webconsole: hud,
|
||||
messages: [{
|
||||
text: "foobarBug613013",
|
||||
category: CATEGORY_WEBDEV,
|
||||
severity: SEVERITY_LOG,
|
||||
}],
|
||||
}).then(finishTest);
|
||||
}
|
||||
|
||||
function test() {
|
||||
|
|
|
@ -855,6 +855,12 @@ function getMessageElementText(aElement)
|
|||
* @param object aOptions
|
||||
* Options for what you want to wait for:
|
||||
* - webconsole: the webconsole instance you work with.
|
||||
* - matchCondition: "any" or "all". Default: "all". The promise
|
||||
* returned by this function resolves when all of the messages are
|
||||
* matched, if the |matchCondition| is "all". If you set the condition to
|
||||
* "any" then the promise is resolved by any message rule that matches,
|
||||
* irrespective of order - waiting for messages stops whenever any rule
|
||||
* matches.
|
||||
* - messages: an array of objects that tells which messages to wait for.
|
||||
* Properties:
|
||||
* - text: string or RegExp to match the textContent of each new
|
||||
|
@ -905,6 +911,7 @@ function waitForMessages(aOptions)
|
|||
let rulesMatched = 0;
|
||||
let listenerAdded = false;
|
||||
let deferred = promise.defer();
|
||||
aOptions.matchCondition = aOptions.matchCondition || "all";
|
||||
|
||||
function checkText(aRule, aText)
|
||||
{
|
||||
|
@ -1154,9 +1161,15 @@ function waitForMessages(aOptions)
|
|||
}
|
||||
}
|
||||
|
||||
function allRulesMatched()
|
||||
{
|
||||
return aOptions.matchCondition == "all" && rulesMatched == rules.length ||
|
||||
aOptions.matchCondition == "any" && rulesMatched > 0;
|
||||
}
|
||||
|
||||
function maybeDone()
|
||||
{
|
||||
if (rulesMatched == rules.length) {
|
||||
if (allRulesMatched()) {
|
||||
if (listenerAdded) {
|
||||
webconsole.ui.off("messages-added", onMessagesAdded);
|
||||
webconsole.ui.off("messages-updated", onMessagesAdded);
|
||||
|
@ -1169,7 +1182,7 @@ function waitForMessages(aOptions)
|
|||
}
|
||||
|
||||
function testCleanup() {
|
||||
if (rulesMatched == rules.length) {
|
||||
if (allRulesMatched()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1198,7 +1211,7 @@ function waitForMessages(aOptions)
|
|||
|
||||
executeSoon(() => {
|
||||
onMessagesAdded("messages-added", webconsole.outputNode.childNodes);
|
||||
if (rulesMatched != rules.length) {
|
||||
if (!allRulesMatched()) {
|
||||
listenerAdded = true;
|
||||
registerCleanupFunction(testCleanup);
|
||||
webconsole.ui.on("messages-added", onMessagesAdded);
|
||||
|
|
|
@ -20,4 +20,8 @@
|
|||
|
||||
<!-- LOCALIZATION NOTE (profilerStop.label): This is the label for the
|
||||
- button that stops the profiler. -->
|
||||
<!ENTITY profilerStop.label "Stop">
|
||||
<!ENTITY profilerStop.label "Stop">
|
||||
|
||||
<!-- LOCALIZATION NOTE (profiler.importProfile): This string is displayed
|
||||
- on a button that opens a dialog to import a saved profile data file. -->
|
||||
<!ENTITY importProfile.label "Import…">
|
|
@ -102,4 +102,17 @@ profiler.stateCompleted=Completed
|
|||
# This string is displayed in the profiler sidebar when there are no
|
||||
# existing profiles to show (usually happens when the user opens the
|
||||
# profiler for the first time).
|
||||
profiler.sidebarNotice=There are no profiles yet.
|
||||
profiler.sidebarNotice=There are no profiles yet.
|
||||
|
||||
# LOCALIZATION NOTE (profiler.save)
|
||||
# This string is displayed as a label for a button that opens a Save File
|
||||
# dialog where user can save generated profiler to a file.
|
||||
profiler.save=Save
|
||||
|
||||
# LOCALIZATION NOTE (profiler.saveFileAs)
|
||||
# This string as a title for a Save File dialog.
|
||||
profiler.saveFileAs=Save Profile As
|
||||
|
||||
# LOCALIZATION NOTE (profiler.openFile)
|
||||
# This string as a title for a Open File dialog.
|
||||
profiler.openFile=Import Profile
|
|
@ -247,6 +247,8 @@ TopSitesView.prototype = {
|
|||
// fire a MozContextActionsChange event to update the context appbar
|
||||
let event = document.createEvent("Events");
|
||||
event.actions = [...nextContextActions];
|
||||
event.noun = tileGroup.contextNoun;
|
||||
event.qty = selectedTiles.length;
|
||||
event.initEvent("MozContextActionsChange", true, false);
|
||||
tileGroup.dispatchEvent(event);
|
||||
},0);
|
||||
|
|
|
@ -45,8 +45,10 @@ var Appbar = {
|
|||
|
||||
case 'MozContextActionsChange':
|
||||
let actions = aEvent.actions;
|
||||
let noun = aEvent.noun;
|
||||
let qty = aEvent.qty;
|
||||
// could transition in old, new buttons?
|
||||
this.showContextualActions(actions);
|
||||
this.showContextualActions(actions, noun, qty);
|
||||
break;
|
||||
|
||||
case "selectionchange":
|
||||
|
@ -158,33 +160,36 @@ var Appbar = {
|
|||
}
|
||||
},
|
||||
|
||||
showContextualActions: function(aVerbs) {
|
||||
showContextualActions: function(aVerbs, aNoun, aQty) {
|
||||
if (aVerbs.length)
|
||||
Elements.contextappbar.show();
|
||||
else
|
||||
Elements.contextappbar.hide();
|
||||
|
||||
let doc = document;
|
||||
// button element id to action verb lookup
|
||||
let buttonsMap = new Map();
|
||||
// Look up all of the buttons for the verbs that should be visible.
|
||||
let idsToVisibleVerbs = new Map();
|
||||
for (let verb of aVerbs) {
|
||||
let id = verb + "-selected-button";
|
||||
if (!doc.getElementById(id)) {
|
||||
if (!document.getElementById(id)) {
|
||||
throw new Error("Appbar.showContextualActions: no button for " + verb);
|
||||
}
|
||||
buttonsMap.set(id, verb);
|
||||
idsToVisibleVerbs.set(id, verb);
|
||||
}
|
||||
|
||||
// sort buttons into 2 buckets - needing showing and needing hiding
|
||||
let toHide = [],
|
||||
toShow = [];
|
||||
for (let btnNode of Elements.contextappbar.querySelectorAll("#contextualactions-tray > toolbarbutton")) {
|
||||
// correct the hidden state for each button;
|
||||
// .. buttons present in the map should be visible, otherwise not
|
||||
if (buttonsMap.has(btnNode.id)) {
|
||||
if (btnNode.hidden) toShow.push(btnNode);
|
||||
} else if (!btnNode.hidden) {
|
||||
toHide.push(btnNode);
|
||||
// Sort buttons into 2 buckets - needing showing and needing hiding.
|
||||
let toHide = [], toShow = [];
|
||||
let buttons = Elements.contextappbar.getElementsByTagName("toolbarbutton");
|
||||
for (let button of buttons) {
|
||||
let verb = idsToVisibleVerbs.get(button.id);
|
||||
if (verb != undefined) {
|
||||
// Button should be visible, and may or may not be showing.
|
||||
this._updateContextualActionLabel(button, verb, aNoun, aQty);
|
||||
if (button.hidden) {
|
||||
toShow.push(button);
|
||||
}
|
||||
} else if (!button.hidden) {
|
||||
// Button is visible, but shouldn't be.
|
||||
toHide.push(button);
|
||||
}
|
||||
}
|
||||
return Task.spawn(function() {
|
||||
|
@ -201,6 +206,20 @@ var Appbar = {
|
|||
this.showContextualActions([]);
|
||||
},
|
||||
|
||||
_updateContextualActionLabel: function(aBtnNode, aVerb, aNoun, aQty) {
|
||||
// True if action modifies the noun for the grid (bookmark, top site, etc.),
|
||||
// causing the label to be pluralized by the number of selected items.
|
||||
let modifiesNoun = aBtnNode.getAttribute("modifies-noun") == "true";
|
||||
if (modifiesNoun && (!aNoun || isNaN(aQty))) {
|
||||
throw new Error("Appbar._updateContextualActionLabel: " +
|
||||
"missing noun/quantity for " + aVerb);
|
||||
}
|
||||
|
||||
let labelName = "contextAppbar." + aVerb + (modifiesNoun ? "." + aNoun : "");
|
||||
let label = Strings.browser.GetStringFromName(labelName);
|
||||
aBtnNode.label = modifiesNoun ? PluralForm.get(aQty, label) : label;
|
||||
},
|
||||
|
||||
_onTileSelectionChanged: function _onTileSelectionChanged(aEvent){
|
||||
let activeTileset = aEvent.target;
|
||||
|
||||
|
@ -219,6 +238,8 @@ var Appbar = {
|
|||
// fire event with these verbs as payload
|
||||
let event = document.createEvent("Events");
|
||||
event.actions = verbs;
|
||||
event.noun = activeTileset.contextNoun;
|
||||
event.qty = activeTileset.selectedItems.length;
|
||||
event.initEvent("MozContextActionsChange", true, false);
|
||||
Elements.contextappbar.dispatchEvent(event);
|
||||
|
||||
|
|
|
@ -117,6 +117,10 @@
|
|||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<property name="contextNoun" readonly="true"
|
||||
onget="return this.getAttribute('noun');"/>
|
||||
|
||||
<property name="contextActions">
|
||||
<getter>
|
||||
<![CDATA[
|
||||
|
|
|
@ -17,11 +17,11 @@
|
|||
<binding id="checkbox-toggleswitch" display="xul:box" extends="chrome://global/content/bindings/checkbox.xml#checkbox-baseline">
|
||||
<content>
|
||||
<xul:hbox>
|
||||
<xul:description anonid="onlabel" class="onlabel" value="&checkbox.on.label;" xbl:inherits="value=onlabel"/>
|
||||
<xul:description anonid="offlabel" class="offlabel" value="&checkbox.off.label;" xbl:inherits="value=offlabel"/>
|
||||
<xul:description anonid="onlabel" class="onlabel" value="&checkbox.on.label;" xbl:inherits="value=onlabel"/>
|
||||
<xul:radiogroup anonid="group" xbl:inherits="disabled">
|
||||
<xul:radio type="toggle" anonid="on" class="checkbox-radio-on"/>
|
||||
<xul:radio type="toggle" anonid="off" class="checkbox-radio-off"/>
|
||||
<xul:radio type="toggle" anonid="on" class="checkbox-radio-on"/>
|
||||
</xul:radiogroup>
|
||||
</xul:hbox>
|
||||
</content>
|
||||
|
|
|
@ -314,6 +314,8 @@ BookmarksView.prototype = {
|
|||
let event = document.createEvent("Events");
|
||||
// we need the restore button to show (the tile node will go away though)
|
||||
event.actions = ["restore"];
|
||||
event.noun = tileGroup.contextNoun;
|
||||
event.qty = selectedTiles.length;
|
||||
event.initEvent("MozContextActionsChange", true, false);
|
||||
tileGroup.dispatchEvent(event);
|
||||
}, 0);
|
||||
|
|
|
@ -1180,6 +1180,9 @@ var StartUI = {
|
|||
// of the keyboard transition.
|
||||
ContentAreaObserver.navBarWillBlur();
|
||||
}
|
||||
|
||||
if (aEvent.button == 0)
|
||||
ContextUI.dismissTabs();
|
||||
},
|
||||
|
||||
handleEvent: function handleEvent(aEvent) {
|
||||
|
|
|
@ -197,19 +197,19 @@
|
|||
<scrollbox id="start-scrollbox" orient="horizontal" observes="bcast_preciseInput" flex="1">
|
||||
<vbox id="start-topsites" class="meta-section">
|
||||
<label class="meta-section-title" value="&startTopSitesHeader.label;"/>
|
||||
<richgrid id="start-topsites-grid" rows="3" columns="3" tiletype="thumbnail" seltype="multiple" flex="1"/>
|
||||
<richgrid id="start-topsites-grid" noun="topsite" rows="3" columns="3" tiletype="thumbnail" seltype="multiple" flex="1"/>
|
||||
</vbox>
|
||||
<vbox id="start-bookmarks" class="meta-section">
|
||||
<label class="meta-section-title" value="&startBookmarksHeader.label;"/>
|
||||
<richgrid id="start-bookmarks-grid" seltype="multiple" flex="1"/>
|
||||
<richgrid id="start-bookmarks-grid" noun="bookmark" seltype="multiple" flex="1"/>
|
||||
</vbox>
|
||||
<vbox id="start-history" class="meta-section">
|
||||
<label class="meta-section-title" value="&startHistoryHeader.label;"/>
|
||||
<richgrid id="start-history-grid" seltype="multiple" flex="1"/>
|
||||
<richgrid id="start-history-grid" noun="history" seltype="multiple" flex="1"/>
|
||||
</vbox>
|
||||
<vbox id="start-remotetabs" class="meta-section">
|
||||
<label class="meta-section-title" value="&startRemoteTabsHeader.label;"/>
|
||||
<richgrid id="start-remotetabs-grid" seltype="multiple" flex="1"/>
|
||||
<richgrid id="start-remotetabs-grid" noun="tab" seltype="multiple" flex="1"/>
|
||||
</vbox>
|
||||
</scrollbox>
|
||||
</hbox>
|
||||
|
@ -219,7 +219,7 @@
|
|||
<scrollbox id="snapped-scrollbox" orient="vertical" flex="1">
|
||||
<vbox id="snapped-topsites">
|
||||
<label class="meta-section-title" value="&startTopSitesHeader.label;"/>
|
||||
<richgrid id="snapped-topsites-grid" class="canSnapTiles" rows="8" columns="1" flex="1"/>
|
||||
<richgrid id="snapped-topsites-grid" noun="topsite" class="canSnapTiles" rows="8" columns="1" flex="1"/>
|
||||
</vbox>
|
||||
<label class="meta-section-title" value="&snappedBookmarksHeader.label;"
|
||||
onclick="PanelUI.show('bookmarks-container');"/>
|
||||
|
@ -291,7 +291,7 @@
|
|||
<toolbarbutton id="stop-button" command="cmd_stop"/>
|
||||
</hbox>
|
||||
|
||||
<toolbarbutton id="download-button" oncommand="Appbar.onDownloadButton()"/>
|
||||
<toolbarbutton id="download-button" class="appbar-secondary" oncommand="Appbar.onDownloadButton()"/>
|
||||
<toolbarbutton id="star-button" class="appbar-primary" type="checkbox" oncommand="Appbar.onStarButton()"/>
|
||||
<toolbarbutton id="pin-button" class="appbar-primary" type="checkbox" oncommand="Appbar.onPinButton()"/>
|
||||
<toolbarbutton id="menu-button" class="appbar-primary" oncommand="Appbar.onMenuButton(event)"/>
|
||||
|
@ -315,16 +315,16 @@
|
|||
|
||||
<deck id="panel-items" selectedIndex="0" flex="1" >
|
||||
<scrollbox id="bookmarks-container" flex="1">
|
||||
<richgrid id="bookmarks-list" class="canSnapTiles" seltype="multiple" flex="1"/>
|
||||
<richgrid id="bookmarks-list" noun="bookmark" class="canSnapTiles" seltype="multiple" flex="1"/>
|
||||
</scrollbox>
|
||||
<scrollbox id="history-container" flex="1">
|
||||
<richgrid id="history-list" class="canSnapTiles" seltype="multiple" flex="1"/>
|
||||
<richgrid id="history-list" noun="history" class="canSnapTiles" seltype="multiple" flex="1"/>
|
||||
</scrollbox>
|
||||
<scrollbox id="downloads-container" flex="1">
|
||||
<richgrid id="downloads-list" class="canSnapTiles" seltype="single" flex="1"/>
|
||||
<richgrid id="downloads-list" noun="download" class="canSnapTiles" seltype="single" flex="1"/>
|
||||
</scrollbox>
|
||||
<scrollbox id="remotetabs-container" flex="1">
|
||||
<richgrid id="remotetabs-list" class="canSnapTiles" seltype="single" flex="1"/>
|
||||
<richgrid id="remotetabs-list" noun="tab" class="canSnapTiles" seltype="single" flex="1"/>
|
||||
</scrollbox>
|
||||
<vbox id="console-container" flex="1">
|
||||
<vbox id="console-header" class="panel-list">
|
||||
|
@ -361,12 +361,22 @@
|
|||
|
||||
<!-- Context button bar -->
|
||||
<appbar id="contextappbar">
|
||||
<toolbar id="contextualactions-tray" flex="1">
|
||||
<toolbarbutton id="delete-selected-button" hidden="true" fade="true" oncommand="Appbar.dispatchContextualAction('delete')"/>
|
||||
<toolbarbutton id="restore-selected-button" hidden="true" fade="true" oncommand="Appbar.dispatchContextualAction('restore')"/>
|
||||
<toolbarbutton id="pin-selected-button" hidden="true" fade="true" oncommand="Appbar.dispatchContextualAction('pin')"/>
|
||||
<toolbarbutton id="unpin-selected-button" hidden="true" fade="true" oncommand="Appbar.dispatchContextualAction('unpin')"/>
|
||||
<toolbarbutton id="clear-selected-button" hidden="true" fade="true" oncommand="Appbar.dispatchContextualAction('clear')"/>
|
||||
<toolbar id="contextualactions-tray" labelled="true" flex="1">
|
||||
<toolbarbutton id="delete-selected-button" class="appbar-secondary"
|
||||
modifies-noun="true" hidden="true" fade="true"
|
||||
oncommand="Appbar.dispatchContextualAction('delete')"/>
|
||||
<toolbarbutton id="restore-selected-button" class="appbar-secondary"
|
||||
modifies-noun="true" hidden="true" fade="true"
|
||||
oncommand="Appbar.dispatchContextualAction('restore')"/>
|
||||
<toolbarbutton id="pin-selected-button" class="appbar-secondary"
|
||||
modifies-noun="true" hidden="true" fade="true"
|
||||
oncommand="Appbar.dispatchContextualAction('pin')"/>
|
||||
<toolbarbutton id="unpin-selected-button" class="appbar-secondary"
|
||||
modifies-noun="true" hidden="true" fade="true"
|
||||
oncommand="Appbar.dispatchContextualAction('unpin')"/>
|
||||
<toolbarbutton id="clear-selected-button" class="appbar-secondary"
|
||||
hidden="true" fade="true"
|
||||
oncommand="Appbar.dispatchContextualAction('clear')"/>
|
||||
</toolbar>
|
||||
</appbar>
|
||||
|
||||
|
|
|
@ -148,6 +148,8 @@ HistoryView.prototype = {
|
|||
let event = document.createEvent("Events");
|
||||
// we need the restore button to show (the tile node will go away though)
|
||||
event.actions = ["restore"];
|
||||
event.noun = tileGroup.contextNoun;
|
||||
event.qty = selectedTiles.length;
|
||||
event.initEvent("MozContextActionsChange", true, false);
|
||||
tileGroup.dispatchEvent(event);
|
||||
}, 0);
|
||||
|
|
|
@ -41,7 +41,7 @@ gTests.push({
|
|||
yield waitForCondition(() => BrowserUI.ready);
|
||||
is(Elements.findbar.isShowing, false, "Find bar is hidden by default");
|
||||
|
||||
ContextUI.displayNavbar();
|
||||
yield showNavBar();
|
||||
EventUtils.sendMouseEvent({ type: "click" }, "menu-button");
|
||||
EventUtils.sendMouseEvent({ type: "click" }, "context-findinpage");
|
||||
yield waitForEvent(Elements.findbar, "transitionend");
|
||||
|
|
|
@ -14,6 +14,33 @@ browser.search.order.3=Yahoo
|
|||
# menu item text will be: |Search (browser.search.defaultenginename) for "string"|
|
||||
browser.search.contextTextSearchLabel2=Search %S for "%S"
|
||||
|
||||
# Contextual Appbar - button labels
|
||||
# LOCALIZATION NOTE: All of the following represent actions that can be done
|
||||
# to items (top sites, bookmarks, history items) that are selected by the user
|
||||
# on the start screen. Each string is a semicolon list of plural forms.
|
||||
contextAppbar.delete.topsite=Delete top site;Delete top sites
|
||||
contextAppbar.restore.topsite=Restore top site;Restore top sites
|
||||
contextAppbar.pin.topsite=Pin top site;Pin top sites
|
||||
contextAppbar.unpin.topsite=Unpin top site;Unpin top sites
|
||||
contextAppbar.delete.bookmark=Delete bookmark;Delete bookmarks
|
||||
contextAppbar.restore.bookmark=Restore bookmark;Restore bookmarks
|
||||
contextAppbar.pin.bookmark=Pin bookmark;Pin bookmarks
|
||||
contextAppbar.unpin.bookmark=Unpin bookmark;Unpin bookmarks
|
||||
contextAppbar.delete.history=Delete page;Delete pages
|
||||
contextAppbar.restore.history=Restore page;Restore pages
|
||||
contextAppbar.pin.history=Pin page;Pin pages
|
||||
contextAppbar.unpin.history=Unpin page;Unpin pages
|
||||
contextAppbar.delete.tab=Delete tab;Delete tabs
|
||||
contextAppbar.restore.tab=Restore tab;Restore tabs
|
||||
contextAppbar.pin.tab=Pin tab;Pin tabs
|
||||
contextAppbar.unpin.tab=Unpin page;Unpin tabs
|
||||
contextAppbar.delete.download=Delete download;Delete downloads
|
||||
contextAppbar.restore.download=Restore download;Restore downloads
|
||||
contextAppbar.pin.download=Pin download;Pin downloads
|
||||
contextAppbar.unpin.download=Unpin page;Unpin downloads
|
||||
# LOCALIZATION NOTE (contextAppbar.clear): Unselects items without modification.
|
||||
contextAppbar.clear=Clear selection
|
||||
|
||||
# Settings Charms
|
||||
aboutCharm1=About
|
||||
optionsCharm=Options
|
||||
|
|
|
@ -352,97 +352,11 @@ documenttab[selected] .documenttab-selection {
|
|||
visibility: collapse;
|
||||
}
|
||||
|
||||
/* App Bar ----------------------------------------------------------------- */
|
||||
|
||||
appbar {
|
||||
display: block;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
transform: translateY(100%);
|
||||
transition: transform @metro_animation_duration@ @metro_animation_easing@;
|
||||
font-size: 0;
|
||||
}
|
||||
|
||||
appbar toolbar {
|
||||
-moz-appearance: none;
|
||||
-moz-box-align: center;
|
||||
border: 0;
|
||||
width: 100%;
|
||||
min-height: @toolbar_height@;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
appbar toolbar > toolbarbutton {
|
||||
border: 0;
|
||||
margin: 0 @toolbar_horizontal_spacing@;
|
||||
padding: 0;
|
||||
/* Don't inherit background-color from toolbarbutton[checked="true"] */
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
appbar > toolbar > toolbarbutton[disabled] {
|
||||
visibility: collapse;
|
||||
}
|
||||
|
||||
#navbar[startpage],
|
||||
appbar[visible] {
|
||||
#navbar[startpage] {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
#stack[keyboardVisible] > appbar {
|
||||
/* Slow the bottom up transition since it's impossible to match the system's
|
||||
soft keyboard movement. */
|
||||
transition: transform @metro_animation_duration@ @metro_animation_easing@,
|
||||
bottom @appbar_keyboard_slideup_duration@ @metro_animation_easing@;
|
||||
}
|
||||
|
||||
#toolbar > .appbar-primary {
|
||||
-moz-image-region: rect(0 40px 40px 0);
|
||||
}
|
||||
|
||||
#toolbar > .appbar-primary:not([checked]):hover:not(:active) {
|
||||
-moz-image-region: rect(0 80px 40px 40px);
|
||||
}
|
||||
|
||||
#toolbar > .appbar-primary[checked] {
|
||||
-moz-image-region: rect(0 120px 40px 80px);
|
||||
}
|
||||
|
||||
#toolbar > .appbar-primary[checked]:hover:not(:active) {
|
||||
-moz-image-region: rect(0 160px 40px 120px);
|
||||
}
|
||||
|
||||
#toolbar > .appbar-primary:active {
|
||||
-moz-image-region: rect(0 120px 40px 80px);
|
||||
}
|
||||
|
||||
@media (min-resolution: 130dpi) {
|
||||
#toolbar > .appbar-primary > .toolbarbutton-icon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
#toolbar > .appbar-primary {
|
||||
-moz-image-region: rect(0 56px 56px 0);
|
||||
}
|
||||
|
||||
#toolbar > .appbar-primary:not([checked]):hover:not(:active) {
|
||||
-moz-image-region: rect(0 112px 56px 56px);
|
||||
}
|
||||
|
||||
#toolbar > .appbar-primary[checked] {
|
||||
-moz-image-region: rect(0 224px 56px 168px);
|
||||
}
|
||||
|
||||
#toolbar > .appbar-primary[checked]:hover:not(:active) {
|
||||
-moz-image-region: rect(0 224px 56px 168px);
|
||||
}
|
||||
|
||||
#toolbar > .appbar-primary:active {
|
||||
-moz-image-region: rect(0 168px 56px 112px);
|
||||
}
|
||||
}
|
||||
/* App Bar ----------------------------------------------------------------- */
|
||||
|
||||
/* Page-Specific */
|
||||
|
||||
|
@ -474,10 +388,6 @@ appbar[visible] {
|
|||
|
||||
/* Application-Specific */
|
||||
|
||||
#download-button, #contextualactions-tray > toolbarbutton {
|
||||
list-style-image: url(chrome://browser/skin/images/appbar-icons.png);
|
||||
}
|
||||
|
||||
#download-button {
|
||||
-moz-image-region: rect(0px, 40px, 40px, 0px) !important;
|
||||
}
|
||||
|
@ -504,6 +414,9 @@ appbar[visible] {
|
|||
transition-timing-function: ease-in;
|
||||
transition-delay: 80ms;
|
||||
}
|
||||
#contextualactions-tray > toolbarbutton > .toolbarbutton-text {
|
||||
color: white;
|
||||
}
|
||||
|
||||
#pin-selected-button {
|
||||
-moz-image-region: rect(0px, 240px, 40px, 200px) !important;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
%define toolbar_vertical_spacing 5px
|
||||
%define toolbar_horizontal_spacing 20px
|
||||
%define toolbar_height 68px
|
||||
%define labelled_toolbar_height 90px
|
||||
%define tabs_height 178px
|
||||
%define findbar_height 54px
|
||||
|
||||
|
|
|
@ -498,7 +498,6 @@ notification {
|
|||
-moz-box-flex: 9999;
|
||||
}
|
||||
|
||||
|
||||
/* Dialogs ----------------------------------------------------------------- */
|
||||
|
||||
.modal-block,
|
||||
|
@ -664,6 +663,125 @@ arrowbox {
|
|||
font-weight: 100;
|
||||
}
|
||||
|
||||
/* App bars ----------------------------------------------------------------- */
|
||||
|
||||
appbar {
|
||||
display: block;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
transform: translateY(100%);
|
||||
transition: transform @metro_animation_duration@ @metro_animation_easing@;
|
||||
font-size: 0;
|
||||
}
|
||||
|
||||
appbar toolbar {
|
||||
-moz-appearance: none;
|
||||
-moz-box-align: center;
|
||||
border: 0;
|
||||
width: 100%;
|
||||
min-height: @toolbar_height@;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
appbar[visible] {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
#stack[keyboardVisible] > appbar {
|
||||
/* Slow the bottom up transition since it's impossible to match the system's
|
||||
soft keyboard movement. */
|
||||
transition: transform @metro_animation_duration@ @metro_animation_easing@,
|
||||
bottom @appbar_keyboard_slideup_duration@ @metro_animation_easing@;
|
||||
}
|
||||
|
||||
appbar toolbar > toolbarbutton {
|
||||
border: 0;
|
||||
margin: 0 @toolbar_horizontal_spacing@;
|
||||
padding: 0;
|
||||
/* Don't inherit background-color from toolbarbutton[checked="true"] */
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
appbar toolbar > toolbarbutton[disabled] {
|
||||
visibility: collapse;
|
||||
}
|
||||
|
||||
appbar toolbar[labelled] {
|
||||
min-height: @labelled_toolbar_height@;
|
||||
}
|
||||
|
||||
appbar toolbar[labelled] > toolbarbutton {
|
||||
-moz-box-orient: vertical;
|
||||
}
|
||||
|
||||
appbar toolbar[labelled] > toolbarbutton > .toolbarbutton-text {
|
||||
display: block;
|
||||
padding-top: @metro_spacing_small@;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
/* Sprites */
|
||||
|
||||
.appbar-primary > .toolbarbutton-icon,
|
||||
.appbar-secondary > .toolbarbutton-icon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
/* Primary sprite format: one button per sprite.
|
||||
|
||||
States from left to right:
|
||||
normal, hover, active/toggled, toggled+hover, toggled+active. */
|
||||
|
||||
.appbar-primary {
|
||||
-moz-image-region: rect(0 40px 40px 0);
|
||||
}
|
||||
|
||||
.appbar-primary:not([checked]):hover:not(:active) {
|
||||
-moz-image-region: rect(0 80px 40px 40px);
|
||||
}
|
||||
|
||||
.appbar-primary[checked] {
|
||||
-moz-image-region: rect(0 120px 40px 80px);
|
||||
}
|
||||
|
||||
.appbar-primary[checked]:hover:not(:active) {
|
||||
-moz-image-region: rect(0 160px 40px 120px);
|
||||
}
|
||||
|
||||
.appbar-primary:active {
|
||||
-moz-image-region: rect(0 120px 40px 80px);
|
||||
}
|
||||
|
||||
@media (min-resolution: 130dpi) {
|
||||
.appbar-primary {
|
||||
-moz-image-region: rect(0 56px 56px 0);
|
||||
}
|
||||
|
||||
.appbar-primary:not([checked]):hover:not(:active) {
|
||||
-moz-image-region: rect(0 112px 56px 56px);
|
||||
}
|
||||
|
||||
.appbar-primary[checked] {
|
||||
-moz-image-region: rect(0 224px 56px 168px);
|
||||
}
|
||||
|
||||
.appbar-primary[checked]:hover:not(:active) {
|
||||
-moz-image-region: rect(0 224px 56px 168px);
|
||||
}
|
||||
|
||||
.appbar-primary:active {
|
||||
-moz-image-region: rect(0 168px 56px 112px);
|
||||
}
|
||||
}
|
||||
|
||||
/* Secondary sprite format: one sprite for everything */
|
||||
|
||||
.appbar-secondary {
|
||||
list-style-image: url(chrome://browser/skin/images/appbar-icons.png);
|
||||
}
|
||||
|
||||
/* Find bar ------------------------------------------------------------- */
|
||||
|
||||
#findbar {
|
||||
|
|
|
@ -27,7 +27,11 @@ this.SitePermissions = {
|
|||
/* Returns an array of all permission IDs.
|
||||
*/
|
||||
listPermissions: function () {
|
||||
return Object.keys(gPermissionObject);
|
||||
let array = Object.keys(gPermissionObject);
|
||||
array.sort((a, b) => {
|
||||
return this.getPermissionLabel(a).localeCompare(this.getPermissionLabel(b));
|
||||
});
|
||||
return array;
|
||||
},
|
||||
|
||||
/* Returns an array of permission states to be exposed to the user for a
|
||||
|
@ -89,11 +93,11 @@ this.SitePermissions = {
|
|||
|
||||
/* Removes the saved state of a particular permission for a given URI.
|
||||
*/
|
||||
remove: function (aURI, aPermission) {
|
||||
remove: function (aURI, aPermissionID) {
|
||||
if (!this.isSupportedURI(aURI))
|
||||
return;
|
||||
|
||||
Services.perms.remove(aURI.host, aPermission);
|
||||
Services.perms.remove(aURI.host, aPermissionID);
|
||||
|
||||
if (aPermissionID in gPermissionObject &&
|
||||
gPermissionObject[aPermissionID].onChange)
|
||||
|
@ -110,7 +114,14 @@ this.SitePermissions = {
|
|||
/* Returns the localized label for the given permission state, to be used in
|
||||
* a UI for managing permissions.
|
||||
*/
|
||||
getStateLabel: function (aState) {
|
||||
getStateLabel: function (aPermissionID, aState) {
|
||||
if (aPermissionID in gPermissionObject &&
|
||||
gPermissionObject[aPermissionID].getStateLabel) {
|
||||
let label = gPermissionObject[aPermissionID].getStateLabel(aState);
|
||||
if (label)
|
||||
return label;
|
||||
}
|
||||
|
||||
switch (aState) {
|
||||
case this.UNKNOWN:
|
||||
return gStringBundle.GetStringFromName("alwaysAsk");
|
||||
|
@ -140,6 +151,11 @@ let gPermissionObject = {
|
|||
* Defaults to UNKNOWN, indicating that the user will be asked each time
|
||||
* a page asks for that permissions.
|
||||
*
|
||||
* - getStateLabel
|
||||
* Called to get the localized label for the given permission state, to be
|
||||
* used in a UI for managing permissions. May return null for states that
|
||||
* should use their default label.
|
||||
*
|
||||
* - onChange
|
||||
* Called when a permission state changes.
|
||||
*
|
||||
|
@ -189,8 +205,18 @@ let gPermissionObject = {
|
|||
},
|
||||
|
||||
"indexedDB": {
|
||||
getDefault: function () {
|
||||
return SitePermissions.ALLOW;
|
||||
states: [ SitePermissions.ALLOW, SitePermissions.UNKNOWN, SitePermissions.BLOCK ],
|
||||
getStateLabel: function (aState) {
|
||||
// indexedDB redefines nsIPermissionManager.UNKNOWN_ACTION (the default)
|
||||
// as "allow" and nsIPermissionManager.ALLOW_ACTION as "ask the user."
|
||||
switch (aState) {
|
||||
case SitePermissions.UNKNOWN:
|
||||
return gStringBundle.GetStringFromName("allow");
|
||||
case SitePermissions.ALLOW:
|
||||
return gStringBundle.GetStringFromName("alwaysAsk");
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
},
|
||||
onChange: function (aURI, aState) {
|
||||
if (aState == SitePermissions.ALLOW || aState == SitePermissions.BLOCK)
|
||||
|
|
|
@ -28,17 +28,32 @@
|
|||
padding: 3px 5px;
|
||||
}
|
||||
|
||||
.profiler-sidebar-item, .side-menu-widget-item-contents {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.profiler-sidebar-item > h3 {
|
||||
font-size: 13px;
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.profiler-sidebar-item > span {
|
||||
.profiler-sidebar-item > hbox {
|
||||
margin-top: 2px;
|
||||
color: rgb(140, 152, 165);
|
||||
}
|
||||
|
||||
.selected .profiler-sidebar-item > span {
|
||||
.profiler-sidebar-item > hbox > a {
|
||||
display: none;
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
[state=completed].selected .profiler-sidebar-item > hbox > a {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.selected .profiler-sidebar-item > hbox {
|
||||
color: rgb(128, 195, 228);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,8 +15,8 @@ MSVC_ENABLE_PGO := 1
|
|||
LIBXUL_LIBRARY = 1
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
|
||||
LOCAL_INCLUDES += \
|
||||
-I$(topsrcdir)/netwerk/protocol/res \
|
||||
|
|
|
@ -20,12 +20,14 @@ new
|
|||
algorithm
|
||||
atomic
|
||||
deque
|
||||
ios
|
||||
iostream
|
||||
iterator
|
||||
limits
|
||||
list
|
||||
map
|
||||
memory
|
||||
ostream
|
||||
set
|
||||
stack
|
||||
string
|
||||
|
|
|
@ -468,6 +468,7 @@ IOKit/IOKitLib.h
|
|||
IOKit/IOMessage.h
|
||||
IOKit/pwr_mgt/IOPMLib.h
|
||||
iomanip
|
||||
ios
|
||||
iostream
|
||||
iostream.h
|
||||
iterator
|
||||
|
@ -678,6 +679,7 @@ OpenTransport.h
|
|||
os2.h
|
||||
OS.h
|
||||
osreldate.h
|
||||
ostream
|
||||
OSUtils.h
|
||||
Packages.h
|
||||
Palettes.h
|
||||
|
|
15
configure.in
15
configure.in
|
@ -2241,7 +2241,6 @@ ia64*-hpux*)
|
|||
CXXFLAGS="$CXXFLAGS -mstackrealign -fno-keep-inline-dllexport"
|
||||
LDFLAGS="$LDFLAGS -Wl,--enable-stdcall-fixup -Wl,--large-address-aware"
|
||||
else
|
||||
AC_DEFINE(HAVE_STDCALL)
|
||||
DSO_LDOPTS="$DSO_LDOPTS -MACHINE:X86"
|
||||
LDFLAGS="$LDFLAGS -SAFESEH"
|
||||
fi
|
||||
|
@ -2630,20 +2629,6 @@ AC_TYPE_OFF_T
|
|||
AC_TYPE_PID_T
|
||||
AC_TYPE_SIZE_T
|
||||
AC_LANG_CPLUSPLUS
|
||||
AC_MSG_CHECKING(for __stdcall)
|
||||
AC_CACHE_VAL(ac_cv___stdcall,
|
||||
[AC_TRY_COMPILE([template <typename Method> struct foo;
|
||||
template <> struct foo<void (*)()> {};
|
||||
template <> struct foo<void (__stdcall*)()> {};],
|
||||
[],
|
||||
[ac_cv___stdcall=true],
|
||||
[ac_cv___stdcall=false])])
|
||||
if test "$ac_cv___stdcall" = true ; then
|
||||
AC_DEFINE(HAVE_STDCALL)
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
AC_LANG_C
|
||||
AC_MSG_CHECKING(for ssize_t)
|
||||
AC_CACHE_VAL(ac_cv_type_ssize_t,
|
||||
|
|
|
@ -31,8 +31,8 @@ EXTRA_COMPONENTS = \
|
|||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
|
||||
LOCAL_INCLUDES += \
|
||||
-I$(topsrcdir)/caps/include \
|
||||
|
|
|
@ -132,9 +132,11 @@ nsDOMFileReader::Init()
|
|||
mPrincipal.swap(principal);
|
||||
|
||||
// Instead of grabbing some random global from the context stack,
|
||||
// let's use the default one (junk drawer) for now.
|
||||
// let's use the default one (junk scope) for now.
|
||||
// We should move away from this Init...
|
||||
BindToOwner(xpc::GetNativeForGlobal(xpc::GetJunkScope()));
|
||||
nsCOMPtr<nsIGlobalObject> global = xpc::GetJunkScopeGlobal();
|
||||
NS_ENSURE_TRUE(global, NS_ERROR_FAILURE);
|
||||
BindToOwner(global);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -1954,7 +1954,9 @@ nsDocument::Init()
|
|||
// we use the default compartment for this document, instead of creating
|
||||
// wrapper in some random compartment when the document is exposed to js
|
||||
// via some events.
|
||||
mScopeObject = do_GetWeakReference(xpc::GetNativeForGlobal(xpc::GetJunkScope()));
|
||||
nsCOMPtr<nsIGlobalObject> global = xpc::GetJunkScopeGlobal();
|
||||
NS_ENSURE_TRUE(global, NS_ERROR_FAILURE);
|
||||
mScopeObject = do_GetWeakReference(global);
|
||||
MOZ_ASSERT(mScopeObject);
|
||||
|
||||
// Force initialization.
|
||||
|
@ -2750,8 +2752,11 @@ nsDocument::SetDocumentURI(nsIURI* aURI)
|
|||
nsIURI* newBase = GetDocBaseURI();
|
||||
|
||||
bool equalBases = false;
|
||||
// Changing just the ref of a URI does not change how relative URIs would
|
||||
// resolve wrt to it, so we can treat the bases as equal as long as they're
|
||||
// equal ignoring the ref.
|
||||
if (oldBase && newBase) {
|
||||
oldBase->Equals(newBase, &equalBases);
|
||||
oldBase->EqualsExceptRef(newBase, &equalBases);
|
||||
}
|
||||
else {
|
||||
equalBases = !oldBase && !newBase;
|
||||
|
|
|
@ -3350,8 +3350,8 @@ nsObjectLoadingContent::TeardownProtoChain()
|
|||
|
||||
bool
|
||||
nsObjectLoadingContent::DoNewResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
|
||||
JS::Handle<jsid> aId, unsigned aFlags,
|
||||
JS::MutableHandle<JSObject*> aObjp)
|
||||
JS::Handle<jsid> aId,
|
||||
JS::MutableHandle<JS::Value> aValue)
|
||||
{
|
||||
// We don't resolve anything; we just try to make sure we're instantiated
|
||||
|
||||
|
|
|
@ -148,8 +148,9 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
|||
void TeardownProtoChain();
|
||||
|
||||
// Helper for WebIDL newResolve
|
||||
bool DoNewResolve(JSContext* aCx, JS::Handle<JSObject*> aObject, JS::Handle<jsid> aId,
|
||||
unsigned aFlags, JS::MutableHandle<JSObject*> aObjp);
|
||||
bool DoNewResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
|
||||
JS::Handle<jsid> aId,
|
||||
JS::MutableHandle<JS::Value> aValue);
|
||||
|
||||
// WebIDL API
|
||||
nsIDocument* GetContentDocument();
|
||||
|
|
|
@ -356,9 +356,11 @@ nsXMLHttpRequest::Init()
|
|||
NS_ENSURE_STATE(subjectPrincipal);
|
||||
|
||||
// Instead of grabbing some random global from the context stack,
|
||||
// let's use the default one (junk drawer) for now.
|
||||
// let's use the default one (junk scope) for now.
|
||||
// We should move away from this Init...
|
||||
Construct(subjectPrincipal, xpc::GetNativeForGlobal(xpc::GetJunkScope()));
|
||||
nsCOMPtr<nsIGlobalObject> global = xpc::GetJunkScopeGlobal();
|
||||
NS_ENSURE_TRUE(global, NS_ERROR_FAILURE);
|
||||
Construct(subjectPrincipal, global);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -3296,6 +3296,8 @@ CanvasRenderingContext2D::DrawWindow(nsIDOMWindow* window, double x,
|
|||
// gfxContext-over-Azure may modify the DrawTarget's transform, so
|
||||
// save and restore it
|
||||
Matrix matrix = mTarget->GetTransform();
|
||||
double sw = matrix._11 * w;
|
||||
double sh = matrix._22 * h;
|
||||
nsRefPtr<gfxContext> thebes;
|
||||
nsRefPtr<gfxASurface> drawSurf;
|
||||
if (gfxPlatform::GetPlatform()->SupportsAzureContentForDrawTarget(mTarget)) {
|
||||
|
@ -3304,7 +3306,7 @@ CanvasRenderingContext2D::DrawWindow(nsIDOMWindow* window, double x,
|
|||
matrix._22, matrix._31, matrix._32));
|
||||
} else {
|
||||
drawSurf =
|
||||
gfxPlatform::GetPlatform()->CreateOffscreenSurface(gfxIntSize(ceil(w), ceil(h)),
|
||||
gfxPlatform::GetPlatform()->CreateOffscreenSurface(gfxIntSize(ceil(sw), ceil(sh)),
|
||||
gfxASurface::CONTENT_COLOR_ALPHA);
|
||||
if (!drawSurf) {
|
||||
error.Throw(NS_ERROR_FAILURE);
|
||||
|
@ -3314,6 +3316,7 @@ CanvasRenderingContext2D::DrawWindow(nsIDOMWindow* window, double x,
|
|||
drawSurf->SetDeviceOffset(gfxPoint(-floor(x), -floor(y)));
|
||||
thebes = new gfxContext(drawSurf);
|
||||
thebes->Translate(gfxPoint(floor(x), floor(y)));
|
||||
thebes->Scale(matrix._11, matrix._22);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPresShell> shell = presContext->PresShell();
|
||||
|
@ -3333,8 +3336,9 @@ CanvasRenderingContext2D::DrawWindow(nsIDOMWindow* window, double x,
|
|||
IntSize(size.width, size.height),
|
||||
img->Stride(),
|
||||
FORMAT_B8G8R8A8);
|
||||
mgfx::Rect rect(0, 0, w, h);
|
||||
mTarget->DrawSurface(data, rect, rect);
|
||||
mgfx::Rect destRect(0, 0, w, h);
|
||||
mgfx::Rect sourceRect(0, 0, sw, sh);
|
||||
mTarget->DrawSurface(data, destRect, sourceRect);
|
||||
mTarget->Flush();
|
||||
} else {
|
||||
mTarget->SetTransform(matrix);
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "WebGL1Context.h"
|
||||
#include "mozilla/dom/WebGLRenderingContextBinding.h"
|
||||
|
||||
#include "mozilla/Telemetry.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// CONSTRUCTOR & DESTRUCTOR
|
||||
|
||||
WebGL1Context::WebGL1Context()
|
||||
: WebGLContext()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
WebGL1Context::~WebGL1Context()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// IMPLEMENT nsWrapperCache
|
||||
|
||||
JSObject*
|
||||
WebGL1Context::WrapObject(JSContext *cx, JS::Handle<JSObject*> scope)
|
||||
{
|
||||
return dom::WebGLRenderingContextBinding::Wrap(cx, scope, this);
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// INSTANCING nsIDOMWebGLRenderingContext
|
||||
|
||||
nsresult
|
||||
NS_NewCanvasRenderingContextWebGL(nsIDOMWebGLRenderingContext** aResult)
|
||||
{
|
||||
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_USED, 1);
|
||||
nsIDOMWebGLRenderingContext* ctx = new WebGL1Context();
|
||||
|
||||
NS_ADDREF(*aResult = ctx);
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef WEBGL1CONTEXT_H_
|
||||
#define WEBGL1CONTEXT_H_
|
||||
|
||||
#include "WebGLContext.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class WebGL1Context
|
||||
: public WebGLContext
|
||||
{
|
||||
// -----------------------------------------------------------------------------
|
||||
// PUBLIC
|
||||
public:
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// CONSTRUCTOR & DESTRUCTOR
|
||||
|
||||
WebGL1Context();
|
||||
virtual ~WebGL1Context();
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// IMPLEMENT nsWrapperCache
|
||||
|
||||
virtual JSObject* WrapObject(JSContext *cx,
|
||||
JS::Handle<JSObject*> scope) MOZ_OVERRIDE;
|
||||
|
||||
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
|
@ -4,6 +4,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "WebGLContext.h"
|
||||
#include "WebGL1Context.h"
|
||||
#include "WebGLObjectModel.h"
|
||||
#include "WebGLExtensions.h"
|
||||
#include "WebGLContextUtils.h"
|
||||
|
@ -88,20 +89,6 @@ WebGLMemoryPressureObserver::Observe(nsISupports* aSubject,
|
|||
}
|
||||
|
||||
|
||||
nsresult NS_NewCanvasRenderingContextWebGL(nsIDOMWebGLRenderingContext** aResult);
|
||||
|
||||
nsresult
|
||||
NS_NewCanvasRenderingContextWebGL(nsIDOMWebGLRenderingContext** aResult)
|
||||
{
|
||||
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_USED, 1);
|
||||
nsIDOMWebGLRenderingContext* ctx = new WebGLContext();
|
||||
if (!ctx)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(*aResult = ctx);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
WebGLContextOptions::WebGLContextOptions()
|
||||
: alpha(true), depth(true), stencil(false),
|
||||
premultipliedAlpha(true), antialias(true),
|
||||
|
@ -227,12 +214,6 @@ WebGLContext::~WebGLContext()
|
|||
mContextRestorer = nullptr;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
WebGLContext::WrapObject(JSContext *cx, JS::Handle<JSObject*> scope)
|
||||
{
|
||||
return dom::WebGLRenderingContextBinding::Wrap(cx, scope, this);
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::DestroyResourcesAndContext()
|
||||
{
|
||||
|
|
|
@ -151,7 +151,7 @@ public:
|
|||
nsIDOMWebGLRenderingContext)
|
||||
|
||||
virtual JSObject* WrapObject(JSContext *cx,
|
||||
JS::Handle<JSObject*> scope) MOZ_OVERRIDE;
|
||||
JS::Handle<JSObject*> scope) = 0;
|
||||
|
||||
NS_DECL_NSIDOMWEBGLRENDERINGCONTEXT
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ if CONFIG['MOZ_WEBGL']:
|
|||
CPP_SOURCES += [
|
||||
'WebGLActiveInfo.cpp',
|
||||
'WebGLBuffer.cpp',
|
||||
'WebGL1Context.cpp',
|
||||
'WebGLContext.cpp',
|
||||
'WebGLContextGL.cpp',
|
||||
'WebGLContextUtils.cpp',
|
||||
|
|
|
@ -16,8 +16,8 @@ LIBXUL_LIBRARY = 1
|
|||
FAIL_ON_WARNINGS = 1
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
|
||||
LOCAL_INCLUDES += \
|
||||
-I$(srcdir)/../../base/src \
|
||||
|
|
|
@ -4567,7 +4567,10 @@ nsEventStateManager::CheckForAndDispatchClick(nsPresContext* aPresContext,
|
|||
if (!mouseContent && !mCurrentTarget) {
|
||||
return NS_OK;
|
||||
}
|
||||
ret = presShell->HandleEventWithTarget(&event, mCurrentTarget,
|
||||
|
||||
// HandleEvent clears out mCurrentTarget which we might need again
|
||||
nsWeakFrame currentTarget = mCurrentTarget;
|
||||
ret = presShell->HandleEventWithTarget(&event, currentTarget,
|
||||
mouseContent, aStatus);
|
||||
if (NS_SUCCEEDED(ret) && aEvent->clickCount == 2) {
|
||||
//fire double click
|
||||
|
@ -4581,7 +4584,7 @@ nsEventStateManager::CheckForAndDispatchClick(nsPresContext* aPresContext,
|
|||
event2.button = aEvent->button;
|
||||
event2.inputSource = aEvent->inputSource;
|
||||
|
||||
ret = presShell->HandleEventWithTarget(&event2, mCurrentTarget,
|
||||
ret = presShell->HandleEventWithTarget(&event2, currentTarget,
|
||||
mouseContent, aStatus);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -104,6 +104,7 @@ MOCHITEST_FILES = \
|
|||
test_focus_disabled.html \
|
||||
test_bug847597.html \
|
||||
test_bug855741.html \
|
||||
test_dblclick_explicit_original_target.html \
|
||||
$(NULL)
|
||||
|
||||
ifeq (,$(filter gonk,$(MOZ_WIDGET_TOOLKIT)))
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test explicit original target of dblclick event</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display">Test explicit original target of dblclick event</p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(runTests);
|
||||
|
||||
function runTests()
|
||||
{
|
||||
synthesizeMouse(document.getElementById("display"), 5, 5, { clickCount: 2 });
|
||||
}
|
||||
|
||||
window.ondblclick = function(event) {
|
||||
is(event.explicitOriginalTarget.nodeType, Node.TEXT_NODE, "explicitOriginalTarget is a text node");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -390,6 +390,8 @@ MOCHITEST_FILES = \
|
|||
file_srcdoc.html \
|
||||
test_srcdoc-2.html \
|
||||
file_srcdoc-2.html \
|
||||
test_bug893537.html \
|
||||
file_bug893537.html \
|
||||
$(NULL)
|
||||
|
||||
MOCHITEST_CHROME_FILES = \
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=893537
|
||||
-->
|
||||
<body>
|
||||
<iframe id="iframe" src="data:text/html;charset=US-ASCII,Goodbye World" srcdoc="Hello World"></iframe>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,42 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=893537
|
||||
-->
|
||||
<head>
|
||||
<title>Test for crash caused by unloading and reloading srcdoc iframes</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=893537">Mozilla Bug 893537</a>
|
||||
|
||||
<iframe id="pframe" src="file_bug893537.html"></iframe>
|
||||
|
||||
<pre id="test">
|
||||
<script>
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
var pframe = $("pframe");
|
||||
|
||||
var loadState = 1;
|
||||
pframe.contentWindow.addEventListener("load", function () {
|
||||
|
||||
if (loadState == 1) {
|
||||
var iframe = pframe.contentDocument.getElementById("iframe");
|
||||
iframe.removeAttribute("srcdoc");
|
||||
loadState = 2;
|
||||
}
|
||||
if (loadState == 2) {
|
||||
SimpleTest.executeSoon(function () { pframe.contentWindow.location.reload() });
|
||||
loadState = 3;
|
||||
}
|
||||
if (loadState == 3) {
|
||||
ok(true, "This is a mochitest implementation of a crashtest. To finish is to pass");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -15,9 +15,9 @@ LIBXUL_LIBRARY = 1
|
|||
FAIL_ON_WARNINGS = 1
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
|
||||
INCLUDES += \
|
||||
-I$(srcdir)/../../../base/src \
|
||||
|
|
|
@ -65,6 +65,13 @@ public:
|
|||
MOZ_ASSERT(mOffset <= mLength);
|
||||
return NS_OK;
|
||||
}
|
||||
virtual nsresult ReadAt(int64_t aOffset, char* aBuffer,
|
||||
uint32_t aCount, uint32_t* aBytes)
|
||||
{
|
||||
nsresult rv = Seek(nsISeekableStream::NS_SEEK_SET, aOffset);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
return Read(aBuffer, aCount, aBytes);
|
||||
}
|
||||
virtual nsresult Seek(int32_t aWhence, int64_t aOffset)
|
||||
{
|
||||
MOZ_ASSERT(aOffset <= UINT32_MAX);
|
||||
|
|
|
@ -15,8 +15,8 @@ LIBXUL_LIBRARY = 1
|
|||
FAIL_ON_WARNINGS := 1
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
|
||||
INCLUDES += \
|
||||
-I$(topsrcdir)/content/base/src \
|
||||
|
|
|
@ -2191,6 +2191,18 @@ MediaCacheStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
MediaCacheStream::ReadAt(int64_t aOffset, char* aBuffer,
|
||||
uint32_t aCount, uint32_t* aBytes)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
|
||||
|
||||
ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
|
||||
nsresult rv = Seek(nsISeekableStream::NS_SEEK_SET, aOffset);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
return Read(aBuffer, aCount, aBytes);
|
||||
}
|
||||
|
||||
nsresult
|
||||
MediaCacheStream::ReadFromCache(char* aBuffer,
|
||||
int64_t aOffset,
|
||||
|
|
|
@ -345,7 +345,10 @@ public:
|
|||
// this will block until the data is available or the stream is
|
||||
// closed, otherwise it won't block.
|
||||
nsresult Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes);
|
||||
|
||||
// Seeks to aOffset in the stream then performs a Read operation. See
|
||||
// 'Read' for argument and return details.
|
||||
nsresult ReadAt(int64_t aOffset, char* aBuffer,
|
||||
uint32_t aCount, uint32_t* aBytes);
|
||||
private:
|
||||
friend class MediaCache;
|
||||
|
||||
|
|
|
@ -799,6 +799,16 @@ nsresult ChannelMediaResource::Read(char* aBuffer,
|
|||
return mCacheStream.Read(aBuffer, aCount, aBytes);
|
||||
}
|
||||
|
||||
nsresult ChannelMediaResource::ReadAt(int64_t aOffset,
|
||||
char* aBuffer,
|
||||
uint32_t aCount,
|
||||
uint32_t* aBytes)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
|
||||
|
||||
return mCacheStream.ReadAt(aOffset, aBuffer, aCount, aBytes);
|
||||
}
|
||||
|
||||
nsresult ChannelMediaResource::Seek(int32_t aWhence, int64_t aOffset)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
|
||||
|
@ -1307,6 +1317,8 @@ public:
|
|||
virtual void SetReadMode(MediaCacheStream::ReadMode aMode) {}
|
||||
virtual void SetPlaybackRate(uint32_t aBytesPerSecond) {}
|
||||
virtual nsresult Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes);
|
||||
virtual nsresult ReadAt(int64_t aOffset, char* aBuffer,
|
||||
uint32_t aCount, uint32_t* aBytes);
|
||||
virtual nsresult Seek(int32_t aWhence, int64_t aOffset);
|
||||
virtual void StartSeekingForMetadata() {};
|
||||
virtual void EndSeekingForMetadata() {};
|
||||
|
@ -1347,6 +1359,13 @@ public:
|
|||
|
||||
nsresult GetCachedRanges(nsTArray<MediaByteRange>& aRanges);
|
||||
|
||||
protected:
|
||||
// These Unsafe variants of Read and Seek perform their operations
|
||||
// without acquiring mLock. The caller must obtain the lock before
|
||||
// calling. The implmentation of Read, Seek and ReadAt obtains the
|
||||
// lock before calling these Unsafe variants to read or seek.
|
||||
nsresult UnsafeRead(char* aBuffer, uint32_t aCount, uint32_t* aBytes);
|
||||
nsresult UnsafeSeek(int32_t aWhence, int64_t aOffset);
|
||||
private:
|
||||
// Ensures mSize is initialized, if it can be.
|
||||
// mLock must be held when this is called, and mInput must be non-null.
|
||||
|
@ -1572,16 +1591,38 @@ nsresult FileMediaResource::ReadFromCache(char* aBuffer, int64_t aOffset, uint32
|
|||
nsresult FileMediaResource::Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes)
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
return UnsafeRead(aBuffer, aCount, aBytes);
|
||||
}
|
||||
|
||||
nsresult FileMediaResource::UnsafeRead(char* aBuffer, uint32_t aCount, uint32_t* aBytes)
|
||||
{
|
||||
EnsureSizeInitialized();
|
||||
return mInput->Read(aBuffer, aCount, aBytes);
|
||||
}
|
||||
|
||||
nsresult FileMediaResource::ReadAt(int64_t aOffset, char* aBuffer,
|
||||
uint32_t aCount, uint32_t* aBytes)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
|
||||
|
||||
MutexAutoLock lock(mLock);
|
||||
nsresult rv = UnsafeSeek(nsISeekableStream::NS_SEEK_SET, aOffset);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
return UnsafeRead(aBuffer, aCount, aBytes);
|
||||
}
|
||||
|
||||
nsresult FileMediaResource::Seek(int32_t aWhence, int64_t aOffset)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
|
||||
|
||||
MutexAutoLock lock(mLock);
|
||||
return UnsafeSeek(aWhence, aOffset);
|
||||
}
|
||||
|
||||
nsresult FileMediaResource::UnsafeSeek(int32_t aWhence, int64_t aOffset)
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
|
||||
|
||||
if (!mSeekable)
|
||||
return NS_ERROR_FAILURE;
|
||||
EnsureSizeInitialized();
|
||||
|
|
|
@ -247,6 +247,12 @@ public:
|
|||
// available bytes is less than aCount. Always check *aBytes after
|
||||
// read, and call again if necessary.
|
||||
virtual nsresult Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes) = 0;
|
||||
// Read up to aCount bytes from the stream. The read starts at
|
||||
// aOffset in the stream, seeking to that location initially if
|
||||
// it is not the current stream offset. The remaining arguments,
|
||||
// results and requirements are the same as per the Read method.
|
||||
virtual nsresult ReadAt(int64_t aOffset, char* aBuffer,
|
||||
uint32_t aCount, uint32_t* aBytes) = 0;
|
||||
// Seek to the given bytes offset in the stream. aWhence can be
|
||||
// one of:
|
||||
// NS_SEEK_SET
|
||||
|
@ -518,6 +524,8 @@ public:
|
|||
virtual void SetReadMode(MediaCacheStream::ReadMode aMode);
|
||||
virtual void SetPlaybackRate(uint32_t aBytesPerSecond);
|
||||
virtual nsresult Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes);
|
||||
virtual nsresult ReadAt(int64_t offset, char* aBuffer,
|
||||
uint32_t aCount, uint32_t* aBytes);
|
||||
virtual nsresult Seek(int32_t aWhence, int64_t aOffset);
|
||||
virtual void StartSeekingForMetadata();
|
||||
virtual void EndSeekingForMetadata();
|
||||
|
|
|
@ -176,12 +176,13 @@ AudioContext::CreateBuffer(JSContext* aJSContext, ArrayBuffer& aBuffer,
|
|||
aBuffer.Data(), aBuffer.Length(),
|
||||
contentType);
|
||||
|
||||
WebAudioDecodeJob job(contentType, this);
|
||||
nsRefPtr<WebAudioDecodeJob> job =
|
||||
new WebAudioDecodeJob(contentType, this, aBuffer);
|
||||
|
||||
if (mDecoder.SyncDecodeMedia(contentType.get(),
|
||||
aBuffer.Data(), aBuffer.Length(), job) &&
|
||||
job.mOutput) {
|
||||
nsRefPtr<AudioBuffer> buffer = job.mOutput.forget();
|
||||
aBuffer.Data(), aBuffer.Length(), *job) &&
|
||||
job->mOutput) {
|
||||
nsRefPtr<AudioBuffer> buffer = job->mOutput.forget();
|
||||
if (aMixToMono) {
|
||||
buffer->MixToMono(aJSContext);
|
||||
}
|
||||
|
@ -374,8 +375,8 @@ AudioContext::DecodeAudioData(const ArrayBuffer& aBuffer,
|
|||
if (aFailureCallback.WasPassed()) {
|
||||
failureCallback = &aFailureCallback.Value();
|
||||
}
|
||||
nsAutoPtr<WebAudioDecodeJob> job(
|
||||
new WebAudioDecodeJob(contentType, this,
|
||||
nsRefPtr<WebAudioDecodeJob> job(
|
||||
new WebAudioDecodeJob(contentType, this, aBuffer,
|
||||
&aSuccessCallback, failureCallback));
|
||||
mDecoder.AsyncDecodeMedia(contentType.get(),
|
||||
aBuffer.Data(), aBuffer.Length(), *job);
|
||||
|
|
|
@ -227,7 +227,7 @@ private:
|
|||
nsRefPtr<AudioDestinationNode> mDestination;
|
||||
nsRefPtr<AudioListener> mListener;
|
||||
MediaBufferDecoder mDecoder;
|
||||
nsTArray<nsAutoPtr<WebAudioDecodeJob> > mDecodeJobs;
|
||||
nsTArray<nsRefPtr<WebAudioDecodeJob> > mDecodeJobs;
|
||||
// Two hashsets containing all the PannerNodes and AudioBufferSourceNodes,
|
||||
// to compute the doppler shift, and also to stop AudioBufferSourceNodes.
|
||||
// These are all weak pointers.
|
||||
|
|
|
@ -25,6 +25,29 @@
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(WebAudioDecodeJob)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mContext)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOutput)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSuccessCallback)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFailureCallback)
|
||||
tmp->mArrayBuffer = nullptr;
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(WebAudioDecodeJob)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContext)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOutput)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSuccessCallback)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFailureCallback)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(WebAudioDecodeJob)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mArrayBuffer)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebAudioDecodeJob, AddRef)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebAudioDecodeJob, Release)
|
||||
|
||||
using namespace dom;
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
|
@ -793,6 +816,7 @@ MediaBufferDecoder::Shutdown() {
|
|||
|
||||
WebAudioDecodeJob::WebAudioDecodeJob(const nsACString& aContentType,
|
||||
AudioContext* aContext,
|
||||
const ArrayBuffer& aBuffer,
|
||||
DecodeSuccessCallback* aSuccessCallback,
|
||||
DecodeErrorCallback* aFailureCallback)
|
||||
: mContentType(aContentType)
|
||||
|
@ -805,15 +829,21 @@ WebAudioDecodeJob::WebAudioDecodeJob(const nsACString& aContentType,
|
|||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_COUNT_CTOR(WebAudioDecodeJob);
|
||||
|
||||
mArrayBuffer = aBuffer.Obj();
|
||||
|
||||
MOZ_ASSERT(aSuccessCallback ||
|
||||
(!aSuccessCallback && !aFailureCallback),
|
||||
"If a success callback is not passed, no failure callback should be passed either");
|
||||
|
||||
nsContentUtils::HoldJSObjects(this, NS_CYCLE_COLLECTION_PARTICIPANT(WebAudioDecodeJob));
|
||||
}
|
||||
|
||||
WebAudioDecodeJob::~WebAudioDecodeJob()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_COUNT_DTOR(WebAudioDecodeJob);
|
||||
mArrayBuffer = nullptr;
|
||||
nsContentUtils::DropJSObjects(this);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -26,16 +26,20 @@ class DecodeErrorCallback;
|
|||
class DecodeSuccessCallback;
|
||||
}
|
||||
|
||||
struct WebAudioDecodeJob
|
||||
struct WebAudioDecodeJob MOZ_FINAL
|
||||
{
|
||||
// You may omit both the success and failure callback, or you must pass both.
|
||||
// The callbacks are only necessary for asynchronous operation.
|
||||
WebAudioDecodeJob(const nsACString& aContentType,
|
||||
dom::AudioContext* aContext,
|
||||
const dom::ArrayBuffer& aBuffer,
|
||||
dom::DecodeSuccessCallback* aSuccessCallback = nullptr,
|
||||
dom::DecodeErrorCallback* aFailureCallback = nullptr);
|
||||
~WebAudioDecodeJob();
|
||||
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebAudioDecodeJob)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebAudioDecodeJob)
|
||||
|
||||
enum ErrorCode {
|
||||
NoError,
|
||||
UnknownContent,
|
||||
|
@ -52,6 +56,8 @@ struct WebAudioDecodeJob
|
|||
|
||||
bool AllocateBuffer();
|
||||
|
||||
|
||||
JS::Heap<JSObject*> mArrayBuffer;
|
||||
nsCString mContentType;
|
||||
uint32_t mWriteIndex;
|
||||
nsRefPtr<dom::AudioContext> mContext;
|
||||
|
|
|
@ -20,5 +20,5 @@ LIBXUL_LIBRARY := 1
|
|||
LOCAL_INCLUDES += $(VPATH:%=-I%)
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
|
|
|
@ -23,5 +23,5 @@ LIBXUL_LIBRARY = 1
|
|||
LOCAL_INCLUDES += $(VPATH:%=-I%)
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
|
|
|
@ -15,9 +15,9 @@ LIBXUL_LIBRARY = 1
|
|||
FAIL_ON_WARNINGS = 1
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
|
||||
INCLUDES += \
|
||||
-I$(srcdir)/../../../xml/content/src \
|
||||
|
|
|
@ -20,8 +20,8 @@ DEFINES += -DMOZ_TOOLKIT_SEARCH
|
|||
endif
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
|
||||
LOCAL_INCLUDES += \
|
||||
-I$(srcdir)/../shistory/src \
|
||||
|
|
|
@ -374,6 +374,9 @@ nsSHEntry::Create(nsIURI * aURI, const nsAString &aTitle,
|
|||
//By default the page is not expired
|
||||
mShared->mExpired = false;
|
||||
|
||||
mIsSrcdocEntry = false;
|
||||
mSrcdocData = NullString();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,9 @@ contract @mozilla.org/dom/activities/proxy;1 {ba9bd5cb-76a0-4ecf-a7b3-d2f7c43c59
|
|||
component {5430d6f9-32d6-4924-ba39-6b6d1b093cd6} ActivityWrapper.js
|
||||
contract @mozilla.org/dom/system-messages/wrapper/activity;1 {5430d6f9-32d6-4924-ba39-6b6d1b093cd6}
|
||||
|
||||
component {d2296daa-c406-4c5e-b698-e5f2c1715798} ActivityMessageConfigurator.js
|
||||
contract @mozilla.org/dom/system-messages/configurator/activity;1 {d2296daa-c406-4c5e-b698-e5f2c1715798}
|
||||
|
||||
component {9326952a-dbe3-4d81-a51f-d9c160d96d6b} ActivityRequestHandler.js
|
||||
contract @mozilla.org/dom/activities/request-handler;1 {9326952a-dbe3-4d81-a51f-d9c160d96d6b}
|
||||
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
function debug(aMsg) {
|
||||
// dump("-- ActivityMessageConfigurator.js " + Date.now() + " : " + aMsg + "\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* nsISystemMessagesConfigurator implementation.
|
||||
*/
|
||||
function ActivityMessageConfigurator() {
|
||||
debug("ActivityMessageConfigurator");
|
||||
}
|
||||
|
||||
ActivityMessageConfigurator.prototype = {
|
||||
get safeToSendBeforeRunningApp() {
|
||||
debug("safeToSendBeforeRunningApp returning false");
|
||||
return false;
|
||||
},
|
||||
|
||||
classID: Components.ID("{d2296daa-c406-4c5e-b698-e5f2c1715798}"),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsISystemMessagesConfigurator])
|
||||
}
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ActivityMessageConfigurator]);
|
|
@ -16,6 +16,7 @@ CPP_SOURCES += [
|
|||
|
||||
EXTRA_COMPONENTS += [
|
||||
'Activities.manifest',
|
||||
'ActivityMessageConfigurator.js',
|
||||
'ActivityOptions.js',
|
||||
'ActivityProxy.js',
|
||||
'ActivityRequestHandler.js',
|
||||
|
|
|
@ -17,6 +17,6 @@ include $(topsrcdir)/dom/dom-config.mk
|
|||
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
|
||||
|
|
|
@ -25,6 +25,6 @@ EXPORT_LIBRARY = 1
|
|||
FAIL_ON_WARNINGS := 1
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
|
||||
|
|
|
@ -30,9 +30,8 @@ DEFINES += -DMOZ_B2G_FM
|
|||
endif
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
|
||||
LOCAL_INCLUDES += \
|
||||
-I$(topsrcdir)/js/xpconnect/src \
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -40,6 +40,7 @@ class nsIDOMMozConnection;
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
class Geolocation;
|
||||
class systemMessageCallback;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,6 +70,8 @@ class nsIDOMTelephony;
|
|||
// Navigator: Script "navigator" object
|
||||
//*****************************************************************************
|
||||
|
||||
void NS_GetNavigatorAppName(nsAString& aAppName);
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
|
@ -79,6 +82,15 @@ class BatteryManager;
|
|||
class DesktopNotificationCenter;
|
||||
class SmsManager;
|
||||
class MobileMessageManager;
|
||||
class MozIdleObserver;
|
||||
#ifdef MOZ_GAMEPAD
|
||||
class Gamepad;
|
||||
#endif // MOZ_GAMEPAD
|
||||
#ifdef MOZ_MEDIA_NAVIGATOR
|
||||
class MozDOMGetUserMediaSuccessCallback;
|
||||
class MozDOMGetUserMediaErrorCallback;
|
||||
class MozGetUserMediaDevicesSuccessCallback;
|
||||
#endif // MOZ_MEDIA_NAVIGATOR
|
||||
|
||||
namespace icc {
|
||||
#ifdef MOZ_B2G_RIL
|
||||
|
@ -192,7 +204,7 @@ public:
|
|||
static void Init();
|
||||
|
||||
void Invalidate();
|
||||
nsPIDOMWindow *GetWindow()
|
||||
nsPIDOMWindow *GetWindow() const
|
||||
{
|
||||
return mWindow;
|
||||
}
|
||||
|
@ -218,8 +230,186 @@ public:
|
|||
|
||||
NS_DECL_NSIDOMNAVIGATORCAMERA
|
||||
|
||||
// WebIDL API
|
||||
void GetAppName(nsString& aAppName)
|
||||
{
|
||||
NS_GetNavigatorAppName(aAppName);
|
||||
}
|
||||
void GetAppVersion(nsString& aAppVersion, ErrorResult& aRv)
|
||||
{
|
||||
aRv = GetAppVersion(aAppVersion);
|
||||
}
|
||||
void GetPlatform(nsString& aPlatform, ErrorResult& aRv)
|
||||
{
|
||||
aRv = GetPlatform(aPlatform);
|
||||
}
|
||||
void GetUserAgent(nsString& aUserAgent, ErrorResult& aRv)
|
||||
{
|
||||
aRv = GetUserAgent(aUserAgent);
|
||||
}
|
||||
// The XPCOM GetProduct is OK
|
||||
// The XPCOM GetLanguage is OK
|
||||
bool OnLine();
|
||||
void RegisterProtocolHandler(const nsAString& aScheme, const nsAString& aURL,
|
||||
const nsAString& aTitle, ErrorResult& rv)
|
||||
{
|
||||
rv = RegisterProtocolHandler(aScheme, aURL, aTitle);
|
||||
}
|
||||
void RegisterContentHandler(const nsAString& aMIMEType, const nsAString& aURL,
|
||||
const nsAString& aTitle, ErrorResult& rv)
|
||||
{
|
||||
rv = RegisterContentHandler(aMIMEType, aURL, aTitle);
|
||||
}
|
||||
nsMimeTypeArray* GetMimeTypes(ErrorResult& aRv);
|
||||
nsPluginArray* GetPlugins(ErrorResult& aRv);
|
||||
// The XPCOM GetDoNotTrack is ok
|
||||
Geolocation* GetGeolocation(ErrorResult& aRv);
|
||||
battery::BatteryManager* GetBattery(ErrorResult& aRv);
|
||||
void Vibrate(uint32_t aDuration, ErrorResult& aRv);
|
||||
void Vibrate(const nsTArray<uint32_t>& aDuration, ErrorResult& aRv);
|
||||
void GetAppCodeName(nsString& aAppCodeName, ErrorResult& aRv)
|
||||
{
|
||||
aRv = GetAppCodeName(aAppCodeName);
|
||||
}
|
||||
void GetOscpu(nsString& aOscpu, ErrorResult& aRv)
|
||||
{
|
||||
aRv = GetOscpu(aOscpu);
|
||||
}
|
||||
// The XPCOM GetVendor is OK
|
||||
// The XPCOM GetVendorSub is OK
|
||||
// The XPCOM GetProductSub is OK
|
||||
bool CookieEnabled();
|
||||
void GetBuildID(nsString& aBuildID, ErrorResult& aRv)
|
||||
{
|
||||
aRv = GetBuildID(aBuildID);
|
||||
}
|
||||
nsIDOMMozPowerManager* GetMozPower(ErrorResult& aRv);
|
||||
bool JavaEnabled(ErrorResult& aRv);
|
||||
bool TaintEnabled()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
void AddIdleObserver(MozIdleObserver& aObserver, ErrorResult& aRv);
|
||||
void RemoveIdleObserver(MozIdleObserver& aObserver, ErrorResult& aRv);
|
||||
already_AddRefed<nsIDOMMozWakeLock> RequestWakeLock(const nsAString &aTopic,
|
||||
ErrorResult& aRv);
|
||||
nsDOMDeviceStorage* GetDeviceStorage(const nsAString& aType,
|
||||
ErrorResult& aRv);
|
||||
void GetDeviceStorages(const nsAString& aType,
|
||||
nsTArray<nsRefPtr<nsDOMDeviceStorage> >& aStores,
|
||||
ErrorResult& aRv);
|
||||
DesktopNotificationCenter* GetMozNotification(ErrorResult& aRv);
|
||||
bool MozIsLocallyAvailable(const nsAString& aURI, bool aWhenOffline,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
bool available = false;
|
||||
aRv = MozIsLocallyAvailable(aURI, aWhenOffline, &available);
|
||||
return available;
|
||||
}
|
||||
nsIDOMMozSmsManager* GetMozSms();
|
||||
nsIDOMMozMobileMessageManager* GetMozMobileMessage();
|
||||
nsIDOMMozConnection* GetMozConnection();
|
||||
nsDOMCameraManager* GetMozCameras(ErrorResult& aRv);
|
||||
void MozSetMessageHandler(const nsAString& aType,
|
||||
systemMessageCallback* aCallback,
|
||||
ErrorResult& aRv);
|
||||
bool MozHasPendingMessage(const nsAString& aType, ErrorResult& aRv);
|
||||
#ifdef MOZ_B2G_RIL
|
||||
nsIDOMTelephony* GetMozTelephony(ErrorResult& aRv);
|
||||
nsIDOMMozMobileConnection* GetMozMobileConnection(ErrorResult& aRv);
|
||||
nsIDOMMozCellBroadcast* GetMozCellBroadcast(ErrorResult& aRv);
|
||||
nsIDOMMozVoicemail* GetMozVoicemail(ErrorResult& aRv);
|
||||
nsIDOMMozIccManager* GetMozIccManager(ErrorResult& aRv);
|
||||
#endif // MOZ_B2G_RIL
|
||||
#ifdef MOZ_GAMEPAD
|
||||
void GetGamepads(nsTArray<nsRefPtr<Gamepad> >& aGamepads, ErrorResult& aRv);
|
||||
#endif // MOZ_GAMEPAD
|
||||
#ifdef MOZ_B2G_BT
|
||||
nsIDOMBluetoothManager* GetMozBluetooth(ErrorResult& aRv);
|
||||
#endif // MOZ_B2G_BT
|
||||
#ifdef MOZ_TIME_MANAGER
|
||||
time::TimeManager* GetMozTime(ErrorResult& aRv);
|
||||
#endif // MOZ_TIME_MANAGER
|
||||
#ifdef MOZ_AUDIO_CHANNEL_MANAGER
|
||||
system::AudioChannelManager* GetMozAudioChannelManager(ErrorResult& aRv);
|
||||
#endif // MOZ_AUDIO_CHANNEL_MANAGER
|
||||
#ifdef MOZ_MEDIA_NAVIGATOR
|
||||
void MozGetUserMedia(nsIMediaStreamOptions* aParams,
|
||||
MozDOMGetUserMediaSuccessCallback* aOnSuccess,
|
||||
MozDOMGetUserMediaErrorCallback* aOnError,
|
||||
ErrorResult& aRv);
|
||||
void MozGetUserMedia(nsIMediaStreamOptions* aParams,
|
||||
nsIDOMGetUserMediaSuccessCallback* aOnSuccess,
|
||||
nsIDOMGetUserMediaErrorCallback* aOnError,
|
||||
ErrorResult& aRv);
|
||||
void MozGetUserMediaDevices(MozGetUserMediaDevicesSuccessCallback* aOnSuccess,
|
||||
MozDOMGetUserMediaErrorCallback* aOnError,
|
||||
ErrorResult& aRv);
|
||||
void MozGetUserMediaDevices(nsIGetUserMediaDevicesSuccessCallback* aOnSuccess,
|
||||
nsIDOMGetUserMediaErrorCallback* aOnError,
|
||||
ErrorResult& aRv);
|
||||
#endif // MOZ_MEDIA_NAVIGATOR
|
||||
bool DoNewResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
|
||||
JS::Handle<jsid> aId, JS::MutableHandle<JS::Value> aValue);
|
||||
|
||||
// WebIDL helper methods
|
||||
static bool HasBatterySupport(JSContext* /* unused*/, JSObject* /*unused */);
|
||||
static bool HasPowerSupport(JSContext* /* unused */, JSObject* aGlobal);
|
||||
static bool HasIdleSupport(JSContext* /* unused */, JSObject* aGlobal);
|
||||
static bool HasWakeLockSupport(JSContext* /* unused*/, JSObject* /*unused */);
|
||||
static bool HasDesktopNotificationSupport(JSContext* /* unused*/,
|
||||
JSObject* /*unused */)
|
||||
{
|
||||
return HasDesktopNotificationSupport();
|
||||
}
|
||||
static bool HasSmsSupport(JSContext* /* unused */, JSObject* aGlobal);
|
||||
static bool HasMobileMessageSupport(JSContext* /* unused */,
|
||||
JSObject* aGlobal);
|
||||
static bool HasCameraSupport(JSContext* /* unused */,
|
||||
JSObject* aGlobal);
|
||||
#ifdef MOZ_B2G_RIL
|
||||
static bool HasTelephonySupport(JSContext* /* unused */,
|
||||
JSObject* aGlobal);
|
||||
static bool HasMobileConnectionSupport(JSContext* /* unused */,
|
||||
JSObject* aGlobal);
|
||||
static bool HasCellBroadcastSupport(JSContext* /* unused */,
|
||||
JSObject* aGlobal);
|
||||
static bool HasVoicemailSupport(JSContext* /* unused */,
|
||||
JSObject* aGlobal);
|
||||
static bool HasIccManagerSupport(JSContext* /* unused */,
|
||||
JSObject* aGlobal);
|
||||
#endif // MOZ_B2G_RIL
|
||||
#ifdef MOZ_B2G_BT
|
||||
static bool HasBluetoothSupport(JSContext* /* unused */, JSObject* aGlobal);
|
||||
#endif // MOZ_B2G_BT
|
||||
#ifdef MOZ_TIME_MANAGER
|
||||
static bool HasTimeSupport(JSContext* /* unused */, JSObject* aGlobal);
|
||||
#endif // MOZ_TIME_MANAGER
|
||||
#ifdef MOZ_MEDIA_NAVIGATOR
|
||||
static bool HasUserMediaSupport(JSContext* /* unused */,
|
||||
JSObject* /* unused */);
|
||||
#endif // MOZ_MEDIA_NAVIGATOR
|
||||
|
||||
nsPIDOMWindow* GetParentObject() const
|
||||
{
|
||||
return GetWindow();
|
||||
}
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* cx,
|
||||
JS::Handle<JSObject*> scope) MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
bool CheckPermission(const char* type);
|
||||
static bool CheckPermission(nsPIDOMWindow* aWindow, const char* aType);
|
||||
static bool HasMobileMessageSupport(nsPIDOMWindow* aWindow);
|
||||
// GetWindowFromGlobal returns the inner window for this global, if
|
||||
// any, else null.
|
||||
static already_AddRefed<nsPIDOMWindow> GetWindowFromGlobal(JSObject* aGlobal);
|
||||
|
||||
// Methods to common up the XPCOM and WebIDL implementations of
|
||||
// Add/RemoveIdleObserver.
|
||||
void AddIdleObserver(nsIIdleObserver& aIdleObserver);
|
||||
void RemoveIdleObserver(nsIIdleObserver& aIdleObserver);
|
||||
|
||||
nsRefPtr<nsMimeTypeArray> mMimeTypes;
|
||||
nsRefPtr<nsPluginArray> mPlugins;
|
||||
|
@ -258,6 +448,5 @@ private:
|
|||
nsresult NS_GetNavigatorUserAgent(nsAString& aUserAgent);
|
||||
nsresult NS_GetNavigatorPlatform(nsAString& aPlatform);
|
||||
nsresult NS_GetNavigatorAppVersion(nsAString& aAppVersion);
|
||||
nsresult NS_GetNavigatorAppName(nsAString& aAppName);
|
||||
|
||||
#endif // mozilla_dom_Navigator_h
|
||||
|
|
|
@ -129,7 +129,6 @@
|
|||
#include "nsIXSLTProcessorPrivate.h"
|
||||
|
||||
#include "nsXMLHttpRequest.h"
|
||||
#include "nsIDOMSettingsManager.h"
|
||||
#include "nsIDOMContactManager.h"
|
||||
#include "nsIDOMPermissionSettings.h"
|
||||
#include "nsIDOMApplicationRegistry.h"
|
||||
|
@ -4660,101 +4659,24 @@ nsNavigatorSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
|||
{
|
||||
JS::Rooted<JSObject*> obj(cx, aObj);
|
||||
JS::Rooted<jsid> id(cx, aId);
|
||||
if (!JSID_IS_STRING(id)) {
|
||||
return NS_OK;
|
||||
nsCOMPtr<nsIDOMNavigator> navigator = do_QueryWrappedNative(wrapper);
|
||||
JS::Rooted<JS::Value> value(cx, JS::UndefinedValue());
|
||||
if (!static_cast<Navigator*>(navigator.get())->DoNewResolve(cx, obj, id,
|
||||
&value)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsScriptNameSpaceManager *nameSpaceManager =
|
||||
nsJSRuntime::GetNameSpaceManager();
|
||||
NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
nsDependentJSString name(id);
|
||||
|
||||
const nsGlobalNameStruct* name_struct =
|
||||
nameSpaceManager->LookupNavigatorName(name);
|
||||
if (!name_struct) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (name_struct->mType == nsGlobalNameStruct::eTypeNewDOMBinding) {
|
||||
mozilla::dom::ConstructNavigatorProperty construct = name_struct->mConstructNavigatorProperty;
|
||||
MOZ_ASSERT(construct);
|
||||
|
||||
JS::Rooted<JSObject*> naviObj(cx, js::CheckedUnwrap(obj, /* stopAtOuter = */ false));
|
||||
NS_ENSURE_TRUE(naviObj, NS_ERROR_DOM_SECURITY_ERR);
|
||||
|
||||
JS::Rooted<JSObject*> domObject(cx);
|
||||
{
|
||||
JSAutoCompartment ac(cx, naviObj);
|
||||
|
||||
// Check whether our constructor is enabled after we unwrap Xrays, since
|
||||
// we don't want to define an interface on the Xray if it's disabled in
|
||||
// the target global, even if it's enabled in the Xray's global.
|
||||
if (name_struct->mConstructorEnabled &&
|
||||
!(*name_struct->mConstructorEnabled)(cx, naviObj)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
domObject = construct(cx, naviObj);
|
||||
if (!domObject) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!JS_WrapObject(cx, domObject.address()) ||
|
||||
!JS_DefinePropertyById(cx, obj, id,
|
||||
JS::ObjectValue(*domObject),
|
||||
nullptr, nullptr, JSPROP_ENUMERATE)) {
|
||||
if (!value.isUndefined()) {
|
||||
if (!JS_DefinePropertyById(cx, obj, id, value, JS_PropertyStub,
|
||||
JS_StrictPropertyStub, JSPROP_ENUMERATE)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*_retval = true;
|
||||
*objp = obj;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_ASSERTION(name_struct->mType == nsGlobalNameStruct::eTypeNavigatorProperty,
|
||||
"unexpected type");
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
nsCOMPtr<nsISupports> native(do_CreateInstance(name_struct->mCID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
JS::Rooted<JS::Value> prop_val(cx, JS::UndefinedValue()); // Property value.
|
||||
|
||||
nsCOMPtr<nsIDOMGlobalPropertyInitializer> gpi(do_QueryInterface(native));
|
||||
|
||||
if (gpi) {
|
||||
nsCOMPtr<nsIDOMNavigator> navigator = do_QueryWrappedNative(wrapper);
|
||||
nsIDOMWindow *window = static_cast<Navigator*>(navigator.get())->GetWindow();
|
||||
NS_ENSURE_TRUE(window, NS_ERROR_UNEXPECTED);
|
||||
|
||||
rv = gpi->Init(window, prop_val.address());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
if (JSVAL_IS_PRIMITIVE(prop_val) && !JSVAL_IS_NULL(prop_val)) {
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
rv = WrapNative(cx, obj, native, true, prop_val.address(),
|
||||
getter_AddRefs(holder));
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
if (!JS_WrapValue(cx, prop_val.address())) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
JSBool ok = ::JS_DefinePropertyById(cx, obj, id, prop_val,
|
||||
JS_PropertyStub, JS_StrictPropertyStub,
|
||||
JSPROP_ENUMERATE);
|
||||
|
||||
*_retval = true;
|
||||
*objp = obj;
|
||||
|
||||
return ok ? NS_OK : NS_ERROR_FAILURE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
@ -20,6 +20,6 @@ LOCAL_INCLUDES = \
|
|||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче