mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge mozilla-central into services-central
This commit is contained in:
commit
9c12eea8ed
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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!");
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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) {
|
||||
|
@ -15,7 +15,7 @@ NS_IMPL_ISUPPORTS_INHERITED0(HyperTextAccessibleWrap,
|
||||
IMPL_IUNKNOWN_INHERITED2(HyperTextAccessibleWrap,
|
||||
AccessibleWrap,
|
||||
ia2AccessibleHypertext,
|
||||
CAccessibleEditableText);
|
||||
ia2AccessibleEditableText);
|
||||
|
||||
nsresult
|
||||
HyperTextAccessibleWrap::HandleAccEvent(AccEvent* aEvent)
|
||||
|
@ -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) :
|
||||
|
@ -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)
|
||||
|
@ -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 {
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
#include "AccessibleEditableText.h"
|
||||
|
||||
class CAccessibleEditableText: public IAccessibleEditableText
|
||||
class ia2AccessibleEditableText: public IAccessibleEditableText
|
||||
{
|
||||
public:
|
||||
|
@ -27,7 +27,7 @@ ia2AccessibleHypertext::QueryInterface(REFIID iid, void** ppv)
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
return CAccessibleText::QueryInterface(iid, ppv);
|
||||
return ia2AccessibleText::QueryInterface(iid, ppv);
|
||||
}
|
||||
|
||||
// IAccessibleHypertext
|
||||
|
@ -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(
|
||||
|
@ -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:
|
@ -13,7 +13,7 @@
|
||||
|
||||
#include "AccessibleText.h"
|
||||
|
||||
class CAccessibleText: public IAccessibleText
|
||||
class ia2AccessibleText: public IAccessibleText
|
||||
{
|
||||
public:
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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); \
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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">
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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() {
|
||||
|
@ -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)
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -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
|
||||
|
@ -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
@ -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
|
||||
|
@ -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
|
||||
|
@ -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() {
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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(); };
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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();
|
||||
});
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -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)
|
||||
|
@ -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>
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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"];
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
},
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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();
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -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 },
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
});
|
||||
|
@ -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() {
|
||||
|
@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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];
|
||||
|
||||
|
@ -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];
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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() {
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -156,3 +156,7 @@ installer:: removed-files
|
||||
ifdef INSTALLER_DIR
|
||||
$(MAKE) -C $(INSTALLER_DIR)
|
||||
endif
|
||||
|
||||
ifdef ENABLE_MARIONETTE
|
||||
DEFINES += -DENABLE_MARIONETTE=1
|
||||
endif
|
||||
|
@ -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/*
|
||||
|
@ -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);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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=
|
||||
|
14
content/base/crashtests/543645.html
Normal file
14
content/base/crashtests/543645.html
Normal 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>
|
@ -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
|
||||
|
@ -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
@ -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!
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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")
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user