Merge last green PGO from inbound to central

This commit is contained in:
Marco Bonardo 2012-03-29 17:37:31 +02:00
commit e7e2c4f5be
166 changed files with 3758 additions and 1886 deletions

View File

@ -85,50 +85,7 @@ public:
virtual nsAccessible* GetRootDocumentAccessible(nsIPresShell* aPresShell,
bool aCanCreate) = 0;
/**
* Creates accessible for the given DOM node or frame.
*/
virtual already_AddRefed<nsAccessible>
CreateHTMLBRAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
virtual already_AddRefed<nsAccessible>
CreateHTMLCaptionAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
virtual already_AddRefed<nsAccessible>
CreateHTMLCheckboxAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
virtual already_AddRefed<nsAccessible>
CreateHTMLComboboxAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
virtual already_AddRefed<nsAccessible>
CreateHTMLGroupboxAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
virtual already_AddRefed<nsAccessible>
CreateHTMLHRAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
virtual already_AddRefed<nsAccessible>
CreateHTMLImageAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
virtual already_AddRefed<nsAccessible>
CreateHTMLLabelAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
virtual already_AddRefed<nsAccessible>
CreateHTMLLIAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
virtual already_AddRefed<nsAccessible>
CreateHTMLListboxAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
virtual already_AddRefed<nsAccessible>
CreateHTMLMediaAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
virtual already_AddRefed<nsAccessible>
CreateHTMLObjectFrameAccessible(nsObjectFrame* aFrame, nsIContent* aContent,
nsIPresShell* aPresShell) = 0;
virtual already_AddRefed<nsAccessible>
CreateHTMLRadioButtonAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
virtual already_AddRefed<nsAccessible>
CreateHTMLTableAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
virtual already_AddRefed<nsAccessible>
CreateHTMLTableCellAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
virtual already_AddRefed<nsAccessible>
CreateHTMLTextAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
virtual already_AddRefed<nsAccessible>
CreateHTMLTextFieldAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
virtual already_AddRefed<nsAccessible>
CreateHyperTextAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
virtual already_AddRefed<nsAccessible>
CreateOuterDocAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
/**
/**
* Adds/remove ATK root accessible for gtk+ native window to/from children
* of the application accessible.
*/

View File

@ -116,12 +116,6 @@ void nsAccessNode::LastRelease()
////////////////////////////////////////////////////////////////////////////////
// nsAccessNode public
bool
nsAccessNode::IsDefunct() const
{
return !mContent;
}
bool
nsAccessNode::Init()
{
@ -218,7 +212,7 @@ void nsAccessNode::ShutdownXPAccessibility()
// nsAccessNode protected
nsPresContext* nsAccessNode::GetPresContext()
{
if (IsDefunct())
if (!mDoc)
return nsnull;
nsIPresShell* presShell(mDoc->PresShell());
@ -262,7 +256,7 @@ nsAccessNode::IsPrimaryForNode() const
void
nsAccessNode::ScrollTo(PRUint32 aScrollType)
{
if (IsDefunct())
if (!mDoc)
return;
nsIPresShell* shell = mDoc->PresShell();
@ -288,7 +282,7 @@ nsAccessNode::Language(nsAString& aLanguage)
{
aLanguage.Truncate();
if (IsDefunct())
if (!mDoc)
return;
nsCoreUtils::GetLanguageFor(mContent, nsnull, aLanguage);

View File

@ -105,11 +105,6 @@ public:
*/
virtual void Shutdown();
/**
* Returns true when the accessible is defunct.
*/
virtual bool IsDefunct() const;
/**
* Return frame for the given access node object.
*/

View File

@ -93,50 +93,50 @@ public:
bool aCanCreate);
already_AddRefed<nsAccessible>
CreateHTMLButtonAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
virtual already_AddRefed<nsAccessible>
already_AddRefed<nsAccessible>
CreateHTMLBRAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
already_AddRefed<nsAccessible>
CreateHTMLCanvasAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
virtual already_AddRefed<nsAccessible>
already_AddRefed<nsAccessible>
CreateHTMLCaptionAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
virtual already_AddRefed<nsAccessible>
already_AddRefed<nsAccessible>
CreateHTMLCheckboxAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
virtual already_AddRefed<nsAccessible>
already_AddRefed<nsAccessible>
CreateHTMLComboboxAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
already_AddRefed<nsAccessible>
CreateHTMLFileInputAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
virtual already_AddRefed<nsAccessible>
already_AddRefed<nsAccessible>
CreateHTMLGroupboxAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
virtual already_AddRefed<nsAccessible>
already_AddRefed<nsAccessible>
CreateHTMLHRAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
virtual already_AddRefed<nsAccessible>
already_AddRefed<nsAccessible>
CreateHTMLImageAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
already_AddRefed<nsAccessible>
CreateHTMLImageMapAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
virtual already_AddRefed<nsAccessible>
already_AddRefed<nsAccessible>
CreateHTMLLabelAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
virtual already_AddRefed<nsAccessible>
already_AddRefed<nsAccessible>
CreateHTMLLIAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
virtual already_AddRefed<nsAccessible>
already_AddRefed<nsAccessible>
CreateHTMLListboxAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
virtual already_AddRefed<nsAccessible>
already_AddRefed<nsAccessible>
CreateHTMLMediaAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
virtual already_AddRefed<nsAccessible>
already_AddRefed<nsAccessible>
CreateHTMLObjectFrameAccessible(nsObjectFrame* aFrame, nsIContent* aContent,
nsIPresShell* aPresShell);
virtual already_AddRefed<nsAccessible>
already_AddRefed<nsAccessible>
CreateHTMLRadioButtonAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
virtual already_AddRefed<nsAccessible>
already_AddRefed<nsAccessible>
CreateHTMLTableAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
virtual already_AddRefed<nsAccessible>
already_AddRefed<nsAccessible>
CreateHTMLTableCellAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
virtual already_AddRefed<nsAccessible>
already_AddRefed<nsAccessible>
CreateHTMLTextAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
virtual already_AddRefed<nsAccessible>
already_AddRefed<nsAccessible>
CreateHTMLTextFieldAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
virtual already_AddRefed<nsAccessible>
already_AddRefed<nsAccessible>
CreateHyperTextAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
virtual already_AddRefed<nsAccessible>
already_AddRefed<nsAccessible>
CreateOuterDocAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
virtual nsAccessible* AddNativeRootAccessible(void* aAtkAccessible);

View File

@ -2519,8 +2519,10 @@ nsAccessible::AppendTextTo(nsAString& aText, PRUint32 aStartOffset,
void
nsAccessible::Shutdown()
{
// Invalidate the child count and pointers to other accessibles, also make
// sure none of its children point to this parent
// Mark the accessible as defunct, invalidate the child count and pointers to
// other accessibles, also make sure none of its children point to this parent
mFlags |= eIsDefunct;
InvalidateChildren();
if (mParent)
mParent->RemoveChild(this);

View File

@ -643,6 +643,11 @@ public:
*/
static void TranslateString(const nsAString& aKey, nsAString& aStringOut);
/**
* Return true if the accessible is defunct.
*/
bool IsDefunct() const { return mFlags & eIsDefunct; }
protected:
//////////////////////////////////////////////////////////////////////////////
@ -687,25 +692,33 @@ protected:
{ mFlags = (mFlags & ~kChildrenFlagsMask) | aFlag; }
/**
* Flags describing the accessible itself.
* Flags used to describe the state of this accessible.
* @note keep these flags in sync with ChildrenFlags
*/
enum StateFlags {
eIsDefunct = 1 << 2 // accessible is defunct
};
/**
* Flags describing the type of this accessible.
* @note keep these flags in sync with ChildrenFlags and StateFlags
*/
enum AccessibleTypes {
eApplicationAccessible = 1 << 2,
eAutoCompleteAccessible = 1 << 3,
eAutoCompletePopupAccessible = 1 << 4,
eComboboxAccessible = 1 << 5,
eDocAccessible = 1 << 6,
eHyperTextAccessible = 1 << 7,
eHTMLFileInputAccessible = 1 << 8,
eHTMLListItemAccessible = 1 << 9,
eImageAccessible = 1 << 10,
eImageMapAccessible = 1 << 11,
eListControlAccessible = 1 << 12,
eMenuButtonAccessible = 1 << 13,
eMenuPopupAccessible = 1 << 14,
eRootAccessible = 1 << 15,
eTextLeafAccessible = 1 << 16
eApplicationAccessible = 1 << 3,
eAutoCompleteAccessible = 1 << 4,
eAutoCompletePopupAccessible = 1 << 5,
eComboboxAccessible = 1 << 6,
eDocAccessible = 1 << 7,
eHyperTextAccessible = 1 << 8,
eHTMLFileInputAccessible = 1 << 9,
eHTMLListItemAccessible = 1 << 10,
eImageAccessible = 1 << 11,
eImageMapAccessible = 1 << 12,
eListControlAccessible = 1 << 13,
eMenuButtonAccessible = 1 << 14,
eMenuPopupAccessible = 1 << 15,
eRootAccessible = 1 << 16,
eTextLeafAccessible = 1 << 17
};
//////////////////////////////////////////////////////////////////////////////

View File

@ -309,12 +309,6 @@ nsApplicationAccessible::GetPlatformVersion(nsAString& aVersion)
////////////////////////////////////////////////////////////////////////////////
// nsAccessNode public methods
bool
nsApplicationAccessible::IsDefunct() const
{
return nsAccessibilityService::IsShutdown();
}
bool
nsApplicationAccessible::Init()
{

View File

@ -98,7 +98,6 @@ public:
NS_DECL_NSIACCESSIBLEAPPLICATION
// nsAccessNode
virtual bool IsDefunct() const;
virtual bool Init();
virtual void Shutdown();
virtual bool IsPrimaryForNode() const;

View File

@ -693,12 +693,6 @@ nsDocAccessible::GetFrame() const
return root;
}
bool
nsDocAccessible::IsDefunct() const
{
return nsHyperTextAccessibleWrap::IsDefunct() || !mDocument;
}
// nsDocAccessible protected member
void nsDocAccessible::GetBoundsRect(nsRect& aBounds, nsIFrame** aRelativeFrame)
{

View File

@ -116,7 +116,6 @@ public:
virtual bool Init();
virtual void Shutdown();
virtual nsIFrame* GetFrame() const;
virtual bool IsDefunct() const;
virtual nsINode* GetNode() const { return mDocument; }
virtual nsIDocument* GetDocumentNode() const { return mDocument; }

View File

@ -215,10 +215,11 @@ __try{
*aNodeName = nsnull;
*aNodeValue = nsnull;
if (IsDefunct())
nsINode* node = GetNode();
if (!node)
return E_FAIL;
nsCOMPtr<nsIDOMNode> DOMNode(do_QueryInterface(GetNode()));
nsCOMPtr<nsIDOMNode> DOMNode(do_QueryInterface(node));
PRUint16 nodeType = 0;
DOMNode->GetNodeType(&nodeType);
@ -244,7 +245,7 @@ __try{
// data nodes in their internal object model.
*aUniqueID = - NS_PTR_TO_INT32(UniqueID());
*aNumChildren = GetNode()->GetChildCount();
*aNumChildren = node->GetChildCount();
} __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
return S_OK;
@ -262,7 +263,7 @@ STDMETHODIMP nsAccessNodeWrap::get_attributes(
__try{
*aNumAttribs = 0;
if (IsDefunct() || IsDocumentNode())
if (!mContent || IsDocumentNode())
return E_FAIL;
PRUint32 numAttribs = mContent->GetAttrCount();
@ -293,7 +294,7 @@ STDMETHODIMP nsAccessNodeWrap::get_attributesForNames(
/* [length_is][size_is][retval] */ BSTR __RPC_FAR *aAttribValues)
{
__try {
if (IsDefunct() || !IsElement())
if (!mContent || !IsElement())
return E_FAIL;
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(mContent));
@ -335,7 +336,7 @@ STDMETHODIMP nsAccessNodeWrap::get_computedStyle(
__try{
*aNumStyleProperties = 0;
if (IsDefunct() || IsDocumentNode())
if (!mContent || IsDocumentNode())
return E_FAIL;
nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl =
@ -370,7 +371,7 @@ STDMETHODIMP nsAccessNodeWrap::get_computedStyleForProperties(
/* [length_is][size_is][out] */ BSTR __RPC_FAR *aStyleValues)
{
__try {
if (IsDefunct() || IsDocumentNode())
if (!mContent || IsDocumentNode())
return E_FAIL;
nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl =
@ -442,10 +443,11 @@ nsAccessNodeWrap::MakeAccessNode(nsINode *aNode)
STDMETHODIMP nsAccessNodeWrap::get_parentNode(ISimpleDOMNode __RPC_FAR *__RPC_FAR *aNode)
{
__try {
if (IsDefunct())
nsINode* node = GetNode();
if (!node)
return E_FAIL;
*aNode = MakeAccessNode(GetNode()->GetNodeParent());
*aNode = MakeAccessNode(node->GetNodeParent());
} __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
@ -455,10 +457,11 @@ __try {
STDMETHODIMP nsAccessNodeWrap::get_firstChild(ISimpleDOMNode __RPC_FAR *__RPC_FAR *aNode)
{
__try {
if (IsDefunct())
nsINode* node = GetNode();
if (!node)
return E_FAIL;
*aNode = MakeAccessNode(GetNode()->GetFirstChild());
*aNode = MakeAccessNode(node->GetFirstChild());
} __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
@ -468,10 +471,11 @@ __try {
STDMETHODIMP nsAccessNodeWrap::get_lastChild(ISimpleDOMNode __RPC_FAR *__RPC_FAR *aNode)
{
__try {
if (IsDefunct())
nsINode* node = GetNode();
if (!node)
return E_FAIL;
*aNode = MakeAccessNode(GetNode()->GetLastChild());
*aNode = MakeAccessNode(node->GetLastChild());
} __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
@ -481,10 +485,11 @@ __try {
STDMETHODIMP nsAccessNodeWrap::get_previousSibling(ISimpleDOMNode __RPC_FAR *__RPC_FAR *aNode)
{
__try {
if (IsDefunct())
nsINode* node = GetNode();
if (!node)
return E_FAIL;
*aNode = MakeAccessNode(GetNode()->GetPreviousSibling());
*aNode = MakeAccessNode(node->GetPreviousSibling());
} __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
@ -494,10 +499,11 @@ __try {
STDMETHODIMP nsAccessNodeWrap::get_nextSibling(ISimpleDOMNode __RPC_FAR *__RPC_FAR *aNode)
{
__try {
if (IsDefunct())
nsINode* node = GetNode();
if (!node)
return E_FAIL;
*aNode = MakeAccessNode(GetNode()->GetNextSibling());
*aNode = MakeAccessNode(node->GetNextSibling());
} __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
@ -511,10 +517,11 @@ nsAccessNodeWrap::get_childAt(unsigned aChildIndex,
__try {
*aNode = nsnull;
if (IsDefunct())
nsINode* node = GetNode();
if (!node)
return E_FAIL;
*aNode = MakeAccessNode(GetNode()->GetChildAt(aChildIndex));
*aNode = MakeAccessNode(node->GetChildAt(aChildIndex));
} __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }

View File

@ -124,6 +124,9 @@ nsXULTreeAccessible::NativeState()
state |= states::READONLY;
// multiselectable state.
if (!mTreeView)
return state;
nsCOMPtr<nsITreeSelection> selection;
mTreeView->GetSelection(getter_AddRefs(selection));
NS_ENSURE_TRUE(selection, state);
@ -145,7 +148,7 @@ nsXULTreeAccessible::GetValue(nsAString& aValue)
aValue.Truncate();
if (IsDefunct())
if (IsDefunct() || !mTreeView)
return NS_ERROR_FAILURE;
nsCOMPtr<nsITreeSelection> selection;
@ -173,12 +176,6 @@ nsXULTreeAccessible::GetValue(nsAString& aValue)
////////////////////////////////////////////////////////////////////////////////
// nsXULTreeAccessible: nsAccessNode implementation
bool
nsXULTreeAccessible::IsDefunct() const
{
return nsAccessibleWrap::IsDefunct() || !mTree || !mTreeView;
}
void
nsXULTreeAccessible::Shutdown()
{
@ -270,6 +267,9 @@ nsXULTreeAccessible::IsSelect()
nsAccessible*
nsXULTreeAccessible::CurrentItem()
{
if (!mTreeView)
return nsnull;
nsCOMPtr<nsITreeSelection> selection;
mTreeView->GetSelection(getter_AddRefs(selection));
if (selection) {
@ -291,6 +291,9 @@ nsXULTreeAccessible::SetCurrentItem(nsAccessible* aItem)
already_AddRefed<nsIArray>
nsXULTreeAccessible::SelectedItems()
{
if (!mTreeView)
return nsnull;
nsCOMPtr<nsITreeSelection> selection;
mTreeView->GetSelection(getter_AddRefs(selection));
if (!selection)
@ -321,6 +324,9 @@ nsXULTreeAccessible::SelectedItems()
PRUint32
nsXULTreeAccessible::SelectedItemCount()
{
if (!mTreeView)
return 0;
nsCOMPtr<nsITreeSelection> selection;
mTreeView->GetSelection(getter_AddRefs(selection));
if (selection) {
@ -335,6 +341,9 @@ nsXULTreeAccessible::SelectedItemCount()
bool
nsXULTreeAccessible::AddItemToSelection(PRUint32 aIndex)
{
if (!mTreeView)
return false;
nsCOMPtr<nsITreeSelection> selection;
mTreeView->GetSelection(getter_AddRefs(selection));
if (selection) {
@ -351,6 +360,9 @@ nsXULTreeAccessible::AddItemToSelection(PRUint32 aIndex)
bool
nsXULTreeAccessible::RemoveItemFromSelection(PRUint32 aIndex)
{
if (!mTreeView)
return false;
nsCOMPtr<nsITreeSelection> selection;
mTreeView->GetSelection(getter_AddRefs(selection));
if (selection) {
@ -367,6 +379,9 @@ nsXULTreeAccessible::RemoveItemFromSelection(PRUint32 aIndex)
bool
nsXULTreeAccessible::IsItemSelected(PRUint32 aIndex)
{
if (!mTreeView)
return false;
nsCOMPtr<nsITreeSelection> selection;
mTreeView->GetSelection(getter_AddRefs(selection));
if (selection) {
@ -380,6 +395,9 @@ nsXULTreeAccessible::IsItemSelected(PRUint32 aIndex)
bool
nsXULTreeAccessible::UnselectAll()
{
if (!mTreeView)
return false;
nsCOMPtr<nsITreeSelection> selection;
mTreeView->GetSelection(getter_AddRefs(selection));
if (!selection)
@ -392,6 +410,9 @@ nsXULTreeAccessible::UnselectAll()
nsAccessible*
nsXULTreeAccessible::GetSelectedItem(PRUint32 aIndex)
{
if (!mTreeView)
return nsnull;
nsCOMPtr<nsITreeSelection> selection;
mTreeView->GetSelection(getter_AddRefs(selection));
if (!selection)
@ -418,6 +439,9 @@ bool
nsXULTreeAccessible::SelectAll()
{
// see if we are multiple select if so set ourselves as such
if (!mTreeView)
return false;
nsCOMPtr<nsITreeSelection> selection;
mTreeView->GetSelection(getter_AddRefs(selection));
if (selection) {
@ -453,8 +477,8 @@ nsXULTreeAccessible::GetChildCount()
{
// tree's children count is row count + treecols count.
PRInt32 childCount = nsAccessible::GetChildCount();
if (childCount == -1)
return -1;
if (childCount == -1 || !mTreeView)
return childCount;
PRInt32 rowCount = 0;
mTreeView->GetRowCount(&rowCount);
@ -536,7 +560,7 @@ nsXULTreeAccessible::ContainerWidget() const
nsAccessible*
nsXULTreeAccessible::GetTreeItemAccessible(PRInt32 aRow)
{
if (aRow < 0 || IsDefunct())
if (aRow < 0 || IsDefunct() || !mTreeView)
return nsnull;
PRInt32 rowCount = 0;
@ -793,7 +817,7 @@ nsXULTreeItemAccessibleBase::GetBounds(PRInt32 *aX, PRInt32 *aY,
NS_IMETHODIMP
nsXULTreeItemAccessibleBase::SetSelected(bool aSelect)
{
if (IsDefunct())
if (IsDefunct() || !mTreeView)
return NS_ERROR_FAILURE;
nsCOMPtr<nsITreeSelection> selection;
@ -811,7 +835,7 @@ nsXULTreeItemAccessibleBase::SetSelected(bool aSelect)
NS_IMETHODIMP
nsXULTreeItemAccessibleBase::TakeFocus()
{
if (IsDefunct())
if (IsDefunct() || !mTreeView)
return NS_ERROR_FAILURE;
nsCOMPtr<nsITreeSelection> selection;
@ -826,10 +850,13 @@ nsXULTreeItemAccessibleBase::TakeFocus()
Relation
nsXULTreeItemAccessibleBase::RelationByType(PRUint32 aType)
{
if (!mTreeView)
return Relation();
if (aType != nsIAccessibleRelation::RELATION_NODE_CHILD_OF)
return Relation();
PRInt32 parentIndex;
PRInt32 parentIndex = -1;
if (!NS_SUCCEEDED(mTreeView->GetParentIndex(mRow, &parentIndex)))
return Relation();
@ -890,12 +917,6 @@ nsXULTreeItemAccessibleBase::DoAction(PRUint8 aIndex)
////////////////////////////////////////////////////////////////////////////////
// nsXULTreeItemAccessibleBase: nsAccessNode implementation
bool
nsXULTreeItemAccessibleBase::IsDefunct() const
{
return nsAccessibleWrap::IsDefunct() || !mTree || !mTreeView || mRow < 0;
}
void
nsXULTreeItemAccessibleBase::Shutdown()
{
@ -930,7 +951,7 @@ nsXULTreeItemAccessibleBase::GroupPosition(PRInt32 *aGroupLevel,
NS_ENSURE_ARG_POINTER(aPositionInGroup);
*aPositionInGroup = 0;
if (IsDefunct())
if (IsDefunct() || !mTreeView)
return NS_ERROR_FAILURE;
PRInt32 level;
@ -978,6 +999,9 @@ nsXULTreeItemAccessibleBase::GroupPosition(PRInt32 *aGroupLevel,
PRUint64
nsXULTreeItemAccessibleBase::NativeState()
{
if (!mTreeView)
return states::DEFUNCT;
// focusable and selectable states
PRUint64 state = states::FOCUSABLE | states::SELECTABLE;
@ -1075,6 +1099,9 @@ nsXULTreeItemAccessibleBase::GetSiblingAtOffset(PRInt32 aOffset,
bool
nsXULTreeItemAccessibleBase::IsExpandable()
{
if (!mTreeView)
return false;
bool isContainer = false;
mTreeView->IsContainer(mRow, &isContainer);
if (isContainer) {
@ -1100,6 +1127,9 @@ void
nsXULTreeItemAccessibleBase::GetCellName(nsITreeColumn* aColumn,
nsAString& aName)
{
if (!mTreeView)
return;
mTreeView->GetCellText(mRow, aColumn, aName);
// If there is still no name try the cell value:
@ -1164,12 +1194,6 @@ nsXULTreeItemAccessible::GetName(nsAString& aName)
////////////////////////////////////////////////////////////////////////////////
// nsXULTreeItemAccessible: nsAccessNode implementation
bool
nsXULTreeItemAccessible::IsDefunct() const
{
return nsXULTreeItemAccessibleBase::IsDefunct() || !mColumn;
}
bool
nsXULTreeItemAccessible::Init()
{

View File

@ -78,7 +78,6 @@ public:
NS_IMETHOD GetValue(nsAString& aValue);
// nsAccessNode
virtual bool IsDefunct() const;
virtual void Shutdown();
// nsAccessible
@ -204,7 +203,6 @@ public:
NS_IMETHOD DoAction(PRUint8 aIndex);
// nsAccessNode
virtual bool IsDefunct() const;
virtual void Shutdown();
virtual bool IsPrimaryForNode() const;
@ -287,7 +285,6 @@ public:
NS_IMETHOD GetName(nsAString& aName);
// nsAccessNode
virtual bool IsDefunct() const;
virtual bool Init();
virtual void Shutdown();

View File

@ -93,15 +93,18 @@ nsXULTreeGridAccessible::GetColumnCount(PRInt32 *aColumnCount)
}
NS_IMETHODIMP
nsXULTreeGridAccessible::GetRowCount(PRInt32 *arowCount)
nsXULTreeGridAccessible::GetRowCount(PRInt32* aRowCount)
{
NS_ENSURE_ARG_POINTER(arowCount);
*arowCount = nsnull;
NS_ENSURE_ARG_POINTER(aRowCount);
*aRowCount = 0;
if (IsDefunct())
return NS_ERROR_FAILURE;
return mTreeView->GetRowCount(arowCount);
if (!mTreeView)
return NS_OK;
return mTreeView->GetRowCount(aRowCount);
}
NS_IMETHODIMP
@ -176,6 +179,9 @@ nsXULTreeGridAccessible::GetSelectedCells(nsIArray **aCells)
NS_ENSURE_ARG_POINTER(aCells);
*aCells = nsnull;
if (!mTreeView)
return NS_OK;
nsCOMPtr<nsIMutableArray> selCells = do_CreateInstance(NS_ARRAY_CONTRACTID);
NS_ENSURE_TRUE(selCells, NS_ERROR_FAILURE);
@ -220,6 +226,9 @@ nsXULTreeGridAccessible::GetSelectedCellIndices(PRUint32 *aCellsCount,
NS_ENSURE_ARG_POINTER(aCells);
*aCells = nsnull;
if (!mTreeView)
return NS_OK;
PRInt32 selectedrowCount = 0;
nsresult rv = GetSelectionCount(&selectedrowCount);
NS_ENSURE_SUCCESS(rv, rv);
@ -309,6 +318,9 @@ nsXULTreeGridAccessible::GetSelectedRowIndices(PRUint32 *arowCount,
if (IsDefunct())
return NS_ERROR_FAILURE;
if (!mTreeView)
return NS_OK;
PRInt32 selectedrowCount = 0;
nsresult rv = GetSelectionCount(&selectedrowCount);
NS_ENSURE_SUCCESS(rv, rv);
@ -515,6 +527,9 @@ nsXULTreeGridAccessible::IsRowSelected(PRInt32 aRowIndex, bool *aIsSelected)
if (IsDefunct())
return NS_ERROR_FAILURE;
if (!mTreeView)
return NS_ERROR_INVALID_ARG;
nsCOMPtr<nsITreeSelection> selection;
nsresult rv = mTreeView->GetSelection(getter_AddRefs(selection));
NS_ENSURE_SUCCESS(rv, rv);
@ -532,6 +547,9 @@ nsXULTreeGridAccessible::IsCellSelected(PRInt32 aRowIndex, PRInt32 aColumnIndex,
NS_IMETHODIMP
nsXULTreeGridAccessible::SelectRow(PRInt32 aRowIndex)
{
if (!mTreeView)
return NS_ERROR_INVALID_ARG;
nsCOMPtr<nsITreeSelection> selection;
mTreeView->GetSelection(getter_AddRefs(selection));
NS_ENSURE_STATE(selection);
@ -548,6 +566,9 @@ nsXULTreeGridAccessible::SelectColumn(PRInt32 aColumnIndex)
NS_IMETHODIMP
nsXULTreeGridAccessible::UnselectRow(PRInt32 aRowIndex)
{
if (!mTreeView)
return NS_ERROR_INVALID_ARG;
nsCOMPtr<nsITreeSelection> selection;
mTreeView->GetSelection(getter_AddRefs(selection));
NS_ENSURE_STATE(selection);
@ -854,7 +875,7 @@ nsXULTreeGridCellAccessible::GetName(nsAString& aName)
{
aName.Truncate();
if (IsDefunct())
if (IsDefunct() || !mTreeView)
return NS_ERROR_FAILURE;
mTreeView->GetCellText(mRow, mColumn, aName);
@ -936,7 +957,7 @@ nsXULTreeGridCellAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
if (aIndex != eAction_Click)
return NS_ERROR_INVALID_ARG;
if (IsDefunct())
if (IsDefunct() || !mTreeView)
return NS_ERROR_FAILURE;
bool isCycler = false;
@ -1103,7 +1124,7 @@ nsXULTreeGridCellAccessible::IsSelected(bool *aIsSelected)
NS_ENSURE_ARG_POINTER(aIsSelected);
*aIsSelected = false;
if (IsDefunct())
if (IsDefunct() || !mTreeView)
return NS_ERROR_FAILURE;
nsCOMPtr<nsITreeSelection> selection;
@ -1116,17 +1137,10 @@ nsXULTreeGridCellAccessible::IsSelected(bool *aIsSelected)
////////////////////////////////////////////////////////////////////////////////
// nsXULTreeGridCellAccessible: nsAccessNode implementation
bool
nsXULTreeGridCellAccessible::IsDefunct() const
{
return nsLeafAccessible::IsDefunct() || !mParent || !mTree || !mTreeView ||
!mColumn;
}
bool
nsXULTreeGridCellAccessible::Init()
{
if (!nsLeafAccessible::Init())
if (!nsLeafAccessible::Init() || !mTreeView)
return false;
PRInt16 type;
@ -1196,6 +1210,9 @@ nsXULTreeGridCellAccessible::NativeRole()
PRUint64
nsXULTreeGridCellAccessible::NativeState()
{
if (!mTreeView)
return states::DEFUNCT;
// selectable/selected state
PRUint64 states = states::SELECTABLE;
@ -1255,6 +1272,9 @@ nsXULTreeGridCellAccessible::GetColumnIndex() const
void
nsXULTreeGridCellAccessible::CellInvalidated()
{
if (!mTreeView)
return;
nsAutoString textEquiv;
PRInt16 type;
@ -1326,6 +1346,9 @@ nsXULTreeGridCellAccessible::DispatchClickEvent(nsIContent *aContent,
bool
nsXULTreeGridCellAccessible::IsEditable() const
{
if (!mTreeView)
return false;
// XXX: logic corresponds to tree.xml, it's preferable to have interface
// method to check it.
bool isEditable = false;

View File

@ -161,7 +161,6 @@ public:
NS_DECL_NSIACCESSIBLETABLECELL
// nsAccessNode
virtual bool IsDefunct() const;
virtual bool Init();
virtual bool IsPrimaryForNode() const;

View File

@ -297,6 +297,8 @@
; JavaScript components
@BINPATH@/components/ConsoleAPI.manifest
@BINPATH@/components/ConsoleAPI.js
@BINPATH@/components/BrowserElementAPI.manifest
@BINPATH@/components/BrowserElementAPI.js
@BINPATH@/components/ContactManager.js
@BINPATH@/components/ContactManager.manifest
@BINPATH@/components/FeedProcessor.manifest

View File

@ -1,4 +1,4 @@
pref("startup.homepage_override_url","http://www.mozilla.org/projects/%APP%/%VERSION%/whatsnew/");
pref("startup.homepage_override_url","http://www.mozilla.org/projects/%APP%/%VERSION%/whatsnew/?oldversion=%OLD_VERSION%");
pref("startup.homepage_welcome_url","http://www.mozilla.org/projects/%APP%/%VERSION%/firstrun/");
// The time interval between checks for a new version (in seconds)
pref("app.update.interval", 3600); // 1 hour

View File

@ -1,4 +1,4 @@
pref("startup.homepage_override_url","http://www.mozilla.com/%LOCALE%/%APP%/%VERSION%/whatsnew/");
pref("startup.homepage_override_url","http://www.mozilla.com/%LOCALE%/%APP%/%VERSION%/whatsnew/?oldversion=%OLD_VERSION%");
pref("startup.homepage_welcome_url","http://www.mozilla.com/%LOCALE%/%APP%/%VERSION%/firstrun/");
// Interval: Time between checks for a new version (in seconds)
// nightly=6 hours, official=24 hours

View File

@ -581,6 +581,15 @@ nsBrowserContentHandler.prototype = {
var overridePage = "";
var haveUpdateSession = false;
try {
// Read the old value of homepage_override.mstone before
// needHomepageOverride updates it, so that we can later add it to the
// URL if we do end up showing an overridePage. This makes it possible
// to have the overridePage's content vary depending on the version we're
// upgrading from.
let old_mstone = "unknown";
try {
old_mstone = Services.prefs.getCharPref("browser.startup.homepage_override.mstone");
} catch (ex) {}
let override = needHomepageOverride(prefb);
if (override != OVERRIDE_NONE) {
// Setup the default search engine to about:home page.
@ -604,6 +613,8 @@ nsBrowserContentHandler.prototype = {
overridePage = Services.urlFormatter.formatURLPref("startup.homepage_override_url");
if (prefb.prefHasUserValue("app.update.postupdate"))
overridePage = getPostUpdateOverridePage(overridePage);
overridePage = overridePage.replace("%OLD_VERSION%", old_mstone);
break;
}
}

View File

@ -1208,33 +1208,6 @@ BrowserGlue.prototype = {
this._dataSource = this._rdf.GetDataSource("rdf:local-store");
this._dirty = false;
if (currentUIVersion < 1) {
// this code should always migrate pre-FF3 profiles to the current UI state
let currentsetResource = this._rdf.GetResource("currentset");
let toolbars = ["nav-bar", "toolbar-menubar", "PersonalToolbar"];
for (let i = 0; i < toolbars.length; i++) {
let toolbar = this._rdf.GetResource(BROWSER_DOCURL + toolbars[i]);
let currentset = this._getPersist(toolbar, currentsetResource);
if (!currentset) {
// toolbar isn't customized
if (i == 0)
// new button is in the defaultset, nothing to migrate
break;
continue;
}
if (/(?:^|,)unified-back-forward-button(?:$|,)/.test(currentset))
// new button is already there, nothing to migrate
break;
if (/(?:^|,)back-button(?:$|,)/.test(currentset)) {
let newset = currentset.replace(/(^|,)back-button($|,)/,
"$1unified-back-forward-button,back-button$2")
this._setPersist(toolbar, currentsetResource, newset);
// done migrating
break;
}
}
}
if (currentUIVersion < 2) {
// This code adds the customizable bookmarks button.
let currentsetResource = this._rdf.GetResource("currentset");

View File

@ -136,6 +136,11 @@ var SidebarUtils = {
},
setMouseoverURL: function SU_setMouseoverURL(aURL) {
window.top.XULBrowserWindow.setOverLink(aURL, null);
// When the browser window is closed with an open sidebar, the sidebar
// unload event happens after the browser's one. In this case
// top.XULBrowserWindow has been nullified already.
if (top.XULBrowserWindow) {
top.XULBrowserWindow.setOverLink(aURL, null);
}
}
};

View File

@ -289,6 +289,8 @@
; JavaScript components
@BINPATH@/components/ConsoleAPI.manifest
@BINPATH@/components/ConsoleAPI.js
@BINPATH@/components/BrowserElementAPI.manifest
@BINPATH@/components/BrowserElementAPI.js
@BINPATH@/components/FeedProcessor.manifest
@BINPATH@/components/FeedProcessor.js
@BINPATH@/components/BrowserFeeds.manifest

View File

@ -111,6 +111,7 @@ class imgIRequest;
class nsISHEntry;
class nsDOMNavigationTiming;
class nsWindowSizes;
class nsIObjectLoadingContent;
namespace mozilla {
namespace css {
@ -1570,6 +1571,10 @@ public:
// state is unlocked/false.
virtual nsresult SetImageLockingState(bool aLocked) = 0;
virtual nsresult AddPlugin(nsIObjectLoadingContent* aPlugin) = 0;
virtual void RemovePlugin(nsIObjectLoadingContent* aPlugin) = 0;
virtual void GetPlugins(nsTArray<nsIObjectLoadingContent*>& aPlugins) = 0;
virtual nsresult GetStateObject(nsIVariant** aResult) = 0;
virtual nsDOMNavigationTiming* GetNavigationTiming() const = 0;

View File

@ -52,7 +52,7 @@ interface nsIURI;
/**
* This interface represents a content node that loads objects.
*/
[scriptable, uuid(3FF07AB3-5BAC-4D98-9549-5BD15CCEBCD3)]
[scriptable, uuid(fd56fda8-d3c3-4368-8cf3-67dbc992aec9)]
interface nsIObjectLoadingContent : nsISupports
{
const unsigned long TYPE_LOADING = 0;
@ -125,6 +125,12 @@ interface nsIObjectLoadingContent : nsISupports
*/
void playPlugin();
/**
* This attribute will return true if the plugin has been activated
* and false if the plugin is still in the click-to-play state.
*/
readonly attribute boolean activated;
[noscript] void stopPluginInstance();
[noscript] void syncStartPluginInstance();

View File

@ -161,19 +161,20 @@ interface nsIXMLHttpRequest : nsISupports
/**
* The status of the response to the request for HTTP requests.
*/
// XXX spec says unsigned short
readonly attribute unsigned long status;
/**
* The string representing the status of the response for
* HTTP requests.
*/
readonly attribute AUTF8String statusText;
readonly attribute DOMString statusText;
/**
* If the request has been sent already, this method will
* abort the request.
*/
void abort();
[binaryname(SlowAbort)] void abort();
/**
* Returns all of the response headers as a string for HTTP
@ -312,7 +313,7 @@ interface nsIXMLHttpRequest : nsISupports
* @param mimetype The type used to override that returned by the server
* (if any).
*/
void overrideMimeType(in AUTF8String mimetype);
[binaryname(SlowOverrideMimeType)] void overrideMimeType(in DOMString mimetype);
/**
* Set to true if the response is expected to be a stream of

View File

@ -485,7 +485,7 @@ nsContentUtils::InitializeModifierStrings()
nsCOMPtr<nsIStringBundleService> bundleService =
mozilla::services::GetStringBundleService();
nsCOMPtr<nsIStringBundle> bundle;
nsresult rv = NS_OK;
DebugOnly<nsresult> rv = NS_OK;
if (bundleService) {
rv = bundleService->CreateBundle( "chrome://global-platform/locale/platformKeys.properties",
getter_AddRefs(bundle));

View File

@ -1674,6 +1674,8 @@ nsDocument::~nsDocument()
// unlocked state, and then clear the table.
SetImageLockingState(false);
mImageTracker.Clear();
mPlugins.Clear();
}
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDocument)
@ -2024,7 +2026,8 @@ nsDocument::Init()
mScriptLoader = new nsScriptLoader(this);
NS_ENSURE_TRUE(mScriptLoader, NS_ERROR_OUT_OF_MEMORY);
if (!mImageTracker.Init()) {
if (!mImageTracker.Init() ||
!mPlugins.Init()) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -8362,6 +8365,51 @@ nsDocument::RemoveImage(imgIRequest* aImage)
return rv;
}
nsresult
nsDocument::AddPlugin(nsIObjectLoadingContent* aPlugin)
{
MOZ_ASSERT(aPlugin);
if (!mPlugins.PutEntry(aPlugin)) {
return NS_ERROR_OUT_OF_MEMORY;
}
return NS_OK;
}
void
nsDocument::RemovePlugin(nsIObjectLoadingContent* aPlugin)
{
MOZ_ASSERT(aPlugin);
mPlugins.RemoveEntry(aPlugin);
}
static bool
AllSubDocumentPluginEnum(nsIDocument* aDocument, void* userArg)
{
nsTArray<nsIObjectLoadingContent*>* plugins =
reinterpret_cast< nsTArray<nsIObjectLoadingContent*>* >(userArg);
MOZ_ASSERT(plugins);
aDocument->GetPlugins(*plugins);
return true;
}
static PLDHashOperator
AllPluginEnum(nsPtrHashKey<nsIObjectLoadingContent>* aPlugin, void* userArg)
{
nsTArray<nsIObjectLoadingContent*>* allPlugins =
reinterpret_cast< nsTArray<nsIObjectLoadingContent*>* >(userArg);
MOZ_ASSERT(allPlugins);
allPlugins->AppendElement(aPlugin->GetKey());
return PL_DHASH_NEXT;
}
void
nsDocument::GetPlugins(nsTArray<nsIObjectLoadingContent*>& aPlugins)
{
aPlugins.SetCapacity(aPlugins.Length() + mPlugins.Count());
mPlugins.EnumerateEntries(AllPluginEnum, &aPlugins);
EnumerateSubDocuments(AllSubDocumentPluginEnum, &aPlugins);
}
PLDHashOperator LockEnumerator(imgIRequest* aKey,
PRUint32 aData,
void* userArg)

View File

@ -935,6 +935,16 @@ public:
virtual NS_HIDDEN_(nsresult) RemoveImage(imgIRequest* aImage);
virtual NS_HIDDEN_(nsresult) SetImageLockingState(bool aLocked);
// AddPlugin adds a plugin-related element to mPlugins when the element is
// added to the tree.
virtual nsresult AddPlugin(nsIObjectLoadingContent* aPlugin);
// RemovePlugin removes a plugin-related element to mPlugins when the
// element is removed from the tree.
virtual void RemovePlugin(nsIObjectLoadingContent* aPlugin);
// GetPlugins returns the plugin-related elements from
// the frame and any subframes.
virtual void GetPlugins(nsTArray<nsIObjectLoadingContent*>& aPlugins);
virtual nsresult GetStateObject(nsIVariant** aResult);
virtual nsDOMNavigationTiming* GetNavigationTiming() const;
@ -1304,6 +1314,9 @@ private:
// Tracking for images in the document.
nsDataHashtable< nsPtrHashKey<imgIRequest>, PRUint32> mImageTracker;
// Tracking for plugins in the document.
nsTHashtable< nsPtrHashKey<nsIObjectLoadingContent> > mPlugins;
VisibilityState mVisibilityState;
#ifdef DEBUG

View File

@ -467,7 +467,7 @@ nsEventSource::Observe(nsISupports* aSubject,
return NS_OK;
}
nsresult rv;
DebugOnly<nsresult> rv;
if (strcmp(aTopic, DOM_WINDOW_FROZEN_TOPIC) == 0) {
rv = Freeze();
NS_ASSERTION(rv, "Freeze() failed");

View File

@ -1110,9 +1110,7 @@ nsFrameMessageManager::MarkForCC()
{
PRUint32 len = mListeners.Length();
for (PRUint32 i = 0; i < len; ++i) {
nsCOMPtr<nsIXPConnectWrappedJS> wjs =
do_QueryInterface(mListeners[i].mListener);
xpc_UnmarkGrayObject(wjs);
xpc_TryUnmarkWrappedGrayObject(mListeners[i].mListener);
}
return true;
}

View File

@ -4582,9 +4582,7 @@ void
nsGenericElement::MarkUserDataHandler(void* aObject, nsIAtom* aKey,
void* aChild, void* aData)
{
nsCOMPtr<nsIXPConnectWrappedJS> wjs =
do_QueryInterface(static_cast<nsISupports*>(aChild));
xpc_UnmarkGrayObject(wjs);
xpc_TryUnmarkWrappedGrayObject(static_cast<nsISupports*>(aChild));
}
void

View File

@ -115,6 +115,18 @@ static PRLogModuleInfo* gObjectLog = PR_NewLogModule("objlc");
#include "mozilla/Preferences.h"
static bool gClickToPlayPlugins = false;
static void
InitPrefCache()
{
static bool initializedPrefCache = false;
if (!initializedPrefCache) {
mozilla::Preferences::AddBoolVarCache(&gClickToPlayPlugins, "plugins.click_to_play");
}
initializedPrefCache = true;
}
class nsAsyncInstantiateEvent : public nsRunnable {
public:
nsObjectLoadingContent *mContent;
@ -486,16 +498,26 @@ IsSupportedImage(const nsCString& aMimeType)
nsresult nsObjectLoadingContent::IsPluginEnabledForType(const nsCString& aMIMEType)
{
nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
if (!pluginHost) {
return NS_ERROR_FAILURE;
}
nsresult rv = pluginHost->IsPluginEnabledForType(aMIMEType.get());
// Check to see if the plugin is disabled before deciding if it
// should be in the "click to play" state, since we only want to
// display "click to play" UI for enabled plugins.
if (NS_FAILED(rv)) {
return rv;
}
if (!mShouldPlay) {
return NS_ERROR_PLUGIN_CLICKTOPLAY;
}
nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
if (!pluginHost) {
return false;
}
return pluginHost->IsPluginEnabledForType(aMIMEType.get());
return NS_OK;
}
static void
@ -546,6 +568,26 @@ bool nsObjectLoadingContent::IsPluginEnabledByExtension(nsIURI* uri, nsCString&
return false;
}
nsresult
nsObjectLoadingContent::BindToTree(nsIDocument* aDocument, nsIContent* /*aParent*/,
nsIContent* /*aBindingParent*/,
bool /*aCompileEventHandlers*/)
{
if (aDocument) {
return aDocument->AddPlugin(this);
}
return NS_OK;
}
void
nsObjectLoadingContent::UnbindFromTree(bool /*aDeep*/, bool /*aNullParent*/)
{
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIObjectLoadingContent*>(this));
MOZ_ASSERT(thisContent);
nsIDocument* ownerDoc = thisContent->OwnerDoc();
ownerDoc->RemovePlugin(this);
}
nsObjectLoadingContent::nsObjectLoadingContent()
: mPendingInstantiateEvent(nsnull)
, mChannel(nsnull)
@ -554,11 +596,14 @@ nsObjectLoadingContent::nsObjectLoadingContent()
, mUserDisabled(false)
, mSuppressed(false)
, mNetworkCreated(true)
// If plugins.click_to_play is false, plugins should always play
, mShouldPlay(!mozilla::Preferences::GetBool("plugins.click_to_play", false))
, mSrcStreamLoading(false)
, mFallbackReason(ePluginOtherState)
{
InitPrefCache();
// If plugins.click_to_play is false, plugins should always play
mShouldPlay = !gClickToPlayPlugins;
// If plugins.click_to_play is true, track the activated state of plugins.
mActivated = !gClickToPlayPlugins;
}
nsObjectLoadingContent::~nsObjectLoadingContent()
@ -2206,5 +2251,13 @@ nsObjectLoadingContent::PlayPlugin()
return NS_OK;
mShouldPlay = true;
mActivated = true;
return LoadObject(mURI, true, mContentType, true);
}
NS_IMETHODIMP
nsObjectLoadingContent::GetActivated(bool* aActivated)
{
*aActivated = mActivated;
return NS_OK;
}

View File

@ -244,6 +244,12 @@ class nsObjectLoadingContent : public nsImageLoadingContent
static void DoStopPlugin(nsPluginInstanceOwner *aInstanceOwner, bool aDelayedStop);
nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
bool aCompileEventHandler);
void UnbindFromTree(bool aDeep = true,
bool aNullParent = true);
private:
void NotifyContentObjectWrapper();
@ -399,6 +405,10 @@ class nsObjectLoadingContent : public nsImageLoadingContent
// This is used for click-to-play plugins.
bool mShouldPlay : 1;
// Used to keep track of whether or not a plugin has been played.
// This is used for click-to-play plugins.
bool mActivated : 1;
// Used to track when we might try to instantiate a plugin instance based on
// a src data stream being delivered to this object. When this is true we don't
// want plugin instance instantiation code to attempt to load src data again or

File diff suppressed because it is too large Load Diff

View File

@ -71,6 +71,7 @@
class nsILoadGroup;
class AsyncVerifyRedirectCallbackForwarder;
class nsIUnicodeDecoder;
class nsIDOMFormData;
class nsXHREventTarget : public nsDOMEventTargetHelper,
public nsIXMLHttpRequestEventTarget
@ -83,8 +84,103 @@ public:
NS_DECL_NSIXMLHTTPREQUESTEVENTTARGET
NS_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper::)
JSObject* GetOnloadstart()
{
return GetListenerAsJSObject(mOnLoadStartListener);
}
JSObject* GetOnprogress()
{
return GetListenerAsJSObject(mOnProgressListener);
}
JSObject* GetOnabort()
{
return GetListenerAsJSObject(mOnAbortListener);
}
JSObject* GetOnerror()
{
return GetListenerAsJSObject(mOnErrorListener);
}
JSObject* GetOnload()
{
return GetListenerAsJSObject(mOnLoadListener);
}
JSObject* GetOntimeout()
{
return GetListenerAsJSObject(mOnTimeoutListener);
}
JSObject* GetOnloadend()
{
return GetListenerAsJSObject(mOnLoadendListener);
}
void SetOnloadstart(JSObject* aCallback, nsresult& aRv)
{
aRv = SetJSObjectListener(NS_LITERAL_STRING("loadstart"),
mOnLoadStartListener,
aCallback);
}
void SetOnprogress(JSObject* aCallback, nsresult& aRv)
{
aRv = SetJSObjectListener(NS_LITERAL_STRING("progress"),
mOnProgressListener,
aCallback);
}
void SetOnabort(JSObject* aCallback, nsresult& aRv)
{
aRv = SetJSObjectListener(NS_LITERAL_STRING("abort"), mOnAbortListener,
aCallback);
}
void SetOnerror(JSObject* aCallback, nsresult& aRv)
{
aRv = SetJSObjectListener(NS_LITERAL_STRING("error"), mOnErrorListener,
aCallback);
}
void SetOnload(JSObject* aCallback, nsresult& aRv)
{
aRv = SetJSObjectListener(NS_LITERAL_STRING("load"), mOnLoadListener,
aCallback);
}
void SetOntimeout(JSObject* aCallback, nsresult& aRv)
{
aRv = SetJSObjectListener(NS_LITERAL_STRING("timeout"),
mOnTimeoutListener,
aCallback);
}
void SetOnloadend(JSObject* aCallback, nsresult& aRv)
{
aRv = SetJSObjectListener(NS_LITERAL_STRING("loadend"),
mOnLoadendListener,
aCallback);
}
virtual void DisconnectFromOwner();
protected:
static inline JSObject* GetListenerAsJSObject(nsDOMEventListenerWrapper* aWrapper)
{
nsCOMPtr<nsIXPConnectJSObjectHolder> holder =
do_QueryInterface(aWrapper->GetInner());
JSObject* obj;
return holder && NS_SUCCEEDED(holder->GetJSObject(&obj)) ? obj : nsnull;
}
inline nsresult SetJSObjectListener(const nsAString& aType,
nsRefPtr<nsDOMEventListenerWrapper>& aWrapper,
JSObject* aCallback)
{
nsresult rv;
nsIScriptContext* context = GetContextForEventHandlers(&rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMEventListener> listener;
if (aCallback) {
rv = nsContentUtils::XPConnect()->WrapJS(context->GetNativeContext(),
aCallback,
NS_GET_IID(nsIDOMEventListener),
getter_AddRefs(listener));
NS_ENSURE_SUCCESS(rv, rv);
}
return RemoveAddEventListener(aType, aWrapper, listener);
}
nsRefPtr<nsDOMEventListenerWrapper> mOnLoadListener;
nsRefPtr<nsDOMEventListenerWrapper> mOnErrorListener;
nsRefPtr<nsDOMEventListenerWrapper> mOnAbortListener;
@ -164,6 +260,209 @@ public:
NS_FORWARD_NSIDOMEVENTTARGET(nsXHREventTarget::)
#ifdef DEBUG
void StaticAssertions();
#endif
// event handler
JSObject* GetOnreadystatechange()
{
return GetListenerAsJSObject(mOnReadystatechangeListener);
}
void SetOnreadystatechange(JSObject* aCallback, nsresult& aRv)
{
aRv = SetJSObjectListener(NS_LITERAL_STRING("readystatechange"),
mOnReadystatechangeListener,
aCallback);
}
// states
uint16_t GetReadyState();
// request
void Open(const nsAString& aMethod, const nsAString& aUrl, bool aAsync,
const nsAString& aUser, const nsAString& aPassword, nsresult& aRv)
{
aRv = Open(NS_ConvertUTF16toUTF8(aMethod), NS_ConvertUTF16toUTF8(aUrl),
aAsync, aUser, aPassword);
}
void SetRequestHeader(const nsAString& aHeader, const nsAString& aValue,
nsresult& aRv)
{
aRv = SetRequestHeader(NS_ConvertUTF16toUTF8(aHeader),
NS_ConvertUTF16toUTF8(aValue));
}
uint32_t GetTimeout()
{
return mTimeoutMilliseconds;
}
void SetTimeout(uint32_t aTimeout, nsresult& aRv);
bool GetWithCredentials();
void SetWithCredentials(bool aWithCredentials, nsresult& aRv);
nsXMLHttpRequestUpload* GetUpload();
private:
class RequestBody
{
public:
RequestBody() : mType(Uninitialized)
{
}
RequestBody(JSObject* aArrayBuffer) : mType(ArrayBuffer)
{
mValue.mArrayBuffer = aArrayBuffer;
}
RequestBody(nsIDOMBlob* aBlob) : mType(Blob)
{
mValue.mBlob = aBlob;
}
RequestBody(nsIDocument* aDocument) : mType(Document)
{
mValue.mDocument = aDocument;
}
RequestBody(const nsAString& aString) : mType(DOMString)
{
mValue.mString = &aString;
}
RequestBody(nsIDOMFormData* aFormData) : mType(FormData)
{
mValue.mFormData = aFormData;
}
RequestBody(nsIInputStream* aStream) : mType(InputStream)
{
mValue.mStream = aStream;
}
enum Type {
Uninitialized,
ArrayBuffer,
Blob,
Document,
DOMString,
FormData,
InputStream
};
union Value {
JSObject* mArrayBuffer;
nsIDOMBlob* mBlob;
nsIDocument* mDocument;
const nsAString* mString;
nsIDOMFormData* mFormData;
nsIInputStream* mStream;
};
Type GetType() const
{
MOZ_ASSERT(mType != Uninitialized);
return mType;
}
Value GetValue() const
{
MOZ_ASSERT(mType != Uninitialized);
return mValue;
}
private:
Type mType;
Value mValue;
};
static nsresult GetRequestBody(nsIVariant* aVariant,
const RequestBody* aBody,
nsIInputStream** aResult,
nsACString& aContentType,
nsACString& aCharset);
nsresult Send(nsIVariant* aVariant, const RequestBody* aBody);
nsresult Send(const RequestBody& aBody)
{
return Send(nsnull, &aBody);
}
public:
void Send(nsresult& aRv)
{
aRv = Send(nsnull, nsnull);
}
void Send(JSObject* aArrayBuffer, nsresult& aRv)
{
NS_ASSERTION(aArrayBuffer, "Null should go to string version");
aRv = Send(RequestBody(aArrayBuffer));
}
void Send(nsIDOMBlob* aBlob, nsresult& aRv)
{
NS_ASSERTION(aBlob, "Null should go to string version");
aRv = Send(RequestBody(aBlob));
}
void Send(nsIDocument* aDoc, nsresult& aRv)
{
NS_ASSERTION(aDoc, "Null should go to string version");
aRv = Send(RequestBody(aDoc));
}
void Send(const nsAString& aString, nsresult& aRv)
{
if (DOMStringIsNull(aString)) {
Send(aRv);
}
else {
aRv = Send(RequestBody(aString));
}
}
void Send(nsIDOMFormData* aFormData, nsresult& aRv)
{
NS_ASSERTION(aFormData, "Null should go to string version");
aRv = Send(RequestBody(aFormData));
}
void Send(nsIInputStream* aStream, nsresult& aRv)
{
NS_ASSERTION(aStream, "Null should go to string version");
aRv = Send(RequestBody(aStream));
}
void SendAsBinary(const nsAString& aBody, nsresult& aRv);
void Abort();
// response
uint32_t GetStatus();
void GetStatusText(nsString& aStatusText);
void GetResponseHeader(const nsACString& aHeader, nsACString& aResult,
nsresult& aRv);
void GetResponseHeader(const nsAString& aHeader, nsString& aResult,
nsresult& aRv)
{
nsCString result;
GetResponseHeader(NS_ConvertUTF16toUTF8(aHeader), result, aRv);
if (result.IsVoid()) {
aResult.SetIsVoid(true);
}
else {
// We use UTF8ToNewUnicode here because it truncates after invalid UTF-8
// characters, CopyUTF8toUTF16 just doesn't copy in that case.
PRUint32 length;
PRUnichar* chars = UTF8ToNewUnicode(result, &length);
aResult.Adopt(chars, length);
}
}
void GetAllResponseHeaders(nsString& aResponseHeaders);
void OverrideMimeType(const nsAString& aMimeType)
{
// XXX Should we do some validation here?
mOverrideMimeType = aMimeType;
}
JS::Value GetResponse(JSContext* aCx, nsresult& aRv);
void GetResponseText(nsString& aResponseText, nsresult& aRv);
nsIDocument* GetResponseXML(nsresult& aRv);
bool GetMozBackgroundRequest();
void SetMozBackgroundRequest(bool aMozBackgroundRequest, nsresult& aRv);
bool GetMultipart();
void SetMultipart(bool aMultipart, nsresult& aRv);
nsIChannel* GetChannel()
{
return mChannel;
}
// This creates a trusted readystatechange event, which is not cancelable and
// doesn't bubble.
static nsresult CreateReadystatechangeEvent(nsIDOMEvent** aDOMEvent);
@ -253,12 +552,15 @@ protected:
friend class AsyncVerifyRedirectCallbackForwarder;
void OnRedirectVerifyCallback(nsresult result);
nsresult Open(const nsACString& method, const nsACString& url, bool async,
const nsAString& user, const nsAString& password);
nsCOMPtr<nsISupports> mContext;
nsCOMPtr<nsIPrincipal> mPrincipal;
nsCOMPtr<nsIChannel> mChannel;
// mReadRequest is different from mChannel for multipart requests
nsCOMPtr<nsIRequest> mReadRequest;
nsCOMPtr<nsIDOMDocument> mResponseXML;
nsCOMPtr<nsIDocument> mResponseXML;
nsCOMPtr<nsIChannel> mCORSPreflightChannel;
nsTArray<nsCString> mCORSUnsafeHeaders;
@ -304,17 +606,21 @@ protected:
nsCString mResponseCharset;
enum {
enum ResponseType {
XML_HTTP_RESPONSE_TYPE_DEFAULT,
XML_HTTP_RESPONSE_TYPE_ARRAYBUFFER,
XML_HTTP_RESPONSE_TYPE_BLOB,
XML_HTTP_RESPONSE_TYPE_DOCUMENT,
XML_HTTP_RESPONSE_TYPE_TEXT,
XML_HTTP_RESPONSE_TYPE_JSON,
XML_HTTP_RESPONSE_TYPE_TEXT,
XML_HTTP_RESPONSE_TYPE_CHUNKED_TEXT,
XML_HTTP_RESPONSE_TYPE_CHUNKED_ARRAYBUFFER,
XML_HTTP_RESPONSE_TYPE_MOZ_BLOB
} mResponseType;
};
void SetResponseType(nsXMLHttpRequest::ResponseType aType, nsresult& aRv);
ResponseType mResponseType;
// It is either a cached blob-response from the last call to GetResponse,
// but is also explicitly set in OnStopRequest.
@ -327,7 +633,7 @@ protected:
// and mDOMFile is null.
nsRefPtr<nsDOMBlobBuilder> mBuilder;
nsCString mOverrideMimeType;
nsString mOverrideMimeType;
/**
* The notification callbacks the channel had when Send() was

View File

@ -199,11 +199,9 @@ private:
#define NS_DISCONNECT_EVENT_HANDLER(_event) \
if (mOn##_event##Listener) { mOn##_event##Listener->Disconnect(); }
#define NS_UNMARK_LISTENER_WRAPPER(_event) \
if (tmp->mOn##_event##Listener) { \
nsCOMPtr<nsIXPConnectWrappedJS> wjs = \
do_QueryInterface(tmp->mOn##_event##Listener->GetInner()); \
xpc_UnmarkGrayObject(wjs); \
#define NS_UNMARK_LISTENER_WRAPPER(_event) \
if (tmp->mOn##_event##Listener) { \
xpc_TryUnmarkWrappedGrayObject(tmp->mOn##_event##Listener->GetInner()); \
}
#endif // nsDOMEventTargetHelper_h_

View File

@ -1050,8 +1050,7 @@ nsEventListenerManager::UnmarkGrayJSListeners()
xpc_UnmarkGrayObject(jsl->GetHandler());
xpc_UnmarkGrayObject(jsl->GetEventScope());
} else if (ls.mWrappedJS) {
nsCOMPtr<nsIXPConnectWrappedJS> wjs = do_QueryInterface(ls.mListener);
xpc_UnmarkGrayObject(wjs);
xpc_TryUnmarkWrappedGrayObject(ls.mListener);
}
}
}

View File

@ -28,22 +28,18 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGenericHTMLFrameElement,
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_INTERFACE_TABLE_HEAD(nsGenericHTMLFrameElement)
NS_INTERFACE_TABLE_INHERITED4(nsGenericHTMLFrameElement,
NS_INTERFACE_TABLE_INHERITED3(nsGenericHTMLFrameElement,
nsIFrameLoaderOwner,
nsIDOMMozBrowserFrame,
nsIMozBrowserFrame,
nsIWebProgressListener)
nsIMozBrowserFrame)
NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsGenericHTMLFrameElement)
NS_INTERFACE_MAP_END_INHERITING(nsGenericHTMLElement)
NS_IMPL_INT_ATTR(nsGenericHTMLFrameElement, TabIndex, tabindex)
NS_IMPL_BOOL_ATTR(nsGenericHTMLFrameElement, Mozbrowser, mozbrowser)
nsGenericHTMLFrameElement::~nsGenericHTMLFrameElement()
{
if (mTitleChangedListener) {
mTitleChangedListener->Unregister();
}
if (mFrameLoader) {
mFrameLoader->Destroy();
}
@ -115,8 +111,6 @@ nsGenericHTMLFrameElement::EnsureFrameLoader()
return NS_OK;
}
MaybeEnsureBrowserFrameListenersRegistered();
return NS_OK;
}
@ -268,101 +262,25 @@ nsGenericHTMLFrameElement::IsHTMLFocusable(bool aWithMouse,
return false;
}
NS_IMETHODIMP
nsGenericHTMLFrameElement::GetMozbrowser(bool *aValue)
{
return GetBoolAttr(nsGkAtoms::mozbrowser, aValue);
}
NS_IMETHODIMP
nsGenericHTMLFrameElement::SetMozbrowser(bool aValue)
{
nsresult rv = SetBoolAttr(nsGkAtoms::mozbrowser, aValue);
if (NS_SUCCEEDED(rv)) {
MaybeEnsureBrowserFrameListenersRegistered();
}
return rv;
}
/*
* If this frame element is allowed to be a browser frame (i.e.,
* GetReallyIsBrowser returns true), then make sure that it has the appropriate
* event listeners enabled.
*/
void
nsGenericHTMLFrameElement::MaybeEnsureBrowserFrameListenersRegistered()
{
if (mBrowserFrameListenersRegistered) {
return;
}
// If this frame passes the browser frame security check, ensure that its
// listeners are active.
if (!GetReallyIsBrowser()) {
return;
}
// Not much we can do without a frameLoader. But EnsureFrameLoader will call
// this function, so we'll get a chance to pass this test.
if (!mFrameLoader) {
return;
}
mBrowserFrameListenersRegistered = true;
// Register ourselves as a web progress listener on the frameloader's
// docshell.
nsCOMPtr<nsIDocShell> docShell;
mFrameLoader->GetDocShell(getter_AddRefs(docShell));
nsCOMPtr<nsIWebProgress> webProgress = do_QueryInterface(docShell);
// This adds a weak ref, so we don't have to worry about unregistering.
if (webProgress) {
webProgress->AddProgressListener(this,
nsIWebProgress::NOTIFY_LOCATION |
nsIWebProgress::NOTIFY_STATE_WINDOW);
}
// Register a listener for DOMTitleChanged on the window's chrome event
// handler. The chrome event handler outlives this iframe, so we'll have to
// unregister when the iframe is destroyed.
nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(docShell);
if (!window) {
return;
}
MOZ_ASSERT(window->IsOuterWindow());
nsIDOMEventTarget *chromeHandler = window->GetChromeEventHandler();
if (!chromeHandler) {
return;
}
MOZ_ASSERT(!mTitleChangedListener);
mTitleChangedListener = new TitleChangedListener(this, chromeHandler);
chromeHandler->AddSystemEventListener(NS_LITERAL_STRING("DOMTitleChanged"),
mTitleChangedListener,
/* useCapture = */ false,
/* wantsUntrusted = */ false);
}
/**
* Return true if this frame element has permission to send mozbrowser
* events, and false otherwise.
*/
bool
nsGenericHTMLFrameElement::GetReallyIsBrowser()
nsresult
nsGenericHTMLFrameElement::GetReallyIsBrowser(bool *aOut)
{
*aOut = false;
// Fail if browser frames are globally disabled.
if (!Preferences::GetBool("dom.mozBrowserFramesEnabled")) {
return false;
return NS_OK;
}
// Fail if this frame doesn't have the mozbrowser attribute.
bool isBrowser = false;
GetMozbrowser(&isBrowser);
if (!isBrowser) {
return false;
return NS_OK;
}
// Fail if the node principal isn't trusted.
@ -371,223 +289,10 @@ nsGenericHTMLFrameElement::GetReallyIsBrowser()
principal->GetURI(getter_AddRefs(principalURI));
if (!nsContentUtils::URIIsChromeOrInPref(principalURI,
"dom.mozBrowserFramesWhitelist")) {
return false;
return NS_OK;
}
// Otherwise, succeed.
return true;
}
NS_IMETHODIMP
nsGenericHTMLFrameElement::GetReallyIsBrowser(bool *aResult)
{
*aResult = GetReallyIsBrowser();
*aOut = true;
return NS_OK;
}
/**
* Fire a mozbrowser event, if we have permission.
*
* @param aEventName the event name (e.g. "locationchange"). "mozbrowser" is
* added to the beginning of aEventName automatically.
* @param aEventType the event type. Must be either "event" or "customevent".
* @param aValue the value passed along with the event. This value will be
* set as the event's "detail" property. This must be empty if
* aEventType is "event".
*/
nsresult
nsGenericHTMLFrameElement::MaybeFireBrowserEvent(
const nsAString &aEventName,
const nsAString &aEventType,
const nsAString &aValue /* = EmptyString() */)
{
MOZ_ASSERT(aEventType.EqualsLiteral("event") ||
aEventType.EqualsLiteral("customevent"));
MOZ_ASSERT_IF(aEventType.EqualsLiteral("event"),
aValue.IsEmpty());
if (!GetReallyIsBrowser()) {
return NS_OK;
}
nsAutoString eventName;
eventName.AppendLiteral("mozbrowser");
eventName.Append(aEventName);
nsCOMPtr<nsIDOMEvent> domEvent;
nsEventDispatcher::CreateEvent(GetPresContext(), nsnull,
aEventType, getter_AddRefs(domEvent));
nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(domEvent);
NS_ENSURE_STATE(privateEvent);
nsresult rv = privateEvent->SetTrusted(true);
NS_ENSURE_SUCCESS(rv, rv);
if (aEventType.EqualsLiteral("customevent")) {
nsCOMPtr<nsIDOMCustomEvent> customEvent = do_QueryInterface(domEvent);
NS_ENSURE_STATE(customEvent);
nsCOMPtr<nsIWritableVariant> value = new nsVariant();
value->SetAsAString(aValue);
rv = customEvent->InitCustomEvent(eventName,
/* bubbles = */ false,
/* cancelable = */ false,
value);
NS_ENSURE_SUCCESS(rv, rv);
}
else {
rv = domEvent->InitEvent(eventName,
/* bubbles = */ false,
/* cancelable = */ false);
NS_ENSURE_SUCCESS(rv, rv);
}
return (new nsAsyncDOMEvent(this, domEvent))->PostDOMEvent();
}
NS_IMETHODIMP
nsGenericHTMLFrameElement::OnLocationChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
nsIURI* aURI,
PRUint32 aFlags)
{
// aURI may be null, but that indicates an error case we don't care about.
if (!aURI) {
return NS_OK;
}
nsCAutoString spec;
aURI->GetSpec(spec);
MaybeFireBrowserEvent(NS_LITERAL_STRING("locationchange"),
NS_LITERAL_STRING("customevent"),
NS_ConvertUTF8toUTF16(spec));
return NS_OK;
}
NS_IMETHODIMP
nsGenericHTMLFrameElement::OnStateChange(nsIWebProgress* aProgress,
nsIRequest* aRequest,
PRUint32 aProgressStateFlags,
nsresult aStatus)
{
if (!(aProgressStateFlags & STATE_IS_WINDOW)) {
return NS_OK;
}
nsAutoString status;
if (aProgressStateFlags & STATE_START) {
MaybeFireBrowserEvent(NS_LITERAL_STRING("loadstart"),
NS_LITERAL_STRING("event"));
}
else if (aProgressStateFlags & STATE_STOP) {
MaybeFireBrowserEvent(NS_LITERAL_STRING("loadend"),
NS_LITERAL_STRING("event"));
}
return NS_OK;
}
NS_IMETHODIMP
nsGenericHTMLFrameElement::OnProgressChange(nsIWebProgress* aProgress,
nsIRequest* aRequest,
PRInt32 aCurSelfProgress,
PRInt32 aMaxSelfProgress,
PRInt32 aCurTotalProgress,
PRInt32 aMaxTotalProgress)
{
return NS_OK;
}
NS_IMETHODIMP
nsGenericHTMLFrameElement::OnStatusChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
nsresult aStatus,
const PRUnichar* aMessage)
{
return NS_OK;
}
NS_IMETHODIMP
nsGenericHTMLFrameElement::OnSecurityChange(nsIWebProgress *aWebProgress,
nsIRequest *aRequest,
PRUint32 state)
{
return NS_OK;
}
NS_IMPL_ISUPPORTS1(nsGenericHTMLFrameElement::TitleChangedListener,
nsIDOMEventListener)
nsGenericHTMLFrameElement::TitleChangedListener::TitleChangedListener(
nsGenericHTMLFrameElement *aElement,
nsIDOMEventTarget *aChromeHandler)
{
mElement =
do_GetWeakReference(NS_ISUPPORTS_CAST(nsIDOMMozBrowserFrame*, aElement));
mChromeHandler = do_GetWeakReference(aChromeHandler);
}
NS_IMETHODIMP
nsGenericHTMLFrameElement::TitleChangedListener::HandleEvent(nsIDOMEvent *aEvent)
{
#ifdef DEBUG
{
nsString eventType;
aEvent->GetType(eventType);
MOZ_ASSERT(eventType.EqualsLiteral("DOMTitleChanged"));
}
#endif
nsCOMPtr<nsIDOMMozBrowserFrame> element = do_QueryReferent(mElement);
if (!element) {
// Hm, our element is gone, but somehow we weren't unregistered?
Unregister();
return NS_OK;
}
nsGenericHTMLFrameElement* frameElement =
static_cast<nsGenericHTMLFrameElement*>(element.get());
nsCOMPtr<nsIDOMDocument> frameDocument;
frameElement->GetContentDocument(getter_AddRefs(frameDocument));
NS_ENSURE_STATE(frameDocument);
nsCOMPtr<nsIDOMEventTarget> target;
aEvent->GetTarget(getter_AddRefs(target));
nsCOMPtr<nsIDOMDocument> targetDocument = do_QueryInterface(target);
NS_ENSURE_STATE(targetDocument);
if (frameDocument != targetDocument) {
// This is a titlechange event for the wrong document!
return NS_OK;
}
nsString newTitle;
nsresult rv = targetDocument->GetTitle(newTitle);
NS_ENSURE_SUCCESS(rv, rv);
frameElement->MaybeFireBrowserEvent(
NS_LITERAL_STRING("titlechange"),
NS_LITERAL_STRING("customevent"),
newTitle);
return NS_OK;
}
void
nsGenericHTMLFrameElement::TitleChangedListener::Unregister()
{
nsCOMPtr<nsIDOMEventTarget> chromeHandler = do_QueryReferent(mChromeHandler);
if (!chromeHandler) {
return;
}
chromeHandler->RemoveSystemEventListener(NS_LITERAL_STRING("DOMTitleChanged"),
this, /* useCapture = */ false);
// Careful; the call above may have removed the last strong reference to this
// class, so don't dereference |this| here.
}

View File

@ -9,15 +9,13 @@
#include "nsIDOMHTMLFrameElement.h"
#include "nsIMozBrowserFrame.h"
#include "nsIDOMEventListener.h"
#include "nsIWebProgressListener.h"
/**
* A helper class for frame elements
*/
class nsGenericHTMLFrameElement : public nsGenericHTMLElement,
public nsIFrameLoaderOwner,
public nsIMozBrowserFrame,
public nsIWebProgressListener
public nsIMozBrowserFrame
{
public:
nsGenericHTMLFrameElement(already_AddRefed<nsINodeInfo> aNodeInfo,
@ -34,7 +32,6 @@ public:
NS_DECL_NSIFRAMELOADEROWNER
NS_DECL_NSIDOMMOZBROWSERFRAME
NS_DECL_NSIMOZBROWSERFRAME
NS_DECL_NSIWEBPROGRESSLISTENER
// nsIContent
virtual bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, PRInt32 *aTabIndex);
@ -62,9 +59,6 @@ public:
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsGenericHTMLFrameElement,
nsGenericHTMLElement)
// Non-COM version of nsIMozBrowserFrame::GetReallyIsBrowser.
bool GetReallyIsBrowser();
protected:
/**
* Listens to titlechanged events from the document inside the iframe and
@ -95,13 +89,7 @@ protected:
nsresult GetContentDocument(nsIDOMDocument** aContentDocument);
nsresult GetContentWindow(nsIDOMWindow** aContentWindow);
void MaybeEnsureBrowserFrameListenersRegistered();
nsresult MaybeFireBrowserEvent(const nsAString &aEventName,
const nsAString &aEventType,
const nsAString &aValue = EmptyString());
nsRefPtr<nsFrameLoader> mFrameLoader;
nsRefPtr<TitleChangedListener> mTitleChangedListener;
// True when the element is created by the parser
// using NS_FROM_PARSER_NETWORK flag.

View File

@ -265,6 +265,11 @@ nsHTMLObjectElement::BindToTree(nsIDocument *aDocument,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
rv = nsObjectLoadingContent::BindToTree(aDocument, aParent,
aBindingParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
// If we already have all the children, start the load.
if (mIsDoneAddingChildren) {
void (nsHTMLObjectElement::*start)() = &nsHTMLObjectElement::StartObjectLoad;
@ -279,6 +284,7 @@ nsHTMLObjectElement::UnbindFromTree(bool aDeep,
bool aNullParent)
{
RemovedFromDocument();
nsObjectLoadingContent::UnbindFromTree(aDeep, aNullParent);
nsGenericHTMLFormElement::UnbindFromTree(aDeep, aNullParent);
}

View File

@ -283,6 +283,11 @@ nsHTMLSharedObjectElement::BindToTree(nsIDocument *aDocument,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
rv = nsObjectLoadingContent::BindToTree(aDocument, aParent,
aBindingParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
// If we already have all the children, start the load.
if (mIsDoneAddingChildren) {
void (nsHTMLSharedObjectElement::*start)() =
@ -298,6 +303,7 @@ nsHTMLSharedObjectElement::UnbindFromTree(bool aDeep,
bool aNullParent)
{
RemovedFromDocument();
nsObjectLoadingContent::UnbindFromTree(aDeep, aNullParent);
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
}

View File

@ -0,0 +1,342 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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 "mozilla/XPCOM.h"
#include "FileBlockCache.h"
#include "VideoUtils.h"
namespace mozilla {
nsresult FileBlockCache::Open(PRFileDesc* aFD)
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
NS_ENSURE_TRUE(aFD != nsnull, NS_ERROR_FAILURE);
{
MonitorAutoLock mon(mFileMonitor);
mFD = aFD;
}
{
MonitorAutoLock mon(mDataMonitor);
nsresult res = NS_NewThread(getter_AddRefs(mThread),
nsnull,
MEDIA_THREAD_STACK_SIZE);
mIsOpen = NS_SUCCEEDED(res);
return res;
}
}
FileBlockCache::FileBlockCache()
: mFileMonitor("nsMediaCache.Writer.IO.Monitor"),
mFD(nsnull),
mFDCurrentPos(0),
mDataMonitor("nsMediaCache.Writer.Data.Monitor"),
mIsWriteScheduled(false),
mIsOpen(false)
{
MOZ_COUNT_CTOR(FileBlockCache);
}
FileBlockCache::~FileBlockCache()
{
NS_ASSERTION(!mIsOpen, "Should Close() FileBlockCache before destroying");
{
// Note, mThread will be shutdown by the time this runs, so we won't
// block while taking mFileMonitor.
MonitorAutoLock mon(mFileMonitor);
if (mFD) {
PR_Close(mFD);
mFD = nsnull;
}
}
MOZ_COUNT_DTOR(FileBlockCache);
}
void FileBlockCache::Close()
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
MonitorAutoLock mon(mDataMonitor);
mIsOpen = false;
if (mThread) {
// We must shut down the thread in another runnable. This is called
// while we're shutting down the media cache, and nsIThread::Shutdown()
// can cause events to run before it completes, which could end up
// opening more streams, while the media cache is shutting down and
// releasing memory etc! Also note we close mFD in the destructor so
// as to not disturb any IO that's currently running.
nsCOMPtr<nsIRunnable> event = new ShutdownThreadEvent(mThread);
mThread = nsnull;
NS_DispatchToMainThread(event);
}
}
nsresult FileBlockCache::WriteBlock(PRUint32 aBlockIndex, const PRUint8* aData)
{
MonitorAutoLock mon(mDataMonitor);
if (!mIsOpen)
return NS_ERROR_FAILURE;
// Check if we've already got a pending write scheduled for this block.
mBlockChanges.EnsureLengthAtLeast(aBlockIndex + 1);
bool blockAlreadyHadPendingChange = mBlockChanges[aBlockIndex] != nsnull;
mBlockChanges[aBlockIndex] = new BlockChange(aData);
if (!blockAlreadyHadPendingChange || !mChangeIndexList.Contains(aBlockIndex)) {
// We either didn't already have a pending change for this block, or we
// did but we didn't have an entry for it in mChangeIndexList (we're in the process
// of writing it and have removed the block's index out of mChangeIndexList
// in Run() but not finished writing the block to file yet). Add the blocks
// index to the end of mChangeIndexList to ensure the block is written as
// as soon as possible.
mChangeIndexList.PushBack(aBlockIndex);
}
NS_ASSERTION(mChangeIndexList.Contains(aBlockIndex), "Must have entry for new block");
EnsureWriteScheduled();
return NS_OK;
}
void FileBlockCache::EnsureWriteScheduled()
{
mDataMonitor.AssertCurrentThreadOwns();
if (!mIsWriteScheduled) {
mThread->Dispatch(this, NS_DISPATCH_NORMAL);
mIsWriteScheduled = true;
}
}
nsresult FileBlockCache::Seek(PRInt64 aOffset)
{
mFileMonitor.AssertCurrentThreadOwns();
if (mFDCurrentPos != aOffset) {
PROffset64 result = PR_Seek64(mFD, aOffset, PR_SEEK_SET);
if (result != aOffset) {
NS_WARNING("Failed to seek media cache file");
return NS_ERROR_FAILURE;
}
mFDCurrentPos = result;
}
return NS_OK;
}
nsresult FileBlockCache::ReadFromFile(PRInt32 aOffset,
PRUint8* aDest,
PRInt32 aBytesToRead,
PRInt32& aBytesRead)
{
mFileMonitor.AssertCurrentThreadOwns();
nsresult res = Seek(aOffset);
if (NS_FAILED(res)) return res;
aBytesRead = PR_Read(mFD, aDest, aBytesToRead);
if (aBytesRead <= 0)
return NS_ERROR_FAILURE;
mFDCurrentPos += aBytesRead;
return NS_OK;
}
nsresult FileBlockCache::WriteBlockToFile(PRInt32 aBlockIndex,
const PRUint8* aBlockData)
{
mFileMonitor.AssertCurrentThreadOwns();
nsresult rv = Seek(aBlockIndex * BLOCK_SIZE);
if (NS_FAILED(rv)) return rv;
PRInt32 amount = PR_Write(mFD, aBlockData, BLOCK_SIZE);
if (amount < BLOCK_SIZE) {
NS_WARNING("Failed to write media cache block!");
return NS_ERROR_FAILURE;
}
mFDCurrentPos += BLOCK_SIZE;
return NS_OK;
}
nsresult FileBlockCache::MoveBlockInFile(PRInt32 aSourceBlockIndex,
PRInt32 aDestBlockIndex)
{
mFileMonitor.AssertCurrentThreadOwns();
PRUint8 buf[BLOCK_SIZE];
PRInt32 bytesRead = 0;
if (NS_FAILED(ReadFromFile(aSourceBlockIndex * BLOCK_SIZE,
buf,
BLOCK_SIZE,
bytesRead))) {
return NS_ERROR_FAILURE;
}
return WriteBlockToFile(aDestBlockIndex, buf);
}
nsresult FileBlockCache::Run()
{
MonitorAutoLock mon(mDataMonitor);
NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
NS_ASSERTION(!mChangeIndexList.IsEmpty(), "Only dispatch when there's work to do");
NS_ASSERTION(mIsWriteScheduled, "Should report write running or scheduled.");
while (!mChangeIndexList.IsEmpty()) {
if (!mIsOpen) {
// We've been closed, abort, discarding unwritten changes.
mIsWriteScheduled = false;
return NS_ERROR_FAILURE;
}
// Process each pending change. We pop the index out of the change
// list, but leave the BlockChange in mBlockChanges until the change
// is written to file. This is so that any read which happens while
// we drop mDataMonitor to write will refer to the data's source in
// memory, rather than the not-yet up to date data written to file.
// This also ensures we will insert a new index into mChangeIndexList
// when this happens.
// Hold a reference to the change, in case another change
// overwrites the mBlockChanges entry for this block while we drop
// mDataMonitor to take mFileMonitor.
PRInt32 blockIndex = mChangeIndexList.PopFront();
nsRefPtr<BlockChange> change = mBlockChanges[blockIndex];
NS_ABORT_IF_FALSE(change,
"Change index list should only contain entries for blocks with changes");
{
MonitorAutoUnlock unlock(mDataMonitor);
MonitorAutoLock lock(mFileMonitor);
if (change->IsWrite()) {
WriteBlockToFile(blockIndex, change->mData.get());
} else if (change->IsMove()) {
MoveBlockInFile(change->mSourceBlockIndex, blockIndex);
}
}
// If a new change has not been made to the block while we dropped
// mDataMonitor, clear reference to the old change. Otherwise, the old
// reference has been cleared already.
if (mBlockChanges[blockIndex] == change) {
mBlockChanges[blockIndex] = nsnull;
}
}
mIsWriteScheduled = false;
return NS_OK;
}
nsresult FileBlockCache::Read(PRInt64 aOffset,
PRUint8* aData,
PRInt32 aLength,
PRInt32* aBytes)
{
MonitorAutoLock mon(mDataMonitor);
if (!mFD || (aOffset / BLOCK_SIZE) > PR_INT32_MAX)
return NS_ERROR_FAILURE;
PRInt32 bytesToRead = aLength;
PRInt64 offset = aOffset;
PRUint8* dst = aData;
while (bytesToRead > 0) {
PRInt32 blockIndex = static_cast<PRInt32>(offset / BLOCK_SIZE);
PRInt32 start = offset % BLOCK_SIZE;
PRInt32 amount = NS_MIN(BLOCK_SIZE - start, bytesToRead);
// If the block is not yet written to file, we can just read from
// the memory buffer, otherwise we need to read from file.
PRInt32 bytesRead = 0;
nsRefPtr<BlockChange> change = mBlockChanges[blockIndex];
if (change && change->IsWrite()) {
// Block isn't yet written to file. Read from memory buffer.
const PRUint8* blockData = change->mData.get();
memcpy(dst, blockData + start, amount);
bytesRead = amount;
} else {
if (change && change->IsMove()) {
// The target block is the destination of a not-yet-completed move
// action, so read from the move's source block from file. Note we
// *don't* follow a chain of moves here, as a move's source index
// is resolved when MoveBlock() is called, and the move's source's
// block could be have itself been subject to a move (or write)
// which happened *after* this move was recorded.
blockIndex = mBlockChanges[blockIndex]->mSourceBlockIndex;
}
// Block has been written to file, either as the source block of a move,
// or as a stable (all changes made) block. Read the data directly
// from file.
nsresult res;
{
MonitorAutoUnlock unlock(mDataMonitor);
MonitorAutoLock lock(mFileMonitor);
res = ReadFromFile(blockIndex * BLOCK_SIZE + start,
dst,
amount,
bytesRead);
}
NS_ENSURE_SUCCESS(res,res);
}
dst += bytesRead;
offset += bytesRead;
bytesToRead -= bytesRead;
}
*aBytes = aLength - bytesToRead;
return NS_OK;
}
nsresult FileBlockCache::MoveBlock(PRInt32 aSourceBlockIndex, PRInt32 aDestBlockIndex)
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
MonitorAutoLock mon(mDataMonitor);
if (!mIsOpen)
return NS_ERROR_FAILURE;
mBlockChanges.EnsureLengthAtLeast(NS_MAX(aSourceBlockIndex, aDestBlockIndex) + 1);
// The source block's contents may be the destination of another pending
// move, which in turn can be the destination of another pending move,
// etc. Resolve the final source block, so that if one of the blocks in
// the chain of moves is overwritten, we don't lose the reference to the
// contents of the destination block.
PRInt32 sourceIndex = aSourceBlockIndex;
BlockChange* sourceBlock = nsnull;
while ((sourceBlock = mBlockChanges[sourceIndex]) &&
sourceBlock->IsMove()) {
sourceIndex = sourceBlock->mSourceBlockIndex;
}
if (mBlockChanges[aDestBlockIndex] == nsnull ||
!mChangeIndexList.Contains(aDestBlockIndex)) {
// Only add another entry to the change index list if we don't already
// have one for this block. We won't have an entry when either there's
// no pending change for this block, or if there is a pending change for
// this block and we're in the process of writing it (we've popped the
// block's index out of mChangeIndexList in Run() but not finished writing
// the block to file yet.
mChangeIndexList.PushBack(aDestBlockIndex);
}
// If the source block hasn't yet been written to file then the dest block
// simply contains that same write. Resolve this as a write instead.
if (sourceBlock && sourceBlock->IsWrite()) {
mBlockChanges[aDestBlockIndex] = new BlockChange(sourceBlock->mData.get());
} else {
mBlockChanges[aDestBlockIndex] = new BlockChange(sourceIndex);
}
EnsureWriteScheduled();
NS_ASSERTION(mChangeIndexList.Contains(aDestBlockIndex),
"Should have scheduled block for change");
return NS_OK;
}
} // End namespace mozilla.

View File

@ -0,0 +1,202 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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 FILE_BLOCK_CACHE_H_
#define FILE_BLOCK_CACHE_H_
#include "mozilla/Monitor.h"
#include "prio.h"
#include "nsTArray.h"
#include "nsMediaCache.h"
#include "nsDeque.h"
namespace mozilla {
// Manages file I/O for the media cache. Data comes in over the network
// via callbacks on the main thread, however we don't want to write the
// incoming data to the media cache on the main thread, as this could block
// causing UI jank.
//
// So FileBlockCache provides an abstraction for a temporary file accessible
// as an array of blocks, which supports a block move operation, and
// allows synchronous reading and writing from any thread, with writes being
// buffered so as not to block.
//
// Writes and cache block moves (which require reading) are deferred to
// their own non-main thread. This object also ensures that data which has
// been scheduled to be written, but hasn't actually *been* written, is read
// as if it had, i.e. pending writes are cached in readable memory until
// they're flushed to file.
//
// To improve efficiency, writes can only be done at block granularity,
// whereas reads can be done with byte granularity.
//
// Note it's also recommended not to read from the media cache from the main
// thread to prevent jank.
//
// When WriteBlock() or MoveBlock() are called, data about how to complete
// the block change is added to mBlockChanges, indexed by block index, and
// the block index is appended to the mChangeIndexList. This enables
// us to quickly tell if a block has been changed, and ensures we can perform
// the changes in the correct order. An event is dispatched to perform the
// changes listed in mBlockChanges to file. Read() checks mBlockChanges and
// determines the current data to return, reading from file or from
// mBlockChanges as necessary.
class FileBlockCache : public nsRunnable {
public:
enum {
BLOCK_SIZE = nsMediaCacheStream::BLOCK_SIZE
};
FileBlockCache();
~FileBlockCache();
// Assumes ownership of aFD.
nsresult Open(PRFileDesc* aFD);
// Closes writer, shuts down thread.
void Close();
// Can be called on any thread. This defers to a non-main thread.
nsresult WriteBlock(PRUint32 aBlockIndex, const PRUint8* aData);
// Performs block writes and block moves on its own thread.
NS_IMETHOD Run();
// Synchronously reads data from file. May read from file or memory
// depending on whether written blocks have been flushed to file yet.
// Not recommended to be called from the main thread, as can cause jank.
nsresult Read(PRInt64 aOffset,
PRUint8* aData,
PRInt32 aLength,
PRInt32* aBytes);
// Moves a block asynchronously. Can be called on any thread.
// This defers file I/O to a non-main thread.
nsresult MoveBlock(PRInt32 aSourceBlockIndex, PRInt32 aDestBlockIndex);
// Represents a change yet to be made to a block in the file. The change
// is either a write (and the data to be written is stored in this struct)
// or a move (and the index of the source block is stored instead).
struct BlockChange {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BlockChange)
// This block is waiting in memory to be written.
// Stores a copy of the block, so we can write it asynchronously.
BlockChange(const PRUint8* aData)
: mSourceBlockIndex(-1)
{
mData = new PRUint8[BLOCK_SIZE];
memcpy(mData.get(), aData, BLOCK_SIZE);
}
// This block's contents are located in another file
// block, i.e. this block has been moved.
BlockChange(PRInt32 aSourceBlockIndex)
: mSourceBlockIndex(aSourceBlockIndex) {}
nsAutoArrayPtr<PRUint8> mData;
const PRInt32 mSourceBlockIndex;
bool IsMove() const {
return mSourceBlockIndex != -1;
}
bool IsWrite() const {
return mSourceBlockIndex == -1 &&
mData.get() != nsnull;
}
};
class Int32Queue : private nsDeque {
public:
PRInt32 PopFront() {
PRInt32 front = ObjectAt(0);
nsDeque::PopFront();
return front;
}
void PushBack(PRInt32 aValue) {
nsDeque::Push(reinterpret_cast<void*>(aValue));
}
bool Contains(PRInt32 aValue) {
for (PRInt32 i = 0; i < GetSize(); ++i) {
if (ObjectAt(i) == aValue) {
return true;
}
}
return false;
}
bool IsEmpty() {
return nsDeque::GetSize() == 0;
}
private:
PRInt32 ObjectAt(PRInt32 aIndex) {
void* v = nsDeque::ObjectAt(aIndex);
// Ugly hack to work around "casting 64bit void* to 32bit int loses precision"
// error on 64bit Linux.
return *(reinterpret_cast<PRInt32*>(&v));
}
};
private:
// Monitor which controls access to mFD and mFDCurrentPos. Don't hold
// mDataMonitor while holding mFileMonitor! mFileMonitor must be owned
// while accessing any of the following data fields or methods.
mozilla::Monitor mFileMonitor;
// Moves a block already committed to file.
nsresult MoveBlockInFile(PRInt32 aSourceBlockIndex,
PRInt32 aDestBlockIndex);
// Seeks file pointer.
nsresult Seek(PRInt64 aOffset);
// Reads data from file offset.
nsresult ReadFromFile(PRInt32 aOffset,
PRUint8* aDest,
PRInt32 aBytesToRead,
PRInt32& aBytesRead);
nsresult WriteBlockToFile(PRInt32 aBlockIndex, const PRUint8* aBlockData);
// File descriptor we're writing to. This is created externally, but
// shutdown by us.
PRFileDesc* mFD;
// The current file offset in the file.
PRInt64 mFDCurrentPos;
// Monitor which controls access to all data in this class, except mFD
// and mFDCurrentPos. Don't hold mDataMonitor while holding mFileMonitor!
// mDataMonitor must be owned while accessing any of the following data
// fields or methods.
mozilla::Monitor mDataMonitor;
// Ensures we either are running the event to preform IO, or an event
// has been dispatched to preform the IO.
// mDataMonitor must be owned while calling this.
void EnsureWriteScheduled();
// Array of block changes to made. If mBlockChanges[offset/BLOCK_SIZE] == nsnull,
// then the block has no pending changes to be written, but if
// mBlockChanges[offset/BLOCK_SIZE] != nsnull, then either there's a block
// cached in memory waiting to be written, or this block is the target of a
// block move.
nsTArray< nsRefPtr<BlockChange> > mBlockChanges;
// Thread upon which block writes and block moves are performed. This is
// created upon open, and shutdown (asynchronously) upon close (on the
// main thread).
nsCOMPtr<nsIThread> mThread;
// Queue of pending block indexes that need to be written or moved.
//nsAutoTArray<PRInt32, 8> mChangeIndexList;
Int32Queue mChangeIndexList;
// True if we've dispatched an event to commit all pending block changes
// to file on mThread.
bool mIsWriteScheduled;
// True if the writer is ready to write data to file.
bool mIsOpen;
};
} // End namespace mozilla.
#endif /* FILE_BLOCK_CACHE_H_ */

View File

@ -46,6 +46,7 @@ LIBRARY_NAME = gkconmedia_s
LIBXUL_LIBRARY = 1
EXPORTS = \
FileBlockCache.h \
nsAudioAvailableEventManager.h \
nsMediaDecoder.h \
nsMediaCache.h \
@ -58,6 +59,7 @@ EXPORTS = \
$(NULL)
CPPSRCS = \
FileBlockCache.cpp \
nsAudioAvailableEventManager.cpp \
nsMediaDecoder.cpp \
nsMediaCache.cpp \

View File

@ -1208,7 +1208,6 @@ void MediaResource::MoveLoadsToBackground() {
return;
}
nsresult rv;
nsHTMLMediaElement* element = mDecoder->GetMediaElement();
if (!element) {
NS_WARNING("Null element in MediaResource::MoveLoadsToBackground()");
@ -1219,7 +1218,7 @@ void MediaResource::MoveLoadsToBackground() {
if (NS_SUCCEEDED(mChannel->IsPending(&isPending)) &&
isPending) {
nsLoadFlags loadFlags;
rv = mChannel->GetLoadFlags(&loadFlags);
DebugOnly<nsresult> rv = mChannel->GetLoadFlags(&loadFlags);
NS_ASSERTION(NS_SUCCEEDED(rv), "GetLoadFlags() failed!");
loadFlags |= nsIRequest::LOAD_BACKGROUND;
@ -1230,7 +1229,7 @@ void MediaResource::MoveLoadsToBackground() {
void MediaResource::ModifyLoadFlags(nsLoadFlags aFlags)
{
nsCOMPtr<nsILoadGroup> loadGroup;
nsresult rv = mChannel->GetLoadGroup(getter_AddRefs(loadGroup));
DebugOnly<nsresult> rv = mChannel->GetLoadGroup(getter_AddRefs(loadGroup));
NS_ASSERTION(NS_SUCCEEDED(rv), "GetLoadGroup() failed!");
nsresult status;

View File

@ -43,6 +43,7 @@
#include "nsRect.h"
#include "nsIThreadManager.h"
#include "nsThreadUtils.h"
#include "CheckedInt.h"
@ -102,6 +103,21 @@ private:
ReentrantMonitor* mReentrantMonitor;
};
// Shuts down a thread asynchronously.
class ShutdownThreadEvent : public nsRunnable
{
public:
ShutdownThreadEvent(nsIThread* aThread) : mThread(aThread) {}
~ShutdownThreadEvent() {}
NS_IMETHOD Run() {
mThread->Shutdown();
mThread = nsnull;
return NS_OK;
}
private:
nsCOMPtr<nsIThread> mThread;
};
} // namespace mozilla
// Converts from number of audio frames (aFrames) to microseconds, given

View File

@ -169,21 +169,6 @@ public:
const PRUint32 mRate;
};
// Shuts down a thread asynchronously.
class ShutdownThreadEvent : public nsRunnable
{
public:
ShutdownThreadEvent(nsIThread* aThread) : mThread(aThread) {}
~ShutdownThreadEvent() {}
NS_IMETHOD Run() {
mThread->Shutdown();
mThread = nsnull;
return NS_OK;
}
private:
nsCOMPtr<nsIThread> mThread;
};
// Owns the global state machine thread and counts of
// state machine and decoder threads. There should
// only be one instance of this class.
@ -2163,7 +2148,9 @@ void nsBuiltinDecoderStateMachine::StartBuffering()
mState = DECODER_STATE_BUFFERING;
LOG(PR_LOG_DEBUG, ("%p Changed state from DECODING to BUFFERING, decoded for %.3lfs",
mDecoder.get(), decodeDuration.ToSeconds()));
#ifdef PR_LOGGING
nsMediaDecoder::Statistics stats = mDecoder->GetStatistics();
#endif
LOG(PR_LOG_DEBUG, ("%p Playback rate: %.1lfKB/s%s download rate: %.1lfKB/s%s",
mDecoder.get(),
stats.mPlaybackRate/1024, stats.mPlaybackRateReliable ? "" : " (unreliable)",

View File

@ -51,6 +51,7 @@
#include "prlog.h"
#include "nsIPrivateBrowsingService.h"
#include "mozilla/Preferences.h"
#include "FileBlockCache.h"
using namespace mozilla;
@ -136,7 +137,7 @@ public:
nsMediaCache() : mNextResourceID(1),
mReentrantMonitor("nsMediaCache.mReentrantMonitor"),
mFD(nsnull), mFDCurrentPos(0), mUpdateQueued(false)
mUpdateQueued(false)
#ifdef DEBUG
, mInUpdate(false)
#endif
@ -147,9 +148,8 @@ public:
NS_ASSERTION(mStreams.IsEmpty(), "Stream(s) still open!");
Truncate();
NS_ASSERTION(mIndex.Length() == 0, "Blocks leaked?");
if (mFD) {
PR_Close(mFD);
}
mFileCache->Close();
mFileCache = nsnull;
MOZ_COUNT_DTOR(nsMediaCache);
}
@ -175,8 +175,6 @@ public:
PRInt32* aBytes);
// This will fail if all aLength bytes are not read
nsresult ReadCacheFileAllBytes(PRInt64 aOffset, void* aData, PRInt32 aLength);
// This will fail if all aLength bytes are not written
nsresult WriteCacheFile(PRInt64 aOffset, const void* aData, PRInt32 aLength);
PRInt64 AllocateResourceID()
{
@ -360,11 +358,8 @@ protected:
ReentrantMonitor mReentrantMonitor;
// The Blocks describing the cache entries.
nsTArray<Block> mIndex;
// The file descriptor of the cache file. The file will be deleted
// by the operating system when this is closed.
PRFileDesc* mFD;
// The current file offset in the cache file.
PRInt64 mFDCurrentPos;
// Writer which performs IO, asynchronously writing cache blocks.
nsRefPtr<FileBlockCache> mFileCache;
// The list of free blocks; they are not ordered.
BlockList mFreeBlocks;
// True if an event to run Update() has been queued but not processed
@ -550,7 +545,7 @@ nsresult
nsMediaCache::Init()
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
NS_ASSERTION(!mFD, "Cache file already open?");
NS_ASSERTION(!mFileCache, "Cache file already open?");
// In single process Gecko, store the media cache in the profile directory
// so that multiple users can use separate media caches concurrently.
@ -593,8 +588,13 @@ nsMediaCache::Init()
rv = tmpFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0700);
NS_ENSURE_SUCCESS(rv,rv);
PRFileDesc* fileDesc = nsnull;
rv = tmpFile->OpenNSPRFileDesc(PR_RDWR | nsILocalFile::DELETE_ON_CLOSE,
PR_IRWXU, &mFD);
PR_IRWXU, &fileDesc);
NS_ENSURE_SUCCESS(rv,rv);
mFileCache = new FileBlockCache();
rv = mFileCache->Open(fileDesc);
NS_ENSURE_SUCCESS(rv,rv);
#ifdef PR_LOGGING
@ -631,9 +631,9 @@ nsMediaCache::FlushInternal()
// Truncate file, close it, and reopen
Truncate();
NS_ASSERTION(mIndex.Length() == 0, "Blocks leaked?");
if (mFD) {
PR_Close(mFD);
mFD = nsnull;
if (mFileCache) {
mFileCache->Close();
mFileCache = nsnull;
}
Init();
}
@ -679,21 +679,10 @@ nsMediaCache::ReadCacheFile(PRInt64 aOffset, void* aData, PRInt32 aLength,
{
mReentrantMonitor.AssertCurrentThreadIn();
if (!mFD)
if (!mFileCache)
return NS_ERROR_FAILURE;
if (mFDCurrentPos != aOffset) {
PROffset64 offset = PR_Seek64(mFD, aOffset, PR_SEEK_SET);
if (offset != aOffset)
return NS_ERROR_FAILURE;
mFDCurrentPos = aOffset;
}
PRInt32 amount = PR_Read(mFD, aData, aLength);
if (amount <= 0)
return NS_ERROR_FAILURE;
mFDCurrentPos += amount;
*aBytes = amount;
return NS_OK;
return mFileCache->Read(aOffset, reinterpret_cast<PRUint8*>(aData), aLength, aBytes);
}
nsresult
@ -719,35 +708,6 @@ nsMediaCache::ReadCacheFileAllBytes(PRInt64 aOffset, void* aData, PRInt32 aLengt
return NS_OK;
}
nsresult
nsMediaCache::WriteCacheFile(PRInt64 aOffset, const void* aData, PRInt32 aLength)
{
mReentrantMonitor.AssertCurrentThreadIn();
if (!mFD)
return NS_ERROR_FAILURE;
if (mFDCurrentPos != aOffset) {
PROffset64 offset = PR_Seek64(mFD, aOffset, PR_SEEK_SET);
if (offset != aOffset)
return NS_ERROR_FAILURE;
mFDCurrentPos = aOffset;
}
const char* data = static_cast<const char*>(aData);
PRInt32 length = aLength;
while (length > 0) {
PRInt32 amount = PR_Write(mFD, data, length);
if (amount <= 0)
return NS_ERROR_FAILURE;
mFDCurrentPos += amount;
length -= amount;
data += amount;
}
return NS_OK;
}
static PRInt32 GetMaxBlocks()
{
// We look up the cache size every time. This means dynamic changes
@ -1164,27 +1124,18 @@ nsMediaCache::Update()
PredictNextUse(now, destinationBlockIndex) > latestPredictedUseForOverflow) {
// Reuse blocks in the main part of the cache that are less useful than
// the least useful overflow blocks
char buf[BLOCK_SIZE];
nsresult rv = ReadCacheFileAllBytes(blockIndex*BLOCK_SIZE, buf, sizeof(buf));
nsresult rv = mFileCache->MoveBlock(blockIndex, destinationBlockIndex);
if (NS_SUCCEEDED(rv)) {
rv = WriteCacheFile(destinationBlockIndex*BLOCK_SIZE, buf, BLOCK_SIZE);
if (NS_SUCCEEDED(rv)) {
// We successfully copied the file data.
LOG(PR_LOG_DEBUG, ("Swapping blocks %d and %d (trimming cache)",
blockIndex, destinationBlockIndex));
// Swapping the block metadata here lets us maintain the
// correct positions in the linked lists
SwapBlocks(blockIndex, destinationBlockIndex);
} else {
// If the write fails we may have corrupted the destination
// block. Free it now.
LOG(PR_LOG_DEBUG, ("Released block %d (trimming cache)",
destinationBlockIndex));
FreeBlock(destinationBlockIndex);
}
// Free the overflowing block even if the copy failed.
LOG(PR_LOG_DEBUG, ("Released block %d (trimming cache)",
blockIndex));
// We successfully copied the file data.
LOG(PR_LOG_DEBUG, ("Swapping blocks %d and %d (trimming cache)",
blockIndex, destinationBlockIndex));
// Swapping the block metadata here lets us maintain the
// correct positions in the linked lists
SwapBlocks(blockIndex, destinationBlockIndex);
//Free the overflowing block even if the copy failed.
LOG(PR_LOG_DEBUG, ("Released block %d (trimming cache)", blockIndex));
FreeBlock(blockIndex);
}
} else {
@ -1563,7 +1514,7 @@ nsMediaCache::AllocateAndWriteBlock(nsMediaCacheStream* aStream, const void* aDa
}
}
nsresult rv = WriteCacheFile(blockIndex*BLOCK_SIZE, aData, BLOCK_SIZE);
nsresult rv = mFileCache->WriteBlock(blockIndex, reinterpret_cast<const PRUint8*>(aData));
if (NS_FAILED(rv)) {
LOG(PR_LOG_DEBUG, ("Released block %d from stream %p block %d(%lld)",
blockIndex, aStream, streamBlockIndex, (long long)streamBlockIndex*BLOCK_SIZE));

View File

@ -1165,7 +1165,7 @@ nsresult nsOggReader::SeekBisection(PRInt64 aTarget,
ogg_int64_t seekTarget = aTarget;
PRInt64 seekLowerBound = NS_MAX(static_cast<PRInt64>(0), aTarget - aFuzz);
int hops = 0;
ogg_int64_t previousGuess = -1;
DebugOnly<ogg_int64_t> previousGuess = -1;
int backsteps = 0;
const int maxBackStep = 10;
NS_ASSERTION(static_cast<PRUint64>(PAGE_STEP) * pow(2.0, maxBackStep) < PR_INT32_MAX,

View File

@ -61,6 +61,7 @@
#include "nsCCUncollectableMarker.h"
using namespace mozilla::scache;
using namespace mozilla;
static const char kXBLCachePrefix[] = "xblcache";
@ -272,7 +273,7 @@ nsXBLDocGlobalObject::SetContext(nsIScriptContext *aScriptContext)
// NOTE: We init this context with a NULL global, so we automatically
// hook up to the existing nsIScriptGlobalObject global setup by
// nsGlobalWindow.
nsresult rv;
DebugOnly<nsresult> rv;
rv = aScriptContext->InitContext();
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Script Language's InitContext failed");
aScriptContext->SetGCOnDestruction(false);

View File

@ -9263,9 +9263,7 @@ nsDocShell::OnNewURI(nsIURI * aURI, nsIChannel * aChannel, nsISupports* aOwner,
}
#endif
bool updateHistory = true;
bool equalUri = false;
bool shAvailable = true;
// Get the post data from the channel
nsCOMPtr<nsIInputStream> inputStream;
@ -9292,6 +9290,15 @@ nsDocShell::OnNewURI(nsIURI * aURI, nsIChannel * aChannel, nsISupports* aOwner,
}
}
}
// Determine if this type of load should update history.
bool updateGHistory = !(aLoadType == LOAD_BYPASS_HISTORY ||
aLoadType == LOAD_ERROR_PAGE ||
aLoadType & LOAD_CMD_HISTORY);
// We don't update session history on reload.
bool updateSHistory = updateGHistory && (!(aLoadType & LOAD_CMD_RELOAD));
/* Create SH Entry (mLSHE) only if there is a SessionHistory object (mSessionHistory) in
* the current frame or in the root docshell
*/
@ -9299,26 +9306,26 @@ nsDocShell::OnNewURI(nsIURI * aURI, nsIChannel * aChannel, nsISupports* aOwner,
if (!rootSH) {
// Get the handle to SH from the root docshell
GetRootSessionHistory(getter_AddRefs(rootSH));
if (!rootSH)
shAvailable = false;
if (!rootSH) {
updateSHistory = false;
updateGHistory = false; // XXX Why global history too?
}
} // rootSH
// Determine if this type of load should update history.
if (aLoadType == LOAD_BYPASS_HISTORY ||
aLoadType == LOAD_ERROR_PAGE ||
aLoadType & LOAD_CMD_HISTORY ||
aLoadType & LOAD_CMD_RELOAD)
updateHistory = false;
// Check if the url to be loaded is the same as the one already loaded.
if (mCurrentURI)
aURI->Equals(mCurrentURI, &equalUri);
#ifdef DEBUG
bool shAvailable = (rootSH != nsnull);
// XXX This log message is almost useless because |updateSHistory|
// and |updateGHistory| are not correct at this point.
PR_LOG(gDocShellLog, PR_LOG_DEBUG,
(" shAvailable=%i updateHistory=%i equalURI=%i\n",
shAvailable, updateHistory, equalUri));
(" shAvailable=%i updateSHistory=%i updateGHistory=%i"
" equalURI=%i\n",
shAvailable, updateSHistory, updateGHistory, equalUri));
if (shAvailable && mCurrentURI && !mOSHE && aLoadType != LOAD_ERROR_PAGE) {
NS_ASSERTION(NS_IsAboutBlank(mCurrentURI), "no SHEntry for a non-transient viewer?");
@ -9366,8 +9373,9 @@ nsDocShell::OnNewURI(nsIURI * aURI, nsIChannel * aChannel, nsISupports* aOwner,
(aLoadType == LOAD_RELOAD_BYPASS_CACHE ||
aLoadType == LOAD_RELOAD_BYPASS_PROXY ||
aLoadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE)) {
NS_ASSERTION(!updateHistory,
"We shouldn't be updating history for forced reloads!");
NS_ASSERTION(!updateSHistory,
"We shouldn't be updating session history for forced"
" reloads!");
nsCOMPtr<nsICachingChannel> cacheChannel(do_QueryInterface(aChannel));
nsCOMPtr<nsISupports> cacheKey;
@ -9405,7 +9413,7 @@ nsDocShell::OnNewURI(nsIURI * aURI, nsIChannel * aChannel, nsISupports* aOwner,
ClearFrameHistory(mOSHE);
}
if (updateHistory && shAvailable) {
if (updateSHistory) {
// Update session history if necessary...
if (!mLSHE && (mItemType == typeContent) && mURIResultedInDocument) {
/* This is a fresh page getting loaded for the first time
@ -9415,24 +9423,31 @@ nsDocShell::OnNewURI(nsIURI * aURI, nsIChannel * aChannel, nsISupports* aOwner,
(void) AddToSessionHistory(aURI, aChannel, aOwner, aCloneSHChildren,
getter_AddRefs(mLSHE));
}
}
if (aAddToGlobalHistory) {
// If this is a POST request, we do not want to include this in global
// history.
if (!ChannelIsPost(aChannel)) {
nsCOMPtr<nsIURI> previousURI;
PRUint32 previousFlags = 0;
ExtractLastVisit(aChannel, getter_AddRefs(previousURI),
&previousFlags);
// If this is a POST request, we do not want to include this in global
// history.
if (updateGHistory &&
aAddToGlobalHistory &&
!ChannelIsPost(aChannel)) {
nsCOMPtr<nsIURI> previousURI;
PRUint32 previousFlags = 0;
nsCOMPtr<nsIURI> referrer;
// Treat referrer as null if there is an error getting it.
(void)NS_GetReferrerFromChannel(aChannel,
getter_AddRefs(referrer));
AddURIVisit(aURI, referrer, previousURI, previousFlags);
}
if (aLoadType & LOAD_CMD_RELOAD) {
// On a reload request, we don't set redirecting flags.
previousURI = aURI;
} else {
ExtractLastVisit(aChannel, getter_AddRefs(previousURI),
&previousFlags);
}
// Note: We don't use |referrer| when our global history is
// based on IHistory.
nsCOMPtr<nsIURI> referrer;
// Treat referrer as null if there is an error getting it.
(void)NS_GetReferrerFromChannel(aChannel, getter_AddRefs(referrer));
AddURIVisit(aURI, referrer, previousURI, previousFlags);
}
// If this was a history load or a refresh,
@ -11766,6 +11781,42 @@ nsDocShell::GetIsBrowserFrame(bool *aOut)
NS_IMETHODIMP
nsDocShell::SetIsBrowserFrame(bool aValue)
{
// Disallow transitions from browser frame to not-browser-frame. Once a
// browser frame, always a browser frame. (Otherwise, observers of
// docshell-marked-as-browser-frame would have to distinguish between
// newly-created browser frames and frames which went from true to false back
// to true.)
NS_ENSURE_STATE(!mIsBrowserFrame);
bool wasBrowserFrame = mIsBrowserFrame;
mIsBrowserFrame = aValue;
if (aValue && !wasBrowserFrame) {
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
if (os) {
os->NotifyObservers(GetAsSupports(this),
"docshell-marked-as-browser-frame", NULL);
}
}
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetContainedInBrowserFrame(bool *aOut)
{
*aOut = false;
if (mIsBrowserFrame) {
*aOut = true;
return NS_OK;
}
nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
GetSameTypeParent(getter_AddRefs(parentAsItem));
nsCOMPtr<nsIDocShell> parent = do_QueryInterface(parentAsItem);
if (parent) {
return parent->GetContainedInBrowserFrame(aOut);
}
return NS_OK;
}

View File

@ -72,7 +72,7 @@ interface nsIPrincipal;
interface nsIWebBrowserPrint;
interface nsIVariant;
[scriptable, uuid(DBD39C21-5788-4C68-9D97-0FCEE289BCE1)]
[scriptable, uuid(c7325422-817e-4321-957a-c0bdd764941d)]
interface nsIDocShell : nsISupports
{
/**
@ -614,4 +614,10 @@ interface nsIDocShell : nsISupports
* See also nsIMozBrowserFrame.
*/
attribute bool isBrowserFrame;
/*
* Is this docshell contained in an <iframe mozbrowser>, either directly or
* indirectly?
*/
readonly attribute bool containedInBrowserFrame;
};

View File

@ -0,0 +1,283 @@
/* 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/. */
"use strict";
let Cu = Components.utils;
let Ci = Components.interfaces;
let Cc = Components.classes;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed";
const BROWSER_FRAMES_ENABLED_PREF = "dom.mozBrowserFramesEnabled";
/**
* The BrowserElementAPI implements <iframe mozbrowser>.
*
* We detect windows and docshells contained inside <iframe mozbrowser>s and
* alter their behavior so that the page inside the iframe can't tell that it's
* framed and the page outside the iframe can observe changes within the iframe
* (e.g. loadstart/loadstart, locationchange).
*/
function BrowserElementAPI() {}
BrowserElementAPI.prototype = {
classID: Components.ID("{5d6fcab3-6c12-4db6-80fb-352df7a41602}"),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
Ci.nsISupportsWeakReference]),
/**
* The keys of this map are the set of chrome event handlers we've observed
* which contain a mozbrowser window.
*
* The values in this map are ignored.
*/
_chromeEventHandlersWatching: new WeakMap(),
/**
* The keys of this map are the set of windows we've observed that are
* directly contained in <iframe mozbrowser>s.
*
* The values in this map are ignored.
*/
_topLevelBrowserWindows: new WeakMap(),
_browserFramesPrefEnabled: function BA_browserFramesPrefEnabled() {
var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
try {
return prefs.getBoolPref(BROWSER_FRAMES_ENABLED_PREF);
}
catch(e) {
return false;
}
},
/**
* Called on browser start, and also when we observe a change in
* the browser-frames-enabled pref.
*/
_init: function BA_init() {
if (this._initialized) {
return;
}
// If browser frames are disabled, watch the pref so we can enable
// ourselves if the pref is flipped. This is important for tests, if
// nothing else.
if (!this._browserFramesPrefEnabled()) {
var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
prefs.addObserver(BROWSER_FRAMES_ENABLED_PREF, this, /* ownsWeak = */ true);
return;
}
this._initialized = true;
this._progressListener._browserElementAPI = this;
var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
os.addObserver(this, 'content-document-global-created', /* ownsWeak = */ true);
os.addObserver(this, 'docshell-marked-as-browser-frame', /* ownsWeak = */ true);
},
/**
* Called when we observe a docshell-marked-as-browser-frame event, which
* happens when a docshell is created inside an <iframe mozbrowser>.
*
* A docshell may not be un-marked as a browser frame -- this ensures that
* this event will never fire twice for the same docshell, which guarantees
* that we'll never register duplicate listeners.
*/
_observeDocshellMarkedAsBrowserFrame: function BA_observeDocshellMarkedAsBrowserFrame(docshell) {
docshell.QueryInterface(Ci.nsIWebProgress)
.addProgressListener(this._progressListener,
Ci.nsIWebProgress.NOTIFY_LOCATION |
Ci.nsIWebProgress.NOTIFY_STATE_WINDOW);
},
/**
* Called when a content window is created. If the window is directly or
* indirectly contained in an <iframe mozbrowser>, we'll modify it.
*/
_observeContentGlobalCreated: function BA_observeContentGlobalCreated(win) {
var docshell = win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell);
// If this window is not directly or indirectly inside an
// <iframe mozbrowser>, BrowserElementAPI does nothing to it.
if (!docshell.containedInBrowserFrame) {
return;
}
this._initBrowserWindow(win, docshell.isBrowserFrame);
// If this window is directly contained in an <iframe mozbrowser>, do some
// extra work.
if (docshell.isBrowserFrame) {
this._topLevelBrowserWindows.set(win, true);
this._initTopLevelBrowserWindow(win);
}
},
/**
* Initialize a content window which is indirectly or directly contained by
* an <iframe mozbrowser>.
*
* |isTopLevel| is true iff |win| is directly contained by an
* <iframe mozbrowser>.
*/
_initBrowserWindow: function BA_initBrowserWindow(win, isTopLevel) {
// XPCNativeWrapper.unwrap gets us the object that content sees; this is
// the object object that we must define properties on. Otherwise, the
// properties will be visible only to chrome!
var unwrappedWin = XPCNativeWrapper.unwrap(win);
Object.defineProperty(unwrappedWin, 'top', {
get: function() {
if (isTopLevel) {
return win;
}
// Call the mozbrowser-aware |top| method we presumably defined on our
// parent.
return XPCNativeWrapper.unwrap(win.parent).top;
}
});
Object.defineProperty(unwrappedWin, 'parent', {
get: function() {
if (isTopLevel) {
return win;
}
return win.parent;
}
});
Object.defineProperty(unwrappedWin, 'frameElement', {
get: function() {
if (isTopLevel) {
return null;
}
return win.frameElement;
}
});
},
/**
* Initialize a content window directly contained by an <iframe mozbrowser>.
*/
_initTopLevelBrowserWindow: function BA_initTopLevelBrowserWindow(win) {
// If we haven't seen this window's chrome event handler before, register
// listeners on it.
var chromeHandler = win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell)
.chromeEventHandler;
if (chromeHandler && !this._chromeEventHandlersWatching.has(chromeHandler)) {
this._chromeEventHandlersWatching.set(chromeHandler, true);
this._addChromeEventHandlerListeners(chromeHandler);
}
},
/**
* Add some listeners to a chrome event handler. Don't call this twice for
* the same chrome event handler or we'll get duplicate listeners!
*/
_addChromeEventHandlerListeners: function BA_addChromeEventHandlerListeners(chromeHandler) {
var browserElementAPI = this;
// Listen for DOMTitleChanged events on top-level <iframe mozbrowser>
// windows. (The chrome event handler handles
chromeHandler.addEventListener(
'DOMTitleChanged',
function(e) {
var win = e.target.defaultView;
if (browserElementAPI._topLevelBrowserWindows.has(win)) {
browserElementAPI._fireCustomEvent('titlechange', e.target.title,
win, win.frameElement);
}
},
/* useCapture = */ false,
/* wantsUntrusted = */ false);
},
/**
* Asynchronously fire a vanilla event at the given window's frame element.
* (Presumably, the window's frame element is an <iframe mozbrowser>.)
*
* We'll prepend 'mozbrowser' to the event's name.
*/
_fireEvent: function BA_fireEvent(name, win) {
// Because we're chrome, win.frameElement ignores <iframe mozbrowser>
// boundaries, as desired.
var evt = new win.Event('mozbrowser' + name);
win.setTimeout(function() { win.frameElement.dispatchEvent(evt) }, 0);
},
/**
* Like _fireEvent, but fire a customevent with the given data, instead of a
* vanilla event.
*/
_fireCustomEvent: function BA_fireCustomEvent(name, data, win) {
var evt = new win.CustomEvent('mozbrowser' + name, {detail: data});
win.setTimeout(function() { win.frameElement.dispatchEvent(evt) }, 0);
},
/**
* An nsIWebProgressListener registered on docshells directly contained in an
* <iframe mozbrowser>.
*/
_progressListener: {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
Ci.nsISupportsWeakReference,
Ci.nsISupports]),
_getWindow: function(webProgress) {
return webProgress.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindow);
},
onLocationChange: function(webProgress, request, location, flags) {
this._browserElementAPI._fireCustomEvent('locationchange', location.spec,
this._getWindow(webProgress));
},
onStateChange: function(webProgress, request, stateFlags, status) {
if (stateFlags & Ci.nsIWebProgressListener.STATE_START) {
this._browserElementAPI._fireEvent('loadstart', this._getWindow(webProgress));
}
if (stateFlags & Ci.nsIWebProgressListener.STATE_STOP) {
this._browserElementAPI._fireEvent('loadend', this._getWindow(webProgress));
}
},
onStatusChange: function(webProgress, request, status, message) {},
onProgressChange: function(webProgress, request, curSelfProgress,
maxSelfProgress, curTotalProgress, maxTotalProgress) {},
onSecurityChange: function(webProgress, request, aState) {}
},
/**
* nsIObserver::Observe
*/
observe: function BA_observe(subject, topic, data) {
switch(topic) {
case 'app-startup':
this._init();
break;
case 'content-document-global-created':
this._observeContentGlobalCreated(subject);
break;
case 'docshell-marked-as-browser-frame':
this._observeDocshellMarkedAsBrowserFrame(subject);
break;
case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID:
if (data == BROWSER_FRAMES_ENABLED_PREF) {
this._init();
}
break;
}
},
};
var NSGetFactory = XPCOMUtils.generateNSGetFactory([BrowserElementAPI]);

View File

@ -0,0 +1,3 @@
component {5d6fcab3-6c12-4db6-80fb-352df7a41602} BrowserElementAPI.js
contract @mozilla.org/browser-element-api;1 {5d6fcab3-6c12-4db6-80fb-352df7a41602}
category app-startup BrowserElementAPI service,@mozilla.org/browser-element-api;1

View File

@ -54,6 +54,8 @@ DIRS = \
EXTRA_PP_COMPONENTS = \
ConsoleAPI.js \
ConsoleAPI.manifest \
BrowserElementAPI.js \
BrowserElementAPI.manifest \
$(NULL)
EXTRA_JS_MODULES = ConsoleAPIStorage.jsm \

View File

@ -51,6 +51,7 @@
#include "nsRefreshDriver.h"
#include "nsDOMTouchEvent.h"
#include "nsIDOMTouchEvent.h"
#include "nsObjectLoadingContent.h"
#include "nsIScrollableFrame.h"
@ -76,6 +77,7 @@
#include "nsCSSProps.h"
#include "nsDOMFile.h"
#include "BasicLayers.h"
#include "nsTArrayHelpers.h"
#if defined(MOZ_X11) && defined(MOZ_WIDGET_GTK2)
#include <gdk/gdk.h>
@ -2230,3 +2232,26 @@ nsDOMWindowUtils::GetPaintingSuppressed(bool *aPaintingSuppressed)
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetPlugins(JSContext* cx, jsval* aPlugins)
{
if (!IsUniversalXPConnectCapable()) {
return NS_ERROR_DOM_SECURITY_ERR;
}
nsIDOMDocument* ddoc = mWindow->GetExtantDocument();
nsresult rv;
nsCOMPtr<nsIDocument> doc = do_QueryInterface(ddoc, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsTArray<nsIObjectLoadingContent*> plugins;
doc->GetPlugins(plugins);
JSObject* jsPlugins = nsnull;
rv = nsTArrayToJSArray(cx, plugins, &jsPlugins);
NS_ENSURE_SUCCESS(rv, rv);
*aPlugins = OBJECT_TO_JSVAL(jsPlugins);
return NS_OK;
}

View File

@ -3088,47 +3088,14 @@ nsGlobalWindow::GetPerformance(nsIDOMPerformance** aPerformance)
return NS_OK;
}
/**
* GetScriptableParent is called when script reads window.parent.
*
* In contrast to GetRealParent, GetScriptableParent respects <iframe
* mozbrowser> boundaries, so if |this| is contained by an <iframe
* mozbrowser>, we will return |this| as its own parent.
*/
NS_IMETHODIMP
nsGlobalWindow::GetScriptableParent(nsIDOMWindow** aParent)
nsGlobalWindow::GetParent(nsIDOMWindow** aParent)
{
FORWARD_TO_OUTER(GetScriptableParent, (aParent), NS_ERROR_NOT_INITIALIZED);
*aParent = NULL;
if (!mDocShell) {
return NS_OK;
}
bool isMozBrowser = false;
mDocShell->GetIsBrowserFrame(&isMozBrowser);
if (isMozBrowser) {
nsCOMPtr<nsIDOMWindow> parent = static_cast<nsIDOMWindow*>(this);
parent.swap(*aParent);
return NS_OK;
}
return GetRealParent(aParent);
}
/**
* nsIDOMWindow::GetParent (when called from C++) is just a wrapper around
* GetRealParent.
*/
NS_IMETHODIMP
nsGlobalWindow::GetRealParent(nsIDOMWindow** aParent)
{
FORWARD_TO_OUTER(GetRealParent, (aParent), NS_ERROR_NOT_INITIALIZED);
FORWARD_TO_OUTER(GetParent, (aParent), NS_ERROR_NOT_INITIALIZED);
*aParent = nsnull;
if (!mDocShell) {
if (!mDocShell)
return NS_OK;
}
nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(mDocShell));
NS_ENSURE_TRUE(docShellAsItem, NS_ERROR_FAILURE);
@ -3148,62 +3115,21 @@ nsGlobalWindow::GetRealParent(nsIDOMWindow** aParent)
return NS_OK;
}
/**
* GetScriptableTop is called when script reads window.top.
*
* In contrast to GetRealTop, GetScriptableTop respects <iframe mozbrowser>
* boundaries. If we encounter a window owned by an <iframe mozbrowser> while
* walking up the window hierarchy, we'll stop and return that window.
*/
NS_IMETHODIMP
nsGlobalWindow::GetScriptableTop(nsIDOMWindow **aTop)
nsGlobalWindow::GetTop(nsIDOMWindow** aTop)
{
return GetTopImpl(aTop, /* aScriptable = */ true);
}
FORWARD_TO_OUTER(GetTop, (aTop), NS_ERROR_NOT_INITIALIZED);
/**
* nsIDOMWindow::GetTop (when called from C++) is just a wrapper around
* GetRealTop.
*/
NS_IMETHODIMP
nsGlobalWindow::GetRealTop(nsIDOMWindow** aTop)
{
return GetTopImpl(aTop, /* aScriptable = */ false);
}
nsresult
nsGlobalWindow::GetTopImpl(nsIDOMWindow** aTop, bool aScriptable)
{
FORWARD_TO_OUTER(GetTopImpl, (aTop, aScriptable), NS_ERROR_NOT_INITIALIZED);
*aTop = nsnull;
if (mDocShell) {
nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(mDocShell));
nsCOMPtr<nsIDocShellTreeItem> root;
docShellAsItem->GetSameTypeRootTreeItem(getter_AddRefs(root));
// Walk up the parent chain.
nsCOMPtr<nsIDOMWindow> prevParent = this;
nsCOMPtr<nsIDOMWindow> parent = this;
do {
if (!parent) {
break;
if (root) {
nsCOMPtr<nsIDOMWindow> top(do_GetInterface(root));
top.swap(*aTop);
}
prevParent = parent;
nsCOMPtr<nsIDOMWindow> newParent;
nsresult rv;
if (aScriptable) {
rv = parent->GetScriptableParent(getter_AddRefs(newParent));
}
else {
rv = parent->GetParent(getter_AddRefs(newParent));
}
NS_ENSURE_SUCCESS(rv, rv);
parent = newParent;
} while (parent != prevParent);
if (parent) {
parent.swap(*aTop);
}
return NS_OK;
@ -7070,43 +6996,12 @@ nsGlobalWindow::CacheXBLPrototypeHandler(nsXBLPrototypeHandler* aKey,
mCachedXBLPrototypeHandlers.Put(aKey, aHandler.get());
}
/**
* GetScriptableFrameElement is called when script reads
* nsIGlobalWindow::frameElement.
*
* In contrast to GetRealFrameElement, GetScriptableFrameElement says that the
* window contained by an <iframe mozbrowser> has no frame element
* (effectively treating a mozbrowser the same as a content/chrome boundary).
*/
NS_IMETHODIMP
nsGlobalWindow::GetScriptableFrameElement(nsIDOMElement** aFrameElement)
nsGlobalWindow::GetFrameElement(nsIDOMElement** aFrameElement)
{
FORWARD_TO_OUTER(GetScriptableFrameElement, (aFrameElement), NS_ERROR_NOT_INITIALIZED);
*aFrameElement = NULL;
FORWARD_TO_OUTER(GetFrameElement, (aFrameElement), NS_ERROR_NOT_INITIALIZED);
if (!mDocShell) {
return NS_OK;
}
bool isMozBrowser = false;
mDocShell->GetIsBrowserFrame(&isMozBrowser);
if (isMozBrowser) {
return NS_OK;
}
return GetFrameElement(aFrameElement);
}
/**
* nsIGlobalWindow::GetFrameElement (when called from C++) is just a wrapper
* around GetRealFrameElement.
*/
NS_IMETHODIMP
nsGlobalWindow::GetRealFrameElement(nsIDOMElement** aFrameElement)
{
FORWARD_TO_OUTER(GetRealFrameElement, (aFrameElement), NS_ERROR_NOT_INITIALIZED);
*aFrameElement = NULL;
*aFrameElement = nsnull;
nsCOMPtr<nsIDocShellTreeItem> docShellTI(do_QueryInterface(mDocShell));
@ -10332,7 +10227,7 @@ nsGlobalWindow::DisableDeviceSensor(PRUint32 aType)
PRUint32 doomedElement = -1;
for (int i = 0; i < mEnabledSensors.Length(); i++) {
if (mEnabledSensors[i] == aType) {
doomedElement = -1;
doomedElement = i;
break;
}
}

View File

@ -402,16 +402,6 @@ public:
return FromSupports(wrapper->Native());
}
/**
* Wrap nsIDOMWindow::GetTop so we can overload the inline GetTop()
* implementation below. (nsIDOMWindow::GetTop simply calls
* nsIDOMWindow::GetRealTop().)
*/
nsresult GetTop(nsIDOMWindow **aWindow)
{
return nsIDOMWindow::GetTop(aWindow);
}
inline nsGlobalWindow *GetTop()
{
nsCOMPtr<nsIDOMWindow> top;
@ -573,9 +563,6 @@ public:
void AddEventTargetObject(nsDOMEventTargetHelper* aObject);
void RemoveEventTargetObject(nsDOMEventTargetHelper* aObject);
private:
// Implements Get{Real,Scriptable}Top.
nsresult GetTopImpl(nsIDOMWindow **aWindow, bool aScriptable);
protected:
friend class HashchangeCallback;

View File

@ -16,8 +16,8 @@ class nsIEventTarget;
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothAdapter : public nsIDOMBluetoothAdapter
, public nsDOMEventTargetHelper
class BluetoothAdapter : public nsDOMEventTargetHelper
, public nsIDOMBluetoothAdapter
{
public:
NS_DECL_ISUPPORTS

View File

@ -12,8 +12,8 @@
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothDevice : public nsIDOMBluetoothDevice
, public nsDOMEventTargetHelper
class BluetoothDevice : public nsDOMEventTargetHelper
, public nsIDOMBluetoothDevice
{
public:
NS_DECL_ISUPPORTS

View File

@ -70,7 +70,7 @@ interface nsIDOMMozURLProperty : nsISupports
* @see <http://www.whatwg.org/html/#window>
*/
[scriptable, uuid(17400E2B-F78B-4E69-B500-C2A3135A40FD)]
[scriptable, uuid(f6e3b10d-d5f4-4fcd-aa4c-5f98626d428a)]
interface nsIDOMWindow : nsISupports
{
// the current browsing context
@ -134,91 +134,25 @@ interface nsIDOMWindow : nsISupports
readonly attribute unsigned long length;
/**
* |top| gets the root of the window hierarchy.
* Accessor for the root of this hierarchy of windows. This root may
* be the window itself if there is no parent, or if the parent is
* of different type (i.e. this does not cross chrome-content
* boundaries).
*
* This function does not cross chrome-content boundaries, so if this
* window's parent is of a different type, |top| will return this window.
*
* When script reads the top property, we run GetScriptableTop, which
* will not cross an <iframe mozbrowser> boundary.
*
* In contrast, C++ calls to GetTop are forwarded to GetRealTop, which
* ignores <iframe mozbrowser> boundaries.
*
* This property is "replaceable" in JavaScript.
*/
[binaryname(ScriptableTop)]
* This property is "replaceable" in JavaScript */
readonly attribute nsIDOMWindow top;
/**
* You shouldn't need to call this function directly; call GetTop instead.
*/
[noscript]
readonly attribute nsIDOMWindow realTop;
%{C++
nsresult GetTop(nsIDOMWindow **aWindow)
{
return GetRealTop(aWindow);
}
%}
/**
* |parent| gets this window's parent window. If this window has no parent,
* we return the window itself.
*
* This property does not cross chrome-content boundaries, so if this
* window's parent is of a different type, we return the window itself as its
* parent.
*
* When script reads the property (or when C++ calls ScriptableTop), this
* property does not cross <iframe mozbrowser> boundaries. In contrast, when
* C++ calls GetParent, we ignore the mozbrowser attribute.
*/
[binaryname(ScriptableParent)]
readonly attribute nsIDOMWindow parent;
/**
* You shouldn't need to read this property directly; call GetParent instead.
*/
[noscript]
readonly attribute nsIDOMWindow realParent;
%{C++
inline nsresult GetParent(nsIDOMWindow **aWindow)
{
return GetRealParent(aWindow);
}
%}
attribute nsIDOMWindow opener;
/**
* |frameElement| gets this window's <iframe> or <frame> element, if it has
* one.
*
* When script reads this property (or when C++ calls
* ScriptableFrameElement), we return |null| if the window is inside an
* <iframe mozbrowser>. In contrast, when C++ calls GetFrameElement, we
* ignore the mozbrowser attribute.
* Accessor for this window's parent window, or the window itself if
* there is no parent, or if the parent is of different type
* (i.e. this does not cross chrome-content boundaries).
*/
[binaryname(ScriptableFrameElement)]
readonly attribute nsIDOMWindow parent;
readonly attribute nsIDOMElement frameElement;
/**
* You shouldn't need to read this property directly; call GetFrameElement
* instead.
*/
[noscript]
readonly attribute nsIDOMElement realFrameElement;
%{C++
inline nsresult GetFrameElement(nsIDOMElement **aElement)
{
return GetRealFrameElement(aElement);
}
%}
// the user agent
readonly attribute nsIDOMNavigator navigator;

View File

@ -70,7 +70,7 @@ interface nsIDOMFile;
interface nsIFile;
interface nsIDOMTouch;
[scriptable, uuid(43feb172-30e1-4ff1-b021-004f973da516)]
[scriptable, uuid(c7f303a1-4f7b-4d38-a192-c3f0e25dadb1)]
interface nsIDOMWindowUtils : nsISupports {
/**
@ -1099,4 +1099,15 @@ interface nsIDOMWindowUtils : nsISupports {
* otherwise.
*/
readonly attribute boolean paintingSuppressed;
/**
* Returns an array of plugins on the page for opt-in activation.
*
* Cannot be accessed from unprivileged context (not content-accessible).
* Will throw a DOM security error if called without UniversalXPConnect
* privileges.
*
*/
[implicit_jscontext]
readonly attribute jsval plugins;
};

View File

@ -48,9 +48,9 @@ namespace mozilla {
namespace dom {
namespace sms {
class SmsManager : public nsIDOMMozSmsManager
class SmsManager : public nsDOMEventTargetHelper
, public nsIDOMMozSmsManager
, public nsIObserver
, public nsDOMEventTargetHelper
{
public:
NS_DECL_ISUPPORTS

View File

@ -49,8 +49,8 @@ namespace dom {
namespace sms {
class SmsManager;
class SmsRequest : public nsIDOMMozSmsRequest
, public nsDOMEventTargetHelper
class SmsRequest : public nsDOMEventTargetHelper
, public nsIDOMMozSmsRequest
{
public:
friend class SmsRequestManager;

View File

@ -437,12 +437,15 @@ const GET_RESPONSE_EF_SIZE_BYTES = 15;
const EF_PATH_MF_SIM = "3f00";
const EF_PATH_DF_TELECOM = "7f10";
// Status code for ICC I/O,
// see GSM11.11 and TS 51.011 clause 9.4.
const STATUS_NORMAL_ENDING = 0x90;
const STATUS_NORMAL_ENDING_WITH_EXTRA = 0x91;
const STATUS_WITH_SIM_DATA = 0x9e;
const STATUS_WITH_RESPONSE_DATA = 0x9f;
// Status code of sw1 for ICC I/O,
// see GSM11.11 and TS 51.011 clause 9.4, and ISO 7816-4
const ICC_STATUS_NORMAL_ENDING = 0x90;
const ICC_STATUS_NORMAL_ENDING_WITH_EXTRA = 0x91;
const ICC_STATUS_WITH_SIM_DATA = 0x9e;
const ICC_STATUS_WITH_RESPONSE_DATA = 0x9f;
const ICC_STATUS_ERROR_WRONG_LENGTH = 0x67;
const ICC_STATUS_ERROR_COMMAND_NOT_ALLOWED = 0x69;
const ICC_STATUS_ERROR_WRONG_PARAMETERS = 0x6a;
/**
* GSM PDU constants

View File

@ -777,7 +777,7 @@ let RIL = {
let token = Buf.newParcel(REQUEST_SIM_IO, options);
Buf.writeUint32(options.command);
Buf.writeUint32(options.fileid);
Buf.writeString(options.path);
Buf.writeString(options.pathid);
Buf.writeUint32(options.p1);
Buf.writeUint32(options.p2);
Buf.writeUint32(options.p3);
@ -1244,16 +1244,6 @@ let RIL = {
* Process the MSISDN ICC I/O response.
*/
_processMSISDNResponse: function _processMSISDNResponse(options) {
let sw1 = Buf.readUint32();
let sw2 = Buf.readUint32();
// See GSM11.11 section 9.4 for sw1 and sw2
if (sw1 != STATUS_NORMAL_ENDING) {
// TODO: error
// Wait for fix for Bug 733990 to report error.
debug("Error in iccIO");
}
if (DEBUG) debug("ICC I/O (" + sw1 + "/" + sw2 + ")");
switch (options.command) {
case ICC_COMMAND_GET_RESPONSE:
let response = Buf.readString();
@ -1823,6 +1813,17 @@ RIL[REQUEST_SETUP_DATA_CALL] = function REQUEST_SETUP_DATA_CALL(length, options)
this[REQUEST_DATA_CALL_LIST](length, options);
};
RIL[REQUEST_SIM_IO] = function REQUEST_SIM_IO(length, options) {
let sw1 = Buf.readUint32();
let sw2 = Buf.readUint32();
if (sw1 != ICC_STATUS_NORMAL_ENDING) {
// See GSM11.11, TS 51.011 clause 9.4, and ISO 7816-4 for the error
// description.
debug("ICC I/O Error EF id = " + options.fileid.toString(16) +
" command = " + options.command.toString(16) +
"(" + sw1.toString(16) + "/" + sw2.toString(16) + ")");
return;
}
switch (options.fileid) {
case ICC_EF_MSISDN:
this._processMSISDNResponse(options);

View File

@ -57,6 +57,7 @@ DIRS += \
orientation \
sessionstorage \
storageevent \
browser-frame \
$(NULL)
#needs IPC support, also tests do not run successfully in Firefox for now

View File

@ -0,0 +1,60 @@
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is
# Mozilla Foundation.
# Portions created by the Initial Developer are Copyright (C) 2007
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#
# Alternatively, the contents of this file may be used under the terms of
# either of the GNU General Public License Version 2 or later (the "GPL"),
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = dom/tests/mochitest/browser-frame
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
_TEST_FILES = \
file_empty.html \
browserFrameHelpers.js \
test_browserFrame1.html \
test_browserFrame2.html \
test_browserFrame3.html \
test_browserFrame4.html \
test_browserFrame5.html \
test_browserFrame6.html \
test_browserFrame7.html \
$(NULL)
libs:: $(_TEST_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)

View File

@ -51,7 +51,15 @@ const browserFrameHelpers = {
},
'origEnabledPref': null,
'origWhitelistPref': null
'origWhitelistPref': null,
// Two basically-empty pages from two different domains you can load.
'emptyPage1': 'http://example.com' +
window.location.pathname.substring(0, window.location.pathname.lastIndexOf('/')) +
'/file_empty.html',
'emptyPage2': 'http://example.org' +
window.location.pathname.substring(0, window.location.pathname.lastIndexOf('/')) +
'/file_empty.html',
};
browserFrameHelpers.origEnabledPref = browserFrameHelpers.getEnabledPref();

View File

@ -0,0 +1,10 @@
<html>
<body>
Aloha! My URL is <span id='url'></span>.
<script>
document.getElementById('url').innerHTML = window.location;
</script>
</body>
</html>

View File

@ -6,6 +6,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=710231
<head>
<title>Test for Bug 710231</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="browserFrameHelpers.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
@ -32,7 +33,7 @@ function runTest() {
SimpleTest.finish();
});
iframe.src = 'http://example.com';
iframe.src = browserFrameHelpers.emptyPage1;
}
addEventListener('load', function() { SimpleTest.executeSoon(runTest); });

View File

@ -38,7 +38,7 @@ function runTest() {
SimpleTest.finish();
});
iframe.src = 'http://example.com';
iframe.src = browserFrameHelpers.emptyPage1;
}
addEventListener('load', function() { SimpleTest.executeSoon(runTest); });

View File

@ -39,7 +39,7 @@ function runTest() {
SimpleTest.finish();
});
iframe.src = 'http://example.com';
iframe.src = browserFrameHelpers.emptyPage1;
}
addEventListener('load', function() { SimpleTest.executeSoon(runTest); });

View File

@ -0,0 +1,156 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=710231
-->
<head>
<title>Test for Bug 710231</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="browserFrameHelpers.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=710231">Mozilla Bug 710231</a>
<!--
Test that an iframe with the |mozbrowser| attribute emits
mozbrowserX events when this page is in the whitelist.
-->
<script type="application/javascript;version=1.7">
SimpleTest.waitForExplicitFinish();
function runTest() {
browserFrameHelpers.setEnabledPref(true);
browserFrameHelpers.addToWhitelist();
// Load emptypage1 into the iframe, wait for that to finish loading, then
// call runTest2.
//
// This should trigger loadstart, load, and loadend events, but not a
// locationchange, because this is the initial load into the iframe.
var seenLoad = false;
var seenLoadEnd = false;
var seenLoadStart = false;
var iframe = document.createElement('iframe');
iframe.mozbrowser = true;
iframe.id = 'iframe';
iframe.src = browserFrameHelpers.emptyPage1;
function loadstart(e) {
ok(e.isTrusted, 'Event should be trusted.');
ok(!seenLoad, 'loadstart before load.');
ok(!seenLoadEnd, 'loadstart before loadend.');
ok(!seenLoadStart, 'Just one loadstart event.');
seenLoadStart = true;
}
function locationchange(e) {
ok(e.isTrusted, 'Event should be trusted.');
ok(false, 'Unexpected locationchange.');
}
function loadend(e) {
ok(e.isTrusted, 'Event should be trusted.');
ok(seenLoadStart, 'loadend after loadstart.');
ok(seenLoad, 'loadend after load.');
ok(!seenLoadEnd, 'Just one loadend event.');
seenLoadEnd = true;
}
function load(e) {
ok(e.isTrusted, 'Event should be trusted.');
ok(seenLoadStart, 'load after loadstart.');
ok(!seenLoad, 'Just one load event.');
ok(!seenLoadEnd, 'load before loadend.');
seenLoad = true;
}
iframe.addEventListener('mozbrowserloadstart', loadstart);
iframe.addEventListener('mozbrowserlocationchange', locationchange);
iframe.addEventListener('mozbrowserloadend', loadend);
iframe.addEventListener('load', load);
function waitForAllCallbacks() {
if (!seenLoadStart || !seenLoad || !seenLoadEnd) {
SimpleTest.executeSoon(waitForAllCallbacks);
return;
}
iframe.removeEventListener('mozbrowserloadstart', loadstart);
iframe.removeEventListener('mozbrowserlocationchange', locationchange);
iframe.removeEventListener('mozbrowserloadend', loadend);
iframe.removeEventListener('load', load);
runTest2();
}
document.body.appendChild(iframe);
waitForAllCallbacks();
}
function runTest2() {
var seenLoadStart = false;
var seenLoad = false;
var seenLoadEnd = false;
var seenLocationChange = false;
var iframe = document.getElementById('iframe');
iframe.addEventListener('mozbrowserloadstart', function(e) {
ok(e.isTrusted, 'Event should be trusted.');
ok(!seenLoadStart, 'Just one loadstart event.');
seenLoadStart = true;
ok(!seenLoad, 'Got mozbrowserloadstart event before load.');
ok(!seenLoadEnd, 'Got mozbrowserloadstart before loadend.');
ok(!seenLocationChange, 'Got mozbrowserloadstart before locationchange.');
});
iframe.addEventListener('mozbrowserlocationchange', function(e) {
ok(e.isTrusted, 'Event should be trusted.');
ok(!seenLocationChange, 'Just one locationchange event.');
seenLocationChange = true;
ok(seenLoadStart, 'Location change after load start.');
ok(!seenLoad, 'Location change before load.');
ok(!seenLoadEnd, 'Location change before load end.');
ok(e.detail, browserFrameHelpers.emptyPage2, "event's reported location");
});
iframe.addEventListener('load', function(e) {
ok(e.isTrusted, 'Event should be trusted.');
ok(!seenLoad, 'Just one load event.');
seenLoad = true;
ok(seenLoadStart, 'Load after loadstart.');
ok(seenLocationChange, 'Load after locationchange.');
ok(!seenLoadEnd, 'Load before loadend.');
});
iframe.addEventListener('mozbrowserloadend', function(e) {
ok(e.isTrusted, 'Event should be trusted.');
ok(!seenLoadEnd, 'Just one load end event.');
seenLoadEnd = true;
ok(seenLoadStart, 'Load end after load start.');
ok(seenLocationChange, 'Load end after location change.');
});
iframe.src = browserFrameHelpers.emptyPage2;
function waitForAllCallbacks() {
if (!seenLoadStart || !seenLoad || !seenLoadEnd || !seenLocationChange) {
SimpleTest.executeSoon(waitForAllCallbacks);
return;
}
SimpleTest.finish();
}
waitForAllCallbacks();
}
addEventListener('load', function() { SimpleTest.executeSoon(runTest); });
</script>
</body>
</html>

View File

@ -25,25 +25,25 @@ function runTest() {
browserFrameHelpers.addToWhitelist();
var iframe1 = document.createElement('iframe');
document.body.appendChild(iframe1);
iframe1.mozbrowser = true;
iframe1.id = 'iframe1';
iframe1.addEventListener('load', function() {
iframe1.removeEventListener('load', arguments.callee);
SimpleTest.executeSoon(runTest2);
});
iframe1.src = 'http://example.org';
iframe1.src = browserFrameHelpers.emptyPage1;
document.body.appendChild(iframe1);
}
function runTest2() {
var iframe1 = document.getElementById('iframe1');
iframe1.mozbrowser = true;
var iframe2 = document.getElementById('iframe2');
var sawLoad = false;
var sawLocationChange = false;
iframe1.addEventListener('mozbrowserlocationchange', function(e) {
ok(e.isTrusted, 'Event should be trusted.');
ok(!sawLocationChange, 'Just one locationchange event.');
ok(!sawLoad, 'locationchange before load.');
is(e.detail, 'data:text/html,1', "event's reported location");
@ -72,7 +72,7 @@ function runTest2() {
// Load something into iframe2 to check that it doesn't trigger a
// locationchange for our iframe1 listener.
iframe2.src = 'http://example.com';
iframe2.src = browserFrameHelpers.emptyPage2;
}
addEventListener('load', function() { SimpleTest.executeSoon(runTest); });

View File

@ -36,6 +36,11 @@ function runTest() {
iframe2.mozbrowser = true;
document.body.appendChild(iframe2);
// iframe3 is another red herring. It's not a mozbrowser, so we shouldn't
// get any titlechange events on it.
var iframe3 = document.createElement('iframe');
document.body.appendChild(iframe3);
var numTitleChanges = 0;
iframe1.addEventListener('mozbrowsertitlechange', function(e) {
@ -59,8 +64,13 @@ function runTest() {
}
});
iframe3.addEventListener('mozbrowsertitlechange', function(e) {
ok(false, 'Should not get a titlechange event for iframe3.');
});
iframe1.src = 'data:text/html,<html><head><title>Title</title></head><body></body></html>';
iframe2.src = 'data:text/html,<html><head><title>BAD TITLE</title></head><body></body></html>';
iframe3.src = 'data:text/html,<html><head><title>SHOULD NOT GET EVENT</title></head><body></body></html>';
}
addEventListener('load', function() { SimpleTest.executeSoon(runTest); });
@ -69,4 +79,3 @@ addEventListener('load', function() { SimpleTest.executeSoon(runTest); });
</body>
</html>

View File

@ -26,22 +26,31 @@ browserFrameHelpers.setEnabledPref(true);
browserFrameHelpers.addToWhitelist();
var iframe = document.createElement('iframe');
iframe.addEventListener('load', function() {
outerIframeLoaded();
});
iframe.mozbrowser = true;
iframe.src = 'data:text/html,Outer iframe';
document.body.appendChild(iframe);
var innerIframe = document.createElement('iframe');
iframe.contentDocument.body.appendChild(innerIframe);
SimpleTest.waitForExplicitFinish();
var iframeCw = iframe.contentWindow;
var innerCw = innerIframe.contentWindow;
function outerIframeLoaded() {
var innerIframe = iframe.contentDocument.createElement('iframe');
iframe.contentDocument.body.appendChild(innerIframe);
is(iframeCw.top, iframeCw, 'iframe top');
is(iframeCw.parent, iframeCw, 'iframe parent');
is(iframeCw.frameElement, null, 'iframe frameElement');
var iframeCw = iframe.contentWindow;
var innerCw = innerIframe.contentWindow;
is(innerCw.top, iframeCw, 'inner iframe top');
is(innerCw.parent, iframeCw, 'inner iframe parent');
is(innerCw.frameElement, innerIframe, 'inner iframe frameElement');
is(iframeCw.top, iframeCw, 'iframe top');
is(iframeCw.parent, iframeCw, 'iframe parent');
is(iframeCw.frameElement, null, 'iframe frameElement');
is(innerCw.top, iframeCw, 'inner iframe top');
is(innerCw.parent, iframeCw, 'inner iframe parent');
is(innerCw.frameElement, innerIframe, 'inner iframe frameElement');
SimpleTest.finish();
}
</script>
</body>

View File

@ -72,14 +72,6 @@ _TEST_FILES = \
test_focusrings.xul \
file_moving_xhr.html \
test_vibrator.html \
browserFrameHelpers.js \
test_browserFrame1.html \
test_browserFrame2.html \
test_browserFrame3.html \
test_browserFrame4.html \
test_browserFrame5.html \
test_browserFrame6.html \
test_browserFrame7.html \
test_for_of.html \
test_focus_legend_noparent.html \
file_clonewrapper.html \

View File

@ -1,101 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=710231
-->
<head>
<title>Test for Bug 710231</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="browserFrameHelpers.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=710231">Mozilla Bug 710231</a>
<!--
Test that an iframe with the |mozbrowser| attribute emits
mozbrowserX events when this page is in the whitelist.
-->
<script type="application/javascript;version=1.7">
SimpleTest.waitForExplicitFinish();
var seenLoadStart = false;
var seenLoad = false;
var seenLoadEnd = false;
var seenLocationChange = false;
function runTest() {
browserFrameHelpers.setEnabledPref(true);
browserFrameHelpers.addToWhitelist();
// Load example.org into the iframe, wait for that to load, then call
// runTest2. This would *almost* work if we just had a <iframe mozbrowser>
// in the HTML, except that we have to set the prefs before we create the
// iframe!
var iframe = document.createElement('iframe');
iframe.id = 'iframe';
document.body.appendChild(iframe);
iframe.src = 'data:text/html,1';
iframe.addEventListener('load', function() {
iframe.removeEventListener('load', arguments.callee);
SimpleTest.executeSoon(runTest2);
});
}
function runTest2() {
var iframe = document.getElementById('iframe');
iframe.mozbrowser = true;
iframe.addEventListener('mozbrowserloadstart', function() {
ok(!seenLoadStart, 'Just one loadstart event.');
seenLoadStart = true;
ok(!seenLoad, 'Got mozbrowserloadstart event before load.');
ok(!seenLoadEnd, 'Got mozbrowserloadstart before loadend.');
ok(!seenLocationChange, 'Got mozbrowserloadstart before locationchange.');
});
iframe.addEventListener('mozbrowserlocationchange', function(e) {
ok(!seenLocationChange, 'Just one locationchange event.');
seenLocationChange = true;
ok(seenLoadStart, 'Location change after load start.');
ok(!seenLoad, 'Location change before load.');
ok(!seenLoadEnd, 'Location change before load end.');
ok(e.detail, 'http://example.com', "event's reported location");
});
iframe.addEventListener('load', function() {
ok(!seenLoad, 'Just one load event.');
seenLoad = true;
ok(seenLoadStart, 'Load after loadstart.');
ok(seenLocationChange, 'Load after locationchange.');
ok(!seenLoadEnd, 'Load before loadend.');
});
iframe.addEventListener('mozbrowserloadend', function() {
ok(!seenLoadEnd, 'Just one load end event.');
seenLoadEnd = true;
ok(seenLoadStart, 'Load end after load start.');
ok(seenLocationChange, 'Load end after location change.');
});
iframe.src = 'http://example.com';
waitForAllCallbacks();
}
function waitForAllCallbacks() {
if (!seenLoadStart || !seenLoad || !seenLoadEnd || !seenLocationChange) {
SimpleTest.executeSoon(waitForAllCallbacks);
return;
}
SimpleTest.finish();
}
addEventListener('load', function() { SimpleTest.executeSoon(runTest); });
</script>
</body>
</html>

View File

@ -133,7 +133,7 @@ public:
bool mSeenUploadLoadStart;
// Only touched on the main thread.
nsCString mPreviousStatusText;
nsString mPreviousStatusText;
PRUint32 mSyncQueueKey;
PRUint32 mSyncEventResponseSyncQueueKey;
bool mUploadEventListenersAttached;
@ -543,7 +543,7 @@ class EventRunnable : public MainThreadProxyRunnable
JSAutoStructuredCloneBuffer mResponseBuffer;
nsTArray<nsCOMPtr<nsISupports> > mClonedObjects;
jsval mResponse;
nsCString mStatusText;
nsString mStatusText;
PRUint64 mLoaded;
PRUint64 mTotal;
PRUint32 mEventStreamId;
@ -554,7 +554,6 @@ class EventRunnable : public MainThreadProxyRunnable
bool mLengthComputable;
bool mResponseTextException;
bool mStatusException;
bool mStatusTextException;
bool mReadyStateException;
bool mResponseException;
@ -566,7 +565,7 @@ public:
mEventStreamId(aProxy->mInnerEventStreamId), mStatus(0), mReadyState(0),
mUploadEvent(aUploadEvent), mProgressEvent(true),
mLengthComputable(aLengthComputable), mResponseTextException(false),
mStatusException(false), mStatusTextException(false),
mStatusException(false),
mReadyStateException(false), mResponseException(false)
{ }
@ -576,7 +575,7 @@ public:
mEventStreamId(aProxy->mInnerEventStreamId), mStatus(0), mReadyState(0),
mUploadEvent(aUploadEvent), mProgressEvent(false), mLengthComputable(0),
mResponseTextException(false), mStatusException(false),
mStatusTextException(false), mReadyStateException(false),
mReadyStateException(false),
mResponseException(false)
{ }
@ -623,17 +622,11 @@ public:
mStatusException = NS_FAILED(xhr->GetStatus(&mStatus));
if (NS_SUCCEEDED(xhr->GetStatusText(mStatusText))) {
if (mStatusText == mProxy->mPreviousStatusText) {
mStatusText.SetIsVoid(true);
}
else {
mProxy->mPreviousStatusText = mStatusText;
}
mStatusTextException = false;
}
else {
mStatusTextException = true;
xhr->GetStatusText(mStatusText);
if (mStatusText == mProxy->mPreviousStatusText) {
mStatusText.SetIsVoid(true);
} else {
mProxy->mPreviousStatusText = mStatusText;
}
mReadyStateException = NS_FAILED(xhr->GetReadyState(&mReadyState));
@ -750,16 +743,16 @@ public:
state.mStatusException = mStatusException;
state.mStatus = mStatusException ? JSVAL_VOID : INT_TO_JSVAL(mStatus);
state.mStatusTextException = mStatusTextException;
if (mStatusTextException || mStatusText.IsVoid()) {
state.mStatusTextException = false;
if (mStatusText.IsVoid()) {
state.mStatusText = JSVAL_VOID;
}
else if (mStatusText.IsEmpty()) {
state.mStatusText = JS_GetEmptyStringValue(aCx);
}
else {
JSString* statusText = JS_NewStringCopyN(aCx, mStatusText.get(),
mStatusText.Length());
JSString* statusText = JS_NewUCStringCopyN(aCx, mStatusText.get(),
mStatusText.Length());
if (!statusText) {
return false;
}
@ -800,7 +793,7 @@ public:
if (StringBeginsWith(mResponseType, NS_LITERAL_STRING("moz-chunked-"))) {
xhr::StateData newState = {
JSVAL_NULL, JSVAL_VOID, JSVAL_VOID, JSVAL_VOID, JSVAL_NULL,
false, false, false, false, false
false, false, false, false
};
if (!xhr::UpdateXHRState(aCx, target, mUploadEvent, newState)) {
@ -1042,13 +1035,13 @@ public:
WorkerPrivate* oldWorker = mProxy->mWorkerPrivate;
mProxy->mWorkerPrivate = mWorkerPrivate;
nsresult rv = mProxy->mXHR->Abort();
mProxy->mXHR->Abort();
mProxy->mWorkerPrivate = oldWorker;
mProxy->Reset();
return GetDOMExceptionCodeFromResult(rv);
return 0;
}
};
@ -1066,9 +1059,8 @@ public:
int
MainThreadRun()
{
nsresult rv =
mProxy->mXHR->GetAllResponseHeaders(mResponseHeaders);
return GetDOMExceptionCodeFromResult(rv);
mProxy->mXHR->GetAllResponseHeaders(mResponseHeaders);
return 0;
}
};
@ -1327,19 +1319,19 @@ public:
class OverrideMimeTypeRunnable : public WorkerThreadProxySyncRunnable
{
nsCString mMimeType;
nsString mMimeType;
public:
OverrideMimeTypeRunnable(WorkerPrivate* aWorkerPrivate, Proxy* aProxy,
const nsCString& aMimeType)
const nsString& aMimeType)
: WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy), mMimeType(aMimeType)
{ }
int
MainThreadRun()
{
nsresult rv = mProxy->mXHR->OverrideMimeType(mMimeType);
return GetDOMExceptionCodeFromResult(rv);
mProxy->mXHR->OverrideMimeType(mMimeType);
return 0;
}
};
@ -2106,8 +2098,7 @@ XMLHttpRequestPrivate::OverrideMimeType(JSContext* aCx, JSString* aMimeType)
}
nsRefPtr<OverrideMimeTypeRunnable> runnable =
new OverrideMimeTypeRunnable(mWorkerPrivate, mProxy,
NS_ConvertUTF16toUTF8(mimeType));
new OverrideMimeTypeRunnable(mWorkerPrivate, mProxy, mimeType);
return runnable->Dispatch(aCx);
}
@ -2119,7 +2110,7 @@ XMLHttpRequestPrivate::MaybeDispatchPrematureAbortEvents(JSContext* aCx)
xhr::StateData state = {
JSVAL_VOID, JSVAL_VOID, JSVAL_VOID, INT_TO_JSVAL(4), JSVAL_VOID,
false, false, false, false, false
false, false, false, false
};
if (mProxy->mSeenUploadLoadStart) {

View File

@ -931,8 +931,9 @@ TiledTextureImage::DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion,
// Override a callback cancelling iteration if the texture wasn't valid.
// We need to force the update in that situation, or we may end up
// showing invalid/out-of-date texture data.
} while (NextTile() ||
(mTextureState != Valid && mCurrentImage < mImages.Length()));
if (mCurrentImage == mImages.Length() - 1)
break;
} while (NextTile() || (mTextureState != Valid));
mCurrentImage = oldCurrentImage;
mShaderType = mImages[0]->GetShaderProgramType();
@ -1091,8 +1092,11 @@ bool TiledTextureImage::NextTile()
continueIteration = mIterationCallback(this, mCurrentImage,
mIterationCallbackData);
mCurrentImage++;
return continueIteration && (mCurrentImage < mImages.Length());
if (mCurrentImage + 1 < mImages.Length()) {
mCurrentImage++;
return continueIteration;
}
return false;
}
void TiledTextureImage::SetIterationCallback(TileIterationCallback aCallback,
@ -1217,6 +1221,7 @@ void TiledTextureImage::Resize(const nsIntSize& aSize)
mColumns = columns;
mSize = aSize;
mTextureState = Allocated;
mCurrentImage = 0;
}
PRUint32 TiledTextureImage::GetTileCount()

View File

@ -434,7 +434,7 @@ public:
// but we will be able to do things like resource releases.
succeeded = sEGLLibrary.fMakeCurrent(EGL_DISPLAY(),
EGL_NO_SURFACE, EGL_NO_SURFACE,
mContext);
EGL_NO_CONTEXT);
if (!succeeded && sEGLLibrary.fGetError() == LOCAL_EGL_CONTEXT_LOST) {
mContextLost = true;
NS_WARNING("EGL context has been lost.");

View File

@ -572,9 +572,11 @@ void WriteSnapshotToDumpFile_internal(T* aObj, gfxASurface* aSurf)
nsCString string(aObj->Name());
string.Append("-");
string.AppendInt((PRUint64)aObj);
fprintf(gfxUtils::sDumpPaintFile, "array[\"%s\"]=\"", string.BeginReading());
if (gfxUtils::sDumpPaintFile)
fprintf(gfxUtils::sDumpPaintFile, "array[\"%s\"]=\"", string.BeginReading());
aSurf->DumpAsDataURL(gfxUtils::sDumpPaintFile);
fprintf(gfxUtils::sDumpPaintFile, "\";");
if (gfxUtils::sDumpPaintFile)
fprintf(gfxUtils::sDumpPaintFile, "\";");
}
void WriteSnapshotToDumpFile(Layer* aLayer, gfxASurface* aSurf)

View File

@ -90,6 +90,20 @@ CompositorParent::RecvStop()
return true;
}
bool
CompositorParent::RecvPause()
{
PauseComposition();
return true;
}
bool
CompositorParent::RecvResume()
{
ResumeComposition();
return true;
}
void
CompositorParent::ScheduleRenderOnCompositorThread()
{

View File

@ -94,6 +94,8 @@ public:
virtual ~CompositorParent();
virtual bool RecvStop() MOZ_OVERRIDE;
virtual bool RecvPause() MOZ_OVERRIDE;
virtual bool RecvResume() MOZ_OVERRIDE;
virtual void ShadowLayersUpdated(bool isFirstPaint) MOZ_OVERRIDE;
void Destroy();

View File

@ -64,6 +64,11 @@ parent:
// Clean up in preparation for destruction.
sync Stop();
// Pause/resume the compositor. These are intended to be used on mobile, when
// the compositor needs to pause/resume in lockstep with the application.
sync Pause();
sync Resume();
sync PLayers(LayersBackend backend);
};

View File

@ -69,8 +69,10 @@ const ots::LookupSubtableParser::TypeParser kGposTypeParsers[] = {
{GPOS_TYPE_EXTENSION_POSITIONING, ParseExtensionPositioning}
};
// TODO(bashi): Port Chromium's arraysize macro and use it instead of sizeof().
const ots::LookupSubtableParser kGposLookupSubtableParser = {
GPOS_TYPE_RESERVED, GPOS_TYPE_EXTENSION_POSITIONING, kGposTypeParsers
sizeof(kGposTypeParsers) / sizeof(kGposTypeParsers[0]),
GPOS_TYPE_EXTENSION_POSITIONING, kGposTypeParsers
};
// Shared Tables: ValueRecord, Anchor Table, and MarkArray

View File

@ -63,8 +63,10 @@ const ots::LookupSubtableParser::TypeParser kGsubTypeParsers[] = {
ParseReverseChainingContextSingleSubstitution}
};
// TODO(bashi): Port Chromium's arraysize macro and use it instead of sizeof().
const ots::LookupSubtableParser kGsubLookupSubtableParser = {
GSUB_TYPE_RESERVED, GSUB_TYPE_EXTENSION_SUBSTITUTION, kGsubTypeParsers
sizeof(kGsubTypeParsers) / sizeof(kGsubTypeParsers[0]),
GSUB_TYPE_EXTENSION_SUBSTITUTION, kGsubTypeParsers
};
// Lookup Type 1:

View File

@ -282,7 +282,6 @@ CPPSRCS = \
SkUtils.cpp \
SkWriter32.cpp \
SkXfermode.cpp \
SkDebug_stdio.cpp \
SkGlobals_global.cpp \
SkOSFile_stdio.cpp \
SkThread_none.cpp \
@ -309,6 +308,7 @@ endif
ifeq (android,$(MOZ_WIDGET_TOOLKIT))
CPPSRCS += \
SkDebug_android.cpp \
SkFontHost_FreeType.cpp \
SkFontHost_android.cpp \
SkFontHost_gamma.cpp \
@ -318,6 +318,10 @@ CPPSRCS += \
DEFINES += -DSK_BUILD_FOR_ANDROID_NDK
OS_CXXFLAGS += $(CAIRO_FT_CFLAGS)
else
CPPSRCS += \
SkDebug_stdio.cpp \
$(NULL)
endif
ifeq (gtk2,$(MOZ_WIDGET_TOOLKIT))

View File

@ -29,6 +29,9 @@ static void S32A_D565_Opaque_neon(uint16_t* SK_RESTRICT dst,
"vmov.u8 d31, #1<<7 \n\t"
"vld1.16 {q12}, [%[dst]] \n\t"
"vld4.8 {d0-d3}, [%[src]] \n\t"
// Thumb does not support the standard ARM conditional instructions but
// instead requires the 'it' instruction to signal conditional execution.
"it eq \n\t"
"moveq ip, #8 \n\t"
"mov %[keep_dst], %[dst] \n\t"

View File

@ -32,6 +32,14 @@ arm_memset16:
.fnstart
push {lr}
/* if count is equal to zero then abort */
teq r2, #0
beq .Lfinish
/* Multiply count by 2 - go from the number of 16-bit shorts
* to the number of bytes desired. */
mov r2, r2, lsl #1
/* expand the data to 32 bits */
orr r1, r1, lsl #16
@ -40,10 +48,6 @@ arm_memset16:
strneh r1, [r0], #2
subne r2, r2, #2
/* Multiply count by 2 - go from the number of 16-bit shorts
* to the number of bytes desired. */
mov r2, r2, lsl #1
/* Now jump into the main loop below. */
b .Lwork_32
.fnend
@ -52,6 +56,10 @@ arm_memset32:
.fnstart
push {lr}
/* if count is equal to zero then abort */
teq r2, #0
beq .Lfinish
/* Multiply count by 4 - go from the number of 32-bit words to
* the number of bytes desired. */
mov r2, r2, lsl #2
@ -97,5 +105,6 @@ arm_memset32:
strcs r1, [r0], #4
strmih lr, [r0], #2
.Lfinish:
pop {pc}
.fnend

View File

@ -2114,7 +2114,7 @@ gfxFont::GetShapedWord(gfxContext *aContext,
return nsnull;
}
bool ok = false;
DebugOnly<bool> ok = false;
if (sizeof(T) == sizeof(PRUnichar)) {
ok = ShapeWord(aContext, sw, (const PRUnichar*)aText);
} else {

View File

@ -1137,10 +1137,13 @@ gfxFontUtils::ValidateSFNTHeaders(const PRUint8 *aFontData,
}
// iterate through the table headers to find the head, name and OS/2 tables
bool foundHead = false, foundOS2 = false, foundName = false;
#ifdef XP_WIN
bool foundOS2 = false;
#endif
bool foundHead = false, foundName = false;
bool foundGlyphs = false, foundCFF = false, foundKern = false;
bool foundLoca = false, foundMaxp = false;
PRUint32 headOffset = 0, headLen, nameOffset = 0, nameLen, kernOffset = 0,
PRUint32 headOffset = 0, headLen, nameOffset = 0, kernOffset = 0,
kernLen = 0, glyfLen = 0, locaOffset = 0, locaLen = 0,
maxpOffset = 0, maxpLen;
PRUint32 i, numTables;
@ -1197,11 +1200,12 @@ gfxFontUtils::ValidateSFNTHeaders(const PRUint8 *aFontData,
case TRUETYPE_TAG('n','a','m','e'):
foundName = true;
nameOffset = dirEntry->offset;
nameLen = dirEntry->length;
break;
case TRUETYPE_TAG('O','S','/','2'):
#ifdef XP_WIN
foundOS2 = true;
#endif
break;
case TRUETYPE_TAG('g','l','y','f'): // TrueType-style quadratic glyph table
@ -1423,17 +1427,15 @@ gfxFontUtils::RenameFont(const nsAString& aName, const PRUint8 *aFontData,
reinterpret_cast<TableDirEntry*>(newFontData + sizeof(SFNTHeader));
PRUint32 numTables = sfntHeader->numTables;
bool foundName = false;
for (i = 0; i < numTables; i++, dirEntry++) {
if (dirEntry->tag == TRUETYPE_TAG('n','a','m','e')) {
foundName = true;
break;
}
}
// function only called if font validates, so this should always be true
NS_ASSERTION(foundName, "attempt to rename font with no name table");
NS_ASSERTION(i < numTables, "attempt to rename font with no name table");
// note: dirEntry now points to name record

View File

@ -738,7 +738,8 @@ gfxUtils::CopyAsDataURL(DrawTarget* aDT)
}
}
bool gfxUtils::sDumpPainting = getenv("MOZ_DUMP_PAINT_LIST") != 0;
bool gfxUtils::sDumpPaintList = getenv("MOZ_DUMP_PAINT_LIST") != 0;
bool gfxUtils::sDumpPainting = getenv("MOZ_DUMP_PAINT") != 0;
bool gfxUtils::sDumpPaintingToFile = getenv("MOZ_DUMP_PAINT_TO_FILE") != 0;
FILE *gfxUtils::sDumpPaintFile = NULL;
#endif

View File

@ -171,6 +171,7 @@ public:
*/
static void CopyAsDataURL(mozilla::gfx::DrawTarget* aDT);
static bool sDumpPaintList;
static bool sDumpPainting;
static bool sDumpPaintingToFile;
static FILE* sDumpPaintFile;

View File

@ -1315,10 +1315,6 @@ BindNameToSlot(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
* must be globals, so try to use GNAME ops.
*/
if (caller->isGlobalFrame() && TryConvertToGname(bce, pn, &op)) {
jsatomid _;
if (!bce->makeAtomIndex(atom, &_))
return JS_FALSE;
pn->setOp(op);
pn->pn_dflags |= PND_BOUND;
return JS_TRUE;
@ -1335,10 +1331,6 @@ BindNameToSlot(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
if (!TryConvertToGname(bce, pn, &op))
return JS_TRUE;
jsatomid _;
if (!bce->makeAtomIndex(atom, &_))
return JS_FALSE;
pn->setOp(op);
pn->pn_dflags |= PND_BOUND;
@ -2908,7 +2900,9 @@ EmitDestructuringLHS(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, VarEmit
case JSOP_SETLOCAL:
{
uint16_t slot = pn->pn_cookie.slot();
EMIT_UINT16_IMM_OP(JSOP_SETLOCALPOP, slot);
EMIT_UINT16_IMM_OP(JSOP_SETLOCAL, slot);
if (Emit1(cx, bce, JSOP_POP) < 0)
return JS_FALSE;
break;
}
@ -3942,7 +3936,9 @@ EmitCatch(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
case PNK_NAME:
/* Inline and specialize BindNameToSlot for pn2. */
JS_ASSERT(!pn2->pn_cookie.isFree());
EMIT_UINT16_IMM_OP(JSOP_SETLOCALPOP, pn2->pn_cookie.slot());
EMIT_UINT16_IMM_OP(JSOP_SETLOCAL, pn2->pn_cookie.slot());
if (Emit1(cx, bce, JSOP_POP) < 0)
return false;
break;
default:
@ -4893,7 +4889,7 @@ EmitFor(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
: EmitNormalFor(cx, bce, pn, top);
}
static bool
static JS_NEVER_INLINE bool
EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
{
#if JS_HAS_XML_SUPPORT
@ -4918,35 +4914,29 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
fun->kind() == JSFUN_INTERPRETED);
{
/*
* Generate code for the function's body. bce2 is not allocated on the
* stack because doing so significantly reduces the maximum depth of
* nested functions we can handle. See bug 696284.
*/
AutoPtr<BytecodeEmitter> bce2(cx);
bce2 = cx->new_<BytecodeEmitter>(bce->parser, pn->pn_pos.begin.lineno);
if (!bce2 || !bce2->init(cx))
BytecodeEmitter bce2(bce->parser, pn->pn_pos.begin.lineno);
if (!bce2.init(cx))
return false;
bce2->flags = pn->pn_funbox->tcflags | TCF_COMPILING | TCF_IN_FUNCTION |
bce2.flags = pn->pn_funbox->tcflags | TCF_COMPILING | TCF_IN_FUNCTION |
(bce->flags & TCF_FUN_MIGHT_ALIAS_LOCALS);
bce2->bindings.transfer(cx, &pn->pn_funbox->bindings);
bce2->setFunction(fun);
bce2->funbox = pn->pn_funbox;
bce2->parent = bce;
bce2->globalScope = bce->globalScope;
bce2.bindings.transfer(cx, &pn->pn_funbox->bindings);
bce2.setFunction(fun);
bce2.funbox = pn->pn_funbox;
bce2.parent = bce;
bce2.globalScope = bce->globalScope;
/*
* js::frontend::SetStaticLevel limited static nesting depth to fit in
* 16 bits and to reserve the all-ones value, thereby reserving the
* magic FREE_UPVAR_COOKIE value. Note the bce2->staticLevel assignment
* magic FREE_UPVAR_COOKIE value. Note the bce2.staticLevel assignment
* below.
*/
JS_ASSERT(bce->staticLevel < JS_BITMASK(16) - 1);
bce2->staticLevel = bce->staticLevel + 1;
bce2.staticLevel = bce->staticLevel + 1;
/* We measured the max scope depth when we parsed the function. */
if (!EmitFunctionScript(cx, bce2.get(), pn->pn_body))
if (!EmitFunctionScript(cx, &bce2, pn->pn_body))
return false;
}
@ -5807,7 +5797,6 @@ EmitObject(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
return false;
}
unsigned methodInits = 0, slowMethodInits = 0;
for (ParseNode *pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
/* Emit an index for t[2] for later consumption by JSOP_INITELEM. */
ParseNode *pn3 = pn2->pn_left;

View File

@ -51,6 +51,8 @@
#include "gc/Statistics.h"
#include "gc/Barrier-inl.h"
namespace js {
namespace gcstats {

View File

@ -73,6 +73,8 @@ test('return let (x = x + 1, [] = x, [[, , ]] = x, y = x) y;');
test('return let ([{a: x}] = x, [, {b: y}] = x) let (x = x + 1, y = y + 2) x + y;', [{a:"p"},{b:"p"}], "p1p2");
test('return let ([] = []) x;');
test('return let ([] = [x]) x;');
test('return let ([a] = (1, [x])) a;');
test('return let ([a] = (1, x, 1, x)) a;', ['ponies']);
test('return let ([x] = [x]) x;');
test('return let ([[a, [b, c]]] = [[x, []]]) a;');
test('return let ([x, y] = [x, x + 1]) x + y;', 1, 3);
@ -129,6 +131,8 @@ test('let (x = x + 1, [] = x, [[, , ]] = x, y = x) {return y;}');
test('let ([{a: x}] = x, [, {b: y}] = x) {let (x = x + 1, y = y + 2) {return x + y;}}', [{a:"p"},{b:"p"}], "p1p2");
test('let ([] = []) {return x;}');
test('let ([] = [x]) {return x;}');
test('let ([a] = (1, [x])) {return a;}');
test('let ([a] = (1, x, 1, x)) {return a;}', ['ponies']);
test('let ([x] = [x]) {return x;}');
test('let ([[a, [b, c]]] = [[x, []]]) {return a;}');
test('let ([x, y] = [x, x + 1]) {return x + y;}', 1, 3);
@ -174,6 +178,8 @@ test('var [{a: X}] = x, [, {b: y}] = x;var X = X + 1, y = y + 2;return X + y;',
test('var [x] = [x];return x;');
test('var [[a, [b, c]]] = [[x, []]];return a;');
test('var [y] = [x];return y;');
test('var [a] = (1, [x]);return a;');
test('var [a] = (1, x, 1, x);return a;', ['ponies']);
test('var [x, y] = [x, x + 1];return x + y;', 1, 3);
test('var [x, y, z] = [x, x + 1, x + 2];return x + y + z;', 1, 6);
test('var [[x]] = [[x]];return x;');
@ -213,6 +219,8 @@ test('if (x) {let [{a: X}] = x, [, {b: Y}] = x;var XX = X + 1, YY = Y + 2;return
test('if (x) {let [[a, [b, c]]] = [[x, []]];return a;}');
test('if (x) {let [X] = [x];return X;}');
test('if (x) {let [y] = [x];return y;}');
test('if (x) {let [a] = (1, [x]);return a;}');
test('if (x) {let [a] = (1, x, 1, x);return a;}', ['ponies']);
test('if (x) {let [X, y] = [x, x + 1];return X + y;}', 1, 3);
test('if (x) {let [X, y, z] = [x, x + 1, x + 2];return X + y + z;}', 1, 6);
test('if (x) {let [[X]] = [[x]];return X;}');
@ -279,6 +287,8 @@ test('for (let y;;) {let y;return x;}');
test('for (let a = x;;) {let c = x, d = x;return c;}');
test('for (let [a, b] = x;;) {let c = x, d = x;return c;}');
test('for (let [] = [[]] = {};;) {return x;}');
test('for (let [a] = (1, [x]);;) {return a;}');
test('for (let [a] = (1, x, 1, x);;) {return a;}', ['ponies']);
isError('for (let x = 1, x = 2;;) {}');
isError('for (let [x, y] = a, {a:x} = b;;) {}');
isError('for (let [x, y, x] = a;;) {}');

View File

@ -517,8 +517,7 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
case JSOP_DECLOCAL:
case JSOP_LOCALINC:
case JSOP_LOCALDEC:
case JSOP_SETLOCAL:
case JSOP_SETLOCALPOP: {
case JSOP_SETLOCAL: {
uint32_t local = GET_SLOTNO(pc);
if (local >= script->nfixed) {
localsAliasStack_ = true;
@ -825,8 +824,7 @@ ScriptAnalysis::analyzeLifetimes(JSContext *cx)
}
case JSOP_SETARG:
case JSOP_SETLOCAL:
case JSOP_SETLOCALPOP: {
case JSOP_SETLOCAL: {
uint32_t slot = GetBytecodeSlot(script, pc);
if (!slotEscapes(slot))
killVariable(cx, lifetimes[slot], offset, saved, savedCount);

View File

@ -257,7 +257,6 @@ ExtendedDef(jsbytecode *pc)
case JSOP_ARGINC:
case JSOP_ARGDEC:
case JSOP_SETLOCAL:
case JSOP_SETLOCALPOP:
case JSOP_INCLOCAL:
case JSOP_DECLOCAL:
case JSOP_LOCALINC:
@ -385,7 +384,6 @@ static inline uint32_t GetBytecodeSlot(JSScript *script, jsbytecode *pc)
case JSOP_GETLOCAL:
case JSOP_CALLLOCAL:
case JSOP_SETLOCAL:
case JSOP_SETLOCALPOP:
case JSOP_INCLOCAL:
case JSOP_DECLOCAL:
case JSOP_LOCALINC:
@ -408,7 +406,6 @@ BytecodeUpdatesSlot(JSOp op)
switch (op) {
case JSOP_SETARG:
case JSOP_SETLOCAL:
case JSOP_SETLOCALPOP:
case JSOP_INCARG:
case JSOP_DECARG:
case JSOP_ARGINC:

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