mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-15 22:44:13 +00:00
Merge last green PGO from inbound to central
This commit is contained in:
commit
e7e2c4f5be
@ -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.
|
||||
*/
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -309,12 +309,6 @@ nsApplicationAccessible::GetPlatformVersion(nsAString& aVersion)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsAccessNode public methods
|
||||
|
||||
bool
|
||||
nsApplicationAccessible::IsDefunct() const
|
||||
{
|
||||
return nsAccessibilityService::IsShutdown();
|
||||
}
|
||||
|
||||
bool
|
||||
nsApplicationAccessible::Init()
|
||||
{
|
||||
|
@ -98,7 +98,6 @@ public:
|
||||
NS_DECL_NSIACCESSIBLEAPPLICATION
|
||||
|
||||
// nsAccessNode
|
||||
virtual bool IsDefunct() const;
|
||||
virtual bool Init();
|
||||
virtual void Shutdown();
|
||||
virtual bool IsPrimaryForNode() const;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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; }
|
||||
|
||||
|
@ -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())) { }
|
||||
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
|
@ -161,7 +161,6 @@ public:
|
||||
NS_DECL_NSIACCESSIBLETABLECELL
|
||||
|
||||
// nsAccessNode
|
||||
virtual bool IsDefunct() const;
|
||||
virtual bool Init();
|
||||
virtual bool IsPrimaryForNode() const;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
@ -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
|
||||
|
@ -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_
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
342
content/media/FileBlockCache.cpp
Normal file
342
content/media/FileBlockCache.cpp
Normal 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.
|
202
content/media/FileBlockCache.h
Normal file
202
content/media/FileBlockCache.h
Normal 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_ */
|
@ -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 \
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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)",
|
||||
|
@ -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));
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
283
dom/base/BrowserElementAPI.js
Normal file
283
dom/base/BrowserElementAPI.js
Normal 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]);
|
3
dom/base/BrowserElementAPI.manifest
Normal file
3
dom/base/BrowserElementAPI.manifest
Normal 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
|
@ -54,6 +54,8 @@ DIRS = \
|
||||
EXTRA_PP_COMPONENTS = \
|
||||
ConsoleAPI.js \
|
||||
ConsoleAPI.manifest \
|
||||
BrowserElementAPI.js \
|
||||
BrowserElementAPI.manifest \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_JS_MODULES = ConsoleAPIStorage.jsm \
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -12,8 +12,8 @@
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
class BluetoothDevice : public nsIDOMBluetoothDevice
|
||||
, public nsDOMEventTargetHelper
|
||||
class BluetoothDevice : public nsDOMEventTargetHelper
|
||||
, public nsIDOMBluetoothDevice
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -57,6 +57,7 @@ DIRS += \
|
||||
orientation \
|
||||
sessionstorage \
|
||||
storageevent \
|
||||
browser-frame \
|
||||
$(NULL)
|
||||
|
||||
#needs IPC support, also tests do not run successfully in Firefox for now
|
||||
|
60
dom/tests/mochitest/browser-frame/Makefile.in
Normal file
60
dom/tests/mochitest/browser-frame/Makefile.in
Normal 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)
|
@ -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();
|
10
dom/tests/mochitest/browser-frame/file_empty.html
Normal file
10
dom/tests/mochitest/browser-frame/file_empty.html
Normal 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>
|
@ -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); });
|
@ -38,7 +38,7 @@ function runTest() {
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
iframe.src = 'http://example.com';
|
||||
iframe.src = browserFrameHelpers.emptyPage1;
|
||||
}
|
||||
|
||||
addEventListener('load', function() { SimpleTest.executeSoon(runTest); });
|
@ -39,7 +39,7 @@ function runTest() {
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
iframe.src = 'http://example.com';
|
||||
iframe.src = browserFrameHelpers.emptyPage1;
|
||||
}
|
||||
|
||||
addEventListener('load', function() { SimpleTest.executeSoon(runTest); });
|
156
dom/tests/mochitest/browser-frame/test_browserFrame4.html
Normal file
156
dom/tests/mochitest/browser-frame/test_browserFrame4.html
Normal 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>
|
@ -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); });
|
@ -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>
|
||||
|
@ -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>
|
@ -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 \
|
||||
|
@ -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>
|
@ -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) {
|
||||
|
@ -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()
|
||||
|
@ -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.");
|
||||
|
@ -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)
|
||||
|
@ -90,6 +90,20 @@ CompositorParent::RecvStop()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CompositorParent::RecvPause()
|
||||
{
|
||||
PauseComposition();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CompositorParent::RecvResume()
|
||||
{
|
||||
ResumeComposition();
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CompositorParent::ScheduleRenderOnCompositorThread()
|
||||
{
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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))
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -171,6 +171,7 @@ public:
|
||||
*/
|
||||
static void CopyAsDataURL(mozilla::gfx::DrawTarget* aDT);
|
||||
|
||||
static bool sDumpPaintList;
|
||||
static bool sDumpPainting;
|
||||
static bool sDumpPaintingToFile;
|
||||
static FILE* sDumpPaintFile;
|
||||
|
@ -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;
|
||||
|
@ -51,6 +51,8 @@
|
||||
|
||||
#include "gc/Statistics.h"
|
||||
|
||||
#include "gc/Barrier-inl.h"
|
||||
|
||||
namespace js {
|
||||
namespace gcstats {
|
||||
|
||||
|
@ -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;;) {}');
|
||||
|
@ -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);
|
||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user