mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 15:52:07 +00:00
Merge the last good pgo-green cset on mozilla-inbound to mozilla-central.
This commit is contained in:
commit
34b94a5666
@ -99,7 +99,9 @@ endif
|
||||
LOCAL_INCLUDES += \
|
||||
-I$(srcdir) \
|
||||
-I$(srcdir)/../base \
|
||||
-I$(srcdir)/../generic \
|
||||
-I$(srcdir)/../html \
|
||||
-I$(srcdir)/../xpcom \
|
||||
-I$(srcdir)/../xul \
|
||||
-I$(topsrcdir)/other-licenses/atk-1.0 \
|
||||
$(NULL)
|
||||
|
@ -42,12 +42,14 @@
|
||||
#include "nsAccessibleWrap.h"
|
||||
#include "nsAccUtils.h"
|
||||
#include "nsIAccessibleTable.h"
|
||||
#include "TableAccessible.h"
|
||||
#include "nsMai.h"
|
||||
|
||||
#include "nsArrayUtils.h"
|
||||
|
||||
extern "C" {
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
extern "C" {
|
||||
static AtkObject*
|
||||
refAtCB(AtkTable *aTable, gint aRow, gint aColumn)
|
||||
{
|
||||
@ -208,23 +210,17 @@ getRowExtentAtCB(AtkTable *aTable,
|
||||
}
|
||||
|
||||
static AtkObject*
|
||||
getCaptionCB(AtkTable *aTable)
|
||||
getCaptionCB(AtkTable* aTable)
|
||||
{
|
||||
nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
|
||||
if (!accWrap)
|
||||
return nsnull;
|
||||
nsAccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
|
||||
if (!accWrap)
|
||||
return nsnull;
|
||||
|
||||
nsCOMPtr<nsIAccessibleTable> accTable;
|
||||
accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
|
||||
getter_AddRefs(accTable));
|
||||
NS_ENSURE_TRUE(accTable, nsnull);
|
||||
TableAccessible* table = accWrap->AsTable();
|
||||
NS_ENSURE_TRUE(table, nsnull);
|
||||
|
||||
nsCOMPtr<nsIAccessible> caption;
|
||||
nsresult rv = accTable->GetCaption(getter_AddRefs(caption));
|
||||
if (NS_FAILED(rv) || !caption)
|
||||
return nsnull;
|
||||
|
||||
return nsAccessibleWrap::GetAtkObject(caption);
|
||||
nsAccessible* caption = table->Caption();
|
||||
return caption ? nsAccessibleWrap::GetAtkObject(caption) : nsnull;
|
||||
}
|
||||
|
||||
static const gchar*
|
||||
|
@ -44,9 +44,6 @@
|
||||
#include "nsApplicationAccessibleWrap.h"
|
||||
#include "nsDocAccessible.h"
|
||||
#include "nsIAccessibleText.h"
|
||||
#ifdef MOZ_XUL
|
||||
#include "nsXULTreeAccessible.h"
|
||||
#endif
|
||||
#include "nsAccEvent.h"
|
||||
#include "States.h"
|
||||
|
||||
|
@ -104,8 +104,9 @@ include $(topsrcdir)/config/rules.mk
|
||||
|
||||
LOCAL_INCLUDES += \
|
||||
-I$(srcdir) \
|
||||
-I$(srcdir)/../xpcom \
|
||||
-I$(srcdir)/../generic \
|
||||
-I$(srcdir)/../html \
|
||||
-I$(srcdir)/../xpcom \
|
||||
-I$(srcdir)/../xul \
|
||||
-I$(srcdir)/../../../layout/generic \
|
||||
-I$(srcdir)/../../../layout/style \
|
||||
|
@ -58,7 +58,7 @@ using namespace mozilla::a11y;
|
||||
|
||||
nsARIAGridAccessible::
|
||||
nsARIAGridAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
|
||||
nsAccessibleWrap(aContent, aDoc)
|
||||
nsAccessibleWrap(aContent, aDoc), xpcAccessibleTable(this)
|
||||
{
|
||||
}
|
||||
|
||||
@ -70,21 +70,18 @@ NS_IMPL_ISUPPORTS_INHERITED1(nsARIAGridAccessible,
|
||||
nsIAccessibleTable)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsIAccessibleTable
|
||||
//nsAccessNode
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsARIAGridAccessible::GetCaption(nsIAccessible **aCaption)
|
||||
void
|
||||
nsARIAGridAccessible::Shutdown()
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCaption);
|
||||
*aCaption = nsnull;
|
||||
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// XXX: should be pointed by aria-labelledby on grid?
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
mTable = nsnull;
|
||||
nsAccessibleWrap::Shutdown();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsIAccessibleTable
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsARIAGridAccessible::GetSummary(nsAString &aSummary)
|
||||
{
|
||||
@ -710,15 +707,6 @@ nsARIAGridAccessible::UnselectColumn(PRInt32 aColumn)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsARIAGridAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aIsProbablyForLayout);
|
||||
*aIsProbablyForLayout = false;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Protected
|
||||
|
||||
|
@ -42,12 +42,16 @@
|
||||
#include "nsIAccessibleTable.h"
|
||||
|
||||
#include "nsHyperTextAccessibleWrap.h"
|
||||
#include "TableAccessible.h"
|
||||
#include "xpcAccessibleTable.h"
|
||||
|
||||
/**
|
||||
* Accessible for ARIA grid and treegrid.
|
||||
*/
|
||||
class nsARIAGridAccessible : public nsAccessibleWrap,
|
||||
public nsIAccessibleTable
|
||||
public xpcAccessibleTable,
|
||||
public nsIAccessibleTable,
|
||||
public mozilla::a11y::TableAccessible
|
||||
{
|
||||
public:
|
||||
nsARIAGridAccessible(nsIContent* aContent, nsDocAccessible* aDoc);
|
||||
@ -56,7 +60,13 @@ public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsIAccessibleTable
|
||||
NS_DECL_NSIACCESSIBLETABLE
|
||||
NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE
|
||||
|
||||
// nsAccessible
|
||||
virtual mozilla::a11y::TableAccessible* AsTable() { return this; }
|
||||
|
||||
// nsAccessNode
|
||||
virtual void Shutdown();
|
||||
|
||||
protected:
|
||||
/**
|
||||
|
@ -47,9 +47,7 @@
|
||||
#include "nsARIAMap.h"
|
||||
#include "nsDocAccessible.h"
|
||||
#include "nsHyperTextAccessible.h"
|
||||
#include "nsHTMLTableAccessible.h"
|
||||
#include "nsTextAccessible.h"
|
||||
#include "nsXULTreeGridAccessible.h"
|
||||
|
||||
#include "nsIDOMXULContainerElement.h"
|
||||
#include "nsIDOMXULSelectCntrlEl.h"
|
||||
|
@ -66,6 +66,11 @@ class nsHTMLImageMapAccessible;
|
||||
class nsHTMLLIAccessible;
|
||||
struct nsRoleMapEntry;
|
||||
class Relation;
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
class TableAccessible;
|
||||
}
|
||||
}
|
||||
class nsTextAccessible;
|
||||
|
||||
struct nsRect;
|
||||
@ -471,6 +476,8 @@ public:
|
||||
inline bool IsRoot() const { return mFlags & eRootAccessible; }
|
||||
nsRootAccessible* AsRoot();
|
||||
|
||||
virtual mozilla::a11y::TableAccessible* AsTable() { return nsnull; }
|
||||
|
||||
inline bool IsTextLeaf() const { return mFlags & eTextLeafAccessible; }
|
||||
nsTextAccessible* AsTextLeaf();
|
||||
|
||||
|
@ -41,15 +41,13 @@
|
||||
#include "nsCaretAccessible.h"
|
||||
#include "nsDocAccessibleWrap.h"
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
#include "nsXULTreeAccessible.h"
|
||||
#endif
|
||||
|
||||
#include "nsHashtable.h"
|
||||
#include "nsCaretAccessible.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
|
||||
class nsXULTreeAccessible;
|
||||
class Relation;
|
||||
|
||||
#define NS_ROOTACCESSIBLE_IMPL_CID \
|
||||
|
170
accessible/src/generic/TableAccessible.h
Normal file
170
accessible/src/generic/TableAccessible.h
Normal file
@ -0,0 +1,170 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef TABLE_ACCESSIBLE_H
|
||||
#define TABLE_ACCESSIBLE_H
|
||||
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
#include "prtypes.h"
|
||||
|
||||
class nsAccessible;
|
||||
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
|
||||
/**
|
||||
* Accessible table interface.
|
||||
*/
|
||||
class TableAccessible
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Return the caption accessible if any for this table.
|
||||
*/
|
||||
virtual nsAccessible* Caption() { return nsnull; }
|
||||
|
||||
/**
|
||||
* Get the summary for this table.
|
||||
*/
|
||||
virtual void Summary(nsString& aSummary) { aSummary.Truncate(); }
|
||||
|
||||
/**
|
||||
* Return the number of columns in the table.
|
||||
*/
|
||||
virtual PRUint32 ColCount() { return 0; }
|
||||
|
||||
/**
|
||||
* Return the number of rows in the table.
|
||||
*/
|
||||
virtual PRUint32 RowCount() { return 0; }
|
||||
|
||||
/**
|
||||
* Return the accessible for the cell at the given row and column indices.
|
||||
*/
|
||||
virtual nsAccessible* CellAt(PRUint32 aRowIdx, PRUint32 aColIdx) { return nsnull; }
|
||||
|
||||
/**
|
||||
* Return the index of the cell at the given row and column.
|
||||
*/
|
||||
virtual PRInt32 CellIndexAt(PRUint32 aRowIdx, PRUint32 aColIdx) { return -1; }
|
||||
|
||||
/**
|
||||
* Return the column index of the cell with the given index.
|
||||
*/
|
||||
virtual PRInt32 ColIndexAt(PRUint32 aCellIdx) { return -1; }
|
||||
|
||||
/**
|
||||
* Return the row index of the cell with the given index.
|
||||
*/
|
||||
virtual PRInt32 RowIndexAt(PRUint32 aCellIdx) { return -1; }
|
||||
|
||||
/**
|
||||
* Get the row and column indices for the cell at the given index.
|
||||
*/
|
||||
virtual void RowAndColIndicesAt(PRUint32 aCellIdx, PRInt32* aRowIdx,
|
||||
PRInt32* aColIdx) {}
|
||||
|
||||
/**
|
||||
* Return the number of columns occupied by the cell at the given row and
|
||||
* column indices.
|
||||
*/
|
||||
virtual PRUint32 ColExtentAt(PRUint32 aRowIdx, PRUint32 aColIdx) { return 1; }
|
||||
|
||||
/**
|
||||
* Return the number of rows occupied by the cell at the given row and column
|
||||
* indices.
|
||||
*/
|
||||
virtual PRUint32 RowExtentAt(PRUint32 aRowIdx, PRUint32 aColIdx) { return 1; }
|
||||
|
||||
/**
|
||||
* Get the description of the given column.
|
||||
*/
|
||||
virtual void ColDescription(PRUint32 aColIdx, nsString& aDescription)
|
||||
{ aDescription.Truncate(); }
|
||||
|
||||
/**
|
||||
* Get the description for the given row.
|
||||
*/
|
||||
virtual void RowDescription(PRUint32 aRowIdx, nsString& aDescription)
|
||||
{ aDescription.Truncate(); }
|
||||
|
||||
/**
|
||||
* Return true if the given column is selected.
|
||||
*/
|
||||
virtual bool IsColSelected(PRUint32 aColIdx) { return false; }
|
||||
|
||||
/**
|
||||
* Return true if the given row is selected.
|
||||
*/
|
||||
virtual bool IsRowSelected(PRUint32 aRowIdx) { return false; }
|
||||
|
||||
/**
|
||||
* Return true if the given cell is selected.
|
||||
*/
|
||||
virtual bool IsCellSelected(PRUint32 aRowIdx, PRUint32 aColIdx) { return false; }
|
||||
|
||||
/**
|
||||
* Return the number of selected cells.
|
||||
*/
|
||||
virtual PRUint32 SelectedCellCount() { return 0; }
|
||||
|
||||
/**
|
||||
* Return the number of selected columns.
|
||||
*/
|
||||
virtual PRUint32 SelectedColCount() { return 0; }
|
||||
|
||||
/**
|
||||
* Return the number of selected rows.
|
||||
*/
|
||||
virtual PRUint32 SelectedRowCount() { return 0; }
|
||||
|
||||
/**
|
||||
* Get the set of selected cells.
|
||||
*/
|
||||
virtual void SelectedCells(nsTArray<nsAccessible*>* aCells) {}
|
||||
|
||||
/**
|
||||
* Get the set of selected column indices.
|
||||
*/
|
||||
virtual void SelectedColIndices(nsTArray<PRUint32>* aCols) {}
|
||||
|
||||
/**
|
||||
* Get the set of selected row indices.
|
||||
*/
|
||||
virtual void SelectedRowIndices(nsTArray<PRUint32>* aRows) {}
|
||||
|
||||
/**
|
||||
* Select the given column unselecting any other selected columns.
|
||||
*/
|
||||
virtual void SelectCol(PRUint32 aColIdx) {}
|
||||
|
||||
/**
|
||||
* Select the given row unselecting all other previously selected rows.
|
||||
*/
|
||||
virtual void SelectRow(PRUint32 aRowIdx) {}
|
||||
|
||||
/**
|
||||
* Unselect the given column leaving other selected columns selected.
|
||||
*/
|
||||
virtual void UnselectCol(PRUint32 aColIdx) {}
|
||||
|
||||
/**
|
||||
* Unselect the given row leaving other selected rows selected.
|
||||
*/
|
||||
virtual void UnselectRow(PRUint32 aRowIdx) {}
|
||||
|
||||
/**
|
||||
* Return true if the table is probably for layout.
|
||||
*/
|
||||
virtual bool IsProbablyLayoutTable() { return false; }
|
||||
};
|
||||
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
@ -73,6 +73,8 @@ include $(topsrcdir)/config/rules.mk
|
||||
|
||||
LOCAL_INCLUDES = \
|
||||
-I$(srcdir)/../base \
|
||||
-I$(srcdir)/../generic \
|
||||
-I$(srcdir)/../xpcom \
|
||||
-I$(srcdir)/../../../layout/generic \
|
||||
-I$(srcdir)/../../../layout/xul/base/src \
|
||||
$(NULL)
|
||||
|
@ -436,7 +436,7 @@ nsHTMLTableHeaderCellAccessible::NativeRole()
|
||||
|
||||
nsHTMLTableAccessible::
|
||||
nsHTMLTableAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
|
||||
nsAccessibleWrap(aContent, aDoc)
|
||||
nsAccessibleWrap(aContent, aDoc), xpcAccessibleTable(this)
|
||||
{
|
||||
}
|
||||
|
||||
@ -446,6 +446,16 @@ nsHTMLTableAccessible::
|
||||
NS_IMPL_ISUPPORTS_INHERITED2(nsHTMLTableAccessible, nsAccessible,
|
||||
nsHTMLTableAccessible, nsIAccessibleTable)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//nsAccessNode
|
||||
|
||||
void
|
||||
nsHTMLTableAccessible::Shutdown()
|
||||
{
|
||||
mTable = nsnull;
|
||||
nsAccessibleWrap::Shutdown();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLTableAccessible: nsAccessible implementation
|
||||
@ -511,9 +521,7 @@ nsHTMLTableAccessible::GetAttributesInternal(nsIPersistentProperties *aAttribute
|
||||
nsresult rv = nsAccessibleWrap::GetAttributesInternal(aAttributes);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool isProbablyForLayout;
|
||||
IsProbablyForLayout(&isProbablyForLayout);
|
||||
if (isProbablyForLayout) {
|
||||
if (IsProbablyLayoutTable()) {
|
||||
nsAutoString oldValueUnused;
|
||||
aAttributes->SetStringProperty(NS_LITERAL_CSTRING("layout-guess"),
|
||||
NS_LITERAL_STRING("true"), oldValueUnused);
|
||||
@ -538,13 +546,11 @@ nsHTMLTableAccessible::RelationByType(PRUint32 aType)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLTableAccessible: nsIAccessibleTable implementation
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLTableAccessible::GetCaption(nsIAccessible **aCaption)
|
||||
nsAccessible*
|
||||
nsHTMLTableAccessible::Caption()
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCaption);
|
||||
|
||||
NS_IF_ADDREF(*aCaption = Caption());
|
||||
return NS_OK;
|
||||
nsAccessible* child = mChildren.SafeElementAt(0, nsnull);
|
||||
return child && child->Role() == roles::CAPTION ? child : nsnull;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -1307,8 +1313,7 @@ nsHTMLTableAccessible::Description(nsString& aDescription)
|
||||
|
||||
#ifdef SHOW_LAYOUT_HEURISTIC
|
||||
if (aDescription.IsEmpty()) {
|
||||
bool isProbablyForLayout;
|
||||
IsProbablyForLayout(&isProbablyForLayout);
|
||||
bool isProbablyForLayout = IsProbablyLayoutTable();
|
||||
aDescription = mLayoutHeuristic;
|
||||
}
|
||||
#ifdef DEBUG_A11Y
|
||||
@ -1357,8 +1362,8 @@ nsHTMLTableAccessible::HasDescendant(const nsAString& aTagName,
|
||||
return !!foundItem;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLTableAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout)
|
||||
bool
|
||||
nsHTMLTableAccessible::IsProbablyLayoutTable()
|
||||
{
|
||||
// Implement a heuristic to determine if table is most likely used for layout
|
||||
// XXX do we want to look for rowspan or colspan, especialy that span all but a couple cells
|
||||
@ -1370,18 +1375,16 @@ nsHTMLTableAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout)
|
||||
// Change to |#define SHOW_LAYOUT_HEURISTIC DEBUG| before final release
|
||||
#ifdef SHOW_LAYOUT_HEURISTIC
|
||||
#define RETURN_LAYOUT_ANSWER(isLayout, heuristic) \
|
||||
{ *aIsProbablyForLayout = isLayout; \
|
||||
mLayoutHeuristic = isLayout ? NS_LITERAL_STRING("layout table: ") : NS_LITERAL_STRING("data table: "); \
|
||||
mLayoutHeuristic += NS_LITERAL_STRING(heuristic); return NS_OK; }
|
||||
{ \
|
||||
mLayoutHeuristic = isLayout ? \
|
||||
NS_LITERAL_STRING("layout table: " heuristic) : \
|
||||
NS_LITERAL_STRING("data table: " heuristic); \
|
||||
return isLayout; \
|
||||
}
|
||||
#else
|
||||
#define RETURN_LAYOUT_ANSWER(isLayout, heuristic) { *aIsProbablyForLayout = isLayout; return NS_OK; }
|
||||
#define RETURN_LAYOUT_ANSWER(isLayout, heuristic) { return isLayout; }
|
||||
#endif
|
||||
|
||||
*aIsProbablyForLayout = false;
|
||||
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsDocAccessible* docAccessible = Document();
|
||||
if (docAccessible) {
|
||||
PRUint64 docState = docAccessible->State();
|
||||
|
@ -41,6 +41,8 @@
|
||||
|
||||
#include "nsHyperTextAccessibleWrap.h"
|
||||
#include "nsIAccessibleTable.h"
|
||||
#include "TableAccessible.h"
|
||||
#include "xpcAccessibleTable.h"
|
||||
|
||||
class nsITableLayout;
|
||||
class nsITableCellLayout;
|
||||
@ -121,16 +123,28 @@ public:
|
||||
}
|
||||
|
||||
class nsHTMLTableAccessible : public nsAccessibleWrap,
|
||||
public nsIAccessibleTable
|
||||
public xpcAccessibleTable,
|
||||
public nsIAccessibleTable,
|
||||
public mozilla::a11y::TableAccessible
|
||||
{
|
||||
public:
|
||||
nsHTMLTableAccessible(nsIContent* aContent, nsDocAccessible* aDoc);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIACCESSIBLETABLE
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_TABLEACCESSIBLE_IMPL_CID)
|
||||
|
||||
// nsIAccessible Table
|
||||
NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE
|
||||
|
||||
// TableAccessible
|
||||
virtual nsAccessible* Caption();
|
||||
virtual bool IsProbablyLayoutTable();
|
||||
|
||||
// nsAccessNode
|
||||
virtual void Shutdown();
|
||||
|
||||
// nsAccessible
|
||||
virtual mozilla::a11y::TableAccessible* AsTable() { return this; }
|
||||
virtual void Description(nsString& aDescription);
|
||||
virtual nsresult GetNameInternal(nsAString& aName);
|
||||
virtual mozilla::a11y::role NativeRole();
|
||||
@ -138,13 +152,6 @@ public:
|
||||
virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
|
||||
virtual Relation RelationByType(PRUint32 aRelationType);
|
||||
|
||||
// TableAccessible
|
||||
inline nsAccessible* Caption() const
|
||||
{
|
||||
nsAccessible* child = mChildren.SafeElementAt(0, nsnull);
|
||||
return child && child->Role() == mozilla::a11y::roles::CAPTION ? child : nsnull;
|
||||
}
|
||||
|
||||
// nsHTMLTableAccessible
|
||||
|
||||
/**
|
||||
|
@ -132,7 +132,7 @@ nsHyperTextAccessible::NativeRole()
|
||||
return roles::FORM;
|
||||
|
||||
if (tag == nsGkAtoms::blockquote || tag == nsGkAtoms::div ||
|
||||
tag == nsGkAtoms::nav)
|
||||
tag == nsGkAtoms::section || tag == nsGkAtoms::nav)
|
||||
return roles::SECTION;
|
||||
|
||||
if (tag == nsGkAtoms::h1 || tag == nsGkAtoms::h2 ||
|
||||
@ -1239,6 +1239,9 @@ nsHyperTextAccessible::GetAttributesInternal(nsIPersistentProperties *aAttribute
|
||||
if (mContent->Tag() == nsGkAtoms::nav)
|
||||
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
|
||||
NS_LITERAL_STRING("navigation"));
|
||||
else if (mContent->Tag() == nsGkAtoms::section)
|
||||
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
|
||||
NS_LITERAL_STRING("region"));
|
||||
else if (mContent->Tag() == nsGkAtoms::footer)
|
||||
nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
|
||||
NS_LITERAL_STRING("contentinfo"));
|
||||
|
@ -114,7 +114,9 @@ include $(topsrcdir)/config/rules.mk
|
||||
LOCAL_INCLUDES += \
|
||||
-I$(srcdir) \
|
||||
-I$(srcdir)/../base \
|
||||
-I$(srcdir)/../generic \
|
||||
-I$(srcdir)/../html \
|
||||
-I$(srcdir)/../xpcom \
|
||||
-I$(srcdir)/../xul \
|
||||
-I$(srcdir)/../../../content/base/src \
|
||||
-I$(srcdir)/../../../content/events/src \
|
||||
|
@ -50,6 +50,7 @@ LIBXUL_LIBRARY = 1
|
||||
CPPSRCS = \
|
||||
nsAccEvent.cpp \
|
||||
nsAccessibleRelation.cpp \
|
||||
xpcAccessibleTable.cpp \
|
||||
$(NULL)
|
||||
|
||||
# we don't want the shared lib, but we want to force the creation of a static lib.
|
||||
@ -59,4 +60,5 @@ include $(topsrcdir)/config/rules.mk
|
||||
|
||||
LOCAL_INCLUDES = \
|
||||
-I$(srcdir)/../base \
|
||||
-I$(srcdir)/../generic \
|
||||
$(NULL)
|
||||
|
34
accessible/src/xpcom/xpcAccessibleTable.cpp
Normal file
34
accessible/src/xpcom/xpcAccessibleTable.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "xpcAccessibleTable.h"
|
||||
|
||||
#include "nsAccessible.h"
|
||||
#include "TableAccessible.h"
|
||||
|
||||
nsresult
|
||||
xpcAccessibleTable::GetCaption(nsIAccessible** aCaption)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCaption);
|
||||
*aCaption = nsnull;
|
||||
if (!mTable)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
NS_IF_ADDREF(*aCaption = mTable->Caption());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
xpcAccessibleTable::IsProbablyForLayout(bool* aResult)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
*aResult = false;
|
||||
if (!mTable)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
*aResult = mTable->IsProbablyLayoutTable();
|
||||
return NS_OK;
|
||||
}
|
63
accessible/src/xpcom/xpcAccessibleTable.h
Normal file
63
accessible/src/xpcom/xpcAccessibleTable.h
Normal file
@ -0,0 +1,63 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef MOZILLA_A11Y_XPCOM_XPACCESSIBLETABLE_H_
|
||||
#define MOZILLA_A11Y_XPCOM_XPACCESSIBLETABLE_H_
|
||||
|
||||
#include "nscore.h"
|
||||
|
||||
class nsIAccessible;
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
class TableAccessible;
|
||||
}
|
||||
}
|
||||
|
||||
class xpcAccessibleTable
|
||||
{
|
||||
public:
|
||||
xpcAccessibleTable(mozilla::a11y::TableAccessible* aTable) : mTable(aTable) { }
|
||||
|
||||
nsresult GetCaption(nsIAccessible** aCaption);
|
||||
nsresult IsProbablyForLayout(bool* aIsForLayout);
|
||||
|
||||
protected:
|
||||
mozilla::a11y::TableAccessible* mTable;
|
||||
};
|
||||
|
||||
#define NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE \
|
||||
NS_IMETHOD GetCaption(nsIAccessible** aCaption) \
|
||||
{ return xpcAccessibleTable::GetCaption(aCaption); } \
|
||||
NS_SCRIPTABLE NS_IMETHOD GetSummary(nsAString & aSummary); \
|
||||
NS_SCRIPTABLE NS_IMETHOD GetColumnCount(PRInt32 *aColumnCount); \
|
||||
NS_SCRIPTABLE NS_IMETHOD GetRowCount(PRInt32 *aRowCount); \
|
||||
NS_SCRIPTABLE NS_IMETHOD GetCellAt(PRInt32 rowIndex, PRInt32 columnIndex, nsIAccessible * *_retval NS_OUTPARAM); \
|
||||
NS_SCRIPTABLE NS_IMETHOD GetCellIndexAt(PRInt32 rowIndex, PRInt32 columnIndex, PRInt32 *_retval NS_OUTPARAM); \
|
||||
NS_SCRIPTABLE NS_IMETHOD GetColumnIndexAt(PRInt32 cellIndex, PRInt32 *_retval NS_OUTPARAM); \
|
||||
NS_SCRIPTABLE NS_IMETHOD GetRowIndexAt(PRInt32 cellIndex, PRInt32 *_retval NS_OUTPARAM); \
|
||||
NS_SCRIPTABLE NS_IMETHOD GetRowAndColumnIndicesAt(PRInt32 cellIndex, PRInt32 *rowIndex NS_OUTPARAM, PRInt32 *columnIndex NS_OUTPARAM); \
|
||||
NS_SCRIPTABLE NS_IMETHOD GetColumnExtentAt(PRInt32 row, PRInt32 column, PRInt32 *_retval NS_OUTPARAM); \
|
||||
NS_SCRIPTABLE NS_IMETHOD GetRowExtentAt(PRInt32 row, PRInt32 column, PRInt32 *_retval NS_OUTPARAM); \
|
||||
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 GetSelectedCellCount(PRUint32 *aSelectedCellCount); \
|
||||
NS_SCRIPTABLE NS_IMETHOD GetSelectedColumnCount(PRUint32 *aSelectedColumnCount); \
|
||||
NS_SCRIPTABLE NS_IMETHOD GetSelectedRowCount(PRUint32 *aSelectedRowCount); \
|
||||
NS_SCRIPTABLE NS_IMETHOD GetSelectedCells(nsIArray * *aSelectedCells); \
|
||||
NS_SCRIPTABLE NS_IMETHOD GetSelectedCellIndices(PRUint32 *cellsArraySize NS_OUTPARAM, PRInt32 **cellsArray NS_OUTPARAM); \
|
||||
NS_SCRIPTABLE NS_IMETHOD GetSelectedColumnIndices(PRUint32 *rowsArraySize NS_OUTPARAM, PRInt32 **rowsArray NS_OUTPARAM); \
|
||||
NS_SCRIPTABLE NS_IMETHOD GetSelectedRowIndices(PRUint32 *rowsArraySize NS_OUTPARAM, PRInt32 **rowsArray NS_OUTPARAM); \
|
||||
NS_SCRIPTABLE NS_IMETHOD SelectRow(PRInt32 rowIndex); \
|
||||
NS_SCRIPTABLE NS_IMETHOD SelectColumn(PRInt32 columnIndex); \
|
||||
NS_SCRIPTABLE NS_IMETHOD UnselectColumn(PRInt32 columnIndex); \
|
||||
NS_IMETHOD UnselectRow(PRInt32 aRowIdx); \
|
||||
NS_IMETHOD IsProbablyForLayout(bool* aResult) \
|
||||
{ return xpcAccessibleTable::IsProbablyForLayout(aResult); } \
|
||||
|
||||
#endif // MOZILLA_A11Y_XPCOM_XPACCESSIBLETABLE_H_
|
@ -72,7 +72,9 @@ include $(topsrcdir)/config/rules.mk
|
||||
LOCAL_INCLUDES = \
|
||||
-I$(srcdir) \
|
||||
-I$(srcdir)/../base \
|
||||
-I$(srcdir)/../generic \
|
||||
-I$(srcdir)/../html \
|
||||
-I$(srcdir)/../xpcom \
|
||||
-I$(srcdir)/../../../layout/generic \
|
||||
-I$(srcdir)/../../../layout/xul/base/src \
|
||||
$(NULL)
|
||||
|
@ -134,7 +134,7 @@ nsXULColumnItemAccessible::DoAction(PRUint8 aIndex)
|
||||
|
||||
nsXULListboxAccessible::
|
||||
nsXULListboxAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
|
||||
XULSelectControlAccessible(aContent, aDoc)
|
||||
XULSelectControlAccessible(aContent, aDoc), xpcAccessibleTable(this)
|
||||
{
|
||||
nsIContent* parentContent = mContent->GetParent();
|
||||
if (parentContent) {
|
||||
@ -164,6 +164,16 @@ nsXULListboxAccessible::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
||||
return NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//nsAccessNode
|
||||
|
||||
void
|
||||
nsXULListboxAccessible::Shutdown()
|
||||
{
|
||||
mTable = nsnull;
|
||||
XULSelectControlAccessible::Shutdown();
|
||||
}
|
||||
|
||||
bool
|
||||
nsXULListboxAccessible::IsMulticolumn()
|
||||
{
|
||||
@ -229,15 +239,6 @@ nsXULListboxAccessible::NativeRole()
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsXULListboxAccessible. nsIAccessibleTable
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULListboxAccessible::GetCaption(nsIAccessible **aCaption)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCaption);
|
||||
*aCaption = nsnull;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULListboxAccessible::GetSummary(nsAString &aSummary)
|
||||
{
|
||||
@ -820,15 +821,6 @@ nsXULListboxAccessible::UnselectColumn(PRInt32 aColumn)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULListboxAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aIsProbablyForLayout);
|
||||
*aIsProbablyForLayout = false;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsXULListboxAccessible: Widgets
|
||||
|
||||
|
@ -40,11 +40,12 @@
|
||||
#ifndef __nsXULListboxAccessible_h__
|
||||
#define __nsXULListboxAccessible_h__
|
||||
|
||||
#include "nsIAccessibleTable.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsXULMenuAccessible.h"
|
||||
#include "nsBaseWidgetAccessible.h"
|
||||
#include "nsIAccessibleTable.h"
|
||||
#include "TableAccessible.h"
|
||||
#include "xpcAccessibleTable.h"
|
||||
#include "XULSelectControlAccessible.h"
|
||||
|
||||
class nsIWeakReference;
|
||||
@ -90,19 +91,27 @@ public:
|
||||
* A class the represents the XUL Listbox widget.
|
||||
*/
|
||||
class nsXULListboxAccessible : public XULSelectControlAccessible,
|
||||
public nsIAccessibleTable
|
||||
public xpcAccessibleTable,
|
||||
public nsIAccessibleTable,
|
||||
public mozilla::a11y::TableAccessible
|
||||
{
|
||||
public:
|
||||
nsXULListboxAccessible(nsIContent* aContent, nsDocAccessible* aDoc);
|
||||
virtual ~nsXULListboxAccessible() {}
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIACCESSIBLETABLE
|
||||
|
||||
// nsIAccessibleTable
|
||||
NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE
|
||||
|
||||
// nsIAccessible
|
||||
NS_IMETHOD GetValue(nsAString& aValue);
|
||||
|
||||
// nsAccessNode
|
||||
virtual void Shutdown();
|
||||
|
||||
// nsAccessible
|
||||
virtual mozilla::a11y::TableAccessible* AsTable() { return this; }
|
||||
virtual mozilla::a11y::role NativeRole();
|
||||
virtual PRUint64 NativeState();
|
||||
|
||||
|
@ -58,7 +58,7 @@ using namespace mozilla::a11y;
|
||||
|
||||
nsXULTreeGridAccessible::
|
||||
nsXULTreeGridAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
|
||||
nsXULTreeAccessible(aContent, aDoc)
|
||||
nsXULTreeAccessible(aContent, aDoc), xpcAccessibleTable(this)
|
||||
{
|
||||
}
|
||||
|
||||
@ -72,15 +72,6 @@ NS_IMPL_ISUPPORTS_INHERITED1(nsXULTreeGridAccessible,
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsXULTreeGridAccessible: nsIAccessibleTable implementation
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTreeGridAccessible::GetCaption(nsIAccessible **aCaption)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCaption);
|
||||
*aCaption = nsnull;
|
||||
|
||||
return IsDefunct() ? NS_ERROR_FAILURE : NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTreeGridAccessible::GetSummary(nsAString &aSummary)
|
||||
{
|
||||
@ -570,13 +561,14 @@ nsXULTreeGridAccessible::UnselectColumn(PRInt32 aColumnIndex)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTreeGridAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aIsProbablyForLayout);
|
||||
*aIsProbablyForLayout = false;
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsXULTreeGridAccessible: nsAccessNode implementation
|
||||
|
||||
return NS_OK;
|
||||
void
|
||||
nsXULTreeGridAccessible::Shutdown()
|
||||
{
|
||||
mTable = nsnull;
|
||||
nsXULTreeAccessible::Shutdown();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -39,15 +39,17 @@
|
||||
#ifndef __nsXULTreeGridAccessible_h__
|
||||
#define __nsXULTreeGridAccessible_h__
|
||||
|
||||
#include "nsIAccessibleTable.h"
|
||||
|
||||
#include "nsXULTreeAccessible.h"
|
||||
#include "TableAccessible.h"
|
||||
#include "xpcAccessibleTable.h"
|
||||
|
||||
/**
|
||||
* Represents accessible for XUL tree in the case when it has multiple columns.
|
||||
*/
|
||||
class nsXULTreeGridAccessible : public nsXULTreeAccessible,
|
||||
public nsIAccessibleTable
|
||||
public xpcAccessibleTable,
|
||||
public nsIAccessibleTable,
|
||||
public mozilla::a11y::TableAccessible
|
||||
{
|
||||
public:
|
||||
nsXULTreeGridAccessible(nsIContent* aContent, nsDocAccessible* aDoc);
|
||||
@ -56,9 +58,13 @@ public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsIAccessibleTable
|
||||
NS_DECL_NSIACCESSIBLETABLE
|
||||
NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE
|
||||
|
||||
// nsAccessNode
|
||||
virtual void Shutdown();
|
||||
|
||||
// nsAccessible
|
||||
virtual mozilla::a11y::TableAccessible* AsTable() { return this; }
|
||||
virtual mozilla::a11y::role NativeRole();
|
||||
|
||||
protected:
|
||||
|
@ -24,6 +24,7 @@
|
||||
testRole("footer", ROLE_FOOTER);
|
||||
testRole("article", ROLE_DOCUMENT);
|
||||
testRole("aside", ROLE_NOTE);
|
||||
testRole("section", ROLE_SECTION); // XXX bug 739612: not a landmark
|
||||
|
||||
testRole("main", ROLE_DOCUMENT);
|
||||
testRole("form", ROLE_FORM);
|
||||
@ -32,6 +33,7 @@
|
||||
testAttrs("nav", {"xml-roles" : "navigation"}, true);
|
||||
testAttrs("footer", {"xml-roles" : "contentinfo"}, true);
|
||||
testAttrs("aside", {"xml-roles" : "complementary"}, true);
|
||||
testAttrs("section", {"xml-roles" : "region"}, true);
|
||||
testAttrs("main", {"xml-roles" : "main"}, true); // // ARIA override
|
||||
testAttrs("form", {"xml-roles" : "form"}, true);
|
||||
|
||||
@ -41,6 +43,7 @@
|
||||
testAttrs("footer", {"tag" : "footer"}, true);
|
||||
testAttrs("article", {"tag" : "article"}, true);
|
||||
testAttrs("aside", {"tag" : "aside"}, true);
|
||||
testAttrs("section", {"tag" : "section"}, true);
|
||||
testAttrs("main", {"tag" : "article"}, true);
|
||||
testAttrs("form", {"tag" : "article"}, true);
|
||||
|
||||
@ -68,6 +71,11 @@
|
||||
title="Change implementation of HTML5 landmark elements to conform">
|
||||
Bug 610650
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=614310"
|
||||
title="Map section to pane (like role=region)">
|
||||
Mozilla Bug 614310
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=734982"
|
||||
title="Map ARIA role FORM">
|
||||
@ -82,6 +90,7 @@
|
||||
<header id="header">a header</header>
|
||||
<footer id="footer">a footer</footer>
|
||||
<aside id="aside">by the way I am an aside</aside>
|
||||
<section id="section">a section</section>
|
||||
|
||||
<article id="article">an article</article>
|
||||
<article id="main" role="main">a main area</article>
|
||||
|
@ -53,6 +53,7 @@ const ROLE_PROGRESSBAR = nsIAccessibleRole.ROLE_PROGRESSBAR;
|
||||
const ROLE_PROPERTYPAGE = nsIAccessibleRole.ROLE_PROPERTYPAGE;
|
||||
const ROLE_PUSHBUTTON = nsIAccessibleRole.ROLE_PUSHBUTTON;
|
||||
const ROLE_RADIOBUTTON = nsIAccessibleRole.ROLE_RADIOBUTTON;
|
||||
const ROLE_RICH_OPTION = nsIAccessibleRole.ROLE_RICH_OPTION;
|
||||
const ROLE_ROW = nsIAccessibleRole.ROLE_ROW;
|
||||
const ROLE_ROWHEADER = nsIAccessibleRole.ROLE_ROWHEADER;
|
||||
const ROLE_SCROLLBAR = nsIAccessibleRole.ROLE_SCROLLBAR;
|
||||
|
@ -57,6 +57,7 @@ _TEST_FILES =\
|
||||
test_imagemap.html \
|
||||
test_list_editabledoc.html \
|
||||
test_list.html \
|
||||
test_listbox.xul \
|
||||
test_menu.xul \
|
||||
test_menubutton.xul \
|
||||
test_recreation.html \
|
||||
|
180
accessible/tests/mochitest/treeupdate/test_listbox.xul
Normal file
180
accessible/tests/mochitest/treeupdate/test_listbox.xul
Normal file
@ -0,0 +1,180 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
|
||||
type="text/css"?>
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="Accessible XUL listbox hierarchy tests">
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
|
||||
|
||||
<script type="application/javascript"
|
||||
src="../common.js" />
|
||||
<script type="application/javascript"
|
||||
src="../role.js" />
|
||||
<script type="application/javascript"
|
||||
src="../events.js" />
|
||||
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Test
|
||||
|
||||
function insertListitem(aListboxID)
|
||||
{
|
||||
this.listboxNode = getNode(aListboxID);
|
||||
|
||||
this.listitemNode = document.createElement("listitem");
|
||||
this.listitemNode.setAttribute("label", "item1");
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_SHOW, this.listitemNode),
|
||||
new invokerChecker(EVENT_REORDER, this.listboxNode)
|
||||
];
|
||||
|
||||
this.invoke = function insertListitem_invoke()
|
||||
{
|
||||
this.listboxNode.insertBefore(this.listitemNode,
|
||||
this.listboxNode.firstChild);
|
||||
}
|
||||
|
||||
this.finalCheck = function insertListitem_finalCheck()
|
||||
{
|
||||
var tree =
|
||||
{ LISTBOX: [
|
||||
{
|
||||
role: ROLE_RICH_OPTION,
|
||||
name: "item1"
|
||||
},
|
||||
{
|
||||
role: ROLE_RICH_OPTION,
|
||||
name: "item2"
|
||||
},
|
||||
{
|
||||
role: ROLE_RICH_OPTION,
|
||||
name: "item3"
|
||||
},
|
||||
{
|
||||
role: ROLE_RICH_OPTION,
|
||||
name: "item4"
|
||||
}
|
||||
] };
|
||||
testAccessibleTree(this.listboxNode, tree);
|
||||
}
|
||||
|
||||
this.getID = function insertListitem_getID()
|
||||
{
|
||||
return "insert listitem ";
|
||||
}
|
||||
}
|
||||
|
||||
function removeListitem(aListboxID)
|
||||
{
|
||||
this.listboxNode = getNode(aListboxID);
|
||||
this.listitemNode = null;
|
||||
this.listitem;
|
||||
|
||||
function getListitem(aThisObj)
|
||||
{
|
||||
return aThisObj.listitem;
|
||||
}
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_HIDE, getListitem, this),
|
||||
new invokerChecker(EVENT_REORDER, this.listboxNode)
|
||||
];
|
||||
|
||||
this.invoke = function removeListitem_invoke()
|
||||
{
|
||||
this.listitemNode = this.listboxNode.firstChild;
|
||||
this.listitem = getAccessible(this.listitemNode);
|
||||
|
||||
this.listboxNode.removeChild(this.listitemNode);
|
||||
}
|
||||
|
||||
this.finalCheck = function removeListitem_finalCheck()
|
||||
{
|
||||
var tree =
|
||||
{ LISTBOX: [
|
||||
{
|
||||
role: ROLE_RICH_OPTION,
|
||||
name: "item2"
|
||||
},
|
||||
{
|
||||
role: ROLE_RICH_OPTION,
|
||||
name: "item3"
|
||||
},
|
||||
{
|
||||
role: ROLE_RICH_OPTION,
|
||||
name: "item4"
|
||||
}
|
||||
] };
|
||||
testAccessibleTree(this.listboxNode, tree);
|
||||
}
|
||||
|
||||
this.getID = function removeListitem_getID()
|
||||
{
|
||||
return "remove listitem ";
|
||||
}
|
||||
}
|
||||
|
||||
//gA11yEventDumpToConsole = true; // debug stuff
|
||||
|
||||
var gQueue = null;
|
||||
function doTest()
|
||||
{
|
||||
var tree =
|
||||
{ LISTBOX: [
|
||||
{
|
||||
role: ROLE_RICH_OPTION,
|
||||
name: "item2"
|
||||
},
|
||||
{
|
||||
role: ROLE_RICH_OPTION,
|
||||
name: "item3"
|
||||
},
|
||||
{
|
||||
role: ROLE_RICH_OPTION,
|
||||
name: "item4"
|
||||
}
|
||||
] };
|
||||
testAccessibleTree("listbox", tree);
|
||||
|
||||
gQueue = new eventQueue();
|
||||
gQueue.push(new insertListitem("listbox"));
|
||||
gQueue.push(new removeListitem("listbox"));
|
||||
gQueue.invoke(); // Will call SimpleTest.finish()
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addA11yLoadEvent(doTest);
|
||||
]]>
|
||||
</script>
|
||||
|
||||
<hbox flex="1" style="overflow: auto;">
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=656225"
|
||||
title="XUL listbox accessible tree doesn't get updated">
|
||||
Mozilla Bug 656225
|
||||
</a>
|
||||
<br/>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
|
||||
<vbox flex="1">
|
||||
<listbox id="listbox" rows="2">
|
||||
<listitem label="item2"/>
|
||||
<listitem label="item3"/>
|
||||
<listitem label="item4"/>
|
||||
</listbox>
|
||||
</vbox>
|
||||
</hbox>
|
||||
|
||||
</window>
|
||||
|
@ -69,3 +69,4 @@ fi
|
||||
|
||||
MOZ_APP_ID={3c2e2abc-06d4-11e1-ac3b-374f68613e61}
|
||||
MOZ_EXTENSION_MANAGER=1
|
||||
ENABLE_MARIONETTE=1
|
||||
|
@ -56,13 +56,14 @@ DIRS = \
|
||||
app \
|
||||
$(NULL)
|
||||
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
ifdef MAKENSISU
|
||||
DIRS += installer/windows
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
ifdef MAKENSISU
|
||||
|
||||
# For Windows build the uninstaller during the application build since the
|
||||
# uninstaller is included with the application for mar file generation.
|
||||
libs::
|
||||
|
@ -8663,6 +8663,31 @@ let gPrivateBrowsingUI = {
|
||||
|
||||
get privateBrowsingEnabled() {
|
||||
return this._privateBrowsingService.privateBrowsingEnabled;
|
||||
},
|
||||
|
||||
/**
|
||||
* These accessors are used to support per-window Private Browsing mode.
|
||||
* For now the getter returns nsIPrivateBrowsingService.privateBrowsingEnabled,
|
||||
* and the setter should only be used in tests.
|
||||
*/
|
||||
get privateWindow() {
|
||||
return window.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShellTreeItem)
|
||||
.treeOwner
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIXULWindow)
|
||||
.docShell.QueryInterface(Ci.nsILoadContext)
|
||||
.usePrivateBrowsing;
|
||||
},
|
||||
|
||||
set privateWindow(val) {
|
||||
return window.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShellTreeItem)
|
||||
.treeOwner
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIXULWindow)
|
||||
.docShell.QueryInterface(Ci.nsILoadContext)
|
||||
.usePrivateBrowsing = val;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -193,9 +193,9 @@ PrivateBrowsingService.prototype = {
|
||||
if (!this._quitting && this._saveSession) {
|
||||
let browserWindow = this._getBrowserWindow();
|
||||
|
||||
// if there are open browser windows, load a dummy session to get a distinct
|
||||
// if there are open browser windows, load a dummy session to get a distinct
|
||||
// separation between private and non-private sessions
|
||||
if (browserWindow) {
|
||||
if (browserWindow) {
|
||||
// set an empty session to transition from/to pb mode, see bug 476463
|
||||
ss.setBrowserState(blankState);
|
||||
|
||||
@ -217,7 +217,9 @@ PrivateBrowsingService.prototype = {
|
||||
.getInterface(Ci.nsIXULWindow)
|
||||
.docShell.contentViewer.resetCloseWindow();
|
||||
}
|
||||
}
|
||||
|
||||
if (!this._quitting) {
|
||||
var windowsEnum = Services.wm.getEnumerator("navigator:browser");
|
||||
while (windowsEnum.hasMoreElements()) {
|
||||
var window = windowsEnum.getNext();
|
||||
|
@ -58,21 +58,31 @@ function test() {
|
||||
ok(gPrivateBrowsingUI, "The gPrivateBrowsingUI object exists");
|
||||
is(pb.privateBrowsingEnabled, false, "The private browsing mode should not be started initially");
|
||||
is(gPrivateBrowsingUI.privateBrowsingEnabled, false, "gPrivateBrowsingUI should expose the correct private browsing status");
|
||||
is(gPrivateBrowsingUI.privateWindow, false, "gPrivateBrowsingUI should expose the correct per-window private browsing status");
|
||||
ok(pbMenuItem, "The Private Browsing menu item exists");
|
||||
is(pbMenuItem.getAttribute("label"), pbMenuItem.getAttribute("startlabel"), "The Private Browsing menu item should read \"Start Private Browsing\"");
|
||||
gPrivateBrowsingUI.toggleMode();
|
||||
is(pb.privateBrowsingEnabled, true, "The private browsing mode should be started");
|
||||
is(gPrivateBrowsingUI.privateBrowsingEnabled, true, "gPrivateBrowsingUI should expose the correct private browsing status");
|
||||
is(gPrivateBrowsingUI.privateWindow, true, "gPrivateBrowsingUI should expose the correct per-window private browsing status");
|
||||
// check to see if the Private Browsing mode was activated successfully
|
||||
is(observerData, "enter", "Private Browsing mode was activated using the gPrivateBrowsingUI object");
|
||||
is(pbMenuItem.getAttribute("label"), pbMenuItem.getAttribute("stoplabel"), "The Private Browsing menu item should read \"Stop Private Browsing\"");
|
||||
gPrivateBrowsingUI.toggleMode()
|
||||
is(pb.privateBrowsingEnabled, false, "The private browsing mode should not be started");
|
||||
is(gPrivateBrowsingUI.privateBrowsingEnabled, false, "gPrivateBrowsingUI should expose the correct private browsing status");
|
||||
is(gPrivateBrowsingUI.privateWindow, false, "gPrivateBrowsingUI should expose the correct per-window private browsing status");
|
||||
// check to see if the Private Browsing mode was deactivated successfully
|
||||
is(observerData, "exit", "Private Browsing mode was deactivated using the gPrivateBrowsingUI object");
|
||||
is(pbMenuItem.getAttribute("label"), pbMenuItem.getAttribute("startlabel"), "The Private Browsing menu item should read \"Start Private Browsing\"");
|
||||
|
||||
// These are tests for the privateWindow setter. Note that the setter should
|
||||
// not be used anywhere else for now!
|
||||
gPrivateBrowsingUI.privateWindow = true;
|
||||
is(gPrivateBrowsingUI.privateWindow, true, "gPrivateBrowsingUI should accept the correct per-window private browsing status");
|
||||
gPrivateBrowsingUI.privateWindow = false;
|
||||
is(gPrivateBrowsingUI.privateWindow, false, "gPrivateBrowsingUI should accept the correct per-window private browsing status");
|
||||
|
||||
// now, test using the <command> object
|
||||
let cmd = document.getElementById("Tools:PrivateBrowsing");
|
||||
isnot(cmd, null, "XUL command object for the private browsing service exists");
|
||||
|
@ -102,7 +102,7 @@ if [ "$MOZ_SAFE_BROWSING" ]; then
|
||||
"
|
||||
fi
|
||||
|
||||
if [ "$MOZ_WIDGET_TOOLKIT" = "windows" ]; then
|
||||
if [ "$MAKENSISU" ]; then
|
||||
add_makefiles "
|
||||
browser/installer/windows/Makefile
|
||||
"
|
||||
|
@ -41,6 +41,7 @@ package @ANDROID_PACKAGE_NAME@;
|
||||
|
||||
public interface Assert {
|
||||
void dumpLog(String message);
|
||||
void dumpLog(String message, Throwable t);
|
||||
void setLogFile(String filename);
|
||||
void setTestName(String testName);
|
||||
|
||||
|
@ -66,6 +66,11 @@ public class FennecMochitestAssert implements Assert {
|
||||
FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_INFO, message);
|
||||
}
|
||||
|
||||
/** Write information to a logfile and logcat */
|
||||
public void dumpLog(String message, Throwable t) {
|
||||
FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_INFO, message, t);
|
||||
}
|
||||
|
||||
/** Set the filename used for dumpLog. */
|
||||
public void setLogFile(String filename) {
|
||||
FennecNativeDriver.setLogFile(filename);
|
||||
|
@ -41,7 +41,6 @@ package @ANDROID_PACKAGE_NAME@;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
@ -49,6 +48,7 @@ import java.io.FileWriter;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.IntBuffer;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@ -459,41 +459,48 @@ public class FennecNativeDriver implements Driver {
|
||||
}
|
||||
|
||||
public static void log(LogLevel level, String message) {
|
||||
log(level, message, null);
|
||||
}
|
||||
|
||||
public static void log(LogLevel level, Throwable t) {
|
||||
log(level, null, t);
|
||||
}
|
||||
|
||||
public static void log(LogLevel level, String message, Throwable t) {
|
||||
if (mLogFile == null) {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
if (level.isEnabled(mLogLevel)) {
|
||||
File file = new File(mLogFile);
|
||||
BufferedWriter bw = null;
|
||||
|
||||
PrintWriter pw = null;
|
||||
try {
|
||||
bw = new BufferedWriter(new FileWriter(mLogFile, true));
|
||||
bw.write(message);
|
||||
bw.newLine();
|
||||
} catch(IOException e) {
|
||||
pw = new PrintWriter(new FileWriter(mLogFile, true));
|
||||
if (message != null) {
|
||||
pw.println(message);
|
||||
}
|
||||
if (t != null) {
|
||||
t.printStackTrace(pw);
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
Log.e("Robocop", "exception with file writer on: " + mLogFile);
|
||||
} finally {
|
||||
try {
|
||||
if (bw != null) {
|
||||
bw.flush();
|
||||
bw.close();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
pw.close();
|
||||
}
|
||||
// PrintWriter doesn't throw IOE but sets an error flag instead,
|
||||
// so check for that
|
||||
if (pw.checkError()) {
|
||||
Log.e("Robocop", "exception with file writer on: " + mLogFile);
|
||||
}
|
||||
}
|
||||
|
||||
if (level == LogLevel.LOG_LEVEL_INFO) {
|
||||
Log.i("Robocop", message);
|
||||
Log.i("Robocop", message, t);
|
||||
} else if (level == LogLevel.LOG_LEVEL_DEBUG) {
|
||||
Log.d("Robocop", message);
|
||||
Log.d("Robocop", message, t);
|
||||
} else if (level == LogLevel.LOG_LEVEL_WARN) {
|
||||
Log.w("Robocop", message);
|
||||
Log.w("Robocop", message, t);
|
||||
} else if (level == LogLevel.LOG_LEVEL_ERROR) {
|
||||
Log.e("Robocop", message);
|
||||
Log.e("Robocop", message, t);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -49,6 +49,11 @@ public class FennecTalosAssert implements Assert {
|
||||
FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_INFO, message);
|
||||
}
|
||||
|
||||
/** Write information to a logfile and logcat */
|
||||
public void dumpLog(String message, Throwable t) {
|
||||
FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_INFO, message, t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the filename used for dumpLog.
|
||||
*/
|
||||
|
@ -127,8 +127,8 @@ classes.dex: $(_JAVA_TESTS)
|
||||
$(JAVAC) $(JAVAC_FLAGS) -d classes $(JAVAFILES) $(_JAVA_HARNESS) $(addprefix $(DEPTH)/mobile/android/base/tests/,$(_JAVA_TESTS))
|
||||
$(DX) --dex --output=$@ classes $(ROBOTIUM_PATH)
|
||||
|
||||
robocop.ap_: AndroidManifest.xml
|
||||
$(AAPT) package -f -M AndroidManifest.xml -I $(ANDROID_SDK)/android.jar -I . -S res -F $@ -J ./
|
||||
robocop.ap_: AndroidManifest.xml $(TESTPATH)/assets/*
|
||||
$(AAPT) package -f -M AndroidManifest.xml -I $(ANDROID_SDK)/android.jar -I . -S res -A $(TESTPATH)/assets -F $@ -J ./
|
||||
|
||||
robocop.apk: robocop.ap_ classes.dex
|
||||
cp $(TESTPATH)/robocop.ini robocop.ini
|
||||
|
@ -265,9 +265,9 @@ build_one_stage({"CC": "gcc", "CXX" : "g++"}, stage1_dir, True)
|
||||
|
||||
stage1_tool_inst_dir = stage1_dir + '/inst'
|
||||
stage2_dir = build_dir + '/stage2'
|
||||
build_one_stage({"CC" : stage1_tool_inst_dir + "/bin/gcc -fgnu89-inline",
|
||||
"CXX" : stage1_tool_inst_dir + "/bin/g++",
|
||||
"AR" : stage1_tool_inst_dir + "/bin/ar",
|
||||
build_one_stage({"PATH" : stage1_tool_inst_dir + "/bin:/bin:/usr/bin",
|
||||
"CC" : "gcc -fgnu89-inline",
|
||||
"CXX" : "g++",
|
||||
"RANLIB" : "true" },
|
||||
stage2_dir, False)
|
||||
|
||||
|
53
configure.in
53
configure.in
@ -6319,29 +6319,38 @@ dnl ========================================================
|
||||
dnl Installer
|
||||
dnl ========================================================
|
||||
dnl Abort Windows build if the required major version and
|
||||
dnl minimum minor version of Unicode NSIS isn't in the path.
|
||||
dnl minimum minor version of Unicode NSIS isn't in the path
|
||||
dnl (unless in case of cross compiling, for which Unicode
|
||||
dnl is not yet sufficient).
|
||||
if test "$OS_ARCH" = "WINNT"; then
|
||||
REQ_NSIS_MAJOR_VER=2
|
||||
MIN_NSIS_MINOR_VER=33
|
||||
MOZ_PATH_PROGS(MAKENSISU, $MAKENSISU makensisu-2.46 makensisu makensis)
|
||||
if test -z "$MAKENSISU" -o "$MAKENSISU" = ":"; then
|
||||
AC_MSG_ERROR([To build the installer you must have the latest MozillaBuild or Unicode NSIS with a major version of $REQ_NSIS_MAJOR_VER and a minimum minor version of $MIN_NSIS_MINOR_VER in your path.])
|
||||
if test -n "$MAKENSISU" -a "$MAKENSISU" != ":"; then
|
||||
AC_MSG_RESULT([yes])
|
||||
changequote(,)
|
||||
MAKENSISU_VER=`"$MAKENSISU" -version 2>/dev/null | sed -e '/-Unicode/!s/.*//g' -e 's/^v\([0-9]\+\.[0-9]\+\)\-Unicode$/\1/g'`
|
||||
changequote([,])
|
||||
if test ! "$MAKENSISU_VER" = ""; then
|
||||
MAKENSISU_MAJOR_VER=`echo $MAKENSISU_VER | $AWK -F\. '{ print $1 }'`
|
||||
MAKENSISU_MINOR_VER=`echo $MAKENSISU_VER | $AWK -F\. '{ print $2 }'`
|
||||
fi
|
||||
AC_MSG_CHECKING([for Unicode NSIS with major version == $REQ_NSIS_MAJOR_VER and minor version >= $MIN_NSIS_MINOR_VER])
|
||||
if test "$MAKENSISU_VER" = "" || \
|
||||
test ! "$MAKENSISU_MAJOR_VER" = "$REQ_NSIS_MAJOR_VER" -o \
|
||||
! "$MAKENSISU_MINOR_VER" -ge $MIN_NSIS_MINOR_VER; then
|
||||
AC_MSG_RESULT([no])
|
||||
if test -z "$CROSS_COMPILE"; then
|
||||
AC_MSG_ERROR([To build the installer you must have the latest MozillaBuild or Unicode NSIS with a major version of $REQ_NSIS_MAJOR_VER and a minimum minor version of $MIN_NSIS_MINOR_VER in your path.])
|
||||
else
|
||||
MAKENSISU=
|
||||
fi
|
||||
fi
|
||||
elif test -z "$CROSS_COMPILE"; then
|
||||
AC_MSG_ERROR([To build the installer you must have the latest MozillaBuild or Unicode NSIS with a major version of $REQ_NSIS_MAJOR_VER and a minimum minor version of $MIN_NSIS_MINOR_VER in your path.])
|
||||
else
|
||||
MAKENSISU=
|
||||
fi
|
||||
changequote(,)
|
||||
MAKENSISU_VER=`"$MAKENSISU" -version 2>/dev/null | sed -e '/-Unicode/!s/.*//g' -e 's/^v\([0-9]\+\.[0-9]\+\)\-Unicode$/\1/g'`
|
||||
changequote([,])
|
||||
if test ! "$MAKENSISU_VER" = ""; then
|
||||
MAKENSISU_MAJOR_VER=`echo $MAKENSISU_VER | $AWK -F\. '{ print $1 }'`
|
||||
MAKENSISU_MINOR_VER=`echo $MAKENSISU_VER | $AWK -F\. '{ print $2 }'`
|
||||
fi
|
||||
AC_MSG_CHECKING([for Unicode NSIS with major version == $REQ_NSIS_MAJOR_VER and minor version >= $MIN_NSIS_MINOR_VER])
|
||||
if test "$MAKENSISU_VER" = "" ||
|
||||
test ! "$MAKENSISU_MAJOR_VER" = "$REQ_NSIS_MAJOR_VER" -o \
|
||||
! "$MAKENSISU_MINOR_VER" -ge $MIN_NSIS_MINOR_VER; then
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([To build the installer you must have the latest MozillaBuild or Unicode NSIS with a major version of $REQ_NSIS_MAJOR_VER and a minimum minor version of $MIN_NSIS_MINOR_VER in your path.])
|
||||
fi
|
||||
AC_MSG_RESULT([yes])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([for tar archiver])
|
||||
@ -6458,14 +6467,6 @@ MOZ_ARG_DISABLE_BOOL(tests,
|
||||
ENABLE_TESTS=,
|
||||
ENABLE_TESTS=1 )
|
||||
|
||||
dnl ========================================================
|
||||
dnl Marionette
|
||||
dnl ========================================================
|
||||
MOZ_ARG_ENABLE_BOOL(marionette,
|
||||
[ --enable-marionette Enable Marionette for remote testing and control],
|
||||
ENABLE_MARIONETTE=1,
|
||||
ENABLE_MARIONETTE)
|
||||
|
||||
dnl ========================================================
|
||||
dnl parental controls (for Windows Vista)
|
||||
dnl ========================================================
|
||||
|
@ -19,6 +19,7 @@
|
||||
* Contributor(s):
|
||||
* Sid Stamm <sid@mozilla.com>
|
||||
* Brandon Sterne <bsterne@mozilla.com>
|
||||
* Ian Melven <imelven@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -301,7 +302,7 @@ ContentSecurityPolicy.prototype = {
|
||||
|
||||
var failure = function(aEvt) {
|
||||
if (req.readyState == 4 && req.status != 200) {
|
||||
CSPError("Failed to send report to " + reportURI);
|
||||
CSPError("Failed to send report to " + uris[i]);
|
||||
}
|
||||
};
|
||||
var req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
|
||||
@ -313,6 +314,10 @@ ContentSecurityPolicy.prototype = {
|
||||
req.upload.addEventListener("error", failure, false);
|
||||
req.upload.addEventListener("abort", failure, false);
|
||||
|
||||
// we need to set an nsIChannelEventSink on the XHR object
|
||||
// so we can tell it to not follow redirects when posting the reports
|
||||
req.channel.notificationCallbacks = new CSPReportRedirectSink();
|
||||
|
||||
req.send(JSON.stringify(report));
|
||||
CSPdebug("Sent violation report to " + uris[i]);
|
||||
} catch(e) {
|
||||
@ -494,4 +499,54 @@ ContentSecurityPolicy.prototype = {
|
||||
},
|
||||
};
|
||||
|
||||
// The POST of the violation report (if it happens) should not follow
|
||||
// redirects, per the spec. hence, we implement an nsIChannelEventSink
|
||||
// with an object so we can tell XHR to abort if a redirect happens.
|
||||
function CSPReportRedirectSink() {
|
||||
}
|
||||
|
||||
CSPReportRedirectSink.prototype = {
|
||||
QueryInterface: function requestor_qi(iid) {
|
||||
if (iid.equals(Ci.nsISupports) ||
|
||||
iid.equals(Ci.nsIInterfaceRequestor) ||
|
||||
iid.equals(Ci.nsIChannelEventSink))
|
||||
return this;
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
|
||||
// nsIInterfaceRequestor
|
||||
getInterface: function requestor_gi(iid) {
|
||||
if (iid.equals(Ci.nsIChannelEventSink))
|
||||
return this;
|
||||
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
|
||||
// nsIChannelEventSink
|
||||
asyncOnChannelRedirect: function channel_redirect(oldChannel, newChannel,
|
||||
flags, callback) {
|
||||
CSPWarning("Post of violation report to " + oldChannel.URI.asciiSpec +
|
||||
" failed, as a redirect occurred");
|
||||
|
||||
// cancel the old channel so XHR failure callback happens
|
||||
oldChannel.cancel(Cr.NS_ERROR_ABORT);
|
||||
|
||||
// notify an observer that we have blocked the report POST due to a redirect,
|
||||
// used in testing, do this async since we're in an async call now to begin with
|
||||
Services.tm.mainThread.dispatch(
|
||||
function() {
|
||||
observerSubject = Cc["@mozilla.org/supports-cstring;1"]
|
||||
.createInstance(Ci.nsISupportsCString);
|
||||
observerSubject.data = oldChannel.URI.asciiSpec;
|
||||
|
||||
Services.obs.notifyObservers(observerSubject,
|
||||
CSP_VIOLATION_TOPIC,
|
||||
"denied redirect while sending violation report");
|
||||
}, Ci.nsIThread.DISPATCH_NORMAL);
|
||||
|
||||
// throw to stop the redirect happening
|
||||
throw Cr.NS_BINDING_REDIRECTED;
|
||||
}
|
||||
};
|
||||
|
||||
var NSGetFactory = XPCOMUtils.generateNSGetFactory([ContentSecurityPolicy]);
|
||||
|
@ -378,3 +378,29 @@ nsCCUncollectableMarker::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
TraceActiveWindowGlobal(const PRUint64& aId, nsGlobalWindow*& aWindow, void* aClosure)
|
||||
{
|
||||
if (aWindow->GetDocShell() && aWindow->IsOuterWindow()) {
|
||||
if (JSObject* global = aWindow->FastGetGlobalJSObject()) {
|
||||
JSTracer* trc = static_cast<JSTracer *>(aClosure);
|
||||
JS_CALL_OBJECT_TRACER(trc, global, "active window global");
|
||||
}
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
mozilla::dom::TraceBlackJS(JSTracer* aTrc)
|
||||
{
|
||||
if (!nsCCUncollectableMarker::sGeneration) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Mark globals of active windows black.
|
||||
nsGlobalWindow::WindowByIdTable* windowsById =
|
||||
nsGlobalWindow::GetWindowsTable();
|
||||
if (windowsById) {
|
||||
windowsById->Enumerate(TraceActiveWindowGlobal, aTrc);
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,8 @@
|
||||
#include "nsIObserver.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
|
||||
struct JSTracer;
|
||||
|
||||
class nsCCUncollectableMarker : public nsIObserver
|
||||
{
|
||||
NS_DECL_ISUPPORTS
|
||||
@ -56,10 +58,10 @@ class nsCCUncollectableMarker : public nsIObserver
|
||||
return aGeneration && aGeneration == sGeneration;
|
||||
}
|
||||
|
||||
static bool InGeneration(nsCycleCollectionTraversalCallback &cb,
|
||||
static bool InGeneration(nsCycleCollectionTraversalCallback& aCb,
|
||||
PRUint32 aGeneration)
|
||||
{
|
||||
return InGeneration(aGeneration) && !cb.WantAllTraces();
|
||||
return InGeneration(aGeneration) && !aCb.WantAllTraces();
|
||||
}
|
||||
|
||||
static PRUint32 sGeneration;
|
||||
@ -68,3 +70,9 @@ private:
|
||||
nsCCUncollectableMarker() {}
|
||||
|
||||
};
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
void TraceBlackJS(JSTracer* aTrc);
|
||||
}
|
||||
}
|
||||
|
@ -2547,6 +2547,7 @@ void
|
||||
nsDocument::StopDocumentLoad()
|
||||
{
|
||||
if (mParser) {
|
||||
mParserAborted = true;
|
||||
mParser->Terminate();
|
||||
}
|
||||
}
|
||||
|
@ -1188,6 +1188,10 @@ protected:
|
||||
// our presshell. This is used to handle flush reentry correctly.
|
||||
bool mInFlush:1;
|
||||
|
||||
// Parser aborted. True if the parser of this document was forcibly
|
||||
// terminated instead of letting it finish at its own pace.
|
||||
bool mParserAborted:1;
|
||||
|
||||
PRUint8 mXMLDeclarationBits;
|
||||
|
||||
nsInterfaceHashtable<nsPtrHashKey<nsIContent>, nsPIBoxObject> *mBoxObjectTable;
|
||||
|
@ -1935,7 +1935,8 @@ GK_ATOM(VolumeUp, "VolumeUp")
|
||||
GK_ATOM(VolumeDown, "VolumeDown")
|
||||
GK_ATOM(Menu, "Menu")
|
||||
|
||||
// Smooth scroll profiles
|
||||
// Smooth scroll events origins
|
||||
GK_ATOM(mouseWheel, "mouseWheel") // For discrete wheel events (e.g. not OSX magic mouse)
|
||||
GK_ATOM(pixels, "pixels")
|
||||
GK_ATOM(lines, "lines")
|
||||
GK_ATOM(pages, "pages")
|
||||
|
@ -314,42 +314,32 @@ nsImageLoadingContent::OnStopDecode(imgIRequest* aRequest,
|
||||
mCurrentRequestNeedsResetAnimation = false;
|
||||
}
|
||||
|
||||
// We just loaded all the data we're going to get. If we haven't done an
|
||||
// initial paint, we want to make sure the image starts decoding for 2
|
||||
// reasons:
|
||||
// We just loaded all the data we're going to get. If we're visible and
|
||||
// haven't done an initial paint (*), we want to make sure the image starts
|
||||
// decoding immediately, for two reasons:
|
||||
//
|
||||
// 1) This image is sitting idle but might need to be decoded as soon as we
|
||||
// start painting, in which case we've wasted time.
|
||||
//
|
||||
// 2) We want to block onload until all visible images are decoded. We do this
|
||||
// by blocking onload until all in progress decodes get at least one frame
|
||||
// by blocking onload until all in-progress decodes get at least one frame
|
||||
// decoded. However, if all the data comes in while painting is suppressed
|
||||
// (ie, before the initial paint delay is finished), we fire onload without
|
||||
// doing a paint first. This means that decode-on-draw images don't start
|
||||
// decoding, so we can't wait for them to finish. See bug 512435.
|
||||
//
|
||||
// (*) IsPaintingSuppressed returns false if we haven't gotten the initial
|
||||
// reflow yet, so we have to test !DidInitialReflow || IsPaintingSuppressed.
|
||||
// It's possible for painting to be suppressed for reasons other than the
|
||||
// initial paint delay (for example, being in the bfcache), but we probably
|
||||
// aren't loading images in those situations.
|
||||
|
||||
// We can only do this if we have a presshell
|
||||
nsIDocument* doc = GetOurDocument();
|
||||
nsIPresShell* shell = doc ? doc->GetShell() : nsnull;
|
||||
if (shell) {
|
||||
// We need to figure out whether to kick off decoding
|
||||
bool doRequestDecode = false;
|
||||
if (shell && shell->IsVisible() &&
|
||||
(!shell->DidInitialReflow() || shell->IsPaintingSuppressed())) {
|
||||
|
||||
// If we haven't got the initial reflow yet, IsPaintingSuppressed actually
|
||||
// returns false
|
||||
if (!shell->DidInitialReflow())
|
||||
doRequestDecode = true;
|
||||
|
||||
// Figure out if painting is suppressed. Note that it's possible for painting
|
||||
// to be suppressed for reasons other than the initial paint delay (for
|
||||
// example - being in the bfcache), but we probably aren't loading images in
|
||||
// those situations.
|
||||
if (shell->IsPaintingSuppressed())
|
||||
doRequestDecode = true;
|
||||
|
||||
// If we're requesting a decode, do it
|
||||
if (doRequestDecode)
|
||||
mCurrentRequest->RequestDecode();
|
||||
mCurrentRequest->RequestDecode();
|
||||
}
|
||||
|
||||
// Fire the appropriate DOM event.
|
||||
|
@ -2768,10 +2768,13 @@ nsXMLHttpRequest::Send(nsIVariant *aBody)
|
||||
// Create our listener
|
||||
nsCOMPtr<nsIStreamListener> listener = this;
|
||||
if (mState & XML_HTTP_REQUEST_MULTIPART) {
|
||||
Telemetry::Accumulate(Telemetry::MULTIPART_XHR_RESPONSE, 1);
|
||||
listener = new nsMultipartProxyListener(listener);
|
||||
if (!listener) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
} else {
|
||||
Telemetry::Accumulate(Telemetry::MULTIPART_XHR_RESPONSE, 0);
|
||||
}
|
||||
|
||||
// Blocking gets are common enough out of XHR that we should mark
|
||||
|
@ -572,6 +572,12 @@ _TEST_FILES2 = \
|
||||
test_bug737612.html \
|
||||
test_bug738108.html \
|
||||
test_bug366944.html \
|
||||
test_bug650386_redirect_301.html \
|
||||
test_bug650386_redirect_302.html \
|
||||
test_bug650386_redirect_303.html \
|
||||
test_bug650386_redirect_307.html \
|
||||
file_bug650386_content.sjs \
|
||||
file_bug650386_report.sjs \
|
||||
$(NULL)
|
||||
|
||||
_CHROME_FILES = \
|
||||
|
37
content/base/test/file_bug650386_content.sjs
Normal file
37
content/base/test/file_bug650386_content.sjs
Normal file
@ -0,0 +1,37 @@
|
||||
// SJS file for tests for bug650386, serves file_bug650386_content.html
|
||||
// with a CSP that will trigger a violation and that will report it
|
||||
// to file_bug650386_report.sjs
|
||||
//
|
||||
// This handles 301, 302, 303 and 307 redirects. The HTTP status code
|
||||
// returned/type of redirect to do comes from the query string
|
||||
// parameter passed in from the test_bug650386_* files and then also
|
||||
// uses that value in the report-uri parameter of the CSP
|
||||
function handleRequest(request, response) {
|
||||
response.setHeader("Cache-Control", "no-cache", false);
|
||||
|
||||
// this gets used in the CSP as part of the report URI.
|
||||
var redirect = request.queryString;
|
||||
|
||||
if (redirect < 301 || (redirect > 303 && redirect <= 306) || redirect > 307) {
|
||||
// if we somehow got some bogus redirect code here,
|
||||
// do a 302 redirect to the same URL as the report URI
|
||||
// redirects to - this will fail the test.
|
||||
var loc = "http://example.com/some/fake/path";
|
||||
response.setStatusLine("1.1", 302, "Found");
|
||||
response.setHeader("Location", loc, false);
|
||||
return;
|
||||
}
|
||||
|
||||
var csp = "default-src \'self\';report-uri http://mochi.test:8888/tests/content/base/test/file_bug650386_report.sjs?" + redirect;
|
||||
|
||||
response.setHeader("X-Content-Security-Policy", csp, false);
|
||||
|
||||
// the actual file content.
|
||||
// this image load will (intentionally) fail due to the CSP policy of default-src: 'self'
|
||||
// specified by the CSP string above.
|
||||
var content = "<!DOCTYPE HTML><html><body><img src = \"http://some.other.domain.example.com\"></body></html>";
|
||||
|
||||
response.write(content);
|
||||
|
||||
return;
|
||||
}
|
16
content/base/test/file_bug650386_report.sjs
Normal file
16
content/base/test/file_bug650386_report.sjs
Normal file
@ -0,0 +1,16 @@
|
||||
// SJS file for tests for bug650386, this serves as CSP violation report target
|
||||
// and issues a redirect, to make sure the browser does not post to the target
|
||||
// of the redirect, per CSP spec.
|
||||
// This handles 301, 302, 303 and 307 redirects. The HTTP status code
|
||||
// returned/type of redirect to do comes from the query string
|
||||
// parameter
|
||||
function handleRequest(request, response) {
|
||||
response.setHeader("Cache-Control", "no-cache", false);
|
||||
|
||||
var redirect = request.queryString;
|
||||
|
||||
var loc = "http://example.com/some/fake/path";
|
||||
response.setStatusLine("1.1", redirect, "Found");
|
||||
response.setHeader("Location", loc, false);
|
||||
return;
|
||||
}
|
78
content/base/test/test_bug650386_redirect_301.html
Normal file
78
content/base/test/test_bug650386_redirect_301.html
Normal file
@ -0,0 +1,78 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=650386
|
||||
Test that CSP violation reports are not sent when a 301 redirect is encountered
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 650386</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=650386">Mozilla Bug 650386</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
<iframe id = "content_iframe"></iframe>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 650386 **/
|
||||
|
||||
// This is used to watch the redirect of the report POST get blocked
|
||||
function examiner() {
|
||||
SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
|
||||
SpecialPowers.addObserver(this, "http-on-modify-request", false);
|
||||
}
|
||||
|
||||
examiner.prototype = {
|
||||
observe: function(subject, topic, data) {
|
||||
// subject should be an nsURI
|
||||
if(!SpecialPowers.can_QI(subject))
|
||||
return;
|
||||
|
||||
if (topic === "http-on-modify-request") {
|
||||
// this is used to fail the test - if we see the POST to the target of the redirect
|
||||
// we know this is a fail
|
||||
var asciiSpec = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIHttpChannel"), "URI.asciiSpec");
|
||||
|
||||
if (asciiSpec == "http://example.com/some/fake/path")
|
||||
window.done(false);
|
||||
}
|
||||
|
||||
if(topic === "csp-on-violate-policy") {
|
||||
// something was blocked, but we are looking specifically for the redirect being blocked
|
||||
if (data == "denied redirect while sending violation report")
|
||||
window.done(true);
|
||||
}
|
||||
},
|
||||
|
||||
// must eventually call this to remove the listener,
|
||||
// or mochitests might get borked.
|
||||
remove: function() {
|
||||
SpecialPowers.removeObserver(this, "csp-on-violate-policy");
|
||||
SpecialPowers.removeObserver(this, "http-on-modify-request");
|
||||
}
|
||||
}
|
||||
|
||||
window.examiner = new examiner();
|
||||
|
||||
// result == true if we saw the redirect blocked notify, false if we saw the post
|
||||
// to the redirect target go out
|
||||
window.done = function(result) {
|
||||
ok(result, "a 301 redirect when posting violation report should be blocked");
|
||||
|
||||
// clean up observers and finish the test
|
||||
window.examiner.remove();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// save this for last so that our listeners are registered.
|
||||
document.getElementById('content_iframe').src = 'file_bug650386_content.sjs?301';
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
78
content/base/test/test_bug650386_redirect_302.html
Normal file
78
content/base/test/test_bug650386_redirect_302.html
Normal file
@ -0,0 +1,78 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=650386
|
||||
Test that CSP violation reports are not sent when a 302 redirect is encountered
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 650386</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=650386">Mozilla Bug 650386</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
<iframe id = "content_iframe"></iframe>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 650386 **/
|
||||
|
||||
// This is used to watch the redirect of the report POST get blocked
|
||||
function examiner() {
|
||||
SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
|
||||
SpecialPowers.addObserver(this, "http-on-modify-request", false);
|
||||
}
|
||||
|
||||
examiner.prototype = {
|
||||
observe: function(subject, topic, data) {
|
||||
// subject should be an nsURI
|
||||
if(!SpecialPowers.can_QI(subject))
|
||||
return;
|
||||
|
||||
if (topic === "http-on-modify-request") {
|
||||
// this is used to fail the test - if we see the POST to the target of the redirect
|
||||
// we know this is a fail
|
||||
var asciiSpec = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIHttpChannel"), "URI.asciiSpec");
|
||||
|
||||
if (asciiSpec == "http://example.com/some/fake/path")
|
||||
window.done(false);
|
||||
}
|
||||
|
||||
if(topic === "csp-on-violate-policy") {
|
||||
// something was blocked, but we are looking specifically for the redirect being blocked
|
||||
if (data == "denied redirect while sending violation report")
|
||||
window.done(true);
|
||||
}
|
||||
},
|
||||
|
||||
// must eventually call this to remove the listener,
|
||||
// or mochitests might get borked.
|
||||
remove: function() {
|
||||
SpecialPowers.removeObserver(this, "csp-on-violate-policy");
|
||||
SpecialPowers.removeObserver(this, "http-on-modify-request");
|
||||
}
|
||||
}
|
||||
|
||||
window.examiner = new examiner();
|
||||
|
||||
// result == true if we saw the redirect blocked notify, false if we saw the post
|
||||
// to the redirect target go out
|
||||
window.done = function(result) {
|
||||
ok(result, "a 302 redirect when posting violation report should be blocked");
|
||||
|
||||
// clean up observers and finish the test
|
||||
window.examiner.remove();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// save this for last so that our listeners are registered.
|
||||
document.getElementById('content_iframe').src = 'file_bug650386_content.sjs?302';
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
78
content/base/test/test_bug650386_redirect_303.html
Normal file
78
content/base/test/test_bug650386_redirect_303.html
Normal file
@ -0,0 +1,78 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=650386
|
||||
Test that CSP violation reports are not sent when a 303 redirect is encountered
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 650386</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=650386">Mozilla Bug 650386</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
<iframe id = "content_iframe"></iframe>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 650386 **/
|
||||
|
||||
// This is used to watch the redirect of the report POST get blocked
|
||||
function examiner() {
|
||||
SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
|
||||
SpecialPowers.addObserver(this, "http-on-modify-request", false);
|
||||
}
|
||||
|
||||
examiner.prototype = {
|
||||
observe: function(subject, topic, data) {
|
||||
// subject should be an nsURI
|
||||
if(!SpecialPowers.can_QI(subject))
|
||||
return;
|
||||
|
||||
if (topic === "http-on-modify-request") {
|
||||
// this is used to fail the test - if we see the POST to the target of the redirect
|
||||
// we know this is a fail
|
||||
var asciiSpec = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIHttpChannel"), "URI.asciiSpec");
|
||||
|
||||
if (asciiSpec == "http://example.com/some/fake/path")
|
||||
window.done(false);
|
||||
}
|
||||
|
||||
if(topic === "csp-on-violate-policy") {
|
||||
// something was blocked, but we are looking specifically for the redirect being blocked
|
||||
if (data == "denied redirect while sending violation report")
|
||||
window.done(true);
|
||||
}
|
||||
},
|
||||
|
||||
// must eventually call this to remove the listener,
|
||||
// or mochitests might get borked.
|
||||
remove: function() {
|
||||
SpecialPowers.removeObserver(this, "csp-on-violate-policy");
|
||||
SpecialPowers.removeObserver(this, "http-on-modify-request");
|
||||
}
|
||||
}
|
||||
|
||||
window.examiner = new examiner();
|
||||
|
||||
// result == true if we saw the redirect blocked notify, false if we saw the post
|
||||
// to the redirect target go out
|
||||
window.done = function(result) {
|
||||
ok(result, "a 303 redirect when posting violation report should be blocked");
|
||||
|
||||
// clean up observers and finish the test
|
||||
window.examiner.remove();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// save this for last so that our listeners are registered.
|
||||
document.getElementById('content_iframe').src = 'file_bug650386_content.sjs?303';
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
78
content/base/test/test_bug650386_redirect_307.html
Normal file
78
content/base/test/test_bug650386_redirect_307.html
Normal file
@ -0,0 +1,78 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=650386
|
||||
Test that CSP violation reports are not sent when a 307 redirect is encountered
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 650386</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=650386">Mozilla Bug 650386</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
<iframe id = "content_iframe"></iframe>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 650386 **/
|
||||
|
||||
// This is used to watch the redirect of the report POST get blocked
|
||||
function examiner() {
|
||||
SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
|
||||
SpecialPowers.addObserver(this, "http-on-modify-request", false);
|
||||
}
|
||||
|
||||
examiner.prototype = {
|
||||
observe: function(subject, topic, data) {
|
||||
// subject should be an nsURI
|
||||
if(!SpecialPowers.can_QI(subject))
|
||||
return;
|
||||
|
||||
if (topic === "http-on-modify-request") {
|
||||
// this is used to fail the test - if we see the POST to the target of the redirect
|
||||
// we know this is a fail
|
||||
var asciiSpec = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIHttpChannel"), "URI.asciiSpec");
|
||||
|
||||
if (asciiSpec == "http://example.com/some/fake/path")
|
||||
window.done(false);
|
||||
}
|
||||
|
||||
if(topic === "csp-on-violate-policy") {
|
||||
// something was blocked, but we are looking specifically for the redirect being blocked
|
||||
if (data == "denied redirect while sending violation report")
|
||||
window.done(true);
|
||||
}
|
||||
},
|
||||
|
||||
// must eventually call this to remove the listener,
|
||||
// or mochitests might get borked.
|
||||
remove: function() {
|
||||
SpecialPowers.removeObserver(this, "csp-on-violate-policy");
|
||||
SpecialPowers.removeObserver(this, "http-on-modify-request");
|
||||
}
|
||||
}
|
||||
|
||||
window.examiner = new examiner();
|
||||
|
||||
// result == true if we saw the redirect blocked notify, false if we saw the post
|
||||
// to the redirect target go out
|
||||
window.done = function(result) {
|
||||
ok(result, "a 307 redirect when posting violation report should be blocked");
|
||||
|
||||
// clean up observers and finish the test
|
||||
window.examiner.remove();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// save this for last so that our listeners are registered.
|
||||
document.getElementById('content_iframe').src = 'file_bug650386_content.sjs?307';
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -2695,7 +2695,8 @@ nsEventStateManager::DoScrollText(nsIFrame* aTargetFrame,
|
||||
nsMouseScrollEvent* aMouseEvent,
|
||||
nsIScrollableFrame::ScrollUnit aScrollQuantity,
|
||||
bool aAllowScrollSpeedOverride,
|
||||
nsQueryContentEvent* aQueryEvent)
|
||||
nsQueryContentEvent* aQueryEvent,
|
||||
nsIAtom *aOrigin)
|
||||
{
|
||||
nsIScrollableFrame* frameToScroll = nsnull;
|
||||
nsIFrame* scrollFrame = aTargetFrame;
|
||||
@ -2857,7 +2858,7 @@ nsEventStateManager::DoScrollText(nsIFrame* aTargetFrame,
|
||||
|
||||
nsIntPoint overflow;
|
||||
frameToScroll->ScrollBy(nsIntPoint(scrollX, scrollY), aScrollQuantity,
|
||||
mode, &overflow);
|
||||
mode, &overflow, aOrigin);
|
||||
aMouseEvent->scrollOverflow = isHorizontal ? overflow.x : overflow.y;
|
||||
return NS_OK;
|
||||
}
|
||||
@ -2867,7 +2868,7 @@ nsEventStateManager::DoScrollText(nsIFrame* aTargetFrame,
|
||||
aTargetFrame->PresContext()->FrameManager()->GetRootFrame());
|
||||
if (newFrame)
|
||||
return DoScrollText(newFrame, aMouseEvent, aScrollQuantity,
|
||||
aAllowScrollSpeedOverride, aQueryEvent);
|
||||
aAllowScrollSpeedOverride, aQueryEvent, aOrigin);
|
||||
}
|
||||
|
||||
aMouseEvent->scrollOverflow = numLines;
|
||||
@ -3213,7 +3214,7 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext,
|
||||
switch (action) {
|
||||
case MOUSE_SCROLL_N_LINES:
|
||||
DoScrollText(aTargetFrame, msEvent, nsIScrollableFrame::LINES,
|
||||
useSysNumLines);
|
||||
useSysNumLines, nsnull, nsGkAtoms::mouseWheel);
|
||||
break;
|
||||
|
||||
case MOUSE_SCROLL_PAGE:
|
||||
@ -3222,8 +3223,11 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext,
|
||||
break;
|
||||
|
||||
case MOUSE_SCROLL_PIXELS:
|
||||
DoScrollText(aTargetFrame, msEvent, nsIScrollableFrame::DEVICE_PIXELS,
|
||||
false);
|
||||
{
|
||||
bool fromLines = msEvent->scrollFlags & nsMouseScrollEvent::kFromLines;
|
||||
DoScrollText(aTargetFrame, msEvent, nsIScrollableFrame::DEVICE_PIXELS,
|
||||
false, nsnull, (fromLines ? nsGkAtoms::mouseWheel : nsnull));
|
||||
}
|
||||
break;
|
||||
|
||||
case MOUSE_SCROLL_HISTORY:
|
||||
|
@ -353,7 +353,8 @@ protected:
|
||||
nsMouseScrollEvent* aMouseEvent,
|
||||
nsIScrollableFrame::ScrollUnit aScrollQuantity,
|
||||
bool aAllowScrollSpeedOverride,
|
||||
nsQueryContentEvent* aQueryEvent = nsnull);
|
||||
nsQueryContentEvent* aQueryEvent = nsnull,
|
||||
nsIAtom *aOrigin = nsnull);
|
||||
void DoScrollHistory(PRInt32 direction);
|
||||
void DoScrollZoom(nsIFrame *aTargetFrame, PRInt32 adjustment);
|
||||
nsresult GetMarkupDocumentViewer(nsIMarkupDocumentViewer** aMv);
|
||||
|
@ -134,6 +134,7 @@
|
||||
#include "nsMimeTypes.h"
|
||||
#include "nsIRequest.h"
|
||||
#include "nsHtml5TreeOpExecutor.h"
|
||||
#include "nsHtml5Parser.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
@ -1558,6 +1559,7 @@ nsHTMLDocument::Open(const nsAString& aContentTypeOrUrl,
|
||||
// resetting the document.
|
||||
mSecurityInfo = securityInfo;
|
||||
|
||||
mParserAborted = false;
|
||||
bool loadAsHtml5 = nsHtml5Module::sEnabled;
|
||||
if (loadAsHtml5) {
|
||||
mParser = nsHtml5Module::NewHtml5Parser();
|
||||
@ -1644,8 +1646,8 @@ nsHTMLDocument::Close()
|
||||
}
|
||||
|
||||
++mWriteLevel;
|
||||
nsresult rv = mParser->Parse(EmptyString(), nsnull,
|
||||
GetContentTypeInternal(), true);
|
||||
nsresult rv = (static_cast<nsHtml5Parser*>(mParser.get()))->Parse(
|
||||
EmptyString(), nsnull, GetContentTypeInternal(), true);
|
||||
--mWriteLevel;
|
||||
|
||||
// XXX Make sure that all the document.written content is
|
||||
@ -1701,6 +1703,13 @@ nsHTMLDocument::WriteCommon(JSContext *cx,
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
if (mParserAborted) {
|
||||
// Hixie says aborting the parser doesn't undefine the insertion point.
|
||||
// However, since we null out mParser in that case, we track the
|
||||
// theoretically defined insertion point using mParserAborted.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
void *key = GenerateParserKey();
|
||||
@ -1764,13 +1773,11 @@ nsHTMLDocument::WriteCommon(JSContext *cx,
|
||||
// since the concatenation of strings costs more than we like. And
|
||||
// why pay that price when we don't need to?
|
||||
if (aNewlineTerminate) {
|
||||
rv = mParser->Parse(aText + new_line,
|
||||
key, GetContentTypeInternal(),
|
||||
false);
|
||||
rv = (static_cast<nsHtml5Parser*>(mParser.get()))->Parse(
|
||||
aText + new_line, key, GetContentTypeInternal(), false);
|
||||
} else {
|
||||
rv = mParser->Parse(aText,
|
||||
key, GetContentTypeInternal(),
|
||||
false);
|
||||
rv = (static_cast<nsHtml5Parser*>(mParser.get()))->Parse(
|
||||
aText, key, GetContentTypeInternal(), false);
|
||||
}
|
||||
|
||||
--mWriteLevel;
|
||||
|
@ -8348,13 +8348,6 @@ nsDocShell::InternalLoad(nsIURI * aURI,
|
||||
sameExceptHashes && !newHash.IsEmpty());
|
||||
|
||||
if (doShortCircuitedLoad) {
|
||||
// If our load group contains a LOAD_DOCUMENT_URI request with a
|
||||
// channel which doesn't match our document's channel, cancel it.
|
||||
//
|
||||
// That is, a short-circuited load will cancel a non-short-circuited
|
||||
// load of a different document.
|
||||
StopOutstandingOtherDocumentLoad();
|
||||
|
||||
// Save the current URI; we need it if we fire a hashchange later.
|
||||
nsCOMPtr<nsIURI> oldURI = mCurrentURI;
|
||||
|
||||
@ -8654,47 +8647,6 @@ nsDocShell::InternalLoad(nsIURI * aURI,
|
||||
return rv;
|
||||
}
|
||||
|
||||
// If our load group contains a LOAD_DOCUMENT_URI channel that's not our
|
||||
// document's channel, cancel it.
|
||||
void
|
||||
nsDocShell::StopOutstandingOtherDocumentLoad()
|
||||
{
|
||||
nsCOMPtr<nsIChannel> docChannel = GetCurrentDocChannel();
|
||||
if (!docChannel || !mLoadGroup) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> requests;
|
||||
mLoadGroup->GetRequests(getter_AddRefs(requests));
|
||||
if (!requests) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
bool hasMoreElements = false;
|
||||
requests->HasMoreElements(&hasMoreElements);
|
||||
if (!hasMoreElements) {
|
||||
break;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISupports> next;
|
||||
requests->GetNext(getter_AddRefs(next));
|
||||
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(next);
|
||||
if (!channel) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsLoadFlags flags;
|
||||
channel->GetLoadFlags(&flags);
|
||||
|
||||
// As promised, cancel the channel if it's loading a different document.
|
||||
if ((flags & nsIChannel::LOAD_DOCUMENT_URI) && channel != docChannel) {
|
||||
channel->Cancel(NS_BINDING_ABORTED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsIPrincipal*
|
||||
nsDocShell::GetInheritedPrincipal(bool aConsiderCurrentDocument)
|
||||
{
|
||||
|
@ -672,11 +672,6 @@ protected:
|
||||
nsresult EnsureCommandHandler();
|
||||
|
||||
nsIChannel* GetCurrentDocChannel();
|
||||
|
||||
// If our load group contains a LOAD_DOCUMENT_URI channel that's not our
|
||||
// document's channel, cancel it.
|
||||
void StopOutstandingOtherDocumentLoad();
|
||||
|
||||
protected:
|
||||
// Override the parent setter from nsDocLoader
|
||||
virtual nsresult SetDocLoaderParent(nsDocLoader * aLoader);
|
||||
|
@ -1153,7 +1153,7 @@ Navigator::GetMozBluetooth(nsIDOMBluetoothAdapter** aBluetooth)
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
|
||||
NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
|
||||
|
||||
mBluetooth = new bluetooth::BluetoothAdapter();
|
||||
mBluetooth = new bluetooth::BluetoothAdapter(window);
|
||||
|
||||
bluetooth = mBluetooth;
|
||||
}
|
||||
|
@ -85,6 +85,7 @@ nsStructuredCloneContainer::InitFromVariant(nsIVariant *aData, JSContext *aCx)
|
||||
JSAutoRequest ar(aCx);
|
||||
JSAutoEnterCompartment ac;
|
||||
NS_ENSURE_STATE(ac.enter(aCx, JS_GetGlobalObject(aCx)));
|
||||
JS_WrapValue(aCx, &jsData);
|
||||
|
||||
nsCxPusher cxPusher;
|
||||
cxPusher.Push(aCx);
|
||||
|
@ -4,13 +4,33 @@
|
||||
* 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 "BluetoothAdapter.h"
|
||||
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "nsDOMEvent.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsXPCOMCIDInternal.h"
|
||||
#include "mozilla/LazyIdleThread.h"
|
||||
#include "mozilla/Util.h"
|
||||
#include <dlfcn.h>
|
||||
#include "BluetoothAdapter.h"
|
||||
|
||||
static void
|
||||
FireEnabled(bool aResult, nsIDOMDOMRequest* aDomRequest)
|
||||
{
|
||||
nsCOMPtr<nsIDOMRequestService> rs = do_GetService("@mozilla.org/dom/dom-request-service;1");
|
||||
|
||||
if (!rs) {
|
||||
NS_WARNING("No DOMRequest Service!");
|
||||
return;
|
||||
}
|
||||
|
||||
mozilla::DebugOnly<nsresult> rv = aResult ?
|
||||
rs->FireSuccess(aDomRequest, JSVAL_VOID) :
|
||||
rs->FireError(aDomRequest,
|
||||
NS_LITERAL_STRING("Bluetooth firmware loading failed"));
|
||||
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Bluetooth firmware loading failed");
|
||||
}
|
||||
|
||||
USING_BLUETOOTH_NAMESPACE
|
||||
|
||||
@ -67,11 +87,16 @@ static bool EnsureBluetoothInit() {
|
||||
class ToggleBtResultTask : public nsRunnable
|
||||
{
|
||||
public:
|
||||
ToggleBtResultTask(nsRefPtr<BluetoothAdapter>& adapterPtr, bool result)
|
||||
: mResult(result)
|
||||
ToggleBtResultTask(nsRefPtr<BluetoothAdapter>& adapterPtr,
|
||||
nsCOMPtr<nsIDOMDOMRequest>& req,
|
||||
bool enabled,
|
||||
bool result)
|
||||
: mResult(result),
|
||||
mEnabled(enabled)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
mDOMRequest.swap(req);
|
||||
mAdapterPtr.swap(adapterPtr);
|
||||
}
|
||||
|
||||
@ -79,29 +104,35 @@ class ToggleBtResultTask : public nsRunnable
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!mResult) {
|
||||
//TODO:Bug-731361
|
||||
NS_WARNING("BT firmware loading fails.\n");
|
||||
// Update bt power status to BluetoothAdapter only if loading bluetooth
|
||||
// firmware succeeds.
|
||||
if (mResult) {
|
||||
mAdapterPtr->SetEnabledInternal(mEnabled);
|
||||
}
|
||||
|
||||
|
||||
FireEnabled(mResult, mDOMRequest);
|
||||
|
||||
//mAdapterPtr must be null before returning to prevent the background
|
||||
//thread from racing to release it during the destruction of this runnable.
|
||||
mAdapterPtr->FirePowered();
|
||||
mAdapterPtr = nsnull;
|
||||
mDOMRequest = nsnull;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<BluetoothAdapter> mAdapterPtr;
|
||||
nsCOMPtr<nsIDOMDOMRequest> mDOMRequest;
|
||||
bool mEnabled;
|
||||
bool mResult;
|
||||
};
|
||||
|
||||
class ToggleBtTask : public nsRunnable
|
||||
{
|
||||
public:
|
||||
ToggleBtTask(bool onOff, BluetoothAdapter* adapterPtr)
|
||||
: mOnOff(onOff),
|
||||
ToggleBtTask(bool enabled, nsIDOMDOMRequest* req, BluetoothAdapter* adapterPtr)
|
||||
: mEnabled(enabled),
|
||||
mDOMRequest(req),
|
||||
mAdapterPtr(adapterPtr)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
@ -111,23 +142,36 @@ class ToggleBtTask : public nsRunnable
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
bool result;
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
// Platform specific check for gonk until object is divided in
|
||||
// different implementations per platform. Linux doesn't require
|
||||
// bluetooth firmware loading, but code should work otherwise.
|
||||
if(!EnsureBluetoothInit()) {
|
||||
NS_ERROR("Failed to load bluedroid library.\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
bool result;
|
||||
// return 1 if it's enabled, 0 if it's disabled, and -1 on error
|
||||
int isEnabled = sBluedroidFunctions.bt_is_enabled();
|
||||
|
||||
//Toggle BT here
|
||||
|
||||
if (mOnOff) {
|
||||
result = sBluedroidFunctions.bt_enable();
|
||||
if ((isEnabled == 1 && mEnabled) || (isEnabled == 0 && !mEnabled)) {
|
||||
result = true;
|
||||
} else if (isEnabled < 0) {
|
||||
result = false;
|
||||
} else if (mEnabled) {
|
||||
result = (sBluedroidFunctions.bt_enable() == 0) ? true : false;
|
||||
} else {
|
||||
result = sBluedroidFunctions.bt_disable();
|
||||
result = (sBluedroidFunctions.bt_disable() == 0) ? true : false;
|
||||
}
|
||||
#else
|
||||
result = true;
|
||||
NS_WARNING("No bluetooth support in this build configuration, faking a success event instead");
|
||||
#endif
|
||||
|
||||
// Create a result thread and pass it to Main Thread,
|
||||
nsCOMPtr<nsIRunnable> resultRunnable = new ToggleBtResultTask(mAdapterPtr, result);
|
||||
nsCOMPtr<nsIRunnable> resultRunnable = new ToggleBtResultTask(mAdapterPtr, mDOMRequest, mEnabled, result);
|
||||
|
||||
if (NS_FAILED(NS_DispatchToMainThread(resultRunnable))) {
|
||||
NS_WARNING("Failed to dispatch to main thread!");
|
||||
@ -137,8 +181,9 @@ class ToggleBtTask : public nsRunnable
|
||||
}
|
||||
|
||||
private:
|
||||
bool mOnOff;
|
||||
bool mEnabled;
|
||||
nsRefPtr<BluetoothAdapter> mAdapterPtr;
|
||||
nsCOMPtr<nsIDOMDOMRequest> mDOMRequest;
|
||||
};
|
||||
|
||||
DOMCI_DATA(BluetoothAdapter, BluetoothAdapter)
|
||||
@ -147,12 +192,12 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothAdapter)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothAdapter,
|
||||
nsDOMEventTargetHelper)
|
||||
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(powered)
|
||||
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(enabled)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothAdapter,
|
||||
nsDOMEventTargetHelper)
|
||||
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(powered)
|
||||
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(enabled)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BluetoothAdapter)
|
||||
@ -163,77 +208,43 @@ NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
|
||||
NS_IMPL_ADDREF_INHERITED(BluetoothAdapter, nsDOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(BluetoothAdapter, nsDOMEventTargetHelper)
|
||||
|
||||
BluetoothAdapter::BluetoothAdapter()
|
||||
: mPower(false)
|
||||
BluetoothAdapter::BluetoothAdapter(nsPIDOMWindow *aWindow)
|
||||
{
|
||||
BindToOwner(aWindow);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BluetoothAdapter::GetPower(bool* aPower)
|
||||
BluetoothAdapter::SetEnabled(bool aEnabled, nsIDOMDOMRequest** aDomRequest)
|
||||
{
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
if(!EnsureBluetoothInit()) {
|
||||
NS_ERROR("Failed to load bluedroid library.\n");
|
||||
nsCOMPtr<nsIDOMRequestService> rs = do_GetService("@mozilla.org/dom/dom-request-service;1");
|
||||
|
||||
if (!rs) {
|
||||
NS_ERROR("No DOMRequest Service!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
*aPower = sBluedroidFunctions.bt_is_enabled();
|
||||
#else
|
||||
*aPower = mPower;
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BluetoothAdapter::SetPower(bool aPower)
|
||||
{
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
// Platform specific check for gonk until object is divided in
|
||||
// different implementations per platform. Linux doesn't require
|
||||
// bluetooth firmware loading, but code should work otherwise.
|
||||
if(!EnsureBluetoothInit()) {
|
||||
NS_ERROR("Failed to load bluedroid library.\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
#endif
|
||||
if (mPower != aPower) {
|
||||
mPower = aPower;
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
return ToggleBluetoothAsync();
|
||||
#endif
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothAdapter::ToggleBluetoothAsync()
|
||||
{
|
||||
nsCOMPtr<nsIDOMDOMRequest> request;
|
||||
nsresult rv = rs->CreateRequest(GetOwner(), getter_AddRefs(request));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!mToggleBtThread) {
|
||||
mToggleBtThread = new LazyIdleThread(15000);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRunnable> r = new ToggleBtTask(mPower, this);
|
||||
nsCOMPtr<nsIRunnable> r = new ToggleBtTask(aEnabled, request, this);
|
||||
|
||||
return mToggleBtThread->Dispatch(r, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothAdapter::FirePowered()
|
||||
{
|
||||
nsRefPtr<nsDOMEvent> event = new nsDOMEvent(nsnull, nsnull);
|
||||
nsresult rv = event->InitEvent(NS_LITERAL_STRING("powered"), false, false);
|
||||
rv = mToggleBtThread->Dispatch(r, NS_DISPATCH_NORMAL);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = event->SetTrusted(true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool dummy;
|
||||
rv = DispatchEvent(event, &dummy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
request.forget(aDomRequest);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_EVENT_HANDLER(BluetoothAdapter, powered)
|
||||
NS_IMETHODIMP
|
||||
BluetoothAdapter::GetEnabled(bool* aEnabled)
|
||||
{
|
||||
*aEnabled = mEnabled;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "BluetoothCommon.h"
|
||||
#include "nsDOMEventTargetHelper.h"
|
||||
#include "nsIDOMBluetoothAdapter.h"
|
||||
#include "nsIDOMDOMRequest.h"
|
||||
|
||||
class nsIEventTarget;
|
||||
|
||||
@ -27,19 +28,19 @@ public:
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(BluetoothAdapter,
|
||||
nsDOMEventTargetHelper)
|
||||
|
||||
BluetoothAdapter();
|
||||
BluetoothAdapter(nsPIDOMWindow*);
|
||||
|
||||
nsresult FirePowered();
|
||||
inline void SetEnabledInternal(bool aEnabled) {mEnabled = aEnabled;}
|
||||
|
||||
protected:
|
||||
bool mPower;
|
||||
bool mEnabled;
|
||||
|
||||
NS_DECL_EVENT_HANDLER(powered)
|
||||
NS_DECL_EVENT_HANDLER(enabled)
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIEventTarget> mToggleBtThread;
|
||||
nsresult ToggleBluetoothAsync();
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
@ -6,12 +6,13 @@
|
||||
|
||||
#include "nsIDOMEventTarget.idl"
|
||||
|
||||
interface nsIDOMDOMRequest;
|
||||
interface nsIDOMEventListener;
|
||||
|
||||
[scriptable, builtinclass, uuid(3dbaa9f4-5c93-11e1-8592-ff9bfcc3ab4b)]
|
||||
[scriptable, builtinclass, uuid(ac288eab-dcdb-4f6a-b94d-6c0e286d6a73)]
|
||||
interface nsIDOMBluetoothAdapter : nsIDOMEventTarget
|
||||
{
|
||||
attribute boolean power;
|
||||
readonly attribute bool enabled;
|
||||
|
||||
attribute nsIDOMEventListener onpowered;
|
||||
nsIDOMDOMRequest setEnabled(in boolean enabled);
|
||||
};
|
||||
|
@ -344,6 +344,13 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(IDBKeyRange)
|
||||
|
||||
DOMCI_DATA(IDBKeyRange, IDBKeyRange)
|
||||
|
||||
IDBKeyRange::~IDBKeyRange()
|
||||
{
|
||||
if (mRooted) {
|
||||
NS_DROP_JS_OBJECTS(this, IDBKeyRange);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
IDBKeyRange::GetLower(JSContext* aCx,
|
||||
jsval* aLower)
|
||||
|
@ -170,7 +170,7 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
~IDBKeyRange() { }
|
||||
~IDBKeyRange();
|
||||
|
||||
Key mLower;
|
||||
Key mUpper;
|
||||
|
@ -1318,8 +1318,6 @@ nsDOMStorage::nsDOMStorage()
|
||||
: mStorageType(nsPIDOMStorage::Unknown)
|
||||
, mEventBroadcaster(nsnull)
|
||||
{
|
||||
mSecurityChecker = this;
|
||||
|
||||
if (XRE_GetProcessType() != GeckoProcessType_Default)
|
||||
mStorageImpl = new StorageChild(this);
|
||||
else
|
||||
@ -1328,10 +1326,9 @@ nsDOMStorage::nsDOMStorage()
|
||||
|
||||
nsDOMStorage::nsDOMStorage(nsDOMStorage& aThat)
|
||||
: mStorageType(aThat.mStorageType)
|
||||
, mPrincipal(aThat.mPrincipal)
|
||||
, mEventBroadcaster(nsnull)
|
||||
{
|
||||
mSecurityChecker = this;
|
||||
|
||||
if (XRE_GetProcessType() != GeckoProcessType_Default) {
|
||||
StorageChild* other = static_cast<StorageChild*>(aThat.mStorageImpl.get());
|
||||
mStorageImpl = new StorageChild(this, *other);
|
||||
@ -1382,6 +1379,7 @@ nsDOMStorage::InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring &
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mDocumentURI = aDocumentURI;
|
||||
mPrincipal = aPrincipal;
|
||||
|
||||
mStorageType = SessionStorage;
|
||||
|
||||
@ -1397,6 +1395,7 @@ nsDOMStorage::InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aD
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mDocumentURI = aDocumentURI;
|
||||
mPrincipal = aPrincipal;
|
||||
|
||||
mStorageType = LocalStorage;
|
||||
|
||||
@ -1495,8 +1494,7 @@ nsDOMStorage::CacheStoragePermissions()
|
||||
nsresult rv = ssm->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
NS_ASSERTION(mSecurityChecker, "Has non-null mSecurityChecker");
|
||||
return mSecurityChecker->CanAccess(subjectPrincipal);
|
||||
return CanAccess(subjectPrincipal);
|
||||
}
|
||||
|
||||
// static
|
||||
@ -1729,17 +1727,17 @@ nsDOMStorage::CanAccessSystem(nsIPrincipal *aPrincipal)
|
||||
bool
|
||||
nsDOMStorage::CanAccess(nsIPrincipal *aPrincipal)
|
||||
{
|
||||
// Allow C++/system callers to access the storage
|
||||
if (CanAccessSystem(aPrincipal))
|
||||
// Allow C++ callers to access the storage
|
||||
if (!aPrincipal)
|
||||
return true;
|
||||
|
||||
nsCAutoString domain;
|
||||
nsCOMPtr<nsIURI> unused;
|
||||
nsresult rv = GetPrincipalURIAndHost(aPrincipal,
|
||||
getter_AddRefs(unused), domain);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
// Allow more powerful principals (e.g. system) to access the storage
|
||||
bool subsumes;
|
||||
nsresult rv = aPrincipal->SubsumesIgnoringDomain(mPrincipal, &subsumes);
|
||||
if (NS_FAILED(rv))
|
||||
return false;
|
||||
|
||||
return domain.Equals(mStorageImpl->mDomain);
|
||||
return subsumes;
|
||||
}
|
||||
|
||||
nsPIDOMStorage::nsDOMStorageType
|
||||
@ -1797,7 +1795,6 @@ nsDOMStorage2::nsDOMStorage2()
|
||||
nsDOMStorage2::nsDOMStorage2(nsDOMStorage2& aThat)
|
||||
{
|
||||
mStorage = new nsDOMStorage(*aThat.mStorage.get());
|
||||
mStorage->mSecurityChecker = mStorage;
|
||||
mPrincipal = aThat.mPrincipal;
|
||||
}
|
||||
|
||||
@ -1808,7 +1805,6 @@ nsDOMStorage2::InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring
|
||||
if (!mStorage)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
mStorage->mSecurityChecker = this;
|
||||
mPrincipal = aPrincipal;
|
||||
mDocumentURI = aDocumentURI;
|
||||
|
||||
@ -1822,7 +1818,6 @@ nsDOMStorage2::InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &a
|
||||
if (!mStorage)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
mStorage->mSecurityChecker = this;
|
||||
mPrincipal = aPrincipal;
|
||||
mDocumentURI = aDocumentURI;
|
||||
|
||||
@ -1892,20 +1887,7 @@ nsDOMStorage2::Principal()
|
||||
bool
|
||||
nsDOMStorage2::CanAccess(nsIPrincipal *aPrincipal)
|
||||
{
|
||||
if (mStorage->mSecurityChecker != this)
|
||||
return mStorage->mSecurityChecker->CanAccess(aPrincipal);
|
||||
|
||||
// Allow C++ callers to access the storage
|
||||
if (!aPrincipal)
|
||||
return true;
|
||||
|
||||
// Allow more powerful principals (e.g. system) to access the storage
|
||||
bool subsumes;
|
||||
nsresult rv = aPrincipal->SubsumesIgnoringDomain(mPrincipal, &subsumes);
|
||||
if (NS_FAILED(rv))
|
||||
return false;
|
||||
|
||||
return subsumes;
|
||||
return mStorage->CanAccess(aPrincipal);
|
||||
}
|
||||
|
||||
nsPIDOMStorage::nsDOMStorageType
|
||||
|
@ -419,7 +419,7 @@ public:
|
||||
nsDOMStorageType mStorageType;
|
||||
|
||||
friend class nsIDOMStorage2;
|
||||
nsPIDOMStorage* mSecurityChecker;
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
nsPIDOMStorage* mEventBroadcaster;
|
||||
};
|
||||
|
||||
|
@ -8,7 +8,7 @@ function runAJAXTest() {
|
||||
|
||||
var test = AJAXtests.shift();
|
||||
var testframe = document.getElementById("testframe");
|
||||
setTimeout(function() { testframe.src = test; }, 0);
|
||||
testframe.src = test;
|
||||
}
|
||||
|
||||
function onManifestLoad(manifest) {
|
||||
|
@ -69,7 +69,7 @@ DECL_EVENTTARGET_CLASS(gMainThreadClass, "WorkerEventTarget")
|
||||
|
||||
inline
|
||||
bool
|
||||
EnsureObjectIsEventTarget(JSContext* aCx, JSObject* aObj, char* aFunctionName)
|
||||
EnsureObjectIsEventTarget(JSContext* aCx, JSObject* aObj, const char* aFunctionName)
|
||||
{
|
||||
JSClass* classPtr = JS_GetClass(aObj);
|
||||
if (ClassIsWorker(classPtr) || ClassIsWorkerGlobalScope(classPtr) ||
|
||||
|
@ -3164,6 +3164,8 @@ WorkerPrivate::NotifyFeatures(JSContext* aCx, Status aStatus)
|
||||
void
|
||||
WorkerPrivate::CancelAllTimeouts(JSContext* aCx)
|
||||
{
|
||||
AssertIsOnWorkerThread();
|
||||
|
||||
if (mTimerRunning) {
|
||||
NS_ASSERTION(mTimer, "Huh?!");
|
||||
NS_ASSERTION(!mTimeouts.IsEmpty(), "Huh?!");
|
||||
@ -3176,13 +3178,19 @@ WorkerPrivate::CancelAllTimeouts(JSContext* aCx)
|
||||
mTimeouts[index]->mCanceled = true;
|
||||
}
|
||||
|
||||
RunExpiredTimeouts(aCx);
|
||||
if (!RunExpiredTimeouts(aCx)) {
|
||||
JS_ReportPendingException(aCx);
|
||||
}
|
||||
|
||||
mTimer = nsnull;
|
||||
mTimerRunning = false;
|
||||
}
|
||||
else {
|
||||
#ifdef DEBUG
|
||||
else if (!mRunningExpiredTimeouts) {
|
||||
NS_ASSERTION(mTimeouts.IsEmpty(), "Huh?!");
|
||||
}
|
||||
#endif
|
||||
|
||||
mTimer = nsnull;
|
||||
}
|
||||
|
||||
PRUint32
|
||||
@ -3511,8 +3519,15 @@ WorkerPrivate::SetTimeout(JSContext* aCx, unsigned aArgc, jsval* aVp,
|
||||
currentStatus = mStatus;
|
||||
}
|
||||
|
||||
if (currentStatus > Running) {
|
||||
// It's a script bug if setTimeout/setInterval are called from a close handler
|
||||
// so throw an exception.
|
||||
if (currentStatus == Closing) {
|
||||
JS_ReportError(aCx, "Cannot schedule timeouts from the close handler!");
|
||||
}
|
||||
|
||||
// If the worker is trying to call setTimeout/setInterval and the parent
|
||||
// thread has initiated the close process then just silently fail.
|
||||
if (currentStatus >= Closing) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -3655,6 +3670,7 @@ WorkerPrivate::RunExpiredTimeouts(JSContext* aCx)
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_ASSERTION(mTimer, "Must have a timer!");
|
||||
NS_ASSERTION(!mTimeouts.IsEmpty(), "Should have some work to do!");
|
||||
|
||||
bool retval = true;
|
||||
@ -3719,12 +3735,16 @@ WorkerPrivate::RunExpiredTimeouts(JSContext* aCx)
|
||||
}
|
||||
}
|
||||
|
||||
NS_ASSERTION(mRunningExpiredTimeouts, "Someone changed this!");
|
||||
|
||||
// Reschedule intervals.
|
||||
if (info->mIsInterval) {
|
||||
if (info->mIsInterval && !info->mCanceled) {
|
||||
PRUint32 timeoutIndex = mTimeouts.IndexOf(info);
|
||||
NS_ASSERTION(timeoutIndex != PRUint32(-1),
|
||||
"Should still be in the main list!");
|
||||
|
||||
// This is nasty but we have to keep the old nsAutoPtr from deleting the
|
||||
// info we're about to re-add.
|
||||
mTimeouts[timeoutIndex].forget();
|
||||
mTimeouts.RemoveElementAt(timeoutIndex);
|
||||
|
||||
@ -3755,8 +3775,8 @@ WorkerPrivate::RunExpiredTimeouts(JSContext* aCx)
|
||||
}
|
||||
}
|
||||
|
||||
// Signal the parent that we're no longer using timeouts or reschedule the
|
||||
// timer.
|
||||
// Either signal the parent that we're no longer using timeouts or reschedule
|
||||
// the timer.
|
||||
if (mTimeouts.IsEmpty()) {
|
||||
if (!ModifyBusyCountFromWorker(aCx, false)) {
|
||||
retval = false;
|
||||
|
@ -56,6 +56,8 @@ _TEST_FILES = \
|
||||
test_atob.html \
|
||||
atob_worker.js \
|
||||
test_blobWorkers.html \
|
||||
test_clearTimeouts.html \
|
||||
clearTimeouts_worker.js \
|
||||
test_close.html \
|
||||
close_worker.js \
|
||||
test_closeOnGC.html \
|
||||
|
12
dom/workers/test/clearTimeouts_worker.js
Normal file
12
dom/workers/test/clearTimeouts_worker.js
Normal file
@ -0,0 +1,12 @@
|
||||
var count = 0;
|
||||
function timerFunction() {
|
||||
if (++count == 30) {
|
||||
close();
|
||||
postMessage("ready");
|
||||
while (true) { }
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < 10; i++) {
|
||||
setInterval(timerFunction, 500);
|
||||
}
|
30
dom/workers/test/test_clearTimeouts.html
Normal file
30
dom/workers/test/test_clearTimeouts.html
Normal file
@ -0,0 +1,30 @@
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for DOM Worker Threads</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
new Worker("clearTimeouts_worker.js").onmessage = function(event) {
|
||||
event.target.terminate();
|
||||
|
||||
is(event.data, "ready", "Correct message");
|
||||
setTimeout(function() { SimpleTest.finish(); }, 1000);
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -65,7 +65,6 @@ _TEST_FILES = \
|
||||
test_bug645914.html \
|
||||
test_bug681229.html \
|
||||
test_bug692520.html \
|
||||
test_bug717147.html \
|
||||
test_dom_input_event_on_texteditor.html \
|
||||
$(NULL)
|
||||
|
||||
|
@ -1,99 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=717147
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 717147</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717147">Mozilla Bug 717147</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<iframe id="formTarget" name="formTarget"></iframe>
|
||||
<form action="data:text/html," target="formTarget">
|
||||
<input name="test" id="initValue"><input type="submit">
|
||||
</form>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 717147 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(function() {
|
||||
var formTarget = document.getElementById("formTarget");
|
||||
var initValue = document.getElementById("initValue");
|
||||
|
||||
formTarget.addEventListener("load", function() {
|
||||
var newInput = document.createElement("input");
|
||||
newInput.setAttribute("name", "test");
|
||||
document.body.appendChild(newInput);
|
||||
|
||||
setTimeout(function() {
|
||||
var popupShown = false;
|
||||
function listener() {
|
||||
popupShown = true;
|
||||
}
|
||||
SpecialPowers.addAutoCompletePopupEventListener(window, listener);
|
||||
|
||||
newInput.value = "";
|
||||
newInput.focus();
|
||||
|
||||
synthesizeComposition({ type: "compositionstart" });
|
||||
synthesizeComposition({ type: "compositionupdate", data: "f" });
|
||||
synthesizeText(
|
||||
{ "composition":
|
||||
{ "string": "f",
|
||||
"clauses":
|
||||
[
|
||||
{ "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
|
||||
]
|
||||
},
|
||||
"caret": { "start": 1, "length": 0 }
|
||||
});
|
||||
|
||||
hitEventLoop(function() {
|
||||
ok(!popupShown, "Popup must not be opened during composition");
|
||||
|
||||
synthesizeText(
|
||||
{ "composition":
|
||||
{ "string": "f",
|
||||
"clauses":
|
||||
[
|
||||
{ "length": 0, "attr": 0 }
|
||||
]
|
||||
},
|
||||
"caret": { "start": 1, "length": 0 }
|
||||
});
|
||||
synthesizeComposition({ type: "compositionend", data: "f" });
|
||||
|
||||
hitEventLoop(function () {
|
||||
ok(popupShown, "Popup must be opened after compositionend");
|
||||
|
||||
SpecialPowers.removeAutoCompletePopupEventListener(window, listener);
|
||||
SimpleTest.finish();
|
||||
}, 100);
|
||||
}, 100);
|
||||
}, 0);
|
||||
}, false);
|
||||
|
||||
initValue.focus();
|
||||
initValue.value = "foo";
|
||||
synthesizeKey("VK_ENTER", {});
|
||||
});
|
||||
|
||||
function hitEventLoop(func, times) {
|
||||
if (times > 0) {
|
||||
setTimeout(hitEventLoop, 0, func, times - 1);
|
||||
} else {
|
||||
setTimeout(func, 0);
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -55,13 +55,13 @@
|
||||
#include "nsTextFragment.h"
|
||||
#include "nsString.h"
|
||||
#include "nsIAtom.h"
|
||||
#include "nsParserCIID.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIWordBreaker.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsRange.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
// Yikes! Casting a char to unichar can fill with ones!
|
||||
#define CHAR_TO_UNICHAR(c) ((PRUnichar)(const unsigned char)c)
|
||||
@ -457,17 +457,6 @@ NS_NewFindContentIterator(bool aFindBackward,
|
||||
}
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
// Sure would be nice if we could just get these from somewhere else!
|
||||
PRInt32 nsFind::sInstanceCount = 0;
|
||||
nsIAtom* nsFind::sImgAtom = nsnull;
|
||||
nsIAtom* nsFind::sHRAtom = nsnull;
|
||||
nsIAtom* nsFind::sScriptAtom = nsnull;
|
||||
nsIAtom* nsFind::sNoframesAtom = nsnull;
|
||||
nsIAtom* nsFind::sSelectAtom = nsnull;
|
||||
nsIAtom* nsFind::sTextareaAtom = nsnull;
|
||||
nsIAtom* nsFind::sThAtom = nsnull;
|
||||
nsIAtom* nsFind::sTdAtom = nsnull;
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsFind, nsIFind)
|
||||
|
||||
nsFind::nsFind()
|
||||
@ -475,35 +464,10 @@ nsFind::nsFind()
|
||||
, mCaseSensitive(false)
|
||||
, mIterOffset(0)
|
||||
{
|
||||
// Initialize the atoms if they aren't already:
|
||||
if (sInstanceCount <= 0)
|
||||
{
|
||||
sImgAtom = NS_NewAtom("img");
|
||||
sHRAtom = NS_NewAtom("hr");
|
||||
sScriptAtom = NS_NewAtom("script");
|
||||
sNoframesAtom = NS_NewAtom("noframes");
|
||||
sSelectAtom = NS_NewAtom("select");
|
||||
sTextareaAtom = NS_NewAtom("textarea");
|
||||
sThAtom = NS_NewAtom("th");
|
||||
sTdAtom = NS_NewAtom("td");
|
||||
}
|
||||
++sInstanceCount;
|
||||
}
|
||||
|
||||
nsFind::~nsFind()
|
||||
{
|
||||
if (sInstanceCount <= 1)
|
||||
{
|
||||
NS_IF_RELEASE(sImgAtom);
|
||||
NS_IF_RELEASE(sHRAtom);
|
||||
NS_IF_RELEASE(sScriptAtom);
|
||||
NS_IF_RELEASE(sNoframesAtom);
|
||||
NS_IF_RELEASE(sSelectAtom);
|
||||
NS_IF_RELEASE(sTextareaAtom);
|
||||
NS_IF_RELEASE(sThAtom);
|
||||
NS_IF_RELEASE(sTdAtom);
|
||||
}
|
||||
--sInstanceCount;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_FIND
|
||||
@ -780,21 +744,13 @@ bool nsFind::IsBlockNode(nsIContent* aContent)
|
||||
|
||||
nsIAtom *atom = aContent->Tag();
|
||||
|
||||
if (atom == sImgAtom ||
|
||||
atom == sHRAtom ||
|
||||
atom == sThAtom ||
|
||||
atom == sTdAtom)
|
||||
if (atom == nsGkAtoms::img ||
|
||||
atom == nsGkAtoms::hr ||
|
||||
atom == nsGkAtoms::th ||
|
||||
atom == nsGkAtoms::td)
|
||||
return true;
|
||||
|
||||
if (!mParserService) {
|
||||
mParserService = do_GetService(NS_PARSERSERVICE_CONTRACTID);
|
||||
if (!mParserService)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isBlock = false;
|
||||
mParserService->IsBlock(mParserService->HTMLAtomTagToId(atom), isBlock);
|
||||
return isBlock;
|
||||
return nsContentUtils::IsHTMLBlock(atom);
|
||||
}
|
||||
|
||||
bool nsFind::IsTextNode(nsIDOMNode* aNode)
|
||||
@ -849,9 +805,9 @@ bool nsFind::SkipNode(nsIContent* aContent)
|
||||
|
||||
if (aContent->IsNodeOfType(nsINode::eCOMMENT) ||
|
||||
(content->IsHTML() &&
|
||||
(atom == sScriptAtom ||
|
||||
atom == sNoframesAtom ||
|
||||
atom == sSelectAtom)))
|
||||
(atom == nsGkAtoms::script ||
|
||||
atom == nsGkAtoms::noframes ||
|
||||
atom == nsGkAtoms::select)))
|
||||
{
|
||||
#ifdef DEBUG_FIND
|
||||
printf("Skipping node: ");
|
||||
|
@ -45,7 +45,6 @@
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIDOMRange.h"
|
||||
#include "nsIContentIterator.h"
|
||||
#include "nsIParserService.h"
|
||||
#include "nsIWordBreaker.h"
|
||||
|
||||
class nsIAtom;
|
||||
@ -70,26 +69,12 @@ public:
|
||||
static already_AddRefed<nsIDOMRange> CreateRange();
|
||||
|
||||
protected:
|
||||
static PRInt32 sInstanceCount;
|
||||
|
||||
// HTML tags we treat specially
|
||||
static nsIAtom* sImgAtom;
|
||||
static nsIAtom* sHRAtom;
|
||||
// Nodes we skip
|
||||
static nsIAtom* sScriptAtom;
|
||||
static nsIAtom* sNoframesAtom;
|
||||
static nsIAtom* sSelectAtom;
|
||||
static nsIAtom* sTextareaAtom;
|
||||
static nsIAtom* sThAtom;
|
||||
static nsIAtom* sTdAtom;
|
||||
|
||||
// Parameters set from the interface:
|
||||
//nsCOMPtr<nsIDOMRange> mRange; // search only in this range
|
||||
bool mFindBackward;
|
||||
bool mCaseSensitive;
|
||||
|
||||
nsCOMPtr<nsIWordBreaker> mWordBreaker;
|
||||
nsCOMPtr<nsIParserService> mParserService;
|
||||
|
||||
PRInt32 mIterOffset;
|
||||
nsCOMPtr<nsIDOMNode> mIterNode;
|
||||
|
@ -50,6 +50,8 @@ EXPORTS = \
|
||||
gfx3DMatrix.h \
|
||||
gfxASurface.h \
|
||||
gfxAlphaRecovery.h \
|
||||
gfxAtomList.h \
|
||||
gfxAtoms.h \
|
||||
gfxBlur.h \
|
||||
gfxCachedTempSurface.h \
|
||||
gfxColor.h \
|
||||
|
@ -95,3 +95,9 @@ GFX_ATOM(x_symbol, "x-symbol")
|
||||
|
||||
// referenced in all.js
|
||||
GFX_ATOM(x_user_def, "x-user-def")
|
||||
|
||||
// additional languages that use Turkish-style case transformation
|
||||
GFX_ATOM(az, "az")
|
||||
GFX_ATOM(ba, "ba")
|
||||
GFX_ATOM(crh, "crh")
|
||||
GFX_ATOM(tt, "tt")
|
||||
|
@ -249,6 +249,23 @@ gfxDWriteFontFamily::LocalizedName(nsAString &aLocalizedName)
|
||||
aLocalizedName = nsDependentString(famName.Elements());
|
||||
}
|
||||
|
||||
void
|
||||
gfxDWriteFontFamily::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const
|
||||
{
|
||||
gfxFontFamily::SizeOfExcludingThis(aMallocSizeOf, aSizes);
|
||||
// TODO:
|
||||
// This doesn't currently account for |mDWFamily|
|
||||
}
|
||||
|
||||
void
|
||||
gfxDWriteFontFamily::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const
|
||||
{
|
||||
aSizes->mFontListSize += aMallocSizeOf(this);
|
||||
SizeOfExcludingThis(aMallocSizeOf, aSizes);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// gfxDWriteFontEntry
|
||||
|
||||
@ -377,7 +394,8 @@ gfxDWriteFontEntry::ReadCMAP()
|
||||
unicodeFont, symbolFont);
|
||||
#ifdef PR_LOGGING
|
||||
LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d\n",
|
||||
NS_ConvertUTF16toUTF8(mName).get(), mCharacterMap.GetSize()));
|
||||
NS_ConvertUTF16toUTF8(mName).get(),
|
||||
mCharacterMap.SizeOfExcludingThis(moz_malloc_size_of)));
|
||||
if (LOG_CMAPDATA_ENABLED()) {
|
||||
char prefix[256];
|
||||
sprintf(prefix, "(cmapdata) name: %.220s",
|
||||
@ -424,7 +442,8 @@ gfxDWriteFontEntry::ReadCMAP()
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d\n",
|
||||
NS_ConvertUTF16toUTF8(mName).get(), mCharacterMap.GetSize()));
|
||||
NS_ConvertUTF16toUTF8(mName).get(),
|
||||
mCharacterMap.SizeOfExcludingThis(moz_malloc_size_of)));
|
||||
if (LOG_CMAPDATA_ENABLED()) {
|
||||
char prefix[256];
|
||||
sprintf(prefix, "(cmapdata) name: %.220s",
|
||||
@ -544,6 +563,23 @@ gfxDWriteFontEntry::IsCJKFont()
|
||||
return mIsCJK;
|
||||
}
|
||||
|
||||
void
|
||||
gfxDWriteFontEntry::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const
|
||||
{
|
||||
gfxFontEntry::SizeOfExcludingThis(aMallocSizeOf, aSizes);
|
||||
// TODO:
|
||||
// This doesn't currently account for the |mFont| and |mFontFile| members
|
||||
}
|
||||
|
||||
void
|
||||
gfxDWriteFontEntry::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const
|
||||
{
|
||||
aSizes->mFontListSize += aMallocSizeOf(this);
|
||||
SizeOfExcludingThis(aMallocSizeOf, aSizes);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// gfxDWriteFontList
|
||||
|
||||
@ -587,7 +623,6 @@ gfxFontEntry *
|
||||
gfxDWriteFontList::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
const nsAString& aFullname)
|
||||
{
|
||||
bool found;
|
||||
gfxFontEntry *lookup;
|
||||
|
||||
// initialize name lookup tables if needed
|
||||
@ -596,8 +631,8 @@ gfxDWriteFontList::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
}
|
||||
|
||||
// lookup in name lookup tables, return null if not found
|
||||
if (!(lookup = mPostscriptNames.GetWeak(aFullname, &found)) &&
|
||||
!(lookup = mFullnames.GetWeak(aFullname, &found)))
|
||||
if (!(lookup = mPostscriptNames.GetWeak(aFullname)) &&
|
||||
!(lookup = mFullnames.GetWeak(aFullname)))
|
||||
{
|
||||
return nsnull;
|
||||
}
|
||||
@ -1182,8 +1217,8 @@ gfxDWriteFontList::ResolveFontName(const nsAString& aFontName,
|
||||
nsAutoString keyName(aFontName);
|
||||
BuildKeyNameFromFontName(keyName);
|
||||
|
||||
nsRefPtr<gfxFontFamily> ff;
|
||||
if (mFontSubstitutes.Get(keyName, &ff)) {
|
||||
gfxFontFamily *ff = mFontSubstitutes.GetWeak(keyName);
|
||||
if (ff) {
|
||||
aResolvedFontName = ff->Name();
|
||||
return true;
|
||||
}
|
||||
@ -1195,6 +1230,32 @@ gfxDWriteFontList::ResolveFontName(const nsAString& aFontName,
|
||||
return gfxPlatformFontList::ResolveFontName(aFontName, aResolvedFontName);
|
||||
}
|
||||
|
||||
void
|
||||
gfxDWriteFontList::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const
|
||||
{
|
||||
gfxPlatformFontList::SizeOfExcludingThis(aMallocSizeOf, aSizes);
|
||||
|
||||
aSizes->mFontListSize +=
|
||||
mFontSubstitutes.SizeOfExcludingThis(SizeOfFamilyNameEntryExcludingThis,
|
||||
aMallocSizeOf);
|
||||
|
||||
aSizes->mFontListSize +=
|
||||
mNonExistingFonts.SizeOfExcludingThis(aMallocSizeOf);
|
||||
for (PRUint32 i = 0; i < mNonExistingFonts.Length(); ++i) {
|
||||
aSizes->mFontListSize +=
|
||||
mNonExistingFonts[i].SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gfxDWriteFontList::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const
|
||||
{
|
||||
aSizes->mFontListSize += aMallocSizeOf(this);
|
||||
SizeOfExcludingThis(aMallocSizeOf, aSizes);
|
||||
}
|
||||
|
||||
static nsresult GetFamilyName(IDWriteFont *aFont, nsString& aFamilyName)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
@ -79,6 +79,11 @@ public:
|
||||
|
||||
void SetForceGDIClassic(bool aForce) { mForceGDIClassic = aForce; }
|
||||
|
||||
virtual void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const;
|
||||
virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const;
|
||||
|
||||
protected:
|
||||
/** This font family's directwrite fontfamily object */
|
||||
nsRefPtr<IDWriteFontFamily> mDWFamily;
|
||||
@ -179,6 +184,11 @@ public:
|
||||
void SetForceGDIClassic(bool aForce) { mForceGDIClassic = aForce; }
|
||||
bool GetForceGDIClassic() { return mForceGDIClassic; }
|
||||
|
||||
virtual void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const;
|
||||
virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const;
|
||||
|
||||
protected:
|
||||
friend class gfxDWriteFont;
|
||||
friend class gfxDWriteFontList;
|
||||
@ -380,6 +390,11 @@ public:
|
||||
|
||||
gfxFloat GetForceGDIClassicMaxFontSize() { return mForceGDIClassicMaxFontSize; }
|
||||
|
||||
virtual void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const;
|
||||
virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const;
|
||||
|
||||
private:
|
||||
friend class gfxDWriteFontFamily;
|
||||
|
||||
@ -401,7 +416,7 @@ private:
|
||||
*/
|
||||
nsTArray<nsString> mNonExistingFonts;
|
||||
|
||||
typedef nsDataHashtable<nsStringHashKey, nsRefPtr<gfxFontFamily> > FontTable;
|
||||
typedef nsRefPtrHashtable<nsStringHashKey, gfxFontFamily> FontTable;
|
||||
|
||||
/**
|
||||
* Table of font substitutes, we grab this from the registry to get
|
||||
|
@ -389,6 +389,23 @@ FT2FontEntry::GetFontTable(PRUint32 aTableTag,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
FT2FontEntry::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const
|
||||
{
|
||||
gfxFontEntry::SizeOfExcludingThis(aMallocSizeOf, aSizes);
|
||||
aSizes->mFontListSize +=
|
||||
mFilename.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
}
|
||||
|
||||
void
|
||||
FT2FontEntry::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const
|
||||
{
|
||||
aSizes->mFontListSize += aMallocSizeOf(this);
|
||||
SizeOfExcludingThis(aMallocSizeOf, aSizes);
|
||||
}
|
||||
|
||||
/*
|
||||
* FT2FontFamily
|
||||
* A standard gfxFontFamily; just adds a method used to support sending
|
||||
|
@ -102,6 +102,11 @@ public:
|
||||
nsresult ReadCMAP();
|
||||
nsresult GetFontTable(PRUint32 aTableTag, FallibleTArray<PRUint8>& aBuffer);
|
||||
|
||||
virtual void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const;
|
||||
virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const;
|
||||
|
||||
FT_Face mFTFace;
|
||||
cairo_font_face_t *mFontFace;
|
||||
|
||||
|
@ -272,6 +272,13 @@ public:
|
||||
mHashEntry = nsnull;
|
||||
}
|
||||
|
||||
size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const {
|
||||
return mTableData.SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const {
|
||||
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
private:
|
||||
// The font table data block, owned (via adoption)
|
||||
FallibleTArray<PRUint8> mTableData;
|
||||
@ -401,6 +408,46 @@ gfxFontEntry::CheckForGraphiteTables()
|
||||
}
|
||||
#endif
|
||||
|
||||
/* static */ size_t
|
||||
gfxFontEntry::FontTableHashEntry::SizeOfEntryExcludingThis
|
||||
(FontTableHashEntry *aEntry,
|
||||
nsMallocSizeOfFun aMallocSizeOf,
|
||||
void* aUserArg)
|
||||
{
|
||||
FontListSizes *sizes = static_cast<FontListSizes*>(aUserArg);
|
||||
if (aEntry->mBlob) {
|
||||
sizes->mFontTableCacheSize += aMallocSizeOf(aEntry->mBlob);
|
||||
}
|
||||
if (aEntry->mSharedBlobData) {
|
||||
sizes->mFontTableCacheSize +=
|
||||
aEntry->mSharedBlobData->SizeOfIncludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
// the size of the table is recorded in the FontListSizes record,
|
||||
// so we return 0 here for the function result
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
gfxFontEntry::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const
|
||||
{
|
||||
aSizes->mFontListSize += mName.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
aSizes->mCharMapsSize += mCharacterMap.SizeOfExcludingThis(aMallocSizeOf);
|
||||
aSizes->mFontTableCacheSize +=
|
||||
mFontTableCache.SizeOfExcludingThis(
|
||||
FontTableHashEntry::SizeOfEntryExcludingThis,
|
||||
aMallocSizeOf, aSizes);
|
||||
}
|
||||
|
||||
void
|
||||
gfxFontEntry::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const
|
||||
{
|
||||
aSizes->mFontListSize += aMallocSizeOf(this);
|
||||
SizeOfExcludingThis(aMallocSizeOf, aSizes);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// class gfxFontFamily
|
||||
@ -975,6 +1022,32 @@ gfxFontFamily::FindFont(const nsAString& aPostscriptName)
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
void
|
||||
gfxFontFamily::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const
|
||||
{
|
||||
aSizes->mFontListSize +=
|
||||
mName.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
aSizes->mCharMapsSize += mCharacterMap.SizeOfExcludingThis(aMallocSizeOf);
|
||||
|
||||
aSizes->mFontListSize +=
|
||||
mAvailableFonts.SizeOfExcludingThis(aMallocSizeOf);
|
||||
for (PRUint32 i = 0; i < mAvailableFonts.Length(); ++i) {
|
||||
gfxFontEntry *fe = mAvailableFonts[i];
|
||||
if (fe) {
|
||||
fe->SizeOfIncludingThis(aMallocSizeOf, aSizes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gfxFontFamily::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const
|
||||
{
|
||||
aSizes->mFontListSize += aMallocSizeOf(this);
|
||||
SizeOfExcludingThis(aMallocSizeOf, aSizes);
|
||||
}
|
||||
|
||||
/*
|
||||
* gfxFontCache - global cache of gfxFont instances.
|
||||
* Expires unused fonts after a short interval;
|
||||
|
@ -91,6 +91,8 @@ struct THEBES_API gfxFontFeature {
|
||||
// to features that select among multiple alternatives
|
||||
};
|
||||
|
||||
struct FontListSizes;
|
||||
|
||||
inline bool
|
||||
operator<(const gfxFontFeature& a, const gfxFontFeature& b)
|
||||
{
|
||||
@ -314,6 +316,12 @@ public:
|
||||
hb_blob_t *ShareFontTableAndGetBlob(PRUint32 aTag,
|
||||
FallibleTArray<PRUint8>* aTable);
|
||||
|
||||
// For memory reporting
|
||||
virtual void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const;
|
||||
virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const;
|
||||
|
||||
nsString mName;
|
||||
|
||||
bool mItalic : 1;
|
||||
@ -468,6 +476,11 @@ private:
|
||||
|
||||
void Clear();
|
||||
|
||||
static size_t
|
||||
SizeOfEntryExcludingThis(FontTableHashEntry *aEntry,
|
||||
nsMallocSizeOfFun aMallocSizeOf,
|
||||
void* aUserArg);
|
||||
|
||||
private:
|
||||
static void DeleteFontTableBlobData(void *aBlobData);
|
||||
// not implemented
|
||||
@ -634,6 +647,12 @@ public:
|
||||
// if so set the mIsSimpleFamily flag (defaults to False before we've checked)
|
||||
void CheckForSimpleFamily();
|
||||
|
||||
// For memory reporter
|
||||
virtual void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const;
|
||||
virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const;
|
||||
|
||||
protected:
|
||||
// fills in an array with weights of faces that match style,
|
||||
// returns whether any matching entries found
|
||||
|
@ -264,14 +264,18 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
PRUint32 GetSize() {
|
||||
PRUint32 size = 0;
|
||||
size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const {
|
||||
size_t total = mBlocks.SizeOfExcludingThis(aMallocSizeOf);
|
||||
for (PRUint32 i = 0; i < mBlocks.Length(); i++) {
|
||||
if (mBlocks[i])
|
||||
size += sizeof(Block);
|
||||
size += sizeof(nsAutoPtr<Block>);
|
||||
if (mBlocks[i]) {
|
||||
total += aMallocSizeOf(mBlocks[i]);
|
||||
}
|
||||
}
|
||||
return size;
|
||||
return total;
|
||||
}
|
||||
|
||||
size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const {
|
||||
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
// clear out all blocks in the array
|
||||
|
@ -246,7 +246,8 @@ GDIFontEntry::ReadCMAP()
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d\n",
|
||||
NS_ConvertUTF16toUTF8(mName).get(), mCharacterMap.GetSize()));
|
||||
NS_ConvertUTF16toUTF8(mName).get(),
|
||||
mCharacterMap.SizeOfExcludingThis(moz_malloc_size_of)));
|
||||
if (LOG_CMAPDATA_ENABLED()) {
|
||||
char prefix[256];
|
||||
sprintf(prefix, "(cmapdata) name: %.220s",
|
||||
@ -459,6 +460,14 @@ GDIFontEntry::CreateFontEntry(const nsAString& aName,
|
||||
return fe;
|
||||
}
|
||||
|
||||
void
|
||||
GDIFontEntry::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const
|
||||
{
|
||||
aSizes->mFontListSize += aMallocSizeOf(this);
|
||||
SizeOfExcludingThis(aMallocSizeOf, aSizes);
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* GDIFontFamily
|
||||
@ -658,7 +667,7 @@ gfxGDIFontList::GetFontSubstitutes()
|
||||
nsAutoString substituteName;
|
||||
substituteName.AssignLiteral("Courier");
|
||||
BuildKeyNameFromFontName(substituteName);
|
||||
if (!mFontSubstitutes.Get(substituteName)) {
|
||||
if (!mFontSubstitutes.GetWeak(substituteName)) {
|
||||
gfxFontFamily *ff;
|
||||
nsAutoString actualFontName;
|
||||
actualFontName.AssignLiteral("Courier New");
|
||||
@ -743,7 +752,6 @@ gfxFontEntry*
|
||||
gfxGDIFontList::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
const nsAString& aFullname)
|
||||
{
|
||||
bool found;
|
||||
gfxFontEntry *lookup;
|
||||
|
||||
// initialize name lookup tables if needed
|
||||
@ -752,8 +760,8 @@ gfxGDIFontList::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
|
||||
}
|
||||
|
||||
// lookup in name lookup tables, return null if not found
|
||||
if (!(lookup = mPostscriptNames.GetWeak(aFullname, &found)) &&
|
||||
!(lookup = mFullnames.GetWeak(aFullname, &found)))
|
||||
if (!(lookup = mPostscriptNames.GetWeak(aFullname)) &&
|
||||
!(lookup = mFullnames.GetWeak(aFullname)))
|
||||
{
|
||||
return nsnull;
|
||||
}
|
||||
@ -1038,8 +1046,8 @@ gfxGDIFontList::ResolveFontName(const nsAString& aFontName, nsAString& aResolved
|
||||
nsAutoString keyName(aFontName);
|
||||
BuildKeyNameFromFontName(keyName);
|
||||
|
||||
nsRefPtr<gfxFontFamily> ff;
|
||||
if (mFontSubstitutes.Get(keyName, &ff)) {
|
||||
gfxFontFamily *ff = mFontSubstitutes.GetWeak(keyName);
|
||||
if (ff) {
|
||||
aResolvedFontName = ff->Name();
|
||||
return true;
|
||||
}
|
||||
@ -1052,3 +1060,27 @@ gfxGDIFontList::ResolveFontName(const nsAString& aFontName, nsAString& aResolved
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
gfxGDIFontList::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const
|
||||
{
|
||||
gfxPlatformFontList::SizeOfExcludingThis(aMallocSizeOf, aSizes);
|
||||
aSizes->mFontListSize +=
|
||||
mFontSubstitutes.SizeOfExcludingThis(SizeOfFamilyNameEntryExcludingThis,
|
||||
aMallocSizeOf);
|
||||
aSizes->mFontListSize +=
|
||||
mNonExistingFonts.SizeOfExcludingThis(aMallocSizeOf);
|
||||
for (PRUint32 i = 0; i < mNonExistingFonts.Length(); ++i) {
|
||||
aSizes->mFontListSize +=
|
||||
mNonExistingFonts[i].SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gfxGDIFontList::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const
|
||||
{
|
||||
aSizes->mFontListSize += aMallocSizeOf(this);
|
||||
SizeOfExcludingThis(aMallocSizeOf, aSizes);
|
||||
}
|
||||
|
@ -274,6 +274,9 @@ public:
|
||||
|
||||
virtual bool TestCharacterMap(PRUint32 aCh);
|
||||
|
||||
virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const;
|
||||
|
||||
// create a font entry for a font with a given name
|
||||
static GDIFontEntry* CreateFontEntry(const nsAString& aName,
|
||||
gfxWindowsFontType aFontType,
|
||||
@ -347,6 +350,11 @@ public:
|
||||
virtual bool ResolveFontName(const nsAString& aFontName,
|
||||
nsAString& aResolvedFontName);
|
||||
|
||||
virtual void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const;
|
||||
virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const;
|
||||
|
||||
private:
|
||||
friend class gfxWindowsPlatform;
|
||||
|
||||
@ -361,7 +369,7 @@ private:
|
||||
DWORD fontType,
|
||||
LPARAM lParam);
|
||||
|
||||
typedef nsDataHashtable<nsStringHashKey, nsRefPtr<gfxFontFamily> > FontTable;
|
||||
typedef nsRefPtrHashtable<nsStringHashKey, gfxFontFamily> FontTable;
|
||||
|
||||
FontTable mFontSubstitutes;
|
||||
nsTArray<nsString> mNonExistingFonts;
|
||||
|
@ -111,6 +111,9 @@ public:
|
||||
virtual nsresult GetFontTable(PRUint32 aTableTag,
|
||||
FallibleTArray<PRUint8>& aBuffer);
|
||||
|
||||
virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const;
|
||||
|
||||
protected:
|
||||
virtual bool HasFontTable(PRUint32 aTableTag);
|
||||
|
||||
@ -134,6 +137,9 @@ public:
|
||||
virtual nsresult GetFontTable(PRUint32 aTableTag,
|
||||
FallibleTArray<PRUint8>& aBuffer);
|
||||
|
||||
virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const;
|
||||
|
||||
protected:
|
||||
virtual bool HasFontTable(PRUint32 aTableTag);
|
||||
};
|
||||
|
@ -270,7 +270,7 @@ MacOSFontEntry::ReadCMAP()
|
||||
#ifdef PR_LOGGING
|
||||
LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d\n",
|
||||
NS_ConvertUTF16toUTF8(mName).get(),
|
||||
mCharacterMap.GetSize()));
|
||||
mCharacterMap.SizeOfExcludingThis(moz_malloc_size_of)));
|
||||
if (LOG_CMAPDATA_ENABLED()) {
|
||||
char prefix[256];
|
||||
sprintf(prefix, "(cmapdata) name: %.220s",
|
||||
@ -398,6 +398,14 @@ ATSFontEntry::HasFontTable(PRUint32 aTableTag)
|
||||
(::ATSFontGetTable(fontRef, aTableTag, 0, 0, 0, &size) == noErr);
|
||||
}
|
||||
|
||||
void
|
||||
ATSFontEntry::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const
|
||||
{
|
||||
aSizes->mFontListSize += aMallocSizeOf(this);
|
||||
SizeOfExcludingThis(aMallocSizeOf, aSizes);
|
||||
}
|
||||
|
||||
/* CGFontEntry - used on Mac OS X 10.6+ */
|
||||
#pragma mark-
|
||||
|
||||
@ -486,6 +494,14 @@ CGFontEntry::HasFontTable(PRUint32 aTableTag)
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CGFontEntry::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const
|
||||
{
|
||||
aSizes->mFontListSize += aMallocSizeOf(this);
|
||||
SizeOfExcludingThis(aMallocSizeOf, aSizes);
|
||||
}
|
||||
|
||||
/* gfxMacFontFamily */
|
||||
#pragma mark-
|
||||
|
||||
@ -811,10 +827,9 @@ gfxMacPlatformFontList::InitSingleFaceList()
|
||||
#endif
|
||||
|
||||
// add only if doesn't exist already
|
||||
bool found;
|
||||
gfxFontFamily *familyEntry;
|
||||
if (!(familyEntry = mFontFamilies.GetWeak(key, &found))) {
|
||||
familyEntry = new gfxSingleFaceMacFontFamily(familyName);
|
||||
if (!mFontFamilies.GetWeak(key)) {
|
||||
gfxFontFamily *familyEntry =
|
||||
new gfxSingleFaceMacFontFamily(familyName);
|
||||
familyEntry->AddFontEntry(fontEntry);
|
||||
familyEntry->SetHasStyles(true);
|
||||
mFontFamilies.Put(key, familyEntry);
|
||||
|
@ -130,6 +130,63 @@ gfxFontListPrefObserver::Observe(nsISupports *aSubject,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(gfxPlatformFontList::MemoryReporter, nsIMemoryMultiReporter)
|
||||
|
||||
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(FontListMallocSizeOf, "font-list")
|
||||
|
||||
NS_IMETHODIMP
|
||||
gfxPlatformFontList::MemoryReporter::GetName(nsACString &aName)
|
||||
{
|
||||
aName.AssignLiteral("font-list");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
gfxPlatformFontList::MemoryReporter::CollectReports
|
||||
(nsIMemoryMultiReporterCallback* aCb,
|
||||
nsISupports* aClosure)
|
||||
{
|
||||
FontListSizes sizes;
|
||||
sizes.mFontListSize = 0;
|
||||
sizes.mFontTableCacheSize = 0;
|
||||
sizes.mCharMapsSize = 0;
|
||||
|
||||
gfxPlatformFontList::PlatformFontList()->SizeOfIncludingThis(&FontListMallocSizeOf,
|
||||
&sizes);
|
||||
|
||||
aCb->Callback(EmptyCString(),
|
||||
NS_LITERAL_CSTRING("explicit/gfx/font-list"),
|
||||
nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES,
|
||||
sizes.mFontListSize,
|
||||
NS_LITERAL_CSTRING("Memory used to manage the list of font families and faces."),
|
||||
aClosure);
|
||||
|
||||
aCb->Callback(EmptyCString(),
|
||||
NS_LITERAL_CSTRING("explicit/gfx/font-charmaps"),
|
||||
nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES,
|
||||
sizes.mCharMapsSize,
|
||||
NS_LITERAL_CSTRING("Memory used to record the character coverage of individual fonts."),
|
||||
aClosure);
|
||||
|
||||
if (sizes.mFontTableCacheSize) {
|
||||
aCb->Callback(EmptyCString(),
|
||||
NS_LITERAL_CSTRING("explicit/gfx/font-tables"),
|
||||
nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES,
|
||||
sizes.mFontTableCacheSize,
|
||||
NS_LITERAL_CSTRING("Memory used for cached font metrics and layout tables."),
|
||||
aClosure);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
gfxPlatformFontList::MemoryReporter::GetExplicitNonHeap(PRInt64* aAmount)
|
||||
{
|
||||
// This reporter only measures heap memory.
|
||||
*aAmount = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
gfxPlatformFontList::gfxPlatformFontList(bool aNeedFullnamePostscriptNames)
|
||||
: mNeedFullnamePostscriptNames(aNeedFullnamePostscriptNames),
|
||||
@ -184,6 +241,8 @@ gfxPlatformFontList::InitFontList()
|
||||
mCodepointsWithNoFonts.SetRange(0,0x1f); // C0 controls
|
||||
mCodepointsWithNoFonts.SetRange(0x7f,0x9f); // C1 controls
|
||||
|
||||
NS_RegisterMemoryMultiReporter(new MemoryReporter);
|
||||
|
||||
sPlatformFontList = this;
|
||||
|
||||
return NS_OK;
|
||||
@ -244,12 +303,11 @@ gfxPlatformFontList::PreloadNamesList()
|
||||
|
||||
PRUint32 numFonts = preloadFonts.Length();
|
||||
for (PRUint32 i = 0; i < numFonts; i++) {
|
||||
bool found;
|
||||
nsAutoString key;
|
||||
GenerateFontListKey(preloadFonts[i], key);
|
||||
|
||||
// only search canonical names!
|
||||
gfxFontFamily *familyEntry = mFontFamilies.GetWeak(key, &found);
|
||||
gfxFontFamily *familyEntry = mFontFamilies.GetWeak(key);
|
||||
if (familyEntry) {
|
||||
familyEntry->ReadOtherFamilyNames(this);
|
||||
}
|
||||
@ -549,18 +607,17 @@ gfxPlatformFontList::FindFamily(const nsAString& aFamily)
|
||||
{
|
||||
nsAutoString key;
|
||||
gfxFontFamily *familyEntry;
|
||||
bool found;
|
||||
GenerateFontListKey(aFamily, key);
|
||||
|
||||
NS_ASSERTION(mFontFamilies.Count() != 0, "system font list was not initialized correctly");
|
||||
|
||||
// lookup in canonical (i.e. English) family name list
|
||||
if ((familyEntry = mFontFamilies.GetWeak(key, &found))) {
|
||||
if ((familyEntry = mFontFamilies.GetWeak(key))) {
|
||||
return familyEntry;
|
||||
}
|
||||
|
||||
// lookup in other family names list (mostly localized names)
|
||||
if ((familyEntry = mOtherFamilyNames.GetWeak(key, &found)) != nsnull) {
|
||||
if ((familyEntry = mOtherFamilyNames.GetWeak(key)) != nsnull) {
|
||||
return familyEntry;
|
||||
}
|
||||
|
||||
@ -571,7 +628,7 @@ gfxPlatformFontList::FindFamily(const nsAString& aFamily)
|
||||
// in practice so avoid pulling in names at startup
|
||||
if (!mOtherFamilyNamesInitialized && !IsASCII(aFamily)) {
|
||||
InitOtherFamilyNames();
|
||||
if ((familyEntry = mOtherFamilyNames.GetWeak(key, &found)) != nsnull) {
|
||||
if ((familyEntry = mOtherFamilyNames.GetWeak(key)) != nsnull) {
|
||||
return familyEntry;
|
||||
}
|
||||
}
|
||||
@ -608,10 +665,9 @@ void
|
||||
gfxPlatformFontList::AddOtherFamilyName(gfxFontFamily *aFamilyEntry, nsAString& aOtherFamilyName)
|
||||
{
|
||||
nsAutoString key;
|
||||
bool found;
|
||||
GenerateFontListKey(aOtherFamilyName, key);
|
||||
|
||||
if (!mOtherFamilyNames.GetWeak(key, &found)) {
|
||||
if (!mOtherFamilyNames.GetWeak(key)) {
|
||||
mOtherFamilyNames.Put(key, aFamilyEntry);
|
||||
#ifdef PR_LOGGING
|
||||
LOG_FONTLIST(("(fontlist-otherfamily) canonical family: %s, "
|
||||
@ -627,9 +683,7 @@ gfxPlatformFontList::AddOtherFamilyName(gfxFontFamily *aFamilyEntry, nsAString&
|
||||
void
|
||||
gfxPlatformFontList::AddFullname(gfxFontEntry *aFontEntry, nsAString& aFullname)
|
||||
{
|
||||
bool found;
|
||||
|
||||
if (!mFullnames.GetWeak(aFullname, &found)) {
|
||||
if (!mFullnames.GetWeak(aFullname)) {
|
||||
mFullnames.Put(aFullname, aFontEntry);
|
||||
#ifdef PR_LOGGING
|
||||
LOG_FONTLIST(("(fontlist-fullname) name: %s, fullname: %s\n",
|
||||
@ -642,9 +696,7 @@ gfxPlatformFontList::AddFullname(gfxFontEntry *aFontEntry, nsAString& aFullname)
|
||||
void
|
||||
gfxPlatformFontList::AddPostscriptName(gfxFontEntry *aFontEntry, nsAString& aPostscriptName)
|
||||
{
|
||||
bool found;
|
||||
|
||||
if (!mPostscriptNames.GetWeak(aPostscriptName, &found)) {
|
||||
if (!mPostscriptNames.GetWeak(aPostscriptName)) {
|
||||
mPostscriptNames.Put(aPostscriptName, aFontEntry);
|
||||
#ifdef PR_LOGGING
|
||||
LOG_FONTLIST(("(fontlist-postscript) name: %s, psname: %s\n",
|
||||
@ -714,3 +766,111 @@ gfxPlatformFontList::FinishLoader()
|
||||
mFontFamiliesToLoad.Clear();
|
||||
mNumFamilies = 0;
|
||||
}
|
||||
|
||||
// Support for memory reporting
|
||||
|
||||
static size_t
|
||||
SizeOfFamilyEntryExcludingThis(const nsAString& aKey,
|
||||
const nsRefPtr<gfxFontFamily>& aFamily,
|
||||
nsMallocSizeOfFun aMallocSizeOf,
|
||||
void* aUserArg)
|
||||
{
|
||||
FontListSizes *sizes = static_cast<FontListSizes*>(aUserArg);
|
||||
aFamily->SizeOfExcludingThis(aMallocSizeOf, sizes);
|
||||
|
||||
sizes->mFontListSize += aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
|
||||
// we return zero here because the measurements have been added directly
|
||||
// to the relevant fields of the FontListSizes record
|
||||
return 0;
|
||||
}
|
||||
|
||||
// this is also used by subclasses that hold additional hashes of family names
|
||||
/*static*/ size_t
|
||||
gfxPlatformFontList::SizeOfFamilyNameEntryExcludingThis
|
||||
(const nsAString& aKey,
|
||||
const nsRefPtr<gfxFontFamily>& aFamily,
|
||||
nsMallocSizeOfFun aMallocSizeOf,
|
||||
void* aUserArg)
|
||||
{
|
||||
// we don't count the size of the family here, because this is an *extra*
|
||||
// reference to a family that will have already been counted in the main list
|
||||
return aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
}
|
||||
|
||||
static size_t
|
||||
SizeOfFontNameEntryExcludingThis(const nsAString& aKey,
|
||||
const nsRefPtr<gfxFontEntry>& aFont,
|
||||
nsMallocSizeOfFun aMallocSizeOf,
|
||||
void* aUserArg)
|
||||
{
|
||||
// the font itself is counted by its owning family; here we only care about
|
||||
// the name stored in the hashtable key
|
||||
return aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
}
|
||||
|
||||
static size_t
|
||||
SizeOfPrefFontEntryExcludingThis
|
||||
(const PRUint32& aKey,
|
||||
const nsTArray<nsRefPtr<gfxFontFamily> >& aList,
|
||||
nsMallocSizeOfFun aMallocSizeOf,
|
||||
void* aUserArg)
|
||||
{
|
||||
// again, we only care about the size of the array itself; we don't follow
|
||||
// the refPtrs stored in it, because they point to entries already owned
|
||||
// and accounted-for by the main font list
|
||||
return aList.SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
static size_t
|
||||
SizeOfStringEntryExcludingThis(nsStringHashKey* aHashEntry,
|
||||
nsMallocSizeOfFun aMallocSizeOf,
|
||||
void* aUserArg)
|
||||
{
|
||||
return aHashEntry->GetKey().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
}
|
||||
|
||||
void
|
||||
gfxPlatformFontList::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const
|
||||
{
|
||||
aSizes->mFontListSize +=
|
||||
mFontFamilies.SizeOfExcludingThis(SizeOfFamilyEntryExcludingThis,
|
||||
aMallocSizeOf, aSizes);
|
||||
|
||||
aSizes->mFontListSize +=
|
||||
mOtherFamilyNames.SizeOfExcludingThis(SizeOfFamilyNameEntryExcludingThis,
|
||||
aMallocSizeOf);
|
||||
|
||||
if (mNeedFullnamePostscriptNames) {
|
||||
aSizes->mFontListSize +=
|
||||
mFullnames.SizeOfExcludingThis(SizeOfFontNameEntryExcludingThis,
|
||||
aMallocSizeOf);
|
||||
aSizes->mFontListSize +=
|
||||
mPostscriptNames.SizeOfExcludingThis(SizeOfFontNameEntryExcludingThis,
|
||||
aMallocSizeOf);
|
||||
}
|
||||
|
||||
aSizes->mFontListSize +=
|
||||
mCodepointsWithNoFonts.SizeOfExcludingThis(aMallocSizeOf);
|
||||
aSizes->mFontListSize +=
|
||||
mReplacementCharFallbackFamily.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
aSizes->mFontListSize +=
|
||||
mFontFamiliesToLoad.SizeOfExcludingThis(aMallocSizeOf);
|
||||
|
||||
aSizes->mFontListSize +=
|
||||
mPrefFonts.SizeOfExcludingThis(SizeOfPrefFontEntryExcludingThis,
|
||||
aMallocSizeOf);
|
||||
|
||||
aSizes->mFontListSize +=
|
||||
mBadUnderlineFamilyNames.SizeOfExcludingThis(SizeOfStringEntryExcludingThis,
|
||||
aMallocSizeOf);
|
||||
}
|
||||
|
||||
void
|
||||
gfxPlatformFontList::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const
|
||||
{
|
||||
aSizes->mFontListSize += aMallocSizeOf(this);
|
||||
SizeOfExcludingThis(aMallocSizeOf, aSizes);
|
||||
}
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "gfxFont.h"
|
||||
#include "gfxPlatform.h"
|
||||
|
||||
#include "nsIMemoryReporter.h"
|
||||
#include "mozilla/FunctionTimer.h"
|
||||
|
||||
// gfxPlatformFontList is an abstract class for the global font list on the system;
|
||||
@ -57,6 +58,14 @@
|
||||
|
||||
// Much of this is based on the old gfxQuartzFontCache, but adapted for use on all platforms.
|
||||
|
||||
struct FontListSizes {
|
||||
PRUint32 mFontListSize; // size of the font list and dependent objects
|
||||
// (font family and face names, etc), but NOT
|
||||
// including the font table cache and the cmaps
|
||||
PRUint32 mFontTableCacheSize; // memory used for the gfxFontEntry table caches
|
||||
PRUint32 mCharMapsSize; // memory used for cmap coverage info
|
||||
};
|
||||
|
||||
class gfxPlatformFontList : protected gfxFontInfoLoader
|
||||
{
|
||||
public:
|
||||
@ -141,7 +150,20 @@ public:
|
||||
// (platforms may override, eg Mac)
|
||||
virtual bool GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName);
|
||||
|
||||
virtual void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const;
|
||||
virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const;
|
||||
|
||||
protected:
|
||||
class MemoryReporter
|
||||
: public nsIMemoryMultiReporter
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIMEMORYMULTIREPORTER
|
||||
};
|
||||
|
||||
gfxPlatformFontList(bool aNeedFullnamePostscriptNames = true);
|
||||
|
||||
static gfxPlatformFontList *sPlatformFontList;
|
||||
@ -200,6 +222,13 @@ protected:
|
||||
virtual bool RunLoader();
|
||||
virtual void FinishLoader();
|
||||
|
||||
// used by memory reporter to accumulate sizes of family names in the hash
|
||||
static size_t
|
||||
SizeOfFamilyNameEntryExcludingThis(const nsAString& aKey,
|
||||
const nsRefPtr<gfxFontFamily>& aFamily,
|
||||
nsMallocSizeOfFun aMallocSizeOf,
|
||||
void* aUserArg);
|
||||
|
||||
// canonical family name ==> family entry (unique, one name per family entry)
|
||||
nsRefPtrHashtable<nsStringHashKey, gfxFontFamily> mFontFamilies;
|
||||
|
||||
|
@ -88,6 +88,12 @@ using namespace mozilla::gfx;
|
||||
#include "nsMemory.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Required headers are not available in the current consumer preview Win8
|
||||
* dev kit, disabling for now.
|
||||
*/
|
||||
#undef MOZ_WINSDK_TARGETVER
|
||||
|
||||
/**
|
||||
* XXX below should be >= MOZ_NTDDI_WIN8 or such which is not defined yet
|
||||
*/
|
||||
|
@ -1,265 +1,265 @@
|
||||
aa.accept = false
|
||||
ab.accept = true
|
||||
ae.accept = false
|
||||
af.accept = true
|
||||
ak.accept = false
|
||||
am.accept = true
|
||||
an.accept = true
|
||||
ar.accept = true
|
||||
ar-ae.accept = true
|
||||
ar-bh.accept = true
|
||||
ar-dz.accept = true
|
||||
ar-eg.accept = true
|
||||
ar-iq.accept = true
|
||||
ar-jo.accept = true
|
||||
ar-kw.accept = true
|
||||
ar-lb.accept = true
|
||||
ar-ly.accept = true
|
||||
ar-ma.accept = true
|
||||
ar-om.accept = true
|
||||
ar-qa.accept = true
|
||||
ar-sa.accept = true
|
||||
ar-sy.accept = true
|
||||
ar-tn.accept = true
|
||||
ar-ye.accept = true
|
||||
as.accept = true
|
||||
ast.accept = true
|
||||
av.accept = false
|
||||
ay.accept = true
|
||||
az.accept = true
|
||||
ba.accept = false
|
||||
be.accept = true
|
||||
bg.accept = true
|
||||
bh.accept = false
|
||||
bi.accept = false
|
||||
bm.accept = false
|
||||
bn.accept = true
|
||||
bo.accept = true
|
||||
br.accept = true
|
||||
bs.accept = true
|
||||
ca.accept = true
|
||||
ce.accept = true
|
||||
ch.accept = true
|
||||
co.accept = true
|
||||
cr.accept = true
|
||||
cs.accept = true
|
||||
cu.accept = false
|
||||
cv.accept = true
|
||||
cy.accept = true
|
||||
da.accept = true
|
||||
de.accept = true
|
||||
de-at.accept = true
|
||||
de-ch.accept = true
|
||||
de-de.accept = true
|
||||
de-li.accept = true
|
||||
de-lu.accept = true
|
||||
dv.accept = false
|
||||
dz.accept = true
|
||||
ee.accept = false
|
||||
el.accept = true
|
||||
en.accept = true
|
||||
en-au.accept = true
|
||||
en-bz.accept = true
|
||||
en-ca.accept = true
|
||||
en-gb.accept = true
|
||||
en-ie.accept = true
|
||||
en-jm.accept = true
|
||||
en-nz.accept = true
|
||||
en-ph.accept = true
|
||||
en-tt.accept = true
|
||||
en-us.accept = true
|
||||
en-za.accept = true
|
||||
en-zw.accept = true
|
||||
eo.accept = true
|
||||
es.accept = true
|
||||
es-ar.accept = true
|
||||
es-bo.accept = true
|
||||
es-cl.accept = true
|
||||
es-co.accept = true
|
||||
es-cr.accept = true
|
||||
es-do.accept = true
|
||||
es-ec.accept = true
|
||||
es-es.accept = true
|
||||
es-gt.accept = true
|
||||
es-hn.accept = true
|
||||
es-mx.accept = true
|
||||
es-ni.accept = true
|
||||
es-pa.accept = true
|
||||
es-pe.accept = true
|
||||
es-pr.accept = true
|
||||
es-py.accept = true
|
||||
es-sv.accept = true
|
||||
es-uy.accept = true
|
||||
es-ve.accept = true
|
||||
et.accept = true
|
||||
eu.accept = true
|
||||
fa.accept = true
|
||||
fa-ir.accept = true
|
||||
ff.accept = false
|
||||
fi.accept = true
|
||||
fj.accept = true
|
||||
fo.accept = true
|
||||
fr.accept = true
|
||||
fr-be.accept = true
|
||||
fr-ca.accept = true
|
||||
fr-ch.accept = true
|
||||
fr-fr.accept = true
|
||||
fr-lu.accept = true
|
||||
fr-mc.accept = true
|
||||
fur.accept = true
|
||||
fy.accept = true
|
||||
ga.accept = true
|
||||
gd.accept = true
|
||||
gl.accept = true
|
||||
gn.accept = true
|
||||
gu.accept = true
|
||||
gv.accept = true
|
||||
ha.accept = false
|
||||
he.accept = true
|
||||
hi.accept = true
|
||||
ho.accept = false
|
||||
hsb.accept = true
|
||||
hr.accept = true
|
||||
ht.accept = true
|
||||
hu.accept = true
|
||||
hy.accept = true
|
||||
hz.accept = false
|
||||
ia.accept = true
|
||||
id.accept = true
|
||||
ie.accept = true
|
||||
ig.accept = false
|
||||
ii.accept = false
|
||||
ik.accept = false
|
||||
io.accept = false
|
||||
is.accept = true
|
||||
it.accept = true
|
||||
it-ch.accept = true
|
||||
iu.accept = true
|
||||
ja.accept = true
|
||||
jv.accept = false
|
||||
ka.accept = true
|
||||
kg.accept = false
|
||||
ki.accept = false
|
||||
kk.accept = true
|
||||
kl.accept = true
|
||||
km.accept = true
|
||||
kn.accept = true
|
||||
ko.accept = true
|
||||
ko-kp.accept = true
|
||||
ko-kr.accept = true
|
||||
kok.accept = true
|
||||
kr.accept = false
|
||||
ks.accept = true
|
||||
ku.accept = true
|
||||
kv.accept = false
|
||||
kw.accept = false
|
||||
ky.accept = true
|
||||
la.accept = true
|
||||
lb.accept = true
|
||||
lg.accept = false
|
||||
li.accept = false
|
||||
ln.accept = true
|
||||
lo.accept = false
|
||||
lt.accept = true
|
||||
lu.accept = false
|
||||
lv.accept = true
|
||||
mg.accept = true
|
||||
mh.accept = true
|
||||
mi.accept = true
|
||||
mk.accept = false
|
||||
mk-mk.accept = true
|
||||
ml.accept = true
|
||||
mn.accept = true
|
||||
mr.accept = true
|
||||
ms.accept = true
|
||||
mt.accept = true
|
||||
my.accept = true
|
||||
na.accept = true
|
||||
nb.accept = true
|
||||
nd.accept = true
|
||||
ne.accept = true
|
||||
ng.accept = true
|
||||
nl.accept = true
|
||||
nl-be.accept = true
|
||||
nn.accept = true
|
||||
no.accept = true
|
||||
nr.accept = true
|
||||
nso.accept = true
|
||||
nv.accept = true
|
||||
ny.accept = true
|
||||
oc.accept = true
|
||||
oj.accept = false
|
||||
om.accept = true
|
||||
or.accept = true
|
||||
os.accept = false
|
||||
pa.accept = true
|
||||
pa-in.accept = true
|
||||
pa-pk.accept = true
|
||||
pi.accept = false
|
||||
pl.accept = true
|
||||
ps.accept = true
|
||||
pt.accept = true
|
||||
pt-br.accept = true
|
||||
qu.accept = true
|
||||
rm.accept = true
|
||||
rn.accept = true
|
||||
ro.accept = true
|
||||
ro-md.accept = true
|
||||
ro-ro.accept = true
|
||||
ru.accept = true
|
||||
ru-md.accept = false
|
||||
rw.accept = true
|
||||
sa.accept = true
|
||||
sc.accept = true
|
||||
sd.accept = true
|
||||
sg.accept = true
|
||||
si.accept = true
|
||||
sk.accept = true
|
||||
sl.accept = true
|
||||
sm.accept = true
|
||||
so.accept = true
|
||||
aa.accept = true
|
||||
ab.accept = true
|
||||
ae.accept = true
|
||||
af.accept = true
|
||||
ak.accept = true
|
||||
am.accept = true
|
||||
an.accept = true
|
||||
ar.accept = true
|
||||
ar-ae.accept = true
|
||||
ar-bh.accept = true
|
||||
ar-dz.accept = true
|
||||
ar-eg.accept = true
|
||||
ar-iq.accept = true
|
||||
ar-jo.accept = true
|
||||
ar-kw.accept = true
|
||||
ar-lb.accept = true
|
||||
ar-ly.accept = true
|
||||
ar-ma.accept = true
|
||||
ar-om.accept = true
|
||||
ar-qa.accept = true
|
||||
ar-sa.accept = true
|
||||
ar-sy.accept = true
|
||||
ar-tn.accept = true
|
||||
ar-ye.accept = true
|
||||
as.accept = true
|
||||
ast.accept = true
|
||||
av.accept = true
|
||||
ay.accept = true
|
||||
az.accept = true
|
||||
ba.accept = true
|
||||
be.accept = true
|
||||
bg.accept = true
|
||||
bh.accept = true
|
||||
bi.accept = true
|
||||
bm.accept = true
|
||||
bn.accept = true
|
||||
bo.accept = true
|
||||
br.accept = true
|
||||
bs.accept = true
|
||||
ca.accept = true
|
||||
ce.accept = true
|
||||
ch.accept = true
|
||||
co.accept = true
|
||||
cr.accept = true
|
||||
cs.accept = true
|
||||
cu.accept = true
|
||||
cv.accept = true
|
||||
cy.accept = true
|
||||
da.accept = true
|
||||
de.accept = true
|
||||
de-at.accept = true
|
||||
de-ch.accept = true
|
||||
de-de.accept = true
|
||||
de-li.accept = true
|
||||
de-lu.accept = true
|
||||
dv.accept = true
|
||||
dz.accept = true
|
||||
ee.accept = true
|
||||
el.accept = true
|
||||
en.accept = true
|
||||
en-au.accept = true
|
||||
en-bz.accept = true
|
||||
en-ca.accept = true
|
||||
en-gb.accept = true
|
||||
en-ie.accept = true
|
||||
en-jm.accept = true
|
||||
en-nz.accept = true
|
||||
en-ph.accept = true
|
||||
en-tt.accept = true
|
||||
en-us.accept = true
|
||||
en-za.accept = true
|
||||
en-zw.accept = true
|
||||
eo.accept = true
|
||||
es.accept = true
|
||||
es-ar.accept = true
|
||||
es-bo.accept = true
|
||||
es-cl.accept = true
|
||||
es-co.accept = true
|
||||
es-cr.accept = true
|
||||
es-do.accept = true
|
||||
es-ec.accept = true
|
||||
es-es.accept = true
|
||||
es-gt.accept = true
|
||||
es-hn.accept = true
|
||||
es-mx.accept = true
|
||||
es-ni.accept = true
|
||||
es-pa.accept = true
|
||||
es-pe.accept = true
|
||||
es-pr.accept = true
|
||||
es-py.accept = true
|
||||
es-sv.accept = true
|
||||
es-uy.accept = true
|
||||
es-ve.accept = true
|
||||
et.accept = true
|
||||
eu.accept = true
|
||||
fa.accept = true
|
||||
fa-ir.accept = true
|
||||
ff.accept = true
|
||||
fi.accept = true
|
||||
fj.accept = true
|
||||
fo.accept = true
|
||||
fr.accept = true
|
||||
fr-be.accept = true
|
||||
fr-ca.accept = true
|
||||
fr-ch.accept = true
|
||||
fr-fr.accept = true
|
||||
fr-lu.accept = true
|
||||
fr-mc.accept = true
|
||||
fur.accept = true
|
||||
fy.accept = true
|
||||
ga.accept = true
|
||||
gd.accept = true
|
||||
gl.accept = true
|
||||
gn.accept = true
|
||||
gu.accept = true
|
||||
gv.accept = true
|
||||
ha.accept = true
|
||||
he.accept = true
|
||||
hi.accept = true
|
||||
ho.accept = true
|
||||
hsb.accept = true
|
||||
hr.accept = true
|
||||
ht.accept = true
|
||||
hu.accept = true
|
||||
hy.accept = true
|
||||
hz.accept = true
|
||||
ia.accept = true
|
||||
id.accept = true
|
||||
ie.accept = true
|
||||
ig.accept = true
|
||||
ii.accept = true
|
||||
ik.accept = true
|
||||
io.accept = true
|
||||
is.accept = true
|
||||
it.accept = true
|
||||
it-ch.accept = true
|
||||
iu.accept = true
|
||||
ja.accept = true
|
||||
jv.accept = true
|
||||
ka.accept = true
|
||||
kg.accept = true
|
||||
ki.accept = true
|
||||
kk.accept = true
|
||||
kl.accept = true
|
||||
km.accept = true
|
||||
kn.accept = true
|
||||
ko.accept = true
|
||||
ko-kp.accept = true
|
||||
ko-kr.accept = true
|
||||
kok.accept = true
|
||||
kr.accept = true
|
||||
ks.accept = true
|
||||
ku.accept = true
|
||||
kv.accept = true
|
||||
kw.accept = true
|
||||
ky.accept = true
|
||||
la.accept = true
|
||||
lb.accept = true
|
||||
lg.accept = true
|
||||
li.accept = true
|
||||
ln.accept = true
|
||||
lo.accept = true
|
||||
lt.accept = true
|
||||
lu.accept = true
|
||||
lv.accept = true
|
||||
mg.accept = true
|
||||
mh.accept = true
|
||||
mi.accept = true
|
||||
mk.accept = true
|
||||
mk-mk.accept = true
|
||||
ml.accept = true
|
||||
mn.accept = true
|
||||
mr.accept = true
|
||||
ms.accept = true
|
||||
mt.accept = true
|
||||
my.accept = true
|
||||
na.accept = true
|
||||
nb.accept = true
|
||||
nd.accept = true
|
||||
ne.accept = true
|
||||
ng.accept = true
|
||||
nl.accept = true
|
||||
nl-be.accept = true
|
||||
nn.accept = true
|
||||
no.accept = true
|
||||
nr.accept = true
|
||||
nso.accept = true
|
||||
nv.accept = true
|
||||
ny.accept = true
|
||||
oc.accept = true
|
||||
oj.accept = true
|
||||
om.accept = true
|
||||
or.accept = true
|
||||
os.accept = true
|
||||
pa.accept = true
|
||||
pa-in.accept = true
|
||||
pa-pk.accept = true
|
||||
pi.accept = true
|
||||
pl.accept = true
|
||||
ps.accept = true
|
||||
pt.accept = true
|
||||
pt-br.accept = true
|
||||
qu.accept = true
|
||||
rm.accept = true
|
||||
rn.accept = true
|
||||
ro.accept = true
|
||||
ro-md.accept = true
|
||||
ro-ro.accept = true
|
||||
ru.accept = true
|
||||
ru-md.accept = true
|
||||
rw.accept = true
|
||||
sa.accept = true
|
||||
sc.accept = true
|
||||
sd.accept = true
|
||||
sg.accept = true
|
||||
si.accept = true
|
||||
sk.accept = true
|
||||
sl.accept = true
|
||||
sm.accept = true
|
||||
so.accept = true
|
||||
son-ml.accept = true
|
||||
sq.accept = true
|
||||
sr.accept = true
|
||||
ss.accept = true
|
||||
st.accept = true
|
||||
su.accept = false
|
||||
sv.accept = true
|
||||
sv-fi.accept = true
|
||||
sv-se.accept = true
|
||||
sw.accept = true
|
||||
ta.accept = true
|
||||
te.accept = true
|
||||
tg.accept = false
|
||||
th.accept = true
|
||||
ti.accept = true
|
||||
tig.accept = true
|
||||
tk.accept = true
|
||||
tl.accept = true
|
||||
tlh.accept = true
|
||||
tn.accept = true
|
||||
to.accept = true
|
||||
tr.accept = true
|
||||
ts.accept = true
|
||||
tt.accept = true
|
||||
tw.accept = false
|
||||
ty.accept = false
|
||||
ug.accept = false
|
||||
uk.accept = true
|
||||
ur.accept = true
|
||||
uz.accept = false
|
||||
ve.accept = true
|
||||
vi.accept = true
|
||||
vo.accept = true
|
||||
wa.accept = true
|
||||
wo.accept = true
|
||||
xh.accept = true
|
||||
yi.accept = true
|
||||
yo.accept = false
|
||||
za.accept = false
|
||||
zh.accept = true
|
||||
zh-cn.accept = true
|
||||
zh-hk.accept = true
|
||||
zh-sg.accept = true
|
||||
zh-tw.accept = true
|
||||
zu.accept = true
|
||||
sq.accept = true
|
||||
sr.accept = true
|
||||
ss.accept = true
|
||||
st.accept = true
|
||||
su.accept = true
|
||||
sv.accept = true
|
||||
sv-fi.accept = true
|
||||
sv-se.accept = true
|
||||
sw.accept = true
|
||||
ta.accept = true
|
||||
te.accept = true
|
||||
tg.accept = true
|
||||
th.accept = true
|
||||
ti.accept = true
|
||||
tig.accept = true
|
||||
tk.accept = true
|
||||
tl.accept = true
|
||||
tlh.accept = true
|
||||
tn.accept = true
|
||||
to.accept = true
|
||||
tr.accept = true
|
||||
ts.accept = true
|
||||
tt.accept = true
|
||||
tw.accept = true
|
||||
ty.accept = true
|
||||
ug.accept = true
|
||||
uk.accept = true
|
||||
ur.accept = true
|
||||
uz.accept = true
|
||||
ve.accept = true
|
||||
vi.accept = true
|
||||
vo.accept = true
|
||||
wa.accept = true
|
||||
wo.accept = true
|
||||
xh.accept = true
|
||||
yi.accept = true
|
||||
yo.accept = true
|
||||
za.accept = true
|
||||
zh.accept = true
|
||||
zh-cn.accept = true
|
||||
zh-hk.accept = true
|
||||
zh-sg.accept = true
|
||||
zh-tw.accept = true
|
||||
zu.accept = true
|
||||
|
@ -967,22 +967,6 @@ EmitRegExp(JSContext *cx, uint32_t index, BytecodeEmitter *bce)
|
||||
return EmitIndex32(cx, JSOP_REGEXP, index, bce);
|
||||
}
|
||||
|
||||
static bool
|
||||
EmitSlotObjectOp(JSContext *cx, JSOp op, unsigned slot, uint32_t index, BytecodeEmitter *bce)
|
||||
{
|
||||
JS_ASSERT(JOF_OPTYPE(op) == JOF_SLOTOBJECT);
|
||||
|
||||
ptrdiff_t off = EmitN(cx, bce, op, SLOTNO_LEN + UINT32_INDEX_LEN);
|
||||
if (off < 0)
|
||||
return false;
|
||||
|
||||
jsbytecode *pc = bce->code(off);
|
||||
SET_SLOTNO(pc, slot);
|
||||
pc += SLOTNO_LEN;
|
||||
SET_UINT32_INDEX(pc, index);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
EmitArguments(JSContext *cx, BytecodeEmitter *bce)
|
||||
{
|
||||
@ -4581,43 +4565,6 @@ EmitWith(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||
return PopStatementBCE(cx, bce);
|
||||
}
|
||||
|
||||
static bool
|
||||
SetMethodFunction(JSContext *cx, FunctionBox *funbox, JSAtom *atom)
|
||||
{
|
||||
RootedVarObject parent(cx);
|
||||
parent = funbox->function()->getParent();
|
||||
|
||||
/*
|
||||
* Replace a boxed function with a new one with a method atom. Methods
|
||||
* require a function with the extended size finalize kind, which normal
|
||||
* functions don't have. We don't eagerly allocate functions with the
|
||||
* expanded size for boxed functions, as most functions are not methods.
|
||||
*/
|
||||
JSFunction *fun = js_NewFunction(cx, NULL, NULL,
|
||||
funbox->function()->nargs,
|
||||
funbox->function()->flags,
|
||||
parent,
|
||||
funbox->function()->atom,
|
||||
JSFunction::ExtendedFinalizeKind);
|
||||
if (!fun)
|
||||
return false;
|
||||
|
||||
JSScript *script = funbox->function()->script();
|
||||
if (script) {
|
||||
fun->setScript(script);
|
||||
if (!script->typeSetFunction(cx, fun))
|
||||
return false;
|
||||
}
|
||||
|
||||
JS_ASSERT(funbox->function()->joinable());
|
||||
fun->setJoinable();
|
||||
|
||||
fun->setMethodAtom(atom);
|
||||
|
||||
funbox->object = fun;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
EmitForIn(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
|
||||
{
|
||||
@ -5054,7 +5001,14 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return EmitSlotObjectOp(cx, JSOP_DEFLOCALFUN, slot, index, bce);
|
||||
|
||||
if (NewSrcNote(cx, bce, SRC_CONTINUE) < 0)
|
||||
return false;
|
||||
if (!EmitIndexOp(cx, JSOP_LAMBDA, index, bce))
|
||||
return false;
|
||||
EMIT_UINT16_IMM_OP(JSOP_SETLOCAL, slot);
|
||||
if (Emit1(cx, bce, JSOP_POP) < 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -5380,23 +5334,6 @@ EmitStatement(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||
}
|
||||
#endif
|
||||
if (op != JSOP_NOP) {
|
||||
/*
|
||||
* Specialize JSOP_SETPROP to JSOP_SETMETHOD to defer or
|
||||
* avoid null closure cloning. Do this only for assignment
|
||||
* statements that are not completion values wanted by a
|
||||
* script evaluator, to ensure that the joined function
|
||||
* can't escape directly.
|
||||
*/
|
||||
if (!wantval &&
|
||||
pn2->isKind(PNK_ASSIGN) &&
|
||||
pn2->pn_left->isOp(JSOP_SETPROP) &&
|
||||
pn2->pn_right->isOp(JSOP_LAMBDA) &&
|
||||
pn2->pn_right->pn_funbox->joinable())
|
||||
{
|
||||
if (!SetMethodFunction(cx, pn2->pn_right->pn_funbox, pn2->pn_left->pn_atom))
|
||||
return false;
|
||||
pn2->pn_left->setOp(JSOP_SETMETHOD);
|
||||
}
|
||||
if (!EmitTree(cx, bce, pn2))
|
||||
return false;
|
||||
if (Emit1(cx, bce, op) < 0)
|
||||
@ -5903,28 +5840,13 @@ EmitObject(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||
if (!bce->makeAtomIndex(pn3->pn_atom, &index))
|
||||
return false;
|
||||
|
||||
/* Check whether we can optimize to JSOP_INITMETHOD. */
|
||||
ParseNode *init = pn2->pn_right;
|
||||
bool lambda = init->isOp(JSOP_LAMBDA);
|
||||
if (lambda)
|
||||
++methodInits;
|
||||
if (op == JSOP_INITPROP && lambda && init->pn_funbox->joinable()) {
|
||||
/*
|
||||
* Disable NEWOBJECT on initializers that set __proto__, which has
|
||||
* a non-standard setter on objects.
|
||||
*/
|
||||
if (pn3->pn_atom == cx->runtime->atomState.protoAtom)
|
||||
obj = NULL;
|
||||
op = JSOP_INITMETHOD;
|
||||
if (!SetMethodFunction(cx, init->pn_funbox, pn3->pn_atom))
|
||||
return JS_FALSE;
|
||||
pn2->setOp(op);
|
||||
} else {
|
||||
/*
|
||||
* Disable NEWOBJECT on initializers that set __proto__, which has
|
||||
* a non-standard setter on objects.
|
||||
*/
|
||||
if (pn3->pn_atom == cx->runtime->atomState.protoAtom)
|
||||
obj = NULL;
|
||||
op = JSOP_INITPROP;
|
||||
if (lambda)
|
||||
++slowMethodInits;
|
||||
}
|
||||
op = JSOP_INITPROP;
|
||||
|
||||
if (obj) {
|
||||
JS_ASSERT(!obj->inDictionaryMode());
|
||||
|
@ -161,126 +161,127 @@ struct StmtInfo {
|
||||
#define SET_STATEMENT_TOP(stmt, top) \
|
||||
((stmt)->update = (top), (stmt)->breaks = (stmt)->continues = (-1))
|
||||
|
||||
#define TCF_COMPILING 0x01 /* TreeContext is BytecodeEmitter */
|
||||
#define TCF_IN_FUNCTION 0x02 /* parsing inside function body */
|
||||
#define TCF_RETURN_EXPR 0x04 /* function has 'return expr;' */
|
||||
#define TCF_RETURN_VOID 0x08 /* function has 'return;' */
|
||||
#define TCF_IN_FOR_INIT 0x10 /* parsing init expr of for; exclude 'in' */
|
||||
#define TCF_FUN_SETS_OUTER_NAME 0x20 /* function set outer name (lexical or free) */
|
||||
#define TCF_FUN_PARAM_ARGUMENTS 0x40 /* function has parameter named arguments */
|
||||
#define TCF_FUN_LOCAL_ARGUMENTS 0x80 /* function may contain a local named arguments */
|
||||
#define TCF_FUN_USES_ARGUMENTS 0x100 /* function uses arguments except as a
|
||||
parameter name */
|
||||
#define TCF_FUN_HEAVYWEIGHT 0x200 /* function needs Call object per call */
|
||||
#define TCF_FUN_IS_GENERATOR 0x400 /* parsed yield statement in function */
|
||||
#define TCF_FUN_USES_OWN_NAME 0x800 /* named function expression that uses its
|
||||
own name */
|
||||
#define TCF_HAS_FUNCTION_STMT 0x1000 /* block contains a function statement */
|
||||
#define TCF_GENEXP_LAMBDA 0x2000 /* flag lambda from generator expression */
|
||||
#define TCF_COMPILE_N_GO 0x4000 /* compile-and-go mode of script, can
|
||||
optimize name references based on scope
|
||||
chain */
|
||||
#define TCF_NO_SCRIPT_RVAL 0x8000 /* API caller does not want result value
|
||||
from global script */
|
||||
/*
|
||||
* Set when parsing a declaration-like destructuring pattern. This
|
||||
* flag causes PrimaryExpr to create PN_NAME parse nodes for variable
|
||||
* references which are not hooked into any definition's use chain,
|
||||
* added to any tree context's AtomList, etc. etc. CheckDestructuring
|
||||
* will do that work later.
|
||||
*
|
||||
* The comments atop CheckDestructuring explain the distinction
|
||||
* between assignment-like and declaration-like destructuring
|
||||
* patterns, and why they need to be treated differently.
|
||||
*/
|
||||
#define TCF_DECL_DESTRUCTURING 0x10000
|
||||
JS_ENUM_HEADER(TreeContextFlags, uint32_t)
|
||||
{
|
||||
/* TreeContext is BytecodeEmitter */
|
||||
TCF_COMPILING = 0x1,
|
||||
|
||||
/*
|
||||
* This function/global/eval code body contained a Use Strict Directive. Treat
|
||||
* certain strict warnings as errors, and forbid the use of 'with'. See also
|
||||
* TSF_STRICT_MODE_CODE, JSScript::strictModeCode, and JSREPORT_STRICT_ERROR.
|
||||
*/
|
||||
#define TCF_STRICT_MODE_CODE 0x20000
|
||||
/* parsing inside function body */
|
||||
TCF_IN_FUNCTION = 0x2,
|
||||
|
||||
/* bits 0x40000 and 0x80000 are unused */
|
||||
/* function has 'return expr;' */
|
||||
TCF_RETURN_EXPR = 0x4,
|
||||
|
||||
/*
|
||||
* "Module pattern", i.e., a lambda that is immediately applied and the whole
|
||||
* of an expression statement.
|
||||
*/
|
||||
#define TCF_FUN_MODULE_PATTERN 0x200000
|
||||
/* function has 'return;' */
|
||||
TCF_RETURN_VOID = 0x8,
|
||||
|
||||
/*
|
||||
* Flag to prevent a non-escaping function from being optimized into a null
|
||||
* closure (i.e., a closure that needs only its global object for free variable
|
||||
* resolution), because this function contains a closure that needs one or more
|
||||
* scope objects surrounding it (i.e., a Call object for an outer heavyweight
|
||||
* function). See bug 560234.
|
||||
*/
|
||||
#define TCF_FUN_ENTRAINS_SCOPES 0x400000
|
||||
/* parsing init expr of for; exclude 'in' */
|
||||
TCF_IN_FOR_INIT = 0x10,
|
||||
|
||||
/* The function calls 'eval'. */
|
||||
#define TCF_FUN_CALLS_EVAL 0x800000
|
||||
/* function has parameter named arguments */
|
||||
TCF_FUN_PARAM_ARGUMENTS = 0x20,
|
||||
|
||||
/* The function mutates a positional (non-destructuring) parameter. */
|
||||
#define TCF_FUN_MUTATES_PARAMETER 0x1000000
|
||||
/* function may contain a local named arguments */
|
||||
TCF_FUN_LOCAL_ARGUMENTS = 0x40,
|
||||
|
||||
/*
|
||||
* Compiling an eval() script.
|
||||
*/
|
||||
#define TCF_COMPILE_FOR_EVAL 0x2000000
|
||||
/* function uses arguments except as a parameter name */
|
||||
TCF_FUN_USES_ARGUMENTS = 0x80,
|
||||
|
||||
/*
|
||||
* The function or a function that encloses it may define new local names
|
||||
* at runtime through means other than calling eval.
|
||||
*/
|
||||
#define TCF_FUN_MIGHT_ALIAS_LOCALS 0x4000000
|
||||
/* function needs Call object per call */
|
||||
TCF_FUN_HEAVYWEIGHT = 0x100,
|
||||
|
||||
/*
|
||||
* The script contains singleton initialiser JSOP_OBJECT.
|
||||
*/
|
||||
#define TCF_HAS_SINGLETONS 0x8000000
|
||||
/* parsed yield statement in function */
|
||||
TCF_FUN_IS_GENERATOR = 0x200,
|
||||
|
||||
/*
|
||||
* Some enclosing scope is a with-statement or E4X filter-expression.
|
||||
*/
|
||||
#define TCF_IN_WITH 0x10000000
|
||||
/* named function expression that uses its own name */
|
||||
TCF_FUN_USES_OWN_NAME = 0x400,
|
||||
|
||||
/*
|
||||
* This function does something that can extend the set of bindings in its
|
||||
* call objects --- it does a direct eval in non-strict code, or includes a
|
||||
* function statement (as opposed to a function definition).
|
||||
*
|
||||
* This flag is *not* inherited by enclosed or enclosing functions; it
|
||||
* applies only to the function in whose flags it appears.
|
||||
*/
|
||||
#define TCF_FUN_EXTENSIBLE_SCOPE 0x20000000
|
||||
/* block contains a function statement */
|
||||
TCF_HAS_FUNCTION_STMT = 0x800,
|
||||
|
||||
/*
|
||||
* The caller is JS_Compile*Script*.
|
||||
*/
|
||||
#define TCF_NEED_SCRIPT_GLOBAL 0x40000000
|
||||
/* flag lambda from generator expression */
|
||||
TCF_GENEXP_LAMBDA = 0x1000,
|
||||
|
||||
/*
|
||||
* Flags to check for return; vs. return expr; in a function.
|
||||
*/
|
||||
#define TCF_RETURN_FLAGS (TCF_RETURN_EXPR | TCF_RETURN_VOID)
|
||||
/* script can optimize name references based on scope chain */
|
||||
TCF_COMPILE_N_GO = 0x2000,
|
||||
|
||||
/* API caller does not want result value from global script */
|
||||
TCF_NO_SCRIPT_RVAL = 0x4000,
|
||||
|
||||
/*
|
||||
* Set when parsing a declaration-like destructuring pattern. This flag
|
||||
* causes PrimaryExpr to create PN_NAME parse nodes for variable references
|
||||
* which are not hooked into any definition's use chain, added to any tree
|
||||
* context's AtomList, etc. etc. CheckDestructuring will do that work
|
||||
* later.
|
||||
*
|
||||
* The comments atop CheckDestructuring explain the distinction between
|
||||
* assignment-like and declaration-like destructuring patterns, and why
|
||||
* they need to be treated differently.
|
||||
*/
|
||||
TCF_DECL_DESTRUCTURING = 0x8000,
|
||||
|
||||
/*
|
||||
* This function/global/eval code body contained a Use Strict Directive.
|
||||
* Treat certain strict warnings as errors, and forbid the use of 'with'.
|
||||
* See also TSF_STRICT_MODE_CODE, JSScript::strictModeCode, and
|
||||
* JSREPORT_STRICT_ERROR.
|
||||
*/
|
||||
TCF_STRICT_MODE_CODE = 0x10000,
|
||||
|
||||
/* The function calls 'eval'. */
|
||||
TCF_FUN_CALLS_EVAL = 0x20000,
|
||||
|
||||
/* The function mutates a positional (non-destructuring) parameter. */
|
||||
TCF_FUN_MUTATES_PARAMETER = 0x40000,
|
||||
|
||||
/* Compiling an eval() script. */
|
||||
TCF_COMPILE_FOR_EVAL = 0x100000,
|
||||
|
||||
/*
|
||||
* The function or a function that encloses it may define new local names
|
||||
* at runtime through means other than calling eval.
|
||||
*/
|
||||
TCF_FUN_MIGHT_ALIAS_LOCALS = 0x200000,
|
||||
|
||||
/* The script contains singleton initialiser JSOP_OBJECT. */
|
||||
TCF_HAS_SINGLETONS = 0x400000,
|
||||
|
||||
/* Some enclosing scope is a with-statement or E4X filter-expression. */
|
||||
TCF_IN_WITH = 0x800000,
|
||||
|
||||
/*
|
||||
* This function does something that can extend the set of bindings in its
|
||||
* call objects --- it does a direct eval in non-strict code, or includes a
|
||||
* function statement (as opposed to a function definition).
|
||||
*
|
||||
* This flag is *not* inherited by enclosed or enclosing functions; it
|
||||
* applies only to the function in whose flags it appears.
|
||||
*/
|
||||
TCF_FUN_EXTENSIBLE_SCOPE = 0x1000000,
|
||||
|
||||
/* The caller is JS_Compile*Script*. */
|
||||
TCF_NEED_SCRIPT_GLOBAL = 0x2000000
|
||||
|
||||
} JS_ENUM_FOOTER(TreeContextFlags);
|
||||
|
||||
/* Flags to check for return; vs. return expr; in a function. */
|
||||
static const uint32_t TCF_RETURN_FLAGS = TCF_RETURN_EXPR | TCF_RETURN_VOID;
|
||||
|
||||
/*
|
||||
* Sticky deoptimization flags to propagate from FunctionBody.
|
||||
*/
|
||||
#define TCF_FUN_FLAGS (TCF_FUN_SETS_OUTER_NAME | \
|
||||
TCF_FUN_USES_ARGUMENTS | \
|
||||
TCF_FUN_PARAM_ARGUMENTS | \
|
||||
TCF_FUN_LOCAL_ARGUMENTS | \
|
||||
TCF_FUN_HEAVYWEIGHT | \
|
||||
TCF_FUN_IS_GENERATOR | \
|
||||
TCF_FUN_USES_OWN_NAME | \
|
||||
TCF_FUN_CALLS_EVAL | \
|
||||
TCF_FUN_MIGHT_ALIAS_LOCALS | \
|
||||
TCF_FUN_MUTATES_PARAMETER | \
|
||||
TCF_STRICT_MODE_CODE | \
|
||||
TCF_FUN_EXTENSIBLE_SCOPE)
|
||||
static const uint32_t TCF_FUN_FLAGS = TCF_FUN_USES_ARGUMENTS |
|
||||
TCF_FUN_PARAM_ARGUMENTS |
|
||||
TCF_FUN_LOCAL_ARGUMENTS |
|
||||
TCF_FUN_HEAVYWEIGHT |
|
||||
TCF_FUN_IS_GENERATOR |
|
||||
TCF_FUN_USES_OWN_NAME |
|
||||
TCF_FUN_CALLS_EVAL |
|
||||
TCF_FUN_MIGHT_ALIAS_LOCALS |
|
||||
TCF_FUN_MUTATES_PARAMETER |
|
||||
TCF_STRICT_MODE_CODE |
|
||||
TCF_FUN_EXTENSIBLE_SCOPE;
|
||||
|
||||
struct BytecodeEmitter;
|
||||
|
||||
@ -443,14 +444,16 @@ struct TreeContext { /* tree context for semantic checks */
|
||||
flags & (TCF_FUN_PARAM_ARGUMENTS | TCF_FUN_LOCAL_ARGUMENTS));
|
||||
}
|
||||
|
||||
void noteLocalOverwritesArguments() {
|
||||
flags |= TCF_FUN_LOCAL_ARGUMENTS;
|
||||
}
|
||||
|
||||
void noteArgumentsNameUse(ParseNode *node) {
|
||||
JS_ASSERT(inFunction());
|
||||
JS_ASSERT(node->isKind(PNK_NAME));
|
||||
JS_ASSERT(node->pn_atom == parser->context->runtime->atomState.argumentsAtom);
|
||||
countArgumentsUse(node);
|
||||
flags |= TCF_FUN_USES_ARGUMENTS;
|
||||
if (funbox)
|
||||
funbox->node->pn_dflags |= PND_FUNARG;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -108,15 +108,6 @@ ParseNode::clear()
|
||||
pn_parens = false;
|
||||
}
|
||||
|
||||
bool
|
||||
FunctionBox::joinable() const
|
||||
{
|
||||
return function()->isNullClosure() &&
|
||||
(tcflags & (TCF_FUN_USES_ARGUMENTS |
|
||||
TCF_FUN_USES_OWN_NAME |
|
||||
TCF_COMPILE_N_GO)) == TCF_COMPILE_N_GO;
|
||||
}
|
||||
|
||||
bool
|
||||
FunctionBox::inAnyDynamicScope() const
|
||||
{
|
||||
|
@ -765,15 +765,14 @@ struct ParseNode {
|
||||
#define PND_GVAR 0x40 /* gvar binding, can't close over
|
||||
because it could be deleted */
|
||||
#define PND_PLACEHOLDER 0x80 /* placeholder definition for lexdep */
|
||||
#define PND_FUNARG 0x100 /* downward or upward funarg usage */
|
||||
#define PND_BOUND 0x200 /* bound to a stack or global slot */
|
||||
#define PND_DEOPTIMIZED 0x400 /* former pn_used name node, pn_lexdef
|
||||
#define PND_BOUND 0x100 /* bound to a stack or global slot */
|
||||
#define PND_DEOPTIMIZED 0x200 /* former pn_used name node, pn_lexdef
|
||||
still valid, but this use no longer
|
||||
optimizable via an upvar opcode */
|
||||
#define PND_CLOSED 0x800 /* variable is closed over */
|
||||
#define PND_CLOSED 0x400 /* variable is closed over */
|
||||
|
||||
/* Flags to propagate from uses to definition. */
|
||||
#define PND_USE2DEF_FLAGS (PND_ASSIGNED | PND_FUNARG | PND_CLOSED)
|
||||
#define PND_USE2DEF_FLAGS (PND_ASSIGNED | PND_CLOSED)
|
||||
|
||||
/* PN_LIST pn_xflags bits. */
|
||||
#define PNX_STRCAT 0x01 /* PNK_ADD list has string term */
|
||||
@ -816,7 +815,6 @@ struct ParseNode {
|
||||
bool isPlaceholder() const { return test(PND_PLACEHOLDER); }
|
||||
bool isDeoptimized() const { return test(PND_DEOPTIMIZED); }
|
||||
bool isAssigned() const { return test(PND_ASSIGNED); }
|
||||
bool isFunArg() const { return test(PND_FUNARG); }
|
||||
bool isClosed() const { return test(PND_CLOSED); }
|
||||
|
||||
/*
|
||||
@ -833,9 +831,6 @@ struct ParseNode {
|
||||
*/
|
||||
bool isTopLevel() const { return test(PND_TOPLEVEL); }
|
||||
|
||||
/* Defined below, see after struct Definition. */
|
||||
void setFunArg();
|
||||
|
||||
void become(ParseNode *pn2);
|
||||
void clear();
|
||||
|
||||
@ -1431,26 +1426,6 @@ void DumpParseTree(ParseNode *pn, int indent = 0);
|
||||
* When the compiler unwinds from the outermost tc, tc->lexdeps contains the
|
||||
* definition nodes with use chains for all free variables. These are either
|
||||
* global variables or reference errors.
|
||||
*
|
||||
* We analyze whether a binding is initialized, whether the bound names is ever
|
||||
* assigned apart from its initializer, and if the bound name definition or use
|
||||
* is in a direct child of a block. These PND_* flags allow a subset dominance
|
||||
* computation telling whether an initialized var dominates its uses. An inner
|
||||
* function using only such outer vars (and formal parameters) can be optimized
|
||||
* into a flat closure. See JSOP_{GET,CALL}DSLOT.
|
||||
*
|
||||
* Another important subset dominance relation: ... { var x = ...; ... x ... }
|
||||
* where x is not assigned after initialization and not used outside the block.
|
||||
* This style is common in the absence of 'let'. Even though the var x is not
|
||||
* at top level, we can tell its initialization dominates all uses cheaply,
|
||||
* because the above one-pass algorithm sees the definition before any uses,
|
||||
* and because all uses are contained in the same block as the definition.
|
||||
*
|
||||
* We also analyze function uses to flag upward/downward funargs. If a lambda
|
||||
* post-dominates each of its upvars' sole, inevitable (i.e. not hidden behind
|
||||
* conditions or within loops or the like) initialization or assignment; then
|
||||
* we can optimize the lambda as a flat closure (after Chez Scheme's display
|
||||
* closures).
|
||||
*/
|
||||
#define dn_uses pn_link
|
||||
|
||||
@ -1528,7 +1503,7 @@ ParseNode::test(unsigned flag) const
|
||||
{
|
||||
JS_ASSERT(pn_defn || pn_arity == PN_FUNC || pn_arity == PN_NAME);
|
||||
#ifdef DEBUG
|
||||
if ((flag & (PND_ASSIGNED | PND_FUNARG)) && pn_defn && !(pn_dflags & flag)) {
|
||||
if ((flag & PND_ASSIGNED) && pn_defn && !(pn_dflags & flag)) {
|
||||
for (ParseNode *pn = ((Definition *) this)->dn_uses; pn; pn = pn->pn_link) {
|
||||
JS_ASSERT(!pn->pn_defn);
|
||||
JS_ASSERT(!(pn->pn_dflags & flag));
|
||||
@ -1538,25 +1513,6 @@ ParseNode::test(unsigned flag) const
|
||||
return !!(pn_dflags & flag);
|
||||
}
|
||||
|
||||
inline void
|
||||
ParseNode::setFunArg()
|
||||
{
|
||||
/*
|
||||
* pn_defn NAND pn_used must be true, per this chart:
|
||||
*
|
||||
* pn_defn pn_used
|
||||
* 0 0 anonymous function used implicitly, e.g. by
|
||||
* hidden yield in a genexp
|
||||
* 0 1 a use of a definition or placeholder
|
||||
* 1 0 a definition or placeholder
|
||||
* 1 1 error: this case must not be possible
|
||||
*/
|
||||
JS_ASSERT(!(pn_defn & pn_used));
|
||||
if (pn_used)
|
||||
pn_lexdef->pn_dflags |= PND_FUNARG;
|
||||
pn_dflags |= PND_FUNARG;
|
||||
}
|
||||
|
||||
inline void
|
||||
LinkUseToDef(ParseNode *pn, Definition *dn, TreeContext *tc)
|
||||
{
|
||||
@ -1598,8 +1554,6 @@ struct FunctionBox : public ObjectBox
|
||||
|
||||
JSFunction *function() const { return (JSFunction *) object; }
|
||||
|
||||
bool joinable() const;
|
||||
|
||||
/*
|
||||
* True if this function is inside the scope of a with-statement, an E4X
|
||||
* filter-expression, or a function that uses direct eval.
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user