Merge from mozilla-central.

--HG--
rename : accessible/src/msaa/CAccessibleText.cpp => accessible/src/msaa/ia2AccessibleText.cpp
rename : accessible/src/msaa/CAccessibleText.h => accessible/src/msaa/ia2AccessibleText.h
This commit is contained in:
David Anderson 2012-06-20 17:36:56 -07:00
commit 99dd2a9400
786 changed files with 17799 additions and 8815 deletions

View File

@ -166,6 +166,7 @@ endif
OBJCOPY="$(OBJCOPY)" \
$(PYTHON) $(topsrcdir)/toolkit/crashreporter/tools/symbolstore.py \
$(MAKE_SYM_STORE_ARGS) \
--exclude="*test*" --exclude="*Test*" \
$(foreach dir,$(SYM_STORE_SOURCE_DIRS),-s $(dir)) \
$(DUMP_SYMS_BIN) \
$(DIST)/crashreporter-symbols \

View File

@ -88,7 +88,7 @@ AccEvent::CreateXPCOMObject()
////////////////////////////////////////////////////////////////////////////////
// AccEvent cycle collection
NS_IMPL_CYCLE_COLLECTION_CLASS(AccEvent)
NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(AccEvent)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(AccEvent)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mAccessible)

View File

@ -56,7 +56,7 @@ NotificationController::~NotificationController()
NS_IMPL_ADDREF(NotificationController)
NS_IMPL_RELEASE(NotificationController)
NS_IMPL_CYCLE_COLLECTION_CLASS(NotificationController)
NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(NotificationController)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(NotificationController)
if (tmp->mDocument)
@ -812,7 +812,7 @@ NotificationController::ContentInsertion::
return haveToUpdate;
}
NS_IMPL_CYCLE_COLLECTION_CLASS(NotificationController::ContentInsertion)
NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(NotificationController::ContentInsertion)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(NotificationController::ContentInsertion)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mContainer)

View File

@ -47,7 +47,7 @@ StyleInfo::TextIndent(nsAString& aValue)
const nsStyleCoord& styleCoord =
mStyleContext->GetStyleText()->mTextIndent;
nscoord coordVal;
nscoord coordVal = 0;
switch (styleCoord.GetUnit()) {
case eStyleUnit_Coord:
coordVal = styleCoord.GetCoordValue();
@ -62,6 +62,20 @@ StyleInfo::TextIndent(nsAString& aValue)
styleCoord.GetPercentValue());
break;
}
case eStyleUnit_Null:
case eStyleUnit_Normal:
case eStyleUnit_Auto:
case eStyleUnit_None:
case eStyleUnit_Factor:
case eStyleUnit_Degree:
case eStyleUnit_Grad:
case eStyleUnit_Radian:
case eStyleUnit_Turn:
case eStyleUnit_Integer:
case eStyleUnit_Enumerated:
case eStyleUnit_Calc:
break;
}
aValue.AppendFloat(nsPresContext::AppUnitsToFloatCSSPixels(coordVal));

View File

@ -707,6 +707,9 @@ TextAttrsMgr::TextPosTextAttr::
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textPosition,
NS_LITERAL_STRING("super"));
break;
case eTextPosNone:
break;
}
}
@ -754,6 +757,19 @@ TextAttrsMgr::TextPosTextAttr::
eTextPosSuper :
(coordValue < 0 ? eTextPosSub : eTextPosBaseline);
}
case eStyleUnit_Null:
case eStyleUnit_Normal:
case eStyleUnit_Auto:
case eStyleUnit_None:
case eStyleUnit_Factor:
case eStyleUnit_Degree:
case eStyleUnit_Grad:
case eStyleUnit_Radian:
case eStyleUnit_Turn:
case eStyleUnit_Integer:
case eStyleUnit_Calc:
break;
}
const nsIContent* content = aFrame->GetContent();

View File

@ -63,6 +63,7 @@
#include "nsTextFragment.h"
#include "mozilla/FunctionTimer.h"
#include "mozilla/dom/Element.h"
#include "mozilla/Preferences.h"
#include "mozilla/Services.h"
#include "mozilla/Util.h"
@ -1819,8 +1820,30 @@ nsAccessibilityService::CreateAccessibleForXULTree(nsIContent* aContent,
// Services
////////////////////////////////////////////////////////////////////////////////
mozilla::a11y::FocusManager*
mozilla::a11y::FocusMgr()
namespace mozilla {
namespace a11y {
FocusManager*
FocusMgr()
{
return nsAccessibilityService::gAccessibilityService;
}
EPlatformDisabledState
PlatformDisabledState()
{
static int disabledState = 0xff;
if (disabledState == 0xff) {
disabledState = Preferences::GetInt("accessibility.force_disabled", 0);
if (disabledState < ePlatformIsForceEnabled)
disabledState = ePlatformIsForceEnabled;
else if (disabledState > ePlatformIsDisabled)
disabledState = ePlatformIsDisabled;
}
return (EPlatformDisabledState)disabledState;
}
}
}

View File

@ -26,6 +26,17 @@ namespace a11y {
*/
FocusManager* FocusMgr();
enum EPlatformDisabledState {
ePlatformIsForceEnabled = -1,
ePlatformIsEnabled = 0,
ePlatformIsDisabled = 1
};
/**
* Return the platform disabled state.
*/
EPlatformDisabledState PlatformDisabledState();
#ifdef MOZ_ACCESSIBILITY_ATK
/**
* Perform initialization that should be done as soon as possible, in order

View File

@ -118,7 +118,7 @@ nsAccessiblePivot::SetPosition(nsIAccessible* aPosition)
mPosition.swap(secondPosition);
PRInt32 oldStart = mStartOffset, oldEnd = mEndOffset;
mStartOffset = mEndOffset = -1;
NotifyPivotChanged(secondPosition, oldStart, oldEnd);
NotifyOfPivotChange(secondPosition, oldStart, oldEnd);
return NS_OK;
}
@ -155,7 +155,11 @@ nsAccessiblePivot::SetTextRange(nsIAccessibleText* aTextAccessible,
(aStartOffset >= 0 || (aStartOffset != -1 && aEndOffset != -1)),
NS_ERROR_INVALID_ARG);
nsRefPtr<HyperTextAccessible> newPosition = do_QueryObject(aTextAccessible);
nsRefPtr<Accessible> acc(do_QueryObject(aTextAccessible));
if (!acc)
return NS_ERROR_INVALID_ARG;
HyperTextAccessible* newPosition = acc->AsHyperText();
if (!newPosition || !IsRootDescendant(newPosition))
return NS_ERROR_INVALID_ARG;
@ -170,9 +174,9 @@ nsAccessiblePivot::SetTextRange(nsIAccessibleText* aTextAccessible,
mEndOffset = aEndOffset;
nsRefPtr<Accessible> oldPosition = mPosition.forget();
mPosition = newPosition.forget();
mPosition = newPosition;
NotifyPivotChanged(oldPosition, oldStart, oldEnd);
NotifyOfPivotChange(oldPosition, oldStart, oldEnd);
return NS_OK;
}
@ -199,9 +203,8 @@ nsAccessiblePivot::MoveNext(nsIAccessibleTraversalRule* aRule,
SearchForward(anchor, aRule, (aArgc > 1) ? aIncludeStart : false, &rv);
NS_ENSURE_SUCCESS(rv, rv);
*aResult = accessible;
if (*aResult)
MovePivotInternal(accessible);
if (accessible)
*aResult = MovePivotInternal(accessible);
return NS_OK;
}
@ -227,9 +230,8 @@ nsAccessiblePivot::MovePrevious(nsIAccessibleTraversalRule* aRule,
SearchBackward(anchor, aRule, (aArgc > 1) ? aIncludeStart : false, &rv);
NS_ENSURE_SUCCESS(rv, rv);
*aResult = accessible;
if (*aResult)
MovePivotInternal(accessible);
if (accessible)
*aResult = MovePivotInternal(accessible);
return NS_OK;
}
@ -247,9 +249,8 @@ nsAccessiblePivot::MoveFirst(nsIAccessibleTraversalRule* aRule, bool* aResult)
Accessible* accessible = SearchForward(mRoot, aRule, true, &rv);
NS_ENSURE_SUCCESS(rv, rv);
*aResult = accessible;
if (*aResult)
MovePivotInternal(accessible);
if (accessible)
*aResult = MovePivotInternal(accessible);
return NS_OK;
}
@ -276,9 +277,8 @@ nsAccessiblePivot::MoveLast(nsIAccessibleTraversalRule* aRule, bool* aResult)
accessible = SearchBackward(lastAccessible, aRule, true, &rv);
NS_ENSURE_SUCCESS(rv, rv);
*aResult = accessible;
if (*aResult)
MovePivotInternal(accessible);
if (accessible)
*aResult = MovePivotInternal(accessible);
return NS_OK;
}
@ -343,7 +343,7 @@ nsAccessiblePivot::IsRootDescendant(Accessible* aAccessible)
return false;
}
void
bool
nsAccessiblePivot::MovePivotInternal(Accessible* aPosition)
{
nsRefPtr<Accessible> oldPosition = mPosition.forget();
@ -351,7 +351,7 @@ nsAccessiblePivot::MovePivotInternal(Accessible* aPosition)
PRInt32 oldStart = mStartOffset, oldEnd = mEndOffset;
mStartOffset = mEndOffset = -1;
NotifyPivotChanged(oldPosition, oldStart, oldEnd);
return NotifyOfPivotChange(oldPosition, oldStart, oldEnd);
}
Accessible*
@ -472,15 +472,21 @@ nsAccessiblePivot::SearchForward(Accessible* aAccessible,
return nsnull;
}
void
nsAccessiblePivot::NotifyPivotChanged(Accessible* aOldPosition,
PRInt32 aOldStart, PRInt32 aOldEnd)
bool
nsAccessiblePivot::NotifyOfPivotChange(Accessible* aOldPosition,
PRInt32 aOldStart, PRInt32 aOldEnd)
{
if (aOldPosition == mPosition &&
aOldStart == mStartOffset && aOldEnd == mEndOffset)
return false;
nsTObserverArray<nsCOMPtr<nsIAccessiblePivotObserver> >::ForwardIterator iter(mObservers);
while (iter.HasMore()) {
nsIAccessiblePivotObserver* obs = iter.GetNext();
obs->OnPivotChanged(this, aOldPosition, aOldStart, aOldEnd);
}
return true;
}
nsresult

View File

@ -44,10 +44,11 @@ private:
void operator = (const nsAccessiblePivot&) MOZ_DELETE;
/*
* Notify all observers on a pivot change.
* Notify all observers on a pivot change. Return true if it has changed and
* observers have been notified.
*/
void NotifyPivotChanged(Accessible* aOldAccessible,
PRInt32 aOldStart, PRInt32 aOldEnd);
bool NotifyOfPivotChange(Accessible* aOldAccessible,
PRInt32 aOldStart, PRInt32 aOldEnd);
/*
* Check to see that the given accessible is in the pivot's subtree.
@ -72,9 +73,9 @@ private:
nsresult* aResult);
/*
* Update the pivot, and notify observers.
* Update the pivot, and notify observers. Return true if it moved.
*/
void MovePivotInternal(Accessible* aPosition);
bool MovePivotInternal(Accessible* aPosition);
/*
* The root accessible.

View File

@ -492,5 +492,12 @@ PRUint32 nsTextEquivUtils::gRoleToNameRulesMap[] =
eFromSubtree, // ROLE_RICH_OPTION
eNoRule, // ROLE_LISTBOX
eNoRule, // ROLE_FLAT_EQUATION
eFromSubtree // ROLE_GRID_CELL
eFromSubtree, // ROLE_GRID_CELL
eNoRule, // ROLE_EMBEDDED_OBJECT
eFromSubtree, // ROLE_NOTE
eNoRule, // ROLE_FIGURE
eFromSubtree, // ROLE_CHECK_RICH_OPTION
eFromSubtreeIfRec, // ROLE_DEFINITION_LIST
eFromSubtree, // ROLE_TERM
eFromSubtree // ROLE_DEFINITION
};

View File

@ -165,114 +165,58 @@ ARIAGridAccessible::GetRowAndColumnIndicesAt(PRInt32 aCellIndex,
return NS_OK;
}
NS_IMETHODIMP
ARIAGridAccessible::GetColumnDescription(PRInt32 aColumn,
nsAString& aDescription)
bool
ARIAGridAccessible::IsColSelected(PRUint32 aColIdx)
{
aDescription.Truncate();
if (IsDefunct())
return NS_ERROR_FAILURE;
NS_ENSURE_ARG(IsValidColumn(aColumn));
// XXX: not implemented
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
ARIAGridAccessible::GetRowDescription(PRInt32 aRow, nsAString& aDescription)
{
aDescription.Truncate();
if (IsDefunct())
return NS_ERROR_FAILURE;
NS_ENSURE_ARG(IsValidRow(aRow));
// XXX: not implemented
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
ARIAGridAccessible::IsColumnSelected(PRInt32 aColumn, bool* aIsSelected)
{
NS_ENSURE_ARG_POINTER(aIsSelected);
*aIsSelected = false;
if (IsDefunct())
return NS_ERROR_FAILURE;
NS_ENSURE_ARG(IsValidColumn(aColumn));
AccIterator rowIter(this, filters::GetRow);
Accessible* row = rowIter.Next();
if (!row)
return NS_OK;
return false;
do {
if (!nsAccUtils::IsARIASelected(row)) {
Accessible* cell = GetCellInRowAt(row, aColumn);
if (!cell) // Do not fail due to wrong markup
return NS_OK;
if (!nsAccUtils::IsARIASelected(cell))
return NS_OK;
Accessible* cell = GetCellInRowAt(row, aColIdx);
if (!cell || !nsAccUtils::IsARIASelected(cell))
return false;
}
} while ((row = rowIter.Next()));
*aIsSelected = true;
return NS_OK;
return true;
}
NS_IMETHODIMP
ARIAGridAccessible::IsRowSelected(PRInt32 aRow, bool* aIsSelected)
bool
ARIAGridAccessible::IsRowSelected(PRUint32 aRowIdx)
{
NS_ENSURE_ARG_POINTER(aIsSelected);
*aIsSelected = false;
if (IsDefunct())
return NS_ERROR_FAILURE;
Accessible* row = GetRowAt(aRow);
NS_ENSURE_ARG(row);
Accessible* row = GetRowAt(aRowIdx);
if(!row)
return false;
if (!nsAccUtils::IsARIASelected(row)) {
AccIterator cellIter(row, filters::GetCell);
Accessible* cell = nsnull;
while ((cell = cellIter.Next())) {
if (!nsAccUtils::IsARIASelected(cell))
return NS_OK;
return false;
}
}
*aIsSelected = true;
return NS_OK;
return true;
}
NS_IMETHODIMP
ARIAGridAccessible::IsCellSelected(PRInt32 aRow, PRInt32 aColumn,
bool* aIsSelected)
bool
ARIAGridAccessible::IsCellSelected(PRUint32 aRowIdx, PRUint32 aColIdx)
{
NS_ENSURE_ARG_POINTER(aIsSelected);
*aIsSelected = false;
if (IsDefunct())
return NS_ERROR_FAILURE;
Accessible* row = GetRowAt(aRow);
NS_ENSURE_ARG(row);
Accessible* row = GetRowAt(aRowIdx);
if(!row)
return false;
if (!nsAccUtils::IsARIASelected(row)) {
Accessible* cell = GetCellInRowAt(row, aColumn);
NS_ENSURE_ARG(cell);
if (!nsAccUtils::IsARIASelected(cell))
return NS_OK;
Accessible* cell = GetCellInRowAt(row, aColIdx);
if (!cell || !nsAccUtils::IsARIASelected(cell))
return false;
}
*aIsSelected = true;
return NS_OK;
return true;
}
NS_IMETHODIMP

View File

@ -33,7 +33,7 @@ public:
NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE
// Accessible
virtual mozilla::a11y::TableAccessible* AsTable() { return this; }
virtual TableAccessible* AsTable() { return this; }
// nsAccessNode
virtual void Shutdown();
@ -42,6 +42,9 @@ public:
virtual PRUint32 ColCount();
virtual PRUint32 RowCount();
virtual Accessible* CellAt(PRUint32 aRowIndex, PRUint32 aColumnIndex);
virtual bool IsColSelected(PRUint32 aColIdx);
virtual bool IsRowSelected(PRUint32 aRowIdx);
virtual bool IsCellSelected(PRUint32 aRowIdx, PRUint32 aColIdx);
virtual void SelectCol(PRUint32 aColIdx);
virtual void SelectRow(PRUint32 aRowIdx);
virtual void UnselectCol(PRUint32 aColIdx);

View File

@ -111,7 +111,7 @@ Accessible::QueryInterface(REFNSIID aIID, void** aInstancePtr)
*aInstancePtr = nsnull;
if (aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant))) {
*aInstancePtr = &NS_CYCLE_COLLECTION_NAME(Accessible);
*aInstancePtr = NS_CYCLE_COLLECTION_PARTICIPANT(Accessible);
return NS_OK;
}

View File

@ -55,12 +55,6 @@ HyperTextAccessible::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
*aInstancePtr = nsnull;
if (aIID.Equals(NS_GET_IID(HyperTextAccessible))) {
*aInstancePtr = static_cast<HyperTextAccessible*>(this);
NS_ADDREF_THIS();
return NS_OK;
}
// ARIA roles that these interfaces are not appropriate for.
if (!IsTextRole())
return Accessible::QueryInterface(aIID, aInstancePtr);

View File

@ -24,14 +24,6 @@ const PRUnichar kEmbeddedObjectChar = 0xfffc;
const PRUnichar kImaginaryEmbeddedObjectChar = ' ';
const PRUnichar kForcedNewLineChar = '\n';
#define NS_HYPERTEXTACCESSIBLE_IMPL_CID \
{ /* 245f3bc9-224f-4839-a92e-95239705f30b */ \
0x245f3bc9, \
0x224f, \
0x4839, \
{ 0xa9, 0x2e, 0x95, 0x23, 0x97, 0x05, 0xf3, 0x0b } \
}
/**
* Special Accessible that knows how contain both text and embedded objects
*/
@ -48,7 +40,6 @@ public:
NS_DECL_NSIACCESSIBLETEXT
NS_DECL_NSIACCESSIBLEHYPERTEXT
NS_DECL_NSIACCESSIBLEEDITABLETEXT
NS_DECLARE_STATIC_IID_ACCESSOR(NS_HYPERTEXTACCESSIBLE_IMPL_CID)
// Accessible
virtual PRInt32 GetLevelInternal();
@ -410,9 +401,6 @@ private:
nsTArray<PRUint32> mOffsets;
};
NS_DEFINE_STATIC_IID_ACCESSOR(HyperTextAccessible,
NS_HYPERTEXTACCESSIBLE_IMPL_CID)
////////////////////////////////////////////////////////////////////////////////
// Accessible downcasting method

View File

@ -324,9 +324,8 @@ HTMLTextFieldAccessible::
{
}
NS_IMPL_ISUPPORTS_INHERITED3(HTMLTextFieldAccessible,
Accessible,
HyperTextAccessible,
NS_IMPL_ISUPPORTS_INHERITED2(HTMLTextFieldAccessible,
Accessible,
nsIAccessibleText,
nsIAccessibleEditableText)

View File

@ -972,108 +972,62 @@ HTMLTableAccessible::RowExtentAt(PRUint32 aRowIdx, PRUint32 aColIdx)
return rowExtent;
}
NS_IMETHODIMP
HTMLTableAccessible::GetColumnDescription(PRInt32 aColumn, nsAString& _retval)
bool
HTMLTableAccessible::IsColSelected(PRUint32 aColIdx)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
bool isSelected = false;
NS_IMETHODIMP
HTMLTableAccessible::GetRowDescription(PRInt32 aRow, nsAString& _retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
HTMLTableAccessible::IsColumnSelected(PRInt32 aColumn, bool* aIsSelected)
{
NS_ENSURE_ARG_POINTER(aIsSelected);
*aIsSelected = false;
PRInt32 colCount = 0;
nsresult rv = GetColumnCount(&colCount);
NS_ENSURE_SUCCESS(rv, rv);
if (aColumn < 0 || aColumn >= colCount)
return NS_ERROR_INVALID_ARG;
PRInt32 rowCount = 0;
rv = GetRowCount(&rowCount);
NS_ENSURE_SUCCESS(rv, rv);
for (PRInt32 rowIdx = 0; rowIdx < rowCount; rowIdx++) {
bool isSelected = false;
rv = IsCellSelected(rowIdx, aColumn, &isSelected);
if (NS_SUCCEEDED(rv)) {
*aIsSelected = isSelected;
if (!isSelected)
break;
}
PRUint32 rowCount = RowCount();
for (PRUint32 rowIdx = 0; rowIdx < rowCount; rowIdx++) {
isSelected = IsCellSelected(rowIdx, aColIdx);
if (!isSelected)
return false;
}
return NS_OK;
return isSelected;
}
NS_IMETHODIMP
HTMLTableAccessible::IsRowSelected(PRInt32 aRow, bool* aIsSelected)
bool
HTMLTableAccessible::IsRowSelected(PRUint32 aRowIdx)
{
NS_ENSURE_ARG_POINTER(aIsSelected);
*aIsSelected = false;
bool isSelected = false;
PRInt32 rowCount = 0;
nsresult rv = GetRowCount(&rowCount);
NS_ENSURE_SUCCESS(rv, rv);
if (aRow < 0 || aRow >= rowCount)
return NS_ERROR_INVALID_ARG;
PRInt32 colCount = 0;
rv = GetColumnCount(&colCount);
NS_ENSURE_SUCCESS(rv, rv);
for (PRInt32 colIdx = 0; colIdx < colCount; colIdx++) {
bool isSelected = false;
rv = IsCellSelected(aRow, colIdx, &isSelected);
if (NS_SUCCEEDED(rv)) {
*aIsSelected = isSelected;
if (!isSelected)
break;
}
PRUint32 colCount = ColCount();
for (PRUint32 colIdx = 0; colIdx < colCount; colIdx++) {
isSelected = IsCellSelected(aRowIdx, colIdx);
if (!isSelected)
return false;
}
return NS_OK;
return isSelected;
}
NS_IMETHODIMP
HTMLTableAccessible::IsCellSelected(PRInt32 aRow, PRInt32 aColumn,
bool* aIsSelected)
bool
HTMLTableAccessible::IsCellSelected(PRUint32 aRowIdx, PRUint32 aColIdx)
{
NS_ENSURE_ARG_POINTER(aIsSelected);
*aIsSelected = false;
nsITableLayout *tableLayout = GetTableLayout();
NS_ENSURE_STATE(tableLayout);
if (!tableLayout)
return false;
nsCOMPtr<nsIDOMElement> domElement;
PRInt32 startRowIndex = 0, startColIndex = 0,
rowSpan, colSpan, actualRowSpan, actualColSpan;
bool isSelected = false;
nsresult rv = tableLayout->
GetCellDataAt(aRow, aColumn, *getter_AddRefs(domElement),
startRowIndex, startColIndex, rowSpan, colSpan,
actualRowSpan, actualColSpan, *aIsSelected);
tableLayout->GetCellDataAt(aRowIdx, aColIdx, *getter_AddRefs(domElement),
startRowIndex, startColIndex, rowSpan, colSpan,
actualRowSpan, actualColSpan, isSelected);
if (rv == NS_TABLELAYOUT_CELL_NOT_FOUND)
return NS_ERROR_INVALID_ARG;
return rv;
return isSelected;
}
void
HTMLTableAccessible::SelectRow(PRUint32 aRowIdx)
{
nsresult rv = RemoveRowsOrColumnsFromSelection(aRowIdx,
nsISelectionPrivate::TABLESELECTION_ROW,
true);
nsresult rv =
RemoveRowsOrColumnsFromSelection(aRowIdx,
nsISelectionPrivate::TABLESELECTION_ROW,
true);
NS_ASSERTION(NS_SUCCEEDED(rv),
"RemoveRowsOrColumnsFromSelection() Shouldn't fail!");
@ -1083,9 +1037,10 @@ HTMLTableAccessible::SelectRow(PRUint32 aRowIdx)
void
HTMLTableAccessible::SelectCol(PRUint32 aColIdx)
{
nsresult rv = RemoveRowsOrColumnsFromSelection(aColIdx,
nsISelectionPrivate::TABLESELECTION_COLUMN,
true);
nsresult rv =
RemoveRowsOrColumnsFromSelection(aColIdx,
nsISelectionPrivate::TABLESELECTION_COLUMN,
true);
NS_ASSERTION(NS_SUCCEEDED(rv),
"RemoveRowsOrColumnsFromSelection() Shouldn't fail!");
@ -1446,7 +1401,8 @@ HTMLTableAccessible::IsProbablyLayoutTable()
// Check for styled background color across rows (alternating background
// color is a common feature for data tables).
PRUint32 childCount = ChildCount();
nscolor rowColor, prevRowColor;
nscolor rowColor = 0;
nscolor prevRowColor;
for (PRUint32 childIdx = 0; childIdx < childCount; childIdx++) {
Accessible* child = GetChildAt(childIdx);
if (child->Role() == roles::ROW) {

View File

@ -106,6 +106,9 @@ public:
virtual PRInt32 CellIndexAt(PRUint32 aRowIdx, PRUint32 aColIdx);
virtual PRUint32 ColExtentAt(PRUint32 aRowIdx, PRUint32 aColIdx);
virtual PRUint32 RowExtentAt(PRUint32 aRowIdx, PRUint32 aColIdx);
virtual bool IsColSelected(PRUint32 aColIdx);
virtual bool IsRowSelected(PRUint32 aRowIdx);
virtual bool IsCellSelected(PRUint32 aRowIdx, PRUint32 aColIdx);
virtual void SelectCol(PRUint32 aColIdx);
virtual void SelectRow(PRUint32 aRowIdx);
virtual void UnselectCol(PRUint32 aColIdx);
@ -116,7 +119,7 @@ public:
virtual void Shutdown();
// Accessible
virtual mozilla::a11y::TableAccessible* AsTable() { return this; }
virtual TableAccessible* AsTable() { return this; }
virtual void Description(nsString& aDescription);
virtual nsresult GetNameInternal(nsAString& aName);
virtual a11y::role NativeRole();

View File

@ -304,7 +304,9 @@ AndroidPresenter.prototype = {
type: 'Accessibility:Event',
eventType: this.ANDROID_VIEW_TEXT_CHANGED,
text: [aText],
fromIndex: aStart
fromIndex: aStart,
removedCount: 0,
addedCount: 0
};
if (aIsInserted) {

View File

@ -13,12 +13,14 @@
namespace mozilla {
namespace a11y {
// Mac a11y whitelisting
static bool sA11yShouldBeEnabled = false;
bool
ShouldA11yBeEnabled()
{
return sA11yShouldBeEnabled;
EPlatformDisabledState disabledState = PlatformDisabledState();
return (disabledState == ePlatformIsForceEnabled) || ((disabledState == ePlatformIsEnabled) && sA11yShouldBeEnabled);
}
}

View File

@ -57,7 +57,7 @@ ToNSString(id aValue)
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
if ((self = [super initWithAccessible:accessible])) {
CallQueryInterface(accessible, &mGeckoTextAccessible);
mGeckoTextAccessible = accessible->AsHyperText();
CallQueryInterface(accessible, &mGeckoEditableTextAccessible);
}
return self;
@ -312,7 +312,7 @@ ToNSString(id aValue)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
NS_IF_RELEASE(mGeckoTextAccessible);
mGeckoTextAccessible = nsnull;
NS_IF_RELEASE(mGeckoEditableTextAccessible);
[super expire];

View File

@ -15,7 +15,7 @@ NS_IMPL_ISUPPORTS_INHERITED0(HyperTextAccessibleWrap,
IMPL_IUNKNOWN_INHERITED2(HyperTextAccessibleWrap,
AccessibleWrap,
ia2AccessibleHypertext,
CAccessibleEditableText);
ia2AccessibleEditableText);
nsresult
HyperTextAccessibleWrap::HandleAccEvent(AccEvent* aEvent)

View File

@ -9,13 +9,12 @@
#define mozilla_a11y_HyperTextAccessibleWrap_h__
#include "HyperTextAccessible.h"
#include "CAccessibleText.h"
#include "CAccessibleEditableText.h"
#include "ia2AccessibleEditableText.h"
#include "ia2AccessibleHyperText.h"
class HyperTextAccessibleWrap : public HyperTextAccessible,
public ia2AccessibleHypertext,
public CAccessibleEditableText
public ia2AccessibleEditableText
{
public:
HyperTextAccessibleWrap(nsIContent* aContent, DocAccessible* aDoc) :

View File

@ -26,8 +26,6 @@ CPPSRCS = \
nsAccessNodeWrap.cpp \
nsHTMLWin32ObjectAccessible.cpp \
nsWinUtils.cpp \
CAccessibleText.cpp \
CAccessibleEditableText.cpp \
CAccessibleHyperlink.cpp \
CAccessibleTable.cpp \
CAccessibleTableCell.cpp \
@ -36,9 +34,11 @@ CPPSRCS = \
EnumVariant.cpp \
ia2AccessibleAction.cpp \
ia2AccessibleComponent.cpp \
ia2AccessibleEditableText.cpp \
ia2AccessibleImage.cpp \
ia2AccessibleHypertext.cpp \
ia2AccessibleRelation.cpp \
ia2AccessibleText.cpp \
RootAccessibleWrap.cpp \
TextLeafAccessibleWrap.cpp \
$(NULL)

View File

@ -5,10 +5,10 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "CAccessibleEditableText.h"
#include "ia2AccessibleEditableText.h"
#include "AccessibleEditableText_i.c"
#include "HyperTextAccessible.h"
#include "HyperTextAccessibleWrap.h"
#include "nsCOMPtr.h"
#include "nsString.h"
@ -16,7 +16,7 @@
// IUnknown
STDMETHODIMP
CAccessibleEditableText::QueryInterface(REFIID iid, void** ppv)
ia2AccessibleEditableText::QueryInterface(REFIID iid, void** ppv)
{
*ppv = NULL;
@ -35,10 +35,10 @@ CAccessibleEditableText::QueryInterface(REFIID iid, void** ppv)
// IAccessibleEditableText
STDMETHODIMP
CAccessibleEditableText::copyText(long aStartOffset, long aEndOffset)
ia2AccessibleEditableText::copyText(long aStartOffset, long aEndOffset)
{
__try {
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
@ -50,10 +50,10 @@ __try {
}
STDMETHODIMP
CAccessibleEditableText::deleteText(long aStartOffset, long aEndOffset)
ia2AccessibleEditableText::deleteText(long aStartOffset, long aEndOffset)
{
__try {
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
@ -65,10 +65,10 @@ __try {
}
STDMETHODIMP
CAccessibleEditableText::insertText(long aOffset, BSTR *aText)
ia2AccessibleEditableText::insertText(long aOffset, BSTR *aText)
{
__try {
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
@ -83,10 +83,10 @@ __try {
}
STDMETHODIMP
CAccessibleEditableText::cutText(long aStartOffset, long aEndOffset)
ia2AccessibleEditableText::cutText(long aStartOffset, long aEndOffset)
{
__try {
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
@ -98,10 +98,10 @@ __try {
}
STDMETHODIMP
CAccessibleEditableText::pasteText(long aOffset)
ia2AccessibleEditableText::pasteText(long aOffset)
{
__try {
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
@ -113,11 +113,11 @@ __try {
}
STDMETHODIMP
CAccessibleEditableText::replaceText(long aStartOffset, long aEndOffset,
BSTR *aText)
ia2AccessibleEditableText::replaceText(long aStartOffset, long aEndOffset,
BSTR *aText)
{
__try {
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
@ -136,8 +136,8 @@ __try {
}
STDMETHODIMP
CAccessibleEditableText::setAttributes(long aStartOffset, long aEndOffset,
BSTR *aAttributes)
ia2AccessibleEditableText::setAttributes(long aStartOffset, long aEndOffset,
BSTR *aAttributes)
{
__try {

View File

@ -13,7 +13,7 @@
#include "AccessibleEditableText.h"
class CAccessibleEditableText: public IAccessibleEditableText
class ia2AccessibleEditableText: public IAccessibleEditableText
{
public:

View File

@ -27,7 +27,7 @@ ia2AccessibleHypertext::QueryInterface(REFIID iid, void** ppv)
return E_NOINTERFACE;
}
return CAccessibleText::QueryInterface(iid, ppv);
return ia2AccessibleText::QueryInterface(iid, ppv);
}
// IAccessibleHypertext

View File

@ -10,10 +10,10 @@
#include "nsISupports.h"
#include "CAccessibleText.h"
#include "ia2AccessibleText.h"
#include "AccessibleHypertext.h"
class ia2AccessibleHypertext : public CAccessibleText,
class ia2AccessibleHypertext : public ia2AccessibleText,
public IAccessibleHypertext
{
public:
@ -22,7 +22,7 @@ public:
STDMETHODIMP QueryInterface(REFIID, void**);
// IAccessibleText
FORWARD_IACCESSIBLETEXT(CAccessibleText)
FORWARD_IACCESSIBLETEXT(ia2AccessibleText)
// IAccessibleHypertext
virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_nHyperlinks(

View File

@ -5,19 +5,19 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "CAccessibleText.h"
#include "ia2AccessibleText.h"
#include "Accessible2.h"
#include "AccessibleText_i.c"
#include "HyperTextAccessible.h"
#include "HyperTextAccessibleWrap.h"
#include "nsIPersistentProperties2.h"
// IUnknown
STDMETHODIMP
CAccessibleText::QueryInterface(REFIID iid, void** ppv)
ia2AccessibleText::QueryInterface(REFIID iid, void** ppv)
{
*ppv = NULL;
@ -37,10 +37,10 @@ CAccessibleText::QueryInterface(REFIID iid, void** ppv)
// IAccessibleText
STDMETHODIMP
CAccessibleText::addSelection(long aStartOffset, long aEndOffset)
ia2AccessibleText::addSelection(long aStartOffset, long aEndOffset)
{
__try {
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
@ -52,8 +52,8 @@ __try {
}
STDMETHODIMP
CAccessibleText::get_attributes(long aOffset, long *aStartOffset,
long *aEndOffset, BSTR *aTextAttributes)
ia2AccessibleText::get_attributes(long aOffset, long *aStartOffset,
long *aEndOffset, BSTR *aTextAttributes)
{
__try {
if (!aStartOffset || !aEndOffset || !aTextAttributes)
@ -63,7 +63,7 @@ __try {
*aEndOffset = 0;
*aTextAttributes = NULL;
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
@ -90,12 +90,12 @@ __try {
}
STDMETHODIMP
CAccessibleText::get_caretOffset(long *aOffset)
ia2AccessibleText::get_caretOffset(long *aOffset)
{
__try {
*aOffset = -1;
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
@ -112,10 +112,10 @@ __try {
}
STDMETHODIMP
CAccessibleText::get_characterExtents(long aOffset,
enum IA2CoordinateType aCoordType,
long *aX, long *aY,
long *aWidth, long *aHeight)
ia2AccessibleText::get_characterExtents(long aOffset,
enum IA2CoordinateType aCoordType,
long *aX, long *aY,
long *aWidth, long *aHeight)
{
__try {
*aX = 0;
@ -123,7 +123,7 @@ __try {
*aWidth = 0;
*aHeight = 0;
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
@ -148,12 +148,12 @@ __try {
}
STDMETHODIMP
CAccessibleText::get_nSelections(long *aNSelections)
ia2AccessibleText::get_nSelections(long *aNSelections)
{
__try {
*aNSelections = 0;
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
@ -170,14 +170,14 @@ __try {
}
STDMETHODIMP
CAccessibleText::get_offsetAtPoint(long aX, long aY,
enum IA2CoordinateType aCoordType,
long *aOffset)
ia2AccessibleText::get_offsetAtPoint(long aX, long aY,
enum IA2CoordinateType aCoordType,
long *aOffset)
{
__try {
*aOffset = 0;
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
@ -198,14 +198,14 @@ __try {
}
STDMETHODIMP
CAccessibleText::get_selection(long aSelectionIndex, long *aStartOffset,
long *aEndOffset)
ia2AccessibleText::get_selection(long aSelectionIndex, long *aStartOffset,
long *aEndOffset)
{
__try {
*aStartOffset = 0;
*aEndOffset = 0;
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
@ -224,12 +224,12 @@ __try {
}
STDMETHODIMP
CAccessibleText::get_text(long aStartOffset, long aEndOffset, BSTR *aText)
ia2AccessibleText::get_text(long aStartOffset, long aEndOffset, BSTR *aText)
{
__try {
*aText = NULL;
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
@ -249,17 +249,17 @@ __try {
}
STDMETHODIMP
CAccessibleText::get_textBeforeOffset(long aOffset,
enum IA2TextBoundaryType aBoundaryType,
long *aStartOffset, long *aEndOffset,
BSTR *aText)
ia2AccessibleText::get_textBeforeOffset(long aOffset,
enum IA2TextBoundaryType aBoundaryType,
long *aStartOffset, long *aEndOffset,
BSTR *aText)
{
__try {
*aStartOffset = 0;
*aEndOffset = 0;
*aText = NULL;
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
@ -296,17 +296,17 @@ __try {
}
STDMETHODIMP
CAccessibleText::get_textAfterOffset(long aOffset,
enum IA2TextBoundaryType aBoundaryType,
long *aStartOffset, long *aEndOffset,
BSTR *aText)
ia2AccessibleText::get_textAfterOffset(long aOffset,
enum IA2TextBoundaryType aBoundaryType,
long *aStartOffset, long *aEndOffset,
BSTR *aText)
{
__try {
*aStartOffset = 0;
*aEndOffset = 0;
*aText = NULL;
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
@ -343,17 +343,17 @@ __try {
}
STDMETHODIMP
CAccessibleText::get_textAtOffset(long aOffset,
enum IA2TextBoundaryType aBoundaryType,
long *aStartOffset, long *aEndOffset,
BSTR *aText)
ia2AccessibleText::get_textAtOffset(long aOffset,
enum IA2TextBoundaryType aBoundaryType,
long *aStartOffset, long *aEndOffset,
BSTR *aText)
{
__try {
*aStartOffset = 0;
*aEndOffset = 0;
*aText = NULL;
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
@ -390,10 +390,10 @@ __try {
}
STDMETHODIMP
CAccessibleText::removeSelection(long aSelectionIndex)
ia2AccessibleText::removeSelection(long aSelectionIndex)
{
__try {
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
@ -405,10 +405,10 @@ __try {
}
STDMETHODIMP
CAccessibleText::setCaretOffset(long aOffset)
ia2AccessibleText::setCaretOffset(long aOffset)
{
__try {
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
@ -420,11 +420,11 @@ __try {
}
STDMETHODIMP
CAccessibleText::setSelection(long aSelectionIndex, long aStartOffset,
long aEndOffset)
ia2AccessibleText::setSelection(long aSelectionIndex, long aStartOffset,
long aEndOffset)
{
__try {
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
@ -437,12 +437,12 @@ __try {
}
STDMETHODIMP
CAccessibleText::get_nCharacters(long *aNCharacters)
ia2AccessibleText::get_nCharacters(long *aNCharacters)
{
__try {
*aNCharacters = 0;
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
@ -454,11 +454,11 @@ __try {
}
STDMETHODIMP
CAccessibleText::scrollSubstringTo(long aStartIndex, long aEndIndex,
enum IA2ScrollType aScrollType)
ia2AccessibleText::scrollSubstringTo(long aStartIndex, long aEndIndex,
enum IA2ScrollType aScrollType)
{
__try {
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
@ -470,12 +470,12 @@ __try {
}
STDMETHODIMP
CAccessibleText::scrollSubstringToPoint(long aStartIndex, long aEndIndex,
enum IA2CoordinateType aCoordType,
long aX, long aY)
ia2AccessibleText::scrollSubstringToPoint(long aStartIndex, long aEndIndex,
enum IA2CoordinateType aCoordType,
long aX, long aY)
{
__try {
nsRefPtr<HyperTextAccessible> textAcc(do_QueryObject(this));
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
if (textAcc->IsDefunct())
return CO_E_OBJNOTCONNECTED;
@ -492,7 +492,7 @@ __try {
}
STDMETHODIMP
CAccessibleText::get_newText(IA2TextSegment *aNewText)
ia2AccessibleText::get_newText(IA2TextSegment *aNewText)
{
__try {
return GetModifiedText(true, aNewText);
@ -502,7 +502,7 @@ __try {
}
STDMETHODIMP
CAccessibleText::get_oldText(IA2TextSegment *aOldText)
ia2AccessibleText::get_oldText(IA2TextSegment *aOldText)
{
__try {
return GetModifiedText(false, aOldText);
@ -511,11 +511,11 @@ __try {
return E_FAIL;
}
// CAccessibleText
// ia2AccessibleText
HRESULT
CAccessibleText::GetModifiedText(bool aGetInsertedText,
IA2TextSegment *aText)
ia2AccessibleText::GetModifiedText(bool aGetInsertedText,
IA2TextSegment *aText)
{
PRUint32 startOffset = 0, endOffset = 0;
nsAutoString text;
@ -536,7 +536,7 @@ CAccessibleText::GetModifiedText(bool aGetInsertedText,
}
AccessibleTextBoundary
CAccessibleText::GetGeckoTextBoundary(enum IA2TextBoundaryType aBoundaryType)
ia2AccessibleText::GetGeckoTextBoundary(enum IA2TextBoundaryType aBoundaryType)
{
switch (aBoundaryType) {
case IA2_TEXT_BOUNDARY_CHAR:

View File

@ -13,7 +13,7 @@
#include "AccessibleText.h"
class CAccessibleText: public IAccessibleText
class ia2AccessibleText: public IAccessibleText
{
public:

View File

@ -119,9 +119,8 @@ nsXFormsInputAccessible::
{
}
NS_IMPL_ISUPPORTS_INHERITED3(nsXFormsInputAccessible,
NS_IMPL_ISUPPORTS_INHERITED2(nsXFormsInputAccessible,
Accessible,
HyperTextAccessible,
nsIAccessibleText,
nsIAccessibleEditableText)

View File

@ -119,6 +119,89 @@ xpcAccessibleTable::GetRowExtentAt(PRInt32 aRowIdx, PRInt32 aColIdx,
return NS_OK;
}
nsresult
xpcAccessibleTable::GetColumnDescription(PRInt32 aColIdx,
nsAString& aDescription)
{
if (!mTable)
return NS_ERROR_FAILURE;
if (aColIdx < 0 || static_cast<PRUint32>(aColIdx) >= mTable->ColCount())
return NS_ERROR_INVALID_ARG;
nsAutoString description;
mTable->ColDescription(aColIdx, description);
aDescription.Assign(description);
return NS_OK;
}
nsresult
xpcAccessibleTable::GetRowDescription(PRInt32 aRowIdx, nsAString& aDescription)
{
if (!mTable)
return NS_ERROR_FAILURE;
if (aRowIdx < 0 || static_cast<PRUint32>(aRowIdx) >= mTable->ColCount())
return NS_ERROR_INVALID_ARG;
nsAutoString description;
mTable->RowDescription(aRowIdx, description);
aDescription.Assign(description);
return NS_OK;
}
nsresult
xpcAccessibleTable::IsColumnSelected(PRInt32 aColIdx, bool* aIsSelected)
{
NS_ENSURE_ARG_POINTER(aIsSelected);
*aIsSelected = false;
if (!mTable)
return NS_ERROR_FAILURE;
if (aColIdx < 0 || static_cast<PRUint32>(aColIdx) >= mTable->ColCount())
return NS_ERROR_INVALID_ARG;
*aIsSelected = mTable->IsColSelected(aColIdx);
return NS_OK;
}
nsresult
xpcAccessibleTable::IsRowSelected(PRInt32 aRowIdx, bool* aIsSelected)
{
NS_ENSURE_ARG_POINTER(aIsSelected);
*aIsSelected = false;
if (!mTable)
return NS_ERROR_FAILURE;
if (aRowIdx < 0 || static_cast<PRUint32>(aRowIdx) >= mTable->RowCount())
return NS_ERROR_INVALID_ARG;
*aIsSelected = mTable->IsRowSelected(aRowIdx);
return NS_OK;
}
nsresult
xpcAccessibleTable::IsCellSelected(PRInt32 aRowIdx, PRInt32 aColIdx,
bool* aIsSelected)
{
NS_ENSURE_ARG_POINTER(aIsSelected);
*aIsSelected = false;
if (!mTable)
return NS_ERROR_FAILURE;
if (aRowIdx < 0 || static_cast<PRUint32>(aRowIdx) >= mTable->RowCount() ||
aColIdx < 0 || static_cast<PRUint32>(aColIdx) >= mTable->ColCount())
return NS_ERROR_INVALID_ARG;
*aIsSelected = mTable->IsCellSelected(aRowIdx, aColIdx);
return NS_OK;
}
nsresult
xpcAccessibleTable::GetSummary(nsAString& aSummary)
{

View File

@ -34,6 +34,11 @@ public:
PRInt32* aColumnExtent);
nsresult GetRowExtentAt(PRInt32 row, PRInt32 column,
PRInt32* aRowExtent);
nsresult GetColumnDescription(PRInt32 aColIdx, nsAString& aDescription);
nsresult GetRowDescription(PRInt32 aRowIdx, nsAString& aDescription);
nsresult IsColumnSelected(PRInt32 aColIdx, bool* _retval);
nsresult IsRowSelected(PRInt32 aRowIdx, bool* _retval);
nsresult IsCellSelected(PRInt32 aRowIdx, PRInt32 aColIdx, bool* _retval);
nsresult SelectColumn(PRInt32 aColIdx);
nsresult SelectRow(PRInt32 aRowIdx);
nsresult UnselectColumn(PRInt32 aColIdx);
@ -64,11 +69,16 @@ protected:
{ return xpcAccessibleTable::GetColumnExtentAt(row, column, _retval); } \
NS_SCRIPTABLE NS_IMETHOD GetRowExtentAt(PRInt32 row, PRInt32 column, PRInt32* _retval NS_OUTPARAM) \
{ return xpcAccessibleTable::GetRowExtentAt(row, column, _retval); } \
NS_SCRIPTABLE NS_IMETHOD GetColumnDescription(PRInt32 columnIndex, nsAString & _retval NS_OUTPARAM); \
NS_SCRIPTABLE NS_IMETHOD GetRowDescription(PRInt32 rowIndex, nsAString & _retval NS_OUTPARAM); \
NS_SCRIPTABLE NS_IMETHOD IsColumnSelected(PRInt32 columnIndex, bool *_retval NS_OUTPARAM); \
NS_SCRIPTABLE NS_IMETHOD IsRowSelected(PRInt32 rowIndex, bool *_retval NS_OUTPARAM); \
NS_SCRIPTABLE NS_IMETHOD IsCellSelected(PRInt32 rowIndex, PRInt32 columnIndex, bool *_retval NS_OUTPARAM); \
NS_SCRIPTABLE NS_IMETHOD GetColumnDescription(PRInt32 columnIndex, nsAString& _retval NS_OUTPARAM) \
{ return xpcAccessibleTable::GetColumnDescription(columnIndex, _retval); } \
NS_SCRIPTABLE NS_IMETHOD GetRowDescription(PRInt32 rowIndex, nsAString& _retval NS_OUTPARAM) \
{ return xpcAccessibleTable::GetRowDescription(rowIndex, _retval); } \
NS_SCRIPTABLE NS_IMETHOD IsColumnSelected(PRInt32 colIdx, bool* _retval NS_OUTPARAM) \
{ return xpcAccessibleTable::IsColumnSelected(colIdx, _retval); } \
NS_SCRIPTABLE NS_IMETHOD IsRowSelected(PRInt32 rowIdx, bool* _retval NS_OUTPARAM) \
{ return xpcAccessibleTable::IsRowSelected(rowIdx, _retval); } \
NS_SCRIPTABLE NS_IMETHOD IsCellSelected(PRInt32 rowIdx, PRInt32 colIdx, bool* _retval NS_OUTPARAM) \
{ return xpcAccessibleTable::IsCellSelected(rowIdx, colIdx, _retval); } \
NS_SCRIPTABLE NS_IMETHOD GetSelectedCellCount(PRUint32 *aSelectedCellCount); \
NS_SCRIPTABLE NS_IMETHOD GetSelectedColumnCount(PRUint32 *aSelectedColumnCount); \
NS_SCRIPTABLE NS_IMETHOD GetSelectedRowCount(PRUint32 *aSelectedRowCount); \

View File

@ -685,9 +685,8 @@ XULTextFieldAccessible::
{
}
NS_IMPL_ISUPPORTS_INHERITED3(XULTextFieldAccessible,
NS_IMPL_ISUPPORTS_INHERITED2(XULTextFieldAccessible,
Accessible,
HyperTextAccessible,
nsIAccessibleText,
nsIAccessibleEditableText)

View File

@ -316,30 +316,9 @@ XULListboxAccessible::GetRowAndColumnIndicesAt(PRInt32 aCellIndex,
return NS_OK;
}
NS_IMETHODIMP
XULListboxAccessible::GetColumnDescription(PRInt32 aColumn,
nsAString& aDescription)
bool
XULListboxAccessible::IsColSelected(PRUint32 aColIdx)
{
aDescription.Truncate();
return NS_OK;
}
NS_IMETHODIMP
XULListboxAccessible::GetRowDescription(PRInt32 aRow, nsAString& aDescription)
{
aDescription.Truncate();
return NS_OK;
}
NS_IMETHODIMP
XULListboxAccessible::IsColumnSelected(PRInt32 aColumn, bool* aIsSelected)
{
NS_ENSURE_ARG_POINTER(aIsSelected);
*aIsSelected = false;
if (IsDefunct())
return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
do_QueryInterface(mContent);
NS_ASSERTION(control,
@ -347,42 +326,32 @@ XULListboxAccessible::IsColumnSelected(PRInt32 aColumn, bool* aIsSelected)
PRInt32 selectedrowCount = 0;
nsresult rv = control->GetSelectedCount(&selectedrowCount);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_SUCCESS(rv, false);
PRInt32 rowCount = 0;
rv = GetRowCount(&rowCount);
NS_ENSURE_SUCCESS(rv, rv);
*aIsSelected = (selectedrowCount == rowCount);
return NS_OK;
return selectedrowCount == RowCount();
}
NS_IMETHODIMP
XULListboxAccessible::IsRowSelected(PRInt32 aRow, bool* aIsSelected)
bool
XULListboxAccessible::IsRowSelected(PRUint32 aRowIdx)
{
NS_ENSURE_ARG_POINTER(aIsSelected);
*aIsSelected = false;
if (IsDefunct())
return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMXULSelectControlElement> control =
do_QueryInterface(mContent);
NS_ASSERTION(control,
"Doesn't implement nsIDOMXULSelectControlElement.");
nsCOMPtr<nsIDOMXULSelectControlItemElement> item;
control->GetItemAtIndex(aRow, getter_AddRefs(item));
NS_ENSURE_TRUE(item, NS_ERROR_INVALID_ARG);
nsresult rv = control->GetItemAtIndex(aRowIdx, getter_AddRefs(item));
NS_ENSURE_SUCCESS(rv, false);
return item->GetSelected(aIsSelected);
bool isSelected = false;
item->GetSelected(&isSelected);
return isSelected;
}
NS_IMETHODIMP
XULListboxAccessible::IsCellSelected(PRInt32 aRowIndex, PRInt32 aColumnIndex,
bool* aIsSelected)
bool
XULListboxAccessible::IsCellSelected(PRUint32 aRowIdx, PRUint32 aColIdx)
{
return IsRowSelected(aRowIndex, aIsSelected);
return IsRowSelected(aRowIdx);
}
NS_IMETHODIMP

View File

@ -76,6 +76,9 @@ public:
virtual PRUint32 ColCount();
virtual PRUint32 RowCount();
virtual Accessible* CellAt(PRUint32 aRowIndex, PRUint32 aColumnIndex);
virtual bool IsColSelected(PRUint32 aColIdx);
virtual bool IsRowSelected(PRUint32 aRowIdx);
virtual bool IsCellSelected(PRUint32 aRowIdx, PRUint32 aColIdx);
virtual void SelectRow(PRUint32 aRowIdx);
virtual void UnselectRow(PRUint32 aRowIdx);

View File

@ -553,6 +553,11 @@ XULTreeAccessible::InvalidateCache(PRInt32 aRow, PRInt32 aCount)
if (IsDefunct())
return;
if (!mTreeView) {
ClearCache(mAccessibleCache);
return;
}
// Do not invalidate the cache if rows have been inserted.
if (aCount > 0)
return;
@ -606,6 +611,11 @@ XULTreeAccessible::TreeViewInvalidated(PRInt32 aStartRow, PRInt32 aEndRow,
if (IsDefunct())
return;
if (!mTreeView) {
ClearCache(mAccessibleCache);
return;
}
PRInt32 endRow = aEndRow;
nsresult rv;

View File

@ -368,83 +368,53 @@ XULTreeGridAccessible::GetRowAndColumnIndicesAt(PRInt32 aCellIndex,
return NS_OK;
}
NS_IMETHODIMP
XULTreeGridAccessible::GetColumnDescription(PRInt32 aColumnIndex,
nsAString& aDescription)
void
XULTreeGridAccessible::ColDescription(PRUint32 aColIdx, nsString& aDescription)
{
aDescription.Truncate();
if (IsDefunct())
return NS_ERROR_FAILURE;
nsCOMPtr<nsIAccessible> treeColumns;
Accessible::GetFirstChild(getter_AddRefs(treeColumns));
if (treeColumns) {
nsCOMPtr<nsIAccessible> treeColumnItem;
treeColumns->GetChildAt(aColumnIndex, getter_AddRefs(treeColumnItem));
treeColumns->GetChildAt(aColIdx, getter_AddRefs(treeColumnItem));
if (treeColumnItem)
return treeColumnItem->GetName(aDescription);
treeColumnItem->GetName(aDescription);
}
return NS_OK;
}
NS_IMETHODIMP
XULTreeGridAccessible::GetRowDescription(PRInt32 aRowIndex,
nsAString& aDescription)
bool
XULTreeGridAccessible::IsColSelected(PRUint32 aColIdx)
{
aDescription.Truncate();
return NS_OK;
}
NS_IMETHODIMP
XULTreeGridAccessible::IsColumnSelected(PRInt32 aColumnIndex, bool* aIsSelected)
{
NS_ENSURE_ARG_POINTER(aIsSelected);
*aIsSelected = false;
if (IsDefunct())
return NS_ERROR_FAILURE;
// If all the row has been selected, then all the columns are selected.
// Because we can't select a column alone.
PRInt32 rowCount = 0;
nsresult rv = GetRowCount(&rowCount);
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 selectedrowCount = 0;
rv = GetSelectionCount(&selectedrowCount);
NS_ENSURE_SUCCESS(rv, rv);
nsresult rv = GetSelectionCount(&selectedrowCount);
NS_ENSURE_SUCCESS(rv, false);
*aIsSelected = rowCount == selectedrowCount;
return NS_OK;
return selectedrowCount == RowCount();
}
NS_IMETHODIMP
XULTreeGridAccessible::IsRowSelected(PRInt32 aRowIndex, bool* aIsSelected)
bool
XULTreeGridAccessible::IsRowSelected(PRUint32 aRowIdx)
{
NS_ENSURE_ARG_POINTER(aIsSelected);
*aIsSelected = false;
if (IsDefunct())
return NS_ERROR_FAILURE;
if (!mTreeView)
return NS_ERROR_INVALID_ARG;
return false;
nsCOMPtr<nsITreeSelection> selection;
nsresult rv = mTreeView->GetSelection(getter_AddRefs(selection));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_SUCCESS(rv, false);
return selection->IsSelected(aRowIndex, aIsSelected);
bool isSelected = false;
selection->IsSelected(aRowIdx, &isSelected);
return isSelected;
}
NS_IMETHODIMP
XULTreeGridAccessible::IsCellSelected(PRInt32 aRowIndex, PRInt32 aColumnIndex,
bool* aIsSelected)
bool
XULTreeGridAccessible::IsCellSelected(PRUint32 aRowIdx, PRUint32 aColIdx)
{
return IsRowSelected(aRowIndex, aIsSelected);
return IsRowSelected(aRowIdx);
}
void

View File

@ -34,6 +34,10 @@ public:
virtual PRUint32 ColCount();
virtual PRUint32 RowCount();
virtual Accessible* CellAt(PRUint32 aRowIndex, PRUint32 aColumnIndex);
virtual void ColDescription(PRUint32 aColIdx, nsString& aDescription);
virtual bool IsColSelected(PRUint32 aColIdx);
virtual bool IsRowSelected(PRUint32 aRowIdx);
virtual bool IsCellSelected(PRUint32 aRowIdx, PRUint32 aColIdx);
virtual void SelectRow(PRUint32 aRowIdx);
virtual void UnselectRow(PRUint32 aRowIdx);

View File

@ -307,6 +307,24 @@
attrs = {};
testTextAttrs(ID, 123, attrs, defAttrs, 122, 130);
attrs = {
"text-line-through-style": "solid",
"text-line-through-color": gComputedStyle.color
};
testTextAttrs(ID, 131, attrs, defAttrs, 130, 143);
attrs = {};
testTextAttrs(ID, 144, attrs, defAttrs, 143, 151);
attrs = {
"text-line-through-style": "solid",
"text-line-through-color": gComputedStyle.color
};
testTextAttrs(ID, 152, attrs, defAttrs, 151, 164);
attrs = {};
testTextAttrs(ID, 165, attrs, defAttrs, 164, 172);
//////////////////////////////////////////////////////////////////////////
// area10, different single style spans in non-styled paragraph
ID = "area10";
@ -621,6 +639,8 @@
<span style="font-family: monospace;">Different font</span> normal
<span style="text-decoration: underline;">underlined</span> normal
<span style="text-decoration: line-through;">strikethrough</span> normal
<s>strikethrough</s> normal
<strike>strikethrough</strike> normal
</p>
<p id="area10">Normal

View File

@ -14,12 +14,22 @@
src="../common.js"></script>
<script type="application/javascript"
src="../role.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript"
src="../layout.js"></script>
<script type="application/javascript"
src="../browser.js"></script>
<script type="application/javascript">
//gA11yEventDumpToConsole = true;
function doPreTest()
{
var tabDocument = currentTabDocument();
var imgMap = tabDocument.getElementById("imgmap");
waitForImageMap(imgMap, doTest);
}
function doTest()
{
// Bug 746176: Failure of this whole test file on OS X.
@ -35,7 +45,6 @@
var p2 = tabDocument.getElementById("p2");
var imgMap = tabDocument.getElementById("imgmap");
ensureImageMapTree(imgMap);
var imgMapAcc = getAccessible(imgMap);
var area = imgMapAcc.firstChild;
@ -65,10 +74,11 @@
url += "</body></html>";
SimpleTest.waitForExplicitFinish();
openBrowserWindow(doTest,
openBrowserWindow(doPreTest,
url,
{ left: 0, top: 0, width: 600, height: 600 });
</script>
</head>
<body>

View File

@ -513,24 +513,6 @@ function testDefunctAccessible(aAcc, aNodeOrId)
ok(success, "parent" + msg);
}
/**
* Ensure that image map accessible tree is created.
*/
function ensureImageMapTree(aID)
{
// XXX: We send a useless mouse move to the image to force it to setup its
// image map, because flushing layout won't do it. Hopefully bug 135040
// will make this not suck.
var image = getNode(aID);
synthesizeMouse(image, 10, 10, { type: "mousemove" },
image.ownerDocument.defaultView);
// XXX This may affect a11y more than other code because imagemaps may not
// get drawn or have an mouse event over them. Bug 570322 tracks a11y
// dealing with this.
todo(false, "Need to remove this image map workaround.");
}
/**
* Convert role to human readable string.
*/

View File

@ -98,6 +98,21 @@ function waitForEvent(aEventType, aTarget, aFunc, aContext, aArg1, aArg2)
registerA11yEventListener(aEventType, handler);
}
/**
* Call the given function when the tree of the given image map is built.
*/
function waitForImageMap(aImageMapID, aTestFunc)
{
synthesizeMouse(aImageMapID, 10, 10, { type: "mousemove" },
aImageMapID.ownerDocument.defaultView);
var imageMapAcc = getAccessible(aImageMapID);
if (imageMapAcc.firstChild)
return aTestFunc();
waitForEvent(EVENT_REORDER, imageMapAcc, aTestFunc);
}
/**
* Register accessibility event listener.
*

View File

@ -58,6 +58,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=418368
}
//gA11yEventDumpToConsole = true; // debug stuff
function doPreTest()
{
var imgMap = document.getElementById("imgmap");
waitForImageMap(imgMap, doTest);
}
var gQueue = null;
function doTest()
@ -90,7 +95,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=418368
//////////////////////////////////////////////////////////////////////////
// image map and its link children
ensureImageMapTree("imgmap");
var imageMapHyperlinkAcc = getAccessible("imgmap",
[nsIAccessibleHyperLink]);
@ -239,8 +243,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=418368
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
addA11yLoadEvent(doPreTest);
</script>
</head>
<body><a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=418368">Mozilla Bug 418368</a
><p id="display"></p

View File

@ -14,6 +14,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=428248
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript">
var gParagraphAcc;
@ -39,6 +41,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=428248
is(linkAcc.getAnchor(0).name, aName, "Wrong name for " + aID + "!");
}
//gA11yEventDumpToConsole = true;
function doPreTest()
{
var imgMap = document.getElementById("imgmap");
waitForImageMap(imgMap, doTest);
}
function doTest()
{
// Test link count
@ -55,7 +64,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=428248
testThis("InvalidAriaHyperlink", 63, 2, "Invalid link");
// image map, but not its link children. They are not part of hypertext.
ensureImageMapTree("imgmap");
testThis("imgmap", 76, 3, "b");
// empty hyperlink
@ -98,8 +106,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=428248
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
addA11yLoadEvent(doPreTest);
</script>
</head>
<body>

View File

@ -13,14 +13,21 @@
src="../common.js"></script>
<script type="application/javascript"
src="../role.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript"
src="../states.js"></script>
<script type="application/javascript">
//gA11yEventDumpToConsole = true;
function doPreTest()
{
var imgMap = document.getElementById("imagemap");
waitForImageMap(imgMap, doTest);
}
function doTest()
{
ensureImageMapTree("imagemap");
var imageMap = getAccessible("imagemap");
var t1 = imageMap.getChildAt(0);
@ -41,8 +48,9 @@
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
addA11yLoadEvent(doPreTest);
</script>
</head>
<body>

View File

@ -50,25 +50,9 @@ function doTest()
is(accTable.selectedRowCount, 1, "no cells selected");
var columnDescription;
works = true;
try{
columnDescription = accTable.getColumnDescription(1);
}
catch (e) {
works = false;
}
todo(works, "columnDescription should not throw");
var columnDescription = accTable.getColumnDescription(1);
var rowDescription = accTable.getRowDescription(1);
var rowDescription;
works = true;
try {
rowDescription = accTable.getRowDescription(1);
}
catch (e) {
works = false;
}
todo(works, "rowDescription should not throw");
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
@ -78,6 +62,12 @@ addA11yLoadEvent(doTest);
<body >
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=410052">Mozilla Bug 410052</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=760878"
title="decomtaminate Get Row / Column Description() on accessible tables">
Mozilla Bug 760878
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">

View File

@ -13,14 +13,21 @@
src="../common.js"></script>
<script type="application/javascript"
src="../role.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript"
src="../states.js"></script>
<script type="application/javascript">
//gA11yEventDumpToConsole = true;
function doPreTest()
{
var imgMap = document.getElementById("imagemap");
waitForImageMap(imgMap, doTest);
}
function doTest()
{
ensureImageMapTree("imagemap");
var accTree = {
role: ROLE_IMAGE_MAP,
children: [
@ -70,8 +77,9 @@
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
addA11yLoadEvent(doPreTest);
</script>
</head>
<body>

View File

@ -14,8 +14,17 @@
src="../common.js"></script>
<script type="application/javascript"
src="../role.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript">
//gA11yEventDumpToConsole = true;
function doPreTest()
{
var imgMap = document.getElementById("imgmap");
waitForImageMap(imgMap, doTest);
}
function doTest()
{
// image map
@ -33,7 +42,6 @@
]
};
ensureImageMapTree("imgmap");
testAccessibleTree("imgmap", accTree);
// img
@ -48,8 +56,9 @@
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
addA11yLoadEvent(doPreTest);
</script>
</head>
<body>

View File

@ -324,8 +324,6 @@
map.appendChild(area);
this.containerNode.appendChild(map);
ensureImageMapTree(aImageID);
}
this.finalCheck = function insertMap_finalCheck()
@ -381,6 +379,11 @@
}
gA11yEventDumpToConsole = true;
function doPreTest()
{
var imgMap = document.getElementById("imgmap");
waitForImageMap(imgMap, doTest);
}
var gQueue = null;
function doTest()
@ -400,8 +403,9 @@
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
addA11yLoadEvent(doPreTest);
</script>
</head>
<body>

View File

@ -117,7 +117,6 @@ if [ "$ENABLE_MARIONETTE" ]; then
add_makefiles "
testing/marionette/Makefile
testing/marionette/components/Makefile
testing/marionette/tests/Makefile
"
fi

View File

@ -6,35 +6,6 @@
pref("toolkit.defaultChromeURI", "chrome://browser/content/shell.xul");
pref("browser.chromeURL", "chrome://browser/content/");
#ifdef MOZ_OFFICIAL_BRANDING
pref("browser.homescreenURL", "http://homescreen.gaiamobile.org/");
#else
pref("browser.homescreenURL", "http://homescreen.gaiamobile.org/");
#endif
// All the privileged domains
// XXX TODO : we should read them from a file somewhere
pref("b2g.privileged.domains", "http://browser.gaiamobile.org,
http://calculator.gaiamobile.org,
http://contacts.gaiamobile.org,
http://camera.gaiamobile.org,
http://clock.gaiamobile.org,
http://crystalskull.gaiamobile.org,
http://cubevid.gaiamobile.org,
http://dialer.gaiamobile.org,
http://gallery.gaiamobile.org,
http://homescreen.gaiamobile.org,
http://maps.gaiamobile.org,
http://market.gaiamobile.org,
http://music.gaiamobile.org,
http://penguinpop.gaiamobile.org,
http://settings.gaiamobile.org,
http://sms.gaiamobile.org,
http://towerjelly.gaiamobile.org,
http://video.gaiamobile.org");
// URL for the dialer application.
pref("dom.telephony.app.phone.url", "http://dialer.gaiamobile.org,http://homescreen.gaiamobile.org");
// Device pixel to CSS px ratio, in percent. Set to -1 to calculate based on display density.
pref("browser.viewport.scaleRatio", -1);
@ -395,7 +366,6 @@ pref("browser.link.open_newwindow.restriction", 0);
// Enable browser frames (including OOP, except on Windows, where it doesn't
// work), but make in-process browser frames the default.
pref("dom.mozBrowserFramesEnabled", true);
pref("dom.mozBrowserFramesWhitelist", "http://homescreen.gaiamobile.org,http://browser.gaiamobile.org");
pref("dom.ipc.tabs.disabled", false);
@ -403,14 +373,9 @@ pref("dom.ipc.browser_frames.oop_by_default", false);
// Temporary permission hack for WebSMS
pref("dom.sms.enabled", true);
pref("dom.sms.whitelist", "file://,http://homescreen.gaiamobile.org,http://sms.gaiamobile.org");
// Temporary permission hack for WebMobileConnection
pref("dom.mobileconnection.whitelist", "http://system.gaiamobile.org,http://homescreen.gaiamobile.org,http://dialer.gaiamobile.org");
// Temporary permission hack for WebContacts
pref("dom.mozContacts.enabled", true);
pref("dom.mozContacts.whitelist", "http://dialer.gaiamobile.org,http://sms.gaiamobile.org");
// WebSettings
pref("dom.mozSettings.enabled", true);
@ -437,11 +402,9 @@ pref("b2g.remote-js.port", 9999);
// Handle hardware buttons in the b2g chrome package
pref("b2g.keys.menu.enabled", true);
pref("b2g.keys.search.enabled", false);
// Screen timeout in minutes
// Screen timeout in seconds
pref("power.screen.timeout", 60);
pref("dom.power.whitelist", "http://homescreen.gaiamobile.org,http://settings.gaiamobile.org");
pref("full-screen-api.enabled", true);

View File

@ -131,6 +131,27 @@ DeviceTabActor.prototype = {
return this._contextPool;
},
/**
* Add the specified breakpoint to the default actor pool connection, in order
* to be alive as long as the server is.
*
* @param BreakpointActor actor
* The actor object.
*/
addToBreakpointPool: function DTA_addToBreakpointPool(actor) {
this.conn.addActor(actor);
},
/**
* Remove the specified breakpint from the default actor pool.
*
* @param string actor
* The actor ID.
*/
removeFromBreakpointPool: function DTA_removeFromBreakpointPool(actor) {
this.conn.removeActor(actor);
},
actorPrefix: 'tab',
grip: function DTA_grip() {

View File

@ -69,8 +69,6 @@ function addPermissions(urls) {
}
var shell = {
isDebug: false,
get contentBrowser() {
delete this.contentBrowser;
return this.contentBrowser = document.getElementById('homescreen');
@ -134,6 +132,14 @@ var shell = {
WebappsHelper.init();
// XXX could factor out into a settings->pref map. Not worth it yet.
SettingsListener.observe("debug.fps.enabled", false, function(value) {
Services.prefs.setBoolPref("layers.acceleration.draw-fps", value);
});
SettingsListener.observe("debug.paint-flashing.enabled", false, function(value) {
Services.prefs.setBoolPref("nglayout.debug.paint_flashing", value);
});
let browser = this.contentBrowser;
browser.homePage = homeURL;
browser.goHome();
@ -155,18 +161,6 @@ var shell = {
delete Services.audioManager;
#endif
},
toggleDebug: function shell_toggleDebug() {
this.isDebug = !this.isDebug;
if (this.isDebug) {
Services.prefs.setBoolPref("layers.acceleration.draw-fps", true);
Services.prefs.setBoolPref("nglayout.debug.paint_flashing", true);
} else {
Services.prefs.setBoolPref("layers.acceleration.draw-fps", false);
Services.prefs.setBoolPref("nglayout.debug.paint_flashing", false);
}
},
changeVolume: function shell_changeVolume(delta) {
let steps = 10;
@ -209,11 +203,6 @@ var shell = {
// to the content, let's react on some of the keyup events.
if (evt.type == 'keyup' && evt.eventPhase == evt.BUBBLING_PHASE) {
switch (evt.keyCode) {
case evt.DOM_VK_F5:
if (Services.prefs.getBoolPref('b2g.keys.search.enabled'))
this.toggleDebug();
break;
case evt.DOM_VK_PAGE_DOWN:
this.changeVolume(-1);
break;

View File

@ -216,6 +216,7 @@
@BINPATH@/components/jetpack.xpt
@BINPATH@/components/jsdebugger.xpt
@BINPATH@/components/jsdservice.xpt
@BINPATH@/components/jsinspector.xpt
@BINPATH@/components/layout_base.xpt
@BINPATH@/components/layout_forms.xpt
#ifdef NS_PRINTING

View File

@ -20,6 +20,7 @@
#include <stdio.h>
#include <stdarg.h>
#include <time.h>
#include "nsCOMPtr.h"
#include "nsIFile.h"
@ -241,18 +242,34 @@ int main(int argc, char* argv[])
#elif defined(XP_WIN)
// Don't change the order of these enumeration constants, the order matters
// for reporting telemetry data. If new values are added adjust the
// STARTUP_USING_PRELOAD histogram.
enum PreloadReason { PRELOAD_NONE, PRELOAD_SERVICE };
PreloadReason preloadReason = PRELOAD_NONE;
// STARTUP_USING_PRELOAD_TRIAL histogram.
enum PreloadType{ PREFETCH_PRELOAD,
PREFETCH_NO_PRELOAD,
NO_PREFETCH_PRELOAD,
NO_PREFETCH_NO_PRELOAD };
PreloadType preloadType;
IO_COUNTERS ioCounters;
gotCounters = GetProcessIoCounters(GetCurrentProcess(), &ioCounters);
srand(time(NULL));
bool shouldUsePreload = rand() % 2 == 0;
if (IsPrefetchDisabledViaService()) {
preloadReason = PRELOAD_SERVICE;
if (shouldUsePreload) {
preloadType = NO_PREFETCH_PRELOAD;
} else {
preloadType = NO_PREFETCH_NO_PRELOAD;
}
} else {
if (shouldUsePreload) {
preloadType = PREFETCH_PRELOAD;
} else {
preloadType = PREFETCH_NO_PRELOAD;
}
}
if (preloadReason != PRELOAD_NONE)
if (shouldUsePreload)
#endif
{
XPCOMGlueEnablePreload();
@ -279,8 +296,8 @@ int main(int argc, char* argv[])
#endif
#if defined(XP_WIN)
XRE_TelemetryAccumulate(mozilla::Telemetry::STARTUP_USING_PRELOAD,
preloadReason);
XRE_TelemetryAccumulate(mozilla::Telemetry::STARTUP_USING_PRELOAD_TRIAL,
preloadType);
#endif
if (gotCounters) {

View File

@ -1,6 +1,23 @@
/* 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/. */
// Copyright (c) 2009 Thomas Robinson <tlrobinson.net>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation files
// (the “Software”), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// This module was taken from narwhal:
//

View File

@ -1024,6 +1024,7 @@ pref("devtools.errorconsole.enabled", false);
// Developer toolbar and GCLI preferences
pref("devtools.toolbar.enabled", false);
pref("devtools.toolbar.visible", false);
pref("devtools.gcli.allowSet", false);
// Enable the Inspector

File diff suppressed because it is too large Load Diff

View File

@ -24,7 +24,7 @@
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="BrowserStartup()" onunload="BrowserShutdown()" onclose="return WindowIsClosing();"
onload="gBrowserInit.onLoad()" onunload="gBrowserInit.onUnload()" onclose="return WindowIsClosing();"
title="&mainWindow.title;@PRE_RELEASE_SUFFIX@"
title_normal="&mainWindow.title;@PRE_RELEASE_SUFFIX@"
#ifdef XP_MACOSX

View File

@ -34,8 +34,8 @@
return OpenBrowserWindow();
}
addEventListener("load", nonBrowserWindowStartup, false);
addEventListener("unload", nonBrowserWindowShutdown, false);
addEventListener("load", function() { gBrowserInit.nonBrowserWindowStartup() }, false);
addEventListener("unload", function() { gBrowserInit.nonBrowserWindowShutdown() }, false);
</script>
# All sets except for popupsets (commands, keys, stringbundles and broadcasters) *must* go into the

View File

@ -42,7 +42,8 @@ function test1a() {
ok(!popupNotification, "Test 1a, Should not have a click-to-play notification");
var plugin = gTestBrowser.contentWindow.addPlugin();
setTimeout(test1b, 500);
var condition = function() PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
waitForCondition(condition, test1b, "Test 1a, Waited too long for plugin notification");
}
function test1b() {
@ -53,7 +54,7 @@ function test1b() {
ok(!objLoadingContent.activated, "Test 1b, Plugin should not be activated");
popupNotification.mainAction.callback();
setTimeout(test1c, 500);
test1c();
}
function test1c() {
@ -61,7 +62,9 @@ function test1c() {
ok(!popupNotification, "Test 1c, Should not have a click-to-play notification");
var plugin = gTestBrowser.contentWindow.addPlugin();
setTimeout(test1d, 500);
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
var condition = function() objLoadingContent.activated;
waitForCondition(condition, test1d, "Test 1c, Waited too long for plugin activation");
}
function test1d() {
@ -82,7 +85,9 @@ function test1e() {
ok(!popupNotification, "Test 1e, Should not have a click-to-play notification");
var plugin = gTestBrowser.contentWindow.addPlugin();
setTimeout(test1f, 500);
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
var condition = function() objLoadingContent.activated;
waitForCondition(condition, test1f, "Test 1e, Waited too long for plugin activation");
}
function test1f() {
@ -93,8 +98,10 @@ function test1f() {
ok(objLoadingContent.activated, "Test 1f, Plugin should be activated");
gTestBrowser.contentWindow.history.replaceState({}, "", "replacedState");
gTestBrowser.contentWindow.addPlugin();
setTimeout(test1g, 500);
var plugin = gTestBrowser.contentWindow.addPlugin();
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
var condition = function() objLoadingContent.activated;
waitForCondition(condition, test1g, "Test 1f, Waited too long for plugin activation");
}
function test1g() {

View File

@ -213,21 +213,6 @@ function test8() {
prepareTest(test9a, gTestRoot + "plugin_test2.html");
}
function waitForCondition(condition, nextTest, errorMsg) {
var tries = 0;
var interval = setInterval(function() {
if (tries >= 500) {
ok(false, errorMsg);
moveOn();
}
if (condition()) {
moveOn();
}
tries++;
}, 10);
var moveOn = function() { clearInterval(interval); nextTest(); };
}
// Tests that activating one click-to-play plugin will activate only that plugin (part 1/3)
function test9a() {
var notificationBox = gBrowser.getNotificationBox(gTestBrowser);

View File

@ -72,3 +72,18 @@ function closeToolbarCustomizationUI(aCallback, aBrowserWin) {
button.focus();
button.doCommand();
}
function waitForCondition(condition, nextTest, errorMsg) {
var tries = 0;
var interval = setInterval(function() {
if (tries >= 30) {
ok(false, errorMsg);
moveOn();
}
if (condition()) {
moveOn();
}
tries++;
}, 100);
var moveOn = function() { clearInterval(interval); nextTest(); };
}

View File

@ -16,7 +16,7 @@
#include "nsGNOMEShellService.h"
#endif
#if defined(XP_WIN) && !defined(__MINGW32__)
#if defined(XP_WIN)
#include "nsIEHistoryEnumerator.h"
#endif
@ -41,7 +41,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacShellService)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGNOMEShellService, Init)
#endif
#if defined(XP_WIN) && !defined(__MINGW32__)
#if defined(XP_WIN)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsIEHistoryEnumerator)
#endif
@ -57,7 +57,7 @@ NS_DEFINE_NAMED_CID(NS_SHELLSERVICE_CID);
#endif
NS_DEFINE_NAMED_CID(NS_FEEDSNIFFER_CID);
NS_DEFINE_NAMED_CID(NS_BROWSER_ABOUT_REDIRECTOR_CID);
#if defined(XP_WIN) && !defined(__MINGW32__)
#if defined(XP_WIN)
NS_DEFINE_NAMED_CID(NS_WINIEHISTORYENUMERATOR_CID);
#elif defined(XP_MACOSX)
NS_DEFINE_NAMED_CID(NS_SHELLSERVICE_CID);
@ -73,7 +73,7 @@ static const mozilla::Module::CIDEntry kBrowserCIDs[] = {
#endif
{ &kNS_FEEDSNIFFER_CID, false, NULL, nsFeedSnifferConstructor },
{ &kNS_BROWSER_ABOUT_REDIRECTOR_CID, false, NULL, AboutRedirector::Create },
#if defined(XP_WIN) && !defined(__MINGW32__)
#if defined(XP_WIN)
{ &kNS_WINIEHISTORYENUMERATOR_CID, false, NULL, nsIEHistoryEnumeratorConstructor },
#elif defined(XP_MACOSX)
{ &kNS_SHELLSERVICE_CID, false, NULL, nsMacShellServiceConstructor },
@ -107,7 +107,7 @@ static const mozilla::Module::ContractIDEntry kBrowserContracts[] = {
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "newtab", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "permissions", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "preferences", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
#if defined(XP_WIN) && !defined(__MINGW32__)
#if defined(XP_WIN)
{ NS_IEHISTORYENUMERATOR_CONTRACTID, &kNS_WINIEHISTORYENUMERATOR_CID },
#elif defined(XP_MACOSX)
{ NS_SHELLSERVICE_CONTRACTID, &kNS_SHELLSERVICE_CID },

View File

@ -21,7 +21,7 @@ EXTRA_PP_COMPONENTS = \
FirefoxProfileMigrator.js \
$(NULL)
ifeq ($(OS_ARCH)_$(GNU_CXX),WINNT_)
ifeq ($(OS_ARCH),WINNT)
CPPSRCS += nsIEHistoryEnumerator.cpp
EXTRA_PP_COMPONENTS += IEProfileMigrator.js \

View File

@ -245,7 +245,7 @@ function openWindow(parent, url, target, features, args, noExternalArgs) {
}
// Pass these as null to ensure that we always trigger the "single URL"
// behavior in browser.js's BrowserStartup (which handles the window
// behavior in browser.js's gBrowserInit.onLoad (which handles the window
// arguments)
argArray.AppendElement(null); // charset
argArray.AppendElement(null); // referer

View File

@ -27,8 +27,15 @@ var gConnectionsDialog = {
var backupPortPref = document.getElementById("network.proxy.backup." + proxyPrefs[i] + "_port");
backupServerURLPref.value = proxyServerURLPref.value;
backupPortPref.value = proxyPortPref.value;
proxyServerURLPref.value = httpProxyURLPref.value;
proxyPortPref.value = httpProxyPortPref.value;
// SOCKS: not a protocol: set value to empty/0 while shareProxies is on
if (proxyPrefs[i] == "socks") {
proxyServerURLPref.value = "";
proxyPortPref.value = 0;
} else {
// protocols get HTTP proxy's values
proxyServerURLPref.value = httpProxyURLPref.value;
proxyPortPref.value = httpProxyPortPref.value;
}
}
}
@ -134,6 +141,10 @@ var gConnectionsDialog = {
{
var shareProxiesPref = document.getElementById("network.proxy.share_proxy_settings");
if (shareProxiesPref.value) {
// during shareProxiesPref SOCKS values are empty
if (aProtocol == 'socks') {
return aIsPort ? 0 : "";
}
var pref = document.getElementById("network.proxy.http" + (aIsPort ? "_port" : ""));
return pref.value;
}

View File

@ -35,7 +35,8 @@ EXTRA_COMPONENTS = nsSetDefaultBrowser.js nsSetDefaultBrowser.manifest
include $(topsrcdir)/config/rules.mk
DEFINES += -DMOZ_APP_NAME=\"$(MOZ_APP_NAME)\"
DEFINES += -DMOZ_APP_NAME=\"$(MOZ_APP_NAME)\" \
-DMOZ_APP_VERSION=\"$(MOZ_APP_VERSION)\"
CXXFLAGS += $(TK_CFLAGS)

View File

@ -201,7 +201,8 @@ static SETTING gDDESettings[] = {
#include "updatehelper.h"
#include "updatehelper.cpp"
static const char kPrefetchClearedPref[] = "app.update.service.prefetchCleared";
static const char *kPrefetchClearedPref =
"app.update.service.lastVersionPrefetchCleared";
static nsCOMPtr<nsIThread> sThread;
#endif
@ -1016,17 +1017,20 @@ nsWindowsShellService::nsWindowsShellService() :
}
// check to see if we have attempted to do the one time operation of clearing
// the prefetch.
bool prefetchCleared;
// the prefetch. We do it once per version upgrade.
nsCString lastClearedVer;
nsCOMPtr<nsIPrefBranch> prefBranch;
nsCOMPtr<nsIPrefService> prefs =
do_GetService(NS_PREFSERVICE_CONTRACTID);
if (!prefs ||
NS_FAILED(prefs->GetBranch(nsnull, getter_AddRefs(prefBranch))) ||
(NS_SUCCEEDED(prefBranch->GetBoolPref(kPrefetchClearedPref,
&prefetchCleared)) &&
prefetchCleared)) {
return;
(NS_SUCCEEDED(prefBranch->GetCharPref(kPrefetchClearedPref,
getter_Copies(lastClearedVer))))) {
// If the versions are the same, then bail out early. We only want to clear
// once per version.
if (!strcmp(MOZ_APP_VERSION, lastClearedVer.get())) {
return;
}
}
// In a minute after startup is definitely complete, launch the
@ -1097,7 +1101,7 @@ nsWindowsShellService::LaunchPrefetchClearCommand(nsITimer *aTimer, void*)
do_GetService(NS_PREFSERVICE_CONTRACTID);
if (prefs) {
if (NS_SUCCEEDED(prefs->GetBranch(nsnull, getter_AddRefs(prefBranch)))) {
prefBranch->SetBoolPref(kPrefetchClearedPref, true);
prefBranch->SetCharPref(kPrefetchClearedPref, MOZ_APP_VERSION);
}
}

View File

@ -11,6 +11,8 @@ const Cc = Components.classes;
const Ci = Components.interfaces;
const HTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
const PREF_STORAGE_VERSION = "browser.pagethumbnails.storage_version";
const LATEST_STORAGE_VERSION = 1;
/**
* Name of the directory in the profile that contains the thumbnails.
@ -79,6 +81,9 @@ let PageThumbs = {
if (!this._initialized) {
this._initialized = true;
PlacesUtils.history.addObserver(PageThumbsHistoryObserver, false);
// Migrate the underlying storage, if needed.
PageThumbsStorageMigrator.migrate();
}
},
@ -248,7 +253,7 @@ let PageThumbsStorage = {
getFileForURL: function Storage_getFileForURL(aURL, aOptions) {
let hash = this._calculateMD5Hash(aURL);
let parts = [THUMBNAIL_DIRECTORY, hash[0], hash[1]];
let file = FileUtils.getDir("ProfD", parts, aOptions && aOptions.createPath);
let file = FileUtils.getDir("ProfLD", parts, aOptions && aOptions.createPath);
file.append(hash.slice(2) + ".png");
return file;
},
@ -284,7 +289,7 @@ let PageThumbsStorage = {
wipe: function Storage_wipe() {
try {
FileUtils.getDir("ProfD", [THUMBNAIL_DIRECTORY]).remove(true);
FileUtils.getDir("ProfLD", [THUMBNAIL_DIRECTORY]).remove(true);
} catch (e) {
/* The file might not exist or we're not permitted to remove it. */
}
@ -308,6 +313,44 @@ let PageThumbsStorage = {
};
let PageThumbsStorageMigrator = {
get currentVersion() {
try {
return Services.prefs.getIntPref(PREF_STORAGE_VERSION);
} catch (e) {
// The pref doesn't exist, yet. Return version 0.
return 0;
}
},
set currentVersion(aVersion) {
Services.prefs.setIntPref(PREF_STORAGE_VERSION, aVersion);
},
migrate: function Migrator_migrate() {
let version = this.currentVersion;
if (version < 1)
this.removeThumbnailsFromRoamingProfile();
this.currentVersion = LATEST_STORAGE_VERSION;
},
removeThumbnailsFromRoamingProfile:
function Migrator_removeThumbnailsFromRoamingProfile() {
let local = FileUtils.getDir("ProfLD", [THUMBNAIL_DIRECTORY]);
let roaming = FileUtils.getDir("ProfD", [THUMBNAIL_DIRECTORY]);
if (!roaming.equals(local) && roaming.exists()) {
try {
roaming.remove(true);
} catch (e) {
// The directory might not exist or we're not permitted to remove it.
}
}
}
};
let PageThumbsHistoryObserver = {
onDeleteURI: function Thumbnails_onDeleteURI(aURI, aGUID) {
PageThumbsStorage.remove(aURI.spec);

View File

@ -2,6 +2,7 @@ ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-update-packaging
ac_add_options --enable-codesighs
ac_add_options --enable-signmar
ac_add_options --enable-profiling
# Nightlies only since this has a cost in performance
ac_add_options --enable-js-diagnostics

View File

@ -2,6 +2,7 @@ ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-update-packaging
ac_add_options --enable-codesighs
ac_add_options --enable-signmar
ac_add_options --enable-profiling
# Nightlies only since this has a cost in performance
ac_add_options --enable-js-diagnostics

View File

@ -8,6 +8,7 @@ ac_add_options --enable-update-packaging
ac_add_options --enable-codesighs
ac_add_options --disable-install-strip
ac_add_options --enable-signmar
ac_add_options --enable-profiling
# Nightlies only since this has a cost in performance
ac_add_options --enable-js-diagnostics

View File

@ -5,6 +5,7 @@ ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-update-packaging
ac_add_options --enable-jemalloc
ac_add_options --enable-signmar
ac_add_options --enable-profiling
# Nightlies only since this has a cost in performance
ac_add_options --enable-js-diagnostics

View File

@ -8,6 +8,7 @@ ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-update-packaging
ac_add_options --enable-jemalloc
ac_add_options --enable-signmar
ac_add_options --enable-profiling
# Nightlies only since this has a cost in performance
ac_add_options --enable-js-diagnostics

View File

@ -128,6 +128,9 @@ InsideOutBoxView = {
var EXPORTED_SYMBOLS = ["InsideOutBox"];
const Cu = Components.utils;
Cu.import("resource:///modules/devtools/LayoutHelpers.jsm");
function InsideOutBox(aView, aBox)
{
this.view = aView;
@ -212,7 +215,9 @@ InsideOutBox.prototype =
if (makeBoxVisible) {
this.openObjectBox(objectBox);
if (scrollIntoView) {
objectBox.scrollIntoView(true);
// We want to center the label of the element, not the whole tag
// (which includes all of its children, and is vertically huge).
LayoutHelpers.scrollIntoViewIfNeeded(objectBox.firstElementChild);
}
}
return objectBox;

View File

@ -884,7 +884,11 @@ Highlighter.prototype = {
*/
handleMouseMove: function Highlighter_handleMouseMove(aEvent)
{
if (aEvent.target.ownerDocument) {
let doc = aEvent.target.ownerDocument;
// This should never happen, but just in case, we don't let the
// highlighter highlight browser nodes.
if (doc && doc != this.chromeDoc) {
let element = LayoutHelpers.getElementFromPoint(aEvent.target.ownerDocument,
aEvent.clientX, aEvent.clientY);
if (element && element != this.node) {

View File

@ -1122,7 +1122,14 @@ InspectorUI.prototype = {
deleteNode: function IUI_deleteNode()
{
let selection = this.selection;
let parent = this.selection.parentNode;
let root = selection.ownerDocument.documentElement;
if (selection === root) {
// We can't delete the root element.
return;
}
let parent = selection.parentNode;
// remove the node from the treepanel
if (this.treePanel.isOpen())
@ -1150,6 +1157,11 @@ InspectorUI.prototype = {
*/
inspectNode: function IUI_inspectNode(aNode, aScroll)
{
if (aNode.ownerDocument === this.chromeDoc) {
// This should never happen, but just in case, we don't let the inspector
// inspect browser nodes.
return;
}
this.select(aNode, true, true);
this.highlighter.highlight(aNode, aScroll);
},
@ -1222,7 +1234,7 @@ InspectorUI.prototype = {
/**
* Destroy the InspectorUI instance. This is called by the InspectorUI API
* "user", see BrowserShutdown() in browser.js.
* "user", see gBrowserInit.onUnload() in browser.js.
*/
destroy: function IUI_destroy()
{

View File

@ -78,11 +78,28 @@ function test() {
}
function deleteTest() {
InspectorUI.highlighter.removeListener("nodeSelected", deleteTest);
Services.obs.addObserver(finishUp, InspectorUI.INSPECTOR_NOTIFICATIONS.CLOSED, false);
InspectorUI.highlighter.removeListener("nodeselected", deleteTest);
is(InspectorUI.selection, div, "parent node selected");
let p = doc.querySelector("P");
is(p, null, "node deleted");
InspectorUI.highlighter.addListener("nodeselected", deleteRootNode);
InspectorUI.inspectNode(doc.documentElement, true);
}
function deleteRootNode() {
InspectorUI.highlighter.removeListener("nodeselected", deleteRootNode);
let deleteNode = document.getElementById("inspectorHTMLDelete");
let commandEvent = document.createEvent("XULCommandEvent");
commandEvent.initCommandEvent("command", true, true, window, 0, false, false,
false, false, null);
deleteNode.dispatchEvent(commandEvent);
executeSoon(isRootStillAlive);
}
function isRootStillAlive() {
ok(doc.documentElement, "Document element still alive.");
Services.obs.addObserver(finishUp, InspectorUI.INSPECTOR_NOTIFICATIONS.CLOSED, false);
executeSoon(function() {
InspectorUI.closeInspectorUI();
});

View File

@ -8,6 +8,9 @@ const EXPORTED_SYMBOLS = [ "DeveloperToolbar" ];
const NS_XHTML = "http://www.w3.org/1999/xhtml";
const WEBCONSOLE_CONTENT_SCRIPT_URL =
"chrome://browser/content/devtools/HUDService-content.js";
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/Services.jsm");
@ -36,6 +39,10 @@ function DeveloperToolbar(aChromeWindow, aToolbarElement)
this._lastState = NOTIFICATIONS.HIDE;
this._pendingShowCallback = undefined;
this._pendingHide = false;
this._errorsCount = {};
this._webConsoleButton = this._doc
.getElementById("developer-toolbar-webconsole");
this._webConsoleButtonLabel = this._webConsoleButton.label;
}
/**
@ -58,6 +65,9 @@ const NOTIFICATIONS = {
*/
DeveloperToolbar.prototype.NOTIFICATIONS = NOTIFICATIONS;
DeveloperToolbar.prototype._contentMessageListeners =
["WebConsole:CachedMessages", "WebConsole:PageError"];
/**
* Is the toolbar open?
*/
@ -68,6 +78,18 @@ Object.defineProperty(DeveloperToolbar.prototype, 'visible', {
enumerable: true
});
var _gSequenceId = 0;
/**
* Getter for a unique ID.
*/
Object.defineProperty(DeveloperToolbar.prototype, 'sequenceId', {
get: function DT_visible() {
return _gSequenceId++;
},
enumerable: true
});
/**
* Called from browser.xul in response to menu-click or keyboard shortcut to
* toggle the toolbar
@ -100,6 +122,8 @@ DeveloperToolbar.prototype.show = function DT_show(aCallback)
return;
}
Services.prefs.setBoolPref("devtools.toolbar.visible", true);
this._notify(NOTIFICATIONS.LOAD);
this._pendingShowCallback = aCallback;
this._pendingHide = false;
@ -152,9 +176,13 @@ DeveloperToolbar.prototype._onload = function DT_onload()
this.display.onOutput.add(this.outputPanel._outputChanged, this.outputPanel);
this._chromeWindow.getBrowser().tabContainer.addEventListener("TabSelect", this, false);
this._chromeWindow.getBrowser().tabContainer.addEventListener("TabClose", this, false);
this._chromeWindow.getBrowser().addEventListener("load", this, true);
this._chromeWindow.getBrowser().addEventListener("beforeunload", this, true);
this._chromeWindow.addEventListener("resize", this, false);
this._initErrorsCount(this._chromeWindow.getBrowser().selectedTab);
this._element.hidden = false;
this._input.focus();
@ -178,6 +206,67 @@ DeveloperToolbar.prototype._onload = function DT_onload()
}
};
/**
* Initialize the listeners needed for tracking the number of errors for a given
* tab.
*
* @private
* @param nsIDOMNode aTab the xul:tab for which you want to track the number of
* errors.
*/
DeveloperToolbar.prototype._initErrorsCount = function DT__initErrorsCount(aTab)
{
let tabId = aTab.linkedPanel;
if (tabId in this._errorsCount) {
this._updateErrorsCount();
return;
}
let messageManager = aTab.linkedBrowser.messageManager;
messageManager.loadFrameScript(WEBCONSOLE_CONTENT_SCRIPT_URL, true);
this._errorsCount[tabId] = 0;
this._contentMessageListeners.forEach(function(aName) {
messageManager.addMessageListener(aName, this);
}, this);
let message = {
features: ["PageError"],
cachedMessages: ["PageError"],
};
this.sendMessageToTab(aTab, "WebConsole:Init", message);
this._updateErrorsCount();
};
/**
* Stop the listeners needed for tracking the number of errors for a given
* tab.
*
* @private
* @param nsIDOMNode aTab the xul:tab for which you want to stop tracking the
* number of errors.
*/
DeveloperToolbar.prototype._stopErrorsCount = function DT__stopErrorsCount(aTab)
{
let tabId = aTab.linkedPanel;
if (!(tabId in this._errorsCount)) {
this._updateErrorsCount();
return;
}
this.sendMessageToTab(aTab, "WebConsole:Destroy", {});
let messageManager = aTab.linkedBrowser.messageManager;
this._contentMessageListeners.forEach(function(aName) {
messageManager.removeMessageListener(aName, this);
}, this);
delete this._errorsCount[tabId];
this._updateErrorsCount();
};
/**
* Hide the developer toolbar.
*/
@ -194,6 +283,8 @@ DeveloperToolbar.prototype.hide = function DT_hide()
this._element.hidden = true;
Services.prefs.setBoolPref("devtools.toolbar.visible", false);
this._doc.getElementById("Tools:DevToolbar").setAttribute("checked", "false");
this.destroy();
@ -207,6 +298,11 @@ DeveloperToolbar.prototype.destroy = function DT_destroy()
{
this._chromeWindow.getBrowser().tabContainer.removeEventListener("TabSelect", this, false);
this._chromeWindow.getBrowser().removeEventListener("load", this, true);
this._chromeWindow.getBrowser().removeEventListener("beforeunload", this, true);
this._chromeWindow.removeEventListener("resize", this, false);
let tabs = this._chromeWindow.getBrowser().tabs;
Array.prototype.forEach.call(tabs, this._stopErrorsCount, this);
this.display.onVisibilityChange.remove(this.outputPanel._visibilityChanged, this.outputPanel);
this.display.onVisibilityChange.remove(this.tooltipPanel._visibilityChanged, this.tooltipPanel);
@ -261,11 +357,148 @@ DeveloperToolbar.prototype.handleEvent = function DT_handleEvent(aEvent)
contentDocument: contentDocument
},
});
if (aEvent.type == "TabSelect") {
this._initErrorsCount(aEvent.target);
}
}
}
else if (aEvent.type == "resize") {
this.outputPanel._resize();
}
else if (aEvent.type == "TabClose") {
this._stopErrorsCount(aEvent.target);
}
else if (aEvent.type == "beforeunload") {
this._onPageBeforeUnload(aEvent);
}
};
/**
* The handler of messages received from the nsIMessageManager.
*
* @param object aMessage the message received from the content process.
*/
DeveloperToolbar.prototype.receiveMessage = function DT_receiveMessage(aMessage)
{
if (!aMessage.json || !(aMessage.json.hudId in this._errorsCount)) {
return;
}
let tabId = aMessage.json.hudId;
let errors = this._errorsCount[tabId];
switch (aMessage.name) {
case "WebConsole:PageError":
this._onPageError(tabId, aMessage.json.pageError);
break;
case "WebConsole:CachedMessages":
aMessage.json.messages.forEach(this._onPageError.bind(this, tabId));
break;
}
if (errors != this._errorsCount[tabId]) {
this._updateErrorsCount(tabId);
}
};
/**
* Send a message to the content process using the nsIMessageManager of the
* given tab.
*
* @param nsIDOMNode aTab the tab you want to send a message to.
* @param string aName the name of the message you want to send.
* @param object aMessage the message to send.
*/
DeveloperToolbar.prototype.sendMessageToTab =
function DT_sendMessageToTab(aTab, aName, aMessage)
{
let tabId = aTab.linkedPanel;
aMessage.hudId = tabId;
if (!("id" in aMessage)) {
aMessage.id = "DevToolbar-" + this.sequenceId;
}
aTab.linkedBrowser.messageManager.sendAsyncMessage(aName, aMessage);
};
/**
* Process a "WebConsole:PageError" message received from the given tab. This
* method counts the JavaScript exceptions received.
*
* @private
* @param string aTabId the ID of the tab from where the page error comes.
* @param object aPageError the page error object received from the content
* process.
*/
DeveloperToolbar.prototype._onPageError =
function DT__onPageError(aTabId, aPageError)
{
if (aPageError.category == "CSS Parser" ||
aPageError.category == "CSS Loader" ||
(aPageError.flags & aPageError.warningFlag) ||
(aPageError.flags & aPageError.strictFlag)) {
return; // just a CSS or JS warning
}
this._errorsCount[aTabId]++;
};
/**
* The |beforeunload| event handler. This function resets the errors count when
* a different page starts loading.
*
* @private
* @param nsIDOMEvent aEvent the beforeunload DOM event.
*/
DeveloperToolbar.prototype._onPageBeforeUnload =
function DT__onPageBeforeUnload(aEvent)
{
let window = aEvent.target.defaultView;
if (window.top !== window) {
return;
}
let tabs = this._chromeWindow.getBrowser().tabs;
Array.prototype.some.call(tabs, function(aTab) {
if (aTab.linkedBrowser.contentWindow === window) {
let tabId = aTab.linkedPanel;
if (tabId in this._errorsCount) {
this._errorsCount[tabId] = 0;
this._updateErrorsCount(tabId);
}
return true;
}
return false;
}, this);
};
/**
* Update the page errors count displayed in the Web Console button for the
* currently selected tab.
*
* @private
* @param string [aChangedTabId] Optional. The tab ID that had its page errors
* count changed. If this is provided and it doesn't match the currently
* selected tab, then the button is not updated.
*/
DeveloperToolbar.prototype._updateErrorsCount =
function DT__updateErrorsCount(aChangedTabId)
{
let tabId = this._chromeWindow.getBrowser().selectedTab.linkedPanel;
if (aChangedTabId && tabId != aChangedTabId) {
return;
}
let errors = this._errorsCount[tabId];
if (errors) {
this._webConsoleButton.label =
this._webConsoleButtonLabel + " (" + errors + ")";
}
else {
this._webConsoleButton.label = this._webConsoleButtonLabel;
}
};
/**

View File

@ -186,8 +186,7 @@ LayoutHelpers = {
* @param integer aY
* @returns Node|null the element node found at the given coordinates.
*/
getElementFromPoint: function LH_elementFromPoint(aDocument, aX, aY)
{
getElementFromPoint: function LH_elementFromPoint(aDocument, aX, aY) {
let node = aDocument.elementFromPoint(aX, aY);
if (node && node.contentDocument) {
if (node instanceof Ci.nsIDOMHTMLIFrameElement) {
@ -214,4 +213,82 @@ LayoutHelpers = {
}
return node;
},
/**
* Scroll the document so that the element "elem" appears in the viewport.
*
* @param Element elem the element that needs to appear in the viewport.
* @param bool centered true if you want it centered, false if you want it to
* appear on the top of the viewport. It is true by default, and that is
* usually what you want.
*/
scrollIntoViewIfNeeded:
function LH_scrollIntoViewIfNeeded(elem, centered) {
// We want to default to centering the element in the page,
// so as to keep the context of the element.
centered = centered === undefined? true: !!centered;
let win = elem.ownerDocument.defaultView;
let clientRect = elem.getBoundingClientRect();
// The following are always from the {top, bottom, left, right}
// of the viewport, to the {top, …} of the box.
// Think of them as geometrical vectors, it helps.
// The origin is at the top left.
let topToBottom = clientRect.bottom;
let bottomToTop = clientRect.top - win.innerHeight;
let leftToRight = clientRect.right;
let rightToLeft = clientRect.left - win.innerWidth;
let xAllowed = true; // We allow one translation on the x axis,
let yAllowed = true; // and one on the y axis.
// Whatever `centered` is, the behavior is the same if the box is
// (even partially) visible.
if ((topToBottom > 0 || !centered) && topToBottom <= elem.offsetHeight) {
win.scrollBy(0, topToBottom - elem.offsetHeight);
yAllowed = false;
} else
if ((bottomToTop < 0 || !centered) && bottomToTop >= -elem.offsetHeight) {
win.scrollBy(0, bottomToTop + elem.offsetHeight);
yAllowed = false;
}
if ((leftToRight > 0 || !centered) && leftToRight <= elem.offsetWidth) {
if (xAllowed) {
win.scrollBy(leftToRight - elem.offsetWidth, 0);
xAllowed = false;
}
} else
if ((rightToLeft < 0 || !centered) && rightToLeft >= -elem.offsetWidth) {
if (xAllowed) {
win.scrollBy(rightToLeft + elem.offsetWidth, 0);
xAllowed = false;
}
}
// If we want it centered, and the box is completely hidden,
// then we center it explicitly.
if (centered) {
if (yAllowed && (topToBottom <= 0 || bottomToTop >= 0)) {
win.scroll(win.scrollX,
win.scrollY + clientRect.top
- (win.innerHeight - elem.offsetHeight) / 2);
}
if (xAllowed && (leftToRight <= 0 || rightToLeft <= 0)) {
win.scroll(win.scrollX + clientRect.left
- (win.innerWidth - elem.offsetWidth) / 2,
win.scrollY);
}
}
if (win.parent !== win) {
// We are inside an iframe.
LH_scrollIntoViewIfNeeded(win.frameElement, centered);
}
},
};

View File

@ -19,12 +19,17 @@ _BROWSER_TEST_FILES = \
browser_templater_basic.js \
browser_toolbar_basic.js \
browser_toolbar_tooltip.js \
browser_toolbar_webconsole_errors_count.js \
browser_layoutHelpers.js \
head.js \
$(NULL)
_BROWSER_TEST_PAGES = \
browser_templater_basic.html \
browser_toolbar_basic.html \
browser_toolbar_webconsole_errors_count.html \
browser_layoutHelpers.html \
browser_layoutHelpers_iframe.html \
$(NULL)
libs:: $(_BROWSER_TEST_FILES)

View File

@ -0,0 +1,25 @@
<!doctype html>
<meta charset=utf-8>
<title> Layout Helpers </title>
<style>
html {
height: 300%;
width: 300%;
}
div#some {
position: absolute;
background: black;
width: 2px;
height: 2px;
}
iframe {
position: absolute;
width: 40px;
height: 40px;
border: 0;
}
</style>
<div id=some></div>
<iframe id=frame src='./browser_layoutHelpers_iframe.html'></iframe>

View File

@ -0,0 +1,99 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests that scrollIntoViewIfNeeded works properly.
let imported = {};
Components.utils.import("resource:///modules/devtools/LayoutHelpers.jsm",
imported);
registerCleanupFunction(function () {
imported = {};
});
let LayoutHelpers = imported.LayoutHelpers;
const TEST_URI = "http://example.com/browser/browser/devtools/shared/test/browser_layoutHelpers.html";
function test() {
addTab(TEST_URI, function(browser, tab) {
info("Starting browser_layoutHelpers.js");
let doc = browser.contentDocument;
runTest(doc.defaultView, doc.getElementById('some'));
gBrowser.removeCurrentTab();
finish();
});
}
function runTest(win, some) {
some.style.top = win.innerHeight + 'px';
some.style.left = win.innerWidth + 'px';
// The tests start with a black 2x2 pixels square below bottom right.
// Do not resize the window during the tests.
win.scroll(win.innerWidth / 2, win.innerHeight + 2); // Above the viewport.
LayoutHelpers.scrollIntoViewIfNeeded(some);
is(win.scrollY, Math.floor(win.innerHeight / 2) + 1,
'Element completely hidden above should appear centered.');
win.scroll(win.innerWidth / 2, win.innerHeight + 1); // On the top edge.
LayoutHelpers.scrollIntoViewIfNeeded(some);
is(win.scrollY, win.innerHeight,
'Element partially visible above should appear above.');
win.scroll(win.innerWidth / 2, 0); // Just below the viewport.
LayoutHelpers.scrollIntoViewIfNeeded(some);
is(win.scrollY, Math.floor(win.innerHeight / 2) + 1,
'Element completely hidden below should appear centered.');
win.scroll(win.innerWidth / 2, 1); // On the bottom edge.
LayoutHelpers.scrollIntoViewIfNeeded(some);
is(win.scrollY, 2,
'Element partially visible below should appear below.');
win.scroll(win.innerWidth / 2, win.innerHeight + 2); // Above the viewport.
LayoutHelpers.scrollIntoViewIfNeeded(some, false);
is(win.scrollY, win.innerHeight,
'Element completely hidden above should appear above ' +
'if parameter is false.');
win.scroll(win.innerWidth / 2, win.innerHeight + 1); // On the top edge.
LayoutHelpers.scrollIntoViewIfNeeded(some, false);
is(win.scrollY, win.innerHeight,
'Element partially visible above should appear above ' +
'if parameter is false.');
win.scroll(win.innerWidth / 2, 0); // Below the viewport.
LayoutHelpers.scrollIntoViewIfNeeded(some, false);
is(win.scrollY, 2,
'Element completely hidden below should appear below ' +
'if parameter is false.');
win.scroll(win.innerWidth / 2, 1); // On the bottom edge.
LayoutHelpers.scrollIntoViewIfNeeded(some, false);
is(win.scrollY, 2,
'Element partially visible below should appear below ' +
'if parameter is false.');
// The case of iframes.
win.scroll(0, 0);
let frame = win.document.getElementById('frame');
let fwin = frame.contentWindow;
frame.style.top = win.innerHeight + 'px';
frame.style.left = win.innerWidth + 'px';
fwin.addEventListener('load', function frameLoad() {
let some = fwin.document.getElementById('some');
LayoutHelpers.scrollIntoViewIfNeeded(some);
is(win.scrollX, Math.floor(win.innerWidth / 2) + 20,
'Scrolling from an iframe should center the iframe vertically.');
is(win.scrollY, Math.floor(win.innerHeight / 2) + 20,
'Scrolling from an iframe should center the iframe horizontally.');
is(fwin.scrollX, Math.floor(fwin.innerWidth / 2) + 1,
'Scrolling from an iframe should center the element vertically.');
is(fwin.scrollY, Math.floor(fwin.innerHeight / 2) + 1,
'Scrolling from an iframe should center the element horizontally.');
}, false);
}

View File

@ -0,0 +1,19 @@
<!doctype html>
<meta charset=utf-8>
<title> Layout Helpers </title>
<style>
html {
height: 300%;
width: 300%;
}
div#some {
position: absolute;
background: black;
width: 2px;
height: 2px;
}
</style>
<div id=some></div>

View File

@ -0,0 +1,29 @@
<!DOCTYPE HTML>
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<html>
<head>
<meta charset="UTF-8">
<title>Developer Toolbar Tests - errors count in the Web Console button</title>
<script type="text/javascript">
console.log("foobarBug762996consoleLog");
window.onload = function() {
window.foobarBug762996load();
};
window.foobarBug762996a();
</script>
<script type="text/javascript">
window.foobarBug762996b();
</script>
</head>
<body>
<p>Hello world! Test for errors count in the Web Console button (developer
toolbar).</p>
<p style="color: foobarBug762996css"><button>click me</button></p>
<script type="text/javascript">
document.querySelector("button").onclick = function() {
window.foobarBug762996click();
};
</script>
</body>
</html>

View File

@ -0,0 +1,208 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests that the developer toolbar errors count works properly.
function test() {
const TEST_URI = "http://example.com/browser/browser/devtools/shared/test/browser_toolbar_webconsole_errors_count.html";
let imported = {};
Components.utils.import("resource:///modules/HUDService.jsm", imported);
let HUDService = imported.HUDService;
let webconsole = document.getElementById("developer-toolbar-webconsole");
let toolbar = document.getElementById("Tools:DevToolbar");
let tab1, tab2;
function openToolbar(browser, tab) {
tab1 = tab;
ignoreAllUncaughtExceptions(false);
ok(!DeveloperToolbar.visible, "DeveloperToolbar is not visible");
expectUncaughtException();
oneTimeObserve(DeveloperToolbar.NOTIFICATIONS.SHOW, onOpenToolbar);
toolbar.doCommand();
}
ignoreAllUncaughtExceptions();
addTab(TEST_URI, openToolbar);
function getErrorsCount() {
let match = webconsole.label.match(/\((\d+)\)$/);
return (match || [])[1];
}
function onOpenToolbar() {
ok(DeveloperToolbar.visible, "DeveloperToolbar is visible");
waitForValue({
name: "web console button shows page errors",
validator: getErrorsCount,
value: 3,
success: addErrors,
failure: finish,
});
}
function addErrors() {
expectUncaughtException();
let button = content.document.querySelector("button");
EventUtils.synthesizeMouse(button, 2, 2, {}, content);
waitForValue({
name: "button shows one more error after click in page",
validator: getErrorsCount,
value: 4,
success: function() {
ignoreAllUncaughtExceptions();
addTab(TEST_URI, onOpenSecondTab);
},
failure: finish,
});
}
function onOpenSecondTab(browser, tab) {
tab2 = tab;
ignoreAllUncaughtExceptions(false);
expectUncaughtException();
waitForValue({
name: "button shows correct number of errors after new tab is open",
validator: getErrorsCount,
value: 3,
success: switchToTab1,
failure: finish,
});
}
function switchToTab1() {
gBrowser.selectedTab = tab1;
waitForValue({
name: "button shows the page errors from tab 1",
validator: getErrorsCount,
value: 4,
success: function() {
openWebConsole(tab1, onWebConsoleOpen);
},
failure: finish,
});
}
function openWebConsole(tab, callback)
{
function _onWebConsoleOpen(subject)
{
subject.QueryInterface(Ci.nsISupportsString);
let hud = HUDService.getHudReferenceById(subject.data);
executeSoon(callback.bind(null, hud));
}
oneTimeObserve("web-console-created", _onWebConsoleOpen);
HUDService.activateHUDForContext(tab);
}
function onWebConsoleOpen(hud) {
waitForValue({
name: "web console shows the page errors",
validator: function() {
return hud.outputNode.querySelectorAll(".hud-exception").length;
},
value: 4,
success: checkConsoleOutput.bind(null, hud),
failure: finish,
});
}
function checkConsoleOutput(hud) {
let errors = ["foobarBug762996a", "foobarBug762996b", "foobarBug762996load",
"foobarBug762996click", "foobarBug762996consoleLog",
"foobarBug762996css"];
errors.forEach(function(error) {
isnot(hud.outputNode.textContent.indexOf(error), -1,
error + " found in the Web Console output");
});
hud.jsterm.clearOutput();
is(hud.outputNode.textContent.indexOf("foobarBug762996color"), -1,
"clearOutput() worked");
expectUncaughtException();
let button = content.document.querySelector("button");
EventUtils.synthesizeMouse(button, 2, 2, {}, content);
waitForValue({
name: "button shows one more error after another click in page",
validator: getErrorsCount,
value: 5,
success: function() {
waitForValue(waitForNewError);
},
failure: finish,
});
let waitForNewError = {
name: "the Web Console displays the new error",
validator: function() {
return hud.outputNode.textContent.indexOf("foobarBug762996click") > -1;
},
success: doPageReload.bind(null, hud),
failure: finish,
};
}
function doPageReload(hud) {
tab1.linkedBrowser.addEventListener("load", function _onReload() {
tab1.linkedBrowser.removeEventListener("load", _onReload, true);
ignoreAllUncaughtExceptions(false);
expectUncaughtException();
}, true);
ignoreAllUncaughtExceptions();
content.location.reload();
waitForValue({
name: "the Web Console button count has been reset after page reload",
validator: getErrorsCount,
value: 3,
success: function() {
waitForValue(waitForConsoleOutputAfterReload);
},
failure: finish,
});
let waitForConsoleOutputAfterReload = {
name: "the Web Console displays the correct number of errors after reload",
validator: function() {
return hud.outputNode.querySelectorAll(".hud-exception").length;
},
value: 4,
success: function() {
isnot(hud.outputNode.textContent.indexOf("foobarBug762996load"), -1,
"foobarBug762996load found in console output after page reload");
testEnd();
},
failure: testEnd,
};
}
function testEnd() {
document.getElementById("developer-toolbar-closebutton").doCommand();
HUDService.deactivateHUDForContext(tab1);
gBrowser.removeTab(tab1);
gBrowser.removeTab(tab2);
finish();
}
function oneTimeObserve(name, callback) {
function _onObserve(aSubject, aTopic, aData) {
Services.obs.removeObserver(_onObserve, name);
callback(aSubject, aTopic, aData);
};
Services.obs.addObserver(_onObserve, name, false);
}
}

View File

@ -131,3 +131,67 @@ function catchFail(func) {
}
};
}
/**
* Polls a given function waiting for the given value.
*
* @param object aOptions
* Options object with the following properties:
* - validator
* A validator function that should return the expected value. This is
* called every few milliseconds to check if the result is the expected
* one. When the returned result is the expected one, then the |success|
* function is called and polling stops. If |validator| never returns
* the expected value, then polling timeouts after several tries and
* a failure is recorded - the given |failure| function is invoked.
* - success
* A function called when the validator function returns the expected
* value.
* - failure
* A function called if the validator function timeouts - fails to return
* the expected value in the given time.
* - name
* Name of test. This is used to generate the success and failure
* messages.
* - timeout
* Timeout for validator function, in milliseconds. Default is 5000 ms.
* - value
* The expected value. If this option is omitted then the |validator|
* function must return a trueish value.
* Each of the provided callback functions will receive two arguments:
* the |aOptions| object and the last value returned by |validator|.
*/
function waitForValue(aOptions)
{
let start = Date.now();
let timeout = aOptions.timeout || 5000;
let lastValue;
function wait(validatorFn, successFn, failureFn)
{
if ((Date.now() - start) > timeout) {
// Log the failure.
ok(false, "Timed out while waiting for: " + aOptions.name);
let expected = "value" in aOptions ?
"'" + aOptions.value + "'" :
"a trueish value";
info("timeout info :: got '" + lastValue + "', expected " + expected);
failureFn(aOptions, lastValue);
return;
}
lastValue = validatorFn(aOptions, lastValue);
let successful = "value" in aOptions ?
lastValue == aOptions.value :
lastValue;
if (successful) {
ok(true, aOptions.name);
successFn(aOptions, lastValue);
}
else {
setTimeout(function() wait(validatorFn, successFn, failureFn), 100);
}
}
wait(aOptions.validator, aOptions.success, aOptions.failure);
}

View File

@ -131,6 +131,15 @@ const DEFAULT_KEYBINDINGS = [
},
];
if (Services.appinfo.OS == "WINNT" ||
Services.appinfo.OS == "Linux") {
DEFAULT_KEYBINDINGS.push({
action: "redo",
code: Ci.nsIDOMKeyEvent.DOM_VK_Y,
accel: true,
});
}
var EXPORTED_SYMBOLS = ["SourceEditor"];
/**

View File

@ -98,6 +98,19 @@ function editorLoaded()
is(editor.getText(), "code-editor", "Ctrl-Shift-Z (redo) works");
editor.undo();
EventUtils.synthesizeKey("VK_Y", {accelKey: true}, testWin);
if (Services.appinfo.OS == "WINNT" ||
Services.appinfo.OS == "Linux") {
is(editor.getText(), "code-editor",
"CTRL+Y does redo on Linux and Windows");
} else {
is(editor.getText(), "source-editor",
"CTRL+Y doesn't redo on machines other than Linux and Windows");
editor.setText("code-editor");
}
// Test selection methods.
editor.setSelection(0, 4);

View File

@ -88,21 +88,19 @@ let Manager = {
*/
receiveMessage: function Manager_receiveMessage(aMessage)
{
if (!_alive) {
if (!_alive || !aMessage.json) {
return;
}
if (!aMessage.json || (aMessage.name != "WebConsole:Init" &&
aMessage.json.hudId != this.hudId)) {
Cu.reportError("Web Console content script: received message " +
aMessage.name + " from wrong hudId!");
if (aMessage.name == "WebConsole:Init" && !this.hudId) {
this._onInit(aMessage.json);
return;
}
if (aMessage.json.hudId != this.hudId) {
return;
}
switch (aMessage.name) {
case "WebConsole:Init":
this._onInit(aMessage.json);
break;
case "WebConsole:EnableFeature":
this.enableFeature(aMessage.json.feature, aMessage.json);
break;
@ -1286,17 +1284,8 @@ let ConsoleListener = {
return;
}
switch (aScriptError.category) {
// We ignore chrome-originating errors as we only care about content.
case "XPConnect JavaScript":
case "component javascript":
case "chrome javascript":
case "chrome registration":
case "XBL":
case "XBL Prototype Handler":
case "XBL Content Sink":
case "xbl javascript":
return;
if (!this.isCategoryAllowed(aScriptError.category)) {
return;
}
let errorWindow =
@ -1309,6 +1298,33 @@ let ConsoleListener = {
Manager.sendMessage("WebConsole:PageError", { pageError: aScriptError });
},
/**
* Check if the given script error category is allowed to be tracked or not.
* We ignore chrome-originating errors as we only care about content.
*
* @param string aCategory
* The nsIScriptError category you want to check.
* @return boolean
* True if the category is allowed to be logged, false otherwise.
*/
isCategoryAllowed: function CL_isCategoryAllowed(aCategory)
{
switch (aCategory) {
case "XPConnect JavaScript":
case "component javascript":
case "chrome javascript":
case "chrome registration":
case "XBL":
case "XBL Prototype Handler":
case "XBL Content Sink":
case "xbl javascript":
return false;
}
return true;
},
/**
* Get the cached page errors for the current inner window.
*
@ -1326,14 +1342,15 @@ let ConsoleListener = {
(errors.value || []).forEach(function(aError) {
if (!(aError instanceof Ci.nsIScriptError) ||
aError.innerWindowID != innerWindowId) {
aError.innerWindowID != innerWindowId ||
!this.isCategoryAllowed(aError.category)) {
return;
}
let remoteMessage = WebConsoleUtils.cloneObject(aError);
remoteMessage._type = "PageError";
result.push(remoteMessage);
});
}, this);
return result;
},

View File

@ -175,11 +175,17 @@ const PREFS_PREFIX = "devtools.webconsole.filter.";
// The number of messages to display in a single display update. If we display
// too many messages at once we slow the Firefox UI too much.
const MESSAGES_IN_INTERVAL = 30;
const MESSAGES_IN_INTERVAL = DEFAULT_LOG_LIMIT;
// The delay between display updates - tells how often we should push new
// messages to screen.
const OUTPUT_INTERVAL = 90; // milliseconds
// The delay between display updates - tells how often we should *try* to push
// new messages to screen. This value is optimistic, updates won't always
// happen. Keep this low so the Web Console output feels live.
const OUTPUT_INTERVAL = 50; // milliseconds
// When the output queue has more than MESSAGES_IN_INTERVAL items we throttle
// output updates to this number of milliseconds. So during a lot of output we
// update every N milliseconds given here.
const THROTTLE_UPDATES = 1000; // milliseconds
///////////////////////////////////////////////////////////////////////////
//// Helper for creating the network panel.
@ -1034,27 +1040,28 @@ function HeadsUpDisplay(aTab)
// A cache for tracking repeated CSS Nodes.
this.cssNodes = {};
this._networkRequests = {};
this._setupMessageManager();
}
HeadsUpDisplay.prototype = {
/**
* Last time when we displayed any message in the output. Timestamp in
* milliseconds since the Unix epoch.
*
* Holds the network requests currently displayed by the Web Console. Each key
* represents the connection ID and the value is network request information.
* @private
* @type number
* @type object
*/
_lastOutputFlush: 0,
_networkRequests: null,
/**
* The number of messages displayed in the last interval. The interval is
* given by OUTPUT_INTERVAL.
* Last time when we displayed any message in the output.
*
* @private
* @type number
* Timestamp in milliseconds since the Unix epoch.
*/
_messagesDisplayedInInterval: 0,
_lastOutputFlush: 0,
/**
* Message nodes are stored here in a queue for later display.
@ -1403,11 +1410,15 @@ HeadsUpDisplay.prototype = {
aRemoteMessages.forEach(function(aMessage) {
switch (aMessage._type) {
case "PageError":
this.reportPageError(aMessage);
case "PageError": {
let category = this.categoryForScriptError(aMessage.category);
this.outputMessage(category, this.reportPageError,
[category, aMessage]);
break;
}
case "ConsoleAPI":
this.logConsoleAPIMessage(aMessage);
this.outputMessage(CATEGORY_WEBDEV, this.logConsoleAPIMessage,
[aMessage]);
break;
}
}, this);
@ -1835,7 +1846,10 @@ HeadsUpDisplay.prototype = {
*/
pruneConsoleDirNode: function HUD_pruneConsoleDirNode(aMessageNode)
{
aMessageNode.parentNode.removeChild(aMessageNode);
if (aMessageNode.parentNode) {
aMessageNode.parentNode.removeChild(aMessageNode);
}
let tree = aMessageNode.querySelector("tree");
tree.parentNode.removeChild(tree);
aMessageNode.propertyTreeView = null;
@ -1877,6 +1891,8 @@ HeadsUpDisplay.prototype = {
* information.
* - argumentsToString - the array of arguments passed to the console
* method, each converted to a string.
* @return nsIDOMElement|undefined
* The message element to display in the Web Console output.
*/
logConsoleAPIMessage: function HUD_logConsoleAPIMessage(aMessage)
{
@ -2009,19 +2025,20 @@ HeadsUpDisplay.prototype = {
}.bind(this));
}
ConsoleUtils.outputMessageNode(node, this.hudId);
if (level == "dir") {
// Initialize the inspector message node, by setting the PropertyTreeView
// object on the tree view. This has to be done *after* the node is
// shown, because the tree binding must be attached first.
let tree = node.querySelector("tree");
tree.view = node.propertyTreeView;
// Make sure the cached evaluated object will be purged when the node is
// removed.
node._evalCacheId = aMessage.objectsCacheId;
// Initialize the inspector message node, by setting the PropertyTreeView
// object on the tree view. This has to be done *after* the node is
// shown, because the tree binding must be attached first.
node._onOutput = function _onMessageOutput() {
node.querySelector("tree").view = node.propertyTreeView;
};
}
return node;
},
/**
@ -2029,37 +2046,11 @@ HeadsUpDisplay.prototype = {
*
* @param nsIScriptError aScriptError
* The error message to report.
* @return nsIDOMElement|undefined
* The message element to display in the Web Console output.
*/
reportPageError: function HUD_reportPageError(aScriptError)
reportPageError: function HUD_reportPageError(aCategory, aScriptError)
{
if (!aScriptError.outerWindowID) {
return;
}
let category;
switch (aScriptError.category) {
// We ignore chrome-originating errors as we only care about content.
case "XPConnect JavaScript":
case "component javascript":
case "chrome javascript":
case "chrome registration":
case "XBL":
case "XBL Prototype Handler":
case "XBL Content Sink":
case "xbl javascript":
return;
case "CSS Parser":
case "CSS Loader":
category = CATEGORY_CSS;
break;
default:
category = CATEGORY_JS;
break;
}
// Warnings and legacy strict errors become warnings; other types become
// errors.
let severity = SEVERITY_ERROR;
@ -2069,7 +2060,7 @@ HeadsUpDisplay.prototype = {
}
let node = ConsoleUtils.createMessageNode(this.chromeDocument,
category,
aCategory,
severity,
aScriptError.errorMessage,
this.hudId,
@ -2078,8 +2069,28 @@ HeadsUpDisplay.prototype = {
null,
null,
aScriptError.timeStamp);
return node;
},
ConsoleUtils.outputMessageNode(node, this.hudId);
/**
* Determine the category of a given nsIScriptError.
*
* @param nsIScriptError aScriptError
* The script error you want to determine the category for.
* @return CATEGORY_JS|CATEGORY_CSS
* Depending on the script error CATEGORY_JS or CATEGORY_CSS can be
* returned.
*/
categoryForScriptError: function HUD_categoryForScriptError(aScriptError)
{
switch (aScriptError.category) {
case "CSS Parser":
case "CSS Loader":
return CATEGORY_CSS;
default:
return CATEGORY_JS;
}
},
/**
@ -2087,10 +2098,17 @@ HeadsUpDisplay.prototype = {
*
* @param object aHttpActivity
* The HTTP activity to log.
* @return nsIDOMElement|undefined
* The message element to display in the Web Console output.
*/
logNetActivity: function HUD_logNetActivity(aHttpActivity)
logNetActivity: function HUD_logNetActivity(aConnectionId)
{
let entry = aHttpActivity.log.entries[0];
let networkInfo = this._networkRequests[aConnectionId];
if (!networkInfo) {
return;
}
let entry = networkInfo.httpActivity.log.entries[0];
let request = entry.request;
let msgNode = this.chromeDocument.createElementNS(XUL_NS, "hbox");
@ -2134,17 +2152,19 @@ HeadsUpDisplay.prototype = {
null,
clipboardText);
messageNode.setAttribute("connectionId", entry.connection);
messageNode._httpActivity = aHttpActivity;
messageNode._connectionId = entry.connection;
this.makeOutputMessageLink(messageNode, function HUD_net_message_link() {
if (!messageNode._panelOpen) {
HUDService.openNetworkPanel(messageNode, messageNode._httpActivity);
HUDService.openNetworkPanel(messageNode, networkInfo.httpActivity);
}
}.bind(this));
ConsoleUtils.outputMessageNode(messageNode, this.hudId);
networkInfo.node = messageNode;
this._updateNetMessage(entry.connection);
return messageNode;
},
/**
@ -2152,6 +2172,8 @@ HeadsUpDisplay.prototype = {
*
* @param string aFileURI
* The file URI that was loaded.
* @return nsIDOMElement|undefined
* The message element to display in the Web Console output.
*/
logFileActivity: function HUD_logFileActivity(aFileURI)
{
@ -2179,12 +2201,15 @@ HeadsUpDisplay.prototype = {
viewSourceUtils.viewSource(aFileURI, null, chromeDocument);
});
ConsoleUtils.outputMessageNode(outputNode, this.hudId);
return outputNode;
},
/**
* Inform user that the Web Console API has been replaced by a script
* in a content page.
*
* @return nsIDOMElement|undefined
* The message element to display in the Web Console output.
*/
logWarningAboutReplacedAPI: function HUD_logWarningAboutReplacedAPI()
{
@ -2192,7 +2217,7 @@ HeadsUpDisplay.prototype = {
let node = ConsoleUtils.createMessageNode(this.chromeDocument, CATEGORY_JS,
SEVERITY_WARNING, message,
this.hudId);
ConsoleUtils.outputMessageNode(node, this.hudId);
return node;
},
ERRORS: {
@ -2240,8 +2265,6 @@ HeadsUpDisplay.prototype = {
receiveMessage: function HUD_receiveMessage(aMessage)
{
if (!aMessage.json || aMessage.json.hudId != this.hudId) {
Cu.reportError("JSTerm: received message " + aMessage.name +
" from wrong hudId.");
return;
}
@ -2258,11 +2281,16 @@ HeadsUpDisplay.prototype = {
this.jsterm.handleInspectObject(aMessage.json);
break;
case "WebConsole:ConsoleAPI":
this.logConsoleAPIMessage(aMessage.json);
this.outputMessage(CATEGORY_WEBDEV, this.logConsoleAPIMessage,
[aMessage.json]);
break;
case "WebConsole:PageError":
this.reportPageError(aMessage.json.pageError);
case "WebConsole:PageError": {
let pageError = aMessage.json.pageError;
let category = this.categoryForScriptError(pageError);
this.outputMessage(category, this.reportPageError,
[category, pageError]);
break;
}
case "WebConsole:CachedMessages":
this._displayCachedConsoleMessages(aMessage.json.messages);
this._onInitComplete();
@ -2271,13 +2299,14 @@ HeadsUpDisplay.prototype = {
this.handleNetworkActivity(aMessage.json);
break;
case "WebConsole:FileActivity":
this.logFileActivity(aMessage.json.uri);
this.outputMessage(CATEGORY_NETWORK, this.logFileActivity,
[aMessage.json.uri]);
break;
case "WebConsole:LocationChange":
this.onLocationChange(aMessage.json);
break;
case "JSTerm:NonNativeConsoleAPI":
this.logWarningAboutReplacedAPI();
this.outputMessage(CATEGORY_JS, this.logWarningAboutReplacedAPI);
break;
}
},
@ -2371,26 +2400,69 @@ HeadsUpDisplay.prototype = {
handleNetworkActivity: function HUD_handleNetworkActivity(aMessage)
{
let stage = aMessage.meta.stages[aMessage.meta.stages.length - 1];
let entry = aMessage.log.entries[0];
if (stage == "REQUEST_HEADER") {
this.logNetActivity(aMessage);
let networkInfo = {
node: null,
httpActivity: aMessage,
};
this._networkRequests[entry.connection] = networkInfo;
this.outputMessage(CATEGORY_NETWORK, this.logNetActivity,
[entry.connection]);
return;
}
else if (!(entry.connection in this._networkRequests)) {
return;
}
let entry = aMessage.log.entries[0];
let networkInfo = this._networkRequests[entry.connection];
networkInfo.httpActivity = aMessage;
if (networkInfo.node) {
this._updateNetMessage(entry.connection);
}
// For unit tests we pass the HTTP activity object to the test callback,
// once requests complete.
if (HUDService.lastFinishedRequestCallback &&
aMessage.meta.stages.indexOf("REQUEST_STOP") > -1 &&
aMessage.meta.stages.indexOf("TRANSACTION_CLOSE") > -1) {
HUDService.lastFinishedRequestCallback(aMessage);
}
},
/**
* Update an output message to reflect the latest state of a network request,
* given a network connection ID.
*
* @private
* @param string aConnectionId
* The connection ID to update.
*/
_updateNetMessage: function HUD__updateNetMessage(aConnectionId)
{
let networkInfo = this._networkRequests[aConnectionId];
if (!networkInfo || !networkInfo.node) {
return;
}
let messageNode = networkInfo.node;
let httpActivity = networkInfo.httpActivity;
let stages = httpActivity.meta.stages;
let hasTransactionClose = stages.indexOf("TRANSACTION_CLOSE") > -1;
let hasResponseHeader = stages.indexOf("RESPONSE_HEADER") > -1;
let entry = httpActivity.log.entries[0];
let request = entry.request;
let response = entry.response;
let messageNode = this.outputNode.
querySelector("richlistitem[connectionId=" + entry.connection + "]");
if (!messageNode) {
return;
}
messageNode._httpActivity = aMessage;
if (stage == "TRANSACTION_CLOSE" || stage == "RESPONSE_HEADER") {
let status = [response.httpVersion, response.status, response.statusText];
if (stage == "TRANSACTION_CLOSE") {
if (hasTransactionClose || hasResponseHeader) {
let status = [];
if (response.httpVersion && response.status) {
status = [response.httpVersion, response.status, response.statusText];
}
if (hasTransactionClose) {
status.push(l10n.getFormatStr("NetworkPanel.durationMS", [entry.time]));
}
let statusText = "[" + status.join(" ") + "]";
@ -2402,8 +2474,7 @@ HeadsUpDisplay.prototype = {
messageNode.clipboardText = [request.method, request.url, statusText]
.join(" ");
if (stage == "RESPONSE_HEADER" &&
response.status >= MIN_HTTP_ERROR_CODE &&
if (hasResponseHeader && response.status >= MIN_HTTP_ERROR_CODE &&
response.status <= MAX_HTTP_ERROR_CODE) {
ConsoleUtils.setMessageType(messageNode, CATEGORY_NETWORK,
SEVERITY_ERROR);
@ -2413,14 +2484,6 @@ HeadsUpDisplay.prototype = {
if (messageNode._netPanel) {
messageNode._netPanel.update();
}
// For unit tests we pass the HTTP activity object to the test callback,
// once requests complete.
if (HUDService.lastFinishedRequestCallback &&
aMessage.meta.stages.indexOf("REQUEST_STOP") > -1 &&
aMessage.meta.stages.indexOf("TRANSACTION_CLOSE") > -1) {
HUDService.lastFinishedRequestCallback(aMessage);
}
},
/**
@ -2484,15 +2547,32 @@ HeadsUpDisplay.prototype = {
* Note: this call is async - the given message node may not be displayed when
* you call this method.
*
* @param nsIDOMNode aNode
* The message node to send to the output.
* @param nsIDOMNode [aNodeAfter]
* Insert the node after the given aNodeAfter (optional).
* @param integer aCategory
* The category of the message you want to output. See the CATEGORY_*
* constants.
* @param function|nsIDOMElement aMethodOrNode
* The method that creates the message element to send to the output or
* the actual element. If a method is given it will be bound to the HUD
* object and the arguments will be |aArguments|.
* @param array [aArguments]
* If a method is given to output the message element then the method
* will be invoked with the list of arguments given here.
*/
outputMessageNode: function HUD_outputMessageNode(aNode, aNodeAfter)
outputMessage: function HUD_outputMessage(aCategory, aMethodOrNode, aArguments)
{
this._outputQueue.push([aNode, aNodeAfter]);
this._flushMessageQueue();
if (!this._outputQueue.length) {
// If the queue is empty we consider that now was the last output flush.
// This avoid an immediate output flush when the timer executes.
this._lastOutputFlush = Date.now();
}
this._outputQueue.push([aCategory, aMethodOrNode, aArguments]);
if (!this._outputTimeout) {
this._outputTimeout =
this.chromeWindow.setTimeout(this._flushMessageQueue.bind(this),
OUTPUT_INTERVAL);
}
},
/**
@ -2504,23 +2584,19 @@ HeadsUpDisplay.prototype = {
*/
_flushMessageQueue: function HUD__flushMessageQueue()
{
if ((Date.now() - this._lastOutputFlush) >= OUTPUT_INTERVAL) {
this._messagesDisplayedInInterval = 0;
let timeSinceFlush = Date.now() - this._lastOutputFlush;
if (this._outputQueue.length > MESSAGES_IN_INTERVAL &&
timeSinceFlush < THROTTLE_UPDATES) {
this._outputTimeout =
this.chromeWindow.setTimeout(this._flushMessageQueue.bind(this),
OUTPUT_INTERVAL);
return;
}
// Determine how many messages we can display now.
let toDisplay = Math.min(this._outputQueue.length,
MESSAGES_IN_INTERVAL -
this._messagesDisplayedInInterval);
if (!toDisplay) {
if (!this._outputTimeout && this._outputQueue.length > 0) {
this._outputTimeout =
this.chromeWindow.setTimeout(function() {
delete this._outputTimeout;
this._flushMessageQueue();
}.bind(this), OUTPUT_INTERVAL);
}
let toDisplay = Math.min(this._outputQueue.length, MESSAGES_IN_INTERVAL);
if (toDisplay < 1) {
this._outputTimeout = null;
return;
}
@ -2533,6 +2609,7 @@ HeadsUpDisplay.prototype = {
let batch = this._outputQueue.splice(0, toDisplay);
if (!batch.length) {
this._outputTimeout = null;
return;
}
@ -2545,21 +2622,18 @@ HeadsUpDisplay.prototype = {
// Output the current batch of messages.
for (let item of batch) {
if (this._outputMessageFromQueue(hudIdSupportsString, item)) {
lastVisibleNode = item[0];
let node = this._outputMessageFromQueue(hudIdSupportsString, item);
if (node) {
lastVisibleNode = node;
}
}
// Keep track of how many messages we displayed, so we do not display too
// many at once.
this._messagesDisplayedInInterval += batch.length;
let oldScrollHeight = 0;
// Prune messages if needed. We do not do this for every flush call to
// improve performance.
let removedNodes = 0;
if (shouldPrune || !(this._outputQueue.length % 20)) {
if (shouldPrune || !this._outputQueue.length) {
oldScrollHeight = scrollBox.scrollHeight;
let categories = Object.keys(this._pruneCategoriesQueue);
@ -2592,12 +2666,13 @@ HeadsUpDisplay.prototype = {
}
// If the queue is not empty, schedule another flush.
if (!this._outputTimeout && this._outputQueue.length > 0) {
if (this._outputQueue.length > 0) {
this._outputTimeout =
this.chromeWindow.setTimeout(function() {
delete this._outputTimeout;
this._flushMessageQueue();
}.bind(this), OUTPUT_INTERVAL);
this.chromeWindow.setTimeout(this._flushMessageQueue.bind(this),
OUTPUT_INTERVAL);
}
else {
this._outputTimeout = null;
}
this._lastOutputFlush = Date.now();
@ -2611,13 +2686,26 @@ HeadsUpDisplay.prototype = {
* The HUD ID as an nsISupportsString.
* @param array aItem
* An item from the output queue - this item represents a message.
* @return boolean
* True if the message is visible, false otherwise.
* @return nsIDOMElement|undefined
* The DOM element of the message if the message is visible, undefined
* otherwise.
*/
_outputMessageFromQueue:
function HUD__outputMessageFromQueue(aHudIdSupportsString, aItem)
{
let [node, afterNode] = aItem;
let [category, methodOrNode, args] = aItem;
let node = typeof methodOrNode == "function" ?
methodOrNode.apply(this, args || []) :
methodOrNode;
if (!node) {
return;
}
let afterNode = node._outputAfterNode;
if (afterNode) {
delete node._outputAfterNode;
}
let isFiltered = ConsoleUtils.filterMessageNode(node, this.hudId);
@ -2628,23 +2716,33 @@ HeadsUpDisplay.prototype = {
}
if (!isRepeated &&
!node.classList.contains("webconsole-msg-network") &&
(node.classList.contains("webconsole-msg-console") ||
node.classList.contains("webconsole-msg-exception") ||
node.classList.contains("webconsole-msg-error"))) {
isRepeated = ConsoleUtils.filterRepeatedConsole(node, this.outputNode);
}
let lastVisible = !isRepeated && !isFiltered;
if (!isRepeated) {
this.outputNode.insertBefore(node,
afterNode ? afterNode.nextSibling : null);
this._pruneCategoriesQueue[node.category] = true;
if (afterNode) {
lastVisible = this.outputNode.lastChild == node;
}
}
if (node._onOutput) {
node._onOutput();
delete node._onOutput;
}
let nodeID = node.getAttribute("id");
Services.obs.notifyObservers(aHudIdSupportsString,
"web-console-message-created", nodeID);
return !isRepeated && !isFiltered;
return lastVisible ? node : null;
},
/**
@ -2658,8 +2756,7 @@ HeadsUpDisplay.prototype = {
// Group the messages per category.
this._outputQueue.forEach(function(aItem, aIndex) {
let [node] = aItem;
let category = node.category;
let [category] = aItem;
if (!(category in nodes)) {
nodes[category] = [];
}
@ -2676,7 +2773,7 @@ HeadsUpDisplay.prototype = {
let n = Math.max(0, indexes.length - limit);
pruned += n;
for (let i = n - 1; i >= 0; i--) {
let node = this._outputQueue[indexes[i]][0];
this._pruneItemFromQueue(this._outputQueue[indexes[i]]);
this._outputQueue.splice(indexes[i], 1);
}
}
@ -2685,6 +2782,42 @@ HeadsUpDisplay.prototype = {
return pruned;
},
/**
* Prune an item from the output queue.
*
* @private
* @param array aItem
* The item you want to remove from the output queue.
*/
_pruneItemFromQueue: function HUD__pruneItemFromQueue(aItem)
{
let [category, methodOrNode, args] = aItem;
if (typeof methodOrNode != "function" &&
methodOrNode._evalCacheId && !methodOrNode._panelOpen) {
this.jsterm.clearObjectCache(methodOrNode._evalCacheId);
}
if (category == CATEGORY_NETWORK) {
let connectionId = null;
if (methodOrNode == this.logNetActivity) {
connectionId = args[0];
}
else if (typeof methodOrNode != "function") {
connectionId = methodOrNode._connectionId;
}
if (connectionId && connectionId in this._networkRequests) {
delete this._networkRequests[connectionId];
}
}
else if (category == CATEGORY_WEBDEV &&
methodOrNode == this.logConsoleAPIMessage) {
let level = args[0].apiMessage.level;
if (level == "dir") {
this.jsterm.clearObjectCache(args[0].objectsCacheId);
}
}
},
/**
* Retrieve the limit of messages for a specific category.
*
@ -2728,12 +2861,17 @@ HeadsUpDisplay.prototype = {
}
delete this.cssNodes[desc + location];
}
else if (aNode.classList.contains("webconsole-msg-network")) {
delete this._networkRequests[aNode._connectionId];
}
else if (aNode.classList.contains("webconsole-msg-inspector")) {
this.pruneConsoleDirNode(aNode);
return;
}
aNode.parentNode.removeChild(aNode);
if (aNode.parentNode) {
aNode.parentNode.removeChild(aNode);
}
},
/**
@ -2742,8 +2880,6 @@ HeadsUpDisplay.prototype = {
*/
destroy: function HUD_destroy()
{
this._outputQueue = [];
this.sendMessageToContent("WebConsole:Destroy", {});
this._messageListeners.forEach(function(aName) {
@ -3125,8 +3261,8 @@ JSTerm.prototype = {
aSeverity, aOutputMessage,
this.hudId, null, null, null,
null, aTimestamp);
ConsoleUtils.outputMessageNode(node, this.hudId, aNodeAfter);
node._outputAfterNode = aNodeAfter;
this.hud.outputMessage(aCategory, node);
return node;
},
@ -3140,8 +3276,6 @@ JSTerm.prototype = {
clearOutput: function JST_clearOutput(aClearStorage)
{
let hud = this.hud;
hud.cssNodes = {};
let outputNode = hud.outputNode;
let node;
while ((node = outputNode.firstChild)) {
@ -3150,6 +3284,10 @@ JSTerm.prototype = {
hud.HUDBox.lastTimestamp = 0;
hud.groupDepth = 0;
hud._outputQueue.forEach(hud._pruneItemFromQueue, hud);
hud._outputQueue = [];
hud._networkRequests = {};
hud.cssNodes = {};
if (aClearStorage) {
hud.sendMessageToContent("ConsoleAPI:ClearCache", {});
@ -4247,7 +4385,8 @@ ConsoleUtils = {
let lastMessage = aOutput.lastChild;
// childNodes[2] is the description element
if (lastMessage && !aNode.classList.contains("webconsole-msg-inspector") &&
if (lastMessage && lastMessage.childNodes[2] &&
!aNode.classList.contains("webconsole-msg-inspector") &&
aNode.childNodes[2].textContent ==
lastMessage.childNodes[2].textContent) {
this.mergeFilteredMessageNode(lastMessage, aNode);
@ -4257,23 +4396,6 @@ ConsoleUtils = {
return false;
},
/**
* Filters a node appropriately, then sends it to the output, regrouping and
* pruning output as necessary.
*
* @param nsIDOMNode aNode
* The message node to send to the output.
* @param string aHUDId
* The ID of the HUD in which to insert this node.
* @param nsIDOMNode [aNodeAfter]
* Insert the node after the given aNodeAfter (optional).
*/
outputMessageNode:
function ConsoleUtils_outputMessageNode(aNode, aHUDId, aNodeAfter) {
let hud = HUDService.getHudReferenceById(aHUDId);
hud.outputMessageNode(aNode, aNodeAfter);
},
/**
* Check if the given output node is scrolled to the bottom.
*

View File

@ -23,26 +23,48 @@ function testOpenUI(aTestReopen)
// test to see if the messages are
// displayed when the console UI is opened
let messages = {
"log Bazzle" : false,
"error Bazzle" : false,
"bazBug611032" : false,
"cssColorBug611032" : false,
};
openConsole(null, function(hud) {
testLogEntry(hud.outputNode, "log Bazzle",
"Find a console log entry from before console UI is opened",
false, null);
testLogEntry(hud.outputNode, "error Bazzle",
"Find a console error entry from before console UI is opened",
false, null);
testLogEntry(hud.outputNode, "bazBug611032", "Found the JavaScript error");
testLogEntry(hud.outputNode, "cssColorBug611032", "Found the CSS error");
HUDService.deactivateHUDForContext(gBrowser.selectedTab);
if (aTestReopen) {
HUDService.deactivateHUDForContext(gBrowser.selectedTab);
executeSoon(testOpenUI);
}
else {
executeSoon(finish);
}
waitForSuccess({
name: "cached messages displayed",
validatorFn: function()
{
let foundAll = true;
for (let msg in messages) {
let found = messages[msg];
if (!found) {
found = hud.outputNode.textContent.indexOf(msg) > -1;
if (found) {
info("found message '" + msg + "'");
messages[msg] = found;
}
}
foundAll = foundAll && found;
}
return foundAll;
},
successFn: function()
{
closeConsole(gBrowser.selectedTab, function() {
aTestReopen && info("will reopen the Web Console");
executeSoon(aTestReopen ? testOpenUI : finishTest);
});
},
failureFn: function()
{
for (let msg in messages) {
if (!messages[msg]) {
ok(false, "failed to find '" + msg + "'");
}
}
finishTest();
},
});
});
}

View File

@ -13,15 +13,22 @@ function test() {
function tabLoaded() {
browser.removeEventListener("load", tabLoaded, true);
openConsole(null, function() {
browser.addEventListener("load", tabReloaded, true);
openConsole(null, function(hud) {
content.location.reload();
waitForSuccess({
name: "stacktrace message",
validatorFn: function()
{
return hud.outputNode.querySelector(".hud-log");
},
successFn: performChecks,
failureFn: finishTest,
});
});
}
function tabReloaded() {
browser.removeEventListener("load", tabReloaded, true);
function performChecks() {
// The expected stack trace object.
let stacktrace = [
{ filename: TEST_URI, lineNumber: 9, functionName: null, language: 2 },

View File

@ -27,6 +27,19 @@ function testSelectionWhenMovingBetweenBoxes(hud) {
jsterm.execute("3 + 4");
jsterm.execute("5 + 6");
waitForSuccess({
name: "execution results displayed",
validatorFn: function()
{
return hud.outputNode.textContent.indexOf("5 + 6") > -1 &&
hud.outputNode.textContent.indexOf("11") > -1;
},
successFn: performTestsAfterOutput.bind(null, hud),
failureFn: finishTest,
});
}
function performTestsAfterOutput(hud) {
let outputNode = hud.outputNode;
ok(outputNode.childNodes.length >= 3, "the output node has children after " +
@ -67,4 +80,3 @@ function testSelectionWhenMovingBetweenBoxes(hud) {
finishTest();
}

View File

@ -14,27 +14,33 @@ const TEST_URI = "data:text/html;charset=utf-8,<div style='font-size:3em;" +
function onContentLoaded()
{
browser.removeEventListener("load", arguments.callee, true);
browser.removeEventListener("load", onContentLoaded, true);
let HUD = HUDService.getHudByWindow(content);
let hudId = HUD.hudId;
let outputNode = HUD.outputNode;
let msg = "the unknown CSS property warning is displayed";
testLogEntry(outputNode, "foobarCssParser", msg, true);
HUD.jsterm.clearOutput();
HUDService.setFilterState(hudId, "cssparser", false);
waitForSuccess({
name: "css error displayed",
validatorFn: function()
{
return outputNode.textContent.indexOf("foobarCssParser") > -1;
},
successFn: function()
{
HUDService.setFilterState(hudId, "cssparser", false);
executeSoon(
function (){
let msg = "the unknown CSS property warning is not displayed, " +
"after filtering";
testLogEntry(outputNode, "foobarCssParser", msg, true, true);
HUDService.setFilterState(hudId, "cssparser", true);
finishTest();
}
);
},
failureFn: finishTest,
});
}
/**
@ -44,8 +50,8 @@ function onContentLoaded()
function test()
{
addTab(TEST_URI);
browser.addEventListener("load", function() {
browser.removeEventListener("load", arguments.callee, true);
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
openConsole();
browser.addEventListener("load", onContentLoaded, true);

View File

@ -42,18 +42,31 @@ function tab1Reloaded(aEvent) {
let hud1 = HUDService.getHudByWindow(tab1.linkedBrowser.contentWindow);
let outputNode1 = hud1.outputNode;
let msg = "Found the iframe network request in tab1";
testLogEntry(outputNode1, TEST_IFRAME_URI, msg, true);
waitForSuccess({
name: "iframe network request displayed in tab1",
validatorFn: function()
{
let selector = ".webconsole-msg-url[value='" + TEST_IFRAME_URI +"']";
return outputNode1.querySelector(selector);
},
successFn: function()
{
let hud2 = HUDService.getHudByWindow(tab2.linkedBrowser.contentWindow);
let outputNode2 = hud2.outputNode;
let hud2 = HUDService.getHudByWindow(tab2.linkedBrowser.contentWindow);
let outputNode2 = hud2.outputNode;
isnot(outputNode1, outputNode2,
"the two HUD outputNodes must be different");
isnot(outputNode1, outputNode2,
"the two HUD outputNodes must be different");
let msg = "Didn't find the iframe network request in tab2";
testLogEntry(outputNode2, TEST_IFRAME_URI, msg, true, true);
msg = "Didn't find the iframe network request in tab2";
testLogEntry(outputNode2, TEST_IFRAME_URI, msg, true, true);
testEnd();
},
failureFn: testEnd,
});
}
function testEnd() {
closeConsole(tab2, function() {
gBrowser.removeTab(tab2);
tab1 = tab2 = null;

View File

@ -27,13 +27,23 @@ function consoleOpened(aHud) {
function tabLoad2(aEvent) {
browser.removeEventListener(aEvent.type, tabLoad2, true);
outputItem = outputNode.querySelector(".hud-networkinfo .hud-clickable");
ok(outputItem, "found a network message");
document.addEventListener("popupshown", networkPanelShown, false);
waitForSuccess({
name: "network message displayed",
validatorFn: function()
{
return outputNode.querySelector(".hud-networkinfo .hud-clickable");
},
successFn: function() {
outputItem = outputNode.querySelector(".hud-networkinfo .hud-clickable");
ok(outputItem, "found a network message");
document.addEventListener("popupshown", networkPanelShown, false);
// Send the mousedown and click events such that the network panel opens.
EventUtils.sendMouseEvent({type: "mousedown"}, outputItem);
EventUtils.sendMouseEvent({type: "click"}, outputItem);
// Send the mousedown and click events such that the network panel opens.
EventUtils.sendMouseEvent({type: "mousedown"}, outputItem);
EventUtils.sendMouseEvent({type: "click"}, outputItem);
},
failureFn: finishTest,
});
}
function networkPanelShown(aEvent) {

View File

@ -9,13 +9,23 @@ function tabReload(aEvent) {
browser.removeEventListener(aEvent.type, tabReload, true);
outputNode = hud.outputNode;
findLogEntry("test-network.html");
findLogEntry("test-image.png");
findLogEntry("testscript.js");
isnot(outputNode.textContent.indexOf("running network console logging tests"), -1,
"found the console.log() message from testscript.js");
executeSoon(finishTest);
waitForSuccess({
name: "console.log() message displayed",
validatorFn: function()
{
return outputNode.textContent
.indexOf("running network console logging tests") > -1;
},
successFn: function()
{
findLogEntry("test-network.html");
findLogEntry("test-image.png");
findLogEntry("testscript.js");
finishTest();
},
failureFn: finishTest,
});
}
function test() {
@ -32,6 +42,7 @@ function test() {
browser.removeEventListener("load", tabLoad, true);
openConsole(null, function(aHud) {
hud = aHud;
hud.jsterm.clearOutput();
browser.addEventListener("load", tabReload, true);
content.location.reload();
});

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