Merge mozilla-central into services-central

This commit is contained in:
Gregory Szorc 2012-06-18 11:58:43 -07:00
commit 9c12eea8ed
576 changed files with 18775 additions and 7110 deletions

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

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

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

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

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

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

@ -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);
@ -439,9 +404,8 @@ pref("b2g.remote-js.port", 9999);
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

@ -580,3 +580,73 @@ window.addEventListener('ContentStart', function(evt) {
});
})();
// This is the backend for Gaia's screenshot feature.
// Gaia requests a screenshot by sending a mozContentEvent with
// detail.type set to 'save-screenshot'. Then we take a screenshot
// save it in device storage (external) and send a mozChromeEvent with
// detail.type set to 'saved-screenshot' and detail.filename set to
// the filename.
window.addEventListener('ContentStart', function ss_onContentStart() {
content.addEventListener('mozContentEvent', function ss_onMozContentEvent(e) {
if (e.detail.type !== 'save-screenshot')
return;
try {
var canvas = document.createElementNS('http://www.w3.org/1999/xhtml',
'canvas');
var width = window.innerWidth;
var height = window.innerHeight;
canvas.setAttribute('width', width);
canvas.setAttribute('height', height);
var context = canvas.getContext('2d');
var flags =
context.DRAWWINDOW_DRAW_CARET |
context.DRAWWINDOW_DRAW_VIEW |
context.DRAWWINDOW_USE_WIDGET_LAYERS;
context.drawWindow(window, 0, 0, width, height,
'rgb(255,255,255)', flags);
var filename = 'screenshots/' +
new Date().toISOString().slice(0,-5).replace(/[:T]/g, '-') +
'.png';
var file = canvas.mozGetAsFile(filename, 'image/png');
var storage = navigator.getDeviceStorage('pictures')[0];
if (!storage) { // If we don't have an SD card to save to, send an error
shell.sendEvent(content, 'mozChromeEvent', {
type: 'save-screenshot-no-card'
});
return;
}
var saveRequest = storage.addNamed(file, filename);
saveRequest.onsuccess = function ss_onsuccess() {
try {
shell.sendEvent(content, 'mozChromeEvent', {
type: 'save-screenshot-success',
filename: filename
});
} catch(e) {
dump('exception in onsuccess ' + e + '\n');
}
};
saveRequest.onerror = function ss_onerror() {
try {
shell.sendEvent(content, 'mozChromeEvent', {
type: 'save-screenshot-error',
error: saveRequest.error.name
});
} catch(e) {
dump('exception in onerror ' + e + '\n');
}
};
} catch(e) {
dump('exception while saving screenshot: ' + e + '\n');
shell.sendEvent(content, 'mozChromeEvent', {
type: 'save-screenshot-error',
error: String(e)
});
}
});
});

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"
@ -90,6 +91,7 @@ XRE_FreeAppDataType XRE_FreeAppData;
XRE_SetupDllBlocklistType XRE_SetupDllBlocklist;
#endif
XRE_TelemetryAccumulateType XRE_TelemetryAccumulate;
XRE_StartupTimelineRecordType XRE_StartupTimelineRecord;
XRE_mainType XRE_main;
static const nsDynamicFunctionLoad kXULFuncs[] = {
@ -100,6 +102,7 @@ static const nsDynamicFunctionLoad kXULFuncs[] = {
{ "XRE_SetupDllBlocklist", (NSFuncPtr*) &XRE_SetupDllBlocklist },
#endif
{ "XRE_TelemetryAccumulate", (NSFuncPtr*) &XRE_TelemetryAccumulate },
{ "XRE_StartupTimelineRecord", (NSFuncPtr*) &XRE_StartupTimelineRecord },
{ "XRE_main", (NSFuncPtr*) &XRE_main },
{ nsnull, nsnull }
};
@ -189,8 +192,31 @@ bool IsPrefetchDisabledViaService()
}
#endif
/* Local implementation of PR_Now, since the executable can't depend on NSPR */
static PRTime _PR_Now()
{
#ifdef XP_WIN
MOZ_STATIC_ASSERT(sizeof(PRTime) == sizeof(FILETIME), "PRTime must have the same size as FILETIME");
FILETIME ft;
GetSystemTimeAsFileTime(&ft);
PRTime now;
CopyMemory(&now, &ft, sizeof(PRTime));
#ifdef __GNUC__
return (now - 116444736000000000LL) / 10LL;
#else
return (now - 116444736000000000i64) / 10i64;
#endif
#else
struct timeval tm;
gettimeofday(&tm, 0);
return (((PRTime)tm.tv_sec * 1000000LL) + (PRTime)tm.tv_usec);
#endif
}
int main(int argc, char* argv[])
{
PRTime start = _PR_Now();
char exePath[MAXPATHLEN];
#ifdef XP_MACOSX
@ -216,28 +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, PRELOAD_IOCOUNT };
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;
// GetProcessIoCounters().ReadOperationCount seems to have little to
// do with actual read operations. It reports 0 or 1 at this stage
// in the program. Luckily 1 coincides with when prefetch is
// enabled. If Windows prefetch didn't happen we can do our own
// faster dll preloading.
// The MozillaMaintenance service issues a command to disable the
// prefetch by replacing all found .pf files with 0 byte read only
// files.
IO_COUNTERS ioCounters;
gotCounters = GetProcessIoCounters(GetCurrentProcess(), &ioCounters);
srand(time(NULL));
bool shouldUsePreload = rand() % 2 == 0;
if (IsPrefetchDisabledViaService()) {
preloadReason = PRELOAD_SERVICE;
} else if ((gotCounters && !ioCounters.ReadOperationCount)) {
preloadReason = PRELOAD_IOCOUNT;
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();
@ -257,13 +289,15 @@ int main(int argc, char* argv[])
return 255;
}
XRE_StartupTimelineRecord(mozilla::StartupTimeline::START, start);
#ifdef XRE_HAS_DLL_BLOCKLIST
XRE_SetupDllBlocklist();
#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) {

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

@ -45,6 +45,7 @@ let test_expectedType;
let test_expectedDirection;
let test_expectedDelta;
let test_expectedModifiers;
let test_expectedClickCount;
function test_gestureListener(evt)
{
@ -75,6 +76,10 @@ function test_gestureListener(evt)
is(evt.metaKey, (test_expectedModifiers & Components.interfaces.nsIDOMNSEvent.META_MASK) != 0,
"evt.metaKey did not match expected value");
if (evt.type == "MozTapGesture") {
is(evt.clickCount, test_expectedClickCount, "evt.clickCount does not match");
}
test_eventCount++;
}
@ -95,6 +100,24 @@ function test_helper1(type, direction, delta, modifiers)
is(expectedEventCount, test_eventCount, "Event (" + type + ") was never received by event listener");
}
function test_clicks(type, clicks)
{
// Setup the expected values
test_expectedType = type;
test_expectedDirection = 0;
test_expectedDelta = 0;
test_expectedModifiers = 0;
test_expectedClickCount = clicks;
let expectedEventCount = test_eventCount + 1;
document.addEventListener(type, test_gestureListener, true);
test_utils.sendSimpleGestureEvent(type, 20, 20, 0, 0, 0, clicks);
document.removeEventListener(type, test_gestureListener, true);
is(expectedEventCount, test_eventCount, "Event (" + type + ") was never received by event listener");
}
function test_TestEventListeners()
{
let e = test_helper1; // easier to type this name
@ -126,8 +149,13 @@ function test_TestEventListeners()
e("MozRotateGesture", SimpleGestureEvent.ROTATION_CLOCKWISE, 33.0, 0);
// Tap and presstap gesture events
e("MozTapGesture", 0, 0.0, 0);
e("MozPressTapGesture", 0, 0.0, 0);
test_clicks("MozTapGesture", 1);
test_clicks("MozTapGesture", 2);
test_clicks("MozTapGesture", 3);
test_clicks("MozPressTapGesture", 1);
// simple delivery test for edgeui gesture
e("MozEdgeUIGesture", 0, 0, 0);
// event.shiftKey
let modifier = Components.interfaces.nsIDOMNSEvent.SHIFT_MASK;
@ -171,7 +199,7 @@ function test_helper2(type, direction, delta, altKey, ctrlKey, shiftKey, metaKey
10, 10, 10, 10,
ctrlKey, altKey, shiftKey, metaKey,
1, window,
direction, delta);
direction, delta, 0);
successful = true;
}
catch (ex) {

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

@ -38,7 +38,7 @@ function getMigrationBundle() {
}
/**
* Figure out what is the default browser, and if there is a migraotr
* Figure out what is the default browser, and if there is a migrator
* for it, return that migrator's internal name.
* For the time being, the "internal name" of a migraotr is its contract-id
* trailer (e.g. ie for @mozilla.org/profile/migrator;1?app=browser&type=ie),
@ -448,7 +448,8 @@ let MigrationUtils = Object.freeze({
* @param aKey internal name of the migration source.
* Supported values: ie (windows),
* safari (mac/windows),
* chrome (mac/windows/linux).
* chrome (mac/windows/linux),
* firefox.
*
* If null is returned, either no data can be imported
* for the given migrator, or aMigratorKey is invalid (e.g. ie on mac,
@ -468,13 +469,39 @@ let MigrationUtils = Object.freeze({
migrator = Cc["@mozilla.org/profile/migrator;1?app=browser&type=" +
aKey].createInstance(Ci.nsIBrowserProfileMigrator);
}
catch(ex) { Cu.reportError(ex); }
catch(ex) { }
this._migrators.set(aKey, migrator);
}
return migrator && migrator.sourceExists ? migrator : null;
},
// Iterates the available migrators, in the most suitable
// order for the running platform.
get migrators() {
let migratorKeysOrdered = [
#ifdef XP_WIN
"ie", "chrome", "safari"
#elifdef XP_MACOSX
"safari", "chrome"
#elifdef XP_UNIX
"chrome"
#endif
];
// If a supported default browser is found check it first
// so that the wizard defaults to import from that browser.
let defaultBrowserKey = getMigratorKeyForDefaultBrowser();
if (defaultBrowserKey)
migratorKeysOrdered.sort(function (a, b) b == defaultBrowserKey ? 1 : 0);
for (let migratorKey of migratorKeysOrdered) {
let migrator = this.getMigrator(migratorKey);
if (migrator)
yield migrator;
}
},
// Whether or not we're in the process of startup migration
get isStartupMigration() gProfileStartup != null,
@ -568,6 +595,20 @@ let MigrationUtils = Object.freeze({
}
}
if (!migrator) {
// If there's no migrator set so far, ensure that there is at least one
// migrator available before opening the wizard.
try {
this.migrators.next();
}
catch(ex) {
this.finishMigration();
if (!(ex instanceof StopIteration))
throw ex;
return;
}
}
let params = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
let keyCSTR = Cc["@mozilla.org/supports-cstring;1"].
createInstance(Ci.nsISupportsCString);

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
@ -862,7 +862,7 @@ let AboutHomeUtils = {
loadSnippetsURL: function AHU_loadSnippetsURL()
{
const STARTPAGE_VERSION = 2;
const STARTPAGE_VERSION = 3;
let updateURL = Services.prefs
.getCharPref(this.SNIPPETS_URL_PREF)
.replace("%STARTPAGE_VERSION%", STARTPAGE_VERSION);

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
@ -603,20 +604,6 @@ DynSHOpenWithDialog(HWND hwndParent, const OPENASINFO *poainfo)
NS_IMETHODIMP
nsWindowsShellService::SetDefaultBrowser(bool aClaimAllTypes, bool aForAllUsers)
{
if (IsWin8OrLater()) {
OPENASINFO info;
info.pcszFile = L"http";
info.pcszClass = NULL;
info.oaifInFlags = OAIF_FORCE_REGISTRATION |
OAIF_URL_PROTOCOL |
OAIF_REGISTER_EXT;
nsresult rv = DynSHOpenWithDialog(NULL, &info);
NS_ENSURE_SUCCESS(rv, rv);
bool isDefaultBrowser = false;
return SUCCEEDED(IsDefaultBrowser(&isDefaultBrowser)) &&
isDefaultBrowser ? S_OK : NS_ERROR_FAILURE;
}
nsAutoString appHelperPath;
if (NS_FAILED(GetHelperPath(appHelperPath)))
return NS_ERROR_FAILURE;
@ -627,7 +614,21 @@ nsWindowsShellService::SetDefaultBrowser(bool aClaimAllTypes, bool aForAllUsers)
appHelperPath.AppendLiteral(" /SetAsDefaultAppUser");
}
return LaunchHelper(appHelperPath);
nsresult rv = LaunchHelper(appHelperPath);
if (NS_SUCCEEDED(rv) && IsWin8OrLater()) {
OPENASINFO info;
info.pcszFile = L"http";
info.pcszClass = NULL;
info.oaifInFlags = OAIF_FORCE_REGISTRATION |
OAIF_URL_PROTOCOL |
OAIF_REGISTER_EXT;
nsresult rv = DynSHOpenWithDialog(NULL, &info);
NS_ENSURE_SUCCESS(rv, rv);
bool isDefaultBrowser = false;
rv = NS_SUCCEEDED(IsDefaultBrowser(&isDefaultBrowser)) &&
isDefaultBrowser ? S_OK : NS_ERROR_FAILURE;
}
return rv;
}
NS_IMETHODIMP
@ -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

@ -1,6 +1,7 @@
ac_add_options --enable-debug
ac_add_options --enable-trace-malloc
ac_add_options --enable-signmar
ENABLE_MARIONETTE=1
. $topsrcdir/build/unix/mozconfig.linux

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

@ -1,6 +1,7 @@
ac_add_options --enable-debug
ac_add_options --enable-trace-malloc
ac_add_options --enable-signmar
ENABLE_MARIONETTE=1
. $topsrcdir/build/unix/mozconfig.linux

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

@ -2,6 +2,7 @@
ac_add_options --enable-debug
ac_add_options --enable-trace-malloc
ac_add_options --enable-signmar
ENABLE_MARIONETTE=1
# Enable parallel compiling
mk_add_options MOZ_MAKE_FLAGS="-j12"

View File

@ -4,6 +4,7 @@ ac_add_options --enable-debug
ac_add_options --enable-trace-malloc
ac_add_options --enable-accessibility
ac_add_options --enable-signmar
ENABLE_MARIONETTE=1
# Enable parallel compiling
mk_add_options MOZ_MAKE_FLAGS="-j12"

View File

@ -1,6 +1,7 @@
ac_add_options --enable-debug
ac_add_options --enable-trace-malloc
ac_add_options --enable-signmar
ENABLE_MARIONETTE=1
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1

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

@ -4,6 +4,7 @@ ac_add_options --host=x86_64-pc-mingw32
ac_add_options --enable-debug
ac_add_options --enable-trace-malloc
ac_add_options --enable-signmar
ENABLE_MARIONETTE=1
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1

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

@ -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
@ -152,9 +174,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 +204,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.
*/
@ -207,6 +294,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 +353,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

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

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

View File

@ -40,68 +40,69 @@ const TESTS = [
},
},
{ // #5
file: "test-bug-595934-workers.html",
category: "Web Worker",
matchString: "fooBarWorker",
expectError: true,
},
{ // #6
file: "test-bug-595934-malformedxml.xhtml",
category: "malformed-xml",
matchString: "no element found",
},
{ // #6
{ // #7
file: "test-bug-595934-svg.xhtml",
category: "SVG",
matchString: "fooBarSVG",
},
{ // #7
{ // #8
file: "test-bug-595934-dom-html-external.html",
category: "DOM:HTML",
matchString: "document.all",
},
{ // #8
{ // #9
file: "test-bug-595934-dom-events-external2.html",
category: "DOM Events",
matchString: "preventBubble()",
},
{ // #9
{ // #10
file: "test-bug-595934-canvas.html",
category: "Canvas",
matchString: "strokeStyle",
},
{ // #10
{ // #11
file: "test-bug-595934-css-parser.html",
category: "CSS Parser",
matchString: "foobarCssParser",
},
{ // #11
{ // #12
file: "test-bug-595934-malformedxml-external.html",
category: "malformed-xml",
matchString: "</html>",
},
{ // #12
{ // #14
file: "test-bug-595934-empty-getelementbyid.html",
category: "DOM",
matchString: "getElementById",
},
{ // #13
{ // #15
file: "test-bug-595934-canvas-css.html",
category: "CSS Parser",
matchString: "foobarCanvasCssParser",
},
{ // #14
{ // #16
file: "test-bug-595934-image.html",
category: "Image",
matchString: "corrupt",
},
// TODO: disabled due to Bug 760837 - intermittent failures.
//{ // #15
// file: "test-bug-595934-workers.html",
// category: "Web Worker",
// matchString: "fooBarWorker",
// expectError: true,
//},
];
let pos = -1;
let foundCategory = false;
let foundText = false;
let pageLoaded = false;
let pageError = false;
let output = null;
let jsterm = null;
let testEnded = false;
@ -120,15 +121,11 @@ let TestObserver = {
if (aSubject.category == TESTS[pos].category) {
foundCategory = true;
if (foundText) {
executeSoon(testNext);
}
}
else {
ok(false, aSubject.sourceName + ':' + aSubject.lineNumber + '; ' +
aSubject.errorMessage);
testEnded = true;
executeSoon(finishTest);
}
}
};
@ -149,23 +146,47 @@ function testNext() {
jsterm.clearOutput();
foundCategory = false;
foundText = false;
pageLoaded = false;
pageError = false;
pos++;
if (pos < TESTS.length) {
waitForSuccess({
name: "test #" + pos + " succesful finish",
validatorFn: function()
{
return foundCategory && foundText && pageLoaded && pageError;
},
successFn: testNext,
failureFn: function() {
info("foundCategory " + foundCategory + " foundText " + foundText +
" pageLoaded " + pageLoaded + " pageError " + pageError);
finishTest();
},
});
let test = TESTS[pos];
let testLocation = TESTS_PATH + test.file;
if (test.onload) {
browser.addEventListener("load", function onLoad(aEvent) {
if (content.location.href == testLocation) {
browser.removeEventListener(aEvent.type, onLoad, true);
test.onload(aEvent);
}
}, true);
}
browser.addEventListener("load", function onLoad(aEvent) {
if (content.location.href != testLocation) {
return;
}
browser.removeEventListener(aEvent.type, onLoad, true);
if (test.expectError) {
expectUncaughtException();
}
pageLoaded = true;
test.onload && test.onload(aEvent);
if (test.expectError) {
content.addEventListener("error", function _onError() {
content.removeEventListener("error", _onError);
pageError = true;
});
expectUncaughtException();
}
else {
pageError = true;
}
}, true);
content.location = testLocation;
}
@ -187,10 +208,6 @@ function onDOMNodeInserted(aEvent) {
if (foundText) {
ok(foundText, "test #" + pos + ": message found '" + TESTS[pos].matchString + "'");
}
if (foundCategory) {
executeSoon(testNext);
}
}
function test() {

View File

@ -29,26 +29,29 @@ function tabReloaded(aEvent) {
let HUD = HUDService.hudReferences[hudId];
ok(HUD, "Web Console is open");
isnot(HUD.outputNode.textContent.indexOf("fooBug597756_error"), -1,
"error message must be in console output");
waitForSuccess({
name: "error message displayed",
validatorFn: function() {
return HUD.outputNode.textContent.indexOf("fooBug597756_error") > -1;
},
successFn: function() {
if (newTabIsOpen) {
finishTest();
return;
}
closeConsole(gBrowser.selectedTab, function() {
gBrowser.removeCurrentTab();
executeSoon(function() {
if (newTabIsOpen) {
executeSoon(finishTest);
return;
}
let newTab = gBrowser.addTab();
gBrowser.selectedTab = newTab;
closeConsole(gBrowser.selectedTab, function() {
gBrowser.removeCurrentTab();
let newTab = gBrowser.addTab();
gBrowser.selectedTab = newTab;
newTabIsOpen = true;
gBrowser.selectedBrowser.addEventListener("load", tabLoaded, true);
expectUncaughtException();
content.location = TEST_URI;
});
newTabIsOpen = true;
gBrowser.selectedBrowser.addEventListener("load", tabLoaded, true);
expectUncaughtException();
content.location = TEST_URI;
});
},
failureFn: finishTest,
});
}

View File

@ -10,13 +10,10 @@
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-bug-601177-log-levels.html";
let msgs;
function onContentLoaded()
function performTest()
{
let hudId = HUDService.getHudIdByWindow(content);
let HUD = HUDService.hudReferences[hudId];
msgs = HUD.outputNode.querySelectorAll(".hud-msg-node");
findEntry(HUD, "hud-networkinfo", "test-bug-601177-log-levels.html",
"found test-bug-601177-log-levels.html");
@ -38,8 +35,6 @@ function onContentLoaded()
findEntry(HUD, "hud-jswarn", "foobarBug601177strictError",
"found strict error");
msgs = null;
Services.prefs.setBoolPref("javascript.options.strict", false);
finishTest();
}
@ -51,21 +46,37 @@ function findEntry(aHUD, aClass, aString, aMessage)
function test()
{
addTab("data:text/html;charset=utf-8,Web Console test for bug 601177: log levels");
Services.prefs.setBoolPref("javascript.options.strict", true);
browser.addEventListener("load", function(aEvent) {
browser.removeEventListener(aEvent.type, arguments.callee, true);
registerCleanupFunction(function() {
Services.prefs.clearUserPref("javascript.options.strict");
});
openConsole();
addTab("data:text/html;charset=utf-8,Web Console test for bug 601177: log levels");
browser.addEventListener("load", function(aEvent) {
browser.removeEventListener(aEvent.type, arguments.callee, true);
executeSoon(onContentLoaded);
}, true);
expectUncaughtException();
content.location = TEST_URI;
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
openConsole(null, function(hud) {
browser.addEventListener("load", function onLoad2() {
browser.removeEventListener("load", onLoad2, true);
waitForSuccess({
name: "all messages displayed",
validatorFn: function()
{
return hud.outputNode.itemCount >= 7;
},
successFn: performTest,
failureFn: function() {
info("itemCount: " + hud.outputNode.itemCount);
finishTest();
},
});
}, true);
expectUncaughtException();
content.location = TEST_URI;
});
}, true);
}

View File

@ -55,10 +55,13 @@ function consoleOpened(HUD) {
name: "console output displayed",
validatorFn: function()
{
return HUD.outputNode.itemCount == 103;
return HUD.outputNode.itemCount >= 103;
},
successFn: performTest,
failureFn: finishTest,
failureFn: function() {
info("itemCount: " + HUD.outputNode.itemCount);
finishTest();
},
});
}

View File

@ -10,15 +10,24 @@ const TEST_URI = "data:text/html;charset=utf-8,Web Console test for bug 613280";
function test() {
addTab(TEST_URI);
browser.addEventListener("load", tabLoaded, true);
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
openConsole(null, function(HUD) {
content.console.log("foobarBazBug613280");
waitForSuccess({
name: "a message is displayed",
validatorFn: function()
{
return HUD.outputNode.itemCount > 0;
},
successFn: performTest.bind(null, HUD),
failureFn: finishTest,
});
});
}, true);
}
function tabLoaded() {
browser.removeEventListener("load", tabLoaded, true);
openConsole();
let hudId = HUDService.getHudIdByWindow(content);
let HUD = HUDService.hudReferences[hudId];
function performTest(HUD) {
let input = HUD.jsterm.inputNode;
let selection = getSelection();
let contentSelection = browser.contentWindow.wrappedJSObject.getSelection();
@ -64,6 +73,8 @@ function tabLoaded() {
getControllerForCommand("cmd_copy");
is(controller.isCommandEnabled("cmd_copy"), true, "cmd_copy is enabled");
ok(HUD.outputNode.selectedItem, "we have a selected message");
waitForClipboard(getExpectedClipboardText(HUD.outputNode.selectedItem),
clipboard_setup, clipboard_copy_done, clipboard_copy_done);
}

View File

@ -10,16 +10,23 @@ function test() {
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
openConsole(null, function() {
openConsole(null, function(hud) {
content.location.reload();
browser.addEventListener("load", tabLoaded, true);
waitForSuccess({
name: "network message displayed",
validatorFn: function()
{
return hud.outputNode.querySelector(".webconsole-msg-network");
},
successFn: performTest,
failureFn: finishTest,
});
});
}, true);
}
function tabLoaded() {
browser.removeEventListener("load", tabLoaded, true);
function performTest() {
let hudId = HUDService.getHudIdByWindow(content);
let HUD = HUDService.hudReferences[hudId];

View File

@ -24,17 +24,23 @@ function test() {
togglePBAndThen(function() {
ok(pb.privateBrowsingEnabled, "private browsing is enabled");
openConsole(gBrowser.selectedTab, function() {
openConsole(gBrowser.selectedTab, function(hud) {
content.location = TEST_URI;
gBrowser.selectedBrowser.addEventListener("load", tabLoaded, true);
waitForSuccess({
name: "network message displayed",
validatorFn: function()
{
return hud.outputNode.querySelector(".webconsole-msg-network");
},
successFn: performTest,
failureFn: finishTest,
});
});
});
}, true);
}
function tabLoaded() {
gBrowser.selectedBrowser.removeEventListener("load", tabLoaded, true);
function performTest() {
let hudId = HUDService.getHudIdByWindow(content);
let HUD = HUDService.hudReferences[hudId];

View File

@ -54,14 +54,30 @@ function testPageLoad()
function testPageLoadBody()
{
let loaded = false;
let requestCallbackInvoked = false;
// Turn off logging of request bodies and check again.
requestCallback = function() {
ok(lastRequest, "Page load was logged again");
lastRequest = null;
requestCallback = null;
executeSoon(testXhrGet);
requestCallbackInvoked = true;
if (loaded) {
executeSoon(testXhrGet);
}
};
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
loaded = true;
if (requestCallbackInvoked) {
executeSoon(testXhrGet);
}
}, true);
content.location.reload();
}
@ -100,7 +116,19 @@ function testFormSubmission()
requestCallback = function() {
ok(lastRequest, "testFormSubmission() was logged");
is(lastRequest.request.method, "POST", "Method is correct");
executeSoon(testLiveFilteringOnSearchStrings);
waitForSuccess({
name: "all network request displayed",
validatorFn: function() {
return hud.outputNode.querySelectorAll(".webconsole-msg-network")
.length == 5;
},
successFn: testLiveFilteringOnSearchStrings,
failureFn: function() {
let nodes = hud.outputNode.querySelectorAll(".webconsole-msg-network");
info("nodes: " + nodes.length + "\n");
finishTest();
},
});
};
let form = content.document.querySelector("form");

View File

@ -15,7 +15,17 @@ const SEVERITY_WARNING = 1;
function test() {
addTab(TEST_URI);
browser.addEventListener("DOMContentLoaded", testCSSPruning, false);
browser.addEventListener("load", function onLoad(){
browser.removeEventListener("load", onLoad, false);
Services.prefs.setIntPref("devtools.hud.loglimit.cssparser", LOG_LIMIT);
registerCleanupFunction(function() {
Services.prefs.clearUserPref("devtools.hud.loglimit.cssparser");
});
openConsole(null, testCSSPruning);
}, true);
}
function populateConsoleRepeats(aHudRef) {
@ -27,7 +37,7 @@ function populateConsoleRepeats(aHudRef) {
SEVERITY_WARNING,
"css log x",
aHudRef.hudId);
ConsoleUtils.outputMessageNode(node, aHudRef.hudId);
aHudRef.outputMessage(CATEGORY_CSS, node);
}
}
@ -41,31 +51,40 @@ function populateConsole(aHudRef) {
SEVERITY_WARNING,
"css log " + i,
aHudRef.hudId);
ConsoleUtils.outputMessageNode(node, aHudRef.hudId);
aHudRef.outputMessage(CATEGORY_CSS, node);
}
}
function testCSSPruning() {
let prefBranch = Services.prefs.getBranch("devtools.hud.loglimit.");
prefBranch.setIntPref("cssparser", LOG_LIMIT);
browser.removeEventListener("DOMContentLoaded",testCSSPruning, false);
openConsole();
let hudRef = HUDService.getHudByWindow(content);
function testCSSPruning(hudRef) {
populateConsoleRepeats(hudRef);
ok(hudRef.cssNodes["css log x"], "repeated nodes in cssNodes");
populateConsole(hudRef);
let waitForNoRepeatedNodes = {
name: "number of nodes is LOG_LIMIT",
validatorFn: function()
{
return countMessageNodes() == LOG_LIMIT;
},
successFn: function()
{
ok(!hudRef.cssNodes["css log x"], "repeated nodes pruned from cssNodes");
finishTest();
},
failureFn: finishTest,
};
is(countMessageNodes(), LOG_LIMIT, "number of nodes is LOG_LIMIT");
ok(!hudRef.cssNodes["css log x"], "repeated nodes pruned from cssNodes");
prefBranch.clearUserPref("loglimit");
prefBranch = null;
finishTest();
waitForSuccess({
name: "repeated nodes in cssNodes",
validatorFn: function()
{
return hudRef.cssNodes["css log x"];
},
successFn: function()
{
populateConsole(hudRef);
waitForSuccess(waitForNoRepeatedNodes);
},
failureFn: finishTest,
});
}
function countMessageNodes() {

View File

@ -22,12 +22,6 @@ function testJSInputAndOutputStyling(hud) {
jsterm.clearOutput();
jsterm.execute("2 + 2");
let jsInputNode = jsterm.outputNode.querySelector(".hud-msg-node");
isnot(jsInputNode.textContent.indexOf("2 + 2"), -1,
"JS input node contains '2 + 2'");
ok(jsInputNode.classList.contains("webconsole-msg-input"),
"JS input node is of the CSS class 'webconsole-msg-input'");
waitForSuccess({
name: "jsterm output is displayed",
validatorFn: function()
@ -36,9 +30,16 @@ function testJSInputAndOutputStyling(hud) {
},
successFn: function()
{
let node = jsterm.outputNode.querySelector(".webconsole-msg-output");
isnot(node.textContent.indexOf("4"), -1,
let jsInputNode = jsterm.outputNode.querySelector(".hud-msg-node");
isnot(jsInputNode.textContent.indexOf("2 + 2"), -1,
"JS input node contains '2 + 2'");
ok(jsInputNode.classList.contains("webconsole-msg-input"),
"JS input node is of the CSS class 'webconsole-msg-input'");
let output = jsterm.outputNode.querySelector(".webconsole-msg-output");
isnot(output.textContent.indexOf("4"), -1,
"JS output node contains '4'");
finishTest();
},
failureFn: finishTest,

View File

@ -68,6 +68,9 @@ function testPageLoad()
function testPageLoadBody()
{
let loaded = false;
let requestCallbackInvoked = false;
// Turn on logging of request bodies and check again.
hud.saveRequestAndResponseBodies = true;
requestCallback = function() {
@ -77,9 +80,22 @@ function testPageLoadBody()
lastRequest = null;
requestCallback = null;
executeSoon(testXhrGet);
requestCallbackInvoked = true;
if (loaded) {
executeSoon(testXhrGet);
}
};
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
loaded = true;
if (requestCallbackInvoked) {
executeSoon(testXhrGet);
}
}, true);
content.location.reload();
}

View File

@ -156,3 +156,7 @@ installer:: removed-files
ifdef INSTALLER_DIR
$(MAKE) -C $(INSTALLER_DIR)
endif
ifdef ENABLE_MARIONETTE
DEFINES += -DENABLE_MARIONETTE=1
endif

View File

@ -469,6 +469,12 @@
@BINPATH@/components/ContactManager.js
@BINPATH@/components/ContactManager.manifest
#ifdef ENABLE_MARIONETTE
@BINPATH@/chrome/marionette@JAREXT@
@BINPATH@/chrome/marionette.manifest
@BINPATH@/components/MarionetteComponents.manifest
@BINPATH@/components/marionettecomponent.js
#endif
; Modules
@BINPATH@/modules/*

View File

@ -208,7 +208,8 @@ let AllPages = {
*/
unregister: function AllPages_unregister(aPage) {
let index = this._pages.indexOf(aPage);
this._pages.splice(index, 1);
if (index > -1)
this._pages.splice(index, 1);
},
/**

View File

@ -145,7 +145,7 @@ class B2GRemoteAutomation(Automation):
def restartB2G(self):
self._devicemanager.checkCmd(['shell', 'stop', 'b2g'])
# Wait for a bit to make sure B2G has completely shut down.
time.sleep(5)
time.sleep(10)
self._devicemanager.checkCmd(['shell', 'start', 'b2g'])
if self._is_emulator:
self.marionette.emulator.wait_for_port()
@ -192,7 +192,7 @@ class B2GRemoteAutomation(Automation):
# Infrequently, gecko comes up before networking does, so wait a little
# bit to give the network time to become available.
# XXX: need a more robust mechanism for this
time.sleep(20)
time.sleep(40)
# Set up port forwarding again for Marionette, since any that
# existed previously got wiped out by the reboot.

View File

@ -17,6 +17,7 @@ public class FindProcThread extends Thread {
boolean bStillRunning = true;
public FindProcThread(ContextWrapper ctx, String sProcessName) {
super("FindProcThread");
this.contextWrapper = ctx;
this.sProcNameToFind = sProcessName;
this.bFoundIt = false;

View File

@ -20,6 +20,7 @@ public class RedirOutputThread extends Thread
public RedirOutputThread(Process pProc, OutputStream out)
{
super("RedirOutputThread");
if (pProc != null)
{
this.pProc = pProc;
@ -50,6 +51,13 @@ public class RedirOutputThread extends Thread
{
try
{
// If there's no output to collect, sleep for a while
// rather than checking again immediately, to avoid
// using up cpu capacity in a tight loop.
if (sutOut.available() == 0 && sutErr.available() == 0)
{
Thread.sleep(50);
}
if ((nBytesOut = sutOut.available()) > 0)
{
if (nBytesOut > buffer.length)
@ -109,6 +117,10 @@ public class RedirOutputThread extends Thread
// Bug 743766: InputStream.available() unexpectedly throws this sometimes
e.printStackTrace();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
pProc.destroy();

View File

@ -7850,7 +7850,7 @@ dnl ========================================================
dnl Graphics checks.
dnl ========================================================
if test "${OS_ARCH}" = "Darwin" -o "${MOZ_WIDGET_TOOLKIT}" = "android" -o "${MOZ_WIDGET_TOOLKIT}" = "gtk2"; then
if test "${OS_TARGET}" = "WINNT" -o "${OS_ARCH}" = "Darwin" -o "${MOZ_WIDGET_TOOLKIT}" = "android" -o "${MOZ_WIDGET_TOOLKIT}" = "gtk2"; then
MOZ_ENABLE_SKIA=1
else
MOZ_ENABLE_SKIA=

View File

@ -0,0 +1,14 @@
<!doctype html>
<body> <span></span> <script>
function boom() {
var range = document.createRange();
range.setEnd(document.body.childNodes[2], 0);
window.addEventListener("DOMNodeInserted", f, true);
function f() {
window.removeEventListener("DOMNodeInserted", f, true);
range.deleteContents();
}
range.deleteContents();
}
window.addEventListener("load", boom, false);
</script>

View File

@ -66,6 +66,7 @@ load 509536-1.html
load 522516-1.html
load 529670.html
load 535926-1.html
load 543645.html
load 551631-1.html
load 554230-1.xhtml
load 552651.html

View File

@ -177,6 +177,11 @@ class NS_STACK_CLASS nsTreeSanitizer {
nsIDocument* aDocument,
nsIURI* aBaseURI);
/**
* Removes all attributes from an element node.
*/
void RemoveAllAttributes(nsIContent* aElement);
/**
* The whitelist of HTML elements.
*/

File diff suppressed because it is too large Load Diff

View File

@ -2179,6 +2179,12 @@ nsDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup,
}
}
}
// Refresh the principal on the compartment.
nsPIDOMWindow* win = GetInnerWindow();
if (win) {
win->RefreshCompartmentPrincipal();
}
}
nsresult
@ -3345,18 +3351,6 @@ nsDocument::IsNodeOfType(PRUint32 aFlags) const
return !(aFlags & ~eDOCUMENT);
}
PRUint16
nsDocument::NodeType()
{
return (PRUint16)nsIDOMNode::DOCUMENT_NODE;
}
void
nsDocument::NodeName(nsAString& aNodeName)
{
aNodeName.AssignLiteral("#document");
}
Element*
nsIDocument::GetRootElement() const
{
@ -4413,12 +4407,6 @@ nsDocument::CreateComment(const nsAString& aData, nsIDOMComment** aReturn)
{
*aReturn = nsnull;
// Make sure the substring "--" is not present in aData. Otherwise
// we'll create a document that can't be serialized.
if (FindInReadable(NS_LITERAL_STRING("--"), aData)) {
return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
}
nsCOMPtr<nsIContent> comment;
nsresult rv = NS_NewCommentNode(getter_AddRefs(comment), mNodeInfoManager);
@ -8416,7 +8404,8 @@ NS_IMETHODIMP
nsDocument::CreateTouchList(nsIVariant* aPoints,
nsIDOMTouchList** aRetVal)
{
nsRefPtr<nsDOMTouchList> retval = new nsDOMTouchList();
nsRefPtr<nsDOMTouchList> retval =
new nsDOMTouchList(static_cast<nsIDocument*>(this));
if (aPoints) {
PRUint16 type;
aPoints->GetDataType(&type);
@ -9607,6 +9596,14 @@ nsIDocument::DocSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const
&aWindowSizes->mLayoutPresContext);
}
aWindowSizes->mPropertyTables +=
mPropertyTable.SizeOfExcludingThis(aWindowSizes->mMallocSizeOf);
for (PRUint32 i = 0, count = mExtraPropertyTables.Length();
i < count; ++i) {
aWindowSizes->mPropertyTables +=
mExtraPropertyTables[i]->SizeOfExcludingThis(aWindowSizes->mMallocSizeOf);
}
// Measurement of the following members may be added later if DMD finds it
// is worthwhile:
// - many!

View File

@ -682,8 +682,6 @@ public:
// nsINode
virtual bool IsNodeOfType(PRUint32 aFlags) const;
virtual PRUint16 NodeType();
virtual void NodeName(nsAString& aNodeName);
virtual nsIContent *GetChildAt(PRUint32 aIndex) const;
virtual nsIContent * const * GetChildArray(PRUint32* aChildCount) const;
virtual PRInt32 IndexOf(nsINode* aPossibleChild) const;

View File

@ -4098,7 +4098,9 @@ bool IsAllowedAsChild(nsIContent* aNewChild, nsINode* aParent,
{
// Note that for now we only allow nodes inside document fragments if
// they're allowed inside elements. If we ever change this to allow
// doctype nodes in document fragments, we'll need to update this code
// doctype nodes in document fragments, we'll need to update this code.
// Also, there's a version of this code in ReplaceOrInsertBefore. If you
// change this code, change that too.
if (!aParent->IsNodeOfType(nsINode::eDOCUMENT)) {
// All good here
return true;
@ -4159,6 +4161,11 @@ nsresult
nsINode::ReplaceOrInsertBefore(bool aReplace, nsINode* aNewChild,
nsINode* aRefChild)
{
// XXXbz I wish I could assert that nsContentUtils::IsSafeToRunScript() so we
// could rely on scriptblockers going out of scope to actually run XBL
// teardown, but various crud adds nodes under scriptblockers (e.g. native
// anonymous content). The only good news is those insertions can't trigger
// the bad XBL cases.
if (!aNewChild || (aReplace && !aRefChild)) {
return NS_ERROR_NULL_POINTER;
}
@ -4235,6 +4242,8 @@ nsINode::ReplaceOrInsertBefore(bool aReplace, nsINode* aNewChild,
nodeToInsertBefore = nodeToInsertBefore->GetNextSibling();
}
Maybe<nsAutoTArray<nsCOMPtr<nsIContent>, 50> > fragChildren;
// Remove the new child from the old parent if one exists
nsCOMPtr<nsINode> oldParent = newContent->GetNodeParent();
if (oldParent) {
@ -4254,7 +4263,8 @@ nsINode::ReplaceOrInsertBefore(bool aReplace, nsINode* aNewChild,
// Scope for the mutation batch and scriptblocker, so they go away
// while kungFuDeathGrip is still alive.
{
mozAutoDocUpdate batch(GetCurrentDoc(), UPDATE_CONTENT_MODEL, true);
mozAutoDocUpdate batch(newContent->GetCurrentDoc(),
UPDATE_CONTENT_MODEL, true);
nsAutoMutationBatch mb(oldParent, true, true);
oldParent->RemoveChildAt(removeIndex, true);
if (nsAutoMutationBatch::GetCurrentBatch() == &mb) {
@ -4299,6 +4309,98 @@ nsINode::ReplaceOrInsertBefore(bool aReplace, nsINode* aNewChild,
}
}
}
} else if (nodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
// Make sure to remove all the fragment's kids. We need to do this before
// we start inserting anything, so we will run out XBL destructors and
// binding teardown (GOD, I HATE THESE THINGS) before we insert anything
// into the DOM.
PRUint32 count = newContent->GetChildCount();
fragChildren.construct();
// Copy the children into a separate array to avoid having to deal with
// mutations to the fragment later on here.
fragChildren.ref().SetCapacity(count);
for (nsIContent* child = newContent->GetFirstChild();
child;
child = child->GetNextSibling()) {
NS_ASSERTION(child->GetCurrentDoc() == nsnull,
"How did we get a child with a current doc?");
fragChildren.ref().AppendElement(child);
}
// Hold a strong ref to nodeToInsertBefore across the removals
nsCOMPtr<nsINode> kungFuDeathGrip = nodeToInsertBefore;
nsMutationGuard guard;
// Scope for the mutation batch and scriptblocker, so they go away
// while kungFuDeathGrip is still alive.
{
mozAutoDocUpdate batch(newContent->GetCurrentDoc(),
UPDATE_CONTENT_MODEL, true);
nsAutoMutationBatch mb(newContent, false, true);
for (PRUint32 i = count; i > 0;) {
newContent->RemoveChildAt(--i, true);
}
}
// We expect |count| removals
if (guard.Mutated(count)) {
// XBL destructors, yuck.
// Verify that nodeToInsertBefore, if non-null, is still our child. If
// it's not, there's no way we can do this insert sanely; just bail out.
if (nodeToInsertBefore && nodeToInsertBefore->GetParent() != this) {
return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
}
// Verify that all the things in fragChildren have no parent.
for (PRUint32 i = 0; i < count; ++i) {
if (fragChildren.ref().ElementAt(i)->GetParent()) {
return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
}
}
// Note that unlike the single-element case above, none of our kids can
// be aRefChild, so we can always pass through aReplace in the
// IsAllowedAsChild checks below and don't have to worry about whether
// recomputing nodeToInsertBefore is OK.
// Verify that our aRefChild is still sensible
if (aRefChild && aRefChild->GetParent() != this) {
return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
}
// Recompute nodeToInsertBefore, just in case.
if (aReplace) {
nodeToInsertBefore = aRefChild->GetNextSibling();
} else {
nodeToInsertBefore = aRefChild;
}
// And verify that newContent is still allowed as our child. Sadly, we
// need to reimplement the relevant part of IsAllowedAsChild() because
// now our nodes are in an array and all. If you change this code,
// change the code there.
if (IsNodeOfType(nsINode::eDOCUMENT)) {
bool sawElement = false;
for (PRUint32 i = 0; i < count; ++i) {
nsIContent* child = fragChildren.ref().ElementAt(i);
if (child->IsElement()) {
if (sawElement) {
// No good
return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
}
sawElement = true;
}
if (!IsAllowedAsChild(child, this, aReplace, aRefChild)) {
return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
}
}
}
}
}
mozAutoDocUpdate batch(GetCurrentDoc(), UPDATE_CONTENT_MODEL, true);
@ -4349,36 +4451,15 @@ nsINode::ReplaceOrInsertBefore(bool aReplace, nsINode* aNewChild,
/*
* Check if we're inserting a document fragment. If we are, we need
* to remove the children of the document fragment and add them
* individually (i.e. we don't add the actual document fragment).
* to actually add its children individually (i.e. we don't add the
* actual document fragment).
*/
if (nodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
PRUint32 count = newContent->GetChildCount();
PRUint32 count = fragChildren.ref().Length();
if (!count) {
return NS_OK;
}
// Copy the children into a separate array to avoid having to deal with
// mutations to the fragment while we're inserting.
nsAutoTArray<nsCOMPtr<nsIContent>, 50> fragChildren;
fragChildren.SetCapacity(count);
for (nsIContent* child = newContent->GetFirstChild();
child;
child = child->GetNextSibling()) {
NS_ASSERTION(child->GetCurrentDoc() == nsnull,
"How did we get a child with a current doc?");
fragChildren.AppendElement(child);
}
// Remove the children from the fragment.
{
nsAutoMutationBatch mb(newContent, false, true);
for (PRUint32 i = count; i > 0;) {
newContent->RemoveChildAt(--i, true);
}
}
if (!aReplace) {
mb.Init(this, true, true);
}
@ -4392,14 +4473,14 @@ nsINode::ReplaceOrInsertBefore(bool aReplace, nsINode* aNewChild,
bool appending =
!IsNodeOfType(eDOCUMENT) && PRUint32(insPos) == GetChildCount();
PRInt32 firstInsPos = insPos;
nsIContent* firstInsertedContent = fragChildren[0];
nsIContent* firstInsertedContent = fragChildren.ref().ElementAt(0);
// Iterate through the fragment's children, and insert them in the new
// parent
for (PRUint32 i = 0; i < count; ++i, ++insPos) {
// XXXbz how come no reparenting here? That seems odd...
// Insert the child.
res = InsertChildAt(fragChildren[i], insPos, !appending);
res = InsertChildAt(fragChildren.ref().ElementAt(i), insPos, !appending);
if (NS_FAILED(res)) {
// Make sure to notify on any children that we did succeed to insert
if (appending && i != 0) {
@ -4425,7 +4506,7 @@ nsINode::ReplaceOrInsertBefore(bool aReplace, nsINode* aNewChild,
// Optimize for the case when there are no listeners
if (nsContentUtils::
HasMutationListeners(doc, NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
nsGenericElement::FireNodeInserted(doc, this, fragChildren);
nsGenericElement::FireNodeInserted(doc, this, fragChildren.ref());
}
}
}

View File

@ -1643,6 +1643,7 @@ GK_ATOM(onMozRotateGestureUpdate, "onMozRotateGestureUpdate")
GK_ATOM(onMozRotateGesture, "onMozRotateGesture")
GK_ATOM(onMozTapGesture, "onMozTapGesture")
GK_ATOM(onMozPressTapGesture, "onMozPressTapGesture")
GK_ATOM(onMozEdgeUIGesture, "onMozEdgeUIGesture")
// Touch events
GK_ATOM(onMozTouchDown, "onMozTouchDown")

View File

@ -52,6 +52,8 @@ public:
return mName == aPropertyName;
}
size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf);
nsCOMPtr<nsIAtom> mName; // property name
PLDHashTable mObjectValueMap; // map of object/value pairs
NSPropertyDtorFunc mDtorFunc; // property specific value dtor function
@ -337,6 +339,26 @@ nsPropertyTable::PropertyList::DeletePropertyFor(nsPropertyOwner aObject)
return true;
}
size_t
nsPropertyTable::PropertyList::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf)
{
size_t n = aMallocSizeOf(this);
n += PL_DHashTableSizeOfExcludingThis(&mObjectValueMap, NULL, aMallocSizeOf);
return n;
}
size_t
nsPropertyTable::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
{
size_t n = 0;
for (PropertyList *prop = mPropertyList; prop; prop = prop->mNext) {
n += prop->SizeOfIncludingThis(aMallocSizeOf);
}
return n;
}
/* static */
void
nsPropertyTable::SupportsDtorFunc(void *aObject, nsIAtom *aPropertyName,

View File

@ -177,6 +177,8 @@ class nsPropertyTable
class PropertyList;
size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
private:
NS_HIDDEN_(void) DestroyPropertyList();
NS_HIDDEN_(PropertyList*) GetPropertyListFor(nsIAtom *aPropertyName) const;

View File

@ -1409,6 +1409,11 @@ nsTreeSanitizer::SanitizeChildren(nsINode* aRoot)
PRInt32 ns = nodeInfo->NamespaceID();
if (MustPrune(ns, localName, elt)) {
RemoveAllAttributes(node);
nsIContent* descendant = node;
while ((descendant = descendant->GetNextNode(node))) {
RemoveAllAttributes(descendant);
}
nsIContent* next = node->GetNextNonChildNode(aRoot);
node->GetParent()->RemoveChild(node);
node = next;
@ -1452,6 +1457,7 @@ nsTreeSanitizer::SanitizeChildren(nsINode* aRoot)
continue;
}
if (MustFlatten(ns, localName)) {
RemoveAllAttributes(node);
nsIContent* next = node->GetNextNode(aRoot);
nsIContent* parent = node->GetParent();
nsCOMPtr<nsIContent> child; // Must keep the child alive during move
@ -1504,6 +1510,17 @@ nsTreeSanitizer::SanitizeChildren(nsINode* aRoot)
}
}
void
nsTreeSanitizer::RemoveAllAttributes(nsIContent* aElement)
{
const nsAttrName* attrName;
while ((attrName = aElement->GetAttrNameAt(0))) {
PRInt32 attrNs = attrName->NamespaceID();
nsCOMPtr<nsIAtom> attrLocal = attrName->LocalName();
aElement->UnsetAttr(attrNs, attrLocal, false);
}
}
void
nsTreeSanitizer::InitializeStatics()
{

View File

@ -1076,14 +1076,14 @@ nsXMLHttpRequest::StaticAssertions()
#_uc " should match")
ASSERT_ENUM_EQUAL(_empty, DEFAULT);
ASSERT_ENUM_EQUAL(arraybuffer, ARRAYBUFFER);
ASSERT_ENUM_EQUAL(blob, BLOB);
ASSERT_ENUM_EQUAL(document, DOCUMENT);
ASSERT_ENUM_EQUAL(json, JSON);
ASSERT_ENUM_EQUAL(text, TEXT);
ASSERT_ENUM_EQUAL(moz_chunked_text, CHUNKED_TEXT);
ASSERT_ENUM_EQUAL(moz_chunked_arraybuffer, CHUNKED_ARRAYBUFFER);
ASSERT_ENUM_EQUAL(moz_blob, MOZ_BLOB);
ASSERT_ENUM_EQUAL(Arraybuffer, ARRAYBUFFER);
ASSERT_ENUM_EQUAL(Blob, BLOB);
ASSERT_ENUM_EQUAL(Document, DOCUMENT);
ASSERT_ENUM_EQUAL(Json, JSON);
ASSERT_ENUM_EQUAL(Text, TEXT);
ASSERT_ENUM_EQUAL(Moz_chunked_text, CHUNKED_TEXT);
ASSERT_ENUM_EQUAL(Moz_chunked_arraybuffer, CHUNKED_ARRAYBUFFER);
ASSERT_ENUM_EQUAL(Moz_blob, MOZ_BLOB);
#undef ASSERT_ENUM_EQUAL
}
#endif

View File

@ -44,7 +44,7 @@ function testCharacterData(aNode, aText)
is(aNode.namespaceURI, null, "Check namespaceURI");
}
function testComment(aText, aShouldSucceed)
function testComment(aText)
{
try {
var comment = document.createComment(aText);
@ -58,18 +58,8 @@ function testComment(aText, aShouldSucceed)
testCharacterData(comment, aText);
is(comment.nodeName, "#comment", "Check nodeName");
is(comment.nodeType, Node.COMMENT_NODE, "Check nodeType");
if (!aShouldSucceed) {
ok(0, "Invalid comment creation",
"Shouldn't create comment with embedded \"--\"");
}
} catch (e) {
if (aShouldSucceed) {
ok(0, "Correct functioning of comment stuff", "something broke: " + e);
} else {
is(e.name, "InvalidCharacterError", "Check exception");
is(e.code, DOMException.INVALID_CHARACTER_ERR, "Check exception code");
}
ok(0, "Correct functioning of comment stuff", "something broke: " + e);
}
}
@ -119,11 +109,11 @@ function testPI(aTarget, aData, aShouldSucceed, aReason)
}
}
testComment("Some text", true);
testComment("Some text with a '-' in it", true);
testComment("Some text with a '-' and a '-' and another '-'", true);
testComment("Some text -- this shouldn't create a node!", false);
testComment("<!-- This is an HTML comment -->", false);
testComment("Some text");
testComment("Some text with a '-' in it");
testComment("Some text with a '-' and a '-' and another '-'");
testComment("Some text -- this should create a node!");
testComment("<!-- This is an HTML comment -->");
testCDATASection("Some text", true);
testCDATASection("Some text with a '?' in it", true);

View File

@ -68,7 +68,7 @@ function testCharacterData(aNode, aText)
is(aNode.namespaceURI, null, "Check namespaceURI");
}
function testComment(aText, aShouldSucceed)
function testComment(aText)
{
try {
var comment = document.createComment(aText);
@ -82,18 +82,8 @@ function testComment(aText, aShouldSucceed)
testCharacterData(comment, aText);
is(comment.nodeName, "#comment", "Check nodeName");
is(comment.nodeType, Node.COMMENT_NODE, "Check nodeType");
if (!aShouldSucceed) {
ok(0, "Invalid comment creation",
"Shouldn't create comment with embedded \"--\"");
}
} catch (e) {
if (aShouldSucceed) {
ok(0, "Correct functioning of comment stuff", "something broke: " + e);
} else {
is(e.name, "InvalidCharacterError", "Check exception");
is(e.code, DOMException.INVALID_CHARACTER_ERR, "Check exception code");
}
ok(0, "Correct functioning of comment stuff", "something broke: " + e);
}
}
@ -163,11 +153,11 @@ function testPI(aTarget, aData, aShouldSucceed, aReason)
}
}
testComment("Some text", true);
testComment("Some text with a '-' in it", true);
testComment("Some text with a '-' and a '-' and another '-'", true);
testComment("Some text -- this shouldn't create a node!", false);
testComment("<!-- This is an HTML comment -->", false);
testComment("Some text");
testComment("Some text with a '-' in it");
testComment("Some text with a '-' and a '-' and another '-'");
testComment("Some text -- this should create a node!");
testComment("<!-- This is an HTML comment -->");
testCDATASection("Some text", true);
testCDATASection("Some text with a '?' in it", true);

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