Merge mozilla-central into services-central

This commit is contained in:
Gregory Szorc 2013-07-17 18:07:48 -07:00
commit 96106cd9dd
470 changed files with 8479 additions and 8987 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,4 +1,4 @@
{
"revision": "37d94f0bacee10e768aca70b2ea6acab378ebed5",
"revision": "34a53279dad496e201616f5e782bd58ef6d38ae5",
"repo_path": "/integration/gaia-central"
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -117,6 +117,10 @@
]]>
</body>
</method>
<property name="contextNoun" readonly="true"
onget="return this.getAttribute('noun');"/>
<property name="contextActions">
<getter>
<![CDATA[

View File

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

View File

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

View File

@ -1180,6 +1180,9 @@ var StartUI = {
// of the keyboard transition.
ContentAreaObserver.navBarWillBlur();
}
if (aEvent.button == 0)
ContextUI.dismissTabs();
},
handleEvent: function handleEvent(aEvent) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -20,12 +20,14 @@ new
algorithm
atomic
deque
ios
iostream
iterator
limits
list
map
memory
ostream
set
stack
string

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -28,6 +28,7 @@ if CONFIG['MOZ_WEBGL']:
CPP_SOURCES += [
'WebGLActiveInfo.cpp',
'WebGLBuffer.cpp',
'WebGL1Context.cpp',
'WebGLContext.cpp',
'WebGLContextGL.cpp',
'WebGLContextUtils.cpp',

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -16,6 +16,7 @@ CPP_SOURCES += [
EXTRA_COMPONENTS += [
'Activities.manifest',
'ActivityMessageConfigurator.js',
'ActivityOptions.js',
'ActivityProxy.js',
'ActivityRequestHandler.js',

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

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