mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-13 05:15:45 +00:00
merge m-c into fig
This commit is contained in:
commit
b2c048be2d
4
CLOBBER
4
CLOBBER
@ -17,5 +17,5 @@
|
||||
#
|
||||
# Modifying this file will now automatically clobber the buildbot machines \o/
|
||||
#
|
||||
Bug 889503 - Move Settings API to WebIDL.
|
||||
Requires a clobber due to Bug 890744.
|
||||
Bug 886886 - replace fixed-ratio capture resampler in webrtc with speex resampler
|
||||
Requires a clobber due to modification of a .gypi file without a .gyp or configure.in change
|
||||
|
@ -11,7 +11,7 @@ typedef long AccessibleTextBoundary;
|
||||
interface nsIAccessible;
|
||||
interface nsIPersistentProperties;
|
||||
|
||||
[scriptable, uuid(0f4633b1-550c-4b50-8c04-0eb1005eef2f)]
|
||||
[scriptable, uuid(43d81eb0-1215-4dc4-9226-a4355bd2d20d)]
|
||||
interface nsIAccessibleText : nsISupports
|
||||
{
|
||||
// In parameters for character offsets:
|
||||
@ -27,7 +27,6 @@ interface nsIAccessibleText : nsISupports
|
||||
const AccessibleTextBoundary BOUNDARY_SENTENCE_END = 4; // don't use, deprecated
|
||||
const AccessibleTextBoundary BOUNDARY_LINE_START = 5;
|
||||
const AccessibleTextBoundary BOUNDARY_LINE_END = 6;
|
||||
const AccessibleTextBoundary BOUNDARY_ATTRIBUTE_RANGE = 7;
|
||||
|
||||
/**
|
||||
* The current current caret offset.
|
||||
|
@ -112,7 +112,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
|
||||
eNoLiveAttr,
|
||||
eTableCell,
|
||||
kNoReqStates,
|
||||
eARIASelectable,
|
||||
eARIASelectableIfDefined,
|
||||
eARIAReadonlyOrEditableIfDefined
|
||||
},
|
||||
{ // combobox
|
||||
@ -463,7 +463,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
|
||||
eNoLiveAttr,
|
||||
eTableCell,
|
||||
kNoReqStates,
|
||||
eARIASelectable,
|
||||
eARIASelectableIfDefined,
|
||||
eARIAReadonlyOrEditableIfDefined
|
||||
},
|
||||
{ // scrollbar
|
||||
|
@ -300,6 +300,16 @@ aria::MapToState(EStateRule aRule, dom::Element* aElement, uint64_t* aState)
|
||||
return true;
|
||||
}
|
||||
|
||||
case eARIASelectableIfDefined:
|
||||
{
|
||||
static const TokenTypeData data(
|
||||
nsGkAtoms::aria_selected, eBoolType,
|
||||
states::SELECTABLE, states::SELECTED);
|
||||
|
||||
MapTokenType(aElement, aState, data);
|
||||
return true;
|
||||
}
|
||||
|
||||
case eReadonlyUntilEditable:
|
||||
{
|
||||
if (!(*aState & states::EDITABLE))
|
||||
|
@ -42,6 +42,7 @@ enum EStateRule
|
||||
eARIAReadonlyOrEditableIfDefined,
|
||||
eARIARequired,
|
||||
eARIASelectable,
|
||||
eARIASelectableIfDefined,
|
||||
eReadonlyUntilEditable,
|
||||
eIndeterminateIfNoValue
|
||||
};
|
||||
|
@ -300,7 +300,7 @@ IDRefsIterator::GetElem(const nsDependentSubstring& aID)
|
||||
// In case of bound element check its anonymous subtree.
|
||||
if (!mContent->IsInAnonymousSubtree()) {
|
||||
dom::Element* refElm = mContent->OwnerDoc()->GetElementById(aID);
|
||||
if (refElm || !mContent->OwnerDoc()->BindingManager()->GetBinding(mContent))
|
||||
if (refElm || !mContent->GetXBLBinding())
|
||||
return refElm;
|
||||
}
|
||||
|
||||
@ -318,7 +318,7 @@ IDRefsIterator::GetElem(const nsDependentSubstring& aID)
|
||||
}
|
||||
|
||||
// Check inside the binding of the element.
|
||||
if (mContent->OwnerDoc()->BindingManager()->GetBinding(mContent)) {
|
||||
if (mContent->GetXBLBinding()) {
|
||||
return mContent->OwnerDoc()->
|
||||
GetAnonymousElementByAttribute(mContent, nsGkAtoms::anonid, aID);
|
||||
}
|
||||
|
@ -871,7 +871,10 @@ nsAccessibilityService::GetOrCreateAccessible(nsINode* aNode,
|
||||
if (content->IsNodeOfType(nsINode::eTEXT)) {
|
||||
nsAutoString text;
|
||||
frame->GetRenderedText(&text, nullptr, nullptr, 0, UINT32_MAX);
|
||||
if (text.IsEmpty()) {
|
||||
// Ignore not rendered text nodes and whitespace text nodes between table
|
||||
// cells.
|
||||
if (text.IsEmpty() ||
|
||||
(aContext->IsTableRow() && nsCoreUtils::IsWhitespaceString(text))) {
|
||||
if (aIsSubtreeHidden)
|
||||
*aIsSubtreeHidden = true;
|
||||
|
||||
|
@ -654,6 +654,20 @@ nsCoreUtils::ScrollTo(nsIPresShell* aPresShell, nsIContent* aContent,
|
||||
nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
|
||||
}
|
||||
|
||||
bool
|
||||
nsCoreUtils::IsWhitespaceString(const nsSubstring& aString)
|
||||
{
|
||||
nsSubstring::const_char_iterator iterBegin, iterEnd;
|
||||
|
||||
aString.BeginReading(iterBegin);
|
||||
aString.EndReading(iterEnd);
|
||||
|
||||
while (iterBegin != iterEnd && IsWhitespace(*iterBegin))
|
||||
++iterBegin;
|
||||
|
||||
return iterBegin == iterEnd;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsAccessibleDOMStringList
|
||||
|
@ -6,7 +6,6 @@
|
||||
#ifndef nsCoreUtils_h_
|
||||
#define nsCoreUtils_h_
|
||||
|
||||
|
||||
#include "nsIContent.h"
|
||||
#include "nsIBoxObject.h"
|
||||
#include "nsIPresShell.h"
|
||||
@ -294,6 +293,21 @@ public:
|
||||
aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::scope);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given string is empty or contains whitespace symbols
|
||||
* only. In contrast to nsWhitespaceTokenizer class it takes into account
|
||||
* non-breaking space (0xa0).
|
||||
*/
|
||||
static bool IsWhitespaceString(const nsSubstring& aString);
|
||||
|
||||
/**
|
||||
* Returns true if the given character is whitespace symbol.
|
||||
*/
|
||||
static bool IsWhitespace(PRUnichar aChar)
|
||||
{
|
||||
return aChar == ' ' || aChar == '\n' ||
|
||||
aChar == '\r' || aChar == '\t' || aChar == 0xa0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -45,7 +45,7 @@ nsTextEquivUtils::GetNameFromSubtree(Accessible* aAccessible,
|
||||
nsAutoString name;
|
||||
AppendFromAccessibleChildren(aAccessible, &name);
|
||||
name.CompressWhitespace();
|
||||
if (!IsWhitespaceString(name))
|
||||
if (!nsCoreUtils::IsWhitespaceString(name))
|
||||
aName = name;
|
||||
}
|
||||
}
|
||||
@ -351,38 +351,17 @@ nsTextEquivUtils::AppendString(nsAString *aString,
|
||||
return false;
|
||||
|
||||
// Insert spaces to insure that words from controls aren't jammed together.
|
||||
if (!aString->IsEmpty() && !IsWhitespace(aString->Last()))
|
||||
if (!aString->IsEmpty() && !nsCoreUtils::IsWhitespace(aString->Last()))
|
||||
aString->Append(PRUnichar(' '));
|
||||
|
||||
aString->Append(aTextEquivalent);
|
||||
|
||||
if (!IsWhitespace(aString->Last()))
|
||||
if (!nsCoreUtils::IsWhitespace(aString->Last()))
|
||||
aString->Append(PRUnichar(' '));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
nsTextEquivUtils::IsWhitespaceString(const nsSubstring& aString)
|
||||
{
|
||||
nsSubstring::const_char_iterator iterBegin, iterEnd;
|
||||
|
||||
aString.BeginReading(iterBegin);
|
||||
aString.EndReading(iterEnd);
|
||||
|
||||
while (iterBegin != iterEnd && IsWhitespace(*iterBegin))
|
||||
++iterBegin;
|
||||
|
||||
return iterBegin == iterEnd;
|
||||
}
|
||||
|
||||
bool
|
||||
nsTextEquivUtils::IsWhitespace(PRUnichar aChar)
|
||||
{
|
||||
return aChar == ' ' || aChar == '\n' ||
|
||||
aChar == '\r' || aChar == '\t' || aChar == 0xa0;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
nsTextEquivUtils::GetRoleRule(role aRole)
|
||||
{
|
||||
|
@ -137,18 +137,6 @@ private:
|
||||
static bool AppendString(nsAString *aString,
|
||||
const nsAString& aTextEquivalent);
|
||||
|
||||
/**
|
||||
* Returns true if the given string is empty or contains whitespace symbols
|
||||
* only. In contrast to nsWhitespaceTokenizer class it takes into account
|
||||
* non-breaking space (0xa0).
|
||||
*/
|
||||
static bool IsWhitespaceString(const nsSubstring& aString);
|
||||
|
||||
/**
|
||||
* Returns true if the given character is whitespace symbol.
|
||||
*/
|
||||
static bool IsWhitespace(PRUnichar aChar);
|
||||
|
||||
/**
|
||||
* Returns the rule (constant of ETextEquivRule) for a given role.
|
||||
*/
|
||||
|
@ -465,8 +465,8 @@ ARIAGridAccessible::SetARIASelected(Accessible* aAccessible,
|
||||
rv = content->SetAttr(kNameSpaceID_None, nsGkAtoms::aria_selected,
|
||||
NS_LITERAL_STRING("true"), aNotify);
|
||||
else
|
||||
rv = content->UnsetAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::aria_selected, aNotify);
|
||||
rv = content->SetAttr(kNameSpaceID_None, nsGkAtoms::aria_selected,
|
||||
NS_LITERAL_STRING("false"), aNotify);
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
@ -533,6 +533,7 @@ ARIAGridCellAccessible::
|
||||
ARIAGridCellAccessible(nsIContent* aContent, DocAccessible* aDoc) :
|
||||
HyperTextAccessibleWrap(aContent, aDoc), xpcAccessibleTableCell(this)
|
||||
{
|
||||
mGenericTypes |= eTableCell;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -515,6 +515,7 @@ public:
|
||||
bool IsTable() const { return HasGenericType(eTable); }
|
||||
virtual TableAccessible* AsTable() { return nullptr; }
|
||||
|
||||
bool IsTableCell() const { return HasGenericType(eTableCell); }
|
||||
virtual TableCellAccessible* AsTableCell() { return nullptr; }
|
||||
const TableCellAccessible* AsTableCell() const
|
||||
{ return const_cast<Accessible*>(this)->AsTableCell(); }
|
||||
|
@ -878,186 +878,6 @@ HyperTextAccessible::FindLineBoundary(int32_t aOffset,
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
Gets the specified text relative to aBoundaryType, which means:
|
||||
BOUNDARY_CHAR The character before/at/after the offset is returned.
|
||||
BOUNDARY_WORD_START From the word start before/at/after the offset to the next word start.
|
||||
BOUNDARY_WORD_END From the word end before/at/after the offset to the next work end.
|
||||
BOUNDARY_LINE_START From the line start before/at/after the offset to the next line start.
|
||||
BOUNDARY_LINE_END From the line end before/at/after the offset to the next line start.
|
||||
*/
|
||||
|
||||
nsresult
|
||||
HyperTextAccessible::GetTextHelper(EGetTextType aType,
|
||||
AccessibleTextBoundary aBoundaryType,
|
||||
int32_t aOffset,
|
||||
int32_t* aStartOffset, int32_t* aEndOffset,
|
||||
nsAString& aText)
|
||||
{
|
||||
aText.Truncate();
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aStartOffset);
|
||||
NS_ENSURE_ARG_POINTER(aEndOffset);
|
||||
*aStartOffset = *aEndOffset = 0;
|
||||
|
||||
int32_t offset = ConvertMagicOffset(aOffset);
|
||||
if (offset < 0)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
if (aOffset == nsIAccessibleText::TEXT_OFFSET_CARET && offset > 0 &&
|
||||
(aBoundaryType == BOUNDARY_LINE_START ||
|
||||
aBoundaryType == BOUNDARY_LINE_END)) {
|
||||
// It is the same character offset when the caret is visually at
|
||||
// the very end of a line or the start of a new line. Getting text at
|
||||
// the line should provide the line with the visual caret,
|
||||
// otherwise screen readers will announce the wrong line as the user
|
||||
// presses up or down arrow and land at the end of a line.
|
||||
nsRefPtr<nsFrameSelection> frameSelection = FrameSelection();
|
||||
if (frameSelection &&
|
||||
frameSelection->GetHint() == nsFrameSelection::HINTLEFT) {
|
||||
-- offset; // We are at the start of a line
|
||||
}
|
||||
}
|
||||
|
||||
nsSelectionAmount amount;
|
||||
bool needsStart = false;
|
||||
switch (aBoundaryType) {
|
||||
case BOUNDARY_WORD_START:
|
||||
needsStart = true;
|
||||
amount = eSelectWord;
|
||||
break;
|
||||
|
||||
case BOUNDARY_WORD_END:
|
||||
amount = eSelectWord;
|
||||
break;
|
||||
|
||||
case BOUNDARY_LINE_START:
|
||||
// Newlines are considered at the end of a line. Since getting
|
||||
// the BOUNDARY_LINE_START gets the text from the line-start to the next
|
||||
// line-start, the newline is included at the end of the string.
|
||||
needsStart = true;
|
||||
amount = eSelectLine;
|
||||
break;
|
||||
|
||||
case BOUNDARY_LINE_END:
|
||||
// Newlines are considered at the end of a line. Since getting
|
||||
// the BOUNDARY_END_START gets the text from the line-end to the next
|
||||
//line-end, the newline is included at the beginning of the string.
|
||||
amount = eSelectLine;
|
||||
break;
|
||||
|
||||
case BOUNDARY_ATTRIBUTE_RANGE:
|
||||
{
|
||||
nsresult rv = GetTextAttributes(false, offset,
|
||||
aStartOffset, aEndOffset, nullptr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return GetText(*aStartOffset, *aEndOffset, aText);
|
||||
}
|
||||
|
||||
default: // Note, sentence support is deprecated and falls through to here
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
int32_t startOffset = offset + (aBoundaryType == BOUNDARY_LINE_END); // Avoid getting the previous line
|
||||
int32_t endOffset = startOffset;
|
||||
|
||||
// Convert offsets to frame-relative
|
||||
nsRefPtr<Accessible> startAcc;
|
||||
nsIFrame *startFrame = GetPosAndText(startOffset, endOffset, nullptr, nullptr,
|
||||
nullptr, getter_AddRefs(startAcc));
|
||||
|
||||
if (!startFrame) {
|
||||
int32_t textLength = CharacterCount();
|
||||
if (aBoundaryType == BOUNDARY_LINE_START && offset > 0 && offset == textLength) {
|
||||
// Asking for start of line, while on last character
|
||||
if (startAcc)
|
||||
startFrame = startAcc->GetFrame();
|
||||
}
|
||||
if (!startFrame) {
|
||||
return offset > textLength ? NS_ERROR_FAILURE : NS_OK;
|
||||
}
|
||||
else {
|
||||
// We're on the last continuation since we're on the last character
|
||||
startFrame = startFrame->GetLastContinuation();
|
||||
}
|
||||
}
|
||||
|
||||
int32_t finalStartOffset = 0, finalEndOffset = 0;
|
||||
EWordMovementType wordMovementType = needsStart ? eStartWord : eEndWord;
|
||||
|
||||
nsIPresShell* presShell = mDoc->PresShell();
|
||||
// If aType == eGetAt we'll change both the start and end offset from
|
||||
// the original offset
|
||||
if (aType == eGetAfter) {
|
||||
finalStartOffset = offset;
|
||||
}
|
||||
else {
|
||||
finalStartOffset = GetRelativeOffset(presShell, startFrame, startOffset,
|
||||
startAcc,
|
||||
(amount == eSelectLine ? eSelectBeginLine : amount),
|
||||
eDirPrevious, needsStart,
|
||||
wordMovementType);
|
||||
NS_ENSURE_TRUE(finalStartOffset >= 0, NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
if (aType == eGetBefore) {
|
||||
finalEndOffset = offset;
|
||||
}
|
||||
else {
|
||||
// Start moving forward from the start so that we don't get
|
||||
// 2 words/lines if the offset occurred on whitespace boundary
|
||||
// Careful, startOffset and endOffset are passed by reference to GetPosAndText() and changed
|
||||
// For BOUNDARY_LINE_END, make sure we start of this line
|
||||
startOffset = endOffset = finalStartOffset + (aBoundaryType == BOUNDARY_LINE_END);
|
||||
nsRefPtr<Accessible> endAcc;
|
||||
nsIFrame *endFrame = GetPosAndText(startOffset, endOffset, nullptr, nullptr,
|
||||
nullptr, getter_AddRefs(endAcc));
|
||||
if (endAcc && endAcc->Role() == roles::STATICTEXT) {
|
||||
// Static text like list bullets will ruin our forward calculation,
|
||||
// since the caret cannot be in the static text. Start just after the static text.
|
||||
startOffset = endOffset = finalStartOffset +
|
||||
(aBoundaryType == BOUNDARY_LINE_END) +
|
||||
nsAccUtils::TextLength(endAcc);
|
||||
|
||||
endFrame = GetPosAndText(startOffset, endOffset, nullptr, nullptr,
|
||||
nullptr, getter_AddRefs(endAcc));
|
||||
}
|
||||
if (!endFrame) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
finalEndOffset = GetRelativeOffset(presShell, endFrame, endOffset, endAcc,
|
||||
(amount == eSelectLine ? eSelectEndLine : amount),
|
||||
eDirNext, needsStart, wordMovementType);
|
||||
NS_ENSURE_TRUE(endOffset >= 0, NS_ERROR_FAILURE);
|
||||
if (finalEndOffset == offset) {
|
||||
if (aType == eGetAt && amount == eSelectWord) {
|
||||
// Fix word error for the first character in word: PeekOffset() will return the previous word when
|
||||
// offset points to the first character of the word, but accessibility APIs want the current word
|
||||
// that the first character is in
|
||||
return GetTextHelper(eGetAfter, aBoundaryType, offset,
|
||||
aStartOffset, aEndOffset, aText);
|
||||
}
|
||||
int32_t textLength = CharacterCount();
|
||||
if (finalEndOffset < textLength) {
|
||||
// This happens sometimes when current character at finalStartOffset
|
||||
// is an embedded object character representing another hypertext, that
|
||||
// the AT really needs to dig into separately
|
||||
++ finalEndOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*aStartOffset = finalStartOffset;
|
||||
*aEndOffset = finalEndOffset;
|
||||
|
||||
NS_ASSERTION((finalStartOffset < offset && finalEndOffset >= offset) || aType != eGetBefore, "Incorrect results for GetTextHelper");
|
||||
NS_ASSERTION((finalStartOffset <= offset && finalEndOffset > offset) || aType == eGetBefore, "Incorrect results for GetTextHelper");
|
||||
|
||||
GetPosAndText(finalStartOffset, finalEndOffset, &aText);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* nsIAccessibleText impl.
|
||||
*/
|
||||
@ -1120,10 +940,6 @@ HyperTextAccessible::GetTextBeforeOffset(int32_t aOffset,
|
||||
*aStartOffset = FindLineBoundary(*aEndOffset, ePrevLineEnd);
|
||||
return GetText(*aStartOffset, *aEndOffset, aText);
|
||||
|
||||
case BOUNDARY_ATTRIBUTE_RANGE:
|
||||
return GetTextHelper(eGetBefore, aBoundaryType, aOffset,
|
||||
aStartOffset, aEndOffset, aText);
|
||||
|
||||
default:
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
@ -1177,10 +993,6 @@ HyperTextAccessible::GetTextAtOffset(int32_t aOffset,
|
||||
*aEndOffset = FindLineBoundary(offset, eThisLineEnd);
|
||||
return GetText(*aStartOffset, *aEndOffset, aText);
|
||||
|
||||
case BOUNDARY_ATTRIBUTE_RANGE:
|
||||
return GetTextHelper(eGetAt, aBoundaryType, aOffset,
|
||||
aStartOffset, aEndOffset, aText);
|
||||
|
||||
default:
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
@ -1243,10 +1055,6 @@ HyperTextAccessible::GetTextAfterOffset(int32_t aOffset,
|
||||
*aEndOffset = FindLineBoundary(offset, eNextLineEnd);
|
||||
return GetText(*aStartOffset, *aEndOffset, aText);
|
||||
|
||||
case BOUNDARY_ATTRIBUTE_RANGE:
|
||||
return GetTextHelper(eGetAfter, aBoundaryType, aOffset,
|
||||
aStartOffset, aEndOffset, aText);
|
||||
|
||||
default:
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
@ -334,22 +334,8 @@ protected:
|
||||
nsSelectionAmount aAmount,
|
||||
EWordMovementType aWordMovementType = eDefaultBehavior);
|
||||
|
||||
/*
|
||||
* This does the work for nsIAccessibleText::GetText[At|Before|After]Offset
|
||||
* @param aType, eGetBefore, eGetAt, eGetAfter
|
||||
* @param aBoundaryType, char/word-start/word-end/line-start/line-end/paragraph/attribute
|
||||
* @param aOffset, offset into the hypertext to start from
|
||||
* @param *aStartOffset, the resulting start offset for the returned substring
|
||||
* @param *aEndOffset, the resulting end offset for the returned substring
|
||||
* @param aText, the resulting substring
|
||||
* @return success/failure code
|
||||
*/
|
||||
nsresult GetTextHelper(EGetTextType aType, AccessibleTextBoundary aBoundaryType,
|
||||
int32_t aOffset, int32_t *aStartOffset, int32_t *aEndOffset,
|
||||
nsAString & aText);
|
||||
|
||||
/**
|
||||
* Used by GetTextHelper() to move backward/forward from a given point
|
||||
* Used by FindOffset() to move backward/forward from a given point
|
||||
* by word/line/etc.
|
||||
*
|
||||
* @param aPresShell the current presshell we're moving in
|
||||
|
@ -48,6 +48,7 @@ HTMLTableCellAccessible::
|
||||
HTMLTableCellAccessible(nsIContent* aContent, DocAccessible* aDoc) :
|
||||
HyperTextAccessibleWrap(aContent, aDoc), xpcAccessibleTableCell(this)
|
||||
{
|
||||
mGenericTypes |= eTableCell;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -356,7 +356,56 @@ this.AccessFu = {
|
||||
|
||||
// Keep track of message managers tha already have a 'content-script.js'
|
||||
// injected.
|
||||
_processedMessageManagers: []
|
||||
_processedMessageManagers: [],
|
||||
|
||||
/**
|
||||
* Adjusts the given bounds relative to the given browser. Converts from screen
|
||||
* or device pixels to either device or CSS pixels.
|
||||
* @param {Rect} aJsonBounds the bounds to adjust
|
||||
* @param {browser} aBrowser the browser we want the bounds relative to
|
||||
* @param {bool} aToCSSPixels whether to convert to CSS pixels (as opposed to
|
||||
* device pixels)
|
||||
* @param {bool} aFromDevicePixels whether to convert from device pixels (as
|
||||
* opposed to screen pixels)
|
||||
*/
|
||||
adjustContentBounds: function(aJsonBounds, aBrowser, aToCSSPixels, aFromDevicePixels) {
|
||||
let bounds = new Rect(aJsonBounds.left, aJsonBounds.top,
|
||||
aJsonBounds.right - aJsonBounds.left,
|
||||
aJsonBounds.bottom - aJsonBounds.top);
|
||||
let win = Utils.win;
|
||||
let dpr = win.devicePixelRatio;
|
||||
let vp = Utils.getViewport(win);
|
||||
let offset = { left: -win.mozInnerScreenX, top: -win.mozInnerScreenY };
|
||||
|
||||
if (!aBrowser.contentWindow) {
|
||||
// OOP browser, add offset of browser.
|
||||
// The offset of the browser element in relation to its parent window.
|
||||
let clientRect = aBrowser.getBoundingClientRect();
|
||||
let win = aBrowser.ownerDocument.defaultView;
|
||||
offset.left += clientRect.left + win.mozInnerScreenX;
|
||||
offset.top += clientRect.top + win.mozInnerScreenY;
|
||||
}
|
||||
|
||||
// Here we scale from screen pixels to layout device pixels by dividing by
|
||||
// the resolution (caused by pinch-zooming). The resolution is the viewport
|
||||
// zoom divided by the devicePixelRatio. If there's no viewport, then we're
|
||||
// on a platform without pinch-zooming and we can just ignore this.
|
||||
if (!aFromDevicePixels && vp) {
|
||||
bounds = bounds.scale(vp.zoom / dpr, vp.zoom / dpr);
|
||||
}
|
||||
|
||||
// Add the offset; the offset is in CSS pixels, so multiply the
|
||||
// devicePixelRatio back in before adding to preserve unit consistency.
|
||||
bounds = bounds.translate(offset.left * dpr, offset.top * dpr);
|
||||
|
||||
// If we want to get to CSS pixels from device pixels, this needs to be
|
||||
// further divided by the devicePixelRatio due to widget scaling.
|
||||
if (aToCSSPixels) {
|
||||
bounds = bounds.scale(1 / dpr, 1 / dpr);
|
||||
}
|
||||
|
||||
return bounds.expandToIntegers();
|
||||
}
|
||||
};
|
||||
|
||||
var Output = {
|
||||
@ -472,7 +521,7 @@ var Output = {
|
||||
}
|
||||
|
||||
let padding = aDetails.padding;
|
||||
let r = this._adjustBounds(aDetails.bounds, aBrowser);
|
||||
let r = AccessFu.adjustContentBounds(aDetails.bounds, aBrowser, true);
|
||||
|
||||
// First hide it to avoid flickering when changing the style.
|
||||
highlightBox.style.display = 'none';
|
||||
@ -536,7 +585,7 @@ var Output = {
|
||||
for each (let androidEvent in aDetails) {
|
||||
androidEvent.type = 'Accessibility:Event';
|
||||
if (androidEvent.bounds)
|
||||
androidEvent.bounds = this._adjustBounds(androidEvent.bounds, aBrowser, true);
|
||||
androidEvent.bounds = AccessFu.adjustContentBounds(androidEvent.bounds, aBrowser);
|
||||
|
||||
switch(androidEvent.eventType) {
|
||||
case ANDROID_VIEW_TEXT_CHANGED:
|
||||
@ -559,33 +608,6 @@ var Output = {
|
||||
|
||||
Braille: function Braille(aDetails, aBrowser) {
|
||||
Logger.debug('Braille output: ' + aDetails.text);
|
||||
},
|
||||
|
||||
_adjustBounds: function(aJsonBounds, aBrowser, aIncludeZoom) {
|
||||
let bounds = new Rect(aJsonBounds.left, aJsonBounds.top,
|
||||
aJsonBounds.right - aJsonBounds.left,
|
||||
aJsonBounds.bottom - aJsonBounds.top);
|
||||
let vp = Utils.getViewport(Utils.win) || { zoom: 1.0, offsetY: 0 };
|
||||
let root = Utils.win;
|
||||
let offset = { left: -root.mozInnerScreenX, top: -root.mozInnerScreenY };
|
||||
let scale = 1 / Utils.getPixelsPerCSSPixel(Utils.win);
|
||||
|
||||
if (!aBrowser.contentWindow) {
|
||||
// OOP browser, add offset of browser.
|
||||
// The offset of the browser element in relation to its parent window.
|
||||
let clientRect = aBrowser.getBoundingClientRect();
|
||||
let win = aBrowser.ownerDocument.defaultView;
|
||||
offset.left += clientRect.left + win.mozInnerScreenX;
|
||||
offset.top += clientRect.top + win.mozInnerScreenY;
|
||||
}
|
||||
|
||||
let newBounds = bounds.scale(scale, scale).translate(offset.left, offset.top);
|
||||
|
||||
if (aIncludeZoom) {
|
||||
newBounds = newBounds.scale(vp.zoom, vp.zoom);
|
||||
}
|
||||
|
||||
return newBounds.expandToIntegers();
|
||||
}
|
||||
};
|
||||
|
||||
@ -615,9 +637,6 @@ var Input = {
|
||||
this._handleKeypress(aEvent);
|
||||
break;
|
||||
case 'mozAccessFuGesture':
|
||||
let vp = Utils.getViewport(Utils.win) || { zoom: 1.0 };
|
||||
aEvent.detail.x *= vp.zoom;
|
||||
aEvent.detail.y *= vp.zoom;
|
||||
this._handleGesture(aEvent.detail);
|
||||
break;
|
||||
}
|
||||
@ -796,10 +815,10 @@ var Input = {
|
||||
|
||||
activateContextMenu: function activateContextMenu(aMessage) {
|
||||
if (Utils.MozBuildApp === 'mobile/android') {
|
||||
let vp = Utils.getViewport(Utils.win) || { zoom: 1.0 };
|
||||
let p = AccessFu.adjustContentBounds(aMessage.bounds, Utils.CurrentBrowser,
|
||||
true, true).center();
|
||||
Services.obs.notifyObservers(null, 'Gesture:LongPress',
|
||||
JSON.stringify({x: aMessage.x / vp.zoom,
|
||||
y: aMessage.y / vp.zoom}));
|
||||
JSON.stringify({x: p.x, y: p.y}));
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -326,8 +326,8 @@ this.TouchAdapter = {
|
||||
* of one single touch.
|
||||
*/
|
||||
function TouchPoint(aTouch, aTime, aDPI) {
|
||||
this.startX = this.x = aTouch.screenX;
|
||||
this.startY = this.y = aTouch.screenY;
|
||||
this.startX = this.x = aTouch.screenX * this.scaleFactor;
|
||||
this.startY = this.y = aTouch.screenY * this.scaleFactor;
|
||||
this.startTime = aTime;
|
||||
this.distanceTraveled = 0;
|
||||
this.dpi = aDPI;
|
||||
@ -338,8 +338,8 @@ TouchPoint.prototype = {
|
||||
update: function TouchPoint_update(aTouch, aTime) {
|
||||
let lastX = this.x;
|
||||
let lastY = this.y;
|
||||
this.x = aTouch.screenX;
|
||||
this.y = aTouch.screenY;
|
||||
this.x = aTouch.screenX * this.scaleFactor;
|
||||
this.y = aTouch.screenY * this.scaleFactor;
|
||||
this.time = aTime;
|
||||
|
||||
this.distanceTraveled += this.getDistanceToCoord(lastX, lastY);
|
||||
@ -349,6 +349,20 @@ TouchPoint.prototype = {
|
||||
return Math.sqrt(Math.pow(this.x - aX, 2) + Math.pow(this.y - aY, 2));
|
||||
},
|
||||
|
||||
get scaleFactor() {
|
||||
if (!this._scaleFactor) {
|
||||
// Android events come with the x, y coordinates affected by the widget
|
||||
// scaling; we restore it to normal here.
|
||||
if (Utils.MozBuildApp == 'mobile/android') {
|
||||
this._scaleFactor = Utils.win.devicePixelRatio;
|
||||
} else {
|
||||
this._scaleFactor = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return this._scaleFactor;
|
||||
},
|
||||
|
||||
finish: function TouchPoint_finish() {
|
||||
this.done = true;
|
||||
},
|
||||
|
@ -221,11 +221,6 @@ this.Utils = {
|
||||
return doc.QueryInterface(Ci.nsIAccessibleDocument).virtualCursor;
|
||||
},
|
||||
|
||||
getPixelsPerCSSPixel: function getPixelsPerCSSPixel(aWindow) {
|
||||
return aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils).screenPixelsPerCSSPixel;
|
||||
},
|
||||
|
||||
getBounds: function getBounds(aAccessible) {
|
||||
let objX = {}, objY = {}, objW = {}, objH = {};
|
||||
aAccessible.getBounds(objX, objY, objW, objH);
|
||||
@ -684,4 +679,4 @@ PrefCache.prototype = {
|
||||
|
||||
QueryInterface : XPCOMUtils.generateQI([Ci.nsIObserver,
|
||||
Ci.nsISupportsWeakReference])
|
||||
};
|
||||
};
|
||||
|
@ -97,10 +97,8 @@ function moveToPoint(aMessage) {
|
||||
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);
|
||||
let dpr = content.devicePixelRatio;
|
||||
vc.moveToPoint(rule, details.x * dpr, details.y * dpr, true);
|
||||
forwardToChild(aMessage, moveToPoint, vc.position);
|
||||
} catch (x) {
|
||||
Logger.logException(x, 'Failed move to point');
|
||||
@ -219,9 +217,7 @@ function activateCurrent(aMessage) {
|
||||
function activateContextMenu(aMessage) {
|
||||
function sendContextMenuCoordinates(aAccessible) {
|
||||
let bounds = Utils.getBounds(aAccessible);
|
||||
sendAsyncMessage('AccessFu:ActivateContextMenu',
|
||||
{ x: bounds.left + bounds.width / 2,
|
||||
y: bounds.top + bounds.height / 2 });
|
||||
sendAsyncMessage('AccessFu:ActivateContextMenu', {bounds: bounds});
|
||||
}
|
||||
|
||||
let position = Utils.getVirtualCursor(content.document).position;
|
||||
|
@ -731,6 +731,7 @@ XULListCellAccessible::
|
||||
XULListCellAccessible(nsIContent* aContent, DocAccessible* aDoc) :
|
||||
HyperTextAccessibleWrap(aContent, aDoc), xpcAccessibleTableCell(this)
|
||||
{
|
||||
mGenericTypes |= eTableCell;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -453,6 +453,7 @@ XULTreeGridCellAccessible::
|
||||
{
|
||||
mParent = aRowAcc;
|
||||
mStateFlags |= eSharedNode;
|
||||
mGenericTypes |= eTableCell;
|
||||
|
||||
NS_ASSERTION(mTreeView, "mTreeView is null");
|
||||
|
||||
|
@ -361,7 +361,8 @@ function testTableSelection(aIdentifier, aCellsArray, aMsg)
|
||||
for (var colIdx = 0; colIdx < colsCount; colIdx++) {
|
||||
var isColSelected = true;
|
||||
for (var rowIdx = 0; rowIdx < rowCount; rowIdx++) {
|
||||
if (aCellsArray[rowIdx][colIdx] == false) {
|
||||
if (aCellsArray[rowIdx][colIdx] == false ||
|
||||
aCellsArray[rowIdx][colIdx] == undefined) {
|
||||
isColSelected = false;
|
||||
break;
|
||||
}
|
||||
@ -401,7 +402,8 @@ function testTableSelection(aIdentifier, aCellsArray, aMsg)
|
||||
for (var rowIdx = 0; rowIdx < rowCount; rowIdx++) {
|
||||
var isRowSelected = true;
|
||||
for (var colIdx = 0; colIdx < colsCount; colIdx++) {
|
||||
if (aCellsArray[rowIdx][colIdx] == false) {
|
||||
if (aCellsArray[rowIdx][colIdx] == false ||
|
||||
aCellsArray[rowIdx][colIdx] == undefined) {
|
||||
isRowSelected = false;
|
||||
break;
|
||||
}
|
||||
@ -442,7 +444,8 @@ function testTableSelection(aIdentifier, aCellsArray, aMsg)
|
||||
if (aCellsArray[rowIdx][colIdx] & kSpanned)
|
||||
continue;
|
||||
|
||||
is(acc.isCellSelected(rowIdx, colIdx), aCellsArray[rowIdx][colIdx],
|
||||
var isSelected = aCellsArray[rowIdx][colIdx] == true;
|
||||
is(acc.isCellSelected(rowIdx, colIdx), isSelected,
|
||||
msg + "Wrong selection state of cell at " + rowIdx + " row and " +
|
||||
colIdx + " column for " + prettyName(aIdentifier));
|
||||
|
||||
@ -496,7 +499,9 @@ function testTableSelection(aIdentifier, aCellsArray, aMsg)
|
||||
|
||||
var cell = acc.getCellAt(rowIdx, colIdx);
|
||||
var isSel = aCellsArray[rowIdx][colIdx];
|
||||
if (isSel)
|
||||
if (isSel == undefined)
|
||||
testStates(cell, 0, 0, STATE_SELECTABLE | STATE_SELECTED);
|
||||
else if (isSel == true)
|
||||
testStates(cell, STATE_SELECTED);
|
||||
else
|
||||
testStates(cell, STATE_SELECTABLE, 0, STATE_SELECTED);
|
||||
|
@ -54,6 +54,21 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=410052
|
||||
testUnselectTableColumn("grid2", 0, cellsArray);
|
||||
testUnselectTableRow("grid2", 0, cellsArray);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// ARIA grid (column and row headers)
|
||||
|
||||
cellsArray =
|
||||
[
|
||||
[ undefined, true, false],
|
||||
[ undefined, true, false]
|
||||
];
|
||||
|
||||
testTableSelection("grid3", cellsArray);
|
||||
testSelectTableColumn("grid3", 0, cellsArray);
|
||||
testSelectTableRow("grid3", 0, cellsArray);
|
||||
testUnselectTableColumn("grid3", 0, cellsArray);
|
||||
testUnselectTableRow("grid3", 0, cellsArray);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
@ -65,10 +80,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=410052
|
||||
|
||||
<a target="_blank"
|
||||
title="implement nsIAccessibleTable selection methods for ARIA grids"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=410052">Mozilla Bug 410052</a>
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=410052">Bug 410052</a>
|
||||
<a target="_blank"
|
||||
title="nsHTMLTableCellAccessible is used in dojo's crazy ARIA grid"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=513848">Mozilla Bug 513848</a>
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=513848">Bug 513848</a>
|
||||
<a target="_blank"
|
||||
title="ARIA columnheader/rowheader shouldn't be selectable by default"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=888247">Bug 888247</a>
|
||||
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
@ -112,8 +130,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=410052
|
||||
<div role="row">
|
||||
<table role="presentation">
|
||||
<tr>
|
||||
<td role="columnheader">header1</td>
|
||||
<td role="columnheader">header2</td>
|
||||
<td role="columnheader" aria-selected="false">header1</td>
|
||||
<td role="columnheader" aria-selected="false">header2</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
@ -127,5 +145,17 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=410052
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div role="grid" id="grid3">
|
||||
<div role="row">
|
||||
<div role="columnheader" id="colheader_default">col header1</div>
|
||||
<div role="columnheader" id="colheader_selected" aria-selected="true">col header2</div>
|
||||
<div role="columnheader" id="colheader_notselected" aria-selected="false">col header3</div>
|
||||
</div>
|
||||
<div role="row">
|
||||
<div role="rowheader" id="rowheader_default">row header1</div>
|
||||
<div role="rowheader" id="rowheader_selected" aria-selected="true">row header2</div>
|
||||
<div role="rowheader" id="rowheader_notselected" aria-selected="false">row header3</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -6,7 +6,6 @@ const BOUNDARY_WORD_START = nsIAccessibleText.BOUNDARY_WORD_START;
|
||||
const BOUNDARY_WORD_END = nsIAccessibleText.BOUNDARY_WORD_END;
|
||||
const BOUNDARY_LINE_START = nsIAccessibleText.BOUNDARY_LINE_START;
|
||||
const BOUNDARY_LINE_END = nsIAccessibleText.BOUNDARY_LINE_END;
|
||||
const BOUNDARY_ATTRIBUTE_RANGE = nsIAccessibleText.BOUNDARY_ATTRIBUTE_RANGE;
|
||||
|
||||
const kTextEndOffset = nsIAccessibleText.TEXT_OFFSET_END_OF_TEXT;
|
||||
const kCaretOffset = nsIAccessibleText.TEXT_OFFSET_CARET;
|
||||
@ -585,7 +584,5 @@ function boundaryToString(aBoundaryType)
|
||||
return "line start";
|
||||
case BOUNDARY_LINE_END:
|
||||
return "line end";
|
||||
case BOUNDARY_ATTRIBUTE_RANGE:
|
||||
return "attr range";
|
||||
}
|
||||
}
|
||||
|
@ -151,6 +151,26 @@
|
||||
|
||||
testAccessibleTree("crazy_grid4", accTree);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// grids that could contain whitespace accessibles but shouldn't.
|
||||
|
||||
var accTree =
|
||||
{ TREE_TABLE: [
|
||||
{ ROW: [
|
||||
{ GRID_CELL: [
|
||||
{ TEXT_LEAF: [ ] }
|
||||
] },
|
||||
{ GRID_CELL: [
|
||||
{ TEXT_LEAF: [ ] }
|
||||
] },
|
||||
{ GRID_CELL: [
|
||||
{ TEXT_LEAF: [ ] }
|
||||
] }
|
||||
] },
|
||||
] };
|
||||
|
||||
testAccessibleTree("whitespaces-grid", accTree);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
@ -227,5 +247,13 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div role="treegrid" id="whitespaces-grid">
|
||||
<div role="row" aria-selected="false" tabindex="-1">
|
||||
<span role="gridcell">03:30PM-04:30PM</span>
|
||||
<span role="gridcell" style="font-weight:bold;">test</span>
|
||||
<span role="gridcell">a user1</span>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -421,7 +421,6 @@ pref("services.push.udp.port", 2442);
|
||||
// NetworkStats
|
||||
#ifdef MOZ_B2G_RIL
|
||||
pref("dom.mozNetworkStats.enabled", true);
|
||||
pref("ril.lastKnownMcc", "724");
|
||||
pref("ril.cellbroadcast.disabled", false);
|
||||
#endif
|
||||
|
||||
|
@ -62,43 +62,6 @@ var SettingsListener = {
|
||||
|
||||
SettingsListener.init();
|
||||
|
||||
// =================== Audio ====================
|
||||
SettingsListener.observe('audio.volume.master', 1.0, function(value) {
|
||||
let audioManager = Services.audioManager;
|
||||
if (!audioManager)
|
||||
return;
|
||||
|
||||
audioManager.masterVolume = Math.max(0.0, Math.min(value, 1.0));
|
||||
});
|
||||
|
||||
let audioChannelSettings = [];
|
||||
|
||||
if ("nsIAudioManager" in Ci) {
|
||||
const nsIAudioManager = Ci.nsIAudioManager;
|
||||
audioChannelSettings = [
|
||||
// settings name, max value, apply to stream types
|
||||
['audio.volume.content', 15, [nsIAudioManager.STREAM_TYPE_SYSTEM, nsIAudioManager.STREAM_TYPE_MUSIC]],
|
||||
['audio.volume.notification', 15, [nsIAudioManager.STREAM_TYPE_RING, nsIAudioManager.STREAM_TYPE_NOTIFICATION]],
|
||||
['audio.volume.alarm', 15, [nsIAudioManager.STREAM_TYPE_ALARM]],
|
||||
['audio.volume.telephony', 5, [nsIAudioManager.STREAM_TYPE_VOICE_CALL]],
|
||||
['audio.volume.bt_sco', 15, [nsIAudioManager.STREAM_TYPE_BLUETOOTH_SCO]],
|
||||
];
|
||||
}
|
||||
|
||||
for each (let [setting, maxValue, streamTypes] in audioChannelSettings) {
|
||||
(function AudioStreamSettings(setting, maxValue, streamTypes) {
|
||||
SettingsListener.observe(setting, maxValue, function(value) {
|
||||
let audioManager = Services.audioManager;
|
||||
if (!audioManager)
|
||||
return;
|
||||
|
||||
for each(let streamType in streamTypes) {
|
||||
audioManager.setStreamVolumeIndex(streamType, Math.min(value, maxValue));
|
||||
}
|
||||
});
|
||||
})(setting, maxValue, streamTypes);
|
||||
}
|
||||
|
||||
// =================== Console ======================
|
||||
|
||||
SettingsListener.observe('debug.console.enabled', true, function(value) {
|
||||
|
@ -39,16 +39,6 @@ XPCOMUtils.defineLazyServiceGetter(this, 'gSystemMessenger',
|
||||
'@mozilla.org/system-message-internal;1',
|
||||
'nsISystemMessagesInternal');
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
XPCOMUtils.defineLazyServiceGetter(Services, 'audioManager',
|
||||
'@mozilla.org/telephony/audiomanager;1',
|
||||
'nsIAudioManager');
|
||||
#else
|
||||
Services.audioManager = {
|
||||
'masterVolume': 0
|
||||
};
|
||||
#endif
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(Services, 'fm',
|
||||
'@mozilla.org/focus-manager;1',
|
||||
'nsIFocusManager');
|
||||
@ -344,9 +334,6 @@ var shell = {
|
||||
this.timer = null;
|
||||
}
|
||||
|
||||
#ifndef MOZ_WIDGET_GONK
|
||||
delete Services.audioManager;
|
||||
#endif
|
||||
UserAgentOverrides.uninit();
|
||||
IndexedDBPromptHelper.uninit();
|
||||
},
|
||||
|
@ -1,12 +0,0 @@
|
||||
# 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/.
|
||||
|
||||
DEPTH = @DEPTH@
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
@ -1,4 +1,4 @@
|
||||
{
|
||||
"revision": "34a53279dad496e201616f5e782bd58ef6d38ae5",
|
||||
"revision": "e04bb3527c33dd6771e63397a3b52a4b9a5fce4e",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
. "$topsrcdir/b2g/config/mozconfigs/common"
|
||||
. "$topsrcdir/build/unix/mozconfig.linux32"
|
||||
|
||||
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
|
||||
ac_add_options --enable-update-packaging
|
||||
@ -8,9 +9,6 @@ ac_add_options --enable-signmar
|
||||
# Nightlies only since this has a cost in performance
|
||||
#ac_add_options --enable-js-diagnostics
|
||||
|
||||
# Avoid dependency on libstdc++ 4.5
|
||||
ac_add_options --enable-stdcxx-compat
|
||||
|
||||
# This will overwrite the default of stripping everything and keep the symbol table.
|
||||
# This is useful for profiling and debugging and only increases the package size
|
||||
# by 2 MBs.
|
||||
|
@ -1,4 +1,5 @@
|
||||
. "$topsrcdir/b2g/config/mozconfigs/common"
|
||||
. "$topsrcdir/build/unix/mozconfig.linux"
|
||||
|
||||
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
|
||||
ac_add_options --enable-update-packaging
|
||||
@ -8,9 +9,6 @@ ac_add_options --enable-signmar
|
||||
# Nightlies only since this has a cost in performance
|
||||
#ac_add_options --enable-js-diagnostics
|
||||
|
||||
# Avoid dependency on libstdc++ 4.5
|
||||
ac_add_options --enable-stdcxx-compat
|
||||
|
||||
# This will overwrite the default of stripping everything and keep the symbol table.
|
||||
# This is useful for profiling and debugging and only increases the package size
|
||||
# by 2 MBs.
|
||||
|
@ -175,7 +175,6 @@
|
||||
#ifdef MOZ_B2G_FM
|
||||
@BINPATH@/components/dom_fm.xpt
|
||||
#endif
|
||||
@BINPATH@/components/dom_battery.xpt
|
||||
#ifdef MOZ_B2G_BT
|
||||
@BINPATH@/components/dom_bluetooth.xpt
|
||||
#endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0"?>
|
||||
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1373408730000">
|
||||
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1374187152000">
|
||||
<emItems>
|
||||
<emItem blockID="i350" id="sqlmoz@facebook.com">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3">
|
||||
@ -1052,6 +1052,9 @@
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</pluginItem>
|
||||
<pluginItem blockID="p428">
|
||||
<match name="filename" exp="np[dD]eployJava1\.dll" /> <versionRange severity="0" vulnerabilitystatus="2"></versionRange>
|
||||
</pluginItem>
|
||||
</pluginItems>
|
||||
|
||||
<gfxItems>
|
||||
|
@ -16,20 +16,22 @@ function init(aEvent)
|
||||
var distroId = Services.prefs.getCharPref("distribution.id");
|
||||
if (distroId) {
|
||||
var distroVersion = Services.prefs.getCharPref("distribution.version");
|
||||
var distroAbout = Services.prefs.getComplexValue("distribution.about",
|
||||
Components.interfaces.nsISupportsString);
|
||||
|
||||
var distroField = document.getElementById("distribution");
|
||||
distroField.value = distroAbout;
|
||||
distroField.style.display = "block";
|
||||
|
||||
var distroIdField = document.getElementById("distributionId");
|
||||
distroIdField.value = distroId + " - " + distroVersion;
|
||||
distroIdField.style.display = "block";
|
||||
|
||||
// This must be set last because it might not exist due to bug 895473.
|
||||
var distroAbout = Services.prefs.getComplexValue("distribution.about",
|
||||
Components.interfaces.nsISupportsString);
|
||||
var distroField = document.getElementById("distribution");
|
||||
distroField.value = distroAbout;
|
||||
distroField.style.display = "block";
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
// Pref is unset
|
||||
Components.utils.reportError(e);
|
||||
}
|
||||
|
||||
// Include the build ID and display warning if this is an "a#" (nightly or aurora) build
|
||||
|
@ -571,7 +571,7 @@ HistoryMenu.prototype = {
|
||||
m.setAttribute("label", strings.getString("menuRestoreAllTabs.label"));
|
||||
m.addEventListener("command", function() {
|
||||
for (var i = 0; i < undoItems.length; i++)
|
||||
undoCloseTab();
|
||||
undoCloseTab(0);
|
||||
}, false);
|
||||
},
|
||||
|
||||
|
@ -217,14 +217,21 @@ var gPluginHandler = {
|
||||
},
|
||||
|
||||
handleEvent : function(event) {
|
||||
let plugin = event.target;
|
||||
let doc = plugin.ownerDocument;
|
||||
|
||||
// We're expecting the target to be a plugin.
|
||||
if (!(plugin instanceof Ci.nsIObjectLoadingContent))
|
||||
return;
|
||||
let plugin;
|
||||
let doc;
|
||||
|
||||
let eventType = event.type;
|
||||
if (eventType === "PluginRemoved") {
|
||||
doc = event.target;
|
||||
}
|
||||
else {
|
||||
plugin = event.target;
|
||||
doc = plugin.ownerDocument;
|
||||
|
||||
if (!(plugin instanceof Ci.nsIObjectLoadingContent))
|
||||
return;
|
||||
}
|
||||
|
||||
if (eventType == "PluginBindingAttached") {
|
||||
// The plugin binding fires this event when it is created.
|
||||
// As an untrusted event, ensure that this object actually has a binding
|
||||
@ -243,6 +250,7 @@ var gPluginHandler = {
|
||||
}
|
||||
}
|
||||
|
||||
let shouldShowNotification = false;
|
||||
let browser = gBrowser.getBrowserForDocument(doc.defaultView.top.document);
|
||||
|
||||
switch (eventType) {
|
||||
@ -268,7 +276,7 @@ var gPluginHandler = {
|
||||
|
||||
case "PluginBlocklisted":
|
||||
case "PluginOutdated":
|
||||
this._showClickToPlayNotification(browser);
|
||||
shouldShowNotification = true;
|
||||
break;
|
||||
|
||||
case "PluginVulnerableUpdatable":
|
||||
@ -290,7 +298,7 @@ var gPluginHandler = {
|
||||
let vulnerabilityText = doc.getAnonymousElementByAttribute(plugin, "anonid", "vulnerabilityStatus");
|
||||
vulnerabilityText.textContent = vulnerabilityString;
|
||||
}
|
||||
this._showClickToPlayNotification(browser);
|
||||
shouldShowNotification = true;
|
||||
break;
|
||||
|
||||
case "PluginPlayPreview":
|
||||
@ -300,20 +308,27 @@ var gPluginHandler = {
|
||||
case "PluginDisabled":
|
||||
let manageLink = doc.getAnonymousElementByAttribute(plugin, "class", "managePluginsLink");
|
||||
this.addLinkClickCallback(manageLink, "managePlugins");
|
||||
this._showClickToPlayNotification(browser);
|
||||
shouldShowNotification = true;
|
||||
break;
|
||||
|
||||
case "PluginInstantiated":
|
||||
this._showClickToPlayNotification(browser);
|
||||
case "PluginRemoved":
|
||||
shouldShowNotification = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Hide the in-content UI if it's too big. The crashed plugin handler already did this.
|
||||
if (eventType != "PluginCrashed") {
|
||||
if (eventType != "PluginCrashed" && eventType != "PluginRemoved") {
|
||||
let overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
|
||||
if (overlay != null && this.isTooSmall(plugin, overlay))
|
||||
overlay.style.visibility = "hidden";
|
||||
}
|
||||
|
||||
// Only show the notification after we've done the isTooSmall check, so
|
||||
// that the notification can decide whether to show the "alert" icon
|
||||
if (shouldShowNotification) {
|
||||
this._showClickToPlayNotification(browser);
|
||||
}
|
||||
},
|
||||
|
||||
isKnownPlugin: function PH_isKnownPlugin(objLoadingContent) {
|
||||
@ -686,18 +701,12 @@ var gPluginHandler = {
|
||||
|
||||
switch (aNewState) {
|
||||
case "allownow":
|
||||
if (aPluginInfo.fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE) {
|
||||
return;
|
||||
}
|
||||
permission = Ci.nsIPermissionManager.ALLOW_ACTION;
|
||||
expireType = Ci.nsIPermissionManager.EXPIRE_SESSION;
|
||||
expireTime = Date.now() + Services.prefs.getIntPref(this.PREF_SESSION_PERSIST_MINUTES) * 60 * 1000;
|
||||
break;
|
||||
|
||||
case "allowalways":
|
||||
if (aPluginInfo.fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE) {
|
||||
return;
|
||||
}
|
||||
permission = Ci.nsIPermissionManager.ALLOW_ACTION;
|
||||
expireType = Ci.nsIPermissionManager.EXPIRE_TIME;
|
||||
expireTime = Date.now() +
|
||||
@ -705,25 +714,28 @@ var gPluginHandler = {
|
||||
break;
|
||||
|
||||
case "block":
|
||||
if (aPluginInfo.fallbackType != Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE) {
|
||||
return;
|
||||
}
|
||||
permission = Ci.nsIPermissionManager.PROMPT_ACTION;
|
||||
expireType = Ci.nsIPermissionManager.EXPIRE_NEVER;
|
||||
expireTime = 0;
|
||||
break;
|
||||
|
||||
// In case a plugin has already been allowed in another tab, the "continue allowing" button
|
||||
// shouldn't change any permissions but should run the plugin-enablement code below.
|
||||
case "continue":
|
||||
break;
|
||||
default:
|
||||
Cu.reportError(Error("Unexpected plugin state: " + aNewState));
|
||||
return;
|
||||
}
|
||||
|
||||
let browser = aNotification.browser;
|
||||
Services.perms.add(browser.currentURI, aPluginInfo.permissionString,
|
||||
permission, expireType, expireTime);
|
||||
if (aNewState != "continue") {
|
||||
Services.perms.add(browser.currentURI, aPluginInfo.permissionString,
|
||||
permission, expireType, expireTime);
|
||||
|
||||
if (aNewState == "block") {
|
||||
return;
|
||||
if (aNewState == "block") {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Manually activate the plugins that would have been automatically
|
||||
@ -749,6 +761,7 @@ var gPluginHandler = {
|
||||
let notification = PopupNotifications.getNotification("click-to-play-plugins", aBrowser);
|
||||
|
||||
let contentWindow = aBrowser.contentWindow;
|
||||
let contentDoc = aBrowser.contentDocument;
|
||||
let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
let plugins = cwu.plugins;
|
||||
@ -759,15 +772,25 @@ var gPluginHandler = {
|
||||
return;
|
||||
}
|
||||
|
||||
let haveVulnerablePlugin = plugins.some(function(plugin) {
|
||||
let icon = 'plugins-notification-icon';
|
||||
for (let plugin of plugins) {
|
||||
let fallbackType = plugin.pluginFallbackType;
|
||||
return fallbackType == plugin.PLUGIN_VULNERABLE_UPDATABLE ||
|
||||
fallbackType == plugin.PLUGIN_VULNERABLE_NO_UPDATE ||
|
||||
fallbackType == plugin.PLUGIN_BLOCKLISTED;
|
||||
});
|
||||
if (fallbackType == plugin.PLUGIN_VULNERABLE_UPDATABLE ||
|
||||
fallbackType == plugin.PLUGIN_VULNERABLE_NO_UPDATE ||
|
||||
fallbackType == plugin.PLUGIN_BLOCKLISTED) {
|
||||
icon = 'blocked-plugins-notification-icon';
|
||||
break;
|
||||
}
|
||||
if (fallbackType == plugin.PLUGIN_CLICK_TO_PLAY) {
|
||||
let overlay = contentDoc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
|
||||
if (!overlay || overlay.style.visibility == 'hidden') {
|
||||
icon = 'alert-plugins-notification-icon';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let dismissed = notification ? notification.dismissed : true;
|
||||
// Always show the doorhanger if the anchor is not available.
|
||||
if (!isElementVisible(gURLBar) || aPrimaryPlugin)
|
||||
if (aPrimaryPlugin)
|
||||
dismissed = false;
|
||||
|
||||
let primaryPluginPermission = null;
|
||||
@ -780,7 +803,6 @@ var gPluginHandler = {
|
||||
eventCallback: this._clickToPlayNotificationEventCallback,
|
||||
primaryPlugin: primaryPluginPermission
|
||||
};
|
||||
let icon = haveVulnerablePlugin ? "blocked-plugins-notification-icon" : "plugins-notification-icon";
|
||||
PopupNotifications.show(aBrowser, "click-to-play-plugins",
|
||||
"", icon,
|
||||
null, null, options);
|
||||
|
@ -755,6 +755,7 @@ var gBrowserInit = {
|
||||
gBrowser.addEventListener("PluginCrashed", gPluginHandler, true);
|
||||
gBrowser.addEventListener("PluginOutdated", gPluginHandler, true);
|
||||
gBrowser.addEventListener("PluginInstantiated", gPluginHandler, true);
|
||||
gBrowser.addEventListener("PluginRemoved", gPluginHandler, true);
|
||||
|
||||
gBrowser.addEventListener("NewPluginInstalled", gPluginHandler.newPluginInstalled, true);
|
||||
|
||||
@ -823,7 +824,8 @@ var gBrowserInit = {
|
||||
// setup history swipe animation
|
||||
gHistorySwipeAnimation.init();
|
||||
|
||||
if (window.opener && !window.opener.closed) {
|
||||
if (window.opener && !window.opener.closed &&
|
||||
PrivateBrowsingUtils.isWindowPrivate(window) == PrivateBrowsingUtils.isWindowPrivate(window.opener)) {
|
||||
let openerSidebarBox = window.opener.document.getElementById("sidebar-box");
|
||||
// If the opener had a sidebar, open the same sidebar in our window.
|
||||
// The opener can be the hidden window too, if we're coming from the state
|
||||
@ -2305,11 +2307,11 @@ function BrowserOnAboutPageLoad(doc) {
|
||||
}
|
||||
docElt.setAttribute("snippetsVersion", AboutHomeUtils.snippetsVersion);
|
||||
|
||||
function updateSearchEngine() {
|
||||
let updateSearchEngine = function() {
|
||||
let engine = AboutHomeUtils.defaultSearchEngine;
|
||||
docElt.setAttribute("searchEngineName", engine.name);
|
||||
docElt.setAttribute("searchEngineURL", engine.searchURL);
|
||||
}
|
||||
};
|
||||
updateSearchEngine();
|
||||
|
||||
// Listen for the event that's triggered when the user changes search engine.
|
||||
@ -4432,6 +4434,10 @@ nsBrowserAccess.prototype = {
|
||||
|
||||
isTabContentWindow: function (aWindow) {
|
||||
return gBrowser.browsers.some(function (browser) browser.contentWindow == aWindow);
|
||||
},
|
||||
|
||||
get contentWindow() {
|
||||
return gBrowser.contentWindow;
|
||||
}
|
||||
}
|
||||
|
||||
@ -6259,15 +6265,31 @@ function undoCloseTab(aIndex) {
|
||||
var tab = null;
|
||||
var ss = Cc["@mozilla.org/browser/sessionstore;1"].
|
||||
getService(Ci.nsISessionStore);
|
||||
if (ss.getClosedTabCount(window) > (aIndex || 0)) {
|
||||
TabView.prepareUndoCloseTab(blankTabToRemove);
|
||||
tab = ss.undoCloseTab(window, aIndex || 0);
|
||||
TabView.afterUndoCloseTab();
|
||||
|
||||
if (blankTabToRemove)
|
||||
gBrowser.removeTab(blankTabToRemove);
|
||||
let numberOfTabsToUndoClose = 0;
|
||||
if (Number.isInteger(aIndex)) {
|
||||
if (ss.getClosedTabCount(window) > aIndex) {
|
||||
numberOfTabsToUndoClose = 1;
|
||||
} else {
|
||||
return tab;
|
||||
}
|
||||
} else {
|
||||
numberOfTabsToUndoClose = ss.getNumberOfTabsClosedLast(window);
|
||||
aIndex = 0;
|
||||
}
|
||||
|
||||
while (numberOfTabsToUndoClose > 0 &&
|
||||
numberOfTabsToUndoClose--) {
|
||||
TabView.prepareUndoCloseTab(blankTabToRemove);
|
||||
tab = ss.undoCloseTab(window, aIndex);
|
||||
TabView.afterUndoCloseTab();
|
||||
if (blankTabToRemove) {
|
||||
gBrowser.removeTab(blankTabToRemove);
|
||||
blankTabToRemove = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the number of tabs closed last time to the default.
|
||||
ss.setNumberOfTabsClosedLast(window, 1);
|
||||
return tab;
|
||||
}
|
||||
|
||||
@ -7061,10 +7083,15 @@ var TabContextMenu = {
|
||||
menuItem.disabled = disabled;
|
||||
|
||||
// Session store
|
||||
document.getElementById("context_undoCloseTab").disabled =
|
||||
Cc["@mozilla.org/browser/sessionstore;1"].
|
||||
getService(Ci.nsISessionStore).
|
||||
getClosedTabCount(window) == 0;
|
||||
let ss = Cc["@mozilla.org/browser/sessionstore;1"].
|
||||
getService(Ci.nsISessionStore);
|
||||
let undoCloseTabElement = document.getElementById("context_undoCloseTab");
|
||||
let closedTabCount = ss.getNumberOfTabsClosedLast(window);
|
||||
undoCloseTabElement.disabled = closedTabCount == 0;
|
||||
// Change the label of "Undo Close Tab" to specify if it will undo a batch-close
|
||||
// or a single close.
|
||||
let visibleLabel = closedTabCount <= 1 ? "singletablabel" : "multipletablabel";
|
||||
undoCloseTabElement.setAttribute("label", undoCloseTabElement.getAttribute(visibleLabel));
|
||||
|
||||
// Only one of pin/unpin should be visible
|
||||
document.getElementById("context_pinTab").hidden = this.contextTab.pinned;
|
||||
|
@ -103,7 +103,8 @@
|
||||
oncommand="gBrowser.removeAllTabsBut(TabContextMenu.contextTab);"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="context_undoCloseTab"
|
||||
label="&undoCloseTab.label;"
|
||||
singletablabel="&undoCloseTab.label;"
|
||||
multipletablabel="&undoCloseTabs.label;"
|
||||
accesskey="&undoCloseTab.accesskey;"
|
||||
observes="History:UndoCloseTab"/>
|
||||
<menuitem id="context_closeTab" label="&closeTab.label;" accesskey="&closeTab.accesskey;"
|
||||
@ -504,6 +505,7 @@
|
||||
<image id="webapps-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
<image id="plugins-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
<image id="web-notifications-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
<image id="alert-plugins-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
<image id="blocked-plugins-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
<image id="plugin-install-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
<image id="mixed-content-blocked-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
|
@ -150,7 +150,7 @@ function onCheckboxClick(aPartId)
|
||||
var command = document.getElementById("cmd_" + aPartId + "Toggle");
|
||||
var checkbox = document.getElementById(aPartId + "Def");
|
||||
if (checkbox.checked) {
|
||||
SitePermissions.remove(gPermURI.host, aPartId);
|
||||
SitePermissions.remove(gPermURI, aPartId);
|
||||
command.setAttribute("disabled", "true");
|
||||
var perm = SitePermissions.getDefault(aPartId);
|
||||
setRadioState(aPartId, perm);
|
||||
|
@ -1565,13 +1565,9 @@
|
||||
throw new Error("Invalid argument: " + aCloseTabs);
|
||||
}
|
||||
|
||||
if (tabsToClose <= 1)
|
||||
return true;
|
||||
|
||||
const pref = aCloseTabs == this.closingTabsEnum.ALL ?
|
||||
"browser.tabs.warnOnClose" : "browser.tabs.warnOnCloseOtherTabs";
|
||||
var shouldPrompt = Services.prefs.getBoolPref(pref);
|
||||
if (!shouldPrompt)
|
||||
if (tabsToClose <= 1 ||
|
||||
aCloseTabs != this.closingTabsEnum.ALL ||
|
||||
!Services.prefs.getBoolPref("browser.tabs.warnOnClose"))
|
||||
return true;
|
||||
|
||||
var ps = Services.prompt;
|
||||
@ -1595,13 +1591,12 @@
|
||||
+ (ps.BUTTON_TITLE_CANCEL * ps.BUTTON_POS_1),
|
||||
bundle.getString("tabs.closeButtonMultiple"),
|
||||
null, null,
|
||||
aCloseTabs == this.closingTabsEnum.ALL ?
|
||||
bundle.getString("tabs.closeWarningPromptMe") : null,
|
||||
bundle.getString("tabs.closeWarningPromptMe"),
|
||||
warnOnClose);
|
||||
var reallyClose = (buttonPressed == 0);
|
||||
|
||||
// don't set the pref unless they press OK and it's false
|
||||
if (aCloseTabs == this.closingTabsEnum.ALL && reallyClose && !warnOnClose.value)
|
||||
if (reallyClose && !warnOnClose.value)
|
||||
Services.prefs.setBoolPref(pref, false);
|
||||
|
||||
return reallyClose;
|
||||
@ -1629,9 +1624,13 @@
|
||||
<![CDATA[
|
||||
if (this.warnAboutClosingTabs(this.closingTabsEnum.TO_END, aTab)) {
|
||||
let tabs = this.getTabsToTheEndFrom(aTab);
|
||||
for (let i = tabs.length - 1; i >= 0; --i) {
|
||||
let numberOfTabsToClose = tabs.length;
|
||||
for (let i = numberOfTabsToClose - 1; i >= 0; --i) {
|
||||
this.removeTab(tabs[i], {animate: true});
|
||||
}
|
||||
let ss = Cc["@mozilla.org/browser/sessionstore;1"].
|
||||
getService(Ci.nsISessionStore);
|
||||
ss.setNumberOfTabsClosedLast(window, numberOfTabsToClose);
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
@ -1648,10 +1647,16 @@
|
||||
let tabs = this.visibleTabs;
|
||||
this.selectedTab = aTab;
|
||||
|
||||
let closedTabs = 0;
|
||||
for (let i = tabs.length - 1; i >= 0; --i) {
|
||||
if (tabs[i] != aTab && !tabs[i].pinned)
|
||||
if (tabs[i] != aTab && !tabs[i].pinned) {
|
||||
this.removeTab(tabs[i]);
|
||||
closedTabs++;
|
||||
}
|
||||
}
|
||||
let ss = Cc["@mozilla.org/browser/sessionstore;1"].
|
||||
getService(Ci.nsISessionStore);
|
||||
ss.setNumberOfTabsClosedLast(window, closedTabs);
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
@ -1680,6 +1685,10 @@
|
||||
var byMouse = aParams.byMouse;
|
||||
}
|
||||
|
||||
let ss = Cc["@mozilla.org/browser/sessionstore;1"].
|
||||
getService(Ci.nsISessionStore);
|
||||
ss.setNumberOfTabsClosedLast(window, 1);
|
||||
|
||||
// Handle requests for synchronously removing an already
|
||||
// asynchronously closing tab.
|
||||
if (!animate &&
|
||||
@ -2089,8 +2098,9 @@
|
||||
if (otherFindBar &&
|
||||
otherFindBar.findMode == otherFindBar.FIND_NORMAL) {
|
||||
let ourFindBar = this.getFindBar(aOurTab);
|
||||
ourFindBar.hidden = otherFindBar.hidden;
|
||||
ourFindBar._findField.value = otherFindBar._findField.value;
|
||||
if (!otherFindBar.hidden)
|
||||
ourFindBar.onFindCommand();
|
||||
}
|
||||
|
||||
// Finish tearing down the tab that's going away.
|
||||
|
@ -184,6 +184,7 @@ MOCHITEST_BROWSER_FILES = \
|
||||
browser_bug832435.js \
|
||||
browser_bug839103.js \
|
||||
browser_bug882977.js \
|
||||
browser_bug887515.js \
|
||||
browser_canonizeURL.js \
|
||||
browser_clearplugindata_noage.html \
|
||||
browser_clearplugindata.html \
|
||||
|
@ -111,8 +111,6 @@ let gTests = [
|
||||
doc.addEventListener("AboutHomeSearchEvent", function onSearch(e) {
|
||||
is(e.detail, engineName, "Detail is search engine name");
|
||||
|
||||
gBrowser.stop();
|
||||
|
||||
getNumberOfSearches(engineName).then(num => {
|
||||
is(num, numSearchesBefore + 1, "One more search recorded.");
|
||||
deferred.resolve();
|
||||
@ -126,6 +124,7 @@ let gTests = [
|
||||
info("Perform a search.");
|
||||
doc.getElementById("searchText").value = "a search";
|
||||
doc.getElementById("searchSubmit").click();
|
||||
gBrowser.stop();
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
|
@ -98,6 +98,8 @@ function checkNewWindow() {
|
||||
ok(!newWindow.gFindBar.hidden, "New window shows find bar!");
|
||||
is(newWindow.gFindBar._findField.value, texts[1],
|
||||
"New window find bar has correct find value!");
|
||||
ok(!newWindow.gFindBar.getElement("find-next").disabled,
|
||||
"New window findbar has enabled buttons!");
|
||||
newWindow.close();
|
||||
finish();
|
||||
}
|
||||
|
75
browser/base/content/test/browser_bug887515.js
Normal file
75
browser/base/content/test/browser_bug887515.js
Normal file
@ -0,0 +1,75 @@
|
||||
function numClosedTabs()
|
||||
Cc["@mozilla.org/browser/sessionstore;1"].
|
||||
getService(Ci.nsISessionStore).
|
||||
getNumberOfTabsClosedLast(window);
|
||||
|
||||
var originalTab;
|
||||
var tab1Loaded = false;
|
||||
var tab2Loaded = false;
|
||||
|
||||
function verifyUndoMultipleClose() {
|
||||
if (!tab1Loaded || !tab2Loaded)
|
||||
return;
|
||||
|
||||
gBrowser.removeAllTabsBut(originalTab);
|
||||
updateTabContextMenu();
|
||||
let undoCloseTabElement = document.getElementById("context_undoCloseTab");
|
||||
ok(!undoCloseTabElement.disabled, "Undo Close Tabs should be enabled.");
|
||||
is(numClosedTabs(), 2, "There should be 2 closed tabs.");
|
||||
is(gBrowser.tabs.length, 1, "There should only be 1 open tab");
|
||||
updateTabContextMenu();
|
||||
is(undoCloseTabElement.label, undoCloseTabElement.getAttribute("multipletablabel"),
|
||||
"The label should be showing that the command will restore multiple tabs");
|
||||
undoCloseTab();
|
||||
|
||||
is(gBrowser.tabs.length, 3, "There should be 3 open tabs");
|
||||
updateTabContextMenu();
|
||||
is(undoCloseTabElement.label, undoCloseTabElement.getAttribute("singletablabel"),
|
||||
"The label should be showing that the command will restore a single tab");
|
||||
|
||||
gBrowser.removeTabsToTheEndFrom(originalTab);
|
||||
updateTabContextMenu();
|
||||
ok(!undoCloseTabElement.disabled, "Undo Close Tabs should be enabled.");
|
||||
is(numClosedTabs(), 2, "There should be 2 closed tabs.");
|
||||
is(gBrowser.tabs.length, 1, "There should only be 1 open tab");
|
||||
updateTabContextMenu();
|
||||
is(undoCloseTabElement.label, undoCloseTabElement.getAttribute("multipletablabel"),
|
||||
"The label should be showing that the command will restore multiple tabs");
|
||||
|
||||
finish();
|
||||
}
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
originalTab.linkedBrowser.loadURI("about:blank");
|
||||
originalTab = null;
|
||||
});
|
||||
|
||||
let undoCloseTabElement = document.getElementById("context_undoCloseTab");
|
||||
updateTabContextMenu();
|
||||
is(undoCloseTabElement.label, undoCloseTabElement.getAttribute("singletablabel"),
|
||||
"The label should be showing that the command will restore a single tab");
|
||||
|
||||
originalTab = gBrowser.selectedTab;
|
||||
gBrowser.selectedBrowser.loadURI("http://mochi.test:8888/");
|
||||
var tab1 = gBrowser.addTab("http://mochi.test:8888/");
|
||||
var tab2 = gBrowser.addTab("http://mochi.test:8888/");
|
||||
var browser1 = gBrowser.getBrowserForTab(tab1);
|
||||
browser1.addEventListener("load", function onLoad1() {
|
||||
browser1.removeEventListener("load", onLoad1, true);
|
||||
tab1Loaded = true;
|
||||
tab1 = null;
|
||||
|
||||
verifyUndoMultipleClose();
|
||||
}, true);
|
||||
var browser2 = gBrowser.getBrowserForTab(tab2);
|
||||
browser2.addEventListener("load", function onLoad2() {
|
||||
browser2.removeEventListener("load", onLoad2, true);
|
||||
tab2Loaded = true;
|
||||
tab2 = null;
|
||||
|
||||
verifyUndoMultipleClose();
|
||||
}, true);
|
||||
}
|
@ -1574,12 +1574,19 @@
|
||||
this.appendChild(item);
|
||||
this._items.push(item);
|
||||
}
|
||||
if (this.notification.options.centerActions.length == 1) {
|
||||
this._setState(this._states.SINGLE);
|
||||
} else if (this.notification.options.primaryPlugin) {
|
||||
this._setState(this._states.MULTI_COLLAPSED);
|
||||
} else {
|
||||
this._setState(this._states.MULTI_EXPANDED);
|
||||
switch (this.notification.options.centerActions.length) {
|
||||
case 0:
|
||||
PopupNotifications._dismiss();
|
||||
break;
|
||||
case 1:
|
||||
this._setState(this._states.SINGLE);
|
||||
break;
|
||||
default:
|
||||
if (this.notification.options.primaryPlugin) {
|
||||
this._setState(this._states.MULTI_COLLAPSED);
|
||||
} else {
|
||||
this._setState(this._states.MULTI_EXPANDED);
|
||||
}
|
||||
}
|
||||
]]></constructor>
|
||||
<method name="_setState">
|
||||
@ -1645,7 +1652,7 @@
|
||||
button2 = {
|
||||
label: "pluginContinue.label",
|
||||
accesskey: "pluginContinue.accesskey",
|
||||
action: "_cancel",
|
||||
action: "_singleContinue",
|
||||
default: true
|
||||
};
|
||||
switch (action.blocklistState) {
|
||||
@ -1819,6 +1826,14 @@
|
||||
this._cancel();
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="_singleContinue">
|
||||
<body><![CDATA[
|
||||
gPluginHandler._updatePluginPermission(this.notification,
|
||||
this.notification.options.centerActions[0],
|
||||
"continue");
|
||||
this._cancel();
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="_multiAccept">
|
||||
<body><![CDATA[
|
||||
for (let item of this._items) {
|
||||
|
@ -1,12 +0,0 @@
|
||||
# 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/.
|
||||
|
||||
DEPTH = @DEPTH@
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
@ -273,13 +273,18 @@ DistributionCustomizer.prototype = {
|
||||
|
||||
let partnerAbout = Cc["@mozilla.org/supports-string;1"].
|
||||
createInstance(Ci.nsISupportsString);
|
||||
if (globalPrefs["about." + this._locale]) {
|
||||
partnerAbout.data = this._ini.getString("Global", "about." + this._locale);
|
||||
} else {
|
||||
partnerAbout.data = this._ini.getString("Global", "about");
|
||||
try {
|
||||
if (globalPrefs["about." + this._locale]) {
|
||||
partnerAbout.data = this._ini.getString("Global", "about." + this._locale);
|
||||
} else {
|
||||
partnerAbout.data = this._ini.getString("Global", "about");
|
||||
}
|
||||
defaults.setComplexValue("distribution.about",
|
||||
Ci.nsISupportsString, partnerAbout);
|
||||
} catch (e) {
|
||||
/* ignore bad prefs due to bug 895473 and move on */
|
||||
Cu.reportError(e);
|
||||
}
|
||||
defaults.setComplexValue("distribution.about",
|
||||
Ci.nsISupportsString, partnerAbout);
|
||||
|
||||
if (sections["Preferences"]) {
|
||||
for (let key in enumerate(this._ini.getKeys("Preferences"))) {
|
||||
|
@ -1,12 +0,0 @@
|
||||
# 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/.
|
||||
|
||||
DEPTH = @DEPTH@
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
@ -45,6 +45,7 @@ MOCHITEST_BROWSER_FILES = \
|
||||
browser_privatebrowsing_popupblocker.js \
|
||||
browser_privatebrowsing_protocolhandler.js \
|
||||
browser_privatebrowsing_protocolhandler_page.html \
|
||||
browser_privatebrowsing_sidebar.js \
|
||||
browser_privatebrowsing_theming.js \
|
||||
browser_privatebrowsing_ui.js \
|
||||
browser_privatebrowsing_urlbarfocus.js \
|
||||
|
@ -0,0 +1,92 @@
|
||||
/* 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/. */
|
||||
|
||||
// This test makes sure that Sidebars do not migrate across windows with
|
||||
// different privacy states
|
||||
|
||||
// See Bug 885054: https://bugzilla.mozilla.org/show_bug.cgi?id=885054
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let { utils: Cu } = Components;
|
||||
|
||||
let { Promise: { defer } } = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||
|
||||
// opens a sidebar
|
||||
function openSidebar(win) {
|
||||
let { promise, resolve } = defer();
|
||||
let doc = win.document;
|
||||
|
||||
let sidebarID = 'viewBookmarksSidebar';
|
||||
|
||||
let sidebar = doc.getElementById('sidebar');
|
||||
|
||||
let sidebarurl = doc.getElementById(sidebarID).getAttribute('sidebarurl');
|
||||
|
||||
sidebar.addEventListener('load', function onSidebarLoad() {
|
||||
if (sidebar.contentWindow.location.href != sidebarurl)
|
||||
return;
|
||||
sidebar.removeEventListener('load', onSidebarLoad, true);
|
||||
|
||||
resolve(win);
|
||||
}, true);
|
||||
|
||||
win.toggleSidebar(sidebarID, true);
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
let windowCache = [];
|
||||
function cacheWindow(w) {
|
||||
windowCache.push(w);
|
||||
return w;
|
||||
}
|
||||
function closeCachedWindows () {
|
||||
windowCache.forEach(function(w) w.close());
|
||||
}
|
||||
|
||||
// Part 1: NON PRIVATE WINDOW -> PRIVATE WINDOW
|
||||
openWindow(window, {}, 1).
|
||||
then(cacheWindow).
|
||||
then(openSidebar).
|
||||
then(function(win) openWindow(win, { private: true })).
|
||||
then(cacheWindow).
|
||||
then(function({ document }) {
|
||||
let sidebarBox = document.getElementById("sidebar-box");
|
||||
is(sidebarBox.hidden, true, 'Opening a private window from reg window does not open the sidebar');
|
||||
}).
|
||||
// Part 2: NON PRIVATE WINDOW -> NON PRIVATE WINDOW
|
||||
then(function() openWindow(window)).
|
||||
then(cacheWindow).
|
||||
then(openSidebar).
|
||||
then(function(win) openWindow(win)).
|
||||
then(cacheWindow).
|
||||
then(function({ document }) {
|
||||
let sidebarBox = document.getElementById("sidebar-box");
|
||||
is(sidebarBox.hidden, false, 'Opening a reg window from reg window does open the sidebar');
|
||||
}).
|
||||
// Part 3: PRIVATE WINDOW -> NON PRIVATE WINDOW
|
||||
then(function() openWindow(window, { private: true })).
|
||||
then(cacheWindow).
|
||||
then(openSidebar).
|
||||
then(function(win) openWindow(win)).
|
||||
then(cacheWindow).
|
||||
then(function({ document }) {
|
||||
let sidebarBox = document.getElementById("sidebar-box");
|
||||
is(sidebarBox.hidden, true, 'Opening a reg window from a private window does not open the sidebar');
|
||||
}).
|
||||
// Part 4: PRIVATE WINDOW -> PRIVATE WINDOW
|
||||
then(function() openWindow(window, { private: true })).
|
||||
then(cacheWindow).
|
||||
then(openSidebar).
|
||||
then(function(win) openWindow(win, { private: true })).
|
||||
then(cacheWindow).
|
||||
then(function({ document }) {
|
||||
let sidebarBox = document.getElementById("sidebar-box");
|
||||
is(sidebarBox.hidden, false, 'Opening a private window from private window does open the sidebar');
|
||||
}).
|
||||
then(closeCachedWindows).
|
||||
then(finish);
|
||||
}
|
@ -31,6 +31,20 @@ function whenNewWindowLoaded(aOptions, aCallback) {
|
||||
return win;
|
||||
}
|
||||
|
||||
function openWindow(aParent, aOptions, a3) {
|
||||
let { Promise: { defer } } = Components.utils.import("resource://gre/modules/Promise.jsm", {});
|
||||
let { promise, resolve } = defer();
|
||||
|
||||
let win = aParent.OpenBrowserWindow(aOptions);
|
||||
|
||||
win.addEventListener("load", function onLoad() {
|
||||
win.removeEventListener("load", onLoad, false);
|
||||
resolve(win);
|
||||
}, false);
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
function newDirectory() {
|
||||
let FileUtils =
|
||||
Cu.import("resource://gre/modules/FileUtils.jsm", {}).FileUtils;
|
||||
@ -62,4 +76,3 @@ function _initTest() {
|
||||
}
|
||||
|
||||
_initTest();
|
||||
|
||||
|
@ -25,7 +25,7 @@ interface nsIDOMNode;
|
||||
* |gBrowser.tabContainer| such as e.g. |gBrowser.selectedTab|.
|
||||
*/
|
||||
|
||||
[scriptable, uuid(59bfaf00-e3d8-4728-b4f0-cc0b9dfb4806)]
|
||||
[scriptable, uuid(0aa5492c-15ad-4376-8eac-28895796826e)]
|
||||
interface nsISessionStore : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -105,6 +105,20 @@ interface nsISessionStore : nsISupports
|
||||
nsIDOMNode duplicateTab(in nsIDOMWindow aWindow, in nsIDOMNode aTab,
|
||||
[optional] in long aDelta);
|
||||
|
||||
/**
|
||||
* Set the number of tabs that was closed during the last close-tabs
|
||||
* operation. This helps us keep track of batch-close operations so
|
||||
* we can restore multiple tabs at once.
|
||||
*/
|
||||
void setNumberOfTabsClosedLast(in nsIDOMWindow aWindow, in unsigned long aNumber);
|
||||
|
||||
/**
|
||||
* Get the number of tabs that was closed during the last close-tabs
|
||||
* operation. This helps us keep track of batch-close operations so
|
||||
* we can restore multiple tabs at once.
|
||||
*/
|
||||
unsigned long getNumberOfTabsClosedLast(in nsIDOMWindow aWindow);
|
||||
|
||||
/**
|
||||
* Get the number of restore-able tabs for a browser window
|
||||
*/
|
||||
|
@ -170,6 +170,14 @@ this.SessionStore = {
|
||||
return SessionStoreInternal.duplicateTab(aWindow, aTab, aDelta);
|
||||
},
|
||||
|
||||
getNumberOfTabsClosedLast: function ss_getNumberOfTabsClosedLast(aWindow) {
|
||||
return SessionStoreInternal.getNumberOfTabsClosedLast(aWindow);
|
||||
},
|
||||
|
||||
setNumberOfTabsClosedLast: function ss_setNumberOfTabsClosedLast(aWindow, aNumber) {
|
||||
return SessionStoreInternal.setNumberOfTabsClosedLast(aWindow, aNumber);
|
||||
},
|
||||
|
||||
getClosedTabCount: function ss_getClosedTabCount(aWindow) {
|
||||
return SessionStoreInternal.getClosedTabCount(aWindow);
|
||||
},
|
||||
@ -1529,6 +1537,28 @@ let SessionStoreInternal = {
|
||||
return newTab;
|
||||
},
|
||||
|
||||
setNumberOfTabsClosedLast: function ssi_setNumberOfTabsClosedLast(aWindow, aNumber) {
|
||||
if ("__SSi" in aWindow) {
|
||||
return NumberOfTabsClosedLastPerWindow.set(aWindow, aNumber);
|
||||
}
|
||||
|
||||
throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
|
||||
},
|
||||
|
||||
/* Used to undo batch tab-close operations. Defaults to 1. */
|
||||
getNumberOfTabsClosedLast: function ssi_getNumberOfTabsClosedLast(aWindow) {
|
||||
if ("__SSi" in aWindow) {
|
||||
// Blank tabs cannot be undo-closed, so the number returned by
|
||||
// the NumberOfTabsClosedLastPerWindow can be greater than the
|
||||
// return value of getClosedTabCount. We won't restore blank
|
||||
// tabs, so we return the minimum of these two values.
|
||||
return Math.min(NumberOfTabsClosedLastPerWindow.get(aWindow) || 1,
|
||||
this.getClosedTabCount(aWindow));
|
||||
}
|
||||
|
||||
throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
|
||||
},
|
||||
|
||||
getClosedTabCount: function ssi_getClosedTabCount(aWindow) {
|
||||
if ("__SSi" in aWindow) {
|
||||
return this._windows[aWindow.__SSi]._closedTabs.length;
|
||||
@ -4694,6 +4724,11 @@ let DyingWindowCache = {
|
||||
}
|
||||
};
|
||||
|
||||
// A map storing the number of tabs last closed per windoow. This only
|
||||
// stores the most recent tab-close operation, and is used to undo
|
||||
// batch tab-closing operations.
|
||||
let NumberOfTabsClosedLastPerWindow = new WeakMap();
|
||||
|
||||
// A set of tab attributes to persist. We will read a given list of tab
|
||||
// attributes when collecting tab data and will re-set those attributes when
|
||||
// the given tab data is restored to a new tab.
|
||||
|
@ -40,4 +40,8 @@ function test() {
|
||||
"Invalid window for getWindowValue throws");
|
||||
ok(test(function() ss.setWindowValue({}, "", "")),
|
||||
"Invalid window for setWindowValue throws");
|
||||
ok(test(function() ss.getNumberOfTabsClosedLast({})),
|
||||
"Invalid window for getNumberOfTabsClosedLast throws");
|
||||
ok(test(function() ss.setNumberOfTabsClosedLast({}, 1)),
|
||||
"Invalid window for setNumberOfTabsClosedLast throws");
|
||||
}
|
||||
|
@ -38,5 +38,5 @@ function onTabViewWindowLoaded() {
|
||||
gBrowser.removeTab(tabTwo);
|
||||
finish();
|
||||
});
|
||||
});
|
||||
}, 0);
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ function test() {
|
||||
|
||||
createBlankTab();
|
||||
afterAllTabsLoaded(testUndoCloseWithSelectedBlankPinnedTab);
|
||||
});
|
||||
}, 0);
|
||||
});
|
||||
}
|
||||
|
||||
@ -94,7 +94,7 @@ function test() {
|
||||
gBrowser.removeTab(gBrowser.tabs[0]);
|
||||
|
||||
afterAllTabsLoaded(finishTest);
|
||||
});
|
||||
}, 0);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -81,7 +81,7 @@ function test() {
|
||||
gBrowser.removeTab(gBrowser.tabs[1]);
|
||||
gBrowser.removeTab(gBrowser.tabs[1]);
|
||||
hideTabView(finishTest);
|
||||
});
|
||||
}, 0);
|
||||
}
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
@ -20,7 +20,7 @@ function test() {
|
||||
whenTabViewIsHidden(function() {
|
||||
win.gBrowser.removeTab(win.gBrowser.selectedTab);
|
||||
executeSoon(function() {
|
||||
win.undoCloseTab();
|
||||
win.undoCloseTab(0);
|
||||
|
||||
groupItemTwo.addSubscriber("childAdded", function onChildAdded(data) {
|
||||
groupItemTwo.removeSubscriber("childAdded", onChildAdded);
|
||||
|
@ -359,7 +359,7 @@ function newWindowWithState(state, callback) {
|
||||
function restoreTab(callback, index, win) {
|
||||
win = win || window;
|
||||
|
||||
let tab = win.undoCloseTab(index || 0);
|
||||
let tab = win.undoCloseTab(index);
|
||||
let tabItem = tab._tabViewTabItem;
|
||||
|
||||
let finalize = function () {
|
||||
|
@ -6,9 +6,6 @@ ac_add_options --with-google-api-keyfile=/builds/gapi.data
|
||||
|
||||
. $topsrcdir/build/unix/mozconfig.linux32
|
||||
|
||||
# Avoid dependency on libstdc++ 4.5
|
||||
ac_add_options --enable-stdcxx-compat
|
||||
|
||||
# Needed to enable breakpad in application.ini
|
||||
export MOZILLA_OFFICIAL=1
|
||||
|
||||
|
@ -4,9 +4,6 @@ ac_add_options --enable-signmar
|
||||
|
||||
. $topsrcdir/build/unix/mozconfig.linux32
|
||||
|
||||
# Avoid dependency on libstdc++ 4.5
|
||||
ac_add_options --enable-stdcxx-compat
|
||||
|
||||
# Needed to enable breakpad in application.ini
|
||||
export MOZILLA_OFFICIAL=1
|
||||
|
||||
|
@ -8,9 +8,6 @@ ac_add_options --enable-valgrind
|
||||
|
||||
. $topsrcdir/build/unix/mozconfig.asan
|
||||
|
||||
# Avoid dependency on libstdc++ 4.5
|
||||
ac_add_options --enable-stdcxx-compat
|
||||
|
||||
# Package js shell.
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
||||
|
||||
|
@ -2,9 +2,6 @@ ac_add_options --with-l10n-base=../../l10n
|
||||
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
|
||||
ac_add_options --enable-update-packaging
|
||||
|
||||
# Avoid dependency on libstdc++ 4.5
|
||||
ac_add_options --enable-stdcxx-compat
|
||||
|
||||
. $topsrcdir/build/unix/mozconfig.linux32
|
||||
|
||||
export MOZILLA_OFFICIAL=1
|
||||
|
@ -10,9 +10,6 @@ ac_add_options --enable-codesighs
|
||||
|
||||
. $topsrcdir/build/unix/mozconfig.asan
|
||||
|
||||
# Avoid dependency on libstdc++ 4.5
|
||||
ac_add_options --enable-stdcxx-compat
|
||||
|
||||
# Package js shell.
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
||||
|
||||
|
@ -6,9 +6,6 @@ ac_add_options --with-google-api-keyfile=/builds/gapi.data
|
||||
|
||||
. $topsrcdir/build/unix/mozconfig.linux
|
||||
|
||||
# Avoid dependency on libstdc++ 4.5
|
||||
ac_add_options --enable-stdcxx-compat
|
||||
|
||||
# Needed to enable breakpad in application.ini
|
||||
export MOZILLA_OFFICIAL=1
|
||||
|
||||
|
@ -4,9 +4,6 @@ ac_add_options --enable-signmar
|
||||
|
||||
. $topsrcdir/build/unix/mozconfig.linux
|
||||
|
||||
# Avoid dependency on libstdc++ 4.5
|
||||
ac_add_options --enable-stdcxx-compat
|
||||
|
||||
# Needed to enable breakpad in application.ini
|
||||
export MOZILLA_OFFICIAL=1
|
||||
|
||||
|
@ -8,9 +8,6 @@ ac_add_options --enable-valgrind
|
||||
|
||||
. $topsrcdir/build/unix/mozconfig.asan
|
||||
|
||||
# Avoid dependency on libstdc++ 4.5
|
||||
ac_add_options --enable-stdcxx-compat
|
||||
|
||||
# Package js shell.
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
||||
|
||||
|
@ -9,7 +9,4 @@ export CXX="$topsrcdir/clang/bin/clang++"
|
||||
# Add the static checker
|
||||
ac_add_options --enable-clang-plugin
|
||||
|
||||
# Avoid dependency on libstdc++ 4.5
|
||||
ac_add_options --enable-stdcxx-compat
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
|
@ -2,9 +2,6 @@ ac_add_options --with-l10n-base=../../l10n
|
||||
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
|
||||
ac_add_options --enable-update-packaging
|
||||
|
||||
# Avoid dependency on libstdc++ 4.5
|
||||
ac_add_options --enable-stdcxx-compat
|
||||
|
||||
. $topsrcdir/build/unix/mozconfig.linux
|
||||
|
||||
export MOZILLA_OFFICIAL=1
|
||||
|
@ -10,9 +10,6 @@ ac_add_options --enable-codesighs
|
||||
|
||||
. $topsrcdir/build/unix/mozconfig.asan
|
||||
|
||||
# Avoid dependency on libstdc++ 4.5
|
||||
ac_add_options --enable-stdcxx-compat
|
||||
|
||||
# Package js shell.
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
||||
|
||||
|
@ -600,6 +600,11 @@ XPCOMUtils.defineLazyModuleGetter(this, "AppCacheUtils",
|
||||
return prefService.getBranch(null).QueryInterface(Ci.nsIPrefBranch2);
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, 'supportsString', function() {
|
||||
return Cc["@mozilla.org/supports-string;1"]
|
||||
.createInstance(Ci.nsISupportsString);
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
|
||||
"resource://gre/modules/NetUtil.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "console",
|
||||
@ -719,7 +724,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "AppCacheUtils",
|
||||
gcli.addCommand(commandSpec);
|
||||
commands.push(commandSpec.name);
|
||||
});
|
||||
|
||||
},
|
||||
function onError(reason) {
|
||||
console.error("OS.File.read(" + aFileEntry.path + ") failed.");
|
||||
@ -733,7 +737,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "AppCacheUtils",
|
||||
*/
|
||||
gcli.addCommand({
|
||||
name: "cmd",
|
||||
get hidden() { return !prefBranch.prefHasUserValue(PREF_DIR); },
|
||||
get hidden() {
|
||||
return !prefBranch.prefHasUserValue(PREF_DIR);
|
||||
},
|
||||
description: gcli.lookup("cmdDesc")
|
||||
});
|
||||
|
||||
@ -743,10 +749,49 @@ XPCOMUtils.defineLazyModuleGetter(this, "AppCacheUtils",
|
||||
gcli.addCommand({
|
||||
name: "cmd refresh",
|
||||
description: gcli.lookup("cmdRefreshDesc"),
|
||||
get hidden() { return !prefBranch.prefHasUserValue(PREF_DIR); },
|
||||
exec: function Command_cmdRefresh(args, context) {
|
||||
get hidden() {
|
||||
return !prefBranch.prefHasUserValue(PREF_DIR);
|
||||
},
|
||||
exec: function(args, context) {
|
||||
let chromeWindow = context.environment.chromeDocument.defaultView;
|
||||
CmdCommands.refreshAutoCommands(chromeWindow);
|
||||
|
||||
let dirName = prefBranch.getComplexValue(PREF_DIR,
|
||||
Ci.nsISupportsString).data.trim();
|
||||
return gcli.lookupFormat("cmdStatus", [ commands.length, dirName ]);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* 'cmd setdir' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
name: "cmd setdir",
|
||||
description: gcli.lookup("cmdSetdirDesc"),
|
||||
params: [
|
||||
{
|
||||
name: "directory",
|
||||
description: gcli.lookup("cmdSetdirDirectoryDesc"),
|
||||
type: {
|
||||
name: "file",
|
||||
filetype: "directory",
|
||||
existing: "yes"
|
||||
},
|
||||
defaultValue: null
|
||||
}
|
||||
],
|
||||
returnType: "string",
|
||||
get hidden() {
|
||||
return true; // !prefBranch.prefHasUserValue(PREF_DIR);
|
||||
},
|
||||
exec: function(args, context) {
|
||||
supportsString.data = args.directory;
|
||||
prefBranch.setComplexValue(PREF_DIR, Ci.nsISupportsString, supportsString);
|
||||
|
||||
let chromeWindow = context.environment.chromeDocument.defaultView;
|
||||
CmdCommands.refreshAutoCommands(chromeWindow);
|
||||
|
||||
return gcli.lookupFormat("cmdStatus", [ commands.length, args.directory ]);
|
||||
}
|
||||
});
|
||||
}(this));
|
||||
@ -1493,7 +1538,11 @@ XPCOMUtils.defineLazyModuleGetter(this, "AppCacheUtils",
|
||||
params: [
|
||||
{
|
||||
name: "srcdir",
|
||||
type: "string",
|
||||
type: "string" /* {
|
||||
name: "file",
|
||||
filetype: "directory",
|
||||
existing: "yes"
|
||||
} */,
|
||||
description: gcli.lookup("toolsSrcdirDir")
|
||||
}
|
||||
],
|
||||
@ -2167,3 +2216,49 @@ gcli.addCommand({
|
||||
}
|
||||
});
|
||||
}(this));
|
||||
|
||||
/* CmdMedia ------------------------------------------------------- */
|
||||
|
||||
(function(module) {
|
||||
/**
|
||||
* 'media' command
|
||||
*/
|
||||
|
||||
gcli.addCommand({
|
||||
name: "media",
|
||||
description: gcli.lookup("mediaDesc")
|
||||
});
|
||||
|
||||
gcli.addCommand({
|
||||
name: "media emulate",
|
||||
description: gcli.lookup("mediaEmulateDesc"),
|
||||
manual: gcli.lookup("mediaEmulateManual"),
|
||||
params: [
|
||||
{
|
||||
name: "type",
|
||||
description: gcli.lookup("mediaEmulateType"),
|
||||
type: {
|
||||
name: "selection",
|
||||
data: ["braille", "embossed", "handheld", "print", "projection",
|
||||
"screen", "speech", "tty", "tv"]
|
||||
}
|
||||
}
|
||||
],
|
||||
exec: function(args, context) {
|
||||
let markupDocumentViewer = context.environment.chromeWindow
|
||||
.gBrowser.markupDocumentViewer;
|
||||
markupDocumentViewer.emulateMedium(args.type);
|
||||
}
|
||||
});
|
||||
|
||||
gcli.addCommand({
|
||||
name: "media reset",
|
||||
description: gcli.lookup("mediaResetDesc"),
|
||||
manual: gcli.lookup("mediaEmulateManual"),
|
||||
exec: function(args, context) {
|
||||
let markupDocumentViewer = context.environment.chromeWindow
|
||||
.gBrowser.markupDocumentViewer;
|
||||
markupDocumentViewer.stopEmulatingMedium();
|
||||
}
|
||||
});
|
||||
}(this));
|
||||
|
@ -35,6 +35,8 @@ MOCHITEST_BROWSER_FILES = \
|
||||
browser_cmd_cookie.js \
|
||||
browser_cmd_jsb.js \
|
||||
browser_cmd_jsb_script.jsi \
|
||||
browser_cmd_media.html \
|
||||
browser_cmd_media.js \
|
||||
browser_cmd_pagemod_export.html \
|
||||
browser_cmd_pagemod_export.js \
|
||||
browser_cmd_pref.js \
|
||||
@ -42,10 +44,14 @@ MOCHITEST_BROWSER_FILES = \
|
||||
browser_cmd_screenshot.html \
|
||||
browser_cmd_screenshot.js \
|
||||
browser_cmd_settings.js \
|
||||
browser_gcli_async.js \
|
||||
browser_gcli_canon.js \
|
||||
browser_gcli_cli.js \
|
||||
browser_gcli_completion.js \
|
||||
browser_gcli_date.js \
|
||||
browser_gcli_exec.js \
|
||||
browser_gcli_fail.js \
|
||||
browser_gcli_file.js \
|
||||
browser_gcli_focus.js \
|
||||
browser_gcli_history.js \
|
||||
browser_gcli_incomplete.js \
|
||||
|
28
browser/devtools/commandline/test/browser_cmd_media.html
Normal file
28
browser/devtools/commandline/test/browser_cmd_media.html
Normal file
@ -0,0 +1,28 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>GCLI Test for Bug 819930</title>
|
||||
<style>
|
||||
@media braille {
|
||||
body {
|
||||
background-color: yellow;
|
||||
}
|
||||
}
|
||||
|
||||
@media embossed {
|
||||
body {
|
||||
background-color: indigo;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen {
|
||||
body {
|
||||
background-color: white;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
80
browser/devtools/commandline/test/browser_cmd_media.js
Normal file
80
browser/devtools/commandline/test/browser_cmd_media.js
Normal file
@ -0,0 +1,80 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Test that screenshot command works properly
|
||||
const TEST_URI = "http://example.com/browser/browser/devtools/commandline/" +
|
||||
"test/browser_cmd_media.html";
|
||||
let tests = {
|
||||
testInput: function(options) {
|
||||
return helpers.audit(options, [
|
||||
{
|
||||
setup: "media emulate braille",
|
||||
check: {
|
||||
input: "media emulate braille",
|
||||
markup: "VVVVVVVVVVVVVVVVVVVVV",
|
||||
status: "VALID",
|
||||
args: {
|
||||
type: { value: "braille"},
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
setup: "media reset",
|
||||
check: {
|
||||
input: "media reset",
|
||||
markup: "VVVVVVVVVVV",
|
||||
status: "VALID",
|
||||
args: {
|
||||
}
|
||||
},
|
||||
},
|
||||
]);
|
||||
},
|
||||
|
||||
testEmulateMedia: function(options) {
|
||||
return helpers.audit(options, [
|
||||
{
|
||||
setup: "media emulate braille",
|
||||
check: {
|
||||
args: {
|
||||
type: { value: "braille"}
|
||||
}
|
||||
},
|
||||
exec: {
|
||||
output: ""
|
||||
},
|
||||
post: function() {
|
||||
let body = options.window.document.body;
|
||||
let style = options.window.getComputedStyle(body);
|
||||
is(style.backgroundColor, "rgb(255, 255, 0)", "media correctly emulated");
|
||||
}
|
||||
}
|
||||
]);
|
||||
},
|
||||
|
||||
testEndMediaEmulation: function(options) {
|
||||
return helpers.audit(options, [
|
||||
{
|
||||
setup: function() {
|
||||
let mDV = options.browser.markupDocumentViewer;
|
||||
mDV.emulateMedium("embossed");
|
||||
return helpers.setInput(options, "media reset");
|
||||
},
|
||||
exec: {
|
||||
output: ""
|
||||
},
|
||||
post: function() {
|
||||
let body = options.window.document.body;
|
||||
let style = options.window.getComputedStyle(body);
|
||||
is(style.backgroundColor, "rgb(255, 255, 255)", "media reset");
|
||||
}
|
||||
}
|
||||
]);
|
||||
}
|
||||
};
|
||||
|
||||
function test() {
|
||||
helpers.addTabWithToolbar(TEST_URI, function(options) {
|
||||
return helpers.runTests(options, tests);
|
||||
}).then(finish);
|
||||
}
|
@ -1,7 +1,17 @@
|
||||
/*
|
||||
* Copyright 2009-2011 Mozilla Foundation and contributors
|
||||
* Licensed under the New BSD license. See LICENSE.txt or:
|
||||
* http://opensource.org/licenses/BSD-3-Clause
|
||||
* Copyright 2012, Mozilla Foundation and contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// define(function(require, exports, module) {
|
||||
|
@ -217,10 +217,11 @@ exports.testAltCanon = function(options) {
|
||||
|
||||
var commandSpecs = altCanon.getCommandSpecs();
|
||||
assert.is(JSON.stringify(commandSpecs),
|
||||
'{"tss":{"name":"tss","params":[' +
|
||||
'{"name":"str","type":"string"},' +
|
||||
'{"name":"num","type":"number"},' +
|
||||
'{"name":"opt","type":{"name":"selection","data":["1","2","3"]}}]}}',
|
||||
'{"tss":{"name":"tss","description":"(No description)","params":[' +
|
||||
'{"name":"str","type":"string","description":"(No description)"},' +
|
||||
'{"name":"num","type":"number","description":"(No description)"},' +
|
||||
'{"name":"opt","type":{"name":"selection","data":["1","2","3"]},"description":"(No description)"}'+
|
||||
'],"isParent":false}}',
|
||||
'JSON.stringify(commandSpecs)');
|
||||
|
||||
var remoter = function(args, context) {
|
||||
|
@ -37,26 +37,17 @@ function test() {
|
||||
|
||||
// var helpers = require('gclitest/helpers');
|
||||
// var mockCommands = require('gclitest/mockCommands');
|
||||
var cli = require('gcli/cli');
|
||||
|
||||
var origLogErrors = undefined;
|
||||
|
||||
exports.setup = function(options) {
|
||||
mockCommands.setup();
|
||||
|
||||
origLogErrors = cli.logErrors;
|
||||
cli.logErrors = false;
|
||||
};
|
||||
|
||||
exports.shutdown = function(options) {
|
||||
mockCommands.shutdown();
|
||||
|
||||
cli.logErrors = origLogErrors;
|
||||
origLogErrors = undefined;
|
||||
};
|
||||
|
||||
exports.testBaseline = function(options) {
|
||||
helpers.audit(options, [
|
||||
return helpers.audit(options, [
|
||||
// These 3 establish a baseline for comparison when we have used the
|
||||
// context command
|
||||
{
|
||||
@ -100,7 +91,7 @@ exports.testBaseline = function(options) {
|
||||
};
|
||||
|
||||
exports.testContext = function(options) {
|
||||
helpers.audit(options, [
|
||||
return helpers.audit(options, [
|
||||
// Use the 'tsn' context
|
||||
{
|
||||
setup: 'context tsn',
|
||||
|
@ -1,7 +1,17 @@
|
||||
/*
|
||||
* Copyright 2009-2011 Mozilla Foundation and contributors
|
||||
* Licensed under the New BSD license. See LICENSE.txt or:
|
||||
* http://opensource.org/licenses/BSD-3-Clause
|
||||
* Copyright 2012, Mozilla Foundation and contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// define(function(require, exports, module) {
|
||||
@ -80,8 +90,10 @@ exports.testIncrement = function(options) {
|
||||
};
|
||||
|
||||
exports.testInput = function(options) {
|
||||
helpers.audit(options, [
|
||||
return helpers.audit(options, [
|
||||
{
|
||||
// See bug 892901
|
||||
skipRemainingIf: options.isFirefox,
|
||||
setup: 'tsdate 2001-01-01 1980-01-03',
|
||||
check: {
|
||||
input: 'tsdate 2001-01-01 1980-01-03',
|
||||
@ -132,8 +144,10 @@ exports.testInput = function(options) {
|
||||
};
|
||||
|
||||
exports.testIncrDecr = function(options) {
|
||||
helpers.audit(options, [
|
||||
return helpers.audit(options, [
|
||||
{
|
||||
// See bug 892901
|
||||
skipRemainingIf: options.isFirefox,
|
||||
setup: 'tsdate 2001-01-01<UP>',
|
||||
check: {
|
||||
input: 'tsdate 2001-01-02',
|
||||
@ -224,14 +238,14 @@ exports.testIncrDecr = function(options) {
|
||||
message: ''
|
||||
},
|
||||
d2: {
|
||||
value: function(d1) {
|
||||
assert.is(d1.getFullYear(), 2000, 'd1 year');
|
||||
assert.is(d1.getMonth(), 1, 'd1 month');
|
||||
assert.is(d1.getDate(), 28, 'd1 date');
|
||||
assert.is(d1.getHours(), 0, 'd1 hours');
|
||||
assert.is(d1.getMinutes(), 0, 'd1 minutes');
|
||||
assert.is(d1.getSeconds(), 0, 'd1 seconds');
|
||||
assert.is(d1.getMilliseconds(), 0, 'd1 millis');
|
||||
value: function(d2) {
|
||||
assert.is(d2.getFullYear(), 2000, 'd2 year');
|
||||
assert.is(d2.getMonth(), 1, 'd2 month');
|
||||
assert.is(d2.getDate(), 28, 'd2 date');
|
||||
assert.is(d2.getHours(), 0, 'd2 hours');
|
||||
assert.is(d2.getMinutes(), 0, 'd2 minutes');
|
||||
assert.is(d2.getSeconds(), 0, 'd2 seconds');
|
||||
assert.is(d2.getMilliseconds(), 0, 'd2 millis');
|
||||
},
|
||||
arg: ' "2000-02-28"',
|
||||
status: 'VALID',
|
||||
|
@ -1,7 +1,17 @@
|
||||
/*
|
||||
* Copyright 2009-2011 Mozilla Foundation and contributors
|
||||
* Licensed under the New BSD license. See LICENSE.txt or:
|
||||
* http://opensource.org/licenses/BSD-3-Clause
|
||||
* Copyright 2012, Mozilla Foundation and contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// define(function(require, exports, module) {
|
||||
@ -27,22 +37,13 @@ function test() {
|
||||
|
||||
// var helpers = require('gclitest/helpers');
|
||||
// var mockCommands = require('gclitest/mockCommands');
|
||||
var cli = require('gcli/cli');
|
||||
|
||||
var origLogErrors = undefined;
|
||||
|
||||
exports.setup = function(options) {
|
||||
mockCommands.setup();
|
||||
|
||||
origLogErrors = cli.logErrors;
|
||||
cli.logErrors = false;
|
||||
};
|
||||
|
||||
exports.shutdown = function(options) {
|
||||
mockCommands.shutdown();
|
||||
|
||||
cli.logErrors = origLogErrors;
|
||||
origLogErrors = undefined;
|
||||
};
|
||||
|
||||
exports.testBasic = function(options) {
|
||||
|
848
browser/devtools/commandline/test/browser_gcli_file.js
Normal file
848
browser/devtools/commandline/test/browser_gcli_file.js
Normal file
@ -0,0 +1,848 @@
|
||||
/*
|
||||
* Copyright 2012, Mozilla Foundation and contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// define(function(require, exports, module) {
|
||||
|
||||
// <INJECTED SOURCE:START>
|
||||
|
||||
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
|
||||
// DO NOT EDIT IT DIRECTLY
|
||||
|
||||
var exports = {};
|
||||
|
||||
const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testFile.js</p>";
|
||||
|
||||
function test() {
|
||||
helpers.addTabWithToolbar(TEST_URI, function(options) {
|
||||
return helpers.runTests(options, exports);
|
||||
}).then(finish);
|
||||
}
|
||||
|
||||
// <INJECTED SOURCE:END>
|
||||
|
||||
'use strict';
|
||||
|
||||
// var helpers = require('gclitest/helpers');
|
||||
// var mockCommands = require('gclitest/mockCommands');
|
||||
|
||||
exports.setup = function(options) {
|
||||
mockCommands.setup();
|
||||
};
|
||||
|
||||
exports.shutdown = function(options) {
|
||||
mockCommands.shutdown();
|
||||
};
|
||||
|
||||
var local = false;
|
||||
|
||||
exports.testBasic = function(options) {
|
||||
var isPhantomjsFromFilesystem = (!options.isHttp && options.isPhantomjs);
|
||||
return helpers.audit(options, [
|
||||
{
|
||||
// These tests require us to be using node directly or to be in
|
||||
// phantomjs connected to an allowexec enabled node server or to be in
|
||||
// firefox. In short they only don't work when in phantomjs reading
|
||||
// from the filesystem, but they do work in Firefox
|
||||
skipRemainingIf: isPhantomjsFromFilesystem || options.isFirefox,
|
||||
setup: 'tsfile open /',
|
||||
check: {
|
||||
input: 'tsfile open /',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVI',
|
||||
cursor: 13,
|
||||
current: 'p1',
|
||||
status: 'ERROR',
|
||||
message: '\'/\' is not a file',
|
||||
args: {
|
||||
command: { name: 'tsfile open' },
|
||||
p1: {
|
||||
value: undefined,
|
||||
arg: ' /',
|
||||
status: 'INCOMPLETE',
|
||||
message: '\'/\' is not a file'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'tsfile open /zxcv',
|
||||
check: {
|
||||
input: 'tsfile open /zxcv',
|
||||
// hints: ' -> /etc/',
|
||||
markup: 'VVVVVVVVVVVVIIIII',
|
||||
cursor: 17,
|
||||
current: 'p1',
|
||||
status: 'ERROR',
|
||||
message: '\'/zxcv\' doesn\'t exist',
|
||||
args: {
|
||||
command: { name: 'tsfile open' },
|
||||
p1: {
|
||||
value: undefined,
|
||||
arg: ' /zxcv',
|
||||
status: 'INCOMPLETE',
|
||||
message: '\'/zxcv\' doesn\'t exist'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
skipIf: !local,
|
||||
setup: 'tsfile open /mach_kernel',
|
||||
check: {
|
||||
input: 'tsfile open /mach_kernel',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVVVVVVVVVV',
|
||||
cursor: 24,
|
||||
current: 'p1',
|
||||
status: 'VALID',
|
||||
message: '',
|
||||
args: {
|
||||
command: { name: 'tsfile open' },
|
||||
p1: {
|
||||
value: '/mach_kernel',
|
||||
arg: ' /mach_kernel',
|
||||
status: 'VALID',
|
||||
message: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'tsfile saveas /',
|
||||
check: {
|
||||
input: 'tsfile saveas /',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVI',
|
||||
cursor: 15,
|
||||
current: 'p1',
|
||||
status: 'ERROR',
|
||||
message: '\'/\' already exists',
|
||||
args: {
|
||||
command: { name: 'tsfile saveas' },
|
||||
p1: {
|
||||
value: undefined,
|
||||
arg: ' /',
|
||||
status: 'INCOMPLETE',
|
||||
message: '\'/\' already exists'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'tsfile saveas /zxcv',
|
||||
check: {
|
||||
input: 'tsfile saveas /zxcv',
|
||||
// hints: ' -> /etc/',
|
||||
markup: 'VVVVVVVVVVVVVVVVVVV',
|
||||
cursor: 19,
|
||||
current: 'p1',
|
||||
status: 'VALID',
|
||||
message: '',
|
||||
args: {
|
||||
command: { name: 'tsfile saveas' },
|
||||
p1: {
|
||||
value: '/zxcv',
|
||||
arg: ' /zxcv',
|
||||
status: 'VALID',
|
||||
message: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
skipIf: !local,
|
||||
setup: 'tsfile saveas /mach_kernel',
|
||||
check: {
|
||||
input: 'tsfile saveas /mach_kernel',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVIIIIIIIIIIII',
|
||||
cursor: 26,
|
||||
current: 'p1',
|
||||
status: 'ERROR',
|
||||
message: '\'/mach_kernel\' already exists',
|
||||
args: {
|
||||
command: { name: 'tsfile saveas' },
|
||||
p1: {
|
||||
value: undefined,
|
||||
arg: ' /mach_kernel',
|
||||
status: 'INCOMPLETE',
|
||||
message: '\'/mach_kernel\' already exists'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'tsfile save /',
|
||||
check: {
|
||||
input: 'tsfile save /',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVI',
|
||||
cursor: 13,
|
||||
current: 'p1',
|
||||
status: 'ERROR',
|
||||
message: '\'/\' is not a file',
|
||||
args: {
|
||||
command: { name: 'tsfile save' },
|
||||
p1: {
|
||||
value: undefined,
|
||||
arg: ' /',
|
||||
status: 'INCOMPLETE',
|
||||
message: '\'/\' is not a file'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'tsfile save /zxcv',
|
||||
check: {
|
||||
input: 'tsfile save /zxcv',
|
||||
// hints: ' -> /etc/',
|
||||
markup: 'VVVVVVVVVVVVVVVVV',
|
||||
cursor: 17,
|
||||
current: 'p1',
|
||||
status: 'VALID',
|
||||
message: '',
|
||||
args: {
|
||||
command: { name: 'tsfile save' },
|
||||
p1: {
|
||||
value: '/zxcv',
|
||||
arg: ' /zxcv',
|
||||
status: 'VALID',
|
||||
message: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
skipIf: !local,
|
||||
setup: 'tsfile save /mach_kernel',
|
||||
check: {
|
||||
input: 'tsfile save /mach_kernel',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVVVVVVVVVV',
|
||||
cursor: 24,
|
||||
current: 'p1',
|
||||
status: 'VALID',
|
||||
message: '',
|
||||
args: {
|
||||
command: { name: 'tsfile save' },
|
||||
p1: {
|
||||
value: '/mach_kernel',
|
||||
arg: ' /mach_kernel',
|
||||
status: 'VALID',
|
||||
message: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'tsfile cd /',
|
||||
check: {
|
||||
input: 'tsfile cd /',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVV',
|
||||
cursor: 11,
|
||||
current: 'p1',
|
||||
status: 'VALID',
|
||||
message: '',
|
||||
args: {
|
||||
command: { name: 'tsfile cd' },
|
||||
p1: {
|
||||
value: '/',
|
||||
arg: ' /',
|
||||
status: 'VALID',
|
||||
message: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'tsfile cd /zxcv',
|
||||
check: {
|
||||
input: 'tsfile cd /zxcv',
|
||||
// hints: ' -> /dev/',
|
||||
markup: 'VVVVVVVVVVIIIII',
|
||||
cursor: 15,
|
||||
current: 'p1',
|
||||
status: 'ERROR',
|
||||
message: '\'/zxcv\' doesn\'t exist',
|
||||
args: {
|
||||
command: { name: 'tsfile cd' },
|
||||
p1: {
|
||||
value: undefined,
|
||||
arg: ' /zxcv',
|
||||
status: 'INCOMPLETE',
|
||||
message: '\'/zxcv\' doesn\'t exist'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
skipIf: true || !local,
|
||||
setup: 'tsfile cd /etc/passwd',
|
||||
check: {
|
||||
input: 'tsfile cd /etc/passwd',
|
||||
hints: ' -> /etc/pam.d/',
|
||||
markup: 'VVVVVVVVVVIIIIIIIIIII',
|
||||
cursor: 21,
|
||||
current: 'p1',
|
||||
status: 'ERROR',
|
||||
message: '\'/etc/passwd\' is not a directory',
|
||||
args: {
|
||||
command: { name: 'tsfile cd' },
|
||||
p1: {
|
||||
value: undefined,
|
||||
arg: ' /etc/passwd',
|
||||
status: 'INCOMPLETE',
|
||||
message: '\'/etc/passwd\' is not a directory'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'tsfile mkdir /',
|
||||
check: {
|
||||
input: 'tsfile mkdir /',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVI',
|
||||
cursor: 14,
|
||||
current: 'p1',
|
||||
status: 'ERROR',
|
||||
message: ''/' already exists',
|
||||
args: {
|
||||
command: { name: 'tsfile mkdir' },
|
||||
p1: {
|
||||
value: undefined,
|
||||
arg: ' /',
|
||||
status: 'INCOMPLETE',
|
||||
message: '\'/\' already exists'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'tsfile mkdir /zxcv',
|
||||
check: {
|
||||
input: 'tsfile mkdir /zxcv',
|
||||
// hints: ' -> /dev/',
|
||||
markup: 'VVVVVVVVVVVVVVVVVV',
|
||||
cursor: 18,
|
||||
current: 'p1',
|
||||
status: 'VALID',
|
||||
message: '',
|
||||
args: {
|
||||
command: { name: 'tsfile mkdir' },
|
||||
p1: {
|
||||
value: '/zxcv',
|
||||
arg: ' /zxcv',
|
||||
status: 'VALID',
|
||||
message: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
skipIf: !local,
|
||||
setup: 'tsfile mkdir /mach_kernel',
|
||||
check: {
|
||||
input: 'tsfile mkdir /mach_kernel',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVIIIIIIIIIIII',
|
||||
cursor: 25,
|
||||
current: 'p1',
|
||||
status: 'ERROR',
|
||||
message: '\'/mach_kernel\' already exists',
|
||||
args: {
|
||||
command: { name: 'tsfile mkdir' },
|
||||
p1: {
|
||||
value: undefined,
|
||||
arg: ' /mach_kernel',
|
||||
status: 'INCOMPLETE',
|
||||
message: '\'/mach_kernel\' already exists'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'tsfile rm /',
|
||||
check: {
|
||||
input: 'tsfile rm /',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVV',
|
||||
cursor: 11,
|
||||
current: 'p1',
|
||||
status: 'VALID',
|
||||
message: '',
|
||||
args: {
|
||||
command: { name: 'tsfile rm' },
|
||||
p1: {
|
||||
value: '/',
|
||||
arg: ' /',
|
||||
status: 'VALID',
|
||||
message: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'tsfile rm /zxcv',
|
||||
check: {
|
||||
input: 'tsfile rm /zxcv',
|
||||
// hints: ' -> /etc/',
|
||||
markup: 'VVVVVVVVVVIIIII',
|
||||
cursor: 15,
|
||||
current: 'p1',
|
||||
status: 'ERROR',
|
||||
message: '\'/zxcv\' doesn\'t exist',
|
||||
args: {
|
||||
command: { name: 'tsfile rm' },
|
||||
p1: {
|
||||
value: undefined,
|
||||
arg: ' /zxcv',
|
||||
status: 'INCOMPLETE',
|
||||
message: '\'/zxcv\' doesn\'t exist'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
skipIf: !local,
|
||||
setup: 'tsfile rm /mach_kernel',
|
||||
check: {
|
||||
input: 'tsfile rm /mach_kernel',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVVVVVVVV',
|
||||
cursor: 22,
|
||||
current: 'p1',
|
||||
status: 'VALID',
|
||||
message: '',
|
||||
args: {
|
||||
command: { name: 'tsfile rm' },
|
||||
p1: {
|
||||
value: '/mach_kernel',
|
||||
arg: ' /mach_kernel',
|
||||
status: 'VALID',
|
||||
message: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]);
|
||||
};
|
||||
|
||||
exports.testFirefoxBasic = function(options) {
|
||||
return helpers.audit(options, [
|
||||
{
|
||||
// These tests are just like the ones above tailored for running in
|
||||
// Firefox
|
||||
skipRemainingIf: true,
|
||||
// skipRemainingIf: !options.isFirefox,
|
||||
skipIf: true,
|
||||
setup: 'tsfile open /',
|
||||
check: {
|
||||
input: 'tsfile open /',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVI',
|
||||
cursor: 13,
|
||||
current: 'p1',
|
||||
status: 'ERROR',
|
||||
message: '\'/\' is not a file',
|
||||
args: {
|
||||
command: { name: 'tsfile open' },
|
||||
p1: {
|
||||
value: undefined,
|
||||
arg: ' /',
|
||||
status: 'INCOMPLETE',
|
||||
message: '\'/\' is not a file'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
skipIf: true,
|
||||
setup: 'tsfile open /zxcv',
|
||||
check: {
|
||||
input: 'tsfile open /zxcv',
|
||||
// hints: ' -> /etc/',
|
||||
markup: 'VVVVVVVVVVVVIIIII',
|
||||
cursor: 17,
|
||||
current: 'p1',
|
||||
status: 'ERROR',
|
||||
message: '\'/zxcv\' doesn\'t exist',
|
||||
args: {
|
||||
command: { name: 'tsfile open' },
|
||||
p1: {
|
||||
value: undefined,
|
||||
arg: ' /zxcv',
|
||||
status: 'INCOMPLETE',
|
||||
message: '\'/zxcv\' doesn\'t exist'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
skipIf: !local,
|
||||
setup: 'tsfile open /mach_kernel',
|
||||
check: {
|
||||
input: 'tsfile open /mach_kernel',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVVVVVVVVVV',
|
||||
cursor: 24,
|
||||
current: 'p1',
|
||||
status: 'VALID',
|
||||
message: '',
|
||||
args: {
|
||||
command: { name: 'tsfile open' },
|
||||
p1: {
|
||||
value: '/mach_kernel',
|
||||
arg: ' /mach_kernel',
|
||||
status: 'VALID',
|
||||
message: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
skipIf: true,
|
||||
setup: 'tsfile saveas /',
|
||||
check: {
|
||||
input: 'tsfile saveas /',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVI',
|
||||
cursor: 15,
|
||||
current: 'p1',
|
||||
status: 'ERROR',
|
||||
message: '\'/\' already exists',
|
||||
args: {
|
||||
command: { name: 'tsfile saveas' },
|
||||
p1: {
|
||||
value: undefined,
|
||||
arg: ' /',
|
||||
status: 'INCOMPLETE',
|
||||
message: '\'/\' already exists'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
skipIf: true,
|
||||
setup: 'tsfile saveas /zxcv',
|
||||
check: {
|
||||
input: 'tsfile saveas /zxcv',
|
||||
// hints: ' -> /etc/',
|
||||
markup: 'VVVVVVVVVVVVVVVVVVV',
|
||||
cursor: 19,
|
||||
current: 'p1',
|
||||
status: 'VALID',
|
||||
message: '',
|
||||
args: {
|
||||
command: { name: 'tsfile saveas' },
|
||||
p1: {
|
||||
value: '/zxcv',
|
||||
arg: ' /zxcv',
|
||||
status: 'VALID',
|
||||
message: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
skipIf: !local,
|
||||
setup: 'tsfile saveas /mach_kernel',
|
||||
check: {
|
||||
input: 'tsfile saveas /mach_kernel',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVIIIIIIIIIIII',
|
||||
cursor: 26,
|
||||
current: 'p1',
|
||||
status: 'ERROR',
|
||||
message: '\'/mach_kernel\' already exists',
|
||||
args: {
|
||||
command: { name: 'tsfile saveas' },
|
||||
p1: {
|
||||
value: undefined,
|
||||
arg: ' /mach_kernel',
|
||||
status: 'INCOMPLETE',
|
||||
message: '\'/mach_kernel\' already exists'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
skipIf: true,
|
||||
setup: 'tsfile save /',
|
||||
check: {
|
||||
input: 'tsfile save /',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVI',
|
||||
cursor: 13,
|
||||
current: 'p1',
|
||||
status: 'ERROR',
|
||||
message: '\'/\' is not a file',
|
||||
args: {
|
||||
command: { name: 'tsfile save' },
|
||||
p1: {
|
||||
value: undefined,
|
||||
arg: ' /',
|
||||
status: 'INCOMPLETE',
|
||||
message: '\'/\' is not a file'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
skipIf: true,
|
||||
setup: 'tsfile save /zxcv',
|
||||
check: {
|
||||
input: 'tsfile save /zxcv',
|
||||
// hints: ' -> /etc/',
|
||||
markup: 'VVVVVVVVVVVVVVVVV',
|
||||
cursor: 17,
|
||||
current: 'p1',
|
||||
status: 'VALID',
|
||||
message: '',
|
||||
args: {
|
||||
command: { name: 'tsfile save' },
|
||||
p1: {
|
||||
value: '/zxcv',
|
||||
arg: ' /zxcv',
|
||||
status: 'VALID',
|
||||
message: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
skipIf: !local,
|
||||
setup: 'tsfile save /mach_kernel',
|
||||
check: {
|
||||
input: 'tsfile save /mach_kernel',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVVVVVVVVVV',
|
||||
cursor: 24,
|
||||
current: 'p1',
|
||||
status: 'VALID',
|
||||
message: '',
|
||||
args: {
|
||||
command: { name: 'tsfile save' },
|
||||
p1: {
|
||||
value: '/mach_kernel',
|
||||
arg: ' /mach_kernel',
|
||||
status: 'VALID',
|
||||
message: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'tsfile cd /',
|
||||
check: {
|
||||
input: 'tsfile cd /',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVV',
|
||||
cursor: 11,
|
||||
current: 'p1',
|
||||
status: 'VALID',
|
||||
message: '',
|
||||
args: {
|
||||
command: { name: 'tsfile cd' },
|
||||
p1: {
|
||||
value: '/',
|
||||
arg: ' /',
|
||||
status: 'VALID',
|
||||
message: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'tsfile cd /zxcv',
|
||||
check: {
|
||||
input: 'tsfile cd /zxcv',
|
||||
// hints: ' -> /dev/',
|
||||
// markup: 'VVVVVVVVVVIIIII',
|
||||
cursor: 15,
|
||||
current: 'p1',
|
||||
// status: 'ERROR',
|
||||
message: '\'/zxcv\' doesn\'t exist',
|
||||
args: {
|
||||
command: { name: 'tsfile cd' },
|
||||
p1: {
|
||||
value: undefined,
|
||||
arg: ' /zxcv',
|
||||
// status: 'INCOMPLETE',
|
||||
message: '\'/zxcv\' doesn\'t exist'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
skipIf: true || !local,
|
||||
setup: 'tsfile cd /etc/passwd',
|
||||
check: {
|
||||
input: 'tsfile cd /etc/passwd',
|
||||
hints: ' -> /etc/pam.d/',
|
||||
markup: 'VVVVVVVVVVIIIIIIIIIII',
|
||||
cursor: 21,
|
||||
current: 'p1',
|
||||
status: 'ERROR',
|
||||
message: '\'/etc/passwd\' is not a directory',
|
||||
args: {
|
||||
command: { name: 'tsfile cd' },
|
||||
p1: {
|
||||
value: undefined,
|
||||
arg: ' /etc/passwd',
|
||||
status: 'INCOMPLETE',
|
||||
message: '\'/etc/passwd\' is not a directory'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'tsfile mkdir /',
|
||||
check: {
|
||||
input: 'tsfile mkdir /',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVI',
|
||||
cursor: 14,
|
||||
current: 'p1',
|
||||
status: 'ERROR',
|
||||
message: ''/' already exists',
|
||||
args: {
|
||||
command: { name: 'tsfile mkdir' },
|
||||
p1: {
|
||||
value: undefined,
|
||||
arg: ' /',
|
||||
status: 'INCOMPLETE',
|
||||
message: '\'/\' already exists'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'tsfile mkdir /zxcv',
|
||||
check: {
|
||||
input: 'tsfile mkdir /zxcv',
|
||||
// hints: ' -> /dev/',
|
||||
markup: 'VVVVVVVVVVVVVVVVVV',
|
||||
cursor: 18,
|
||||
current: 'p1',
|
||||
status: 'VALID',
|
||||
message: '',
|
||||
args: {
|
||||
command: { name: 'tsfile mkdir' },
|
||||
p1: {
|
||||
value: '/zxcv',
|
||||
arg: ' /zxcv',
|
||||
status: 'VALID',
|
||||
message: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
skipIf: !local,
|
||||
setup: 'tsfile mkdir /mach_kernel',
|
||||
check: {
|
||||
input: 'tsfile mkdir /mach_kernel',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVIIIIIIIIIIII',
|
||||
cursor: 25,
|
||||
current: 'p1',
|
||||
status: 'ERROR',
|
||||
message: '\'/mach_kernel\' already exists',
|
||||
args: {
|
||||
command: { name: 'tsfile mkdir' },
|
||||
p1: {
|
||||
value: undefined,
|
||||
arg: ' /mach_kernel',
|
||||
status: 'INCOMPLETE',
|
||||
message: '\'/mach_kernel\' already exists'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
skipIf: true,
|
||||
setup: 'tsfile rm /',
|
||||
check: {
|
||||
input: 'tsfile rm /',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVV',
|
||||
cursor: 11,
|
||||
current: 'p1',
|
||||
status: 'VALID',
|
||||
message: '',
|
||||
args: {
|
||||
command: { name: 'tsfile rm' },
|
||||
p1: {
|
||||
value: '/',
|
||||
arg: ' /',
|
||||
status: 'VALID',
|
||||
message: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
skipIf: true,
|
||||
setup: 'tsfile rm /zxcv',
|
||||
check: {
|
||||
input: 'tsfile rm /zxcv',
|
||||
// hints: ' -> /etc/',
|
||||
markup: 'VVVVVVVVVVIIIII',
|
||||
cursor: 15,
|
||||
current: 'p1',
|
||||
status: 'ERROR',
|
||||
message: '\'/zxcv\' doesn\'t exist',
|
||||
args: {
|
||||
command: { name: 'tsfile rm' },
|
||||
p1: {
|
||||
value: undefined,
|
||||
arg: ' /zxcv',
|
||||
status: 'INCOMPLETE',
|
||||
message: '\'/zxcv\' doesn\'t exist'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
skipIf: !local,
|
||||
setup: 'tsfile rm /mach_kernel',
|
||||
check: {
|
||||
input: 'tsfile rm /mach_kernel',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVVVVVVVV',
|
||||
cursor: 22,
|
||||
current: 'p1',
|
||||
status: 'VALID',
|
||||
message: '',
|
||||
args: {
|
||||
command: { name: 'tsfile rm' },
|
||||
p1: {
|
||||
value: '/mach_kernel',
|
||||
arg: ' /mach_kernel',
|
||||
status: 'VALID',
|
||||
message: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]);
|
||||
};
|
||||
|
||||
|
||||
// });
|
57
browser/devtools/commandline/test/browser_gcli_fileparser.js
Normal file
57
browser/devtools/commandline/test/browser_gcli_fileparser.js
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2012, Mozilla Foundation and contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// define(function(require, exports, module) {
|
||||
|
||||
// <INJECTED SOURCE:START>
|
||||
|
||||
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
|
||||
// DO NOT EDIT IT DIRECTLY
|
||||
|
||||
var exports = {};
|
||||
|
||||
const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testFileparser.js</p>";
|
||||
|
||||
function test() {
|
||||
helpers.addTabWithToolbar(TEST_URI, function(options) {
|
||||
return helpers.runTests(options, exports);
|
||||
}).then(finish);
|
||||
}
|
||||
|
||||
// <INJECTED SOURCE:END>
|
||||
|
||||
'use strict';
|
||||
|
||||
// var assert = require('test/assert');
|
||||
var fileparser = require('util/fileparser');
|
||||
|
||||
var local = false;
|
||||
|
||||
exports.testGetPredictor = function(options) {
|
||||
if (!options.isNode || !local) {
|
||||
return;
|
||||
}
|
||||
|
||||
var options = { filetype: 'file', existing: 'yes' };
|
||||
var predictor = fileparser.getPredictor('/usr/locl/bin/nmp', options);
|
||||
return predictor().then(function(replies) {
|
||||
assert.is(replies[0].name,
|
||||
'/usr/local/bin/npm',
|
||||
'predict npm');
|
||||
});
|
||||
};
|
||||
|
||||
// });
|
78
browser/devtools/commandline/test/browser_gcli_filesystem.js
Normal file
78
browser/devtools/commandline/test/browser_gcli_filesystem.js
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2012, Mozilla Foundation and contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// define(function(require, exports, module) {
|
||||
|
||||
// <INJECTED SOURCE:START>
|
||||
|
||||
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
|
||||
// DO NOT EDIT IT DIRECTLY
|
||||
|
||||
var exports = {};
|
||||
|
||||
const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testFilesystem.js</p>";
|
||||
|
||||
function test() {
|
||||
helpers.addTabWithToolbar(TEST_URI, function(options) {
|
||||
return helpers.runTests(options, exports);
|
||||
}).then(finish);
|
||||
}
|
||||
|
||||
// <INJECTED SOURCE:END>
|
||||
|
||||
'use strict';
|
||||
|
||||
// var assert = require('test/assert');
|
||||
// var helpers = require('gclitest/helpers');
|
||||
var filesystem = require('util/filesystem');
|
||||
|
||||
exports.testSplit = function(options) {
|
||||
if (!options.isNode) {
|
||||
return;
|
||||
}
|
||||
|
||||
helpers.arrayIs(filesystem.split('', '/'),
|
||||
[ '.' ],
|
||||
'split <blank>');
|
||||
|
||||
helpers.arrayIs(filesystem.split('a', '/'),
|
||||
[ 'a' ],
|
||||
'split a');
|
||||
|
||||
helpers.arrayIs(filesystem.split('a/b/c', '/'),
|
||||
[ 'a', 'b', 'c' ],
|
||||
'split a/b/c');
|
||||
|
||||
helpers.arrayIs(filesystem.split('/a/b/c/', '/'),
|
||||
[ 'a', 'b', 'c' ],
|
||||
'split a/b/c');
|
||||
|
||||
helpers.arrayIs(filesystem.split('/a/b///c/', '/'),
|
||||
[ 'a', 'b', 'c' ],
|
||||
'split a/b/c');
|
||||
};
|
||||
|
||||
exports.testJoin = function(options) {
|
||||
if (!options.isNode) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert.is(filesystem.join('usr', 'local', 'bin'),
|
||||
'usr/local/bin',
|
||||
'join to usr/local/bin');
|
||||
};
|
||||
|
||||
// });
|
@ -1,7 +1,17 @@
|
||||
/*
|
||||
* Copyright 2009-2011 Mozilla Foundation and contributors
|
||||
* Licensed under the New BSD license. See LICENSE.txt or:
|
||||
* http://opensource.org/licenses/BSD-3-Clause
|
||||
* Copyright 2012, Mozilla Foundation and contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// define(function(require, exports, module) {
|
||||
|
@ -1,7 +1,17 @@
|
||||
/*
|
||||
* Copyright 2009-2011 Mozilla Foundation and contributors
|
||||
* Licensed under the New BSD license. See LICENSE.txt or:
|
||||
* http://opensource.org/licenses/BSD-3-Clause
|
||||
* Copyright 2012, Mozilla Foundation and contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// define(function(require, exports, module) {
|
||||
|
@ -1,7 +1,17 @@
|
||||
/*
|
||||
* Copyright 2009-2011 Mozilla Foundation and contributors
|
||||
* Licensed under the New BSD license. See LICENSE.txt or:
|
||||
* http://opensource.org/licenses/BSD-3-Clause
|
||||
* Copyright 2012, Mozilla Foundation and contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// define(function(require, exports, module) {
|
||||
|
@ -1,7 +1,17 @@
|
||||
/*
|
||||
* Copyright 2009-2011 Mozilla Foundation and contributors
|
||||
* Licensed under the New BSD license. See LICENSE.txt or:
|
||||
* http://opensource.org/licenses/BSD-3-Clause
|
||||
* Copyright 2012, Mozilla Foundation and contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// define(function(require, exports, module) {
|
||||
|
@ -48,6 +48,7 @@ exports.shutdown = function(options) {
|
||||
};
|
||||
|
||||
exports.testRemote = function(options) {
|
||||
var connected = false;
|
||||
return helpers.audit(options, [
|
||||
{
|
||||
skipRemainingIf: !options.isHttp,
|
||||
@ -65,6 +66,72 @@ exports.testRemote = function(options) {
|
||||
unassigned: [ ],
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'connect remote',
|
||||
check: {
|
||||
input: 'connect remote',
|
||||
hints: ' [options]',
|
||||
markup: 'VVVVVVVVVVVVVV',
|
||||
cursor: 14,
|
||||
current: 'prefix',
|
||||
status: 'VALID',
|
||||
options: [ ],
|
||||
message: '',
|
||||
predictions: [ ],
|
||||
unassigned: [ ],
|
||||
args: {
|
||||
command: { name: 'connect' },
|
||||
prefix: { value: 'remote', arg: ' remote', status: 'VALID', message: '' },
|
||||
host: { value: undefined, arg: '', status: 'VALID', message: '' },
|
||||
port: { value: undefined, arg: '', status: 'VALID', message: '' },
|
||||
}
|
||||
},
|
||||
exec: {
|
||||
completed: false,
|
||||
error: false
|
||||
},
|
||||
post: function(output, data) {
|
||||
connected = !output.error;
|
||||
if (!connected) {
|
||||
console.log('Failure from "connect remote". Run server with "node gcli server start --websocket --allowexec" to allow remote command testing');
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
// We do a connect-disconnect dance for 2 reasons, partly re-establishing
|
||||
// a connection is a good test, and secondly it lets us have minimal
|
||||
// testing on the first connection so we don't need to turn websockets
|
||||
// on all the time
|
||||
setup: 'disconnect remote --force',
|
||||
skipRemainingIf: !connected,
|
||||
check: {
|
||||
input: 'disconnect remote --force',
|
||||
hints: '',
|
||||
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVV',
|
||||
cursor: 25,
|
||||
current: 'force',
|
||||
status: 'VALID',
|
||||
message: '',
|
||||
unassigned: [ ],
|
||||
args: {
|
||||
command: { name: 'disconnect' },
|
||||
prefix: {
|
||||
value: function(connection) {
|
||||
assert.is(connection.prefix, 'remote', 'disconnecting remote');
|
||||
},
|
||||
arg: ' remote',
|
||||
status: 'VALID',
|
||||
message: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
exec: {
|
||||
output: /^Removed [0-9]* commands.$/,
|
||||
completed: true,
|
||||
type: 'string',
|
||||
error: false
|
||||
}
|
||||
},
|
||||
{
|
||||
setup: 'connect remote',
|
||||
check: {
|
||||
|
@ -35,7 +35,7 @@ function test() {
|
||||
'use strict';
|
||||
|
||||
// var assert = require('test/assert');
|
||||
var spell = require('gcli/types/spell');
|
||||
var spell = require('util/spell');
|
||||
|
||||
exports.testSpellerSimple = function(options) {
|
||||
var alternatives = Object.keys(options.window);
|
||||
@ -54,5 +54,34 @@ exports.testSpellerSimple = function(options) {
|
||||
assert.is(spell.correct('=========', alternatives), undefined);
|
||||
};
|
||||
|
||||
exports.testRank = function(options) {
|
||||
var distances = spell.rank('fred', [ 'banana', 'fred', 'ed', 'red', 'FRED' ]);
|
||||
|
||||
assert.is(distances.length, 5, 'rank length');
|
||||
|
||||
assert.is(distances[0].name, 'fred', 'fred name #0');
|
||||
assert.is(distances[1].name, 'FRED', 'FRED name #1');
|
||||
assert.is(distances[2].name, 'red', 'red name #2');
|
||||
assert.is(distances[3].name, 'ed', 'ed name #3');
|
||||
assert.is(distances[4].name, 'banana', 'banana name #4');
|
||||
|
||||
assert.is(distances[0].dist, 0, 'fred dist 0');
|
||||
assert.is(distances[1].dist, 4, 'FRED dist 4');
|
||||
assert.is(distances[2].dist, 10, 'red dist 10');
|
||||
assert.is(distances[3].dist, 20, 'ed dist 20');
|
||||
assert.is(distances[4].dist, 100, 'banana dist 100');
|
||||
};
|
||||
|
||||
exports.testRank2 = function(options) {
|
||||
var distances = spell.rank('caps', [ 'CAPS', 'false' ]);
|
||||
assert.is(JSON.stringify(distances),
|
||||
'[{"name":"CAPS","dist":4},{"name":"false","dist":50}]',
|
||||
'spell.rank("caps", [ "CAPS", "false" ]');
|
||||
};
|
||||
|
||||
exports.testDistancePrefix = function(options) {
|
||||
assert.is(spell.distancePrefix('fred', 'freddy'), 0, 'distancePrefix fred');
|
||||
assert.is(spell.distancePrefix('FRED', 'freddy'), 4, 'distancePrefix FRED');
|
||||
};
|
||||
|
||||
// });
|
||||
|
@ -47,7 +47,7 @@ exports.shutdown = function(options) {
|
||||
};
|
||||
|
||||
exports.testNewLine = function(options) {
|
||||
helpers.audit(options, [
|
||||
return helpers.audit(options, [
|
||||
{
|
||||
setup: 'echo a\\nb',
|
||||
check: {
|
||||
@ -72,7 +72,7 @@ exports.testNewLine = function(options) {
|
||||
};
|
||||
|
||||
exports.testTab = function(options) {
|
||||
helpers.audit(options, [
|
||||
return helpers.audit(options, [
|
||||
{
|
||||
setup: 'echo a\\tb',
|
||||
check: {
|
||||
@ -97,7 +97,7 @@ exports.testTab = function(options) {
|
||||
};
|
||||
|
||||
exports.testEscape = function(options) {
|
||||
helpers.audit(options, [
|
||||
return helpers.audit(options, [
|
||||
{
|
||||
// What's typed is actually:
|
||||
// tsrsrsr a\\ b c
|
||||
@ -143,7 +143,7 @@ exports.testEscape = function(options) {
|
||||
};
|
||||
|
||||
exports.testBlank = function(options) {
|
||||
helpers.audit(options, [
|
||||
return helpers.audit(options, [
|
||||
{
|
||||
setup: 'tsrsrsr a "" c',
|
||||
check: {
|
||||
@ -213,7 +213,7 @@ exports.testBlank = function(options) {
|
||||
};
|
||||
|
||||
exports.testBlankWithParam = function(options) {
|
||||
helpers.audit(options, [
|
||||
return helpers.audit(options, [
|
||||
{
|
||||
setup: 'tsrsrsr a --p3',
|
||||
check: {
|
||||
|
@ -30,6 +30,7 @@ let promise = (Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js",
|
||||
let assert = { ok: ok, is: is, log: info };
|
||||
|
||||
var util = require('util/util');
|
||||
var cli = require('gcli/cli');
|
||||
|
||||
var converters = require('gcli/converters');
|
||||
|
||||
@ -566,7 +567,7 @@ helpers._check = function(options, name, checks) {
|
||||
|
||||
if ('predictions' in checks) {
|
||||
var predictionsCheck = function(actualPredictions) {
|
||||
helpers._arrayIs(actualPredictions,
|
||||
helpers.arrayIs(actualPredictions,
|
||||
checks.predictions,
|
||||
'predictions' + suffix);
|
||||
};
|
||||
@ -585,7 +586,7 @@ helpers._check = function(options, name, checks) {
|
||||
}
|
||||
|
||||
if ('unassigned' in checks) {
|
||||
helpers._arrayIs(helpers._actual.unassigned(options),
|
||||
helpers.arrayIs(helpers._actual.unassigned(options),
|
||||
checks.unassigned,
|
||||
'unassigned' + suffix);
|
||||
}
|
||||
@ -613,7 +614,7 @@ helpers._check = function(options, name, checks) {
|
||||
}
|
||||
|
||||
if ('options' in checks) {
|
||||
helpers._arrayIs(helpers._actual.options(options),
|
||||
helpers.arrayIs(helpers._actual.options(options),
|
||||
checks.options,
|
||||
'options' + suffix);
|
||||
}
|
||||
@ -718,6 +719,11 @@ helpers._exec = function(options, name, expected) {
|
||||
return promise.resolve({});
|
||||
}
|
||||
|
||||
var origLogErrors = cli.logErrors;
|
||||
if (expected.error) {
|
||||
cli.logErrors = false;
|
||||
}
|
||||
|
||||
var output;
|
||||
try {
|
||||
output = options.display.requisition.exec({ hidden: true });
|
||||
@ -726,6 +732,9 @@ helpers._exec = function(options, name, expected) {
|
||||
assert.ok(false, 'Failure executing \'' + name + '\': ' + ex);
|
||||
util.errorHandler(ex);
|
||||
|
||||
if (expected.error) {
|
||||
cli.logErrors = origLogErrors;
|
||||
}
|
||||
return promise.resolve({});
|
||||
}
|
||||
|
||||
@ -737,10 +746,17 @@ helpers._exec = function(options, name, expected) {
|
||||
|
||||
if (!options.window.document.createElement) {
|
||||
assert.log('skipping output tests (missing doc.createElement) for ' + name);
|
||||
|
||||
if (expected.error) {
|
||||
cli.logErrors = origLogErrors;
|
||||
}
|
||||
return promise.resolve({ output: output });
|
||||
}
|
||||
|
||||
if (!('output' in expected)) {
|
||||
if (expected.error) {
|
||||
cli.logErrors = origLogErrors;
|
||||
}
|
||||
return promise.resolve({ output: output });
|
||||
}
|
||||
|
||||
@ -788,6 +804,9 @@ helpers._exec = function(options, name, expected) {
|
||||
doTest(expected.output, actualOutput);
|
||||
}
|
||||
|
||||
if (expected.error) {
|
||||
cli.logErrors = origLogErrors;
|
||||
}
|
||||
return { output: output, text: actualOutput };
|
||||
});
|
||||
};
|
||||
@ -940,17 +959,6 @@ helpers.audit = function(options, audits) {
|
||||
log('- START \'' + name + '\' in ' + assert.currentTest);
|
||||
}
|
||||
|
||||
if (audit.skipIf) {
|
||||
var skip = (typeof audit.skipIf === 'function') ?
|
||||
audit.skipIf(options) :
|
||||
!!audit.skipIf;
|
||||
if (skip) {
|
||||
var reason = audit.skipIf.name ? 'due to ' + audit.skipIf.name : '';
|
||||
assert.log('Skipped ' + name + ' ' + reason);
|
||||
return promise.resolve(undefined);
|
||||
}
|
||||
}
|
||||
|
||||
if (audit.skipRemainingIf) {
|
||||
var skipRemainingIf = (typeof audit.skipRemainingIf === 'function') ?
|
||||
audit.skipRemainingIf(options) :
|
||||
@ -964,6 +972,17 @@ helpers.audit = function(options, audits) {
|
||||
}
|
||||
}
|
||||
|
||||
if (audit.skipIf) {
|
||||
var skip = (typeof audit.skipIf === 'function') ?
|
||||
audit.skipIf(options) :
|
||||
!!audit.skipIf;
|
||||
if (skip) {
|
||||
var reason = audit.skipIf.name ? 'due to ' + audit.skipIf.name : '';
|
||||
assert.log('Skipped ' + name + ' ' + reason);
|
||||
return promise.resolve(undefined);
|
||||
}
|
||||
}
|
||||
|
||||
if (skipReason != null) {
|
||||
assert.log('Skipped ' + name + ' ' + skipReason);
|
||||
return promise.resolve(undefined);
|
||||
@ -1008,7 +1027,7 @@ helpers.audit = function(options, audits) {
|
||||
/**
|
||||
* Compare 2 arrays.
|
||||
*/
|
||||
helpers._arrayIs = function(actual, expected, message) {
|
||||
helpers.arrayIs = function(actual, expected, message) {
|
||||
assert.ok(Array.isArray(actual), 'actual is not an array: ' + message);
|
||||
assert.ok(Array.isArray(expected), 'expected is not an array: ' + message);
|
||||
|
||||
|
@ -482,6 +482,116 @@ var tsfail = {
|
||||
}
|
||||
};
|
||||
|
||||
var tsfile = {
|
||||
item: 'command',
|
||||
name: 'tsfile',
|
||||
description: 'test file params',
|
||||
};
|
||||
|
||||
var tsfileOpen = {
|
||||
item: 'command',
|
||||
name: 'tsfile open',
|
||||
description: 'a file param in open mode',
|
||||
params: [
|
||||
{
|
||||
name: 'p1',
|
||||
type: {
|
||||
name: 'file',
|
||||
filetype: 'file',
|
||||
existing: 'yes'
|
||||
}
|
||||
}
|
||||
],
|
||||
exec: createExec('tsfile open')
|
||||
};
|
||||
|
||||
var tsfileSaveas = {
|
||||
item: 'command',
|
||||
name: 'tsfile saveas',
|
||||
description: 'a file param in saveas mode',
|
||||
params: [
|
||||
{
|
||||
name: 'p1',
|
||||
type: {
|
||||
name: 'file',
|
||||
filetype: 'file',
|
||||
existing: 'no'
|
||||
}
|
||||
}
|
||||
],
|
||||
exec: createExec('tsfile saveas')
|
||||
};
|
||||
|
||||
var tsfileSave = {
|
||||
item: 'command',
|
||||
name: 'tsfile save',
|
||||
description: 'a file param in save mode',
|
||||
params: [
|
||||
{
|
||||
name: 'p1',
|
||||
type: {
|
||||
name: 'file',
|
||||
filetype: 'file',
|
||||
existing: 'maybe'
|
||||
}
|
||||
}
|
||||
],
|
||||
exec: createExec('tsfile save')
|
||||
};
|
||||
|
||||
var tsfileCd = {
|
||||
item: 'command',
|
||||
name: 'tsfile cd',
|
||||
description: 'a file param in cd mode',
|
||||
params: [
|
||||
{
|
||||
name: 'p1',
|
||||
type: {
|
||||
name: 'file',
|
||||
filetype: 'directory',
|
||||
existing: 'yes'
|
||||
}
|
||||
}
|
||||
],
|
||||
exec: createExec('tsfile cd')
|
||||
};
|
||||
|
||||
var tsfileMkdir = {
|
||||
item: 'command',
|
||||
name: 'tsfile mkdir',
|
||||
description: 'a file param in mkdir mode',
|
||||
params: [
|
||||
{
|
||||
name: 'p1',
|
||||
type: {
|
||||
name: 'file',
|
||||
filetype: 'directory',
|
||||
existing: 'no'
|
||||
}
|
||||
}
|
||||
],
|
||||
exec: createExec('tsfile mkdir')
|
||||
};
|
||||
|
||||
var tsfileRm = {
|
||||
item: 'command',
|
||||
name: 'tsfile rm',
|
||||
description: 'a file param in rm mode',
|
||||
params: [
|
||||
{
|
||||
name: 'p1',
|
||||
type: {
|
||||
name: 'file',
|
||||
filetype: 'any',
|
||||
existing: 'yes'
|
||||
}
|
||||
}
|
||||
],
|
||||
exec: createExec('tsfile rm')
|
||||
};
|
||||
|
||||
|
||||
|
||||
mockCommands.commands = {};
|
||||
|
||||
/**
|
||||
@ -533,6 +643,13 @@ mockCommands.setup = function(opts) {
|
||||
mockCommands.commands.tslong = canon.addCommand(tslong);
|
||||
mockCommands.commands.tsdate = canon.addCommand(tsdate);
|
||||
mockCommands.commands.tsfail = canon.addCommand(tsfail);
|
||||
mockCommands.commands.tsfile = canon.addCommand(tsfile);
|
||||
mockCommands.commands.tsfileOpen = canon.addCommand(tsfileOpen);
|
||||
mockCommands.commands.tsfileSaveas = canon.addCommand(tsfileSaveas);
|
||||
mockCommands.commands.tsfileSave = canon.addCommand(tsfileSave);
|
||||
mockCommands.commands.tsfileCd = canon.addCommand(tsfileCd);
|
||||
mockCommands.commands.tsfileMkdir = canon.addCommand(tsfileMkdir);
|
||||
mockCommands.commands.tsfileRm = canon.addCommand(tsfileRm);
|
||||
};
|
||||
|
||||
mockCommands.shutdown = function(opts) {
|
||||
@ -564,6 +681,13 @@ mockCommands.shutdown = function(opts) {
|
||||
canon.removeCommand(tslong);
|
||||
canon.removeCommand(tsdate);
|
||||
canon.removeCommand(tsfail);
|
||||
canon.removeCommand(tsfile);
|
||||
canon.removeCommand(tsfileOpen);
|
||||
canon.removeCommand(tsfileSaveas);
|
||||
canon.removeCommand(tsfileSave);
|
||||
canon.removeCommand(tsfileCd);
|
||||
canon.removeCommand(tsfileMkdir);
|
||||
canon.removeCommand(tsfileRm);
|
||||
|
||||
types.removeType(mockCommands.optionType);
|
||||
types.removeType(mockCommands.optionValue);
|
||||
|
@ -707,6 +707,7 @@ FilterView.prototype = {
|
||||
|
||||
this._searchbox = document.getElementById("searchbox");
|
||||
this._searchboxHelpPanel = document.getElementById("searchbox-help-panel");
|
||||
this._filterLabel = document.getElementById("filter-label");
|
||||
this._globalOperatorButton = document.getElementById("global-operator-button");
|
||||
this._globalOperatorLabel = document.getElementById("global-operator-label");
|
||||
this._functionOperatorButton = document.getElementById("function-operator-button");
|
||||
@ -737,6 +738,8 @@ FilterView.prototype = {
|
||||
this._lineOperatorButton.setAttribute("label", SEARCH_LINE_FLAG);
|
||||
this._variableOperatorButton.setAttribute("label", SEARCH_VARIABLE_FLAG);
|
||||
|
||||
this._filterLabel.setAttribute("value",
|
||||
L10N.getFormatStr("searchPanelFilter", this._fileSearchKey));
|
||||
this._globalOperatorLabel.setAttribute("value",
|
||||
L10N.getFormatStr("searchPanelGlobal", this._globalSearchKey));
|
||||
this._functionOperatorLabel.setAttribute("value",
|
||||
@ -780,7 +783,7 @@ FilterView.prototype = {
|
||||
placeholder = L10N.getFormatStr("emptyChromeGlobalsFilterText", this._fileSearchKey);
|
||||
break;
|
||||
case DebuggerView.Sources:
|
||||
placeholder = L10N.getFormatStr("emptyFilterText", this._fileSearchKey);
|
||||
placeholder = L10N.getFormatStr("emptySearchText", this._fileSearchKey);
|
||||
break;
|
||||
}
|
||||
this._searchbox.setAttribute("placeholder", placeholder);
|
||||
|
@ -310,8 +310,11 @@
|
||||
noautofocus="true"
|
||||
position="before_start">
|
||||
<vbox>
|
||||
<label id="searchbox-panel-description"
|
||||
value="&debuggerUI.searchPanelTitle;"/>
|
||||
<hbox>
|
||||
<label id="filter-label"/>
|
||||
</hbox>
|
||||
<label id="searchbox-panel-operators"
|
||||
value="&debuggerUI.searchPanelOperators;"/>
|
||||
<hbox align="center">
|
||||
<button id="global-operator-button"
|
||||
class="searchbox-panel-operator-button"
|
||||
|
@ -106,6 +106,8 @@ MOCHITEST_BROWSER_TESTS = \
|
||||
browser_dbg_source_maps-01.js \
|
||||
browser_dbg_source_maps-02.js \
|
||||
browser_dbg_step-out.js \
|
||||
browser_dbg_event-listeners.js \
|
||||
browser_dbg_break-on-dom-event.js \
|
||||
head.js \
|
||||
$(NULL)
|
||||
|
||||
@ -145,6 +147,7 @@ MOCHITEST_BROWSER_PAGES = \
|
||||
test-location-changes-bp.html \
|
||||
test-step-out.html \
|
||||
test-pause-exceptions-reload.html \
|
||||
test-event-listeners.html \
|
||||
$(NULL)
|
||||
|
||||
# Bug 888811 & bug 891176:
|
||||
|
158
browser/devtools/debugger/test/browser_dbg_break-on-dom-event.js
Normal file
158
browser/devtools/debugger/test/browser_dbg_break-on-dom-event.js
Normal file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
// Tests that the break-on-dom-events request works.
|
||||
|
||||
var gClient = null;
|
||||
var gTab = null;
|
||||
var gThreadClient = null;
|
||||
var gInput = null;
|
||||
var gButton = null;
|
||||
const DEBUGGER_TAB_URL = EXAMPLE_URL + "test-event-listeners.html";
|
||||
|
||||
function test()
|
||||
{
|
||||
let transport = DebuggerServer.connectPipe();
|
||||
gClient = new DebuggerClient(transport);
|
||||
gClient.connect(function(type, traits) {
|
||||
gTab = addTab(DEBUGGER_TAB_URL, function() {
|
||||
attach_thread_actor_for_url(gClient,
|
||||
DEBUGGER_TAB_URL,
|
||||
function(threadClient) {
|
||||
gThreadClient = threadClient;
|
||||
gInput = content.document.querySelector("input");
|
||||
gButton = content.document.querySelector("button");
|
||||
testBreakOnAll();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Test pause on all events.
|
||||
function testBreakOnAll()
|
||||
{
|
||||
gClient.addOneTimeListener("paused", function(event, packet) {
|
||||
is(packet.why.type, "debuggerStatement", "debugger statement was hit.");
|
||||
// Test calling pauseOnDOMEvents from a paused state.
|
||||
gThreadClient.pauseOnDOMEvents("*", function(packet) {
|
||||
is(packet, undefined, "The pause-on-any-event request completed successfully.");
|
||||
|
||||
gClient.addOneTimeListener("paused", function(event, packet) {
|
||||
is(packet.why.type, "pauseOnDOMEvents", "A hidden breakpoint was hit.");
|
||||
is(packet.frame.callee.name, "keyupHandler", "The keyupHandler is entered.");
|
||||
|
||||
gThreadClient.resume(function() {
|
||||
gClient.addOneTimeListener("paused", function(event, packet) {
|
||||
is(packet.why.type, "pauseOnDOMEvents", "A hidden breakpoint was hit.");
|
||||
is(packet.frame.callee.name, "clickHandler", "The clickHandler is entered.");
|
||||
|
||||
gThreadClient.resume(function() {
|
||||
gClient.addOneTimeListener("paused", function(event, packet) {
|
||||
is(packet.why.type, "pauseOnDOMEvents", "A hidden breakpoint was hit.");
|
||||
is(packet.frame.callee.name, "onchange", "The onchange handler is entered.");
|
||||
|
||||
gThreadClient.resume(testBreakOnDisabled);
|
||||
});
|
||||
|
||||
gInput.focus();
|
||||
gInput.value = "foo";
|
||||
gInput.blur();
|
||||
});
|
||||
});
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "click" }, gButton);
|
||||
});
|
||||
});
|
||||
|
||||
gThreadClient.resume(function() {
|
||||
gInput.focus();
|
||||
EventUtils.synthesizeKey("e", {}, content);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "click" }, gButton);
|
||||
}
|
||||
|
||||
// Test that removing events from the array disables them.
|
||||
function testBreakOnDisabled()
|
||||
{
|
||||
// Test calling pauseOnDOMEvents from a running state.
|
||||
gThreadClient.pauseOnDOMEvents(["click"], function(packet) {
|
||||
is(packet.error, undefined, "The pause-on-click-only request completed successfully.");
|
||||
|
||||
gClient.addListener("paused", unexpectedListener);
|
||||
|
||||
// This non-capturing event listener is guaranteed to run after the page's
|
||||
// capturing one had a chance to execute and modify window.foobar.
|
||||
gInput.addEventListener("keyup", function tempHandler() {
|
||||
gInput.removeEventListener("keyup", tempHandler, false);
|
||||
is(content.wrappedJSObject.foobar, "keyupHandler", "No hidden breakpoint was hit.");
|
||||
gClient.removeListener("paused", unexpectedListener);
|
||||
testBreakOnNone();
|
||||
}, false);
|
||||
|
||||
gInput.focus();
|
||||
EventUtils.synthesizeKey("e", {}, content);
|
||||
});
|
||||
}
|
||||
|
||||
// Test that specifying an empty event array clears all hidden breakpoints.
|
||||
function testBreakOnNone()
|
||||
{
|
||||
// Test calling pauseOnDOMEvents from a running state.
|
||||
gThreadClient.pauseOnDOMEvents([], function(packet) {
|
||||
is(packet.error, undefined, "The pause-on-none request completed successfully.");
|
||||
|
||||
gClient.addListener("paused", unexpectedListener);
|
||||
|
||||
// This non-capturing event listener is guaranteed to run after the page's
|
||||
// capturing one had a chance to execute and modify window.foobar.
|
||||
gInput.addEventListener("keyup", function tempHandler() {
|
||||
gInput.removeEventListener("keyup", tempHandler, false);
|
||||
is(content.wrappedJSObject.foobar, "keyupHandler", "No hidden breakpoint was hit.");
|
||||
gClient.removeListener("paused", unexpectedListener);
|
||||
testBreakOnClick();
|
||||
}, false);
|
||||
|
||||
gInput.focus();
|
||||
EventUtils.synthesizeKey("g", {}, content);
|
||||
});
|
||||
}
|
||||
|
||||
function unexpectedListener(event, packet, callback) {
|
||||
gClient.removeListener("paused", unexpectedListener);
|
||||
ok(false, "An unexpected hidden breakpoint was hit.");
|
||||
gThreadClient.resume(testBreakOnClick);
|
||||
}
|
||||
|
||||
// Test pause on a single event.
|
||||
function testBreakOnClick()
|
||||
{
|
||||
// Test calling pauseOnDOMEvents from a running state.
|
||||
gThreadClient.pauseOnDOMEvents(["click"], function(packet) {
|
||||
is(packet.error, undefined, "The pause-on-click request completed successfully.");
|
||||
|
||||
gClient.addOneTimeListener("paused", function(event, packet) {
|
||||
is(packet.why.type, "pauseOnDOMEvents", "A hidden breakpoint was hit.");
|
||||
is(packet.frame.callee.name, "clickHandler", "The clickHandler is entered.");
|
||||
|
||||
gThreadClient.resume(function() {
|
||||
gClient.close(finish);
|
||||
});
|
||||
});
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "click" }, gButton);
|
||||
});
|
||||
}
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
removeTab(gTab);
|
||||
gTab = null;
|
||||
gClient = null;
|
||||
gThreadClient = null;
|
||||
gInput = null;
|
||||
gButton = null;
|
||||
});
|
@ -54,35 +54,33 @@ function test() {
|
||||
cmd("dbg step out", function() {
|
||||
is(output.value, "step out", "debugger stepped out");
|
||||
cmd("dbg continue", function() {
|
||||
cmd("dbg continue", function() {
|
||||
is(output.value, "dbg continue", "debugger continued");
|
||||
is(output.value, "dbg continue", "debugger continued");
|
||||
|
||||
function closeDebugger(cb) {
|
||||
helpers.audit(options, [{
|
||||
setup: "dbg close",
|
||||
completed: false,
|
||||
exec: { output: "" }
|
||||
}]);
|
||||
function closeDebugger(cb) {
|
||||
helpers.audit(options, [{
|
||||
setup: "dbg close",
|
||||
completed: false,
|
||||
exec: { output: "" }
|
||||
}]);
|
||||
|
||||
let toolbox = gDevTools.getToolbox(options.target);
|
||||
if (!toolbox) {
|
||||
let toolbox = gDevTools.getToolbox(options.target);
|
||||
if (!toolbox) {
|
||||
ok(true, "Debugger was closed.");
|
||||
cb();
|
||||
} else {
|
||||
toolbox.on("destroyed", function () {
|
||||
ok(true, "Debugger was closed.");
|
||||
cb();
|
||||
} else {
|
||||
toolbox.on("destroyed", function () {
|
||||
ok(true, "Debugger was closed.");
|
||||
cb();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// We're closing the debugger twice to make sure
|
||||
// 'dbg close' doesn't error when toolbox is already
|
||||
// closed. See bug 884638 for more info.
|
||||
// We're closing the debugger twice to make sure
|
||||
// 'dbg close' doesn't error when toolbox is already
|
||||
// closed. See bug 884638 for more info.
|
||||
|
||||
closeDebugger(() => {
|
||||
closeDebugger(() => deferred.resolve());
|
||||
});
|
||||
closeDebugger(() => {
|
||||
closeDebugger(() => deferred.resolve());
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
// Tests that the eventListeners request works.
|
||||
|
||||
var gClient = null;
|
||||
var gTab = null;
|
||||
var gThreadClient = null;
|
||||
const DEBUGGER_TAB_URL = EXAMPLE_URL + "test-event-listeners.html";
|
||||
|
||||
function test()
|
||||
{
|
||||
let transport = DebuggerServer.connectPipe();
|
||||
gClient = new DebuggerClient(transport);
|
||||
gClient.connect(function(aType, aTraits) {
|
||||
gTab = addTab(DEBUGGER_TAB_URL, function() {
|
||||
attach_thread_actor_for_url(gClient,
|
||||
DEBUGGER_TAB_URL,
|
||||
function(threadClient) {
|
||||
gThreadClient = threadClient;
|
||||
testEventListeners();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function testEventListeners()
|
||||
{
|
||||
gClient.addOneTimeListener("paused", function(aEvent, aPacket) {
|
||||
is(aPacket.why.type, "debuggerStatement", "debugger statement was hit.");
|
||||
gThreadClient.eventListeners(function(aPacket) {
|
||||
is(aPacket.listeners.length, 4, "Found all event listeners.");
|
||||
let types = [];
|
||||
for (let l of aPacket.listeners) {
|
||||
let node = l.node;
|
||||
ok(node, "There is a node property.");
|
||||
ok(node.object, "There is a node object property.");
|
||||
ok(node.selector == "window" ||
|
||||
content.document.querySelectorAll(node.selector).length == 1,
|
||||
"The node property is a unique CSS selector");
|
||||
ok(l.function, "There is a function property.");
|
||||
is(l.function.type, "object", "The function form is of type 'object'.");
|
||||
is(l.function.class, "Function", "The function form is of class 'Function'.");
|
||||
is(l.function.url, DEBUGGER_TAB_URL, "The function url is correct.");
|
||||
is(l.allowsUntrusted, true,
|
||||
"allowsUntrusted property has the right value.");
|
||||
is(l.inSystemEventGroup, false,
|
||||
"inSystemEventGroup property has the right value.");
|
||||
|
||||
types.push(l.type);
|
||||
|
||||
if (l.type == "keyup") {
|
||||
is(l.capturing, true, "Capturing property has the right value.");
|
||||
is(l.isEventHandler, false,
|
||||
"isEventHandler property has the right value.");
|
||||
} else if (l.type == "load") {
|
||||
is(l.capturing, false, "Capturing property has the right value.");
|
||||
is(l.isEventHandler, false,
|
||||
"isEventHandler property has the right value.");
|
||||
} else {
|
||||
is(l.capturing, false, "Capturing property has the right value.");
|
||||
is(l.isEventHandler, true,
|
||||
"isEventHandler property has the right value.");
|
||||
}
|
||||
}
|
||||
ok(types.indexOf("click") != -1, "Found the click handler.");
|
||||
ok(types.indexOf("change") != -1, "Found the change handler.");
|
||||
ok(types.indexOf("keyup") != -1, "Found the keyup handler.");
|
||||
finish_test();
|
||||
});
|
||||
});
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "click" },
|
||||
content.document.querySelector("button"));
|
||||
}
|
||||
|
||||
function finish_test()
|
||||
{
|
||||
gThreadClient.resume(function() {
|
||||
gClient.close(finish);
|
||||
});
|
||||
}
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
removeTab(gTab);
|
||||
gTab = null;
|
||||
gClient = null;
|
||||
gThreadClient = null;
|
||||
});
|
@ -37,6 +37,13 @@ let gEnableLogging = Services.prefs.getBoolPref("devtools.debugger.log");
|
||||
Services.prefs.setBoolPref("devtools.debugger.remote-enabled", true);
|
||||
Services.prefs.setBoolPref("devtools.debugger.log", true);
|
||||
|
||||
// Redeclare dbg_assert with a fatal behavior.
|
||||
function dbg_assert(cond, e) {
|
||||
if (!cond) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
Services.prefs.setBoolPref("devtools.debugger.remote-enabled", gEnableRemote);
|
||||
Services.prefs.setBoolPref("devtools.debugger.log", gEnableLogging);
|
||||
@ -143,11 +150,11 @@ function attach_tab_actor_for_url(aClient, aURL, aCallback) {
|
||||
|
||||
function attach_thread_actor_for_url(aClient, aURL, aCallback) {
|
||||
attach_tab_actor_for_url(aClient, aURL, function(aTabActor, aResponse) {
|
||||
aClient.attachThread(actor.threadActor, function(aResponse, aThreadClient) {
|
||||
aClient.attachThread(aResponse.threadActor, function(aResponse, aThreadClient) {
|
||||
// We don't care about the pause right now (use
|
||||
// get_actor_for_url() if you do), so resume it.
|
||||
aThreadClient.resume(function(aResponse) {
|
||||
aCallback(actor);
|
||||
aCallback(aThreadClient);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user